Sync / foldkit-durable
Install
pnpm add foldkit-durableeffect is a peer dependency, @effect/sql-sqlite-node comes with the
package, and Node 22 is required for node:sqlite.
In a browser, or any runtime without node:sqlite, import
foldkit-durable/core instead: the same journal, as a layer that needs the
SqlClient it runs over, with no file. @effect/sql-sqlite-wasm gives
SQLite compiled to WebAssembly:
import * as WasmClient from '@effect/sql-sqlite-wasm/SqliteClient'
import { Effect, Layer } from 'effect'
import { DocumentId, Journal } from 'foldkit-durable/core'
const Todos = Journal.define<Operation, Snapshot, Principal>('app/Todos')
// `options` as for `Journal.make`, without `file`.
const live = Todos.layer(options).pipe(Layer.provide(WasmClient.layerMemory({})))
const program = Effect.gen(function* () {
const journal = yield* Todos.tag
return yield* journal.cursor(DocumentId.make('todos'))
}).pipe(Effect.provide(live))The database is provided to the layer, so it opens and closes with the
journal: there is no moment the journal holds a closed connection. To share
one connection with the application's own tables, provide the driver once
to both (Layer.mergeAll(Todos.layer(options), Tables).pipe(Layer.provide(
driver))). Outside Effect, keep the layer in a ManagedRuntime that lives
as long as the code using it (runtime.runPromise(Effect.service(Todos.tag))).
core reaches neither Node's driver nor a node: module; payloads are hashed
in plain JavaScript, as node:crypto hashed them, so a database written
before still recognizes its retransmissions.
On Cloudflare D1, provide @effect/sql-d1's client and pass d1: true (see
On Cloudflare D1).