Skip to main content Link Search Menu Expand Document (external link)

CrSql overview

CR-SQLite service for conflict-free replicated database operations.

This module provides a high-level Effect service interface for working with CR-SQLite (Conflict-free Replicated SQLite) databases. CR-SQLite enables multi-master replication with automatic conflict resolution, allowing seamless data synchronization across distributed systems without manual conflict handling.

Core Capabilities:

  • Site Management: Getting unique site identifiers and database versions
  • Change Synchronization: Pulling and applying change sets between replicas
  • Peer Tracking: Managing replication cursors for distributed peers
  • Schema Migration: Automated schema evolution with crsql_automigrate
  • Fractional Indexing: Ordered list support for collaborative editing

Multi-Master Replication: All operations support CR-SQLite’s CRDT (Conflict-free Replicated Data Type) semantics, enabling partition-tolerant systems where multiple replicas can accept writes independently and later converge to a consistent state.

All operations are Effect-based for composable error handling, dependency injection, and integration with the broader Effect ecosystem.

Security Note: This module uses Effect SQL’s tagged template literals, which automatically handle parameterization and SQL injection protection. The ${variable} syntax is safe - Effect SQL converts these to proper parameterized queries under the hood.

Added in v0.1.0


Table of contents


Construction

fromSqliteClient

Creates a CrSql service from an existing SqlClient setup.

Accepts optional parameters (each value or Effect) for providing the CR-SQLite extension path, precomputed extension metadata, or an alternative SqlClient. Missing dependencies are resolved from the ambient environment when available.

Signature

export declare const fromSqliteClient: _fromSqliteClient

Added in v0.1.0

Layer

layerFromSqliteClient

Builds a Layer that wires CR-SQLite services from an existing SqlClient.

The parameters can be provided eagerly or as Effects, allowing callers to defer expensive initialization until layer evaluation.

Signature

export declare const layerFromSqliteClient: <E = never, R = never>(
  _: MaybeEffect<FromSqliteClientParams<E, R>, E, R>
) => Layer.Layer<
  SqlClient.SqlClient | CrSql | CrSqliteExtension.ExtInfoLoaded,
  CrSqlErrors.CrSqliteExtensionMissing | E | CrSqlErrors.UnhexUnavailable,
  Scope | R
>

Added in v0.2.0

utils

CrSql (class)

CR-SQLite service accessor class for conflict-free replicated database operations.

This Effect service provides a complete interface for working with CR-SQLite (Conflict-free Replicated SQLite) databases. CR-SQLite enables multi-master replication with automatic conflict resolution using CRDT semantics.

Service Usage: Use CrSql.CrSql accessors in Effect programs to interact with CR-SQLite-backed databases. The service automatically handles extension loading, connection management, and resource cleanup.

Core Features:

  • Automatic setup: Extension loading and connection verification
  • Type safety: Full TypeScript integration with Effect schemas
  • Resource management: Automatic cleanup via Effect finalizers
  • Multi-replica sync: Built-in peer tracking and change synchronization
  • Schema evolution: Declarative migrations with automigrate
  • Collaborative editing: Fractional indexing for ordered data

Signature

export declare class CrSql

Example

Basic usage:
```typescript
import { CrSql } from "@effect-native/crsql"
import * as NodeSqlite from "@effect/sql-sqlite-node"
import { Effect, Layer } from "effect"

const program = Effect.gen(function* () {
  // Get site identifier
  const siteId = yield* CrSql.CrSql.getSiteIdHex

  // Set up a replicated table
  yield* CrSql.CrSql.automigrate`
    CREATE TABLE IF NOT EXISTS todos (
      id BLOB PRIMARY KEY,
      text TEXT NOT NULL DEFAULT '',
      completed INTEGER NOT NULL DEFAULT 0
    );
    SELECT crsql_as_crr('todos');
  `

  // Make changes that will be replicated
  const sql = yield* CrSql.CrSql.sql
  yield* sql`INSERT INTO todos VALUES (randomblob(16), 'Hello World', 0)`

  // Export changes for synchronization
  const changes = yield* CrSql.CrSql.pullChanges("0")
  console.log(`Generated ${changes.length} changes`)
})

// Run with SQLite layer
const layers = Layer.mergeAll(
  NodeSqlite.SqliteClient.layer({ filename: "app.db" }),
  CrSql.CrSql.Default
)

Effect.provide(program, layers)

Example

Service creation from existing client:
```typescript
import * as CrSql from "@effect-native/crsql/CrSql"
import * as NodeSqlite from "@effect/sql-sqlite-node"
import * as LibCrSql from "@effect-native/libcrsql/effect"
import { Effect } from "effect"

const program = Effect.gen(function* () {
  // Create CrSql service from existing client
  const crsql = yield* CrSql.fromSqliteClient({
    pathToCrSqliteExtension: yield* LibCrSql.getCrSqliteExtensionPath(),
    sql: yield* NodeSqlite.SqliteClient.make({ filename: ":memory:" }),
  })

  // Use the service
  const version = yield* crsql.getDbVersion
})

Added in v0.1.0