@sqlite-sync/core 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as kysely from 'kysely';
2
2
  import { Kysely, SchemaModule } from 'kysely';
3
3
  import { S as SQLiteDbWrapper, L as Logger, T as TypedEvent, I as InternalSQLiteWrapper, a as StoredValue, C as CrdtStorage, E as ExecuteParams, b as ExecuteResult, Q as QueryBuilderOutput, K as KyselyQueryFactory, c as SQLiteTransactionWrapper, W as WorkerState, D as DeSyncDetectedReason } from './crdt-sync-remote-source-CJrVzW-B.js';
4
4
  export { R as CRDT_EVENT_NO_OP_PAYLOAD, U as CrdtEventOrigin, V as CrdtEventStatus, X as CrdtEventType, F as CrdtSyncRemoteSource, Y as CrdtUpdateLogItem, Z as CrdtUpdateLogPayload, g as DatabaseIntrospection, a5 as DeferredPromise, a6 as DistributiveOmit, J as EventsPullRequest, N as EventsPushRequest, O as EventsPushResponse, H as HLC, f as HLCCounter, a1 as KyselyStatementFactory, j as LogLevel, M as MigratableEvent, n as Migrations, o as MigrationsDb, P as PendingCrdtEvent, $ as PersistedCrdtEvent, a2 as PreparedStatement, p as SyncDbMigrator, w as SystemDbConfig, x as SystemMigration, y as SystemMigrationContext, h as TableMetadata, aa as TypedBroadcastChannel, ab as TypedEventTarget, ae as WorkerConfig, af as WorkerNotificationMessage, q as applyMemoryDbSchema, r as applyWorkerDbSchema, t as baseSystemMigrations, d as compareHLC, z as createCrdtApplyFunction, B as createCrdtStorage, G as createCrdtSyncRemoteSource, a3 as createDeferredPromise, l as createMigrations, m as createMigrator, A as createSQLiteCrdtApplyFunction, a0 as createStoredValue, u as createSystemDbConfig, a4 as createTypedEventTarget, e as deserializeHLC, a7 as generateId, i as introspectDb, _ as isNoOpCrdtEventPayload, a8 as jsonSafeParse, a9 as quoteId, v as runSystemMigrations, s as serializeHLC, k as startPerformanceLogger, ac as tryCatch, ad as tryCatchAsync } from './crdt-sync-remote-source-CJrVzW-B.js';
5
- import { S as SyncDbSchema, C as CrdtTableConfig } from './reset-state-C_plkZGK.js';
6
- export { a as CreateCrdtSchemaOptions, R as RESET_REQUEST_TTL_MS, b as ResetRequest, d as ResetStore, c as createSyncDbSchema } from './reset-state-C_plkZGK.js';
5
+ import { S as SyncDbSchema, C as CrdtTableConfig } from './reset-state-Comk7IC0.js';
6
+ export { a as CreateCrdtSchemaOptions, R as RESET_REQUEST_TTL_MS, b as ResetRequest, d as ResetStore, c as createSyncDbSchema } from './reset-state-Comk7IC0.js';
7
7
  import '@sqlite.org/sqlite-wasm';
8
8
 
9
9
  declare const dummyKysely: Kysely<any>;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/memory-db/sqlite-reactive-db.ts","../src/bound-map.ts","../src/sqlite-crdt/crdt-schema.ts","../src/sqlite-crdt/crdt-storage-mutator.ts","../src/sqlite-crdt/make-crdt-table.ts","../src/db-id.ts","../src/devtools-registry.ts","../src/memory-db/memory-db.ts","../src/worker-db/db-worker-client.ts","../src/sync-db.ts"],"sourcesContent":["import sqlite3InitModule, { type Sqlite3Static } from \"@sqlite.org/sqlite-wasm\";\nimport { BoundMap } from \"../bound-map\";\nimport { type Logger, startPerformanceLogger } from \"../logger\";\nimport { type PreparedStatement, SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createTypedEventTarget, type TypedEvent } from \"../utils\";\n\nlet sqliteModule: Sqlite3Static | null = null;\n\ntype TableName<Database> = keyof Database extends string ? keyof Database : never;\n\ntype SQLiteReactiveDbOptions = {\n snapshot: Uint8Array<ArrayBufferLike>;\n logger: Logger;\n};\n\ntype EventsMap = {\n \"transaction-committed\": undefined;\n \"transaction-rolled-back\": undefined;\n \"any-table-changed\": undefined;\n} & Record<`table:${string}`, void>;\n\ntype LiveQuery<TResult> = {\n getRows: () => TResult[];\n refresh: () => void;\n subscribe: (onchange: () => void) => () => void;\n};\n\nexport type SharedLiveQuery<TResult> = LiveQuery<TResult> & {\n readonly sql: string;\n readonly parameters: readonly unknown[];\n getSubscriberCount: () => number;\n};\n\ntype SharedLiveQueryEntry<TResult> = SharedLiveQuery<TResult> & {\n listeners: Set<() => void>;\n unsubscribeFromLiveQuery: (() => void) | null;\n cleanupTimeout: ReturnType<typeof setTimeout> | null;\n};\n\nexport type SharedLiveQuerySnapshot = {\n sql: string;\n parameters: readonly unknown[];\n subscriberCount: number;\n};\n\nexport function createSQLiteReactiveDb<Database>(opts: SQLiteReactiveDbOptions) {\n return SQLiteReactiveDb.create<Database>(opts);\n}\n\nexport class SQLiteReactiveDb<Database> {\n readonly db: SQLiteDbWrapper<Database>;\n private sqlite3: Sqlite3Static;\n\n private readonly logger: Logger;\n\n private tablesUsedStatement: PreparedStatement<[string], { name: string; isWrite: boolean }> | null = null;\n\n private eventTarget = createTypedEventTarget<EventsMap>();\n\n private constructor(sqlite3: Sqlite3Static, logger: Logger) {\n this.sqlite3 = sqlite3;\n this.logger = logger;\n\n this.db = new SQLiteDbWrapper({\n db: () => new sqlite3.oo1.DB({ filename: \":memory:\" }),\n logger: this.logger,\n loggerPrefix: \"memory\",\n sqlite3,\n });\n }\n\n static async create<Database>(opts: SQLiteReactiveDbOptions) {\n const logger = opts.logger;\n const perf = startPerformanceLogger(logger);\n if (!sqliteModule) {\n sqliteModule = await sqlite3InitModule();\n }\n\n const db = new SQLiteReactiveDb<Database>(sqliteModule, logger);\n\n if (opts.snapshot) {\n db.useSnapshot(opts.snapshot);\n }\n db.registerDbHooks();\n\n perf.logEnd(\"createSQLiteMemoryDb\", \"success\", \"system\");\n\n return db;\n }\n\n private liveQueryStatements = new BoundMap<string, PreparedStatement<any[], unknown>>({\n maxSize: 100,\n onRemove(_, value) {\n value.finalize();\n },\n });\n\n private sharedLiveQueries = new Map<string, SharedLiveQueryEntry<unknown>[]>();\n\n createLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const fetchRows = (parameters: readonly unknown[]) => {\n let statement = this.liveQueryStatements.get(query.sql);\n if (!statement) {\n statement = this.db.prepare<any[], any>(query.sql);\n this.liveQueryStatements.set(query.sql, statement);\n }\n return statement.execute(parameters as any) as TResult[];\n };\n\n let rows: TResult[] | null = null;\n\n const getRows = () => {\n if (!rows) {\n rows = fetchRows(query.parameters);\n }\n return rows;\n };\n\n let subscriber: (() => void) | null = null;\n\n let lastParameters: readonly unknown[] = query.parameters;\n const refresh = (parameters?: readonly unknown[]) => {\n if (parameters) {\n lastParameters = parameters;\n }\n rows = fetchRows(lastParameters);\n subscriber?.();\n };\n\n const subscribe = (onchange: () => void) => {\n if (subscriber) {\n throw new Error(\"Subscriber already exists\");\n }\n\n subscriber = onchange;\n const subscription = this.subscribeToQueryChanges({\n sql: query.sql,\n onDataChange: refresh,\n });\n\n return () => {\n subscription.unsubscribe();\n subscriber = null;\n };\n };\n\n return { getRows, refresh, subscribe };\n }\n\n getSharedLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const existingEntry = this.sharedLiveQueries\n .get(query.sql)\n ?.find((entry) => parametersAreEqual(entry.parameters, query.parameters));\n if (existingEntry) {\n if (existingEntry.listeners.size === 0) {\n this.scheduleSharedLiveQueryCleanup(existingEntry);\n }\n return existingEntry as SharedLiveQuery<TResult>;\n }\n\n const liveQuery = this.createLiveQuery<TResult>(query);\n let hasDetachedFromLiveQuery = false;\n const entry: SharedLiveQueryEntry<TResult> = {\n sql: query.sql,\n parameters: query.parameters,\n listeners: new Set(),\n unsubscribeFromLiveQuery: null,\n cleanupTimeout: null,\n getRows: () => liveQuery.getRows(),\n refresh: () => {\n liveQuery.refresh();\n },\n getSubscriberCount: () => entry.listeners.size,\n subscribe: (onchange) => {\n this.cancelSharedLiveQueryCleanup(entry);\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n entry.listeners.add(onchange);\n\n if (!entry.unsubscribeFromLiveQuery) {\n entry.unsubscribeFromLiveQuery = liveQuery.subscribe(() => {\n for (const listener of entry.listeners) {\n listener();\n }\n });\n\n // Rows may have gone stale while no subscriber was listening\n // for table changes.\n if (hasDetachedFromLiveQuery) {\n hasDetachedFromLiveQuery = false;\n liveQuery.refresh();\n }\n }\n\n return () => {\n entry.listeners.delete(onchange);\n\n if (entry.listeners.size === 0) {\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n hasDetachedFromLiveQuery = true;\n this.scheduleSharedLiveQueryCleanup(entry);\n }\n };\n },\n };\n\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n\n // Evict the entry if no subscriber attaches by the next tick.\n this.scheduleSharedLiveQueryCleanup(entry as SharedLiveQueryEntry<unknown>);\n\n return entry;\n }\n\n private registerSharedLiveQueryEntry(entry: SharedLiveQueryEntry<unknown>) {\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql) ?? [];\n if (!matchingSqlEntries.includes(entry)) {\n matchingSqlEntries.push(entry);\n this.sharedLiveQueries.set(entry.sql, matchingSqlEntries);\n }\n }\n\n getSharedLiveQueriesSnapshot(): SharedLiveQuerySnapshot[] {\n const snapshot: SharedLiveQuerySnapshot[] = [];\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n snapshot.push({\n sql: entry.sql,\n parameters: entry.parameters,\n subscriberCount: entry.listeners.size,\n });\n }\n }\n return snapshot;\n }\n\n private scheduleSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.cleanupTimeout = setTimeout(() => {\n entry.cleanupTimeout = null;\n this.releaseSharedLiveQuery(entry);\n }, 0);\n }\n\n private cancelSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.cleanupTimeout) {\n clearTimeout(entry.cleanupTimeout);\n entry.cleanupTimeout = null;\n }\n }\n\n private releaseSharedLiveQuery(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.listeners.size > 0 || entry.unsubscribeFromLiveQuery) {\n return;\n }\n\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql);\n if (!matchingSqlEntries) {\n return;\n }\n\n const nextEntries = matchingSqlEntries.filter((candidate) => candidate !== entry);\n if (nextEntries.length > 0) {\n this.sharedLiveQueries.set(entry.sql, nextEntries);\n } else {\n this.sharedLiveQueries.delete(entry.sql);\n }\n }\n\n subscribeToQueryChanges(params: { sql: string; onDataChange: () => void }) {\n const { sql, onDataChange } = params;\n\n const tables = this.getTablesUsed(sql);\n const readTables = new Set<string>();\n for (const table of tables) {\n if (!readTables.has(table.name)) {\n readTables.add(table.name);\n } else if (table.isWrite) {\n throw new Error(\"This query writes and reads from the same table. This may cause infinite loops.\");\n }\n }\n\n const notifyDataChange = createDebouncedCallback(() => {\n onDataChange();\n }, 30);\n\n for (const table of readTables) {\n this.eventTarget.addEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.addEventListener(\"any-table-changed\", notifyDataChange);\n\n return {\n unsubscribe: () => {\n for (const table of readTables) {\n this.eventTarget.removeEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.removeEventListener(\"any-table-changed\", notifyDataChange);\n },\n };\n }\n\n subscribeToTableChanges(table: string, onChanges: () => void) {\n this.eventTarget.addEventListener(`table:${table}`, onChanges);\n this.eventTarget.addEventListener(\"any-table-changed\", onChanges);\n return {\n unsubscribe: () => {\n this.eventTarget.removeEventListener(`table:${table}`, onChanges);\n this.eventTarget.removeEventListener(\"any-table-changed\", onChanges);\n },\n };\n }\n\n getTablesUsed(query: string) {\n if (!this.tablesUsedStatement) {\n this.tablesUsedStatement = this.db.prepare<[string], { name: string; isWrite: boolean }>(\n \"select t.tbl_name as name, u.wr as isWrite from tables_used(?) as u inner join sqlite_master as t on t.name = u.name where u.schema = 'main'\",\n { loggerLevel: \"system\" },\n );\n }\n\n const tables = this.tablesUsedStatement.execute([query]);\n\n if (tables.length === 0 && query.toLowerCase().includes(\"delete\")) {\n // tables_used function does not work with delete queries that clear entire tables\n tables.push(...this.getClearedTables(query));\n }\n\n return tables;\n }\n\n private getClearedTables(query: string) {\n const operations = this.db.execute<{\n opcode: string;\n p1: number;\n p2: number;\n }>(`EXPLAIN ${query.split(\";\")[0]}`, { loggerLevel: \"system\" }).rows;\n\n const clearedTablesRootPages = new Set<number>();\n for (const operation of operations) {\n if (operation.opcode === \"Clear\" && operation.p2 === 0) {\n clearedTablesRootPages.add(operation.p1);\n }\n }\n\n if (clearedTablesRootPages.size === 0) {\n return [];\n }\n\n const tableNames = this.db.execute<{ name: string; isWrite: boolean }>(\n `select t.tbl_name as name, true as isWrite from sqlite_master as t where t.rootpage in (${Array.from(\n clearedTablesRootPages,\n ).join(\",\")})`,\n { loggerLevel: \"system\" },\n ).rows;\n\n return tableNames;\n }\n\n addEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.addEventListener(type, listener);\n }\n\n removeEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.removeEventListener(type, listener);\n }\n\n private notifyTableSubscribers(tables: (TableName<Database> | (string & {}))[] | Set<string> | null = null) {\n if (!tables) {\n this.eventTarget.dispatchEvent(\"any-table-changed\", undefined);\n return;\n }\n\n for (const table of tables) {\n this.eventTarget.dispatchEvent(`table:${table}`, undefined);\n }\n }\n\n private registerDbHooks() {\n let updateQueue = new Set<string>();\n\n this.sqlite3.capi.sqlite3_update_hook(\n this.db.ensureDb,\n (_ctx, _opId, _db, table) => {\n updateQueue.add(table);\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_rollback_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n updateQueue.clear();\n this.eventTarget.dispatchEvent(\"transaction-rolled-back\", undefined);\n\n return 0;\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_commit_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n const tables = updateQueue;\n updateQueue = new Set<string>();\n this.eventTarget.dispatchEvent(\"transaction-committed\", undefined);\n\n queueMicrotask(() => {\n this.notifyTableSubscribers(tables);\n });\n return 0;\n },\n 0,\n );\n }\n\n createSnapshot() {\n const perf = startPerformanceLogger(this.logger);\n const snapshot = this.sqlite3.capi.sqlite3_js_db_export(this.db.ensureDb);\n perf.logEnd(\"createSnapshot\", `snapshot size: ${snapshot.byteLength}`, \"info\");\n\n return snapshot;\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n this.db.useSnapshot(snapshot);\n this.notifyTableSubscribers();\n }\n\n dispose() {\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n entry.listeners.clear();\n }\n }\n this.sharedLiveQueries.clear();\n this.liveQueryStatements.clear();\n if (this.tablesUsedStatement) {\n this.tablesUsedStatement.finalize();\n this.tablesUsedStatement = null;\n }\n this.db.close();\n }\n}\n\nfunction createDebouncedCallback<TArgs extends unknown[]>(callback: (...args: TArgs) => void, delay: number) {\n let timeout: unknown | null = null;\n let shouldCallWithoutDelay = true;\n\n return (...args: TArgs) => {\n if (shouldCallWithoutDelay) {\n callback(...args);\n shouldCallWithoutDelay = false;\n return;\n }\n\n const effect = () => {\n timeout = null;\n shouldCallWithoutDelay = true;\n return callback(...args);\n };\n\n if (timeout) {\n clearTimeout(timeout as any);\n }\n\n timeout = setTimeout(effect, delay);\n };\n}\n\nexport function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) {\n return false;\n }\n }\n return true;\n}\n","interface BoundMapOptions<K, V> {\n maxSize: number;\n onRemove: ((key: K, value: V) => void) | undefined;\n}\n\nexport class BoundMap<K, V> {\n private map = new Map<K, V>();\n private maxSize: number;\n private onRemove: ((key: K, value: V) => void) | undefined;\n\n constructor(opts: BoundMapOptions<K, V>) {\n this.maxSize = opts.maxSize;\n this.onRemove = opts.onRemove;\n }\n\n set = (key: K, value: V) => {\n if (this.onRemove && this.map.has(key)) {\n const old = this.map.get(key) as V;\n this.map.set(key, value);\n this.onRemove(key, old);\n } else {\n this.map.set(key, value);\n }\n if (this.map.size > this.maxSize) {\n const firstKey = this.map.keys().next().value as K;\n this.delete(firstKey);\n }\n };\n\n get = (key: K): V | undefined => {\n return this.map.get(key);\n };\n\n delete = (key: K) => {\n if (this.onRemove && this.map.has(key)) {\n const value = this.map.get(key) as V;\n this.map.delete(key);\n this.onRemove(key, value);\n } else {\n this.map.delete(key);\n }\n };\n\n clear = () => {\n const onRemove = this.onRemove;\n if (onRemove) {\n this.map.forEach((value, key) => {\n onRemove(key, value);\n });\n }\n this.map.clear();\n };\n}\n","import type { ColumnType } from \"kysely\";\nimport type { Migrations } from \"../migrations/migrator\";\n\nexport type CrdtTableConfig = {\n baseTableName: string;\n crdtTableName: string;\n};\n\nexport function createSyncDbSchema({ migrations }: { migrations: Migrations }) {\n return new CrdtSchemaBuilder({ tables: [], migrations });\n}\n\nexport interface CreateCrdtSchemaOptions {\n tables: CrdtTableConfig[];\n migrations: Migrations;\n}\n\n// biome-ignore lint/complexity/noBannedTypes: required generic\nclass CrdtSchemaBuilder<ClientDB = {}, ServerDB = {}, MutationsDB = {}>\n implements SyncDbSchema<ClientDB, ServerDB, MutationsDB>\n{\n constructor(private config: CreateCrdtSchemaOptions) {}\n\n get tablesConfig() {\n return this.config.tables;\n }\n\n get migrations() {\n return this.config.migrations;\n }\n\n get \"~clientSchema\"() {\n console.warn(\"~clientSchema should not be accessed on the client\");\n return null as any;\n }\n\n get \"~serverSchema\"() {\n console.warn(\"~serverSchema should not be accessed on the server\");\n return null as any;\n }\n\n get \"~mutationsSchema\"() {\n console.warn(\"~mutationsSchema should not be accessed on the client\");\n return null as any;\n }\n\n addTable<Table extends Record<string, unknown>>() {\n const withConfig = <const CrdtTable extends string, const BaseTable extends string>({\n baseTableName,\n crdtTableName,\n }: {\n baseTableName: BaseTable;\n crdtTableName: CrdtTable;\n }) => {\n this.config.tables.push({ baseTableName, crdtTableName });\n return new CrdtSchemaBuilder<\n ClientDB & { [K in CrdtTable]: Table } & { [K in BaseTable]: ReadonlyTable<Table> },\n ServerDB & { [K in BaseTable]: ReadonlyTable<Table> },\n MutationsDB & { [K in BaseTable]: Table }\n >(this.config);\n };\n\n return { withConfig };\n }\n\n build() {\n return this as SyncDbSchema<ClientDB, ServerDB, MutationsDB>;\n }\n}\n\n// biome-ignore lint/complexity/noBannedTypes: required generic\nexport interface SyncDbSchema<ClientDB = {}, ServerDB = {}, MutationsDB = {}> {\n get tablesConfig(): CrdtTableConfig[];\n get migrations(): Migrations;\n \"~clientSchema\": ClientDB;\n \"~serverSchema\": ServerDB;\n \"~mutationsSchema\": MutationsDB;\n}\n\ntype ReadonlyTable<Table extends Record<string, unknown>> = {\n [K in keyof Table]: ColumnType<Table[K], never, never>;\n};\n","import type { CrdtStorage, OwnCrdtEvent } from \"./crdt-storage\";\n\nexport type CrdtStorageMutator<Database> = ReturnType<typeof createCrdtStorageMutator<Database>>;\n\ntype CommitEventOptions<Database, Table extends keyof Database & string> =\n | {\n type: \"item-created\";\n dataset: Table;\n item_id: string;\n payload: CreateEventPayload<Database, Table>;\n }\n | {\n type: \"item-updated\";\n dataset: Table;\n item_id: string;\n payload: UpdateEventPayload<Database, Table>;\n }\n | {\n type: \"item-deleted\";\n dataset: Table;\n item_id: string;\n };\n\ntype CreateEventPayload<Database, Table extends keyof Database> = Omit<Database[Table], \"tombstone\">;\ntype UpdateEventPayload<Database, Table extends keyof Database> = Omit<Partial<Database[Table]>, \"id\" | \"tombstone\">;\n\nexport function createCrdtStorageMutator<Database>({ storage }: { storage: CrdtStorage }) {\n const mapToStorageEvent = (event: CommitEventOptions<Database, keyof Database & string>): OwnCrdtEvent => {\n switch (event.type) {\n case \"item-created\":\n return {\n type: \"item-created\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-updated\":\n return {\n type: \"item-updated\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-deleted\":\n return {\n type: \"item-deleted\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: \"{}\",\n };\n }\n };\n\n const enqueueEvents = (events: CommitEventOptions<Database, keyof Database & string>[]) => {\n storage.enqueueOwnEvents(events.map(mapToStorageEvent));\n };\n\n const createEvent = <Table extends keyof Database & string>(event: CommitEventOptions<Database, Table>) => {\n return event;\n };\n\n const enqueueEvent = (event: CommitEventOptions<Database, keyof Database & string>) => {\n storage.enqueueOwnEvents([mapToStorageEvent(event)]);\n };\n\n return {\n enqueueEvents,\n createEvent,\n enqueueEvent,\n };\n}\n","import type { SQLiteReactiveDb } from \"../memory-db/sqlite-reactive-db\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { quoteId } from \"../utils\";\nimport type { CrdtStorage } from \"./crdt-storage\";\n\nexport function makeCrdtTable({\n db,\n baseTableName,\n crdtTableName,\n}: {\n db: SQLiteDbWrapper<any>;\n baseTableName: string;\n crdtTableName: string;\n}) {\n const tableSchema = db.dbSchema[baseTableName];\n\n if (!tableSchema) {\n throw new Error(`Table ${baseTableName} not found`);\n }\n\n const columns = new Map(tableSchema.columns.map((c) => [c.name, c]));\n\n const idColumn = columns.get(\"id\");\n if (!idColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"id\" column. CRDT tables must have an \"id\" column to identify items.`,\n );\n }\n if (idColumn.dataType.toUpperCase() !== \"TEXT\") {\n throw new Error(\n `Table \"${baseTableName}\": \"id\" column must be of type TEXT, got \"${idColumn.dataType}\". CRDT item IDs are stored as strings.`,\n );\n }\n\n const tombstoneColumn = columns.get(\"tombstone\");\n if (!tombstoneColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"tombstone\" column. CRDT tables must have a \"tombstone\" INTEGER column for soft deletes.`,\n );\n }\n const tombstoneType = tombstoneColumn.dataType.toUpperCase();\n if (tombstoneType !== \"INTEGER\" && tombstoneType !== \"BOOLEAN\") {\n throw new Error(\n `Table \"${baseTableName}\": \"tombstone\" column must be of type INTEGER or BOOLEAN, got \"${tombstoneColumn.dataType}\". It is compared as 0/1 for soft deletes.`,\n );\n }\n\n db.execute(\n `\ncreate view ${quoteId(crdtTableName)} as\nselect * from ${quoteId(baseTableName)}\nwhere tombstone = 0;`,\n { loggerLevel: \"system\" },\n );\n\n const allColumnNames = tableSchema.columns.map((column) => column.name);\n\n const jsonPayload = (from: \"new\" | \"old\") =>\n `'{'||${allColumnNames.map((col) => `'\"${col}\":'||json_quote(${from}.${quoteId(col)})`).join(\"||','||\")}||'}'`;\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_created`)}\ninstead of insert on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_created('${baseTableName}', ${jsonPayload(\"new\")});\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_updated`)}\ninstead of update on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_updated(\n '${baseTableName}',\n ${jsonPayload(\"old\")},\n ${jsonPayload(\"new\")}\n);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_deleted`)}\ninstead of delete on ${quoteId(crdtTableName)}\nfor each row\nwhen old.tombstone = 0\nbegin\nselect handle_item_deleted('${baseTableName}', old.id);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n}\n\nexport function registerCrdtFunctions({\n reactiveDb,\n storage,\n}: {\n reactiveDb: SQLiteReactiveDb<any>;\n storage: CrdtStorage;\n}) {\n let eventApplied = false;\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_created\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, payloadRaw: string) => {\n const payload = JSON.parse(payloadRaw) as { id: string };\n\n storage.applyOwnEvent(\n {\n type: \"item-created\",\n dataset,\n item_id: payload.id,\n payload: payloadRaw,\n },\n {\n wrapInTransaction: false,\n },\n );\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_updated\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, oldPayloadRaw: string, newPayloadRaw: string) => {\n if (oldPayloadRaw === newPayloadRaw) {\n return undefined;\n }\n\n const tableSchema = reactiveDb.db.dbSchema[dataset];\n\n if (!tableSchema?.columns) {\n throw new Error(`Schema not found for dataset: ${dataset}`);\n }\n\n const oldPayload = JSON.parse(oldPayloadRaw);\n const newPayload = JSON.parse(newPayloadRaw);\n\n let hasDiff = false;\n const updatePayload = {} as Record<string, unknown>;\n\n for (const column of tableSchema.columns) {\n const oldValue = oldPayload[column.name];\n const newValue = newPayload[column.name];\n if (oldValue === newValue) {\n continue;\n }\n\n if (column.name === \"id\") {\n throw new Error(\n `Cannot update the \"id\" column of an item. It is used to identify the item and must be immutable.`,\n );\n }\n\n hasDiff = true;\n updatePayload[column.name] = newValue;\n }\n\n if (!hasDiff) {\n return;\n }\n\n storage.applyOwnEvent(\n {\n type: \"item-updated\",\n dataset,\n item_id: oldPayload.id,\n payload: JSON.stringify(updatePayload),\n },\n {\n wrapInTransaction: false,\n },\n );\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_deleted\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, itemId: string) => {\n storage.applyOwnEvent(\n {\n type: \"item-deleted\",\n dataset,\n item_id: itemId,\n payload: \"{}\",\n },\n {\n wrapInTransaction: false,\n },\n );\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.addEventListener(\"transaction-committed\", () => {\n if (eventApplied) {\n eventApplied = false;\n storage.dispatchEventsApplied();\n }\n });\n\n reactiveDb.addEventListener(\"transaction-rolled-back\", () => {\n eventApplied = false;\n });\n}\n","const dbIdRegex = /^[a-zA-Z][a-zA-Z\\-0-9]{2,63}$/;\n\nexport function validateDbId(dbId: string) {\n if (!dbIdRegex.test(dbId)) {\n throw new Error(\"Invalid dbId. Must be between 3 and 64 characters long and start with a letter.\");\n }\n}\n","import type { SyncedDb } from \"./sync-db\";\n\nconst devtoolsRegistrySymbol = Symbol.for(\"@sqlite-sync/devtools\");\n\nexport type SQLiteSyncDevtoolsInstance = {\n instanceId: string;\n dbId: string;\n createdAt: number;\n instance: SyncedDb<any>;\n};\n\nexport type SQLiteSyncDevtoolsSnapshot = {\n instances: readonly SQLiteSyncDevtoolsInstance[];\n};\n\nexport type SQLiteSyncDevtoolsRegistry = {\n version: 1;\n instances: Map<string, SQLiteSyncDevtoolsInstance>;\n subscribe(listener: () => void): () => void;\n getSnapshot(): SQLiteSyncDevtoolsSnapshot;\n register(instance: SQLiteSyncDevtoolsInstance): () => void;\n};\n\ntype RegistryGlobal = typeof globalThis & {\n [key: symbol]: SQLiteSyncDevtoolsRegistry | undefined;\n};\n\nfunction createSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const instances = new Map<string, SQLiteSyncDevtoolsInstance>();\n const listeners = new Set<() => void>();\n let snapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n };\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n const updateSnapshot = () => {\n snapshot = {\n instances: Array.from(instances.values()),\n };\n notify();\n };\n\n return {\n version: 1,\n instances,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return snapshot;\n },\n register(instance) {\n instances.set(instance.instanceId, instance);\n updateSnapshot();\n\n let isUnregistered = false;\n return () => {\n if (isUnregistered) return;\n isUnregistered = true;\n\n if (!instances.delete(instance.instanceId)) return;\n updateSnapshot();\n };\n },\n };\n}\n\nexport function getOrCreateSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const registryGlobal = globalThis as RegistryGlobal;\n\n registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();\n\n return registryGlobal[devtoolsRegistrySymbol];\n}\n","import { xxhash } from \"../hash\";\nimport type { HLCCounter } from \"../hlc\";\nimport type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { applyMemoryDbSchema, type MemoryDbSchema, memoryDbConfig } from \"../migrations/system-schema\";\nimport type { CrdtTableConfig } from \"../sqlite-crdt/crdt-schema\";\nimport { createCrdtStorage } from \"../sqlite-crdt/crdt-storage\";\nimport { makeCrdtTable, registerCrdtFunctions } from \"../sqlite-crdt/make-crdt-table\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { SQLiteReactiveDb } from \"./sqlite-reactive-db\";\n\ntype MemoryDbOptions<Database> = {\n nodeId: string;\n migrator: SyncDbMigrator;\n reactiveDb: SQLiteReactiveDb<Database>;\n hlcCounter: HLCCounter;\n crdtTables: CrdtTableConfig[];\n initializeSchema?: boolean;\n initialSyncId?: number;\n eventHlcAccumulator?: StoredValue<string>;\n};\n\nexport async function createMemoryDb<Database>({\n nodeId,\n migrator,\n reactiveDb: _reactiveDb,\n hlcCounter,\n crdtTables,\n initializeSchema = true,\n initialSyncId,\n eventHlcAccumulator,\n}: MemoryDbOptions<Database>) {\n await xxhash.ensureLoaded();\n\n const reactiveDb = _reactiveDb as unknown as SQLiteReactiveDb<MemoryDbSchema>;\n const db = reactiveDb.db;\n\n if (initializeSchema) {\n applyMemoryDbSchema(db);\n for (const table of crdtTables) {\n makeCrdtTable({\n db,\n baseTableName: table.baseTableName,\n crdtTableName: table.crdtTableName,\n });\n }\n }\n\n const crdtStorage = createCrdtStorage({\n nodeId,\n initialLocalSyncId: initialSyncId ?? getCurrentSyncId(db),\n hlc: hlcCounter,\n migrator,\n db,\n dbConfig: memoryDbConfig,\n eventHlcAccumulator,\n });\n\n registerCrdtFunctions({\n reactiveDb,\n storage: crdtStorage,\n });\n\n return {\n crdtStorage,\n };\n}\n\nfunction getCurrentSyncId(db: SQLiteDbWrapper<MemoryDbSchema>) {\n return (\n db.execute<{ syncId: number }>(\"SELECT coalesce(max(sync_id), 0) AS syncId FROM persisted_crdt_events\", {\n loggerLevel: \"system\",\n }).rows[0]?.syncId ?? 0\n );\n}\n","import {\n createDeferredPromise,\n createTypedEventTarget,\n type DeferredPromise,\n noop,\n type TypedEventTarget,\n} from \"../utils\";\nimport type {\n AsyncRpc,\n WorkerBroadcastChannels,\n WorkerConfig,\n WorkerErrorResponseMessage,\n WorkerInitMessage,\n WorkerNotificationMessage,\n WorkerRequestMessage,\n WorkerRequestMethod,\n WorkerResponseMessage,\n WorkerRpc,\n WorkerState,\n} from \"./worker-common\";\nimport { isWorkerErrorResponseMessage, isWorkerNotificationMessage, isWorkerResponseMessage } from \"./worker-common\";\n\ntype NotificationEvents = {\n [K in WorkerNotificationMessage[\"notificationType\"]]: Extract<WorkerNotificationMessage, { notificationType: K }>;\n};\n\nexport const createWorkerDbClient = async ({\n broadcastChannels,\n worker,\n config,\n}: {\n broadcastChannels: WorkerBroadcastChannels;\n worker: Worker;\n config: WorkerConfig;\n}) => {\n const eventTarget = createTypedEventTarget<NotificationEvents>();\n const workerRequestsMap = new Map<string, DeferredPromise<unknown>>();\n let isDisposed = false;\n\n const queryWorker = <TMethod extends WorkerRequestMethod>(\n method: TMethod,\n args: Parameters<WorkerRpc[TMethod]>,\n ): Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>> => {\n if (isDisposed) {\n return Promise.reject(new Error(\"Worker client disposed\"));\n }\n const requestId = crypto.randomUUID();\n const promise = createDeferredPromise<unknown>({\n timeout: 30_000,\n onTimeout: () => workerRequestsMap.delete(requestId),\n });\n workerRequestsMap.set(requestId, promise);\n\n const request: WorkerRequestMessage<TMethod> = {\n type: \"request\",\n requestId,\n method,\n args,\n };\n\n broadcastChannels.requests.postMessage(request);\n\n return promise.promise as Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>>;\n };\n\n const handleWorkerResponse = (message: WorkerResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.resolve(message.data);\n workerRequestsMap.delete(message.requestId);\n };\n\n const handleWorkerError = (message: WorkerErrorResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.reject(new Error(message.error));\n workerRequestsMap.delete(message.requestId);\n };\n\n broadcastChannels.responses.onmessage = (event) => {\n const message = event.data;\n\n if (isWorkerResponseMessage(message)) {\n handleWorkerResponse(message);\n } else if (isWorkerErrorResponseMessage(message)) {\n handleWorkerError(message);\n } else if (isWorkerNotificationMessage(message)) {\n eventTarget.dispatchEvent(message.notificationType, message);\n }\n };\n\n const rpc: AsyncRpc<WorkerRpc> = {\n execute: (query) => queryWorker(\"execute\", [query]),\n getSnapshot: () => queryWorker(\"getSnapshot\", []),\n pushTabEvents: (request) => queryWorker(\"pushTabEvents\", [request]),\n pullEvents: (params) => queryWorker(\"pullEvents\", [params]),\n postState: () => queryWorker(\"postState\", []),\n goOnline: () => queryWorker(\"goOnline\", []),\n goOffline: () => queryWorker(\"goOffline\", []),\n requestReload: (options) => queryWorker(\"requestReload\", [options]),\n };\n\n const statePromise = awaitWorkerState(eventTarget);\n postWorkerConfig(worker, config);\n // On first tab, the worker may not have its BroadcastChannel listener ready yet,\n // so this request can be silently dropped and timeout. The worker will independently\n // post state at the end of init. For subsequent tabs, this triggers the already-running\n // worker to send its current state.\n rpc.postState().catch(noop);\n\n let workerState = await statePromise;\n\n eventTarget.addEventListener(\"state-changed\", (event) => {\n workerState = event.payload.state;\n });\n\n const dispose = () => {\n isDisposed = true;\n broadcastChannels.responses.onmessage = null;\n for (const [id, deferred] of workerRequestsMap) {\n deferred.reject(new Error(\"Worker client disposed\"));\n workerRequestsMap.delete(id);\n }\n };\n\n return {\n ...rpc,\n subscribe: eventTarget.addEventListener,\n getState: () => workerState,\n dispose,\n };\n};\n\nfunction awaitWorkerState(eventTarget: TypedEventTarget<NotificationEvents>) {\n const promise = createDeferredPromise<WorkerState>({ timeout: 15_000 });\n\n const subscription = eventTarget.addEventListener(\"state-changed\", (event) => {\n promise.resolve(event.payload.state);\n subscription.unsubscribe();\n });\n\n return promise.promise;\n}\n\nfunction postWorkerConfig(worker: Worker, config: WorkerConfig) {\n const configMessage: WorkerInitMessage = {\n type: \"init\",\n config,\n };\n worker.postMessage(configMessage);\n}\n","import { validateDbId } from \"./db-id\";\nimport { getOrCreateSQLiteSyncDevtoolsRegistry } from \"./devtools-registry\";\nimport { HLCCounter } from \"./hlc\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\nimport { createMemoryDb } from \"./memory-db/memory-db\";\nimport { createSQLiteReactiveDb } from \"./memory-db/sqlite-reactive-db\";\nimport type { SyncDbMigrator } from \"./migrations/migrator\";\nimport type { SyncDbSchema } from \"./sqlite-crdt/crdt-schema\";\nimport { createCrdtSyncRemoteSource } from \"./sqlite-crdt/crdt-sync-remote-source\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport { createDeferredPromise, generateId } from \"./utils\";\nimport { createWorkerDbClient } from \"./worker-db/db-worker-client\";\nimport { createBroadcastChannels, syncDbClientLockName } from \"./worker-db/worker-common\";\n\ntype SyncedDbOptions<Database, Props = undefined> = {\n dbId: string;\n worker: Worker;\n workerProps: Props;\n syncDbSchema: SyncDbSchema<Database>;\n};\n\nconst defaultLogger: Logger = (type, message, level = \"info\") => {\n const logMessage = `[${type}] ${message}`;\n switch (level) {\n case \"info\":\n console.log(logMessage);\n break;\n case \"warning\":\n console.warn(logMessage);\n break;\n case \"error\":\n console.error(logMessage);\n break;\n case \"trace\":\n console.trace(logMessage);\n break;\n }\n};\n\nexport async function createSyncedDb<Database, Props = undefined>(options: SyncedDbOptions<Database, Props>) {\n validateDbId(options.dbId);\n\n const perf = startPerformanceLogger(defaultLogger);\n\n const instanceId = generateId();\n const tabId = generateId();\n\n const broadcastChannels = createBroadcastChannels(options.dbId);\n\n const clientLockAcquired = createDeferredPromise<void>();\n const clientLockRelease = createDeferredPromise<void>();\n navigator.locks.request(`${syncDbClientLockName}-${options.dbId}`, { mode: \"shared\" }, () => {\n clientLockAcquired.resolve();\n return clientLockRelease.promise;\n });\n await clientLockAcquired.promise;\n\n const workerClient = await createWorkerDbClient({\n worker: options.worker,\n config: {\n clientId: generateId(),\n dbId: options.dbId,\n props: options.workerProps as never,\n },\n broadcastChannels,\n });\n\n const hlcCounter = new HLCCounter(tabId, () => Date.now());\n\n const workerClientSnapshot = await workerClient.getSnapshot();\n const reactiveDb = await createSQLiteReactiveDb<Database>({\n snapshot: workerClientSnapshot.file,\n logger: defaultLogger,\n });\n\n const memoryDbMigrator: SyncDbMigrator = {\n currentSchemaVersion: workerClientSnapshot.schemaVersion,\n latestSchemaVersion: workerClientSnapshot.schemaVersion,\n migrateDbToLatest: () => {\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvent: (event, targetVersion) => {\n if (event.schema_version === targetVersion) {\n return event;\n }\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvents: (events) => events,\n };\n const { crdtStorage } = await createMemoryDb({\n nodeId: tabId,\n migrator: memoryDbMigrator,\n reactiveDb: reactiveDb,\n hlcCounter,\n crdtTables: options.syncDbSchema.tablesConfig,\n });\n\n const pullSyncId = createStoredValue({\n initialValue: workerClientSnapshot.syncId,\n });\n const pushSyncId = createStoredValue({\n initialValue: 0,\n });\n const tabRemoteSource = createCrdtSyncRemoteSource({\n bufferSize: 500,\n pullSyncId,\n pushSyncId,\n storage: crdtStorage,\n nodeId: tabId,\n migrator: memoryDbMigrator,\n remoteFactory: ({ onEventsAvailable }) => {\n const subscription = workerClient.subscribe(\"new-event-chunk-applied\", (event) => {\n onEventsAvailable({ newSyncId: event.payload.newSyncId, remoteEventHlcSum: event.payload.eventHlcSum });\n });\n\n return {\n pullEvents: (request) => workerClient.pullEvents(request),\n pushEvents: (request) => workerClient.pushTabEvents(request),\n disconnect: () => {\n subscription.unsubscribe();\n },\n };\n },\n });\n tabRemoteSource.goOnline();\n\n const reloadRequestedSubscription = workerClient.subscribe(\"reload-requested\", () => {\n globalThis.location?.reload();\n });\n\n perf.logEnd(\"createSyncedDb\", \"initialized\", \"info\");\n\n let isDisposed = false;\n let unregisterDevtools: (() => void) | undefined;\n const dispose = async () => {\n if (isDisposed) return;\n isDisposed = true;\n\n unregisterDevtools?.();\n reloadRequestedSubscription.unsubscribe();\n clientLockRelease.resolve();\n await tabRemoteSource.dispose();\n broadcastChannels.requests.close();\n broadcastChannels.responses.close();\n workerClient.dispose();\n reactiveDb.dispose();\n };\n\n const syncedDb = {\n db: {\n execute: reactiveDb.db.execute.bind(reactiveDb.db),\n executeKysely: reactiveDb.db.executeKysely.bind(reactiveDb.db),\n executeTransaction: reactiveDb.db.executeTransaction.bind(reactiveDb.db),\n createLiveQuery: reactiveDb.createLiveQuery.bind(reactiveDb),\n getSharedLiveQuery: reactiveDb.getSharedLiveQuery.bind(reactiveDb),\n },\n state: {\n getState: workerClient.getState.bind(workerClient),\n subscribe: (onChange: () => void) => {\n const { unsubscribe } = workerClient.subscribe(\"state-changed\", onChange);\n return unsubscribe;\n },\n goOnline: workerClient.goOnline.bind(workerClient),\n goOffline: workerClient.goOffline.bind(workerClient),\n },\n /**\n * Ask the elected worker to broadcast a page reload to all tabs for this dbId.\n *\n * With `clean: true` the worker durably records a reset request epoch before\n * broadcasting, so the worker elected on the next startup initializes with\n * `clearOnInit: true` and wipes the persisted DB. Destructive — use as a\n * recovery path when the durable worker DB may be de-synced.\n *\n * Pending in-memory tab events are not preserved, and the returned promise\n * may never settle in the caller — the page typically unloads first.\n */\n requestReload: async (options: { clean: boolean }) => {\n await workerClient.requestReload(options);\n // Primary path: this tab receives the worker's \"reload-requested\" broadcast\n // like every other tab. Fallback in case the broadcast is missed — in the\n // normal case the page is already unloading and this timeout never fires.\n setTimeout(() => globalThis.location?.reload(), 250);\n },\n subscribe: workerClient.subscribe,\n dispose,\n _internal: {\n executeAsync: workerClient.execute.bind(workerClient),\n getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),\n getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),\n crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),\n crdtTablesConfig: options.syncDbSchema.tablesConfig,\n schemaVersion: workerClientSnapshot.schemaVersion,\n migrationVersions: Object.keys(options.syncDbSchema.migrations)\n .map(Number)\n .sort((a, b) => a - b),\n },\n };\n\n unregisterDevtools = getOrCreateSQLiteSyncDevtoolsRegistry().register({\n instanceId,\n dbId: options.dbId,\n createdAt: Date.now(),\n instance: syncedDb,\n });\n\n return syncedDb;\n}\n\nexport type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;\n"],"mappings":"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","names":["entry","options"]}
1
+ {"version":3,"sources":["../src/memory-db/sqlite-reactive-db.ts","../src/bound-map.ts","../src/sqlite-crdt/crdt-schema.ts","../src/sqlite-crdt/crdt-storage-mutator.ts","../src/sqlite-crdt/make-crdt-table.ts","../src/db-id.ts","../src/devtools-registry.ts","../src/memory-db/memory-db.ts","../src/worker-db/db-worker-client.ts","../src/sync-db.ts"],"sourcesContent":["import sqlite3InitModule, { type Sqlite3Static } from \"@sqlite.org/sqlite-wasm\";\nimport { BoundMap } from \"../bound-map\";\nimport { type Logger, startPerformanceLogger } from \"../logger\";\nimport { type PreparedStatement, SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createTypedEventTarget, type TypedEvent } from \"../utils\";\n\nlet sqliteModule: Sqlite3Static | null = null;\n\ntype TableName<Database> = keyof Database extends string ? keyof Database : never;\n\ntype SQLiteReactiveDbOptions = {\n snapshot: Uint8Array<ArrayBufferLike>;\n logger: Logger;\n};\n\ntype EventsMap = {\n \"transaction-committed\": undefined;\n \"transaction-rolled-back\": undefined;\n \"any-table-changed\": undefined;\n} & Record<`table:${string}`, void>;\n\ntype LiveQuery<TResult> = {\n getRows: () => TResult[];\n refresh: () => void;\n subscribe: (onchange: () => void) => () => void;\n};\n\nexport type SharedLiveQuery<TResult> = LiveQuery<TResult> & {\n readonly sql: string;\n readonly parameters: readonly unknown[];\n getSubscriberCount: () => number;\n};\n\ntype SharedLiveQueryEntry<TResult> = SharedLiveQuery<TResult> & {\n listeners: Set<() => void>;\n unsubscribeFromLiveQuery: (() => void) | null;\n cleanupTimeout: ReturnType<typeof setTimeout> | null;\n};\n\nexport type SharedLiveQuerySnapshot = {\n sql: string;\n parameters: readonly unknown[];\n subscriberCount: number;\n};\n\nexport function createSQLiteReactiveDb<Database>(opts: SQLiteReactiveDbOptions) {\n return SQLiteReactiveDb.create<Database>(opts);\n}\n\nexport class SQLiteReactiveDb<Database> {\n readonly db: SQLiteDbWrapper<Database>;\n private sqlite3: Sqlite3Static;\n\n private readonly logger: Logger;\n\n private tablesUsedStatement: PreparedStatement<[string], { name: string; isWrite: boolean }> | null = null;\n\n private eventTarget = createTypedEventTarget<EventsMap>();\n\n private constructor(sqlite3: Sqlite3Static, logger: Logger) {\n this.sqlite3 = sqlite3;\n this.logger = logger;\n\n this.db = new SQLiteDbWrapper({\n db: () => new sqlite3.oo1.DB({ filename: \":memory:\" }),\n logger: this.logger,\n loggerPrefix: \"memory\",\n sqlite3,\n });\n }\n\n static async create<Database>(opts: SQLiteReactiveDbOptions) {\n const logger = opts.logger;\n const perf = startPerformanceLogger(logger);\n if (!sqliteModule) {\n sqliteModule = await sqlite3InitModule();\n }\n\n const db = new SQLiteReactiveDb<Database>(sqliteModule, logger);\n\n if (opts.snapshot) {\n db.useSnapshot(opts.snapshot);\n }\n db.registerDbHooks();\n\n perf.logEnd(\"createSQLiteMemoryDb\", \"success\", \"system\");\n\n return db;\n }\n\n private liveQueryStatements = new BoundMap<string, PreparedStatement<any[], unknown>>({\n maxSize: 100,\n onRemove(_, value) {\n value.finalize();\n },\n });\n\n private sharedLiveQueries = new Map<string, SharedLiveQueryEntry<unknown>[]>();\n\n createLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const fetchRows = (parameters: readonly unknown[]) => {\n let statement = this.liveQueryStatements.get(query.sql);\n if (!statement) {\n statement = this.db.prepare<any[], any>(query.sql);\n this.liveQueryStatements.set(query.sql, statement);\n }\n return statement.execute(parameters as any) as TResult[];\n };\n\n let rows: TResult[] | null = null;\n\n const getRows = () => {\n if (!rows) {\n rows = fetchRows(query.parameters);\n }\n return rows;\n };\n\n let subscriber: (() => void) | null = null;\n\n let lastParameters: readonly unknown[] = query.parameters;\n const refresh = (parameters?: readonly unknown[]) => {\n if (parameters) {\n lastParameters = parameters;\n }\n rows = fetchRows(lastParameters);\n subscriber?.();\n };\n\n const subscribe = (onchange: () => void) => {\n if (subscriber) {\n throw new Error(\"Subscriber already exists\");\n }\n\n subscriber = onchange;\n const subscription = this.subscribeToQueryChanges({\n sql: query.sql,\n onDataChange: refresh,\n });\n\n return () => {\n subscription.unsubscribe();\n subscriber = null;\n };\n };\n\n return { getRows, refresh, subscribe };\n }\n\n getSharedLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const existingEntry = this.sharedLiveQueries\n .get(query.sql)\n ?.find((entry) => parametersAreEqual(entry.parameters, query.parameters));\n if (existingEntry) {\n if (existingEntry.listeners.size === 0) {\n this.scheduleSharedLiveQueryCleanup(existingEntry);\n }\n return existingEntry as SharedLiveQuery<TResult>;\n }\n\n const liveQuery = this.createLiveQuery<TResult>(query);\n let hasDetachedFromLiveQuery = false;\n const entry: SharedLiveQueryEntry<TResult> = {\n sql: query.sql,\n parameters: query.parameters,\n listeners: new Set(),\n unsubscribeFromLiveQuery: null,\n cleanupTimeout: null,\n getRows: () => liveQuery.getRows(),\n refresh: () => {\n liveQuery.refresh();\n },\n getSubscriberCount: () => entry.listeners.size,\n subscribe: (onchange) => {\n this.cancelSharedLiveQueryCleanup(entry);\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n entry.listeners.add(onchange);\n\n if (!entry.unsubscribeFromLiveQuery) {\n entry.unsubscribeFromLiveQuery = liveQuery.subscribe(() => {\n for (const listener of entry.listeners) {\n listener();\n }\n });\n\n // Rows may have gone stale while no subscriber was listening\n // for table changes.\n if (hasDetachedFromLiveQuery) {\n hasDetachedFromLiveQuery = false;\n liveQuery.refresh();\n }\n }\n\n return () => {\n entry.listeners.delete(onchange);\n\n if (entry.listeners.size === 0) {\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n hasDetachedFromLiveQuery = true;\n this.scheduleSharedLiveQueryCleanup(entry);\n }\n };\n },\n };\n\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n\n // Evict the entry if no subscriber attaches by the next tick.\n this.scheduleSharedLiveQueryCleanup(entry as SharedLiveQueryEntry<unknown>);\n\n return entry;\n }\n\n private registerSharedLiveQueryEntry(entry: SharedLiveQueryEntry<unknown>) {\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql) ?? [];\n if (!matchingSqlEntries.includes(entry)) {\n matchingSqlEntries.push(entry);\n this.sharedLiveQueries.set(entry.sql, matchingSqlEntries);\n }\n }\n\n getSharedLiveQueriesSnapshot(): SharedLiveQuerySnapshot[] {\n const snapshot: SharedLiveQuerySnapshot[] = [];\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n snapshot.push({\n sql: entry.sql,\n parameters: entry.parameters,\n subscriberCount: entry.listeners.size,\n });\n }\n }\n return snapshot;\n }\n\n private scheduleSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.cleanupTimeout = setTimeout(() => {\n entry.cleanupTimeout = null;\n this.releaseSharedLiveQuery(entry);\n }, 0);\n }\n\n private cancelSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.cleanupTimeout) {\n clearTimeout(entry.cleanupTimeout);\n entry.cleanupTimeout = null;\n }\n }\n\n private releaseSharedLiveQuery(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.listeners.size > 0 || entry.unsubscribeFromLiveQuery) {\n return;\n }\n\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql);\n if (!matchingSqlEntries) {\n return;\n }\n\n const nextEntries = matchingSqlEntries.filter((candidate) => candidate !== entry);\n if (nextEntries.length > 0) {\n this.sharedLiveQueries.set(entry.sql, nextEntries);\n } else {\n this.sharedLiveQueries.delete(entry.sql);\n }\n }\n\n subscribeToQueryChanges(params: { sql: string; onDataChange: () => void }) {\n const { sql, onDataChange } = params;\n\n const tables = this.getTablesUsed(sql);\n const readTables = new Set<string>();\n for (const table of tables) {\n if (!readTables.has(table.name)) {\n readTables.add(table.name);\n } else if (table.isWrite) {\n throw new Error(\"This query writes and reads from the same table. This may cause infinite loops.\");\n }\n }\n\n const notifyDataChange = createDebouncedCallback(() => {\n onDataChange();\n }, 30);\n\n for (const table of readTables) {\n this.eventTarget.addEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.addEventListener(\"any-table-changed\", notifyDataChange);\n\n return {\n unsubscribe: () => {\n for (const table of readTables) {\n this.eventTarget.removeEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.removeEventListener(\"any-table-changed\", notifyDataChange);\n },\n };\n }\n\n subscribeToTableChanges(table: string, onChanges: () => void) {\n this.eventTarget.addEventListener(`table:${table}`, onChanges);\n this.eventTarget.addEventListener(\"any-table-changed\", onChanges);\n return {\n unsubscribe: () => {\n this.eventTarget.removeEventListener(`table:${table}`, onChanges);\n this.eventTarget.removeEventListener(\"any-table-changed\", onChanges);\n },\n };\n }\n\n getTablesUsed(query: string) {\n if (!this.tablesUsedStatement) {\n this.tablesUsedStatement = this.db.prepare<[string], { name: string; isWrite: boolean }>(\n \"select t.tbl_name as name, u.wr as isWrite from tables_used(?) as u inner join sqlite_master as t on t.name = u.name where u.schema = 'main'\",\n { loggerLevel: \"system\" },\n );\n }\n\n const tables = this.tablesUsedStatement.execute([query]);\n\n if (tables.length === 0 && query.toLowerCase().includes(\"delete\")) {\n // tables_used function does not work with delete queries that clear entire tables\n tables.push(...this.getClearedTables(query));\n }\n\n return tables;\n }\n\n private getClearedTables(query: string) {\n const operations = this.db.execute<{\n opcode: string;\n p1: number;\n p2: number;\n }>(`EXPLAIN ${query.split(\";\")[0]}`, { loggerLevel: \"system\" }).rows;\n\n const clearedTablesRootPages = new Set<number>();\n for (const operation of operations) {\n if (operation.opcode === \"Clear\" && operation.p2 === 0) {\n clearedTablesRootPages.add(operation.p1);\n }\n }\n\n if (clearedTablesRootPages.size === 0) {\n return [];\n }\n\n const tableNames = this.db.execute<{ name: string; isWrite: boolean }>(\n `select t.tbl_name as name, true as isWrite from sqlite_master as t where t.rootpage in (${Array.from(\n clearedTablesRootPages,\n ).join(\",\")})`,\n { loggerLevel: \"system\" },\n ).rows;\n\n return tableNames;\n }\n\n addEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.addEventListener(type, listener);\n }\n\n removeEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.removeEventListener(type, listener);\n }\n\n private notifyTableSubscribers(tables: (TableName<Database> | (string & {}))[] | Set<string> | null = null) {\n if (!tables) {\n this.eventTarget.dispatchEvent(\"any-table-changed\", undefined);\n return;\n }\n\n for (const table of tables) {\n this.eventTarget.dispatchEvent(`table:${table}`, undefined);\n }\n }\n\n private registerDbHooks() {\n let updateQueue = new Set<string>();\n\n this.sqlite3.capi.sqlite3_update_hook(\n this.db.ensureDb,\n (_ctx, _opId, _db, table) => {\n updateQueue.add(table);\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_rollback_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n updateQueue.clear();\n this.eventTarget.dispatchEvent(\"transaction-rolled-back\", undefined);\n\n return 0;\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_commit_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n const tables = updateQueue;\n updateQueue = new Set<string>();\n this.eventTarget.dispatchEvent(\"transaction-committed\", undefined);\n\n queueMicrotask(() => {\n this.notifyTableSubscribers(tables);\n });\n return 0;\n },\n 0,\n );\n }\n\n createSnapshot() {\n const perf = startPerformanceLogger(this.logger);\n const snapshot = this.sqlite3.capi.sqlite3_js_db_export(this.db.ensureDb);\n perf.logEnd(\"createSnapshot\", `snapshot size: ${snapshot.byteLength}`, \"info\");\n\n return snapshot;\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n this.db.useSnapshot(snapshot);\n this.notifyTableSubscribers();\n }\n\n dispose() {\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n entry.listeners.clear();\n }\n }\n this.sharedLiveQueries.clear();\n this.liveQueryStatements.clear();\n if (this.tablesUsedStatement) {\n this.tablesUsedStatement.finalize();\n this.tablesUsedStatement = null;\n }\n this.db.close();\n }\n}\n\nfunction createDebouncedCallback<TArgs extends unknown[]>(callback: (...args: TArgs) => void, delay: number) {\n let timeout: unknown | null = null;\n let shouldCallWithoutDelay = true;\n\n return (...args: TArgs) => {\n if (shouldCallWithoutDelay) {\n callback(...args);\n shouldCallWithoutDelay = false;\n return;\n }\n\n const effect = () => {\n timeout = null;\n shouldCallWithoutDelay = true;\n return callback(...args);\n };\n\n if (timeout) {\n clearTimeout(timeout as any);\n }\n\n timeout = setTimeout(effect, delay);\n };\n}\n\nexport function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) {\n return false;\n }\n }\n return true;\n}\n","interface BoundMapOptions<K, V> {\n maxSize: number;\n onRemove: ((key: K, value: V) => void) | undefined;\n}\n\nexport class BoundMap<K, V> {\n private map = new Map<K, V>();\n private maxSize: number;\n private onRemove: ((key: K, value: V) => void) | undefined;\n\n constructor(opts: BoundMapOptions<K, V>) {\n this.maxSize = opts.maxSize;\n this.onRemove = opts.onRemove;\n }\n\n set = (key: K, value: V) => {\n if (this.onRemove && this.map.has(key)) {\n const old = this.map.get(key) as V;\n this.map.set(key, value);\n this.onRemove(key, old);\n } else {\n this.map.set(key, value);\n }\n if (this.map.size > this.maxSize) {\n const firstKey = this.map.keys().next().value as K;\n this.delete(firstKey);\n }\n };\n\n get = (key: K): V | undefined => {\n return this.map.get(key);\n };\n\n delete = (key: K) => {\n if (this.onRemove && this.map.has(key)) {\n const value = this.map.get(key) as V;\n this.map.delete(key);\n this.onRemove(key, value);\n } else {\n this.map.delete(key);\n }\n };\n\n clear = () => {\n const onRemove = this.onRemove;\n if (onRemove) {\n this.map.forEach((value, key) => {\n onRemove(key, value);\n });\n }\n this.map.clear();\n };\n}\n","import type { ColumnType } from \"kysely\";\nimport type { Migrations } from \"../migrations/migrator\";\n\nexport type CrdtTableConfig = {\n baseTableName: string;\n crdtTableName: string;\n};\n\nexport function createSyncDbSchema({ migrations }: { migrations: Migrations }) {\n return new CrdtSchemaBuilder({ tables: [], migrations });\n}\n\nexport interface CreateCrdtSchemaOptions {\n tables: CrdtTableConfig[];\n migrations: Migrations;\n}\n\n// biome-ignore lint/complexity/noBannedTypes: required generic\nclass CrdtSchemaBuilder<ClientDB = {}, ServerDB = {}, MutationsDB = {}>\n implements SyncDbSchema<ClientDB, ServerDB, MutationsDB>\n{\n constructor(private config: CreateCrdtSchemaOptions) {}\n\n get tablesConfig() {\n return this.config.tables;\n }\n\n get migrations() {\n return this.config.migrations;\n }\n\n get \"~clientSchema\"() {\n console.warn(\"~clientSchema should not be accessed on the client\");\n return null as any;\n }\n\n get \"~serverSchema\"() {\n console.warn(\"~serverSchema should not be accessed on the server\");\n return null as any;\n }\n\n get \"~mutationsSchema\"() {\n console.warn(\"~mutationsSchema should not be accessed on the client\");\n return null as any;\n }\n\n addTable<Table extends Record<string, unknown>>() {\n const withConfig = <const CrdtTable extends string, const BaseTable extends string>({\n baseTableName,\n crdtTableName,\n }: {\n baseTableName: BaseTable;\n crdtTableName: CrdtTable;\n }) => {\n this.config.tables.push({ baseTableName, crdtTableName });\n return new CrdtSchemaBuilder<\n ClientDB & { [K in CrdtTable]: Table } & { [K in BaseTable]: ReadonlyTable<Table> },\n ServerDB & { [K in CrdtTable]: ReadonlyTable<Table> } & { [K in BaseTable]: ReadonlyTable<Table> },\n MutationsDB & { [K in BaseTable]: Table }\n >(this.config);\n };\n\n return { withConfig };\n }\n\n build() {\n return this as SyncDbSchema<ClientDB, ServerDB, MutationsDB>;\n }\n}\n\n// biome-ignore lint/complexity/noBannedTypes: required generic\nexport interface SyncDbSchema<ClientDB = {}, ServerDB = {}, MutationsDB = {}> {\n get tablesConfig(): CrdtTableConfig[];\n get migrations(): Migrations;\n \"~clientSchema\": ClientDB;\n \"~serverSchema\": ServerDB;\n \"~mutationsSchema\": MutationsDB;\n}\n\ntype ReadonlyTable<Table extends Record<string, unknown>> = {\n [K in keyof Table]: ColumnType<Table[K], never, never>;\n};\n","import type { CrdtStorage, OwnCrdtEvent } from \"./crdt-storage\";\n\nexport type CrdtStorageMutator<Database> = ReturnType<typeof createCrdtStorageMutator<Database>>;\n\ntype CommitEventOptions<Database, Table extends keyof Database & string> =\n | {\n type: \"item-created\";\n dataset: Table;\n item_id: string;\n payload: CreateEventPayload<Database, Table>;\n }\n | {\n type: \"item-updated\";\n dataset: Table;\n item_id: string;\n payload: UpdateEventPayload<Database, Table>;\n }\n | {\n type: \"item-deleted\";\n dataset: Table;\n item_id: string;\n };\n\ntype CreateEventPayload<Database, Table extends keyof Database> = Omit<Database[Table], \"tombstone\">;\ntype UpdateEventPayload<Database, Table extends keyof Database> = Omit<Partial<Database[Table]>, \"id\" | \"tombstone\">;\n\nexport function createCrdtStorageMutator<Database>({ storage }: { storage: CrdtStorage }) {\n const mapToStorageEvent = (event: CommitEventOptions<Database, keyof Database & string>): OwnCrdtEvent => {\n switch (event.type) {\n case \"item-created\":\n return {\n type: \"item-created\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-updated\":\n return {\n type: \"item-updated\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-deleted\":\n return {\n type: \"item-deleted\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: \"{}\",\n };\n }\n };\n\n const enqueueEvents = (events: CommitEventOptions<Database, keyof Database & string>[]) => {\n storage.enqueueOwnEvents(events.map(mapToStorageEvent));\n };\n\n const createEvent = <Table extends keyof Database & string>(event: CommitEventOptions<Database, Table>) => {\n return event;\n };\n\n const enqueueEvent = (event: CommitEventOptions<Database, keyof Database & string>) => {\n storage.enqueueOwnEvents([mapToStorageEvent(event)]);\n };\n\n return {\n enqueueEvents,\n createEvent,\n enqueueEvent,\n };\n}\n","import type { SQLiteReactiveDb } from \"../memory-db/sqlite-reactive-db\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { quoteId } from \"../utils\";\nimport type { CrdtStorage } from \"./crdt-storage\";\n\nexport function makeCrdtTable({\n db,\n baseTableName,\n crdtTableName,\n}: {\n db: SQLiteDbWrapper<any>;\n baseTableName: string;\n crdtTableName: string;\n}) {\n const tableSchema = db.dbSchema[baseTableName];\n\n if (!tableSchema) {\n throw new Error(`Table ${baseTableName} not found`);\n }\n\n const columns = new Map(tableSchema.columns.map((c) => [c.name, c]));\n\n const idColumn = columns.get(\"id\");\n if (!idColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"id\" column. CRDT tables must have an \"id\" column to identify items.`,\n );\n }\n if (idColumn.dataType.toUpperCase() !== \"TEXT\") {\n throw new Error(\n `Table \"${baseTableName}\": \"id\" column must be of type TEXT, got \"${idColumn.dataType}\". CRDT item IDs are stored as strings.`,\n );\n }\n\n const tombstoneColumn = columns.get(\"tombstone\");\n if (!tombstoneColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"tombstone\" column. CRDT tables must have a \"tombstone\" INTEGER column for soft deletes.`,\n );\n }\n const tombstoneType = tombstoneColumn.dataType.toUpperCase();\n if (tombstoneType !== \"INTEGER\" && tombstoneType !== \"BOOLEAN\") {\n throw new Error(\n `Table \"${baseTableName}\": \"tombstone\" column must be of type INTEGER or BOOLEAN, got \"${tombstoneColumn.dataType}\". It is compared as 0/1 for soft deletes.`,\n );\n }\n\n db.execute(\n `\ncreate view ${quoteId(crdtTableName)} as\nselect * from ${quoteId(baseTableName)}\nwhere tombstone = 0;`,\n { loggerLevel: \"system\" },\n );\n\n const allColumnNames = tableSchema.columns.map((column) => column.name);\n\n const jsonPayload = (from: \"new\" | \"old\") =>\n `'{'||${allColumnNames.map((col) => `'\"${col}\":'||json_quote(${from}.${quoteId(col)})`).join(\"||','||\")}||'}'`;\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_created`)}\ninstead of insert on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_created('${baseTableName}', ${jsonPayload(\"new\")});\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_updated`)}\ninstead of update on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_updated(\n '${baseTableName}',\n ${jsonPayload(\"old\")},\n ${jsonPayload(\"new\")}\n);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_deleted`)}\ninstead of delete on ${quoteId(crdtTableName)}\nfor each row\nwhen old.tombstone = 0\nbegin\nselect handle_item_deleted('${baseTableName}', old.id);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n}\n\nexport function registerCrdtFunctions({\n reactiveDb,\n storage,\n}: {\n reactiveDb: SQLiteReactiveDb<any>;\n storage: CrdtStorage;\n}) {\n let eventApplied = false;\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_created\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, payloadRaw: string) => {\n const payload = JSON.parse(payloadRaw) as { id: string };\n\n storage.applyOwnEvent(\n {\n type: \"item-created\",\n dataset,\n item_id: payload.id,\n payload: payloadRaw,\n },\n {\n wrapInTransaction: false,\n },\n );\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_updated\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, oldPayloadRaw: string, newPayloadRaw: string) => {\n if (oldPayloadRaw === newPayloadRaw) {\n return undefined;\n }\n\n const tableSchema = reactiveDb.db.dbSchema[dataset];\n\n if (!tableSchema?.columns) {\n throw new Error(`Schema not found for dataset: ${dataset}`);\n }\n\n const oldPayload = JSON.parse(oldPayloadRaw);\n const newPayload = JSON.parse(newPayloadRaw);\n\n let hasDiff = false;\n const updatePayload = {} as Record<string, unknown>;\n\n for (const column of tableSchema.columns) {\n const oldValue = oldPayload[column.name];\n const newValue = newPayload[column.name];\n if (oldValue === newValue) {\n continue;\n }\n\n if (column.name === \"id\") {\n throw new Error(\n `Cannot update the \"id\" column of an item. It is used to identify the item and must be immutable.`,\n );\n }\n\n hasDiff = true;\n updatePayload[column.name] = newValue;\n }\n\n if (!hasDiff) {\n return;\n }\n\n storage.applyOwnEvent(\n {\n type: \"item-updated\",\n dataset,\n item_id: oldPayload.id,\n payload: JSON.stringify(updatePayload),\n },\n {\n wrapInTransaction: false,\n },\n );\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_deleted\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, itemId: string) => {\n storage.applyOwnEvent(\n {\n type: \"item-deleted\",\n dataset,\n item_id: itemId,\n payload: \"{}\",\n },\n {\n wrapInTransaction: false,\n },\n );\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.addEventListener(\"transaction-committed\", () => {\n if (eventApplied) {\n eventApplied = false;\n storage.dispatchEventsApplied();\n }\n });\n\n reactiveDb.addEventListener(\"transaction-rolled-back\", () => {\n eventApplied = false;\n });\n}\n","const dbIdRegex = /^[a-zA-Z][a-zA-Z\\-0-9]{2,63}$/;\n\nexport function validateDbId(dbId: string) {\n if (!dbIdRegex.test(dbId)) {\n throw new Error(\"Invalid dbId. Must be between 3 and 64 characters long and start with a letter.\");\n }\n}\n","import type { SyncedDb } from \"./sync-db\";\n\nconst devtoolsRegistrySymbol = Symbol.for(\"@sqlite-sync/devtools\");\n\nexport type SQLiteSyncDevtoolsInstance = {\n instanceId: string;\n dbId: string;\n createdAt: number;\n instance: SyncedDb<any>;\n};\n\nexport type SQLiteSyncDevtoolsSnapshot = {\n instances: readonly SQLiteSyncDevtoolsInstance[];\n};\n\nexport type SQLiteSyncDevtoolsRegistry = {\n version: 1;\n instances: Map<string, SQLiteSyncDevtoolsInstance>;\n subscribe(listener: () => void): () => void;\n getSnapshot(): SQLiteSyncDevtoolsSnapshot;\n register(instance: SQLiteSyncDevtoolsInstance): () => void;\n};\n\ntype RegistryGlobal = typeof globalThis & {\n [key: symbol]: SQLiteSyncDevtoolsRegistry | undefined;\n};\n\nfunction createSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const instances = new Map<string, SQLiteSyncDevtoolsInstance>();\n const listeners = new Set<() => void>();\n let snapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n };\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n const updateSnapshot = () => {\n snapshot = {\n instances: Array.from(instances.values()),\n };\n notify();\n };\n\n return {\n version: 1,\n instances,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return snapshot;\n },\n register(instance) {\n instances.set(instance.instanceId, instance);\n updateSnapshot();\n\n let isUnregistered = false;\n return () => {\n if (isUnregistered) return;\n isUnregistered = true;\n\n if (!instances.delete(instance.instanceId)) return;\n updateSnapshot();\n };\n },\n };\n}\n\nexport function getOrCreateSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const registryGlobal = globalThis as RegistryGlobal;\n\n registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();\n\n return registryGlobal[devtoolsRegistrySymbol];\n}\n","import { xxhash } from \"../hash\";\nimport type { HLCCounter } from \"../hlc\";\nimport type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { applyMemoryDbSchema, type MemoryDbSchema, memoryDbConfig } from \"../migrations/system-schema\";\nimport type { CrdtTableConfig } from \"../sqlite-crdt/crdt-schema\";\nimport { createCrdtStorage } from \"../sqlite-crdt/crdt-storage\";\nimport { makeCrdtTable, registerCrdtFunctions } from \"../sqlite-crdt/make-crdt-table\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { SQLiteReactiveDb } from \"./sqlite-reactive-db\";\n\ntype MemoryDbOptions<Database> = {\n nodeId: string;\n migrator: SyncDbMigrator;\n reactiveDb: SQLiteReactiveDb<Database>;\n hlcCounter: HLCCounter;\n crdtTables: CrdtTableConfig[];\n initializeSchema?: boolean;\n initialSyncId?: number;\n eventHlcAccumulator?: StoredValue<string>;\n};\n\nexport async function createMemoryDb<Database>({\n nodeId,\n migrator,\n reactiveDb: _reactiveDb,\n hlcCounter,\n crdtTables,\n initializeSchema = true,\n initialSyncId,\n eventHlcAccumulator,\n}: MemoryDbOptions<Database>) {\n await xxhash.ensureLoaded();\n\n const reactiveDb = _reactiveDb as unknown as SQLiteReactiveDb<MemoryDbSchema>;\n const db = reactiveDb.db;\n\n if (initializeSchema) {\n applyMemoryDbSchema(db);\n for (const table of crdtTables) {\n makeCrdtTable({\n db,\n baseTableName: table.baseTableName,\n crdtTableName: table.crdtTableName,\n });\n }\n }\n\n const crdtStorage = createCrdtStorage({\n nodeId,\n initialLocalSyncId: initialSyncId ?? getCurrentSyncId(db),\n hlc: hlcCounter,\n migrator,\n db,\n dbConfig: memoryDbConfig,\n eventHlcAccumulator,\n });\n\n registerCrdtFunctions({\n reactiveDb,\n storage: crdtStorage,\n });\n\n return {\n crdtStorage,\n };\n}\n\nfunction getCurrentSyncId(db: SQLiteDbWrapper<MemoryDbSchema>) {\n return (\n db.execute<{ syncId: number }>(\"SELECT coalesce(max(sync_id), 0) AS syncId FROM persisted_crdt_events\", {\n loggerLevel: \"system\",\n }).rows[0]?.syncId ?? 0\n );\n}\n","import {\n createDeferredPromise,\n createTypedEventTarget,\n type DeferredPromise,\n noop,\n type TypedEventTarget,\n} from \"../utils\";\nimport type {\n AsyncRpc,\n WorkerBroadcastChannels,\n WorkerConfig,\n WorkerErrorResponseMessage,\n WorkerInitMessage,\n WorkerNotificationMessage,\n WorkerRequestMessage,\n WorkerRequestMethod,\n WorkerResponseMessage,\n WorkerRpc,\n WorkerState,\n} from \"./worker-common\";\nimport { isWorkerErrorResponseMessage, isWorkerNotificationMessage, isWorkerResponseMessage } from \"./worker-common\";\n\ntype NotificationEvents = {\n [K in WorkerNotificationMessage[\"notificationType\"]]: Extract<WorkerNotificationMessage, { notificationType: K }>;\n};\n\nexport const createWorkerDbClient = async ({\n broadcastChannels,\n worker,\n config,\n}: {\n broadcastChannels: WorkerBroadcastChannels;\n worker: Worker;\n config: WorkerConfig;\n}) => {\n const eventTarget = createTypedEventTarget<NotificationEvents>();\n const workerRequestsMap = new Map<string, DeferredPromise<unknown>>();\n let isDisposed = false;\n\n const queryWorker = <TMethod extends WorkerRequestMethod>(\n method: TMethod,\n args: Parameters<WorkerRpc[TMethod]>,\n ): Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>> => {\n if (isDisposed) {\n return Promise.reject(new Error(\"Worker client disposed\"));\n }\n const requestId = crypto.randomUUID();\n const promise = createDeferredPromise<unknown>({\n timeout: 30_000,\n onTimeout: () => workerRequestsMap.delete(requestId),\n });\n workerRequestsMap.set(requestId, promise);\n\n const request: WorkerRequestMessage<TMethod> = {\n type: \"request\",\n requestId,\n method,\n args,\n };\n\n broadcastChannels.requests.postMessage(request);\n\n return promise.promise as Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>>;\n };\n\n const handleWorkerResponse = (message: WorkerResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.resolve(message.data);\n workerRequestsMap.delete(message.requestId);\n };\n\n const handleWorkerError = (message: WorkerErrorResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.reject(new Error(message.error));\n workerRequestsMap.delete(message.requestId);\n };\n\n broadcastChannels.responses.onmessage = (event) => {\n const message = event.data;\n\n if (isWorkerResponseMessage(message)) {\n handleWorkerResponse(message);\n } else if (isWorkerErrorResponseMessage(message)) {\n handleWorkerError(message);\n } else if (isWorkerNotificationMessage(message)) {\n eventTarget.dispatchEvent(message.notificationType, message);\n }\n };\n\n const rpc: AsyncRpc<WorkerRpc> = {\n execute: (query) => queryWorker(\"execute\", [query]),\n getSnapshot: () => queryWorker(\"getSnapshot\", []),\n pushTabEvents: (request) => queryWorker(\"pushTabEvents\", [request]),\n pullEvents: (params) => queryWorker(\"pullEvents\", [params]),\n postState: () => queryWorker(\"postState\", []),\n goOnline: () => queryWorker(\"goOnline\", []),\n goOffline: () => queryWorker(\"goOffline\", []),\n requestReload: (options) => queryWorker(\"requestReload\", [options]),\n };\n\n const statePromise = awaitWorkerState(eventTarget);\n postWorkerConfig(worker, config);\n // On first tab, the worker may not have its BroadcastChannel listener ready yet,\n // so this request can be silently dropped and timeout. The worker will independently\n // post state at the end of init. For subsequent tabs, this triggers the already-running\n // worker to send its current state.\n rpc.postState().catch(noop);\n\n let workerState = await statePromise;\n\n eventTarget.addEventListener(\"state-changed\", (event) => {\n workerState = event.payload.state;\n });\n\n const dispose = () => {\n isDisposed = true;\n broadcastChannels.responses.onmessage = null;\n for (const [id, deferred] of workerRequestsMap) {\n deferred.reject(new Error(\"Worker client disposed\"));\n workerRequestsMap.delete(id);\n }\n };\n\n return {\n ...rpc,\n subscribe: eventTarget.addEventListener,\n getState: () => workerState,\n dispose,\n };\n};\n\nfunction awaitWorkerState(eventTarget: TypedEventTarget<NotificationEvents>) {\n const promise = createDeferredPromise<WorkerState>({ timeout: 15_000 });\n\n const subscription = eventTarget.addEventListener(\"state-changed\", (event) => {\n promise.resolve(event.payload.state);\n subscription.unsubscribe();\n });\n\n return promise.promise;\n}\n\nfunction postWorkerConfig(worker: Worker, config: WorkerConfig) {\n const configMessage: WorkerInitMessage = {\n type: \"init\",\n config,\n };\n worker.postMessage(configMessage);\n}\n","import { validateDbId } from \"./db-id\";\nimport { getOrCreateSQLiteSyncDevtoolsRegistry } from \"./devtools-registry\";\nimport { HLCCounter } from \"./hlc\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\nimport { createMemoryDb } from \"./memory-db/memory-db\";\nimport { createSQLiteReactiveDb } from \"./memory-db/sqlite-reactive-db\";\nimport type { SyncDbMigrator } from \"./migrations/migrator\";\nimport type { SyncDbSchema } from \"./sqlite-crdt/crdt-schema\";\nimport { createCrdtSyncRemoteSource } from \"./sqlite-crdt/crdt-sync-remote-source\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport { createDeferredPromise, generateId } from \"./utils\";\nimport { createWorkerDbClient } from \"./worker-db/db-worker-client\";\nimport { createBroadcastChannels, syncDbClientLockName } from \"./worker-db/worker-common\";\n\ntype SyncedDbOptions<Database, Props = undefined> = {\n dbId: string;\n worker: Worker;\n workerProps: Props;\n syncDbSchema: SyncDbSchema<Database>;\n};\n\nconst defaultLogger: Logger = (type, message, level = \"info\") => {\n const logMessage = `[${type}] ${message}`;\n switch (level) {\n case \"info\":\n console.log(logMessage);\n break;\n case \"warning\":\n console.warn(logMessage);\n break;\n case \"error\":\n console.error(logMessage);\n break;\n case \"trace\":\n console.trace(logMessage);\n break;\n }\n};\n\nexport async function createSyncedDb<Database, Props = undefined>(options: SyncedDbOptions<Database, Props>) {\n validateDbId(options.dbId);\n\n const perf = startPerformanceLogger(defaultLogger);\n\n const instanceId = generateId();\n const tabId = generateId();\n\n const broadcastChannels = createBroadcastChannels(options.dbId);\n\n const clientLockAcquired = createDeferredPromise<void>();\n const clientLockRelease = createDeferredPromise<void>();\n navigator.locks.request(`${syncDbClientLockName}-${options.dbId}`, { mode: \"shared\" }, () => {\n clientLockAcquired.resolve();\n return clientLockRelease.promise;\n });\n await clientLockAcquired.promise;\n\n const workerClient = await createWorkerDbClient({\n worker: options.worker,\n config: {\n clientId: generateId(),\n dbId: options.dbId,\n props: options.workerProps as never,\n },\n broadcastChannels,\n });\n\n const hlcCounter = new HLCCounter(tabId, () => Date.now());\n\n const workerClientSnapshot = await workerClient.getSnapshot();\n const reactiveDb = await createSQLiteReactiveDb<Database>({\n snapshot: workerClientSnapshot.file,\n logger: defaultLogger,\n });\n\n const memoryDbMigrator: SyncDbMigrator = {\n currentSchemaVersion: workerClientSnapshot.schemaVersion,\n latestSchemaVersion: workerClientSnapshot.schemaVersion,\n migrateDbToLatest: () => {\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvent: (event, targetVersion) => {\n if (event.schema_version === targetVersion) {\n return event;\n }\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvents: (events) => events,\n };\n const { crdtStorage } = await createMemoryDb({\n nodeId: tabId,\n migrator: memoryDbMigrator,\n reactiveDb: reactiveDb,\n hlcCounter,\n crdtTables: options.syncDbSchema.tablesConfig,\n });\n\n const pullSyncId = createStoredValue({\n initialValue: workerClientSnapshot.syncId,\n });\n const pushSyncId = createStoredValue({\n initialValue: 0,\n });\n const tabRemoteSource = createCrdtSyncRemoteSource({\n bufferSize: 500,\n pullSyncId,\n pushSyncId,\n storage: crdtStorage,\n nodeId: tabId,\n migrator: memoryDbMigrator,\n remoteFactory: ({ onEventsAvailable }) => {\n const subscription = workerClient.subscribe(\"new-event-chunk-applied\", (event) => {\n onEventsAvailable({ newSyncId: event.payload.newSyncId, remoteEventHlcSum: event.payload.eventHlcSum });\n });\n\n return {\n pullEvents: (request) => workerClient.pullEvents(request),\n pushEvents: (request) => workerClient.pushTabEvents(request),\n disconnect: () => {\n subscription.unsubscribe();\n },\n };\n },\n });\n tabRemoteSource.goOnline();\n\n const reloadRequestedSubscription = workerClient.subscribe(\"reload-requested\", () => {\n globalThis.location?.reload();\n });\n\n perf.logEnd(\"createSyncedDb\", \"initialized\", \"info\");\n\n let isDisposed = false;\n let unregisterDevtools: (() => void) | undefined;\n const dispose = async () => {\n if (isDisposed) return;\n isDisposed = true;\n\n unregisterDevtools?.();\n reloadRequestedSubscription.unsubscribe();\n clientLockRelease.resolve();\n await tabRemoteSource.dispose();\n broadcastChannels.requests.close();\n broadcastChannels.responses.close();\n workerClient.dispose();\n reactiveDb.dispose();\n };\n\n const syncedDb = {\n db: {\n execute: reactiveDb.db.execute.bind(reactiveDb.db),\n executeKysely: reactiveDb.db.executeKysely.bind(reactiveDb.db),\n executeTransaction: reactiveDb.db.executeTransaction.bind(reactiveDb.db),\n createLiveQuery: reactiveDb.createLiveQuery.bind(reactiveDb),\n getSharedLiveQuery: reactiveDb.getSharedLiveQuery.bind(reactiveDb),\n },\n state: {\n getState: workerClient.getState.bind(workerClient),\n subscribe: (onChange: () => void) => {\n const { unsubscribe } = workerClient.subscribe(\"state-changed\", onChange);\n return unsubscribe;\n },\n goOnline: workerClient.goOnline.bind(workerClient),\n goOffline: workerClient.goOffline.bind(workerClient),\n },\n /**\n * Ask the elected worker to broadcast a page reload to all tabs for this dbId.\n *\n * With `clean: true` the worker durably records a reset request epoch before\n * broadcasting, so the worker elected on the next startup initializes with\n * `clearOnInit: true` and wipes the persisted DB. Destructive — use as a\n * recovery path when the durable worker DB may be de-synced.\n *\n * Pending in-memory tab events are not preserved, and the returned promise\n * may never settle in the caller — the page typically unloads first.\n */\n requestReload: async (options: { clean: boolean }) => {\n await workerClient.requestReload(options);\n // Primary path: this tab receives the worker's \"reload-requested\" broadcast\n // like every other tab. Fallback in case the broadcast is missed — in the\n // normal case the page is already unloading and this timeout never fires.\n setTimeout(() => globalThis.location?.reload(), 250);\n },\n subscribe: workerClient.subscribe,\n dispose,\n _internal: {\n executeAsync: workerClient.execute.bind(workerClient),\n getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),\n getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),\n crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),\n crdtTablesConfig: options.syncDbSchema.tablesConfig,\n schemaVersion: workerClientSnapshot.schemaVersion,\n migrationVersions: Object.keys(options.syncDbSchema.migrations)\n .map(Number)\n .sort((a, b) => a - b),\n },\n };\n\n unregisterDevtools = getOrCreateSQLiteSyncDevtoolsRegistry().register({\n instanceId,\n dbId: options.dbId,\n createdAt: Date.now(),\n instance: syncedDb,\n });\n\n return syncedDb;\n}\n\nexport type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;\n"],"mappings":"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","names":["entry","options"]}
@@ -45,7 +45,7 @@ declare class CrdtSchemaBuilder<ClientDB = {}, ServerDB = {}, MutationsDB = {}>
45
45
  withConfig: <const CrdtTable extends string, const BaseTable extends string>({ baseTableName, crdtTableName, }: {
46
46
  baseTableName: BaseTable;
47
47
  crdtTableName: CrdtTable;
48
- }) => CrdtSchemaBuilder<ClientDB & { [K in CrdtTable]: Table; } & { [K_1 in BaseTable]: ReadonlyTable<Table>; }, ServerDB & { [K_2 in BaseTable]: ReadonlyTable<Table>; }, MutationsDB & { [K_3 in BaseTable]: Table; }>;
48
+ }) => CrdtSchemaBuilder<ClientDB & { [K in CrdtTable]: Table; } & { [K_1 in BaseTable]: ReadonlyTable<Table>; }, ServerDB & { [K_2 in CrdtTable]: ReadonlyTable<Table>; } & { [K_3 in BaseTable]: ReadonlyTable<Table>; }, MutationsDB & { [K_4 in BaseTable]: Table; }>;
49
49
  };
50
50
  build(): SyncDbSchema<ClientDB, ServerDB, MutationsDB>;
51
51
  }
package/dist/worker.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ag as CreateRemoteSourceFactory, ae as WorkerConfig, L as Logger } from './crdt-sync-remote-source-CJrVzW-B.js';
2
2
  export { J as EventsPullRequest, N as EventsPushRequest, O as EventsPushResponse, ah as GetEventsBatch } from './crdt-sync-remote-source-CJrVzW-B.js';
3
- import { S as SyncDbSchema, d as ResetStore } from './reset-state-C_plkZGK.js';
3
+ import { S as SyncDbSchema, d as ResetStore } from './reset-state-Comk7IC0.js';
4
4
  import 'kysely';
5
5
  import '@sqlite.org/sqlite-wasm';
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlite-sync/core",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "SQLite synchronization library with CRDT support",
5
5
  "type": "module",
6
6
  "license": "MIT",