@sqlite-sync/core 0.13.3 → 0.14.0
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/{crdt-sync-producer-t2jHxO38.js → crdt-sync-producer-BQkuzCBM.js} +2 -2
- package/dist/{crdt-sync-producer-t2jHxO38.js.map → crdt-sync-producer-BQkuzCBM.js.map} +1 -1
- package/dist/{index-B3s_6aG6.d.ts → index-BgkTUdlX.d.ts} +10 -4
- package/dist/{index.common-Dp8CNMk4.js → index.common-DIN0mZxR.js} +4 -4
- package/dist/{index.common-Dp8CNMk4.js.map → index.common-DIN0mZxR.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/index.native.d.ts +1 -1
- package/dist/index.native.js +5 -5
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +2 -2
- package/dist/local.d.ts +2 -2
- package/dist/local.js +4 -4
- package/dist/{make-crdt-table-DYCXOYB7.js → make-crdt-table-Cu8WhRBk.js} +3 -3
- package/dist/{make-crdt-table-DYCXOYB7.js.map → make-crdt-table-Cu8WhRBk.js.map} +1 -1
- package/dist/{reset-state-Bz1sfbf3.js → reset-state-DAPyJglN.js} +2 -2
- package/dist/{reset-state-Bz1sfbf3.js.map → reset-state-DAPyJglN.js.map} +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/{sqlite-reactive-db-BwY3FoIy.js → sqlite-reactive-db-DLTvpGzO.js} +92 -18
- package/dist/sqlite-reactive-db-DLTvpGzO.js.map +1 -0
- package/dist/{system-schema-uHQdQTCk.js → system-schema-B8hbFl7o.js} +6 -4
- package/dist/system-schema-B8hbFl7o.js.map +1 -0
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +3 -3
- package/dist/{ws-remote-source-Dgd9dmMl.d.ts → ws-remote-source-BJFkwEyQ.d.ts} +2 -2
- package/package.json +1 -1
- package/dist/sqlite-reactive-db-BwY3FoIy.js.map +0 -1
- package/dist/system-schema-uHQdQTCk.js.map +0 -1
|
@@ -1,5 +1,63 @@
|
|
|
1
|
-
import { g as SQLiteDbWrapper, v as BoundMap, y as startPerformanceLogger } from "./system-schema-
|
|
1
|
+
import { g as SQLiteDbWrapper, v as BoundMap, y as startPerformanceLogger } from "./system-schema-B8hbFl7o.js";
|
|
2
2
|
import { s as createTypedEventTarget } from "./crdt-table-schema-D6Yf61Ex.js";
|
|
3
|
+
//#region src/memory-db/reconcile-rows.ts
|
|
4
|
+
function reconcileRows(previous, next) {
|
|
5
|
+
if (!previous || !sameColumns(previous.raw.columns, next.columns)) return next.rows.map((values) => buildRow(next.columns, values));
|
|
6
|
+
const columns = next.columns;
|
|
7
|
+
const columnCount = columns.length;
|
|
8
|
+
const prevRaw = previous.raw.rows;
|
|
9
|
+
const prevRows = previous.rows;
|
|
10
|
+
const nextRaw = next.rows;
|
|
11
|
+
const idIndex = columns.indexOf("id");
|
|
12
|
+
const result = new Array(nextRaw.length);
|
|
13
|
+
let allInPlace = prevRaw.length === nextRaw.length;
|
|
14
|
+
let byId = null;
|
|
15
|
+
for (let r = 0; r < nextRaw.length; r++) {
|
|
16
|
+
const values = nextRaw[r];
|
|
17
|
+
if (r < prevRaw.length && valuesEqual(prevRaw[r], values, columnCount)) {
|
|
18
|
+
result[r] = prevRows[r];
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
allInPlace = false;
|
|
22
|
+
if (idIndex !== -1) {
|
|
23
|
+
if (!byId) {
|
|
24
|
+
byId = /* @__PURE__ */ new Map();
|
|
25
|
+
for (let p = prevRaw.length - 1; p >= 0; p--) byId.set(prevRaw[p][idIndex], p);
|
|
26
|
+
}
|
|
27
|
+
const candidate = byId.get(values[idIndex]);
|
|
28
|
+
if (candidate !== void 0 && valuesEqual(prevRaw[candidate], values, columnCount)) {
|
|
29
|
+
result[r] = prevRows[candidate];
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
result[r] = buildRow(columns, values);
|
|
34
|
+
}
|
|
35
|
+
return allInPlace ? prevRows : result;
|
|
36
|
+
}
|
|
37
|
+
function buildRow(columns, values) {
|
|
38
|
+
const row = {};
|
|
39
|
+
for (let c = 0; c < columns.length; c++) row[columns[c]] = values[c];
|
|
40
|
+
return row;
|
|
41
|
+
}
|
|
42
|
+
function sameColumns(a, b) {
|
|
43
|
+
return a.length === b.length && a.every((column, i) => column === b[i]);
|
|
44
|
+
}
|
|
45
|
+
function valuesEqual(a, b, count) {
|
|
46
|
+
for (let c = 0; c < count; c++) {
|
|
47
|
+
const x = a[c];
|
|
48
|
+
const y = b[c];
|
|
49
|
+
if (Object.is(x, y)) continue;
|
|
50
|
+
if (x instanceof Uint8Array && y instanceof Uint8Array && bytesEqual(x, y)) continue;
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
function bytesEqual(a, b) {
|
|
56
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
57
|
+
for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
3
61
|
//#region src/memory-db/sqlite-reactive-db.ts
|
|
4
62
|
var SQLiteReactiveDb = class SQLiteReactiveDb {
|
|
5
63
|
db;
|
|
@@ -10,6 +68,8 @@ var SQLiteReactiveDb = class SQLiteReactiveDb {
|
|
|
10
68
|
isDisposed = false;
|
|
11
69
|
mutationVersion = 0;
|
|
12
70
|
tableMutationVersions = /* @__PURE__ */ new Map();
|
|
71
|
+
/** Runs inside the commit hook after a transaction that changed rows, so it must not use the database. */
|
|
72
|
+
afterCommit = null;
|
|
13
73
|
constructor(opts) {
|
|
14
74
|
this.driver = opts.driver;
|
|
15
75
|
this.logger = opts.logger;
|
|
@@ -50,18 +110,29 @@ var SQLiteReactiveDb = class SQLiteReactiveDb {
|
|
|
50
110
|
this.liveQueryStatements.set(query.sql, statement);
|
|
51
111
|
}
|
|
52
112
|
rowsVersion = this.mutationVersion;
|
|
53
|
-
return statement.
|
|
113
|
+
return statement.executeRaw(parameters);
|
|
54
114
|
};
|
|
115
|
+
let raw = null;
|
|
55
116
|
let rows = null;
|
|
56
117
|
const getRows = () => {
|
|
57
|
-
if (!rows)
|
|
118
|
+
if (!rows) {
|
|
119
|
+
raw = fetchRows(query.parameters);
|
|
120
|
+
rows = reconcileRows(null, raw);
|
|
121
|
+
}
|
|
58
122
|
return rows;
|
|
59
123
|
};
|
|
60
124
|
let subscriber = null;
|
|
61
125
|
let lastParameters = query.parameters;
|
|
62
126
|
const refresh = (parameters) => {
|
|
63
127
|
if (parameters) lastParameters = parameters;
|
|
64
|
-
|
|
128
|
+
const nextRaw = fetchRows(lastParameters);
|
|
129
|
+
const nextRows = reconcileRows(raw && rows ? {
|
|
130
|
+
raw,
|
|
131
|
+
rows
|
|
132
|
+
} : null, nextRaw);
|
|
133
|
+
raw = nextRaw;
|
|
134
|
+
if (nextRows === rows) return;
|
|
135
|
+
rows = nextRows;
|
|
65
136
|
subscriber?.();
|
|
66
137
|
};
|
|
67
138
|
const subscribe = (onchange) => {
|
|
@@ -223,13 +294,12 @@ var SQLiteReactiveDb = class SQLiteReactiveDb {
|
|
|
223
294
|
onRollback: () => {
|
|
224
295
|
if (this.isDisposed || updateQueue.size === 0) return;
|
|
225
296
|
updateQueue.clear();
|
|
226
|
-
this.eventTarget.dispatchEvent("transaction-rolled-back", void 0);
|
|
227
297
|
},
|
|
228
298
|
onCommit: () => {
|
|
229
299
|
if (this.isDisposed || updateQueue.size === 0) return;
|
|
230
300
|
const tables = updateQueue;
|
|
231
301
|
updateQueue = /* @__PURE__ */ new Set();
|
|
232
|
-
this.
|
|
302
|
+
this.afterCommit?.();
|
|
233
303
|
queueMicrotask(() => {
|
|
234
304
|
if (!this.isDisposed) this.notifyTableSubscribers(tables);
|
|
235
305
|
});
|
|
@@ -267,20 +337,24 @@ var SQLiteReactiveDb = class SQLiteReactiveDb {
|
|
|
267
337
|
};
|
|
268
338
|
function createDebouncedCallback(callback, delay) {
|
|
269
339
|
let timeout = null;
|
|
270
|
-
let
|
|
340
|
+
let pendingArgs = null;
|
|
341
|
+
const run = (args) => {
|
|
342
|
+
timeout = setTimeout(() => {
|
|
343
|
+
timeout = null;
|
|
344
|
+
if (pendingArgs) {
|
|
345
|
+
const args = pendingArgs;
|
|
346
|
+
pendingArgs = null;
|
|
347
|
+
run(args);
|
|
348
|
+
}
|
|
349
|
+
}, delay);
|
|
350
|
+
callback(...args);
|
|
351
|
+
};
|
|
271
352
|
return (...args) => {
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
shouldCallWithoutDelay = false;
|
|
353
|
+
if (timeout) {
|
|
354
|
+
pendingArgs = args;
|
|
275
355
|
return;
|
|
276
356
|
}
|
|
277
|
-
|
|
278
|
-
timeout = null;
|
|
279
|
-
shouldCallWithoutDelay = true;
|
|
280
|
-
return callback(...args);
|
|
281
|
-
};
|
|
282
|
-
if (timeout) clearTimeout(timeout);
|
|
283
|
-
timeout = setTimeout(effect, delay);
|
|
357
|
+
run(args);
|
|
284
358
|
};
|
|
285
359
|
}
|
|
286
360
|
function parametersAreEqual(a, b) {
|
|
@@ -293,4 +367,4 @@ function parametersAreEqual(a, b) {
|
|
|
293
367
|
//#endregion
|
|
294
368
|
export { parametersAreEqual as n, SQLiteReactiveDb as t };
|
|
295
369
|
|
|
296
|
-
//# sourceMappingURL=sqlite-reactive-db-
|
|
370
|
+
//# sourceMappingURL=sqlite-reactive-db-DLTvpGzO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-reactive-db-DLTvpGzO.js","names":[],"sources":["../src/memory-db/reconcile-rows.ts","../src/memory-db/sqlite-reactive-db.ts"],"sourcesContent":["// Structural sharing for live queries: compares fresh raw driver rows with the previous ones (by\n// position, then by `id`) and reuses the previous object when all values are equal, so matching\n// only affects the hit rate, never correctness. Returns the previous array if nothing changed.\n\nimport type { SqliteDriverRows, SqliteDriverValue } from \"../sqlite-driver\";\n\nexport type ReconciledRows<T> = { raw: SqliteDriverRows; rows: T[] };\n\nexport function reconcileRows<T>(previous: ReconciledRows<T> | null, next: SqliteDriverRows): T[] {\n if (!previous || !sameColumns(previous.raw.columns, next.columns)) {\n return next.rows.map((values) => buildRow<T>(next.columns, values));\n }\n\n const columns = next.columns;\n const columnCount = columns.length;\n const prevRaw = previous.raw.rows;\n const prevRows = previous.rows;\n const nextRaw = next.rows;\n const idIndex = columns.indexOf(\"id\");\n\n const result = new Array<T>(nextRaw.length);\n let allInPlace = prevRaw.length === nextRaw.length;\n let byId: Map<SqliteDriverValue, number> | null = null;\n\n for (let r = 0; r < nextRaw.length; r++) {\n const values = nextRaw[r];\n if (r < prevRaw.length && valuesEqual(prevRaw[r], values, columnCount)) {\n result[r] = prevRows[r];\n continue;\n }\n allInPlace = false;\n\n if (idIndex !== -1) {\n if (!byId) {\n byId = new Map();\n // Backwards, so the first row with a duplicate id wins.\n for (let p = prevRaw.length - 1; p >= 0; p--) {\n byId.set(prevRaw[p][idIndex], p);\n }\n }\n const candidate = byId.get(values[idIndex]);\n if (candidate !== undefined && valuesEqual(prevRaw[candidate], values, columnCount)) {\n result[r] = prevRows[candidate];\n continue;\n }\n }\n\n result[r] = buildRow<T>(columns, values);\n }\n\n return allInPlace ? prevRows : result;\n}\n\nfunction buildRow<T>(columns: string[], values: SqliteDriverValue[]): T {\n const row: Record<string, unknown> = {};\n for (let c = 0; c < columns.length; c++) {\n row[columns[c]] = values[c];\n }\n return row as T;\n}\n\nfunction sameColumns(a: string[], b: string[]) {\n return a.length === b.length && a.every((column, i) => column === b[i]);\n}\n\nfunction valuesEqual(a: SqliteDriverValue[], b: SqliteDriverValue[], count: number) {\n for (let c = 0; c < count; c++) {\n const x = a[c];\n const y = b[c];\n if (Object.is(x, y)) continue;\n if (x instanceof Uint8Array && y instanceof Uint8Array && bytesEqual(x, y)) continue;\n return false;\n }\n return true;\n}\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array) {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n","import { BoundMap } from \"../bound-map\";\nimport { type Logger, startPerformanceLogger } from \"../logger\";\nimport { type PreparedStatement, SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { SqliteDriver, SqliteDriverRows } from \"../sqlite-driver\";\nimport { createTypedEventTarget, type TypedEvent } from \"../utils\";\nimport { reconcileRows } from \"./reconcile-rows\";\n\ntype TableName<Database> = keyof Database extends string ? keyof Database : never;\n\nexport type SQLiteReactiveDbOptions = {\n driver: SqliteDriver;\n snapshot?: Uint8Array<ArrayBufferLike>;\n logger: Logger;\n loggerPrefix?: string;\n};\n\ntype EventsMap = {\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 class SQLiteReactiveDb<Database> {\n readonly db: SQLiteDbWrapper<Database>;\n private readonly driver: SqliteDriver;\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 private isDisposed = false;\n private mutationVersion = 0;\n private tableMutationVersions = new Map<string, number>();\n /** Runs inside the commit hook after a transaction that changed rows, so it must not use the database. */\n afterCommit: (() => void) | null = null;\n\n private constructor(opts: SQLiteReactiveDbOptions) {\n this.driver = opts.driver;\n this.logger = opts.logger;\n\n this.db = new SQLiteDbWrapper({\n driver: opts.driver,\n logger: this.logger,\n loggerPrefix: opts.loggerPrefix ?? \"memory\",\n });\n }\n\n static create<Database>(opts: SQLiteReactiveDbOptions) {\n const perf = startPerformanceLogger(opts.logger, \"system\");\n\n const db = new SQLiteReactiveDb<Database>(opts);\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 /**\n * When false, table mutation versions only advance after the writing statement\n * returns, so they cannot tell whether that statement wrote to a table.\n */\n get hasSynchronousHooks() {\n return this.driver.synchronousHooks;\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 let rowsVersion = 0;\n\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 rowsVersion = this.mutationVersion;\n return statement.executeRaw(parameters as any);\n };\n\n let raw: SqliteDriverRows | null = null;\n let rows: TResult[] | null = null;\n\n const getRows = () => {\n if (!rows) {\n raw = fetchRows(query.parameters);\n rows = reconcileRows<TResult>(null, raw);\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 const nextRaw = fetchRows(lastParameters);\n const nextRows = reconcileRows<TResult>(raw && rows ? { raw, rows } : null, nextRaw);\n raw = nextRaw;\n // Unchanged result: keep the same array and don't notify, so subscribers skip the render.\n if (nextRows === rows) {\n return;\n }\n rows = nextRows;\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 // Tables may have changed while nothing was subscribed, e.g. between React's render and commit.\n if (rows && this.mutationVersion !== rowsVersion) {\n 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 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\n return () => {\n entry.listeners.delete(onchange);\n\n if (entry.listeners.size === 0) {\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\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 getTableMutationVersion(table: string) {\n return this.tableMutationVersions.get(table) ?? 0;\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 // Asynchronous drivers can deliver hooks that were queued before dispose.\n this.driver.setHooks({\n onUpdate: (table) => {\n if (this.isDisposed) {\n return;\n }\n updateQueue.add(table);\n this.tableMutationVersions.set(table, ++this.mutationVersion);\n },\n onRollback: () => {\n if (this.isDisposed || updateQueue.size === 0) {\n return;\n }\n\n updateQueue.clear();\n },\n onCommit: () => {\n if (this.isDisposed || updateQueue.size === 0) {\n return;\n }\n\n const tables = updateQueue;\n updateQueue = new Set<string>();\n this.afterCommit?.();\n\n queueMicrotask(() => {\n if (!this.isDisposed) {\n this.notifyTableSubscribers(tables);\n }\n });\n },\n });\n }\n\n createSnapshot() {\n const perf = startPerformanceLogger(this.logger);\n const snapshot = this.db.createSnapshot();\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.mutationVersion++;\n this.notifyTableSubscribers();\n }\n\n dispose() {\n this.isDisposed = true;\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.driver.setHooks(null);\n this.db.close();\n }\n}\n\n// Leading + trailing throttle: a call after an idle window runs immediately, and calls\n// within the window collapse into one trailing call that opens the next window.\nfunction createDebouncedCallback<TArgs extends unknown[]>(callback: (...args: TArgs) => void, delay: number) {\n let timeout: unknown | null = null;\n let pendingArgs: TArgs | null = null;\n\n const run = (args: TArgs) => {\n timeout = setTimeout(() => {\n timeout = null;\n if (pendingArgs) {\n const args = pendingArgs;\n pendingArgs = null;\n run(args);\n }\n }, delay);\n callback(...args);\n };\n\n return (...args: TArgs) => {\n if (timeout) {\n pendingArgs = args;\n return;\n }\n run(args);\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"],"mappings":";;;AAQA,SAAgB,cAAiB,UAAoC,MAA6B;CAChG,IAAI,CAAC,YAAY,CAAC,YAAY,SAAS,IAAI,SAAS,KAAK,OAAO,GAC9D,OAAO,KAAK,KAAK,KAAK,WAAW,SAAY,KAAK,SAAS,MAAM,CAAC;CAGpE,MAAM,UAAU,KAAK;CACrB,MAAM,cAAc,QAAQ;CAC5B,MAAM,UAAU,SAAS,IAAI;CAC7B,MAAM,WAAW,SAAS;CAC1B,MAAM,UAAU,KAAK;CACrB,MAAM,UAAU,QAAQ,QAAQ,IAAI;CAEpC,MAAM,SAAS,IAAI,MAAS,QAAQ,MAAM;CAC1C,IAAI,aAAa,QAAQ,WAAW,QAAQ;CAC5C,IAAI,OAA8C;CAElD,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ;EACvB,IAAI,IAAI,QAAQ,UAAU,YAAY,QAAQ,IAAI,QAAQ,WAAW,GAAG;GACtE,OAAO,KAAK,SAAS;GACrB;EACF;EACA,aAAa;EAEb,IAAI,YAAY,IAAI;GAClB,IAAI,CAAC,MAAM;IACT,uBAAO,IAAI,IAAI;IAEf,KAAK,IAAI,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,KACvC,KAAK,IAAI,QAAQ,EAAE,CAAC,UAAU,CAAC;GAEnC;GACA,MAAM,YAAY,KAAK,IAAI,OAAO,QAAQ;GAC1C,IAAI,cAAc,KAAA,KAAa,YAAY,QAAQ,YAAY,QAAQ,WAAW,GAAG;IACnF,OAAO,KAAK,SAAS;IACrB;GACF;EACF;EAEA,OAAO,KAAK,SAAY,SAAS,MAAM;CACzC;CAEA,OAAO,aAAa,WAAW;AACjC;AAEA,SAAS,SAAY,SAAmB,QAAgC;CACtE,MAAM,MAA+B,CAAC;CACtC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAClC,IAAI,QAAQ,MAAM,OAAO;CAE3B,OAAO;AACT;AAEA,SAAS,YAAY,GAAa,GAAa;CAC7C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,QAAQ,MAAM,WAAW,EAAE,EAAE;AACxE;AAEA,SAAS,YAAY,GAAwB,GAAwB,OAAe;CAClF,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;EAC9B,MAAM,IAAI,EAAE;EACZ,MAAM,IAAI,EAAE;EACZ,IAAI,OAAO,GAAG,GAAG,CAAC,GAAG;EACrB,IAAI,aAAa,cAAc,aAAa,cAAc,WAAW,GAAG,CAAC,GAAG;EAC5E,OAAO;CACT;CACA,OAAO;AACT;AAEA,SAAS,WAAW,GAAe,GAAe;CAChD,IAAI,EAAE,eAAe,EAAE,YAAY,OAAO;CAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,YAAY,KAChC,IAAI,EAAE,OAAO,EAAE,IAAI,OAAO;CAE5B,OAAO;AACT;;;ACtCA,IAAa,mBAAb,MAAa,iBAA2B;CACtC;CACA;CAEA;CAEA,sBAAsG;CAEtG,cAAsB,uBAAkC;CACxD,aAAqB;CACrB,kBAA0B;CAC1B,wCAAgC,IAAI,IAAoB;;CAExD,cAAmC;CAEnC,YAAoB,MAA+B;EACjD,KAAK,SAAS,KAAK;EACnB,KAAK,SAAS,KAAK;EAEnB,KAAK,KAAK,IAAI,gBAAgB;GAC5B,QAAQ,KAAK;GACb,QAAQ,KAAK;GACb,cAAc,KAAK,gBAAgB;EACrC,CAAC;CACH;CAEA,OAAO,OAAiB,MAA+B;EACrD,MAAM,OAAO,uBAAuB,KAAK,QAAQ,QAAQ;EAEzD,MAAM,KAAK,IAAI,iBAA2B,IAAI;EAE9C,IAAI,KAAK,UACP,GAAG,YAAY,KAAK,QAAQ;EAE9B,GAAG,gBAAgB;EAEnB,KAAK,OAAO,wBAAwB,WAAW,QAAQ;EAEvD,OAAO;CACT;;;;;CAMA,IAAI,sBAAsB;EACxB,OAAO,KAAK,OAAO;CACrB;CAEA,sBAA8B,IAAI,SAAoD;EACpF,SAAS;EACT,SAAS,GAAG,OAAO;GACjB,MAAM,SAAS;EACjB;CACF,CAAC;CAED,oCAA4B,IAAI,IAA6C;CAE7E,gBAAyB,OAAwD;EAC/E,IAAI,cAAc;EAElB,MAAM,aAAa,eAAmC;GACpD,IAAI,YAAY,KAAK,oBAAoB,IAAI,MAAM,GAAG;GACtD,IAAI,CAAC,WAAW;IACd,YAAY,KAAK,GAAG,QAAoB,MAAM,GAAG;IACjD,KAAK,oBAAoB,IAAI,MAAM,KAAK,SAAS;GACnD;GACA,cAAc,KAAK;GACnB,OAAO,UAAU,WAAW,UAAiB;EAC/C;EAEA,IAAI,MAA+B;EACnC,IAAI,OAAyB;EAE7B,MAAM,gBAAgB;GACpB,IAAI,CAAC,MAAM;IACT,MAAM,UAAU,MAAM,UAAU;IAChC,OAAO,cAAuB,MAAM,GAAG;GACzC;GACA,OAAO;EACT;EAEA,IAAI,aAAkC;EAEtC,IAAI,iBAAqC,MAAM;EAC/C,MAAM,WAAW,eAAoC;GACnD,IAAI,YACF,iBAAiB;GAEnB,MAAM,UAAU,UAAU,cAAc;GACxC,MAAM,WAAW,cAAuB,OAAO,OAAO;IAAE;IAAK;GAAK,IAAI,MAAM,OAAO;GACnF,MAAM;GAEN,IAAI,aAAa,MACf;GAEF,OAAO;GACP,aAAa;EACf;EAEA,MAAM,aAAa,aAAyB;GAC1C,IAAI,YACF,MAAM,IAAI,MAAM,2BAA2B;GAG7C,aAAa;GACb,MAAM,eAAe,KAAK,wBAAwB;IAChD,KAAK,MAAM;IACX,cAAc;GAChB,CAAC;GAGD,IAAI,QAAQ,KAAK,oBAAoB,aACnC,QAAQ;GAGV,aAAa;IACX,aAAa,YAAY;IACzB,aAAa;GACf;EACF;EAEA,OAAO;GAAE;GAAS;GAAS;EAAU;CACvC;CAEA,mBAA4B,OAAwD;EAClF,MAAM,gBAAgB,KAAK,kBACxB,IAAI,MAAM,GAAG,CAAC,EACb,MAAM,UAAU,mBAAmB,MAAM,YAAY,MAAM,UAAU,CAAC;EAC1E,IAAI,eAAe;GACjB,IAAI,cAAc,UAAU,SAAS,GACnC,KAAK,+BAA+B,aAAa;GAEnD,OAAO;EACT;EAEA,MAAM,YAAY,KAAK,gBAAyB,KAAK;EACrD,MAAM,QAAuC;GAC3C,KAAK,MAAM;GACX,YAAY,MAAM;GAClB,2BAAW,IAAI,IAAI;GACnB,0BAA0B;GAC1B,gBAAgB;GAChB,eAAe,UAAU,QAAQ;GACjC,eAAe;IACb,UAAU,QAAQ;GACpB;GACA,0BAA0B,MAAM,UAAU;GAC1C,YAAY,aAAa;IACvB,KAAK,6BAA6B,KAAK;IACvC,KAAK,6BAA6B,KAAsC;IACxE,MAAM,UAAU,IAAI,QAAQ;IAE5B,IAAI,CAAC,MAAM,0BACT,MAAM,2BAA2B,UAAU,gBAAgB;KACzD,KAAK,MAAM,YAAY,MAAM,WAC3B,SAAS;IAEb,CAAC;IAGH,aAAa;KACX,MAAM,UAAU,OAAO,QAAQ;KAE/B,IAAI,MAAM,UAAU,SAAS,GAAG;MAC9B,MAAM,2BAA2B;MACjC,MAAM,2BAA2B;MACjC,KAAK,+BAA+B,KAAK;KAC3C;IACF;GACF;EACF;EAEA,KAAK,6BAA6B,KAAsC;EAGxE,KAAK,+BAA+B,KAAsC;EAE1E,OAAO;CACT;CAEA,6BAAqC,OAAsC;EACzE,MAAM,qBAAqB,KAAK,kBAAkB,IAAI,MAAM,GAAG,KAAK,CAAC;EACrE,IAAI,CAAC,mBAAmB,SAAS,KAAK,GAAG;GACvC,mBAAmB,KAAK,KAAK;GAC7B,KAAK,kBAAkB,IAAI,MAAM,KAAK,kBAAkB;EAC1D;CACF;CAEA,+BAA0D;EACxD,MAAM,WAAsC,CAAC;EAC7C,KAAK,MAAM,WAAW,KAAK,kBAAkB,OAAO,GAClD,KAAK,MAAM,SAAS,SAClB,SAAS,KAAK;GACZ,KAAK,MAAM;GACX,YAAY,MAAM;GAClB,iBAAiB,MAAM,UAAU;EACnC,CAAC;EAGL,OAAO;CACT;CAEA,+BAAuC,OAAsC;EAC3E,KAAK,6BAA6B,KAAK;EACvC,MAAM,iBAAiB,iBAAiB;GACtC,MAAM,iBAAiB;GACvB,KAAK,uBAAuB,KAAK;EACnC,GAAG,CAAC;CACN;CAEA,6BAAqC,OAAsC;EACzE,IAAI,MAAM,gBAAgB;GACxB,aAAa,MAAM,cAAc;GACjC,MAAM,iBAAiB;EACzB;CACF;CAEA,uBAA+B,OAAsC;EACnE,IAAI,MAAM,UAAU,OAAO,KAAK,MAAM,0BACpC;EAGF,MAAM,qBAAqB,KAAK,kBAAkB,IAAI,MAAM,GAAG;EAC/D,IAAI,CAAC,oBACH;EAGF,MAAM,cAAc,mBAAmB,QAAQ,cAAc,cAAc,KAAK;EAChF,IAAI,YAAY,SAAS,GACvB,KAAK,kBAAkB,IAAI,MAAM,KAAK,WAAW;OAEjD,KAAK,kBAAkB,OAAO,MAAM,GAAG;CAE3C;CAEA,wBAAwB,QAAmD;EACzE,MAAM,EAAE,KAAK,iBAAiB;EAE9B,MAAM,SAAS,KAAK,cAAc,GAAG;EACrC,MAAM,6BAAa,IAAI,IAAY;EACnC,KAAK,MAAM,SAAS,QAClB,IAAI,CAAC,WAAW,IAAI,MAAM,IAAI,GAC5B,WAAW,IAAI,MAAM,IAAI;OACpB,IAAI,MAAM,SACf,MAAM,IAAI,MAAM,iFAAiF;EAIrG,MAAM,mBAAmB,8BAA8B;GACrD,aAAa;EACf,GAAG,EAAE;EAEL,KAAK,MAAM,SAAS,YAClB,KAAK,YAAY,iBAAiB,SAAS,SAAS,gBAAgB;EAEtE,KAAK,YAAY,iBAAiB,qBAAqB,gBAAgB;EAEvE,OAAO,EACL,mBAAmB;GACjB,KAAK,MAAM,SAAS,YAClB,KAAK,YAAY,oBAAoB,SAAS,SAAS,gBAAgB;GAEzE,KAAK,YAAY,oBAAoB,qBAAqB,gBAAgB;EAC5E,EACF;CACF;CAEA,wBAAwB,OAAe,WAAuB;EAC5D,KAAK,YAAY,iBAAiB,SAAS,SAAS,SAAS;EAC7D,KAAK,YAAY,iBAAiB,qBAAqB,SAAS;EAChE,OAAO,EACL,mBAAmB;GACjB,KAAK,YAAY,oBAAoB,SAAS,SAAS,SAAS;GAChE,KAAK,YAAY,oBAAoB,qBAAqB,SAAS;EACrE,EACF;CACF;CAEA,cAAc,OAAe;EAC3B,IAAI,CAAC,KAAK,qBACR,KAAK,sBAAsB,KAAK,GAAG,QACjC,gJACA,EAAE,aAAa,SAAS,CAC1B;EAGF,MAAM,SAAS,KAAK,oBAAoB,QAAQ,CAAC,KAAK,CAAC;EAEvD,IAAI,OAAO,WAAW,KAAK,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,GAE9D,OAAO,KAAK,GAAG,KAAK,iBAAiB,KAAK,CAAC;EAG7C,OAAO;CACT;CAEA,iBAAyB,OAAe;EACtC,MAAM,aAAa,KAAK,GAAG,QAIxB,WAAW,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,SAAS,CAAC,CAAC,CAAC;EAEhE,MAAM,yCAAyB,IAAI,IAAY;EAC/C,KAAK,MAAM,aAAa,YACtB,IAAI,UAAU,WAAW,WAAW,UAAU,OAAO,GACnD,uBAAuB,IAAI,UAAU,EAAE;EAI3C,IAAI,uBAAuB,SAAS,GAClC,OAAO,CAAC;EAUV,OAPmB,KAAK,GAAG,QACzB,2FAA2F,MAAM,KAC/F,sBACF,CAAC,CAAC,KAAK,GAAG,EAAE,IACZ,EAAE,aAAa,SAAS,CAC1B,CAAC,CAAC;CAGJ;CAEA,iBAA4C,MAAS,UAAqD;EACxG,KAAK,YAAY,iBAAiB,MAAM,QAAQ;CAClD;CAEA,oBAA+C,MAAS,UAAqD;EAC3G,KAAK,YAAY,oBAAoB,MAAM,QAAQ;CACrD;CAEA,wBAAwB,OAAe;EACrC,OAAO,KAAK,sBAAsB,IAAI,KAAK,KAAK;CAClD;CAEA,uBAA+B,SAAuE,MAAM;EAC1G,IAAI,CAAC,QAAQ;GACX,KAAK,YAAY,cAAc,qBAAqB,KAAA,CAAS;GAC7D;EACF;EAEA,KAAK,MAAM,SAAS,QAClB,KAAK,YAAY,cAAc,SAAS,SAAS,KAAA,CAAS;CAE9D;CAEA,kBAA0B;EACxB,IAAI,8BAAc,IAAI,IAAY;EAGlC,KAAK,OAAO,SAAS;GACnB,WAAW,UAAU;IACnB,IAAI,KAAK,YACP;IAEF,YAAY,IAAI,KAAK;IACrB,KAAK,sBAAsB,IAAI,OAAO,EAAE,KAAK,eAAe;GAC9D;GACA,kBAAkB;IAChB,IAAI,KAAK,cAAc,YAAY,SAAS,GAC1C;IAGF,YAAY,MAAM;GACpB;GACA,gBAAgB;IACd,IAAI,KAAK,cAAc,YAAY,SAAS,GAC1C;IAGF,MAAM,SAAS;IACf,8BAAc,IAAI,IAAY;IAC9B,KAAK,cAAc;IAEnB,qBAAqB;KACnB,IAAI,CAAC,KAAK,YACR,KAAK,uBAAuB,MAAM;IAEtC,CAAC;GACH;EACF,CAAC;CACH;CAEA,iBAAiB;EACf,MAAM,OAAO,uBAAuB,KAAK,MAAM;EAC/C,MAAM,WAAW,KAAK,GAAG,eAAe;EACxC,KAAK,OAAO,kBAAkB,kBAAkB,SAAS,cAAc,MAAM;EAE7E,OAAO;CACT;CAEA,YAAY,UAAuC;EACjD,KAAK,GAAG,YAAY,QAAQ;EAC5B,KAAK;EACL,KAAK,uBAAuB;CAC9B;CAEA,UAAU;EACR,KAAK,aAAa;EAClB,KAAK,MAAM,WAAW,KAAK,kBAAkB,OAAO,GAClD,KAAK,MAAM,SAAS,SAAS;GAC3B,KAAK,6BAA6B,KAAK;GACvC,MAAM,2BAA2B;GACjC,MAAM,2BAA2B;GACjC,MAAM,UAAU,MAAM;EACxB;EAEF,KAAK,kBAAkB,MAAM;EAC7B,KAAK,oBAAoB,MAAM;EAC/B,IAAI,KAAK,qBAAqB;GAC5B,KAAK,oBAAoB,SAAS;GAClC,KAAK,sBAAsB;EAC7B;EACA,KAAK,OAAO,SAAS,IAAI;EACzB,KAAK,GAAG,MAAM;CAChB;AACF;AAIA,SAAS,wBAAiD,UAAoC,OAAe;CAC3G,IAAI,UAA0B;CAC9B,IAAI,cAA4B;CAEhC,MAAM,OAAO,SAAgB;EAC3B,UAAU,iBAAiB;GACzB,UAAU;GACV,IAAI,aAAa;IACf,MAAM,OAAO;IACb,cAAc;IACd,IAAI,IAAI;GACV;EACF,GAAG,KAAK;EACR,SAAS,GAAG,IAAI;CAClB;CAEA,QAAQ,GAAG,SAAgB;EACzB,IAAI,SAAS;GACX,cAAc;GACd;EACF;EACA,IAAI,IAAI;CACV;AACF;AAEA,SAAgB,mBAAmB,GAAmC,GAA4C;CAChH,IAAI,MAAM,GAAG,OAAO;CACpB,IAAI,CAAC,KAAK,CAAC,GAAG,OAAO;CACrB,IAAI,EAAE,WAAW,EAAE,QAAQ,OAAO;CAClC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAC5B,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,EAAE,GACvB,OAAO;CAGX,OAAO;AACT"}
|
|
@@ -154,7 +154,7 @@ var SQLiteDbWrapper = class {
|
|
|
154
154
|
transaction = this.beginStatementTransaction();
|
|
155
155
|
totalChangesBefore = driver.totalChanges();
|
|
156
156
|
}
|
|
157
|
-
const rows = toRowObjects(statement.run(bind ?? []), () =>
|
|
157
|
+
const rows = toRowObjects(statement.run(bind ?? []), () => ({}));
|
|
158
158
|
statement.finalize();
|
|
159
159
|
perf.logEnd(`${this.loggerPrefix ?? ""}:query`, sql, loggerLevel);
|
|
160
160
|
if (transaction) {
|
|
@@ -262,21 +262,23 @@ var SQLiteDbWrapper = class {
|
|
|
262
262
|
const stmt = this.ensureDriver.prepare(sql);
|
|
263
263
|
perf.logEnd(`${this.loggerPrefix ?? ""}:prepare`, sql, opts?.loggerLevel);
|
|
264
264
|
let isFinalized = false;
|
|
265
|
-
const
|
|
265
|
+
const executeRaw = (params) => {
|
|
266
266
|
if (isFinalized) throw new Error("Statement is finalized");
|
|
267
267
|
const perf = startPerformanceLogger(this.logger, opts?.loggerLevel);
|
|
268
268
|
try {
|
|
269
|
-
return
|
|
269
|
+
return stmt.run(params);
|
|
270
270
|
} finally {
|
|
271
271
|
perf.logEnd(`${this.loggerPrefix ?? ""}:prepare-execute`, sql, opts?.loggerLevel);
|
|
272
272
|
}
|
|
273
273
|
};
|
|
274
|
+
const execute = (params) => toRowObjects(executeRaw(params), () => ({}));
|
|
274
275
|
const finalize = () => {
|
|
275
276
|
isFinalized = true;
|
|
276
277
|
stmt.finalize();
|
|
277
278
|
};
|
|
278
279
|
const preparedStatement = {
|
|
279
280
|
execute,
|
|
281
|
+
executeRaw,
|
|
280
282
|
finalize,
|
|
281
283
|
get isFinalized() {
|
|
282
284
|
return isFinalized;
|
|
@@ -620,4 +622,4 @@ function applyMemoryDbSchema(db) {
|
|
|
620
622
|
//#endregion
|
|
621
623
|
export { compileKyselyStatement as _, baseSystemMigrations as a, introspectDb as b, memoryDbConfig as c, STATE_HASH_KV_KEY as d, createKvStateHashStore as f, SQLiteDbWrapper as g, createStoredValue as h, applyWorkerDbSchema as i, runSystemMigrations as l, createSQLiteKvStore as m, applyLocalDbSchema as n, createSystemDbConfig as o, createKvStoreTableQuery as p, applyMemoryDbSchema as r, localDbConfig as s, LOCAL_KV_TABLE_NAME as t, workerDbConfig as u, BoundMap as v, dummyKysely as x, startPerformanceLogger as y };
|
|
622
624
|
|
|
623
|
-
//# sourceMappingURL=system-schema-
|
|
625
|
+
//# sourceMappingURL=system-schema-B8hbFl7o.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-schema-B8hbFl7o.js","names":[],"sources":["../src/dummy-kysely.ts","../src/introspection.ts","../src/logger.ts","../src/bound-map.ts","../src/sqlite-db-wrapper.ts","../src/sqlite-crdt/stored-value.ts","../src/sqlite-kv-store.ts","../src/migrations/system-schema.ts"],"sourcesContent":["import { DummyDriver, Kysely, SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from \"kysely\";\n\nexport const dummyKysely: Kysely<any> = new Kysely({\n dialect: {\n createAdapter: () => new SqliteAdapter(),\n createDriver: () => new DummyDriver(),\n createQueryCompiler: () => new SqliteQueryCompiler(),\n createIntrospector: (db) => new SqliteIntrospector(db),\n },\n});\n","import type { Kysely, QueryCreator } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SQLiteDbWrapper } from \"./sqlite-db-wrapper\";\n\ninterface SqliteSystemDatabase {\n // https://www.sqlite.org/schematab.html#alternative_names\n sqlite_master: SQliteMasterTable;\n}\n\n// https://www.sqlite.org/schematab.html#interpretation_of_the_schema_table\ninterface SQliteMasterTable {\n name: string;\n rootpage: number | null;\n sql: string;\n tbl_name: string;\n type: \"index\" | \"table\" | \"trigger\" | \"view\";\n}\n\n// https://www.sqlite.org/pragma.html#pragma_table_info\ninterface PragmaTableInfo {\n cid: number;\n dflt_value: unknown;\n name: string;\n notnull: 0 | 1;\n pk: number;\n type: string;\n}\n\nfunction tablesQuery(qb: QueryCreator<SqliteSystemDatabase> | Kysely<SqliteSystemDatabase>) {\n return qb\n .selectFrom(\"sqlite_master\")\n .where(\"type\", \"in\", [\"table\", \"view\"])\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select([\"name\", \"sql\", \"type\"])\n .orderBy(\"name\");\n}\n\nexport type TableMetadata = {\n name: string;\n isView: boolean;\n columns: ColumnMetadata[];\n};\n\nexport type DatabaseIntrospection = Record<string, TableMetadata>;\n\nexport type ColumnMetadata = {\n name: string;\n dataType: string;\n isNullable: boolean;\n isAutoIncrementing: boolean;\n hasDefaultValue: boolean;\n defaultValueSql: string | null;\n isPrimaryKey: boolean;\n comment: undefined;\n};\n\nexport function introspectDb<BaseDatabase>(_db: SQLiteDbWrapper<BaseDatabase>): DatabaseIntrospection {\n const db = _db as unknown as SQLiteDbWrapper<SqliteSystemDatabase>;\n const tables = db.executeKysely((db) => tablesQuery(db as unknown as Kysely<SqliteSystemDatabase>), {\n loggerLevel: \"system\",\n }).rows;\n\n const tablesMetadata = db.executeKysely(\n (db) =>\n db\n .with(\"table_list\", (qb) => tablesQuery(qb as unknown as Kysely<SqliteSystemDatabase>))\n .selectFrom([\"table_list as tl\", sql<PragmaTableInfo>`pragma_table_info(tl.name)`.as(\"p\")])\n .select([\"tl.name as table\", \"p.cid\", \"p.name\", \"p.type\", \"p.notnull\", \"p.dflt_value\", \"p.pk\"])\n .orderBy(\"tl.name\")\n .orderBy(\"p.cid\"),\n { loggerLevel: \"system\" },\n ).rows;\n\n const columnsByTable: Record<string, typeof tablesMetadata> = {};\n for (const row of tablesMetadata) {\n columnsByTable[row.table] ??= [];\n columnsByTable[row.table].push(row);\n }\n\n return Object.fromEntries(\n tables.map(({ name, sql, type }) => {\n // Try to find the name of the column that has `autoincrement`\n let autoIncrementCol = sql\n ?.split(/[(),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.trimStart()\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = columnsByTable[name] ?? [];\n\n // Otherwise, check for an INTEGER PRIMARY KEY\n // https://www.sqlite.org/autoinc.html\n if (!autoIncrementCol) {\n const pkCols = columns.filter((r) => r.pk > 0);\n if (pkCols.length === 1 && pkCols[0].type.toLowerCase() === \"integer\") {\n autoIncrementCol = pkCols[0].name;\n }\n }\n\n return [\n name,\n {\n name: name,\n isView: type === \"view\",\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n defaultValueSql: col.dflt_value == null ? null : String(col.dflt_value),\n isPrimaryKey: col.pk > 0,\n comment: undefined,\n })),\n },\n ];\n }),\n );\n}\n","export type LogLevel = \"info\" | \"warning\" | \"error\" | \"trace\" | \"system\";\n\nexport type Logger = (type: string, message: string, level?: LogLevel) => void;\n\nexport type PerformanceLogger = {\n restart: () => void;\n logEnd: (type: string, message: string, level?: LogLevel) => void;\n};\n\nconst noopPerformanceLogger: PerformanceLogger = {\n restart() {},\n logEnd() {},\n};\n\nexport const startPerformanceLogger = (logger: Logger | undefined, level: LogLevel = \"info\"): PerformanceLogger => {\n if (!logger || level === \"system\") {\n return noopPerformanceLogger;\n }\n\n let startTime = performance.now();\n\n return {\n restart: () => {\n startTime = performance.now();\n },\n logEnd: (type: string, message: string, logLevel: LogLevel = level) => {\n const elapsed = performance.now() - startTime;\n\n logger(type, `${elapsed.toFixed(2)}ms - ${message}`, logLevel);\n },\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 { Compilable, CompiledQuery, Kysely } from \"kysely\";\nimport { BoundMap } from \"./bound-map\";\nimport { dummyKysely } from \"./dummy-kysely\";\nimport { type DatabaseIntrospection, introspectDb } from \"./introspection\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\nimport type { SqliteDriver, SqliteDriverRows, SqliteDriverStatement, SqliteDriverValue } from \"./sqlite-driver\";\n\nexport type ExecuteParams = {\n sql: string;\n parameters: readonly unknown[];\n};\n\nexport type ExecuteResult<T> = {\n rows: T[];\n};\n\nexport type PreparedStatement<TParams extends unknown[], TResult> = {\n execute: (parameters: TParams) => TResult[];\n /** Runs the statement and returns the driver result as is, without building row objects. */\n executeRaw: (parameters: TParams) => SqliteDriverRows;\n finalize: () => void;\n isFinalized: boolean;\n};\n\ntype ScalarFunctionOptions<\n TArgs extends readonly SqliteDriverValue[],\n TResult extends SqliteDriverValue | undefined,\n> = {\n name: string;\n callback: (...args: TArgs) => TResult;\n deterministic?: boolean;\n directOnly?: boolean;\n innocuous?: boolean;\n};\n\ntype SqliteWrapperOptions = {\n logger?: Logger;\n loggerPrefix?: string;\n driver: SqliteDriver;\n};\n\nexport type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<\n SQLiteDbWrapper<TDatabase>,\n \"sql\" | \"execute\" | \"executePrepared\" | \"executePreparedRaw\" | \"executeKysely\"\n>;\n\nexport type InternalSQLiteTransactionWrapper<TDatabase = unknown> = Pick<\n SQLiteDbWrapper<TDatabase>,\n \"executePrepared\" | \"executePreparedRaw\"\n>;\n\nexport type InternalSQLiteWrapper<TDatabase = unknown> = InternalSQLiteTransactionWrapper<TDatabase> & {\n executeTransaction: (callback: (db: InternalSQLiteTransactionWrapper<TDatabase>) => void) => void;\n};\n\ntype QueryMetaOpts = {\n loggerLevel?: \"info\" | \"system\";\n};\n\n/** Runs after user SQL succeeds, before its transaction or savepoint is committed. */\ntype AfterMutatingStatement<TDatabase> = (db: InternalSQLiteTransactionWrapper<TDatabase>) => void;\n\ntype ExecuteOptions = QueryMetaOpts & {\n /** For internal mutations whose effects must not be processed by afterMutatingStatement. */\n skipAfterMutatingStatement?: boolean;\n};\n\n// sqlite3_stmt_readonly reports transaction control statements as read-only.\nconst TRANSACTION_CONTROL_PATTERN =\n /^(?:\\s|--[^\\n]*\\n|\\/\\*[\\s\\S]*?\\*\\/)*(?:begin|commit|end|rollback|savepoint|release)\\b/i;\n\nexport class SQLiteDbWrapper<TDatabase = unknown> {\n private driver: SqliteDriver | null;\n private logger?: Logger;\n private loggerPrefix?: string;\n\n private loadedDbSchema: DatabaseIntrospection | null = null;\n\n private preparedStatements: PreparedStatement<SqliteDriverValue[], unknown>[] = [];\n private preparedStatementsMap = new Map<string, TypedStatement<Record<string, unknown>, unknown>>();\n private preparedRawStatementsMap = new Map<string, PreparedStatement<SqliteDriverValue[], unknown>>();\n private readonlyStatementCache = new BoundMap<string, boolean>({ maxSize: 500, onRemove: undefined });\n private afterMutatingStatement: AfterMutatingStatement<TDatabase> | null = null;\n\n constructor(opts: SqliteWrapperOptions) {\n this.driver = opts.driver;\n this.logger = opts.logger;\n this.loggerPrefix = opts.loggerPrefix;\n }\n\n get ensureDriver() {\n if (!this.driver) {\n throw new Error(\"Database is already closed\");\n }\n return this.driver;\n }\n\n get dbSchema() {\n if (!this.loadedDbSchema) {\n this.loadedDbSchema = introspectDb(this);\n }\n return this.loadedDbSchema;\n }\n\n private executeSql<T>(\n sql: string,\n bind: readonly unknown[] | undefined,\n loggerLevel: QueryMetaOpts[\"loggerLevel\"],\n skipAfterMutatingStatement: boolean,\n ): ExecuteResult<T> {\n const perf = startPerformanceLogger(this.logger, loggerLevel);\n const driver = this.ensureDriver;\n const statement = driver.prepare(sql);\n let transaction: { commit: () => void; rollback: () => void } | undefined;\n\n try {\n const afterMutatingStatement =\n !skipAfterMutatingStatement && this.afterMutatingStatement && !this.isReadonlyStatement(statement, sql)\n ? this.afterMutatingStatement\n : null;\n\n let totalChangesBefore = 0;\n if (afterMutatingStatement) {\n transaction = this.beginStatementTransaction();\n totalChangesBefore = driver.totalChanges();\n }\n\n const rows = toRowObjects<T>(statement.run(bind ?? []), () => ({}));\n statement.finalize();\n perf.logEnd(`${this.loggerPrefix ?? \"\"}:query`, sql, loggerLevel);\n\n if (transaction) {\n // Nothing was written, so the statement cannot have produced any work for the callback.\n if (driver.totalChanges() !== totalChangesBefore) {\n afterMutatingStatement?.(this);\n }\n transaction.commit();\n }\n\n return { rows };\n } catch (error) {\n statement.finalize();\n transaction?.rollback();\n throw error;\n }\n }\n\n private isReadonlyStatement(statement: SqliteDriverStatement, sql: string) {\n if (statement.readonly !== undefined) {\n return statement.readonly;\n }\n\n let readonly = this.readonlyStatementCache.get(sql);\n if (readonly === undefined) {\n readonly = TRANSACTION_CONTROL_PATTERN.test(sql) || this.isReadonlyByTablesUsed(sql);\n this.readonlyStatementCache.set(sql, readonly);\n }\n return readonly;\n }\n\n private isReadonlyByTablesUsed(sql: string) {\n // Statements that open no b-tree (PRAGMAs, table-less selects, full-table deletes)\n // are reported with no rows, so they are treated as writes.\n const tables = this.executePreparedRaw<[string], { wr: number }>({\n key: \"$tables-used-writes\",\n sql: `select \"wr\" from tables_used(?)`,\n params: [sql],\n meta: { loggerLevel: \"system\" },\n });\n return tables.length > 0 && tables.every((table) => !table.wr);\n }\n\n execute<T = unknown>(opts: ExecuteParams | string | CompiledQuery<T>, options?: ExecuteOptions): ExecuteResult<T> {\n const sql = typeof opts === \"string\" ? opts : opts.sql;\n const bind = typeof opts === \"string\" ? undefined : opts.parameters;\n\n return this.executeSql<T>(sql, bind, options?.loggerLevel, options?.skipAfterMutatingStatement ?? false);\n }\n\n setAfterMutatingStatement(callback: AfterMutatingStatement<TDatabase>) {\n if (this.afterMutatingStatement) {\n throw new Error(\"An afterMutatingStatement callback is already registered\");\n }\n this.afterMutatingStatement = callback;\n }\n\n executeTransaction<T>(callback: (db: SQLiteTransactionWrapper<TDatabase>) => T): T {\n const transaction = this.beginTransaction();\n try {\n const result = callback(this);\n transaction.commit();\n return result;\n } catch (error) {\n transaction.rollback();\n throw error;\n }\n }\n\n beginTransaction() {\n this.executePreparedRaw({\n key: \"$begin-transaction\",\n sql: \"begin\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n\n return {\n commit: () => {\n this.executePreparedRaw({\n key: \"$commit-transaction\",\n sql: \"commit\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n },\n rollback: () => {\n this.executePreparedRaw({\n key: \"$rollback-transaction\",\n sql: \"rollback\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n },\n };\n }\n\n // A savepoint opens a transaction when none is active, so this nests inside user transactions too.\n private beginStatementTransaction() {\n this.executePreparedRaw({\n key: \"$begin-statement-savepoint\",\n sql: \"savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n\n return {\n commit: () => {\n this.executePreparedRaw({\n key: \"$commit-statement-savepoint\",\n sql: \"release savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n },\n rollback: () => {\n this.executePreparedRaw({\n key: \"$rollback-statement-savepoint\",\n sql: \"rollback to savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n this.executePreparedRaw({\n key: \"$release-rolled-back-statement-savepoint\",\n sql: \"release savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n },\n };\n }\n\n prepare<TParams extends unknown[], TResult>(sql: string, opts?: QueryMetaOpts) {\n const perf = startPerformanceLogger(this.logger, opts?.loggerLevel);\n const stmt = this.ensureDriver.prepare(sql);\n perf.logEnd(`${this.loggerPrefix ?? \"\"}:prepare`, sql, opts?.loggerLevel);\n\n let isFinalized = false;\n\n const executeRaw = (params: TParams) => {\n if (isFinalized) {\n throw new Error(\"Statement is finalized\");\n }\n\n const perf = startPerformanceLogger(this.logger, opts?.loggerLevel);\n try {\n return stmt.run(params);\n } finally {\n perf.logEnd(`${this.loggerPrefix ?? \"\"}:prepare-execute`, sql, opts?.loggerLevel);\n }\n };\n\n const execute = (params: TParams) => toRowObjects<TResult>(executeRaw(params), () => ({}));\n\n const finalize = () => {\n isFinalized = true;\n stmt.finalize();\n };\n\n const preparedStatement: PreparedStatement<TParams, TResult> = {\n execute,\n executeRaw,\n finalize,\n get isFinalized() {\n return isFinalized;\n },\n };\n\n this.preparedStatements.push(preparedStatement as PreparedStatement<SqliteDriverValue[], unknown>);\n\n return preparedStatement;\n }\n\n prepareKysely<TParams extends Record<string, unknown>>(opts?: QueryMetaOpts) {\n return <TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>,\n ): TypedStatement<TParams, TResult> => {\n const query = compileKyselyStatement(factory);\n const statement = this.prepare<SqliteDriverValue[], TResult>(query.sql, opts);\n\n return {\n execute: (parameters) => statement.execute(query.bindParameters(parameters) as SqliteDriverValue[]),\n };\n };\n }\n\n executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(\n factory: KyselyQueryFactory<TDatabase, TQuery, TResult>,\n options?: ExecuteOptions,\n ) {\n const query = factory(dummyKysely).compile();\n return this.execute(query, options);\n }\n\n executePrepared<\n TParams extends Record<string, unknown>,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>,\n >(\n key: string,\n params: TParams,\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>,\n meta?: QueryMetaOpts,\n ) {\n let statement = this.preparedStatementsMap.get(key) as TypedStatement<TParams, TResult> | undefined;\n if (!statement) {\n statement = this.prepareKysely<TParams>(meta)(factory);\n this.preparedStatementsMap.set(key, statement as TypedStatement<Record<string, unknown>, unknown>);\n }\n\n return statement.execute(params);\n }\n\n executePreparedRaw<TParams extends unknown[], TResult>({\n key,\n sql,\n params,\n meta,\n }: {\n key: string;\n sql: string;\n params?: TParams;\n meta?: QueryMetaOpts;\n }) {\n let statement = this.preparedRawStatementsMap.get(key) as PreparedStatement<TParams, TResult> | undefined;\n if (!statement) {\n statement = this.prepare(sql, meta);\n this.preparedRawStatementsMap.set(key, statement as PreparedStatement<any[], unknown>);\n }\n\n return statement.execute((params ?? []) as TParams);\n }\n\n sql<T = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]) {\n if (typeof templateOrString === \"string\") {\n return this.execute<T>({\n sql: templateOrString,\n parameters,\n });\n }\n return this.execute<T>({\n sql: templateOrString.join(\"?\"),\n parameters,\n });\n }\n\n createScalarFunction<TArgs extends SqliteDriverValue[], TResult extends SqliteDriverValue | undefined>({\n name,\n callback,\n deterministic,\n directOnly,\n innocuous,\n }: ScalarFunctionOptions<TArgs, TResult>) {\n const driver = this.ensureDriver;\n if (!driver.createScalarFunction) {\n throw new Error(\"This SQLite driver does not support scalar functions\");\n }\n driver.createScalarFunction({\n name,\n callback: (...args) => callback(...(args as TArgs)),\n arity: callback.length,\n deterministic,\n directOnly,\n innocuous,\n });\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n const perf = startPerformanceLogger(this.logger, \"system\");\n const driver = this.ensureDriver;\n if (!driver.deserialize) {\n throw new Error(\"This SQLite driver does not support snapshots\");\n }\n driver.deserialize(snapshot);\n\n this.invalidateDbSchema();\n\n perf.logEnd(\"useSnapshot\", \"success\", \"system\");\n }\n\n createSnapshot() {\n const driver = this.ensureDriver;\n if (!driver.serialize) {\n throw new Error(\"This SQLite driver does not support snapshots\");\n }\n return driver.serialize();\n }\n\n invalidateDbSchema() {\n this.loadedDbSchema = null;\n }\n\n cleanup() {\n this.preparedStatements.forEach((stmt) => {\n stmt.finalize();\n });\n this.preparedStatements.splice(0);\n this.preparedStatementsMap.clear();\n this.preparedRawStatementsMap.clear();\n this.readonlyStatementCache.clear();\n }\n\n close() {\n this.cleanup();\n\n this.driver?.close();\n this.driver = null;\n }\n}\n\nfunction toRowObjects<T>(\n { columns, rows }: { columns: string[]; rows: SqliteDriverValue[][] },\n createRow: () => Record<string, unknown>,\n): T[] {\n const result: T[] = [];\n for (const values of rows) {\n const row = createRow();\n for (let index = 0; index < columns.length; index++) {\n row[columns[index]] = values[index];\n }\n result.push(row as T);\n }\n return result;\n}\n\nexport type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;\ntype ParamsGetter<TParams> = <TKey extends keyof TParams>(key: TKey) => TParams[TKey];\n\ntype TypedStatement<TParams extends Record<string, unknown>, TResult> = {\n execute: (parameters: TParams) => TResult[];\n};\nexport type KyselyStatementFactory<\n TParams extends Record<string, unknown>,\n TDatabase,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>,\n> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;\nexport type KyselyQueryFactory<TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (\n kysely: Kysely<TDatabase>,\n) => TQuery;\n\nexport function compileKyselyStatement<TParams extends Record<string, unknown>, TDatabase>(\n factory: KyselyStatementFactory<TParams, TDatabase, Compilable<unknown>>,\n) {\n const parameterKeys = new Map<unknown, keyof TParams>();\n const query = factory(dummyKysely, (key) => {\n const token = {};\n parameterKeys.set(token, key);\n return token as TParams[typeof key];\n }).compile();\n\n return {\n sql: query.sql,\n bindParameters: (parameters: TParams) =>\n query.parameters.map((value) => {\n const key = parameterKeys.get(value);\n return key === undefined ? value : parameters[key];\n }),\n };\n}\n","export type StoredValue<T> = {\n get current(): T;\n set current(newValue: T);\n};\n\nexport function createStoredValue<T>({\n initialValue,\n saveToStorage,\n}: {\n initialValue: T;\n saveToStorage?: (value: T) => void;\n}): StoredValue<T> {\n let currentValue = initialValue;\n\n return {\n get current() {\n return currentValue;\n },\n set current(newValue: T) {\n saveToStorage?.(newValue);\n currentValue = newValue;\n },\n };\n}\n","import { type SchemaModule, sql } from \"kysely\";\nimport type { StateHashStore } from \"./sqlite-crdt/state-hash\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport type { InternalSQLiteWrapper } from \"./sqlite-db-wrapper\";\n\nexport type KvStoreItem = {\n key: string;\n value: string;\n};\n\nexport function createKvStoreTableQuery(schema: SchemaModule, tableName: string) {\n return schema\n .createTable(tableName)\n .ifNotExists()\n .addColumn(\"key\", \"text\", (col) => col.notNull().primaryKey())\n .addColumn(\"value\", \"text\", (col) => col.notNull())\n .modifyEnd(sql`without rowid`);\n}\n\nexport function createSQLiteKvStore({ db, metaTableName }: { db: InternalSQLiteWrapper<any>; metaTableName: string }) {\n const metaDb = db as InternalSQLiteWrapper<{\n meta: KvStoreItem;\n }>;\n\n const get = (key: string): string | null => {\n const [result] = metaDb.executePrepared(\n \"get-meta-value\",\n { key },\n (db, params) =>\n db\n .selectFrom(metaTableName as \"meta\")\n .where(\"key\", \"=\", params(\"key\"))\n .select(\"value\")\n .limit((eb) => eb.lit(1)),\n { loggerLevel: \"system\" },\n );\n\n return result?.value ?? null;\n };\n\n const set = (key: string, value: string) => {\n metaDb.executePrepared(\n \"set-meta-value\",\n { key, value },\n (db, params) =>\n db\n .insertInto(metaTableName as \"meta\")\n .values({ key: params(\"key\"), value: params(\"value\") })\n .onConflict((oc) => oc.doUpdateSet({ value: params(\"value\") })),\n { loggerLevel: \"system\" },\n );\n };\n\n const remove = (key: string) => {\n metaDb.executePrepared(\n \"remove-meta-value\",\n { key },\n (db, params) => db.deleteFrom(metaTableName as \"meta\").where(\"key\", \"=\", params(\"key\")),\n { loggerLevel: \"system\" },\n );\n };\n\n const getNumberOrDefault = <T>(key: string, defaultValue: T): T | number => {\n const value = get(key);\n if (!value) return defaultValue;\n const parsedValue = Number.parseInt(value, 10);\n return Number.isNaN(parsedValue) ? defaultValue : parsedValue;\n };\n\n return {\n get,\n set,\n remove,\n createStringStoredValue: (key: string, defaultValue: string) =>\n createStoredValue<string>({\n initialValue: get(key) ?? defaultValue,\n saveToStorage: (val) => set(key, val),\n }),\n createNumberStoredValue: (key: string, defaultValue: number) =>\n createStoredValue<number>({\n initialValue: getNumberOrDefault(key, defaultValue),\n saveToStorage: (val) => set(key, val.toString()),\n }),\n };\n}\n\nexport type KvStore = ReturnType<typeof createSQLiteKvStore>;\n\nexport const STATE_HASH_KV_KEY = \"crdt.consistency.state_hash.v2\";\n\nexport function createKvStateHashStore(kvStore: Pick<KvStore, \"get\" | \"set\">): StateHashStore {\n return {\n read: () => kvStore.get(STATE_HASH_KV_KEY),\n write: (value) => kvStore.set(STATE_HASH_KV_KEY, value),\n };\n}\n","import {\n CRDT_EVENT_NO_OP_PAYLOAD,\n type CrdtUpdateLogItem,\n type PersistedCrdtEvent,\n} from \"../sqlite-crdt/crdt-table-schema\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createKvStoreTableQuery, createSQLiteKvStore, type KvStoreItem } from \"../sqlite-kv-store\";\nimport { type ParsedTableName, parseTableName, quoteId } from \"../utils\";\n\nexport type SystemDbConfig = {\n eventsTable: ParsedTableName;\n updateLogTable: ParsedTableName;\n};\n\nexport function createSystemDbConfig({\n eventsTableName,\n updateLogTableName,\n}: {\n eventsTableName: string;\n updateLogTableName: string;\n}): SystemDbConfig {\n return {\n eventsTable: parseTableName(eventsTableName),\n updateLogTable: parseTableName(updateLogTableName),\n };\n}\n\nexport type WorkerDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n \"worker.kv\": KvStoreItem;\n \"worker.crdt_events\": PersistedCrdtEvent;\n};\n\nexport const workerDbConfig = createSystemDbConfig({\n eventsTableName: \"worker.crdt_events\",\n updateLogTableName: \"crdt_update_log\",\n});\n\nexport type LocalDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n crdt_events: PersistedCrdtEvent;\n sync_kv: KvStoreItem;\n};\n\nexport const localDbConfig = createSystemDbConfig({\n eventsTableName: \"crdt_events\",\n updateLogTableName: \"crdt_update_log\",\n});\n\nexport const LOCAL_KV_TABLE_NAME = \"sync_kv\";\n\nexport type MemoryDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n persisted_crdt_events: PersistedCrdtEvent;\n};\n\nexport const memoryDbConfig = createSystemDbConfig({\n eventsTableName: \"persisted_crdt_events\",\n updateLogTableName: \"crdt_update_log\",\n});\n\nexport type SystemMigrationExecute = (sql: string, parameters?: readonly unknown[]) => { rows: unknown[] };\n\nexport type SystemMigrationContext = SystemDbConfig & {\n execute: SystemMigrationExecute;\n};\n\nexport type SystemMigration = {\n version: number;\n up: (ctx: SystemMigrationContext) => void;\n};\n\nconst nonNoOpEventPredicate = `\"payload\" <> '${CRDT_EVENT_NO_OP_PAYLOAD}'`;\n\nexport const baseSystemMigrations: SystemMigration[] = [\n {\n version: 0,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`CREATE TABLE IF NOT EXISTS ${ctx.eventsTable.fullIdentifier} (\n \"sync_id\" integer NOT NULL PRIMARY KEY,\n \"schema_version\" integer NOT NULL,\n \"status\" text NOT NULL,\n \"type\" text NOT NULL,\n \"timestamp\" text NOT NULL,\n \"origin\" text NOT NULL,\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL\n )`);\n ctx.execute(`CREATE TABLE IF NOT EXISTS ${ctx.updateLogTable.fullIdentifier} (\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL,\n PRIMARY KEY (\"item_id\", \"dataset\")\n )`);\n },\n },\n {\n version: 1,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`ALTER TABLE ${ctx.eventsTable.fullIdentifier} ADD COLUMN \"source_node_id\" TEXT NOT NULL DEFAULT ''`);\n },\n },\n {\n version: 2,\n up: (ctx: SystemMigrationContext) => {\n const indexName = `${ctx.eventsTable.table}_status_sync_id_idx`;\n ctx.execute(\n `CREATE INDEX IF NOT EXISTS ${ctx.eventsTable.schema}.${indexName} ON ${ctx.eventsTable.table} (\"status\", \"sync_id\")`,\n );\n },\n },\n {\n version: 3,\n up: (ctx: SystemMigrationContext) => {\n const indexName = `${ctx.eventsTable.table}_timestamp_status_sync_id_idx`;\n ctx.execute(\n `CREATE INDEX IF NOT EXISTS ${ctx.eventsTable.schema}.${indexName} ON ${ctx.eventsTable.table} (\"timestamp\", \"status\", \"sync_id\")`,\n );\n },\n },\n {\n version: 4,\n up: (ctx: SystemMigrationContext) => {\n const indexName = `${ctx.eventsTable.table}_dataset_item_id_non_no_op_idx`;\n ctx.execute(\n `CREATE INDEX IF NOT EXISTS ${ctx.eventsTable.schema}.${indexName} ON ${ctx.eventsTable.table} (\"dataset\", \"item_id\") WHERE ${nonNoOpEventPredicate}`,\n );\n },\n },\n {\n // Older builds kept an item's first create under `id` in its update log. The state hash\n // reads missing cells as written by the latest create, so lift `id` to the latest one\n // the event log still has. Applying a create that is no longer in the log fixes the rest.\n version: 5,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`UPDATE ${quoteId(ctx.updateLogTable.fullIdentifier)} AS \"log\"\nSET \"payload\" = json_set(\"log\".\"payload\", '$.id', \"latest\".\"timestamp\")\nFROM (\n SELECT \"dataset\", \"item_id\", max(\"timestamp\") AS \"timestamp\"\n FROM ${quoteId(ctx.eventsTable.fullIdentifier)}\n WHERE \"type\" = 'item-created' AND \"status\" = 'applied' AND ${nonNoOpEventPredicate}\n GROUP BY \"dataset\", \"item_id\"\n) AS \"latest\"\nWHERE \"latest\".\"dataset\" = \"log\".\"dataset\" AND \"latest\".\"item_id\" = \"log\".\"item_id\"\n AND \"latest\".\"timestamp\" > coalesce(json_extract(\"log\".\"payload\", '$.id'), '')`);\n },\n },\n {\n // Older builds left `tombstone` alone when re-applying a create, so it kept the HLC (and\n // value) of an earlier create or delete. Creates now clear it at their own HLC, so restamp\n // it with the latest create and undelete the row, as a replica replaying history would.\n version: 6,\n up: (ctx: SystemMigrationContext) => {\n const updateLog = quoteId(ctx.updateLogTable.fullIdentifier);\n const isStale = `json_extract(\"payload\", '$.tombstone') < json_extract(\"payload\", '$.id')`;\n const { rows } = ctx.execute(\n `SELECT DISTINCT \"log\".\"dataset\" AS \"dataset\" FROM ${updateLog} AS \"log\"\nJOIN \"sqlite_master\" AS \"master\" ON \"master\".\"type\" = 'table' AND \"master\".\"name\" = \"log\".\"dataset\"\nWHERE ${isStale}`,\n );\n for (const { dataset } of rows as { dataset: string }[]) {\n ctx.execute(\n `UPDATE ${quoteId(dataset)} SET \"tombstone\" = 0\nWHERE \"tombstone\" <> 0 AND \"id\" IN (SELECT \"item_id\" FROM ${updateLog} WHERE \"dataset\" = ? AND ${isStale})`,\n [dataset],\n );\n }\n ctx.execute(\n `UPDATE ${updateLog} SET \"payload\" = json_set(\"payload\", '$.tombstone', json_extract(\"payload\", '$.id')) WHERE ${isStale}`,\n );\n },\n },\n];\n\nexport function runSystemMigrations(opts: {\n version: StoredValue<number>;\n migrations: SystemMigration[];\n dbConfig: SystemDbConfig;\n execute: SystemMigrationExecute;\n transaction: (callback: () => void) => void;\n}): void {\n const ctx: SystemMigrationContext = {\n ...opts.dbConfig,\n execute: opts.execute,\n };\n for (const migration of opts.migrations) {\n if (migration.version > opts.version.current) {\n opts.transaction(() => {\n migration.up(ctx);\n opts.version.current = migration.version;\n });\n }\n }\n}\n\nexport function applyWorkerDbSchema(db: SQLiteDbWrapper<any>) {\n return applySystemDbSchema(db, { kvTableName: \"worker.kv\", dbConfig: workerDbConfig });\n}\n\nexport function applyLocalDbSchema(db: SQLiteDbWrapper<any>) {\n return applySystemDbSchema(db, { kvTableName: LOCAL_KV_TABLE_NAME, dbConfig: localDbConfig });\n}\n\nfunction applySystemDbSchema(\n db: SQLiteDbWrapper<any>,\n { kvTableName, dbConfig }: { kvTableName: string; dbConfig: SystemDbConfig },\n) {\n // KV table stays separate — needed before system migrations for version tracking\n db.executeKysely((kysely) => createKvStoreTableQuery(kysely.schema, kvTableName), { loggerLevel: \"system\" });\n\n // System schema migrations (each in its own transaction)\n const kvStore = createSQLiteKvStore({ db, metaTableName: kvTableName });\n runSystemMigrations({\n migrations: baseSystemMigrations,\n version: kvStore.createNumberStoredValue(\"internal-schema-version\", -1),\n dbConfig,\n execute: (sql, parameters = []) => db.execute({ sql, parameters }, { loggerLevel: \"system\" }),\n transaction: (callback) => db.executeTransaction(callback),\n });\n\n return { kvStore };\n}\n\nexport function applyMemoryDbSchema(db: SQLiteDbWrapper<any>) {\n db.execute(\n `CREATE TABLE IF NOT EXISTS ${memoryDbConfig.eventsTable.fullIdentifier} (\n \"sync_id\" integer NOT NULL PRIMARY KEY,\n \"schema_version\" integer NOT NULL,\n \"status\" text NOT NULL,\n \"type\" text NOT NULL,\n \"timestamp\" text NOT NULL,\n \"origin\" text NOT NULL,\n \"source_node_id\" text NOT NULL DEFAULT '',\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL\n )`,\n { loggerLevel: \"system\" },\n );\n db.execute(\n `CREATE INDEX IF NOT EXISTS ${memoryDbConfig.eventsTable.table}_status_sync_id_idx ON ${memoryDbConfig.eventsTable.table} (\"status\", \"sync_id\")`,\n {\n loggerLevel: \"system\",\n },\n );\n db.execute(\n `CREATE INDEX IF NOT EXISTS ${memoryDbConfig.eventsTable.table}_timestamp_status_sync_id_idx ON ${memoryDbConfig.eventsTable.table} (\"timestamp\", \"status\", \"sync_id\")`,\n {\n loggerLevel: \"system\",\n },\n );\n db.execute(\n `CREATE INDEX IF NOT EXISTS ${memoryDbConfig.eventsTable.table}_dataset_item_id_non_no_op_idx ON ${memoryDbConfig.eventsTable.table} (\"dataset\", \"item_id\") WHERE ${nonNoOpEventPredicate}`,\n {\n loggerLevel: \"system\",\n },\n );\n db.execute(\n `CREATE TABLE IF NOT EXISTS ${memoryDbConfig.updateLogTable.fullIdentifier} (\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL,\n PRIMARY KEY (\"item_id\", \"dataset\")\n)`,\n { loggerLevel: \"system\" },\n );\n}\n"],"mappings":"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"}
|
package/dist/worker.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as EventsPullRequest, O as WorkerConfig, Qt as Logger, S as CreateRemoteSourceFactory, T as EventsPushResponse, c as ResetStore, ct as GetEventsBatch, dn as SyncDbSchema, w as EventsPushRequest } from "./index-
|
|
2
|
-
import { t as createWsRemoteSource } from "./ws-remote-source-
|
|
1
|
+
import { C as EventsPullRequest, O as WorkerConfig, Qt as Logger, S as CreateRemoteSourceFactory, T as EventsPushResponse, c as ResetStore, ct as GetEventsBatch, dn as SyncDbSchema, w as EventsPushRequest } from "./index-BgkTUdlX.js";
|
|
2
|
+
import { t as createWsRemoteSource } from "./ws-remote-source-BJFkwEyQ.js";
|
|
3
3
|
//#region src/worker-db/db-worker.d.ts
|
|
4
4
|
declare function getWorkerConfig<Props = never>(): Promise<WorkerConfig<Props>>;
|
|
5
5
|
type WorkerOptions = {
|
package/dist/worker.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { f as createKvStateHashStore, g as SQLiteDbWrapper, i as applyWorkerDbSchema, u as workerDbConfig } from "./system-schema-
|
|
1
|
+
import { f as createKvStateHashStore, g as SQLiteDbWrapper, i as applyWorkerDbSchema, u as workerDbConfig } from "./system-schema-B8hbFl7o.js";
|
|
2
2
|
import { l as generateId, o as createDeferredPromise } from "./crdt-table-schema-D6Yf61Ex.js";
|
|
3
|
-
import { a as formatSchemaVerificationIssues, c as createMigrator, n as createCrdtStorage, t as createCrdtSyncProducer, u as createImportData } from "./crdt-sync-producer-
|
|
3
|
+
import { a as formatSchemaVerificationIssues, c as createMigrator, n as createCrdtStorage, t as createCrdtSyncProducer, u as createImportData } from "./crdt-sync-producer-BQkuzCBM.js";
|
|
4
4
|
import { o as HLCCounter, t as createCrdtSyncRemoteSource, u as xxhash } from "./crdt-sync-remote-source-yeTEkOjH.js";
|
|
5
|
-
import { _ as createWasmSqliteDriver, d as isWorkerRequestMessage, h as verifySyncSchema, i as createResetStateStore, l as isWorkerInitMessage, m as syncDbWorkerLockName, n as createIdbResetStore, o as runWithNoActiveReplicas, p as syncDbClientLockName, r as createReloadRequestHandler, s as createBroadcastChannels } from "./reset-state-
|
|
5
|
+
import { _ as createWasmSqliteDriver, d as isWorkerRequestMessage, h as verifySyncSchema, i as createResetStateStore, l as isWorkerInitMessage, m as syncDbWorkerLockName, n as createIdbResetStore, o as runWithNoActiveReplicas, p as syncDbClientLockName, r as createReloadRequestHandler, s as createBroadcastChannels } from "./reset-state-DAPyJglN.js";
|
|
6
6
|
import { i as runWorkerEventLogGc, n as createStorageVersionStore, t as createWsRemoteSource } from "./ws-remote-source-BbPWrHB6.js";
|
|
7
7
|
import sqlite3InitModule from "@sqlite.org/sqlite-wasm";
|
|
8
8
|
//#region src/worker-db/db-worker.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as CreateRemoteSourceFactory } from "./index-
|
|
1
|
+
import { S as CreateRemoteSourceFactory } from "./index-BgkTUdlX.js";
|
|
2
2
|
//#region src/web-socket/ws-remote-source.d.ts
|
|
3
3
|
type WsRemoteSourceConfig = {
|
|
4
4
|
createWebSocket: () => Pick<WebSocket, "onmessage" | "close" | "addEventListener" | "removeEventListener"> & {
|
|
@@ -9,4 +9,4 @@ type WsRemoteSourceConfig = {
|
|
|
9
9
|
declare const createWsRemoteSource: ({ createWebSocket }: WsRemoteSourceConfig) => CreateRemoteSourceFactory;
|
|
10
10
|
//#endregion
|
|
11
11
|
export { createWsRemoteSource as t };
|
|
12
|
-
//# sourceMappingURL=ws-remote-source-
|
|
12
|
+
//# sourceMappingURL=ws-remote-source-BJFkwEyQ.d.ts.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-reactive-db-BwY3FoIy.js","names":[],"sources":["../src/memory-db/sqlite-reactive-db.ts"],"sourcesContent":["import { BoundMap } from \"../bound-map\";\nimport { type Logger, startPerformanceLogger } from \"../logger\";\nimport { type PreparedStatement, SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { SqliteDriver } from \"../sqlite-driver\";\nimport { createTypedEventTarget, type TypedEvent } from \"../utils\";\n\ntype TableName<Database> = keyof Database extends string ? keyof Database : never;\n\nexport type SQLiteReactiveDbOptions = {\n driver: SqliteDriver;\n snapshot?: Uint8Array<ArrayBufferLike>;\n logger: Logger;\n loggerPrefix?: string;\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 class SQLiteReactiveDb<Database> {\n readonly db: SQLiteDbWrapper<Database>;\n private readonly driver: SqliteDriver;\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 private isDisposed = false;\n private mutationVersion = 0;\n private tableMutationVersions = new Map<string, number>();\n\n private constructor(opts: SQLiteReactiveDbOptions) {\n this.driver = opts.driver;\n this.logger = opts.logger;\n\n this.db = new SQLiteDbWrapper({\n driver: opts.driver,\n logger: this.logger,\n loggerPrefix: opts.loggerPrefix ?? \"memory\",\n });\n }\n\n static create<Database>(opts: SQLiteReactiveDbOptions) {\n const perf = startPerformanceLogger(opts.logger, \"system\");\n\n const db = new SQLiteReactiveDb<Database>(opts);\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 /**\n * When false, table mutation versions only advance after the writing statement\n * returns, so they cannot tell whether that statement wrote to a table.\n */\n get hasSynchronousHooks() {\n return this.driver.synchronousHooks;\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 let rowsVersion = 0;\n\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 rowsVersion = this.mutationVersion;\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 // Tables may have changed while nothing was subscribed, e.g. between React's render and commit.\n if (rows && this.mutationVersion !== rowsVersion) {\n 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 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\n return () => {\n entry.listeners.delete(onchange);\n\n if (entry.listeners.size === 0) {\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\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 getTableMutationVersion(table: string) {\n return this.tableMutationVersions.get(table) ?? 0;\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 // Asynchronous drivers can deliver hooks that were queued before dispose.\n this.driver.setHooks({\n onUpdate: (table) => {\n if (this.isDisposed) {\n return;\n }\n updateQueue.add(table);\n this.tableMutationVersions.set(table, ++this.mutationVersion);\n },\n onRollback: () => {\n if (this.isDisposed || updateQueue.size === 0) {\n return;\n }\n\n updateQueue.clear();\n this.eventTarget.dispatchEvent(\"transaction-rolled-back\", undefined);\n },\n onCommit: () => {\n if (this.isDisposed || updateQueue.size === 0) {\n return;\n }\n\n const tables = updateQueue;\n updateQueue = new Set<string>();\n this.eventTarget.dispatchEvent(\"transaction-committed\", undefined);\n\n queueMicrotask(() => {\n if (!this.isDisposed) {\n this.notifyTableSubscribers(tables);\n }\n });\n },\n });\n }\n\n createSnapshot() {\n const perf = startPerformanceLogger(this.logger);\n const snapshot = this.db.createSnapshot();\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.mutationVersion++;\n this.notifyTableSubscribers();\n }\n\n dispose() {\n this.isDisposed = true;\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.driver.setHooks(null);\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"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"system-schema-uHQdQTCk.js","names":[],"sources":["../src/dummy-kysely.ts","../src/introspection.ts","../src/logger.ts","../src/bound-map.ts","../src/sqlite-db-wrapper.ts","../src/sqlite-crdt/stored-value.ts","../src/sqlite-kv-store.ts","../src/migrations/system-schema.ts"],"sourcesContent":["import { DummyDriver, Kysely, SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from \"kysely\";\n\nexport const dummyKysely: Kysely<any> = new Kysely({\n dialect: {\n createAdapter: () => new SqliteAdapter(),\n createDriver: () => new DummyDriver(),\n createQueryCompiler: () => new SqliteQueryCompiler(),\n createIntrospector: (db) => new SqliteIntrospector(db),\n },\n});\n","import type { Kysely, QueryCreator } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SQLiteDbWrapper } from \"./sqlite-db-wrapper\";\n\ninterface SqliteSystemDatabase {\n // https://www.sqlite.org/schematab.html#alternative_names\n sqlite_master: SQliteMasterTable;\n}\n\n// https://www.sqlite.org/schematab.html#interpretation_of_the_schema_table\ninterface SQliteMasterTable {\n name: string;\n rootpage: number | null;\n sql: string;\n tbl_name: string;\n type: \"index\" | \"table\" | \"trigger\" | \"view\";\n}\n\n// https://www.sqlite.org/pragma.html#pragma_table_info\ninterface PragmaTableInfo {\n cid: number;\n dflt_value: unknown;\n name: string;\n notnull: 0 | 1;\n pk: number;\n type: string;\n}\n\nfunction tablesQuery(qb: QueryCreator<SqliteSystemDatabase> | Kysely<SqliteSystemDatabase>) {\n return qb\n .selectFrom(\"sqlite_master\")\n .where(\"type\", \"in\", [\"table\", \"view\"])\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select([\"name\", \"sql\", \"type\"])\n .orderBy(\"name\");\n}\n\nexport type TableMetadata = {\n name: string;\n isView: boolean;\n columns: ColumnMetadata[];\n};\n\nexport type DatabaseIntrospection = Record<string, TableMetadata>;\n\nexport type ColumnMetadata = {\n name: string;\n dataType: string;\n isNullable: boolean;\n isAutoIncrementing: boolean;\n hasDefaultValue: boolean;\n defaultValueSql: string | null;\n isPrimaryKey: boolean;\n comment: undefined;\n};\n\nexport function introspectDb<BaseDatabase>(_db: SQLiteDbWrapper<BaseDatabase>): DatabaseIntrospection {\n const db = _db as unknown as SQLiteDbWrapper<SqliteSystemDatabase>;\n const tables = db.executeKysely((db) => tablesQuery(db as unknown as Kysely<SqliteSystemDatabase>), {\n loggerLevel: \"system\",\n }).rows;\n\n const tablesMetadata = db.executeKysely(\n (db) =>\n db\n .with(\"table_list\", (qb) => tablesQuery(qb as unknown as Kysely<SqliteSystemDatabase>))\n .selectFrom([\"table_list as tl\", sql<PragmaTableInfo>`pragma_table_info(tl.name)`.as(\"p\")])\n .select([\"tl.name as table\", \"p.cid\", \"p.name\", \"p.type\", \"p.notnull\", \"p.dflt_value\", \"p.pk\"])\n .orderBy(\"tl.name\")\n .orderBy(\"p.cid\"),\n { loggerLevel: \"system\" },\n ).rows;\n\n const columnsByTable: Record<string, typeof tablesMetadata> = {};\n for (const row of tablesMetadata) {\n columnsByTable[row.table] ??= [];\n columnsByTable[row.table].push(row);\n }\n\n return Object.fromEntries(\n tables.map(({ name, sql, type }) => {\n // Try to find the name of the column that has `autoincrement`\n let autoIncrementCol = sql\n ?.split(/[(),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.trimStart()\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = columnsByTable[name] ?? [];\n\n // Otherwise, check for an INTEGER PRIMARY KEY\n // https://www.sqlite.org/autoinc.html\n if (!autoIncrementCol) {\n const pkCols = columns.filter((r) => r.pk > 0);\n if (pkCols.length === 1 && pkCols[0].type.toLowerCase() === \"integer\") {\n autoIncrementCol = pkCols[0].name;\n }\n }\n\n return [\n name,\n {\n name: name,\n isView: type === \"view\",\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n defaultValueSql: col.dflt_value == null ? null : String(col.dflt_value),\n isPrimaryKey: col.pk > 0,\n comment: undefined,\n })),\n },\n ];\n }),\n );\n}\n","export type LogLevel = \"info\" | \"warning\" | \"error\" | \"trace\" | \"system\";\n\nexport type Logger = (type: string, message: string, level?: LogLevel) => void;\n\nexport type PerformanceLogger = {\n restart: () => void;\n logEnd: (type: string, message: string, level?: LogLevel) => void;\n};\n\nconst noopPerformanceLogger: PerformanceLogger = {\n restart() {},\n logEnd() {},\n};\n\nexport const startPerformanceLogger = (logger: Logger | undefined, level: LogLevel = \"info\"): PerformanceLogger => {\n if (!logger || level === \"system\") {\n return noopPerformanceLogger;\n }\n\n let startTime = performance.now();\n\n return {\n restart: () => {\n startTime = performance.now();\n },\n logEnd: (type: string, message: string, logLevel: LogLevel = level) => {\n const elapsed = performance.now() - startTime;\n\n logger(type, `${elapsed.toFixed(2)}ms - ${message}`, logLevel);\n },\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 { Compilable, CompiledQuery, Kysely } from \"kysely\";\nimport { BoundMap } from \"./bound-map\";\nimport { dummyKysely } from \"./dummy-kysely\";\nimport { type DatabaseIntrospection, introspectDb } from \"./introspection\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\nimport type { SqliteDriver, SqliteDriverStatement, SqliteDriverValue } from \"./sqlite-driver\";\n\nexport type ExecuteParams = {\n sql: string;\n parameters: readonly unknown[];\n};\n\nexport type ExecuteResult<T> = {\n rows: T[];\n};\n\nexport type PreparedStatement<TParams extends unknown[], TResult> = {\n execute: (parameters: TParams) => TResult[];\n finalize: () => void;\n isFinalized: boolean;\n};\n\ntype ScalarFunctionOptions<\n TArgs extends readonly SqliteDriverValue[],\n TResult extends SqliteDriverValue | undefined,\n> = {\n name: string;\n callback: (...args: TArgs) => TResult;\n deterministic?: boolean;\n directOnly?: boolean;\n innocuous?: boolean;\n};\n\ntype SqliteWrapperOptions = {\n logger?: Logger;\n loggerPrefix?: string;\n driver: SqliteDriver;\n};\n\nexport type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<\n SQLiteDbWrapper<TDatabase>,\n \"sql\" | \"execute\" | \"executePrepared\" | \"executePreparedRaw\" | \"executeKysely\"\n>;\n\nexport type InternalSQLiteTransactionWrapper<TDatabase = unknown> = Pick<\n SQLiteDbWrapper<TDatabase>,\n \"executePrepared\" | \"executePreparedRaw\"\n>;\n\nexport type InternalSQLiteWrapper<TDatabase = unknown> = InternalSQLiteTransactionWrapper<TDatabase> & {\n executeTransaction: (callback: (db: InternalSQLiteTransactionWrapper<TDatabase>) => void) => void;\n};\n\ntype QueryMetaOpts = {\n loggerLevel?: \"info\" | \"system\";\n};\n\n/** Runs after user SQL succeeds, before its transaction or savepoint is committed. */\ntype AfterMutatingStatement<TDatabase> = (db: InternalSQLiteTransactionWrapper<TDatabase>) => void;\n\ntype ExecuteOptions = QueryMetaOpts & {\n /** For internal mutations whose effects must not be processed by afterMutatingStatement. */\n skipAfterMutatingStatement?: boolean;\n};\n\n// sqlite3_stmt_readonly reports transaction control statements as read-only.\nconst TRANSACTION_CONTROL_PATTERN =\n /^(?:\\s|--[^\\n]*\\n|\\/\\*[\\s\\S]*?\\*\\/)*(?:begin|commit|end|rollback|savepoint|release)\\b/i;\n\nexport class SQLiteDbWrapper<TDatabase = unknown> {\n private driver: SqliteDriver | null;\n private logger?: Logger;\n private loggerPrefix?: string;\n\n private loadedDbSchema: DatabaseIntrospection | null = null;\n\n private preparedStatements: PreparedStatement<SqliteDriverValue[], unknown>[] = [];\n private preparedStatementsMap = new Map<string, TypedStatement<Record<string, unknown>, unknown>>();\n private preparedRawStatementsMap = new Map<string, PreparedStatement<SqliteDriverValue[], unknown>>();\n private readonlyStatementCache = new BoundMap<string, boolean>({ maxSize: 500, onRemove: undefined });\n private afterMutatingStatement: AfterMutatingStatement<TDatabase> | null = null;\n\n constructor(opts: SqliteWrapperOptions) {\n this.driver = opts.driver;\n this.logger = opts.logger;\n this.loggerPrefix = opts.loggerPrefix;\n }\n\n get ensureDriver() {\n if (!this.driver) {\n throw new Error(\"Database is already closed\");\n }\n return this.driver;\n }\n\n get dbSchema() {\n if (!this.loadedDbSchema) {\n this.loadedDbSchema = introspectDb(this);\n }\n return this.loadedDbSchema;\n }\n\n private executeSql<T>(\n sql: string,\n bind: readonly unknown[] | undefined,\n loggerLevel: QueryMetaOpts[\"loggerLevel\"],\n skipAfterMutatingStatement: boolean,\n ): ExecuteResult<T> {\n const perf = startPerformanceLogger(this.logger, loggerLevel);\n const driver = this.ensureDriver;\n const statement = driver.prepare(sql);\n let transaction: { commit: () => void; rollback: () => void } | undefined;\n\n try {\n const afterMutatingStatement =\n !skipAfterMutatingStatement && this.afterMutatingStatement && !this.isReadonlyStatement(statement, sql)\n ? this.afterMutatingStatement\n : null;\n\n let totalChangesBefore = 0;\n if (afterMutatingStatement) {\n transaction = this.beginStatementTransaction();\n totalChangesBefore = driver.totalChanges();\n }\n\n const rows = toRowObjects<T>(statement.run(bind ?? []), () => Object.create(null));\n statement.finalize();\n perf.logEnd(`${this.loggerPrefix ?? \"\"}:query`, sql, loggerLevel);\n\n if (transaction) {\n // Nothing was written, so the statement cannot have produced any work for the callback.\n if (driver.totalChanges() !== totalChangesBefore) {\n afterMutatingStatement?.(this);\n }\n transaction.commit();\n }\n\n return { rows };\n } catch (error) {\n statement.finalize();\n transaction?.rollback();\n throw error;\n }\n }\n\n private isReadonlyStatement(statement: SqliteDriverStatement, sql: string) {\n if (statement.readonly !== undefined) {\n return statement.readonly;\n }\n\n let readonly = this.readonlyStatementCache.get(sql);\n if (readonly === undefined) {\n readonly = TRANSACTION_CONTROL_PATTERN.test(sql) || this.isReadonlyByTablesUsed(sql);\n this.readonlyStatementCache.set(sql, readonly);\n }\n return readonly;\n }\n\n private isReadonlyByTablesUsed(sql: string) {\n // Statements that open no b-tree (PRAGMAs, table-less selects, full-table deletes)\n // are reported with no rows, so they are treated as writes.\n const tables = this.executePreparedRaw<[string], { wr: number }>({\n key: \"$tables-used-writes\",\n sql: `select \"wr\" from tables_used(?)`,\n params: [sql],\n meta: { loggerLevel: \"system\" },\n });\n return tables.length > 0 && tables.every((table) => !table.wr);\n }\n\n execute<T = unknown>(opts: ExecuteParams | string | CompiledQuery<T>, options?: ExecuteOptions): ExecuteResult<T> {\n const sql = typeof opts === \"string\" ? opts : opts.sql;\n const bind = typeof opts === \"string\" ? undefined : opts.parameters;\n\n return this.executeSql<T>(sql, bind, options?.loggerLevel, options?.skipAfterMutatingStatement ?? false);\n }\n\n setAfterMutatingStatement(callback: AfterMutatingStatement<TDatabase>) {\n if (this.afterMutatingStatement) {\n throw new Error(\"An afterMutatingStatement callback is already registered\");\n }\n this.afterMutatingStatement = callback;\n }\n\n executeTransaction<T>(callback: (db: SQLiteTransactionWrapper<TDatabase>) => T): T {\n const transaction = this.beginTransaction();\n try {\n const result = callback(this);\n transaction.commit();\n return result;\n } catch (error) {\n transaction.rollback();\n throw error;\n }\n }\n\n beginTransaction() {\n this.executePreparedRaw({\n key: \"$begin-transaction\",\n sql: \"begin\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n\n return {\n commit: () => {\n this.executePreparedRaw({\n key: \"$commit-transaction\",\n sql: \"commit\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n },\n rollback: () => {\n this.executePreparedRaw({\n key: \"$rollback-transaction\",\n sql: \"rollback\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n },\n };\n }\n\n // A savepoint opens a transaction when none is active, so this nests inside user transactions too.\n private beginStatementTransaction() {\n this.executePreparedRaw({\n key: \"$begin-statement-savepoint\",\n sql: \"savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n\n return {\n commit: () => {\n this.executePreparedRaw({\n key: \"$commit-statement-savepoint\",\n sql: \"release savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n },\n rollback: () => {\n this.executePreparedRaw({\n key: \"$rollback-statement-savepoint\",\n sql: \"rollback to savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n this.executePreparedRaw({\n key: \"$release-rolled-back-statement-savepoint\",\n sql: \"release savepoint sqlite_sync_statement\",\n meta: { loggerLevel: \"system\" },\n });\n },\n };\n }\n\n prepare<TParams extends unknown[], TResult>(sql: string, opts?: QueryMetaOpts) {\n const perf = startPerformanceLogger(this.logger, opts?.loggerLevel);\n const stmt = this.ensureDriver.prepare(sql);\n perf.logEnd(`${this.loggerPrefix ?? \"\"}:prepare`, sql, opts?.loggerLevel);\n\n let isFinalized = false;\n\n const execute = (params: TParams) => {\n if (isFinalized) {\n throw new Error(\"Statement is finalized\");\n }\n\n const perf = startPerformanceLogger(this.logger, opts?.loggerLevel);\n try {\n return toRowObjects<TResult>(stmt.run(params), () => ({}));\n } finally {\n perf.logEnd(`${this.loggerPrefix ?? \"\"}:prepare-execute`, sql, opts?.loggerLevel);\n }\n };\n\n const finalize = () => {\n isFinalized = true;\n stmt.finalize();\n };\n\n const preparedStatement: PreparedStatement<TParams, TResult> = {\n execute,\n finalize,\n get isFinalized() {\n return isFinalized;\n },\n };\n\n this.preparedStatements.push(preparedStatement as PreparedStatement<SqliteDriverValue[], unknown>);\n\n return preparedStatement;\n }\n\n prepareKysely<TParams extends Record<string, unknown>>(opts?: QueryMetaOpts) {\n return <TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>,\n ): TypedStatement<TParams, TResult> => {\n const query = compileKyselyStatement(factory);\n const statement = this.prepare<SqliteDriverValue[], TResult>(query.sql, opts);\n\n return {\n execute: (parameters) => statement.execute(query.bindParameters(parameters) as SqliteDriverValue[]),\n };\n };\n }\n\n executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(\n factory: KyselyQueryFactory<TDatabase, TQuery, TResult>,\n options?: ExecuteOptions,\n ) {\n const query = factory(dummyKysely).compile();\n return this.execute(query, options);\n }\n\n executePrepared<\n TParams extends Record<string, unknown>,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>,\n >(\n key: string,\n params: TParams,\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>,\n meta?: QueryMetaOpts,\n ) {\n let statement = this.preparedStatementsMap.get(key) as TypedStatement<TParams, TResult> | undefined;\n if (!statement) {\n statement = this.prepareKysely<TParams>(meta)(factory);\n this.preparedStatementsMap.set(key, statement as TypedStatement<Record<string, unknown>, unknown>);\n }\n\n return statement.execute(params);\n }\n\n executePreparedRaw<TParams extends unknown[], TResult>({\n key,\n sql,\n params,\n meta,\n }: {\n key: string;\n sql: string;\n params?: TParams;\n meta?: QueryMetaOpts;\n }) {\n let statement = this.preparedRawStatementsMap.get(key) as PreparedStatement<TParams, TResult> | undefined;\n if (!statement) {\n statement = this.prepare(sql, meta);\n this.preparedRawStatementsMap.set(key, statement as PreparedStatement<any[], unknown>);\n }\n\n return statement.execute((params ?? []) as TParams);\n }\n\n sql<T = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]) {\n if (typeof templateOrString === \"string\") {\n return this.execute<T>({\n sql: templateOrString,\n parameters,\n });\n }\n return this.execute<T>({\n sql: templateOrString.join(\"?\"),\n parameters,\n });\n }\n\n createScalarFunction<TArgs extends SqliteDriverValue[], TResult extends SqliteDriverValue | undefined>({\n name,\n callback,\n deterministic,\n directOnly,\n innocuous,\n }: ScalarFunctionOptions<TArgs, TResult>) {\n const driver = this.ensureDriver;\n if (!driver.createScalarFunction) {\n throw new Error(\"This SQLite driver does not support scalar functions\");\n }\n driver.createScalarFunction({\n name,\n callback: (...args) => callback(...(args as TArgs)),\n arity: callback.length,\n deterministic,\n directOnly,\n innocuous,\n });\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n const perf = startPerformanceLogger(this.logger, \"system\");\n const driver = this.ensureDriver;\n if (!driver.deserialize) {\n throw new Error(\"This SQLite driver does not support snapshots\");\n }\n driver.deserialize(snapshot);\n\n this.invalidateDbSchema();\n\n perf.logEnd(\"useSnapshot\", \"success\", \"system\");\n }\n\n createSnapshot() {\n const driver = this.ensureDriver;\n if (!driver.serialize) {\n throw new Error(\"This SQLite driver does not support snapshots\");\n }\n return driver.serialize();\n }\n\n invalidateDbSchema() {\n this.loadedDbSchema = null;\n }\n\n cleanup() {\n this.preparedStatements.forEach((stmt) => {\n stmt.finalize();\n });\n this.preparedStatements.splice(0);\n this.preparedStatementsMap.clear();\n this.preparedRawStatementsMap.clear();\n this.readonlyStatementCache.clear();\n }\n\n close() {\n this.cleanup();\n\n this.driver?.close();\n this.driver = null;\n }\n}\n\nfunction toRowObjects<T>(\n { columns, rows }: { columns: string[]; rows: SqliteDriverValue[][] },\n createRow: () => Record<string, unknown>,\n): T[] {\n const result: T[] = [];\n for (const values of rows) {\n const row = createRow();\n for (let index = 0; index < columns.length; index++) {\n row[columns[index]] = values[index];\n }\n result.push(row as T);\n }\n return result;\n}\n\nexport type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;\ntype ParamsGetter<TParams> = <TKey extends keyof TParams>(key: TKey) => TParams[TKey];\n\ntype TypedStatement<TParams extends Record<string, unknown>, TResult> = {\n execute: (parameters: TParams) => TResult[];\n};\nexport type KyselyStatementFactory<\n TParams extends Record<string, unknown>,\n TDatabase,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>,\n> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;\nexport type KyselyQueryFactory<TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (\n kysely: Kysely<TDatabase>,\n) => TQuery;\n\nexport function compileKyselyStatement<TParams extends Record<string, unknown>, TDatabase>(\n factory: KyselyStatementFactory<TParams, TDatabase, Compilable<unknown>>,\n) {\n const parameterKeys = new Map<unknown, keyof TParams>();\n const query = factory(dummyKysely, (key) => {\n const token = {};\n parameterKeys.set(token, key);\n return token as TParams[typeof key];\n }).compile();\n\n return {\n sql: query.sql,\n bindParameters: (parameters: TParams) =>\n query.parameters.map((value) => {\n const key = parameterKeys.get(value);\n return key === undefined ? value : parameters[key];\n }),\n };\n}\n","export type StoredValue<T> = {\n get current(): T;\n set current(newValue: T);\n};\n\nexport function createStoredValue<T>({\n initialValue,\n saveToStorage,\n}: {\n initialValue: T;\n saveToStorage?: (value: T) => void;\n}): StoredValue<T> {\n let currentValue = initialValue;\n\n return {\n get current() {\n return currentValue;\n },\n set current(newValue: T) {\n saveToStorage?.(newValue);\n currentValue = newValue;\n },\n };\n}\n","import { type SchemaModule, sql } from \"kysely\";\nimport type { StateHashStore } from \"./sqlite-crdt/state-hash\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport type { InternalSQLiteWrapper } from \"./sqlite-db-wrapper\";\n\nexport type KvStoreItem = {\n key: string;\n value: string;\n};\n\nexport function createKvStoreTableQuery(schema: SchemaModule, tableName: string) {\n return schema\n .createTable(tableName)\n .ifNotExists()\n .addColumn(\"key\", \"text\", (col) => col.notNull().primaryKey())\n .addColumn(\"value\", \"text\", (col) => col.notNull())\n .modifyEnd(sql`without rowid`);\n}\n\nexport function createSQLiteKvStore({ db, metaTableName }: { db: InternalSQLiteWrapper<any>; metaTableName: string }) {\n const metaDb = db as InternalSQLiteWrapper<{\n meta: KvStoreItem;\n }>;\n\n const get = (key: string): string | null => {\n const [result] = metaDb.executePrepared(\n \"get-meta-value\",\n { key },\n (db, params) =>\n db\n .selectFrom(metaTableName as \"meta\")\n .where(\"key\", \"=\", params(\"key\"))\n .select(\"value\")\n .limit((eb) => eb.lit(1)),\n { loggerLevel: \"system\" },\n );\n\n return result?.value ?? null;\n };\n\n const set = (key: string, value: string) => {\n metaDb.executePrepared(\n \"set-meta-value\",\n { key, value },\n (db, params) =>\n db\n .insertInto(metaTableName as \"meta\")\n .values({ key: params(\"key\"), value: params(\"value\") })\n .onConflict((oc) => oc.doUpdateSet({ value: params(\"value\") })),\n { loggerLevel: \"system\" },\n );\n };\n\n const remove = (key: string) => {\n metaDb.executePrepared(\n \"remove-meta-value\",\n { key },\n (db, params) => db.deleteFrom(metaTableName as \"meta\").where(\"key\", \"=\", params(\"key\")),\n { loggerLevel: \"system\" },\n );\n };\n\n const getNumberOrDefault = <T>(key: string, defaultValue: T): T | number => {\n const value = get(key);\n if (!value) return defaultValue;\n const parsedValue = Number.parseInt(value, 10);\n return Number.isNaN(parsedValue) ? defaultValue : parsedValue;\n };\n\n return {\n get,\n set,\n remove,\n createStringStoredValue: (key: string, defaultValue: string) =>\n createStoredValue<string>({\n initialValue: get(key) ?? defaultValue,\n saveToStorage: (val) => set(key, val),\n }),\n createNumberStoredValue: (key: string, defaultValue: number) =>\n createStoredValue<number>({\n initialValue: getNumberOrDefault(key, defaultValue),\n saveToStorage: (val) => set(key, val.toString()),\n }),\n };\n}\n\nexport type KvStore = ReturnType<typeof createSQLiteKvStore>;\n\nexport const STATE_HASH_KV_KEY = \"crdt.consistency.state_hash.v2\";\n\nexport function createKvStateHashStore(kvStore: Pick<KvStore, \"get\" | \"set\">): StateHashStore {\n return {\n read: () => kvStore.get(STATE_HASH_KV_KEY),\n write: (value) => kvStore.set(STATE_HASH_KV_KEY, value),\n };\n}\n","import {\n CRDT_EVENT_NO_OP_PAYLOAD,\n type CrdtUpdateLogItem,\n type PersistedCrdtEvent,\n} from \"../sqlite-crdt/crdt-table-schema\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createKvStoreTableQuery, createSQLiteKvStore, type KvStoreItem } from \"../sqlite-kv-store\";\nimport { type ParsedTableName, parseTableName, quoteId } from \"../utils\";\n\nexport type SystemDbConfig = {\n eventsTable: ParsedTableName;\n updateLogTable: ParsedTableName;\n};\n\nexport function createSystemDbConfig({\n eventsTableName,\n updateLogTableName,\n}: {\n eventsTableName: string;\n updateLogTableName: string;\n}): SystemDbConfig {\n return {\n eventsTable: parseTableName(eventsTableName),\n updateLogTable: parseTableName(updateLogTableName),\n };\n}\n\nexport type WorkerDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n \"worker.kv\": KvStoreItem;\n \"worker.crdt_events\": PersistedCrdtEvent;\n};\n\nexport const workerDbConfig = createSystemDbConfig({\n eventsTableName: \"worker.crdt_events\",\n updateLogTableName: \"crdt_update_log\",\n});\n\nexport type LocalDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n crdt_events: PersistedCrdtEvent;\n sync_kv: KvStoreItem;\n};\n\nexport const localDbConfig = createSystemDbConfig({\n eventsTableName: \"crdt_events\",\n updateLogTableName: \"crdt_update_log\",\n});\n\nexport const LOCAL_KV_TABLE_NAME = \"sync_kv\";\n\nexport type MemoryDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n persisted_crdt_events: PersistedCrdtEvent;\n};\n\nexport const memoryDbConfig = createSystemDbConfig({\n eventsTableName: \"persisted_crdt_events\",\n updateLogTableName: \"crdt_update_log\",\n});\n\nexport type SystemMigrationExecute = (sql: string, parameters?: readonly unknown[]) => { rows: unknown[] };\n\nexport type SystemMigrationContext = SystemDbConfig & {\n execute: SystemMigrationExecute;\n};\n\nexport type SystemMigration = {\n version: number;\n up: (ctx: SystemMigrationContext) => void;\n};\n\nconst nonNoOpEventPredicate = `\"payload\" <> '${CRDT_EVENT_NO_OP_PAYLOAD}'`;\n\nexport const baseSystemMigrations: SystemMigration[] = [\n {\n version: 0,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`CREATE TABLE IF NOT EXISTS ${ctx.eventsTable.fullIdentifier} (\n \"sync_id\" integer NOT NULL PRIMARY KEY,\n \"schema_version\" integer NOT NULL,\n \"status\" text NOT NULL,\n \"type\" text NOT NULL,\n \"timestamp\" text NOT NULL,\n \"origin\" text NOT NULL,\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL\n )`);\n ctx.execute(`CREATE TABLE IF NOT EXISTS ${ctx.updateLogTable.fullIdentifier} (\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL,\n PRIMARY KEY (\"item_id\", \"dataset\")\n )`);\n },\n },\n {\n version: 1,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`ALTER TABLE ${ctx.eventsTable.fullIdentifier} ADD COLUMN \"source_node_id\" TEXT NOT NULL DEFAULT ''`);\n },\n },\n {\n version: 2,\n up: (ctx: SystemMigrationContext) => {\n const indexName = `${ctx.eventsTable.table}_status_sync_id_idx`;\n ctx.execute(\n `CREATE INDEX IF NOT EXISTS ${ctx.eventsTable.schema}.${indexName} ON ${ctx.eventsTable.table} (\"status\", \"sync_id\")`,\n );\n },\n },\n {\n version: 3,\n up: (ctx: SystemMigrationContext) => {\n const indexName = `${ctx.eventsTable.table}_timestamp_status_sync_id_idx`;\n ctx.execute(\n `CREATE INDEX IF NOT EXISTS ${ctx.eventsTable.schema}.${indexName} ON ${ctx.eventsTable.table} (\"timestamp\", \"status\", \"sync_id\")`,\n );\n },\n },\n {\n version: 4,\n up: (ctx: SystemMigrationContext) => {\n const indexName = `${ctx.eventsTable.table}_dataset_item_id_non_no_op_idx`;\n ctx.execute(\n `CREATE INDEX IF NOT EXISTS ${ctx.eventsTable.schema}.${indexName} ON ${ctx.eventsTable.table} (\"dataset\", \"item_id\") WHERE ${nonNoOpEventPredicate}`,\n );\n },\n },\n {\n // Older builds kept an item's first create under `id` in its update log. The state hash\n // reads missing cells as written by the latest create, so lift `id` to the latest one\n // the event log still has. Applying a create that is no longer in the log fixes the rest.\n version: 5,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`UPDATE ${quoteId(ctx.updateLogTable.fullIdentifier)} AS \"log\"\nSET \"payload\" = json_set(\"log\".\"payload\", '$.id', \"latest\".\"timestamp\")\nFROM (\n SELECT \"dataset\", \"item_id\", max(\"timestamp\") AS \"timestamp\"\n FROM ${quoteId(ctx.eventsTable.fullIdentifier)}\n WHERE \"type\" = 'item-created' AND \"status\" = 'applied' AND ${nonNoOpEventPredicate}\n GROUP BY \"dataset\", \"item_id\"\n) AS \"latest\"\nWHERE \"latest\".\"dataset\" = \"log\".\"dataset\" AND \"latest\".\"item_id\" = \"log\".\"item_id\"\n AND \"latest\".\"timestamp\" > coalesce(json_extract(\"log\".\"payload\", '$.id'), '')`);\n },\n },\n {\n // Older builds left `tombstone` alone when re-applying a create, so it kept the HLC (and\n // value) of an earlier create or delete. Creates now clear it at their own HLC, so restamp\n // it with the latest create and undelete the row, as a replica replaying history would.\n version: 6,\n up: (ctx: SystemMigrationContext) => {\n const updateLog = quoteId(ctx.updateLogTable.fullIdentifier);\n const isStale = `json_extract(\"payload\", '$.tombstone') < json_extract(\"payload\", '$.id')`;\n const { rows } = ctx.execute(\n `SELECT DISTINCT \"log\".\"dataset\" AS \"dataset\" FROM ${updateLog} AS \"log\"\nJOIN \"sqlite_master\" AS \"master\" ON \"master\".\"type\" = 'table' AND \"master\".\"name\" = \"log\".\"dataset\"\nWHERE ${isStale}`,\n );\n for (const { dataset } of rows as { dataset: string }[]) {\n ctx.execute(\n `UPDATE ${quoteId(dataset)} SET \"tombstone\" = 0\nWHERE \"tombstone\" <> 0 AND \"id\" IN (SELECT \"item_id\" FROM ${updateLog} WHERE \"dataset\" = ? AND ${isStale})`,\n [dataset],\n );\n }\n ctx.execute(\n `UPDATE ${updateLog} SET \"payload\" = json_set(\"payload\", '$.tombstone', json_extract(\"payload\", '$.id')) WHERE ${isStale}`,\n );\n },\n },\n];\n\nexport function runSystemMigrations(opts: {\n version: StoredValue<number>;\n migrations: SystemMigration[];\n dbConfig: SystemDbConfig;\n execute: SystemMigrationExecute;\n transaction: (callback: () => void) => void;\n}): void {\n const ctx: SystemMigrationContext = {\n ...opts.dbConfig,\n execute: opts.execute,\n };\n for (const migration of opts.migrations) {\n if (migration.version > opts.version.current) {\n opts.transaction(() => {\n migration.up(ctx);\n opts.version.current = migration.version;\n });\n }\n }\n}\n\nexport function applyWorkerDbSchema(db: SQLiteDbWrapper<any>) {\n return applySystemDbSchema(db, { kvTableName: \"worker.kv\", dbConfig: workerDbConfig });\n}\n\nexport function applyLocalDbSchema(db: SQLiteDbWrapper<any>) {\n return applySystemDbSchema(db, { kvTableName: LOCAL_KV_TABLE_NAME, dbConfig: localDbConfig });\n}\n\nfunction applySystemDbSchema(\n db: SQLiteDbWrapper<any>,\n { kvTableName, dbConfig }: { kvTableName: string; dbConfig: SystemDbConfig },\n) {\n // KV table stays separate — needed before system migrations for version tracking\n db.executeKysely((kysely) => createKvStoreTableQuery(kysely.schema, kvTableName), { loggerLevel: \"system\" });\n\n // System schema migrations (each in its own transaction)\n const kvStore = createSQLiteKvStore({ db, metaTableName: kvTableName });\n runSystemMigrations({\n migrations: baseSystemMigrations,\n version: kvStore.createNumberStoredValue(\"internal-schema-version\", -1),\n dbConfig,\n execute: (sql, parameters = []) => db.execute({ sql, parameters }, { loggerLevel: \"system\" }),\n transaction: (callback) => db.executeTransaction(callback),\n });\n\n return { kvStore };\n}\n\nexport function applyMemoryDbSchema(db: SQLiteDbWrapper<any>) {\n db.execute(\n `CREATE TABLE IF NOT EXISTS ${memoryDbConfig.eventsTable.fullIdentifier} (\n \"sync_id\" integer NOT NULL PRIMARY KEY,\n \"schema_version\" integer NOT NULL,\n \"status\" text NOT NULL,\n \"type\" text NOT NULL,\n \"timestamp\" text NOT NULL,\n \"origin\" text NOT NULL,\n \"source_node_id\" text NOT NULL DEFAULT '',\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL\n )`,\n { loggerLevel: \"system\" },\n );\n db.execute(\n `CREATE INDEX IF NOT EXISTS ${memoryDbConfig.eventsTable.table}_status_sync_id_idx ON ${memoryDbConfig.eventsTable.table} (\"status\", \"sync_id\")`,\n {\n loggerLevel: \"system\",\n },\n );\n db.execute(\n `CREATE INDEX IF NOT EXISTS ${memoryDbConfig.eventsTable.table}_timestamp_status_sync_id_idx ON ${memoryDbConfig.eventsTable.table} (\"timestamp\", \"status\", \"sync_id\")`,\n {\n loggerLevel: \"system\",\n },\n );\n db.execute(\n `CREATE INDEX IF NOT EXISTS ${memoryDbConfig.eventsTable.table}_dataset_item_id_non_no_op_idx ON ${memoryDbConfig.eventsTable.table} (\"dataset\", \"item_id\") WHERE ${nonNoOpEventPredicate}`,\n {\n loggerLevel: \"system\",\n },\n );\n db.execute(\n `CREATE TABLE IF NOT EXISTS ${memoryDbConfig.updateLogTable.fullIdentifier} (\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL,\n PRIMARY KEY (\"item_id\", \"dataset\")\n)`,\n { loggerLevel: \"system\" },\n );\n}\n"],"mappings":"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"}
|