@sqlite-sync/core 0.4.3 → 0.4.4

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
@@ -24,6 +24,21 @@ type EventsMap = {
24
24
  "transaction-rolled-back": undefined;
25
25
  "any-table-changed": undefined;
26
26
  } & Record<`table:${string}`, void>;
27
+ type LiveQuery<TResult> = {
28
+ getRows: () => TResult[];
29
+ refresh: () => void;
30
+ subscribe: (onchange: () => void) => () => void;
31
+ };
32
+ type SharedLiveQuery<TResult> = LiveQuery<TResult> & {
33
+ readonly sql: string;
34
+ readonly parameters: readonly unknown[];
35
+ getSubscriberCount: () => number;
36
+ };
37
+ type SharedLiveQuerySnapshot = {
38
+ sql: string;
39
+ parameters: readonly unknown[];
40
+ subscriberCount: number;
41
+ };
27
42
  declare class SQLiteReactiveDb<Database> {
28
43
  readonly db: SQLiteDbWrapper<Database>;
29
44
  private sqlite3;
@@ -33,6 +48,7 @@ declare class SQLiteReactiveDb<Database> {
33
48
  private constructor();
34
49
  static create<Database>(opts: SQLiteReactiveDbOptions): Promise<SQLiteReactiveDb<Database>>;
35
50
  private liveQueryStatements;
51
+ private sharedLiveQueries;
36
52
  createLiveQuery<TResult>(query: {
37
53
  sql: string;
38
54
  parameters: readonly unknown[];
@@ -41,6 +57,15 @@ declare class SQLiteReactiveDb<Database> {
41
57
  refresh: (parameters?: readonly unknown[]) => void;
42
58
  subscribe: (onchange: () => void) => () => void;
43
59
  };
60
+ getSharedLiveQuery<TResult>(query: {
61
+ sql: string;
62
+ parameters: readonly unknown[];
63
+ }): SharedLiveQuery<TResult>;
64
+ private registerSharedLiveQueryEntry;
65
+ getSharedLiveQueriesSnapshot(): SharedLiveQuerySnapshot[];
66
+ private scheduleSharedLiveQueryCleanup;
67
+ private cancelSharedLiveQueryCleanup;
68
+ private releaseSharedLiveQuery;
44
69
  subscribeToQueryChanges(params: {
45
70
  sql: string;
46
71
  onDataChange: () => void;
@@ -63,6 +88,7 @@ declare class SQLiteReactiveDb<Database> {
63
88
  useSnapshot(snapshot: Uint8Array<ArrayBufferLike>): void;
64
89
  dispose(): void;
65
90
  }
91
+ declare function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean;
66
92
 
67
93
  type KvStoreItem = {
68
94
  key: string;
@@ -144,6 +170,10 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
144
170
  refresh: (parameters?: readonly unknown[]) => void;
145
171
  subscribe: (onchange: () => void) => () => void;
146
172
  };
173
+ getSharedLiveQuery: <TResult>(query: {
174
+ sql: string;
175
+ parameters: readonly unknown[];
176
+ }) => SharedLiveQuery<TResult>;
147
177
  };
148
178
  state: {
149
179
  getState: () => WorkerState;
@@ -199,6 +229,7 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
199
229
  name: string;
200
230
  isWrite: boolean;
201
231
  }[];
232
+ getSharedLiveQueriesSnapshot: () => SharedLiveQuerySnapshot[];
202
233
  crdtTableNames: string[];
203
234
  crdtTablesConfig: CrdtTableConfig[];
204
235
  schemaVersion: number;
@@ -207,4 +238,4 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
207
238
  }>;
208
239
  type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;
209
240
 
210
- export { CrdtStorage, type CrdtStorageMutator, ExecuteParams, ExecuteResult, InternalSQLiteWrapper, type KvStoreItem, KyselyQueryFactory, Logger, QueryBuilderOutput, SQLiteDbWrapper, SQLiteReactiveDb, SQLiteTransactionWrapper, StoredValue, SyncDbSchema, type SyncedDb, TypedEvent, WorkerState, createCrdtStorageMutator, createCrdtSyncProducer, createKvStoreTableQuery, createSQLiteKvStore, createSyncedDb, dummyKysely, makeCrdtTable, xxhash };
241
+ export { CrdtStorage, type CrdtStorageMutator, ExecuteParams, ExecuteResult, InternalSQLiteWrapper, type KvStoreItem, KyselyQueryFactory, Logger, QueryBuilderOutput, SQLiteDbWrapper, SQLiteReactiveDb, SQLiteTransactionWrapper, type SharedLiveQuery, type SharedLiveQuerySnapshot, StoredValue, SyncDbSchema, type SyncedDb, TypedEvent, WorkerState, createCrdtStorageMutator, createCrdtSyncProducer, createKvStoreTableQuery, createSQLiteKvStore, createSyncedDb, dummyKysely, makeCrdtTable, parametersAreEqual, xxhash };
package/dist/index.js CHANGED
@@ -135,6 +135,7 @@ var SQLiteReactiveDb = class _SQLiteReactiveDb {
135
135
  value.finalize();
136
136
  }
137
137
  });
138
+ sharedLiveQueries = /* @__PURE__ */ new Map();
138
139
  createLiveQuery(query) {
139
140
  const fetchRows = (parameters) => {
140
141
  let statement = this.liveQueryStatements.get(query.sql);
@@ -176,6 +177,105 @@ var SQLiteReactiveDb = class _SQLiteReactiveDb {
176
177
  };
177
178
  return { getRows, refresh, subscribe };
178
179
  }
180
+ getSharedLiveQuery(query) {
181
+ const existingEntry = this.sharedLiveQueries.get(query.sql)?.find((entry2) => parametersAreEqual(entry2.parameters, query.parameters));
182
+ if (existingEntry) {
183
+ if (existingEntry.listeners.size === 0) {
184
+ this.scheduleSharedLiveQueryCleanup(existingEntry);
185
+ }
186
+ return existingEntry;
187
+ }
188
+ const liveQuery = this.createLiveQuery(query);
189
+ let hasDetachedFromLiveQuery = false;
190
+ const entry = {
191
+ sql: query.sql,
192
+ parameters: query.parameters,
193
+ listeners: /* @__PURE__ */ new Set(),
194
+ unsubscribeFromLiveQuery: null,
195
+ cleanupTimeout: null,
196
+ getRows: () => liveQuery.getRows(),
197
+ refresh: () => {
198
+ liveQuery.refresh();
199
+ },
200
+ getSubscriberCount: () => entry.listeners.size,
201
+ subscribe: (onchange) => {
202
+ this.cancelSharedLiveQueryCleanup(entry);
203
+ this.registerSharedLiveQueryEntry(entry);
204
+ entry.listeners.add(onchange);
205
+ if (!entry.unsubscribeFromLiveQuery) {
206
+ entry.unsubscribeFromLiveQuery = liveQuery.subscribe(() => {
207
+ for (const listener of entry.listeners) {
208
+ listener();
209
+ }
210
+ });
211
+ if (hasDetachedFromLiveQuery) {
212
+ hasDetachedFromLiveQuery = false;
213
+ liveQuery.refresh();
214
+ }
215
+ }
216
+ return () => {
217
+ entry.listeners.delete(onchange);
218
+ if (entry.listeners.size === 0) {
219
+ entry.unsubscribeFromLiveQuery?.();
220
+ entry.unsubscribeFromLiveQuery = null;
221
+ hasDetachedFromLiveQuery = true;
222
+ this.scheduleSharedLiveQueryCleanup(entry);
223
+ }
224
+ };
225
+ }
226
+ };
227
+ this.registerSharedLiveQueryEntry(entry);
228
+ this.scheduleSharedLiveQueryCleanup(entry);
229
+ return entry;
230
+ }
231
+ registerSharedLiveQueryEntry(entry) {
232
+ const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql) ?? [];
233
+ if (!matchingSqlEntries.includes(entry)) {
234
+ matchingSqlEntries.push(entry);
235
+ this.sharedLiveQueries.set(entry.sql, matchingSqlEntries);
236
+ }
237
+ }
238
+ getSharedLiveQueriesSnapshot() {
239
+ const snapshot = [];
240
+ for (const entries of this.sharedLiveQueries.values()) {
241
+ for (const entry of entries) {
242
+ snapshot.push({
243
+ sql: entry.sql,
244
+ parameters: entry.parameters,
245
+ subscriberCount: entry.listeners.size
246
+ });
247
+ }
248
+ }
249
+ return snapshot;
250
+ }
251
+ scheduleSharedLiveQueryCleanup(entry) {
252
+ this.cancelSharedLiveQueryCleanup(entry);
253
+ entry.cleanupTimeout = setTimeout(() => {
254
+ entry.cleanupTimeout = null;
255
+ this.releaseSharedLiveQuery(entry);
256
+ }, 0);
257
+ }
258
+ cancelSharedLiveQueryCleanup(entry) {
259
+ if (entry.cleanupTimeout) {
260
+ clearTimeout(entry.cleanupTimeout);
261
+ entry.cleanupTimeout = null;
262
+ }
263
+ }
264
+ releaseSharedLiveQuery(entry) {
265
+ if (entry.listeners.size > 0 || entry.unsubscribeFromLiveQuery) {
266
+ return;
267
+ }
268
+ const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql);
269
+ if (!matchingSqlEntries) {
270
+ return;
271
+ }
272
+ const nextEntries = matchingSqlEntries.filter((candidate) => candidate !== entry);
273
+ if (nextEntries.length > 0) {
274
+ this.sharedLiveQueries.set(entry.sql, nextEntries);
275
+ } else {
276
+ this.sharedLiveQueries.delete(entry.sql);
277
+ }
278
+ }
179
279
  subscribeToQueryChanges(params) {
180
280
  const { sql, onDataChange } = params;
181
281
  const tables = this.getTablesUsed(sql);
@@ -309,6 +409,15 @@ var SQLiteReactiveDb = class _SQLiteReactiveDb {
309
409
  this.notifyTableSubscribers();
310
410
  }
311
411
  dispose() {
412
+ for (const entries of this.sharedLiveQueries.values()) {
413
+ for (const entry of entries) {
414
+ this.cancelSharedLiveQueryCleanup(entry);
415
+ entry.unsubscribeFromLiveQuery?.();
416
+ entry.unsubscribeFromLiveQuery = null;
417
+ entry.listeners.clear();
418
+ }
419
+ }
420
+ this.sharedLiveQueries.clear();
312
421
  this.liveQueryStatements.clear();
313
422
  if (this.tablesUsedStatement) {
314
423
  this.tablesUsedStatement.finalize();
@@ -337,6 +446,17 @@ function createDebouncedCallback(callback, delay) {
337
446
  timeout = setTimeout(effect, delay);
338
447
  };
339
448
  }
449
+ function parametersAreEqual(a, b) {
450
+ if (a === b) return true;
451
+ if (!a || !b) return false;
452
+ if (a.length !== b.length) return false;
453
+ for (let i = 0; i < a.length; i++) {
454
+ if (!Object.is(a[i], b[i])) {
455
+ return false;
456
+ }
457
+ }
458
+ return true;
459
+ }
340
460
 
341
461
  // src/sqlite-crdt/crdt-schema.ts
342
462
  function createSyncDbSchema({ migrations }) {
@@ -936,7 +1056,8 @@ async function createSyncedDb(options) {
936
1056
  execute: reactiveDb.db.execute.bind(reactiveDb.db),
937
1057
  executeKysely: reactiveDb.db.executeKysely.bind(reactiveDb.db),
938
1058
  executeTransaction: reactiveDb.db.executeTransaction.bind(reactiveDb.db),
939
- createLiveQuery: reactiveDb.createLiveQuery.bind(reactiveDb)
1059
+ createLiveQuery: reactiveDb.createLiveQuery.bind(reactiveDb),
1060
+ getSharedLiveQuery: reactiveDb.getSharedLiveQuery.bind(reactiveDb)
940
1061
  },
941
1062
  state: {
942
1063
  getState: workerClient.getState.bind(workerClient),
@@ -967,6 +1088,7 @@ async function createSyncedDb(options) {
967
1088
  _internal: {
968
1089
  executeAsync: workerClient.execute.bind(workerClient),
969
1090
  getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),
1091
+ getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),
970
1092
  crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),
971
1093
  crdtTablesConfig: options.syncDbSchema.tablesConfig,
972
1094
  schemaVersion: workerClientSnapshot.schemaVersion,
@@ -1016,6 +1138,7 @@ export {
1016
1138
  isNoOpCrdtEventPayload,
1017
1139
  jsonSafeParse,
1018
1140
  makeCrdtTable,
1141
+ parametersAreEqual,
1019
1142
  quoteId,
1020
1143
  runSystemMigrations,
1021
1144
  serializeHLC,
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\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 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 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 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","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 },\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 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":["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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlite-sync/core",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "SQLite synchronization library with CRDT support",
5
5
  "type": "module",
6
6
  "license": "MIT",