@sqlite-sync/core 0.7.0 → 0.7.2
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-remote-source-BFl7v5_I.d.ts → crdt-sync-remote-source-yXp-iMEd.d.ts}
RENAMED
|
@@ -1,176 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CreateTableBuilder, Compilable, Kysely, CreateIndexBuilder, ColumnDataType, Expression, ColumnDefinitionBuilderCallback, ColumnType, CompiledQuery } from 'kysely';
|
|
2
2
|
import { Sqlite3Static, Database, SqlValue, FunctionOptions } from '@sqlite.org/sqlite-wasm';
|
|
3
3
|
|
|
4
|
-
interface HLC {
|
|
5
|
-
timestamp: number;
|
|
6
|
-
counter: number;
|
|
7
|
-
nodeId: string;
|
|
8
|
-
}
|
|
9
|
-
declare class HLCCounter {
|
|
10
|
-
private timestamp;
|
|
11
|
-
private counter;
|
|
12
|
-
private nodeId;
|
|
13
|
-
private readonly getTimestamp;
|
|
14
|
-
private readonly maxDrift;
|
|
15
|
-
constructor(nodeId: string, getTimestamp: () => number, maxDrift?: number);
|
|
16
|
-
getCurrentHLC(): HLC;
|
|
17
|
-
getNextHLC(): HLC;
|
|
18
|
-
mergeHLC(hlc: HLC): void;
|
|
19
|
-
}
|
|
20
|
-
declare function serializeHLC(hlc: HLC): string;
|
|
21
|
-
declare function deserializeHLC(serialized: string): HLC;
|
|
22
|
-
declare function compareHLC(one: HLC, two: HLC): number;
|
|
23
|
-
|
|
24
|
-
type LogLevel = "info" | "warning" | "error" | "trace" | "system";
|
|
25
|
-
type Logger = (type: string, message: string, level?: LogLevel) => void;
|
|
26
|
-
declare const startPerformanceLogger: (logger: Logger) => {
|
|
27
|
-
restart: () => void;
|
|
28
|
-
logEnd: (type: string, message: string, level?: LogLevel) => void;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
type ExecuteParams = {
|
|
32
|
-
sql: string;
|
|
33
|
-
parameters: readonly unknown[];
|
|
34
|
-
};
|
|
35
|
-
type ExecuteResult<T> = {
|
|
36
|
-
rows: T[];
|
|
37
|
-
};
|
|
38
|
-
type PreparedStatement<TParams extends unknown[], TResult> = {
|
|
39
|
-
execute: (parameters: TParams) => TResult[];
|
|
40
|
-
finalize: () => void;
|
|
41
|
-
isFinalized: boolean;
|
|
42
|
-
};
|
|
43
|
-
type ScalarFunctionOptions<TArgs extends readonly SqlValue[], TResult extends SqlValue | undefined> = {
|
|
44
|
-
name: string;
|
|
45
|
-
callback: (...args: TArgs) => TResult;
|
|
46
|
-
} & Pick<FunctionOptions, "deterministic" | "directOnly" | "innocuous">;
|
|
47
|
-
type SqliteWrapperOptions = {
|
|
48
|
-
logger?: Logger;
|
|
49
|
-
loggerPrefix?: string;
|
|
50
|
-
sqlite3: Sqlite3Static;
|
|
51
|
-
db: () => Database;
|
|
52
|
-
};
|
|
53
|
-
type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<SQLiteDbWrapper<TDatabase>, "sql" | "execute" | "executePrepared" | "executePreparedRaw" | "executeKysely">;
|
|
54
|
-
type InternalSQLiteTransactionWrapper<TDatabase = unknown> = Pick<SQLiteDbWrapper<TDatabase>, "executePrepared" | "executePreparedRaw">;
|
|
55
|
-
type InternalSQLiteWrapper<TDatabase = unknown> = InternalSQLiteTransactionWrapper<TDatabase> & {
|
|
56
|
-
executeTransaction: (callback: (db: InternalSQLiteTransactionWrapper<TDatabase>) => void) => void;
|
|
57
|
-
};
|
|
58
|
-
type QueryMetaOpts = {
|
|
59
|
-
loggerLevel?: "info" | "system";
|
|
60
|
-
};
|
|
61
|
-
declare class SQLiteDbWrapper<TDatabase = unknown> {
|
|
62
|
-
private db;
|
|
63
|
-
private sqlite3;
|
|
64
|
-
private logger?;
|
|
65
|
-
private loggerPrefix?;
|
|
66
|
-
private loadedDbSchema;
|
|
67
|
-
private readonly dataPointers;
|
|
68
|
-
private preparedStatements;
|
|
69
|
-
private preparedStatementsMap;
|
|
70
|
-
private preparedRawStatementsMap;
|
|
71
|
-
constructor(opts: SqliteWrapperOptions);
|
|
72
|
-
get ensureDb(): Database;
|
|
73
|
-
get dbSchema(): DatabaseIntrospection;
|
|
74
|
-
execute<T = unknown>(opts: ExecuteParams | string | CompiledQuery<T>, meta?: QueryMetaOpts): ExecuteResult<T>;
|
|
75
|
-
executeTransaction<T>(callback: (db: SQLiteTransactionWrapper<TDatabase>) => T): T;
|
|
76
|
-
isInTransaction(): boolean;
|
|
77
|
-
beginTransaction(): {
|
|
78
|
-
commit: () => void;
|
|
79
|
-
rollback: () => void;
|
|
80
|
-
};
|
|
81
|
-
prepare<TParams extends unknown[], TResult>(sql: string, opts?: QueryMetaOpts): PreparedStatement<TParams, TResult>;
|
|
82
|
-
prepareKysely<TParams extends Record<string, unknown>>(opts?: QueryMetaOpts): <TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>) => TypedStatement<TParams, TResult>;
|
|
83
|
-
executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyQueryFactory<TDatabase, TQuery, TResult>, meta?: QueryMetaOpts): ExecuteResult<TResult>;
|
|
84
|
-
executePrepared<TParams extends Record<string, unknown>, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(key: string, params: TParams, factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>, meta?: QueryMetaOpts): TResult[];
|
|
85
|
-
executePreparedRaw<TParams extends unknown[], TResult>({ key, sql, params, meta, }: {
|
|
86
|
-
key: string;
|
|
87
|
-
sql: string;
|
|
88
|
-
params?: TParams;
|
|
89
|
-
meta?: QueryMetaOpts;
|
|
90
|
-
}): TResult[];
|
|
91
|
-
sql<T = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]): ExecuteResult<T>;
|
|
92
|
-
createScalarFunction<TArgs extends SqlValue[], TResult extends SqlValue | undefined>({ name, callback, deterministic, directOnly, innocuous, }: ScalarFunctionOptions<TArgs, TResult>): Database;
|
|
93
|
-
useSnapshot(snapshot: Uint8Array<ArrayBufferLike>): void;
|
|
94
|
-
createSnapshot(): Uint8Array<ArrayBuffer>;
|
|
95
|
-
invalidateDbSchema(): void;
|
|
96
|
-
cleanup(): void;
|
|
97
|
-
close(): void;
|
|
98
|
-
}
|
|
99
|
-
type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;
|
|
100
|
-
type ParamsGetter<TParams> = <TKey extends keyof TParams>(key: TKey) => TParams[TKey];
|
|
101
|
-
type TypedStatement<TParams extends Record<string, unknown>, TResult> = {
|
|
102
|
-
execute: (parameters: TParams) => TResult[];
|
|
103
|
-
};
|
|
104
|
-
type KyselyStatementFactory<TParams extends Record<string, unknown>, TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;
|
|
105
|
-
type KyselyQueryFactory<TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (kysely: Kysely<TDatabase>) => TQuery;
|
|
106
|
-
|
|
107
|
-
type TableMetadata = {
|
|
108
|
-
name: string;
|
|
109
|
-
isView: boolean;
|
|
110
|
-
columns: ColumnMetadata[];
|
|
111
|
-
};
|
|
112
|
-
type DatabaseIntrospection = Record<string, TableMetadata>;
|
|
113
|
-
type ColumnMetadata = {
|
|
114
|
-
name: string;
|
|
115
|
-
dataType: string;
|
|
116
|
-
isNullable: boolean;
|
|
117
|
-
isAutoIncrementing: boolean;
|
|
118
|
-
hasDefaultValue: boolean;
|
|
119
|
-
defaultValueSql: string | null;
|
|
120
|
-
isPrimaryKey: boolean;
|
|
121
|
-
comment: undefined;
|
|
122
|
-
};
|
|
123
|
-
declare function introspectDb<BaseDatabase>(_db: SQLiteDbWrapper<BaseDatabase>): DatabaseIntrospection;
|
|
124
|
-
|
|
125
|
-
type DeferredPromise<T> = {
|
|
126
|
-
promise: Promise<T>;
|
|
127
|
-
resolve: (value: T) => void;
|
|
128
|
-
reject: (error: Error) => void;
|
|
129
|
-
};
|
|
130
|
-
type DeferredPromiseOptions = {
|
|
131
|
-
timeout?: number;
|
|
132
|
-
onTimeout?: () => void;
|
|
133
|
-
};
|
|
134
|
-
declare function createDeferredPromise<T>(opts?: DeferredPromiseOptions): DeferredPromise<T>;
|
|
135
|
-
declare const generateId: () => `${string}-${string}-${string}-${string}-${string}`;
|
|
136
|
-
type DistributiveOmit<T, K extends keyof T> = T extends any ? Omit<T, K> : never;
|
|
137
|
-
declare class TypedBroadcastChannel<TMessage> {
|
|
138
|
-
private readonly channel;
|
|
139
|
-
constructor(name: string);
|
|
140
|
-
postMessage(message: TMessage): void;
|
|
141
|
-
set onmessage(callback: ((event: MessageEvent<TMessage>) => void) | null);
|
|
142
|
-
close(): void;
|
|
143
|
-
}
|
|
144
|
-
declare class TypedEvent<T = unknown> extends Event {
|
|
145
|
-
readonly payload: T;
|
|
146
|
-
constructor(type: string, payload: T);
|
|
147
|
-
}
|
|
148
|
-
type TypedEventTarget<T extends Record<string, unknown>> = {
|
|
149
|
-
addEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => {
|
|
150
|
-
unsubscribe: () => void;
|
|
151
|
-
};
|
|
152
|
-
removeEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => void;
|
|
153
|
-
dispatchEvent: <K extends keyof T & string>(type: K, payload: T[K]) => void;
|
|
154
|
-
};
|
|
155
|
-
declare const createTypedEventTarget: <T extends Record<string, unknown>>() => TypedEventTarget<T>;
|
|
156
|
-
type TryCatchResult<T> = {
|
|
157
|
-
success: true;
|
|
158
|
-
data: T;
|
|
159
|
-
} | {
|
|
160
|
-
success: false;
|
|
161
|
-
error: unknown;
|
|
162
|
-
};
|
|
163
|
-
declare function tryCatch<T>(fn: () => T): TryCatchResult<T>;
|
|
164
|
-
declare function tryCatchAsync<T>(fn: () => Promise<T>): Promise<TryCatchResult<T>>;
|
|
165
|
-
declare function jsonSafeParse<T>(json: string): TryCatchResult<T>;
|
|
166
|
-
/** Quote a SQLite identifier (table/column name), handling dot-separated schema qualifiers. */
|
|
167
|
-
declare function quoteId(name: string): string;
|
|
168
|
-
type ParsedTableName = {
|
|
169
|
-
schema: "main" | (string & {});
|
|
170
|
-
table: string;
|
|
171
|
-
fullIdentifier: string;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
4
|
type NewCrdtEvent = {
|
|
175
5
|
type: CrdtEventType;
|
|
176
6
|
dataset: string;
|
|
@@ -295,40 +125,6 @@ declare function createMigrator({ migrations, schemaVersion, updateLogTableName,
|
|
|
295
125
|
};
|
|
296
126
|
type SyncDbMigrator = ReturnType<typeof createMigrator>;
|
|
297
127
|
|
|
298
|
-
type SystemDbConfig = {
|
|
299
|
-
eventsTable: ParsedTableName;
|
|
300
|
-
updateLogTable: ParsedTableName;
|
|
301
|
-
};
|
|
302
|
-
declare function createSystemDbConfig({ eventsTableName, updateLogTableName, }: {
|
|
303
|
-
eventsTableName: string;
|
|
304
|
-
updateLogTableName: string;
|
|
305
|
-
}): SystemDbConfig;
|
|
306
|
-
type SystemMigrationContext = SystemDbConfig & {
|
|
307
|
-
execute: (sql: string) => void;
|
|
308
|
-
};
|
|
309
|
-
type SystemMigration = {
|
|
310
|
-
version: number;
|
|
311
|
-
up: (ctx: SystemMigrationContext) => void;
|
|
312
|
-
};
|
|
313
|
-
declare const baseSystemMigrations: SystemMigration[];
|
|
314
|
-
declare function runSystemMigrations(opts: {
|
|
315
|
-
version: StoredValue<number>;
|
|
316
|
-
migrations: SystemMigration[];
|
|
317
|
-
dbConfig: SystemDbConfig;
|
|
318
|
-
execute: (sql: string) => void;
|
|
319
|
-
transaction: (callback: () => void) => void;
|
|
320
|
-
}): void;
|
|
321
|
-
declare function applyWorkerDbSchema(db: SQLiteDbWrapper<any>): {
|
|
322
|
-
kvStore: {
|
|
323
|
-
get: (key: string) => string | null;
|
|
324
|
-
set: (key: string, value: string) => void;
|
|
325
|
-
remove: (key: string) => void;
|
|
326
|
-
createStringStoredValue: (key: string, defaultValue: string) => StoredValue<string>;
|
|
327
|
-
createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
|
|
328
|
-
};
|
|
329
|
-
};
|
|
330
|
-
declare function applyMemoryDbSchema(db: SQLiteDbWrapper<any>): void;
|
|
331
|
-
|
|
332
128
|
type ColumnKind = "text" | "integer" | "real" | "boolean" | "enum";
|
|
333
129
|
type SqliteStorageType = "text" | "integer" | "real";
|
|
334
130
|
type ColumnMeta = {
|
|
@@ -436,43 +232,209 @@ type ReadonlyTable<Table extends Record<string, unknown>> = {
|
|
|
436
232
|
[K in keyof Table]: ColumnType<Table[K], never, never>;
|
|
437
233
|
};
|
|
438
234
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
235
|
+
interface HLC {
|
|
236
|
+
timestamp: number;
|
|
237
|
+
counter: number;
|
|
238
|
+
nodeId: string;
|
|
239
|
+
}
|
|
240
|
+
declare class HLCCounter {
|
|
241
|
+
private timestamp;
|
|
242
|
+
private counter;
|
|
243
|
+
private nodeId;
|
|
244
|
+
private readonly getTimestamp;
|
|
245
|
+
private readonly maxDrift;
|
|
246
|
+
constructor(nodeId: string, getTimestamp: () => number, maxDrift?: number);
|
|
247
|
+
getCurrentHLC(): HLC;
|
|
248
|
+
getNextHLC(): HLC;
|
|
249
|
+
mergeHLC(hlc: HLC): void;
|
|
250
|
+
}
|
|
251
|
+
declare function serializeHLC(hlc: HLC): string;
|
|
252
|
+
declare function deserializeHLC(serialized: string): HLC;
|
|
253
|
+
declare function compareHLC(one: HLC, two: HLC): number;
|
|
254
|
+
|
|
255
|
+
type TableMetadata = {
|
|
256
|
+
name: string;
|
|
257
|
+
isView: boolean;
|
|
258
|
+
columns: ColumnMetadata[];
|
|
445
259
|
};
|
|
446
|
-
|
|
447
|
-
|
|
260
|
+
type DatabaseIntrospection = Record<string, TableMetadata>;
|
|
261
|
+
type ColumnMetadata = {
|
|
262
|
+
name: string;
|
|
263
|
+
dataType: string;
|
|
264
|
+
isNullable: boolean;
|
|
265
|
+
isAutoIncrementing: boolean;
|
|
266
|
+
hasDefaultValue: boolean;
|
|
267
|
+
defaultValueSql: string | null;
|
|
268
|
+
isPrimaryKey: boolean;
|
|
269
|
+
comment: undefined;
|
|
270
|
+
};
|
|
271
|
+
declare function introspectDb<BaseDatabase>(_db: SQLiteDbWrapper<BaseDatabase>): DatabaseIntrospection;
|
|
272
|
+
|
|
273
|
+
type LogLevel = "info" | "warning" | "error" | "trace" | "system";
|
|
274
|
+
type Logger = (type: string, message: string, level?: LogLevel) => void;
|
|
275
|
+
declare const startPerformanceLogger: (logger: Logger) => {
|
|
276
|
+
restart: () => void;
|
|
277
|
+
logEnd: (type: string, message: string, level?: LogLevel) => void;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
type ExecuteParams = {
|
|
281
|
+
sql: string;
|
|
282
|
+
parameters: readonly unknown[];
|
|
283
|
+
};
|
|
284
|
+
type ExecuteResult<T> = {
|
|
285
|
+
rows: T[];
|
|
286
|
+
};
|
|
287
|
+
type PreparedStatement<TParams extends unknown[], TResult> = {
|
|
288
|
+
execute: (parameters: TParams) => TResult[];
|
|
289
|
+
finalize: () => void;
|
|
290
|
+
isFinalized: boolean;
|
|
291
|
+
};
|
|
292
|
+
type ScalarFunctionOptions<TArgs extends readonly SqlValue[], TResult extends SqlValue | undefined> = {
|
|
293
|
+
name: string;
|
|
294
|
+
callback: (...args: TArgs) => TResult;
|
|
295
|
+
} & Pick<FunctionOptions, "deterministic" | "directOnly" | "innocuous">;
|
|
296
|
+
type SqliteWrapperOptions = {
|
|
297
|
+
logger?: Logger;
|
|
298
|
+
loggerPrefix?: string;
|
|
299
|
+
sqlite3: Sqlite3Static;
|
|
300
|
+
db: () => Database;
|
|
301
|
+
};
|
|
302
|
+
type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<SQLiteDbWrapper<TDatabase>, "sql" | "execute" | "executePrepared" | "executePreparedRaw" | "executeKysely">;
|
|
303
|
+
type InternalSQLiteTransactionWrapper<TDatabase = unknown> = Pick<SQLiteDbWrapper<TDatabase>, "executePrepared" | "executePreparedRaw">;
|
|
304
|
+
type InternalSQLiteWrapper<TDatabase = unknown> = InternalSQLiteTransactionWrapper<TDatabase> & {
|
|
305
|
+
executeTransaction: (callback: (db: InternalSQLiteTransactionWrapper<TDatabase>) => void) => void;
|
|
306
|
+
};
|
|
307
|
+
type QueryMetaOpts = {
|
|
308
|
+
loggerLevel?: "info" | "system";
|
|
309
|
+
};
|
|
310
|
+
declare class SQLiteDbWrapper<TDatabase = unknown> {
|
|
311
|
+
private db;
|
|
312
|
+
private sqlite3;
|
|
313
|
+
private logger?;
|
|
314
|
+
private loggerPrefix?;
|
|
315
|
+
private loadedDbSchema;
|
|
316
|
+
private readonly dataPointers;
|
|
317
|
+
private preparedStatements;
|
|
318
|
+
private preparedStatementsMap;
|
|
319
|
+
private preparedRawStatementsMap;
|
|
320
|
+
constructor(opts: SqliteWrapperOptions);
|
|
321
|
+
get ensureDb(): Database;
|
|
322
|
+
get dbSchema(): DatabaseIntrospection;
|
|
323
|
+
execute<T = unknown>(opts: ExecuteParams | string | CompiledQuery<T>, meta?: QueryMetaOpts): ExecuteResult<T>;
|
|
324
|
+
executeTransaction<T>(callback: (db: SQLiteTransactionWrapper<TDatabase>) => T): T;
|
|
325
|
+
isInTransaction(): boolean;
|
|
326
|
+
beginTransaction(): {
|
|
327
|
+
commit: () => void;
|
|
328
|
+
rollback: () => void;
|
|
329
|
+
};
|
|
330
|
+
prepare<TParams extends unknown[], TResult>(sql: string, opts?: QueryMetaOpts): PreparedStatement<TParams, TResult>;
|
|
331
|
+
prepareKysely<TParams extends Record<string, unknown>>(opts?: QueryMetaOpts): <TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>) => TypedStatement<TParams, TResult>;
|
|
332
|
+
executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyQueryFactory<TDatabase, TQuery, TResult>, meta?: QueryMetaOpts): ExecuteResult<TResult>;
|
|
333
|
+
executePrepared<TParams extends Record<string, unknown>, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(key: string, params: TParams, factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>, meta?: QueryMetaOpts): TResult[];
|
|
334
|
+
executePreparedRaw<TParams extends unknown[], TResult>({ key, sql, params, meta, }: {
|
|
335
|
+
key: string;
|
|
336
|
+
sql: string;
|
|
337
|
+
params?: TParams;
|
|
338
|
+
meta?: QueryMetaOpts;
|
|
339
|
+
}): TResult[];
|
|
340
|
+
sql<T = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]): ExecuteResult<T>;
|
|
341
|
+
createScalarFunction<TArgs extends SqlValue[], TResult extends SqlValue | undefined>({ name, callback, deterministic, directOnly, innocuous, }: ScalarFunctionOptions<TArgs, TResult>): Database;
|
|
342
|
+
useSnapshot(snapshot: Uint8Array<ArrayBufferLike>): void;
|
|
343
|
+
createSnapshot(): Uint8Array<ArrayBuffer>;
|
|
344
|
+
invalidateDbSchema(): void;
|
|
345
|
+
cleanup(): void;
|
|
346
|
+
close(): void;
|
|
347
|
+
}
|
|
348
|
+
type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;
|
|
349
|
+
type ParamsGetter<TParams> = <TKey extends keyof TParams>(key: TKey) => TParams[TKey];
|
|
350
|
+
type TypedStatement<TParams extends Record<string, unknown>, TResult> = {
|
|
351
|
+
execute: (parameters: TParams) => TResult[];
|
|
352
|
+
};
|
|
353
|
+
type KyselyStatementFactory<TParams extends Record<string, unknown>, TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;
|
|
354
|
+
type KyselyQueryFactory<TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (kysely: Kysely<TDatabase>) => TQuery;
|
|
355
|
+
|
|
356
|
+
type DeferredPromise<T> = {
|
|
357
|
+
promise: Promise<T>;
|
|
358
|
+
resolve: (value: T) => void;
|
|
359
|
+
reject: (error: Error) => void;
|
|
360
|
+
};
|
|
361
|
+
type DeferredPromiseOptions = {
|
|
362
|
+
timeout?: number;
|
|
363
|
+
onTimeout?: () => void;
|
|
364
|
+
};
|
|
365
|
+
declare function createDeferredPromise<T>(opts?: DeferredPromiseOptions): DeferredPromise<T>;
|
|
366
|
+
declare const generateId: () => `${string}-${string}-${string}-${string}-${string}`;
|
|
367
|
+
type DistributiveOmit<T, K extends keyof T> = T extends any ? Omit<T, K> : never;
|
|
368
|
+
declare class TypedBroadcastChannel<TMessage> {
|
|
369
|
+
private readonly channel;
|
|
370
|
+
constructor(name: string);
|
|
371
|
+
postMessage(message: TMessage): void;
|
|
372
|
+
set onmessage(callback: ((event: MessageEvent<TMessage>) => void) | null);
|
|
373
|
+
close(): void;
|
|
374
|
+
}
|
|
375
|
+
declare class TypedEvent<T = unknown> extends Event {
|
|
376
|
+
readonly payload: T;
|
|
377
|
+
constructor(type: string, payload: T);
|
|
378
|
+
}
|
|
379
|
+
type TypedEventTarget<T extends Record<string, unknown>> = {
|
|
380
|
+
addEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => {
|
|
381
|
+
unsubscribe: () => void;
|
|
382
|
+
};
|
|
383
|
+
removeEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => void;
|
|
384
|
+
dispatchEvent: <K extends keyof T & string>(type: K, payload: T[K]) => void;
|
|
385
|
+
};
|
|
386
|
+
declare const createTypedEventTarget: <T extends Record<string, unknown>>() => TypedEventTarget<T>;
|
|
387
|
+
type TryCatchResult<T> = {
|
|
388
|
+
success: true;
|
|
389
|
+
data: T;
|
|
390
|
+
} | {
|
|
391
|
+
success: false;
|
|
392
|
+
error: unknown;
|
|
393
|
+
};
|
|
394
|
+
declare function tryCatch<T>(fn: () => T): TryCatchResult<T>;
|
|
395
|
+
declare function tryCatchAsync<T>(fn: () => Promise<T>): Promise<TryCatchResult<T>>;
|
|
396
|
+
declare function jsonSafeParse<T>(json: string): TryCatchResult<T>;
|
|
397
|
+
/** Quote a SQLite identifier (table/column name), handling dot-separated schema qualifiers. */
|
|
398
|
+
declare function quoteId(name: string): string;
|
|
399
|
+
type ParsedTableName = {
|
|
400
|
+
schema: "main" | (string & {});
|
|
401
|
+
table: string;
|
|
402
|
+
fullIdentifier: string;
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
type SystemDbConfig = {
|
|
406
|
+
eventsTable: ParsedTableName;
|
|
407
|
+
updateLogTable: ParsedTableName;
|
|
408
|
+
};
|
|
409
|
+
declare function createSystemDbConfig({ eventsTableName, updateLogTableName, }: {
|
|
410
|
+
eventsTableName: string;
|
|
411
|
+
updateLogTableName: string;
|
|
412
|
+
}): SystemDbConfig;
|
|
413
|
+
type SystemMigrationContext = SystemDbConfig & {
|
|
414
|
+
execute: (sql: string) => void;
|
|
415
|
+
};
|
|
416
|
+
type SystemMigration = {
|
|
417
|
+
version: number;
|
|
418
|
+
up: (ctx: SystemMigrationContext) => void;
|
|
419
|
+
};
|
|
420
|
+
declare const baseSystemMigrations: SystemMigration[];
|
|
421
|
+
declare function runSystemMigrations(opts: {
|
|
422
|
+
version: StoredValue<number>;
|
|
423
|
+
migrations: SystemMigration[];
|
|
448
424
|
dbConfig: SystemDbConfig;
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
dataset: string;
|
|
461
|
-
itemId: string;
|
|
462
|
-
payload: string;
|
|
463
|
-
}) => void;
|
|
464
|
-
updateItem: (opts: {
|
|
465
|
-
dataset: string;
|
|
466
|
-
itemId: string;
|
|
467
|
-
payload: Record<string, unknown>;
|
|
468
|
-
}) => void;
|
|
469
|
-
updateCrdtUpdateLog: (opts: {
|
|
470
|
-
dataset: string;
|
|
471
|
-
itemId: string;
|
|
472
|
-
payload: string;
|
|
473
|
-
}) => void;
|
|
425
|
+
execute: (sql: string) => void;
|
|
426
|
+
transaction: (callback: () => void) => void;
|
|
427
|
+
}): void;
|
|
428
|
+
declare function applyWorkerDbSchema(db: SQLiteDbWrapper<any>): {
|
|
429
|
+
kvStore: {
|
|
430
|
+
get: (key: string) => string | null;
|
|
431
|
+
set: (key: string, value: string) => void;
|
|
432
|
+
remove: (key: string) => void;
|
|
433
|
+
createStringStoredValue: (key: string, defaultValue: string) => StoredValue<string>;
|
|
434
|
+
createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
|
|
435
|
+
};
|
|
474
436
|
};
|
|
475
|
-
declare function
|
|
437
|
+
declare function applyMemoryDbSchema(db: SQLiteDbWrapper<any>): void;
|
|
476
438
|
|
|
477
439
|
type LocalCrdtEvent = {
|
|
478
440
|
type: CrdtEventType;
|
|
@@ -573,6 +535,44 @@ declare function createCrdtStorage(storage: DbSyncerStorage): {
|
|
|
573
535
|
};
|
|
574
536
|
};
|
|
575
537
|
|
|
538
|
+
type PendingCrdtEvent = {
|
|
539
|
+
type: CrdtEventType;
|
|
540
|
+
dataset: string;
|
|
541
|
+
item_id: string;
|
|
542
|
+
timestamp: string;
|
|
543
|
+
payload: string;
|
|
544
|
+
};
|
|
545
|
+
declare const createSQLiteCrdtApplyFunction: ({ db, dbConfig, }: {
|
|
546
|
+
db: InternalSQLiteWrapper<any>;
|
|
547
|
+
dbConfig: SystemDbConfig;
|
|
548
|
+
}) => (event: PendingCrdtEvent) => void;
|
|
549
|
+
type CreateCrdtApplyOpts = {
|
|
550
|
+
getCrdtUpdateLog: (opts: {
|
|
551
|
+
itemId: string;
|
|
552
|
+
dataset: string;
|
|
553
|
+
}) => CrdtUpdateLogPayload | null;
|
|
554
|
+
insertItem: (opts: {
|
|
555
|
+
dataset: string;
|
|
556
|
+
payload: Record<string, unknown>;
|
|
557
|
+
}) => void;
|
|
558
|
+
insertCrdtUpdateLog: (opts: {
|
|
559
|
+
dataset: string;
|
|
560
|
+
itemId: string;
|
|
561
|
+
payload: string;
|
|
562
|
+
}) => void;
|
|
563
|
+
updateItem: (opts: {
|
|
564
|
+
dataset: string;
|
|
565
|
+
itemId: string;
|
|
566
|
+
payload: Record<string, unknown>;
|
|
567
|
+
}) => void;
|
|
568
|
+
updateCrdtUpdateLog: (opts: {
|
|
569
|
+
dataset: string;
|
|
570
|
+
itemId: string;
|
|
571
|
+
payload: string;
|
|
572
|
+
}) => void;
|
|
573
|
+
};
|
|
574
|
+
declare function createCrdtApplyFunction({ getCrdtUpdateLog, insertItem, insertCrdtUpdateLog, updateItem, updateCrdtUpdateLog, }: CreateCrdtApplyOpts): (event: PendingCrdtEvent) => void;
|
|
575
|
+
|
|
576
576
|
type WorkerNotificationMessage = {
|
|
577
577
|
notificationType: "new-event-chunk-applied";
|
|
578
578
|
newSyncId: number;
|
|
@@ -710,4 +710,4 @@ declare const createCrdtSyncRemoteSource: ({ bufferSize, storage, migrator, pull
|
|
|
710
710
|
}[K]>) => void) => void;
|
|
711
711
|
};
|
|
712
712
|
|
|
713
|
-
export { type TableOptions as $, type AnyTableBuilder as A, baseSystemMigrations as B, type CrdtStorage as C, type DeSyncDetectedReason as D, type
|
|
713
|
+
export { type TableOptions as $, type AnyTableBuilder as A, baseSystemMigrations as B, type CrdtStorage as C, type DeSyncDetectedReason as D, type ExecuteResult as E, createSystemDbConfig as F, runSystemMigrations as G, type HLC as H, type InternalSQLiteWrapper as I, type SystemDbConfig as J, type KyselyQueryFactory as K, type Logger as L, type Migrations as M, type NewCrdtEvent as N, type SystemMigration as O, type SystemMigrationContext as P, type QueryBuilderOutput as Q, type ReadonlyTable as R, type StoredValue as S, TypedEvent as T, type AnyColumnBuilder as U, ColumnBuilder as V, type WorkerState as W, type ColumnKind as X, type ColumnMeta as Y, type PayloadValidationResult as Z, type SqliteStorageType as _, type CrdtTableConfig as a, t as a0, createCrdtApplyFunction as a1, createSQLiteCrdtApplyFunction as a2, type PendingCrdtEvent as a3, createCrdtStorage as a4, type OwnCrdtEvent as a5, type CrdtSyncRemoteSource as a6, createCrdtSyncRemoteSource as a7, type EventsPullRequest as a8, type EventsPushRequest as a9, type GetEventsBatch as aA, type EventsPullResponse as aB, type EventsPushResponse as aa, CRDT_EVENT_NO_OP_PAYLOAD as ab, type CrdtEventOrigin as ac, type CrdtEventStatus as ad, type CrdtEventType as ae, type CrdtUpdateLogItem as af, type CrdtUpdateLogPayload as ag, isNoOpCrdtEventPayload as ah, type PersistedCrdtEvent as ai, createStoredValue as aj, type KyselyStatementFactory as ak, type PreparedStatement as al, createDeferredPromise as am, createTypedEventTarget as an, type DeferredPromise as ao, type DistributiveOmit as ap, generateId as aq, jsonSafeParse as ar, quoteId as as, TypedBroadcastChannel as at, type TypedEventTarget as au, tryCatch as av, tryCatchAsync as aw, type WorkerConfig as ax, type WorkerNotificationMessage as ay, type CreateRemoteSourceFactory as az, SQLiteDbWrapper as b, type SyncSchemaTables as c, type SyncDbSchema as d, TableBuilder as e, type TableColumns as f, type InferRow as g, type ExecuteParams as h, type SQLiteTransactionWrapper as i, compareHLC as j, deserializeHLC as k, HLCCounter as l, type ColumnMetadata as m, type DatabaseIntrospection as n, introspectDb as o, type TableMetadata as p, type LogLevel as q, startPerformanceLogger as r, serializeHLC as s, createMigrations as t, createMigrator as u, type MigratableEvent as v, type MigrationsDb as w, type SyncDbMigrator as x, applyMemoryDbSchema as y, applyWorkerDbSchema as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,63 @@
|
|
|
1
1
|
import * as kysely from 'kysely';
|
|
2
2
|
import { Kysely, SchemaModule } from 'kysely';
|
|
3
|
-
import {
|
|
4
|
-
export { U as AnyColumnBuilder, ab as CRDT_EVENT_NO_OP_PAYLOAD, V as ColumnBuilder, X as ColumnKind, Y as ColumnMeta, m as ColumnMetadata, ac as CrdtEventOrigin, ad as CrdtEventStatus, ae as CrdtEventType, a6 as CrdtSyncRemoteSource, af as CrdtUpdateLogItem, ag as CrdtUpdateLogPayload, n as DatabaseIntrospection, ao as DeferredPromise, ap as DistributiveOmit, a8 as EventsPullRequest, a9 as EventsPushRequest, aa as EventsPushResponse, H as HLC, l as HLCCounter, ak as KyselyStatementFactory, q as LogLevel, v as MigratableEvent, w as MigrationsDb, a5 as OwnCrdtEvent, Z as PayloadValidationResult, a3 as PendingCrdtEvent, ai as PersistedCrdtEvent, al as PreparedStatement, _ as SqliteStorageType, x as SyncDbMigrator, J as SystemDbConfig, O as SystemMigration, P as SystemMigrationContext, p as TableMetadata, $ as TableOptions, at as TypedBroadcastChannel, au as TypedEventTarget, ax as WorkerConfig, ay as WorkerNotificationMessage, y as applyMemoryDbSchema, z as applyWorkerDbSchema, B as baseSystemMigrations, j as compareHLC, a1 as createCrdtApplyFunction, a4 as createCrdtStorage, a7 as createCrdtSyncRemoteSource, am as createDeferredPromise, t as createMigrations, u as createMigrator, a2 as createSQLiteCrdtApplyFunction, aj as createStoredValue, F as createSystemDbConfig, an as createTypedEventTarget, k as deserializeHLC, aq as generateId, o as introspectDb, ah as isNoOpCrdtEventPayload, ar as jsonSafeParse, as as quoteId, G as runSystemMigrations, s as serializeHLC, r as startPerformanceLogger, a0 as t, av as tryCatch, aw as tryCatchAsync } from './crdt-sync-remote-source-
|
|
3
|
+
import { I as InternalSQLiteWrapper, S as StoredValue, E as ExecuteResult, C as CrdtStorage, a as CrdtTableConfig, b as SQLiteDbWrapper, L as Logger, T as TypedEvent, c as SyncSchemaTables, d as SyncDbSchema, A as AnyTableBuilder, e as TableBuilder, f as TableColumns, g as InferRow, R as ReadonlyTable, M as Migrations, N as NewCrdtEvent, h as ExecuteParams, Q as QueryBuilderOutput, K as KyselyQueryFactory, i as SQLiteTransactionWrapper, W as WorkerState, D as DeSyncDetectedReason } from './crdt-sync-remote-source-yXp-iMEd.js';
|
|
4
|
+
export { U as AnyColumnBuilder, ab as CRDT_EVENT_NO_OP_PAYLOAD, V as ColumnBuilder, X as ColumnKind, Y as ColumnMeta, m as ColumnMetadata, ac as CrdtEventOrigin, ad as CrdtEventStatus, ae as CrdtEventType, a6 as CrdtSyncRemoteSource, af as CrdtUpdateLogItem, ag as CrdtUpdateLogPayload, n as DatabaseIntrospection, ao as DeferredPromise, ap as DistributiveOmit, a8 as EventsPullRequest, a9 as EventsPushRequest, aa as EventsPushResponse, H as HLC, l as HLCCounter, ak as KyselyStatementFactory, q as LogLevel, v as MigratableEvent, w as MigrationsDb, a5 as OwnCrdtEvent, Z as PayloadValidationResult, a3 as PendingCrdtEvent, ai as PersistedCrdtEvent, al as PreparedStatement, _ as SqliteStorageType, x as SyncDbMigrator, J as SystemDbConfig, O as SystemMigration, P as SystemMigrationContext, p as TableMetadata, $ as TableOptions, at as TypedBroadcastChannel, au as TypedEventTarget, ax as WorkerConfig, ay as WorkerNotificationMessage, y as applyMemoryDbSchema, z as applyWorkerDbSchema, B as baseSystemMigrations, j as compareHLC, a1 as createCrdtApplyFunction, a4 as createCrdtStorage, a7 as createCrdtSyncRemoteSource, am as createDeferredPromise, t as createMigrations, u as createMigrator, a2 as createSQLiteCrdtApplyFunction, aj as createStoredValue, F as createSystemDbConfig, an as createTypedEventTarget, k as deserializeHLC, aq as generateId, o as introspectDb, ah as isNoOpCrdtEventPayload, ar as jsonSafeParse, as as quoteId, G as runSystemMigrations, s as serializeHLC, r as startPerformanceLogger, a0 as t, av as tryCatch, aw as tryCatchAsync } from './crdt-sync-remote-source-yXp-iMEd.js';
|
|
5
5
|
export { R as RESET_REQUEST_TTL_MS, a as ResetRequest, b as ResetStore } from './reset-state-D6UslXaj.js';
|
|
6
6
|
import '@sqlite.org/sqlite-wasm';
|
|
7
7
|
|
|
8
8
|
declare const dummyKysely: Kysely<any>;
|
|
9
9
|
|
|
10
|
+
type KvStoreItem = {
|
|
11
|
+
key: string;
|
|
12
|
+
value: string;
|
|
13
|
+
};
|
|
14
|
+
declare function createKvStoreTableQuery(schema: SchemaModule, tableName: string): kysely.CreateTableBuilder<string, "value" | "key">;
|
|
15
|
+
declare function createSQLiteKvStore({ db, metaTableName }: {
|
|
16
|
+
db: InternalSQLiteWrapper<any>;
|
|
17
|
+
metaTableName: string;
|
|
18
|
+
}): {
|
|
19
|
+
get: (key: string) => string | null;
|
|
20
|
+
set: (key: string, value: string) => void;
|
|
21
|
+
remove: (key: string) => void;
|
|
22
|
+
createStringStoredValue: (key: string, defaultValue: string) => StoredValue<string>;
|
|
23
|
+
createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A portable, schema-version-aware dump of every active entity in a synced DB.
|
|
28
|
+
* Unlike a raw SQLite snapshot, it carries no event history — just the current
|
|
29
|
+
* `tombstone = 0` rows, ready to be replayed as fresh create events on import.
|
|
30
|
+
*/
|
|
31
|
+
type SyncedDbExport = {
|
|
32
|
+
schemaVersion: number;
|
|
33
|
+
exportedAt: string;
|
|
34
|
+
/** crdt table name -> active rows (each includes `id`, excludes `tombstone`). */
|
|
35
|
+
tables: Record<string, Array<Record<string, unknown>>>;
|
|
36
|
+
};
|
|
37
|
+
type ExportImportReactiveDb = {
|
|
38
|
+
db: {
|
|
39
|
+
execute<T>(sql: string, meta: {
|
|
40
|
+
loggerLevel: "system";
|
|
41
|
+
}): ExecuteResult<T>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
type CreateExportImportOptions = {
|
|
45
|
+
reactiveDb: ExportImportReactiveDb;
|
|
46
|
+
crdtStorage: CrdtStorage;
|
|
47
|
+
tablesConfig: CrdtTableConfig[];
|
|
48
|
+
schemaVersion: number;
|
|
49
|
+
};
|
|
50
|
+
declare function createExportImport({ reactiveDb, crdtStorage, tablesConfig, schemaVersion, }: CreateExportImportOptions): {
|
|
51
|
+
exportData: (opts?: {
|
|
52
|
+
tables?: string[];
|
|
53
|
+
}) => SyncedDbExport;
|
|
54
|
+
importData: (data: SyncedDbExport, opts?: {
|
|
55
|
+
validate?: boolean;
|
|
56
|
+
}) => {
|
|
57
|
+
imported: number;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
10
61
|
declare function ensureLoaded(): Promise<void>;
|
|
11
62
|
declare function h64(input: string, seed?: bigint): bigint;
|
|
12
63
|
declare const xxhash: {
|
|
@@ -89,22 +140,6 @@ declare class SQLiteReactiveDb<Database> {
|
|
|
89
140
|
}
|
|
90
141
|
declare function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean;
|
|
91
142
|
|
|
92
|
-
type KvStoreItem = {
|
|
93
|
-
key: string;
|
|
94
|
-
value: string;
|
|
95
|
-
};
|
|
96
|
-
declare function createKvStoreTableQuery(schema: SchemaModule, tableName: string): kysely.CreateTableBuilder<string, "key" | "value">;
|
|
97
|
-
declare function createSQLiteKvStore({ db, metaTableName }: {
|
|
98
|
-
db: InternalSQLiteWrapper<any>;
|
|
99
|
-
metaTableName: string;
|
|
100
|
-
}): {
|
|
101
|
-
get: (key: string) => string | null;
|
|
102
|
-
set: (key: string, value: string) => void;
|
|
103
|
-
remove: (key: string) => void;
|
|
104
|
-
createStringStoredValue: (key: string, defaultValue: string) => StoredValue<string>;
|
|
105
|
-
createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
143
|
type Simplify<T> = {
|
|
109
144
|
[K in keyof T]: T[K];
|
|
110
145
|
} & {};
|
|
@@ -287,6 +322,14 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
|
|
|
287
322
|
}[K]>) => void) => {
|
|
288
323
|
unsubscribe: () => void;
|
|
289
324
|
};
|
|
325
|
+
exportData: (opts?: {
|
|
326
|
+
tables?: string[];
|
|
327
|
+
}) => SyncedDbExport;
|
|
328
|
+
importData: (data: SyncedDbExport, opts?: {
|
|
329
|
+
validate?: boolean;
|
|
330
|
+
}) => {
|
|
331
|
+
imported: number;
|
|
332
|
+
};
|
|
290
333
|
dispose: () => Promise<void>;
|
|
291
334
|
_internal: {
|
|
292
335
|
executeAsync: (query: ExecuteParams) => Promise<ExecuteResult<unknown>>;
|
|
@@ -303,4 +346,4 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
|
|
|
303
346
|
}>;
|
|
304
347
|
type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;
|
|
305
348
|
|
|
306
|
-
export { AnyTableBuilder, CrdtEventValidationError, CrdtStorage, type CrdtStorageMutator, CrdtTableConfig, type DefineSyncSchemaConfig, type DefinedSyncSchema, ExecuteParams, ExecuteResult, InferRow, InternalSQLiteWrapper, type KvStoreItem, KyselyQueryFactory, Logger, Migrations, type NewCrdtEventValidationResult, QueryBuilderOutput, ReadonlyTable, SQLiteDbWrapper, SQLiteReactiveDb, SQLiteTransactionWrapper, type SchemaVerificationIssue, type SharedLiveQuery, type SharedLiveQuerySnapshot, StoredValue, SyncDbSchema, SyncSchemaTables, type SyncedDb, TableBuilder, TableColumns, TypedEvent, WorkerState, createCrdtStorageMutator, createCrdtSyncProducer, createKvStoreTableQuery, createSQLiteKvStore, createSyncedDb, defineSyncSchema, dummyKysely, formatSchemaVerificationIssues, makeCrdtTable, parametersAreEqual, validateNewCrdtEvent, verifySyncSchema, xxhash };
|
|
349
|
+
export { AnyTableBuilder, CrdtEventValidationError, CrdtStorage, type CrdtStorageMutator, CrdtTableConfig, type DefineSyncSchemaConfig, type DefinedSyncSchema, ExecuteParams, ExecuteResult, InferRow, InternalSQLiteWrapper, type KvStoreItem, KyselyQueryFactory, Logger, Migrations, type NewCrdtEventValidationResult, QueryBuilderOutput, ReadonlyTable, SQLiteDbWrapper, SQLiteReactiveDb, SQLiteTransactionWrapper, type SchemaVerificationIssue, type SharedLiveQuery, type SharedLiveQuerySnapshot, StoredValue, SyncDbSchema, SyncSchemaTables, type SyncedDb, type SyncedDbExport, TableBuilder, TableColumns, TypedEvent, WorkerState, createCrdtStorageMutator, createCrdtSyncProducer, createExportImport, createKvStoreTableQuery, createSQLiteKvStore, createSyncedDb, defineSyncSchema, dummyKysely, formatSchemaVerificationIssues, makeCrdtTable, parametersAreEqual, validateNewCrdtEvent, verifySyncSchema, xxhash };
|
package/dist/index.js
CHANGED
|
@@ -50,6 +50,63 @@ import {
|
|
|
50
50
|
tryCatchAsync
|
|
51
51
|
} from "./chunk-NHT3ELMN.js";
|
|
52
52
|
|
|
53
|
+
// src/export-import.ts
|
|
54
|
+
function createExportImport({
|
|
55
|
+
reactiveDb,
|
|
56
|
+
crdtStorage,
|
|
57
|
+
tablesConfig,
|
|
58
|
+
schemaVersion
|
|
59
|
+
}) {
|
|
60
|
+
const crdtTableNames = tablesConfig.map((config) => config.crdtTableName);
|
|
61
|
+
const resolveTables = (requested) => {
|
|
62
|
+
if (!requested) {
|
|
63
|
+
return crdtTableNames;
|
|
64
|
+
}
|
|
65
|
+
for (const name of requested) {
|
|
66
|
+
if (!crdtTableNames.includes(name)) {
|
|
67
|
+
throw new Error(`Unknown table "${name}". Known synced tables: ${crdtTableNames.join(", ")}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return requested;
|
|
71
|
+
};
|
|
72
|
+
const exportData = (opts) => {
|
|
73
|
+
const tables = {};
|
|
74
|
+
for (const crdtTableName of resolveTables(opts?.tables)) {
|
|
75
|
+
const { rows } = reactiveDb.db.execute(`select * from ${quoteId(crdtTableName)}`, {
|
|
76
|
+
loggerLevel: "system"
|
|
77
|
+
});
|
|
78
|
+
tables[crdtTableName] = rows.map(({ tombstone: _tombstone, ...rest }) => rest);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
schemaVersion,
|
|
82
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83
|
+
tables
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
const importData = (data, opts) => {
|
|
87
|
+
const validate = opts?.validate ?? true;
|
|
88
|
+
if (validate && data.schemaVersion !== schemaVersion) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Cannot import data from schema version ${data.schemaVersion} into a database at schema version ${schemaVersion}.`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const events = [];
|
|
94
|
+
for (const [crdtTableName, rows] of Object.entries(data.tables)) {
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
events.push({
|
|
97
|
+
type: "item-created",
|
|
98
|
+
dataset: crdtTableName,
|
|
99
|
+
item_id: row.id,
|
|
100
|
+
payload: JSON.stringify(row)
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
crdtStorage.applyOwnEvents(events);
|
|
105
|
+
return { imported: events.length };
|
|
106
|
+
};
|
|
107
|
+
return { exportData, importData };
|
|
108
|
+
}
|
|
109
|
+
|
|
53
110
|
// src/memory-db/sqlite-reactive-db.ts
|
|
54
111
|
import sqlite3InitModule from "@sqlite.org/sqlite-wasm";
|
|
55
112
|
|
|
@@ -1186,6 +1243,12 @@ async function createSyncedDb(options) {
|
|
|
1186
1243
|
globalThis.location?.reload();
|
|
1187
1244
|
});
|
|
1188
1245
|
perf.logEnd("createSyncedDb", "initialized", "info");
|
|
1246
|
+
const { exportData, importData } = createExportImport({
|
|
1247
|
+
reactiveDb,
|
|
1248
|
+
crdtStorage,
|
|
1249
|
+
tablesConfig: options.syncDbSchema.tablesConfig,
|
|
1250
|
+
schemaVersion: workerClientSnapshot.schemaVersion
|
|
1251
|
+
});
|
|
1189
1252
|
let isDisposed = false;
|
|
1190
1253
|
let unregisterDevtools;
|
|
1191
1254
|
const dispose = async () => {
|
|
@@ -1233,6 +1296,8 @@ async function createSyncedDb(options) {
|
|
|
1233
1296
|
setTimeout(() => globalThis.location?.reload(), 250);
|
|
1234
1297
|
},
|
|
1235
1298
|
subscribe: workerClient.subscribe,
|
|
1299
|
+
exportData,
|
|
1300
|
+
importData,
|
|
1236
1301
|
dispose,
|
|
1237
1302
|
_internal: {
|
|
1238
1303
|
executeAsync: workerClient.execute.bind(workerClient),
|
|
@@ -1273,6 +1338,7 @@ export {
|
|
|
1273
1338
|
createCrdtSyncProducer,
|
|
1274
1339
|
createCrdtSyncRemoteSource,
|
|
1275
1340
|
createDeferredPromise,
|
|
1341
|
+
createExportImport,
|
|
1276
1342
|
createKvStoreTableQuery,
|
|
1277
1343
|
createMigrations,
|
|
1278
1344
|
createMigrator,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/memory-db/sqlite-reactive-db.ts","../src/bound-map.ts","../src/schema/define-sync-schema.ts","../src/schema/table-builder.ts","../src/sqlite-crdt/crdt-storage-mutator.ts","../src/sqlite-crdt/make-crdt-table.ts","../src/db-id.ts","../src/devtools-registry.ts","../src/memory-db/memory-db.ts","../src/worker-db/db-worker-client.ts","../src/sync-db.ts"],"sourcesContent":["import sqlite3InitModule, { type Sqlite3Static } from \"@sqlite.org/sqlite-wasm\";\nimport { BoundMap } from \"../bound-map\";\nimport { type Logger, startPerformanceLogger } from \"../logger\";\nimport { type PreparedStatement, SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createTypedEventTarget, type TypedEvent } from \"../utils\";\n\nlet sqliteModule: Sqlite3Static | null = null;\n\ntype TableName<Database> = keyof Database extends string ? keyof Database : never;\n\ntype SQLiteReactiveDbOptions = {\n snapshot: Uint8Array<ArrayBufferLike>;\n logger: Logger;\n};\n\ntype EventsMap = {\n \"transaction-committed\": undefined;\n \"transaction-rolled-back\": undefined;\n \"any-table-changed\": undefined;\n} & Record<`table:${string}`, void>;\n\ntype LiveQuery<TResult> = {\n getRows: () => TResult[];\n refresh: () => void;\n subscribe: (onchange: () => void) => () => void;\n};\n\nexport type SharedLiveQuery<TResult> = LiveQuery<TResult> & {\n readonly sql: string;\n readonly parameters: readonly unknown[];\n getSubscriberCount: () => number;\n};\n\ntype SharedLiveQueryEntry<TResult> = SharedLiveQuery<TResult> & {\n listeners: Set<() => void>;\n unsubscribeFromLiveQuery: (() => void) | null;\n cleanupTimeout: ReturnType<typeof setTimeout> | null;\n};\n\nexport type SharedLiveQuerySnapshot = {\n sql: string;\n parameters: readonly unknown[];\n subscriberCount: number;\n};\n\nexport function createSQLiteReactiveDb<Database>(opts: SQLiteReactiveDbOptions) {\n return SQLiteReactiveDb.create<Database>(opts);\n}\n\nexport class SQLiteReactiveDb<Database> {\n readonly db: SQLiteDbWrapper<Database>;\n private sqlite3: Sqlite3Static;\n\n private readonly logger: Logger;\n\n private tablesUsedStatement: PreparedStatement<[string], { name: string; isWrite: boolean }> | null = null;\n\n private eventTarget = createTypedEventTarget<EventsMap>();\n\n private constructor(sqlite3: Sqlite3Static, logger: Logger) {\n this.sqlite3 = sqlite3;\n this.logger = logger;\n\n this.db = new SQLiteDbWrapper({\n db: () => new sqlite3.oo1.DB({ filename: \":memory:\" }),\n logger: this.logger,\n loggerPrefix: \"memory\",\n sqlite3,\n });\n }\n\n static async create<Database>(opts: SQLiteReactiveDbOptions) {\n const logger = opts.logger;\n const perf = startPerformanceLogger(logger);\n if (!sqliteModule) {\n sqliteModule = await sqlite3InitModule();\n }\n\n const db = new SQLiteReactiveDb<Database>(sqliteModule, logger);\n\n if (opts.snapshot) {\n db.useSnapshot(opts.snapshot);\n }\n db.registerDbHooks();\n\n perf.logEnd(\"createSQLiteMemoryDb\", \"success\", \"system\");\n\n return db;\n }\n\n private liveQueryStatements = new BoundMap<string, PreparedStatement<any[], unknown>>({\n maxSize: 100,\n onRemove(_, value) {\n value.finalize();\n },\n });\n\n private sharedLiveQueries = new Map<string, SharedLiveQueryEntry<unknown>[]>();\n\n createLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const fetchRows = (parameters: readonly unknown[]) => {\n let statement = this.liveQueryStatements.get(query.sql);\n if (!statement) {\n statement = this.db.prepare<any[], any>(query.sql);\n this.liveQueryStatements.set(query.sql, statement);\n }\n return statement.execute(parameters as any) as TResult[];\n };\n\n let rows: TResult[] | null = null;\n\n const getRows = () => {\n if (!rows) {\n rows = fetchRows(query.parameters);\n }\n return rows;\n };\n\n let subscriber: (() => void) | null = null;\n\n let lastParameters: readonly unknown[] = query.parameters;\n const refresh = (parameters?: readonly unknown[]) => {\n if (parameters) {\n lastParameters = parameters;\n }\n rows = fetchRows(lastParameters);\n subscriber?.();\n };\n\n const subscribe = (onchange: () => void) => {\n if (subscriber) {\n throw new Error(\"Subscriber already exists\");\n }\n\n subscriber = onchange;\n const subscription = this.subscribeToQueryChanges({\n sql: query.sql,\n onDataChange: refresh,\n });\n\n return () => {\n subscription.unsubscribe();\n subscriber = null;\n };\n };\n\n return { getRows, refresh, subscribe };\n }\n\n getSharedLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const existingEntry = this.sharedLiveQueries\n .get(query.sql)\n ?.find((entry) => parametersAreEqual(entry.parameters, query.parameters));\n if (existingEntry) {\n if (existingEntry.listeners.size === 0) {\n this.scheduleSharedLiveQueryCleanup(existingEntry);\n }\n return existingEntry as SharedLiveQuery<TResult>;\n }\n\n const liveQuery = this.createLiveQuery<TResult>(query);\n let hasDetachedFromLiveQuery = false;\n const entry: SharedLiveQueryEntry<TResult> = {\n sql: query.sql,\n parameters: query.parameters,\n listeners: new Set(),\n unsubscribeFromLiveQuery: null,\n cleanupTimeout: null,\n getRows: () => liveQuery.getRows(),\n refresh: () => {\n liveQuery.refresh();\n },\n getSubscriberCount: () => entry.listeners.size,\n subscribe: (onchange) => {\n this.cancelSharedLiveQueryCleanup(entry);\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n entry.listeners.add(onchange);\n\n if (!entry.unsubscribeFromLiveQuery) {\n entry.unsubscribeFromLiveQuery = liveQuery.subscribe(() => {\n for (const listener of entry.listeners) {\n listener();\n }\n });\n\n // Rows may have gone stale while no subscriber was listening\n // for table changes.\n if (hasDetachedFromLiveQuery) {\n hasDetachedFromLiveQuery = false;\n liveQuery.refresh();\n }\n }\n\n return () => {\n entry.listeners.delete(onchange);\n\n if (entry.listeners.size === 0) {\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n hasDetachedFromLiveQuery = true;\n this.scheduleSharedLiveQueryCleanup(entry);\n }\n };\n },\n };\n\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n\n // Evict the entry if no subscriber attaches by the next tick.\n this.scheduleSharedLiveQueryCleanup(entry as SharedLiveQueryEntry<unknown>);\n\n return entry;\n }\n\n private registerSharedLiveQueryEntry(entry: SharedLiveQueryEntry<unknown>) {\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql) ?? [];\n if (!matchingSqlEntries.includes(entry)) {\n matchingSqlEntries.push(entry);\n this.sharedLiveQueries.set(entry.sql, matchingSqlEntries);\n }\n }\n\n getSharedLiveQueriesSnapshot(): SharedLiveQuerySnapshot[] {\n const snapshot: SharedLiveQuerySnapshot[] = [];\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n snapshot.push({\n sql: entry.sql,\n parameters: entry.parameters,\n subscriberCount: entry.listeners.size,\n });\n }\n }\n return snapshot;\n }\n\n private scheduleSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.cleanupTimeout = setTimeout(() => {\n entry.cleanupTimeout = null;\n this.releaseSharedLiveQuery(entry);\n }, 0);\n }\n\n private cancelSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.cleanupTimeout) {\n clearTimeout(entry.cleanupTimeout);\n entry.cleanupTimeout = null;\n }\n }\n\n private releaseSharedLiveQuery(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.listeners.size > 0 || entry.unsubscribeFromLiveQuery) {\n return;\n }\n\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql);\n if (!matchingSqlEntries) {\n return;\n }\n\n const nextEntries = matchingSqlEntries.filter((candidate) => candidate !== entry);\n if (nextEntries.length > 0) {\n this.sharedLiveQueries.set(entry.sql, nextEntries);\n } else {\n this.sharedLiveQueries.delete(entry.sql);\n }\n }\n\n subscribeToQueryChanges(params: { sql: string; onDataChange: () => void }) {\n const { sql, onDataChange } = params;\n\n const tables = this.getTablesUsed(sql);\n const readTables = new Set<string>();\n for (const table of tables) {\n if (!readTables.has(table.name)) {\n readTables.add(table.name);\n } else if (table.isWrite) {\n throw new Error(\"This query writes and reads from the same table. This may cause infinite loops.\");\n }\n }\n\n const notifyDataChange = createDebouncedCallback(() => {\n onDataChange();\n }, 30);\n\n for (const table of readTables) {\n this.eventTarget.addEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.addEventListener(\"any-table-changed\", notifyDataChange);\n\n return {\n unsubscribe: () => {\n for (const table of readTables) {\n this.eventTarget.removeEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.removeEventListener(\"any-table-changed\", notifyDataChange);\n },\n };\n }\n\n subscribeToTableChanges(table: string, onChanges: () => void) {\n this.eventTarget.addEventListener(`table:${table}`, onChanges);\n this.eventTarget.addEventListener(\"any-table-changed\", onChanges);\n return {\n unsubscribe: () => {\n this.eventTarget.removeEventListener(`table:${table}`, onChanges);\n this.eventTarget.removeEventListener(\"any-table-changed\", onChanges);\n },\n };\n }\n\n getTablesUsed(query: string) {\n if (!this.tablesUsedStatement) {\n this.tablesUsedStatement = this.db.prepare<[string], { name: string; isWrite: boolean }>(\n \"select t.tbl_name as name, u.wr as isWrite from tables_used(?) as u inner join sqlite_master as t on t.name = u.name where u.schema = 'main'\",\n { loggerLevel: \"system\" },\n );\n }\n\n const tables = this.tablesUsedStatement.execute([query]);\n\n if (tables.length === 0 && query.toLowerCase().includes(\"delete\")) {\n // tables_used function does not work with delete queries that clear entire tables\n tables.push(...this.getClearedTables(query));\n }\n\n return tables;\n }\n\n private getClearedTables(query: string) {\n const operations = this.db.execute<{\n opcode: string;\n p1: number;\n p2: number;\n }>(`EXPLAIN ${query.split(\";\")[0]}`, { loggerLevel: \"system\" }).rows;\n\n const clearedTablesRootPages = new Set<number>();\n for (const operation of operations) {\n if (operation.opcode === \"Clear\" && operation.p2 === 0) {\n clearedTablesRootPages.add(operation.p1);\n }\n }\n\n if (clearedTablesRootPages.size === 0) {\n return [];\n }\n\n const tableNames = this.db.execute<{ name: string; isWrite: boolean }>(\n `select t.tbl_name as name, true as isWrite from sqlite_master as t where t.rootpage in (${Array.from(\n clearedTablesRootPages,\n ).join(\",\")})`,\n { loggerLevel: \"system\" },\n ).rows;\n\n return tableNames;\n }\n\n addEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.addEventListener(type, listener);\n }\n\n removeEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.removeEventListener(type, listener);\n }\n\n private notifyTableSubscribers(tables: (TableName<Database> | (string & {}))[] | Set<string> | null = null) {\n if (!tables) {\n this.eventTarget.dispatchEvent(\"any-table-changed\", undefined);\n return;\n }\n\n for (const table of tables) {\n this.eventTarget.dispatchEvent(`table:${table}`, undefined);\n }\n }\n\n private registerDbHooks() {\n let updateQueue = new Set<string>();\n\n this.sqlite3.capi.sqlite3_update_hook(\n this.db.ensureDb,\n (_ctx, _opId, _db, table) => {\n updateQueue.add(table);\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_rollback_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n updateQueue.clear();\n this.eventTarget.dispatchEvent(\"transaction-rolled-back\", undefined);\n\n return 0;\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_commit_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n const tables = updateQueue;\n updateQueue = new Set<string>();\n this.eventTarget.dispatchEvent(\"transaction-committed\", undefined);\n\n queueMicrotask(() => {\n this.notifyTableSubscribers(tables);\n });\n return 0;\n },\n 0,\n );\n }\n\n createSnapshot() {\n const perf = startPerformanceLogger(this.logger);\n const snapshot = this.sqlite3.capi.sqlite3_js_db_export(this.db.ensureDb);\n perf.logEnd(\"createSnapshot\", `snapshot size: ${snapshot.byteLength}`, \"info\");\n\n return snapshot;\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n this.db.useSnapshot(snapshot);\n this.notifyTableSubscribers();\n }\n\n dispose() {\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n entry.listeners.clear();\n }\n }\n this.sharedLiveQueries.clear();\n this.liveQueryStatements.clear();\n if (this.tablesUsedStatement) {\n this.tablesUsedStatement.finalize();\n this.tablesUsedStatement = null;\n }\n this.db.close();\n }\n}\n\nfunction createDebouncedCallback<TArgs extends unknown[]>(callback: (...args: TArgs) => void, delay: number) {\n let timeout: unknown | null = null;\n let shouldCallWithoutDelay = true;\n\n return (...args: TArgs) => {\n if (shouldCallWithoutDelay) {\n callback(...args);\n shouldCallWithoutDelay = false;\n return;\n }\n\n const effect = () => {\n timeout = null;\n shouldCallWithoutDelay = true;\n return callback(...args);\n };\n\n if (timeout) {\n clearTimeout(timeout as any);\n }\n\n timeout = setTimeout(effect, delay);\n };\n}\n\nexport function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) {\n return false;\n }\n }\n return true;\n}\n","interface BoundMapOptions<K, V> {\n maxSize: number;\n onRemove: ((key: K, value: V) => void) | undefined;\n}\n\nexport class BoundMap<K, V> {\n private map = new Map<K, V>();\n private maxSize: number;\n private onRemove: ((key: K, value: V) => void) | undefined;\n\n constructor(opts: BoundMapOptions<K, V>) {\n this.maxSize = opts.maxSize;\n this.onRemove = opts.onRemove;\n }\n\n set = (key: K, value: V) => {\n if (this.onRemove && this.map.has(key)) {\n const old = this.map.get(key) as V;\n this.map.set(key, value);\n this.onRemove(key, old);\n } else {\n this.map.set(key, value);\n }\n if (this.map.size > this.maxSize) {\n const firstKey = this.map.keys().next().value as K;\n this.delete(firstKey);\n }\n };\n\n get = (key: K): V | undefined => {\n return this.map.get(key);\n };\n\n delete = (key: K) => {\n if (this.onRemove && this.map.has(key)) {\n const value = this.map.get(key) as V;\n this.map.delete(key);\n this.onRemove(key, value);\n } else {\n this.map.delete(key);\n }\n };\n\n clear = () => {\n const onRemove = this.onRemove;\n if (onRemove) {\n this.map.forEach((value, key) => {\n onRemove(key, value);\n });\n }\n this.map.clear();\n };\n}\n","import type { Migrations } from \"../migrations/migrator\";\nimport type { CrdtTableConfig, ReadonlyTable, SyncDbSchema } from \"../sqlite-crdt/crdt-schema\";\nimport type { AnyTableBuilder, InferRow, SyncSchemaTables, TableBuilder, TableColumns } from \"./table-builder\";\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\ntype RowOf<Table extends AnyTableBuilder> =\n Table extends TableBuilder<infer Cols extends TableColumns, any> ? InferRow<Cols> : never;\n\n// Falls back to the \"_\" convention unless ~baseName is a string *literal* — inference can\n// resolve an omitted override to its constraint (string | undefined) rather than undefined.\ntype BaseNameOf<CrdtName, Table extends AnyTableBuilder> = string extends Table[\"~baseName\"]\n ? `_${CrdtName & string}`\n : [Table[\"~baseName\"]] extends [string]\n ? Table[\"~baseName\"]\n : `_${CrdtName & string}`;\n\ntype ClientSchemaOf<Tables extends SyncSchemaTables> = Simplify<\n { [K in keyof Tables]: RowOf<Tables[K]> } & {\n [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>;\n }\n>;\n\ntype ServerSchemaOf<Tables extends SyncSchemaTables> = Simplify<\n { [K in keyof Tables]: ReadonlyTable<RowOf<Tables[K]>> } & {\n [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>;\n }\n>;\n\ntype MutationsSchemaOf<Tables extends SyncSchemaTables> = Simplify<{\n [K in keyof Tables as BaseNameOf<K, Tables[K]>]: RowOf<Tables[K]>;\n}>;\n\nexport interface DefinedSyncSchema<Tables extends SyncSchemaTables>\n extends SyncDbSchema<ClientSchemaOf<Tables>, ServerSchemaOf<Tables>, MutationsSchemaOf<Tables>> {\n /** The table builders, for type extraction (`typeof schema.tables.item.$row`) and runtime metadata. */\n tables: Tables;\n}\n\nexport type DefineSyncSchemaConfig<Tables extends SyncSchemaTables> = {\n tables: Tables;\n /** Full migration history (including the initial createTable version), built with `createMigrations`. */\n migrations: Migrations;\n};\n\n/**\n * Define a sync database schema from `t.table()` builders.\n *\n * Record keys are the crdt (view) table names; base table names default to the key\n * prefixed with \"_\", overridable per table via `t.table(cols, { baseName })`.\n */\nexport function defineSyncSchema<Tables extends SyncSchemaTables>({\n tables,\n migrations,\n}: DefineSyncSchemaConfig<Tables>): DefinedSyncSchema<Tables> {\n const tablesConfig: CrdtTableConfig[] = Object.entries(tables).map(([crdtTableName, table]) => ({\n crdtTableName,\n baseTableName: table.baseName ?? `_${crdtTableName}`,\n }));\n\n const seenNames = new Set<string>();\n for (const { crdtTableName, baseTableName } of tablesConfig) {\n for (const name of [crdtTableName, baseTableName]) {\n if (seenNames.has(name)) {\n throw new Error(`Duplicate table name \"${name}\" in sync schema`);\n }\n seenNames.add(name);\n }\n }\n\n return {\n tables,\n get tablesConfig() {\n return tablesConfig;\n },\n get migrations() {\n return migrations;\n },\n get \"~clientSchema\"(): never {\n throw new Error(\"~clientSchema is type-only and cannot be accessed at runtime\");\n },\n get \"~serverSchema\"(): never {\n throw new Error(\"~serverSchema is type-only and cannot be accessed at runtime\");\n },\n get \"~mutationsSchema\"(): never {\n throw new Error(\"~mutationsSchema is type-only and cannot be accessed at runtime\");\n },\n };\n}\n","export type ColumnKind = \"text\" | \"integer\" | \"real\" | \"boolean\" | \"enum\";\n\nexport type SqliteStorageType = \"text\" | \"integer\" | \"real\";\n\nexport type ColumnMeta = {\n kind: ColumnKind;\n /** Storage type used in generated DDL. Booleans store as integer 0/1. */\n sqlType: SqliteStorageType;\n nullable: boolean;\n hasDefault: boolean;\n /** Declared default in JS form (booleans as booleans). */\n defaultValue?: unknown;\n /** Allowed values for `enum` columns. */\n enumValues?: readonly string[];\n description?: string;\n};\n\nexport class ColumnBuilder<Value, HasDefault extends boolean = false> {\n declare readonly \"~types\": { value: Value; hasDefault: HasDefault };\n\n constructor(readonly meta: ColumnMeta) {}\n\n /** Allow SQL NULL; widens the value type with `null`. */\n nullable(): ColumnBuilder<Value | null, HasDefault> {\n return new ColumnBuilder({ ...this.meta, nullable: true });\n }\n\n /** Declare a column default. The value is used both in DDL and when migrating older events. */\n default(value: Value): ColumnBuilder<Value, true> {\n return new ColumnBuilder({ ...this.meta, hasDefault: true, defaultValue: value });\n }\n\n /** Narrow the TypeScript value type without changing storage, e.g. `t.text().$type<\"movie\" | \"tv\">()`. */\n $type<Narrowed extends Value>(): ColumnBuilder<Narrowed, HasDefault> {\n return this as unknown as ColumnBuilder<Narrowed, HasDefault>;\n }\n\n /** Human/AI-readable description, surfaced in generated schema docs. */\n describe(description: string): ColumnBuilder<Value, HasDefault> {\n return new ColumnBuilder({ ...this.meta, description });\n }\n}\n\nexport type AnyColumnBuilder = ColumnBuilder<any, boolean>;\n\nexport type TableColumns = Record<string, AnyColumnBuilder>;\n\nexport type AnyTableBuilder = TableBuilder<any, any>;\n\nexport type SyncSchemaTables = Record<string, AnyTableBuilder>;\n\nexport type TableOptions<BaseName extends string | undefined = string | undefined> = {\n /** Override the materialized base table name (defaults to the crdt table name prefixed with \"_\"). */\n baseName?: BaseName;\n description?: string;\n};\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\ntype ColumnValue<Column> = Column extends ColumnBuilder<infer Value, boolean> ? Value : never;\n\nexport type InferRow<Cols extends TableColumns> = Simplify<\n { id: string } & { [K in keyof Cols]: ColumnValue<Cols[K]> } & { tombstone?: boolean }\n>;\n\nexport type PayloadValidationResult = { success: true } | { success: false; errors: string[] };\n\nconst RESERVED_COLUMNS = [\"id\", \"tombstone\"] as const;\n\nconst idColumnMeta: ColumnMeta = {\n kind: \"text\",\n sqlType: \"text\",\n nullable: false,\n hasDefault: false,\n description: \"Unique immutable item id\",\n};\n\nconst tombstoneColumnMeta: ColumnMeta = {\n kind: \"boolean\",\n sqlType: \"integer\",\n nullable: false,\n hasDefault: true,\n defaultValue: false,\n description: \"Soft-delete marker\",\n};\n\nexport class TableBuilder<Cols extends TableColumns, BaseName extends string | undefined = undefined> {\n declare readonly \"~baseName\": BaseName;\n\n /** All columns in DDL order, including the auto-injected `id` and `tombstone`. */\n readonly columns: Record<string, ColumnMeta>;\n readonly baseName: BaseName;\n readonly description: string | undefined;\n\n constructor(\n readonly userColumns: Cols,\n options?: TableOptions<BaseName>,\n ) {\n for (const reserved of RESERVED_COLUMNS) {\n if (reserved in userColumns) {\n throw new Error(`Column \"${reserved}\" is added automatically to every synced table and cannot be declared`);\n }\n }\n\n this.columns = {\n id: idColumnMeta,\n ...Object.fromEntries(Object.entries(userColumns).map(([name, column]) => [name, column.meta])),\n tombstone: tombstoneColumnMeta,\n };\n this.baseName = options?.baseName as BaseName;\n this.description = options?.description;\n }\n\n describe(description: string): TableBuilder<Cols, BaseName> {\n return new TableBuilder(this.userColumns, { baseName: this.baseName, description });\n }\n\n /** Type-only: the row shape returned by queries. Do not access at runtime. */\n get $row(): InferRow<Cols> {\n return null as never;\n }\n\n /**\n * Validate a CRDT event payload against the declared columns.\n * `item-created` payloads must contain every column without a default (nullable columns may be omitted);\n * `item-updated` payloads are partial and must not touch `id` or set `tombstone` to a deleted value.\n */\n validatePayload(\n payload: Record<string, unknown>,\n options?: { event?: \"item-created\" | \"item-updated\" },\n ): PayloadValidationResult {\n const event = options?.event ?? \"item-created\";\n const errors: string[] = [];\n\n for (const key of Object.keys(payload)) {\n if (!(key in this.columns)) {\n errors.push(`Unknown column \"${key}\"`);\n }\n }\n\n if (event === \"item-updated\") {\n if (\"id\" in payload) {\n errors.push(`Column \"id\" is immutable and cannot appear in an update payload`);\n }\n if (payload.tombstone === true || payload.tombstone === 1) {\n errors.push(`Column \"tombstone\" cannot be set to true/1 in an update payload; use an item-deleted event`);\n }\n }\n\n if (event === \"item-created\") {\n for (const [name, meta] of Object.entries(this.columns)) {\n if (name in payload || name === \"tombstone\" || meta.nullable || meta.hasDefault) {\n continue;\n }\n errors.push(`Missing required column \"${name}\"`);\n }\n }\n\n for (const [name, value] of Object.entries(payload)) {\n const meta = this.columns[name];\n if (!meta || (event === \"item-updated\" && name === \"id\")) {\n continue;\n }\n const error = validateValue(name, value, meta);\n if (error) {\n errors.push(error);\n }\n }\n\n return errors.length === 0 ? { success: true } : { success: false, errors };\n }\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"array\";\n return typeof value;\n}\n\nfunction validateValue(name: string, value: unknown, meta: ColumnMeta): string | null {\n if (value === null) {\n return meta.nullable ? null : `Column \"${name}\" is not nullable, got null`;\n }\n\n switch (meta.kind) {\n case \"text\":\n return typeof value === \"string\" ? null : `Column \"${name}\" expects text, got ${describeValue(value)}`;\n case \"integer\":\n return typeof value === \"number\" && Number.isInteger(value)\n ? null\n : `Column \"${name}\" expects an integer, got ${describeValue(value)}`;\n case \"real\":\n return typeof value === \"number\" && Number.isFinite(value)\n ? null\n : `Column \"${name}\" expects a number, got ${describeValue(value)}`;\n case \"boolean\":\n return typeof value === \"boolean\" || value === 0 || value === 1\n ? null\n : `Column \"${name}\" expects a boolean (true/false or 0/1), got ${describeValue(value)}`;\n case \"enum\": {\n if (typeof value !== \"string\") {\n return `Column \"${name}\" expects one of ${formatEnumValues(meta)}, got ${describeValue(value)}`;\n }\n return meta.enumValues?.includes(value)\n ? null\n : `Column \"${name}\" expects one of ${formatEnumValues(meta)}, got \"${value}\"`;\n }\n }\n}\n\nfunction formatEnumValues(meta: ColumnMeta): string {\n return (meta.enumValues ?? []).map((value) => `\"${value}\"`).join(\" | \");\n}\n\nfunction column<Value>(kind: ColumnKind, sqlType: SqliteStorageType): ColumnBuilder<Value> {\n return new ColumnBuilder<Value>({ kind, sqlType, nullable: false, hasDefault: false });\n}\n\nexport const t = {\n text: () => column<string>(\"text\", \"text\"),\n integer: () => column<number>(\"integer\", \"integer\"),\n real: () => column<number>(\"real\", \"real\"),\n /** Stored as INTEGER 0/1; always bind booleans as 0/1 when writing raw SQL. */\n boolean: () => column<boolean>(\"boolean\", \"integer\"),\n /**\n * Union of string literals stored as TEXT, e.g. `t.enum([\"movie\", \"tv\"])`. Unlike `$type`, the\n * allowed values are kept as runtime metadata, so payloads are validated against them.\n * For an open-ended set, use `t.text().$type<\"idle\" | (string & {})>()` instead.\n */\n enum: <const Values extends readonly [string, ...string[]]>(values: Values) =>\n new ColumnBuilder<Values[number]>({\n kind: \"enum\",\n sqlType: \"text\",\n nullable: false,\n hasDefault: false,\n enumValues: values,\n }),\n table: <Cols extends TableColumns, const BaseName extends string | undefined = undefined>(\n columns: Cols,\n options?: TableOptions<BaseName>,\n ) => new TableBuilder(columns, options),\n};\n","import type { CrdtStorage, OwnCrdtEvent } from \"./crdt-storage\";\n\nexport type CrdtStorageMutator<Database> = ReturnType<typeof createCrdtStorageMutator<Database>>;\n\ntype CommitEventOptions<Database, Table extends keyof Database & string> =\n | {\n type: \"item-created\";\n dataset: Table;\n item_id: string;\n payload: CreateEventPayload<Database, Table>;\n }\n | {\n type: \"item-updated\";\n dataset: Table;\n item_id: string;\n payload: UpdateEventPayload<Database, Table>;\n }\n | {\n type: \"item-deleted\";\n dataset: Table;\n item_id: string;\n };\n\ntype CreateEventPayload<Database, Table extends keyof Database> = Omit<Database[Table], \"tombstone\">;\ntype UpdateEventPayload<Database, Table extends keyof Database> = Omit<Partial<Database[Table]>, \"id\" | \"tombstone\">;\n\nexport function createCrdtStorageMutator<Database>({ storage }: { storage: CrdtStorage }) {\n const mapToStorageEvent = (event: CommitEventOptions<Database, keyof Database & string>): OwnCrdtEvent => {\n switch (event.type) {\n case \"item-created\":\n return {\n type: \"item-created\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-updated\":\n return {\n type: \"item-updated\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-deleted\":\n return {\n type: \"item-deleted\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: \"{}\",\n };\n }\n };\n\n const enqueueEvents = (events: CommitEventOptions<Database, keyof Database & string>[]) => {\n storage.enqueueOwnEvents(events.map(mapToStorageEvent));\n };\n\n const createEvent = <Table extends keyof Database & string>(event: CommitEventOptions<Database, Table>) => {\n return event;\n };\n\n const enqueueEvent = (event: CommitEventOptions<Database, keyof Database & string>) => {\n storage.enqueueOwnEvents([mapToStorageEvent(event)]);\n };\n\n return {\n enqueueEvents,\n createEvent,\n enqueueEvent,\n };\n}\n","import type { SQLiteReactiveDb } from \"../memory-db/sqlite-reactive-db\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { quoteId } from \"../utils\";\nimport type { InternalCrdtStorage } from \"./crdt-storage\";\n\nexport function makeCrdtTable({\n db,\n baseTableName,\n crdtTableName,\n}: {\n db: SQLiteDbWrapper<any>;\n baseTableName: string;\n crdtTableName: string;\n}) {\n const tableSchema = db.dbSchema[baseTableName];\n\n if (!tableSchema) {\n throw new Error(`Table ${baseTableName} not found`);\n }\n\n const columns = new Map(tableSchema.columns.map((c) => [c.name, c]));\n\n const idColumn = columns.get(\"id\");\n if (!idColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"id\" column. CRDT tables must have an \"id\" column to identify items.`,\n );\n }\n if (idColumn.dataType.toUpperCase() !== \"TEXT\") {\n throw new Error(\n `Table \"${baseTableName}\": \"id\" column must be of type TEXT, got \"${idColumn.dataType}\". CRDT item IDs are stored as strings.`,\n );\n }\n\n const tombstoneColumn = columns.get(\"tombstone\");\n if (!tombstoneColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"tombstone\" column. CRDT tables must have a \"tombstone\" INTEGER column for soft deletes.`,\n );\n }\n const tombstoneType = tombstoneColumn.dataType.toUpperCase();\n if (tombstoneType !== \"INTEGER\" && tombstoneType !== \"BOOLEAN\") {\n throw new Error(\n `Table \"${baseTableName}\": \"tombstone\" column must be of type INTEGER or BOOLEAN, got \"${tombstoneColumn.dataType}\". It is compared as 0/1 for soft deletes.`,\n );\n }\n\n db.execute(\n `\ncreate view ${quoteId(crdtTableName)} as\nselect * from ${quoteId(baseTableName)}\nwhere tombstone = 0;`,\n { loggerLevel: \"system\" },\n );\n\n const allColumnNames = tableSchema.columns.map((column) => column.name);\n\n const jsonPayload = (from: \"new\" | \"old\") =>\n `'{'||${allColumnNames.map((col) => `'\"${col}\":'||json_quote(${from}.${quoteId(col)})`).join(\"||','||\")}||'}'`;\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_created`)}\ninstead of insert on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_created('${baseTableName}', ${jsonPayload(\"new\")});\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_updated`)}\ninstead of update on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_updated(\n '${baseTableName}',\n ${jsonPayload(\"old\")},\n ${jsonPayload(\"new\")}\n);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_deleted`)}\ninstead of delete on ${quoteId(crdtTableName)}\nfor each row\nwhen old.tombstone = 0\nbegin\nselect handle_item_deleted('${baseTableName}', old.id);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n}\n\nexport function registerCrdtFunctions({\n reactiveDb,\n storage,\n}: {\n reactiveDb: SQLiteReactiveDb<any>;\n storage: InternalCrdtStorage;\n}) {\n let eventApplied = false;\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_created\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, payloadRaw: string) => {\n const payload = JSON.parse(payloadRaw) as { id: string };\n\n storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {\n type: \"item-created\",\n dataset,\n item_id: payload.id,\n payload: payloadRaw,\n });\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_updated\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, oldPayloadRaw: string, newPayloadRaw: string) => {\n if (oldPayloadRaw === newPayloadRaw) {\n return undefined;\n }\n\n const tableSchema = reactiveDb.db.dbSchema[dataset];\n\n if (!tableSchema?.columns) {\n throw new Error(`Schema not found for dataset: ${dataset}`);\n }\n\n const oldPayload = JSON.parse(oldPayloadRaw);\n const newPayload = JSON.parse(newPayloadRaw);\n\n let hasDiff = false;\n const updatePayload = {} as Record<string, unknown>;\n\n for (const column of tableSchema.columns) {\n const oldValue = oldPayload[column.name];\n const newValue = newPayload[column.name];\n if (oldValue === newValue) {\n continue;\n }\n\n if (column.name === \"id\") {\n throw new Error(\n `Cannot update the \"id\" column of an item. It is used to identify the item and must be immutable.`,\n );\n }\n\n hasDiff = true;\n updatePayload[column.name] = newValue;\n }\n\n if (!hasDiff) {\n return;\n }\n\n storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {\n type: \"item-updated\",\n dataset,\n item_id: oldPayload.id,\n payload: JSON.stringify(updatePayload),\n });\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_deleted\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, itemId: string) => {\n storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {\n type: \"item-deleted\",\n dataset,\n item_id: itemId,\n payload: \"{}\",\n });\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.addEventListener(\"transaction-committed\", () => {\n if (eventApplied) {\n eventApplied = false;\n void storage.internal.processEnqueuedEvents();\n }\n });\n\n reactiveDb.addEventListener(\"transaction-rolled-back\", () => {\n eventApplied = false;\n });\n}\n","const dbIdRegex = /^[a-zA-Z][a-zA-Z\\-0-9]{2,63}$/;\n\nexport function validateDbId(dbId: string) {\n if (!dbIdRegex.test(dbId)) {\n throw new Error(\"Invalid dbId. Must be between 3 and 64 characters long and start with a letter.\");\n }\n}\n","import type { SyncedDb } from \"./sync-db\";\n\nconst devtoolsRegistrySymbol = Symbol.for(\"@sqlite-sync/devtools\");\n\nexport type SQLiteSyncDevtoolsInstance = {\n instanceId: string;\n dbId: string;\n createdAt: number;\n instance: SyncedDb<any>;\n};\n\nexport type SQLiteSyncDevtoolsSnapshot = {\n instances: readonly SQLiteSyncDevtoolsInstance[];\n};\n\nexport type SQLiteSyncDevtoolsRegistry = {\n version: 1;\n instances: Map<string, SQLiteSyncDevtoolsInstance>;\n subscribe(listener: () => void): () => void;\n getSnapshot(): SQLiteSyncDevtoolsSnapshot;\n register(instance: SQLiteSyncDevtoolsInstance): () => void;\n};\n\ntype RegistryGlobal = typeof globalThis & {\n [key: symbol]: SQLiteSyncDevtoolsRegistry | undefined;\n};\n\nfunction createSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const instances = new Map<string, SQLiteSyncDevtoolsInstance>();\n const listeners = new Set<() => void>();\n let snapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n };\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n const updateSnapshot = () => {\n snapshot = {\n instances: Array.from(instances.values()),\n };\n notify();\n };\n\n return {\n version: 1,\n instances,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return snapshot;\n },\n register(instance) {\n instances.set(instance.instanceId, instance);\n updateSnapshot();\n\n let isUnregistered = false;\n return () => {\n if (isUnregistered) return;\n isUnregistered = true;\n\n if (!instances.delete(instance.instanceId)) return;\n updateSnapshot();\n };\n },\n };\n}\n\nexport function getOrCreateSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const registryGlobal = globalThis as RegistryGlobal;\n\n registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();\n\n return registryGlobal[devtoolsRegistrySymbol];\n}\n","import { xxhash } from \"../hash\";\nimport type { HLCCounter } from \"../hlc\";\nimport type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { applyMemoryDbSchema, type MemoryDbSchema, memoryDbConfig } from \"../migrations/system-schema\";\nimport type { CrdtTableConfig, SyncDbSchema } from \"../sqlite-crdt/crdt-schema\";\nimport { createCrdtStorage } from \"../sqlite-crdt/crdt-storage\";\nimport { makeCrdtTable, registerCrdtFunctions } from \"../sqlite-crdt/make-crdt-table\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { SQLiteReactiveDb } from \"./sqlite-reactive-db\";\n\ntype MemoryDbOptions<Database> = {\n nodeId: string;\n migrator: SyncDbMigrator;\n reactiveDb: SQLiteReactiveDb<Database>;\n hlcCounter: HLCCounter;\n crdtTables: CrdtTableConfig[];\n initializeSchema?: boolean;\n initialSyncId?: number;\n eventHlcAccumulator?: StoredValue<string>;\n syncDbSchema: Pick<SyncDbSchema, \"tables\" | \"tablesConfig\">;\n};\n\nexport async function createMemoryDb<Database>({\n nodeId,\n migrator,\n reactiveDb: _reactiveDb,\n hlcCounter,\n crdtTables,\n initializeSchema = true,\n initialSyncId,\n eventHlcAccumulator,\n syncDbSchema,\n}: MemoryDbOptions<Database>) {\n await xxhash.ensureLoaded();\n\n const reactiveDb = _reactiveDb as unknown as SQLiteReactiveDb<MemoryDbSchema>;\n const db = reactiveDb.db;\n\n if (initializeSchema) {\n applyMemoryDbSchema(db);\n for (const table of crdtTables) {\n makeCrdtTable({\n db,\n baseTableName: table.baseTableName,\n crdtTableName: table.crdtTableName,\n });\n }\n }\n\n const crdtStorage = createCrdtStorage({\n nodeId,\n initialLocalSyncId: initialSyncId ?? getCurrentSyncId(db),\n hlc: hlcCounter,\n migrator,\n db,\n dbConfig: memoryDbConfig,\n eventHlcAccumulator,\n schema: syncDbSchema,\n });\n\n registerCrdtFunctions({\n reactiveDb,\n storage: crdtStorage,\n });\n\n return {\n crdtStorage,\n };\n}\n\nfunction getCurrentSyncId(db: SQLiteDbWrapper<MemoryDbSchema>) {\n return (\n db.execute<{ syncId: number }>(\"SELECT coalesce(max(sync_id), 0) AS syncId FROM persisted_crdt_events\", {\n loggerLevel: \"system\",\n }).rows[0]?.syncId ?? 0\n );\n}\n","import {\n createDeferredPromise,\n createTypedEventTarget,\n type DeferredPromise,\n noop,\n type TypedEventTarget,\n} from \"../utils\";\nimport type {\n AsyncRpc,\n WorkerBroadcastChannels,\n WorkerConfig,\n WorkerErrorResponseMessage,\n WorkerInitMessage,\n WorkerNotificationMessage,\n WorkerRequestMessage,\n WorkerRequestMethod,\n WorkerResponseMessage,\n WorkerRpc,\n WorkerState,\n} from \"./worker-common\";\nimport { isWorkerErrorResponseMessage, isWorkerNotificationMessage, isWorkerResponseMessage } from \"./worker-common\";\n\ntype NotificationEvents = {\n [K in WorkerNotificationMessage[\"notificationType\"]]: Extract<WorkerNotificationMessage, { notificationType: K }>;\n};\n\nexport const createWorkerDbClient = async ({\n broadcastChannels,\n worker,\n config,\n}: {\n broadcastChannels: WorkerBroadcastChannels;\n worker: Worker;\n config: WorkerConfig;\n}) => {\n const eventTarget = createTypedEventTarget<NotificationEvents>();\n const workerRequestsMap = new Map<string, DeferredPromise<unknown>>();\n let isDisposed = false;\n\n const queryWorker = <TMethod extends WorkerRequestMethod>(\n method: TMethod,\n args: Parameters<WorkerRpc[TMethod]>,\n ): Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>> => {\n if (isDisposed) {\n return Promise.reject(new Error(\"Worker client disposed\"));\n }\n const requestId = crypto.randomUUID();\n const promise = createDeferredPromise<unknown>({\n timeout: 30_000,\n onTimeout: () => workerRequestsMap.delete(requestId),\n });\n workerRequestsMap.set(requestId, promise);\n\n const request: WorkerRequestMessage<TMethod> = {\n type: \"request\",\n requestId,\n method,\n args,\n };\n\n broadcastChannels.requests.postMessage(request);\n\n return promise.promise as Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>>;\n };\n\n const handleWorkerResponse = (message: WorkerResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.resolve(message.data);\n workerRequestsMap.delete(message.requestId);\n };\n\n const handleWorkerError = (message: WorkerErrorResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.reject(new Error(message.error));\n workerRequestsMap.delete(message.requestId);\n };\n\n broadcastChannels.responses.onmessage = (event) => {\n const message = event.data;\n\n if (isWorkerResponseMessage(message)) {\n handleWorkerResponse(message);\n } else if (isWorkerErrorResponseMessage(message)) {\n handleWorkerError(message);\n } else if (isWorkerNotificationMessage(message)) {\n eventTarget.dispatchEvent(message.notificationType, message);\n }\n };\n\n const rpc: AsyncRpc<WorkerRpc> = {\n execute: (query) => queryWorker(\"execute\", [query]),\n getSnapshot: () => queryWorker(\"getSnapshot\", []),\n pushTabEvents: (request) => queryWorker(\"pushTabEvents\", [request]),\n pullEvents: (params) => queryWorker(\"pullEvents\", [params]),\n postState: () => queryWorker(\"postState\", []),\n goOnline: () => queryWorker(\"goOnline\", []),\n goOffline: () => queryWorker(\"goOffline\", []),\n requestReload: (options) => queryWorker(\"requestReload\", [options]),\n };\n\n const statePromise = awaitWorkerState(eventTarget);\n postWorkerConfig(worker, config);\n // On first tab, the worker may not have its BroadcastChannel listener ready yet,\n // so this request can be silently dropped and timeout. The worker will independently\n // post state at the end of init. For subsequent tabs, this triggers the already-running\n // worker to send its current state.\n rpc.postState().catch(noop);\n\n let workerState = await statePromise;\n\n eventTarget.addEventListener(\"state-changed\", (event) => {\n workerState = event.payload.state;\n });\n\n const dispose = () => {\n isDisposed = true;\n broadcastChannels.responses.onmessage = null;\n for (const [id, deferred] of workerRequestsMap) {\n deferred.reject(new Error(\"Worker client disposed\"));\n workerRequestsMap.delete(id);\n }\n };\n\n return {\n ...rpc,\n subscribe: eventTarget.addEventListener,\n getState: () => workerState,\n dispose,\n };\n};\n\nfunction awaitWorkerState(eventTarget: TypedEventTarget<NotificationEvents>) {\n const promise = createDeferredPromise<WorkerState>({ timeout: 15_000 });\n\n const subscription = eventTarget.addEventListener(\"state-changed\", (event) => {\n promise.resolve(event.payload.state);\n subscription.unsubscribe();\n });\n\n return promise.promise;\n}\n\nfunction postWorkerConfig(worker: Worker, config: WorkerConfig) {\n const configMessage: WorkerInitMessage = {\n type: \"init\",\n config,\n };\n worker.postMessage(configMessage);\n}\n","import { validateDbId } from \"./db-id\";\nimport { getOrCreateSQLiteSyncDevtoolsRegistry } from \"./devtools-registry\";\nimport { HLCCounter } from \"./hlc\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\nimport { createMemoryDb } from \"./memory-db/memory-db\";\nimport { createSQLiteReactiveDb } from \"./memory-db/sqlite-reactive-db\";\nimport type { SyncDbMigrator } from \"./migrations/migrator\";\nimport type { SyncDbSchema } from \"./sqlite-crdt/crdt-schema\";\nimport { createCrdtSyncRemoteSource } from \"./sqlite-crdt/crdt-sync-remote-source\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport { createDeferredPromise, generateId } from \"./utils\";\nimport { createWorkerDbClient } from \"./worker-db/db-worker-client\";\nimport { createBroadcastChannels, syncDbClientLockName } from \"./worker-db/worker-common\";\n\ntype SyncedDbOptions<Database, Props = undefined> = {\n dbId: string;\n worker: Worker;\n workerProps: Props;\n syncDbSchema: SyncDbSchema<Database>;\n};\n\nconst defaultLogger: Logger = (type, message, level = \"info\") => {\n const logMessage = `[${type}] ${message}`;\n switch (level) {\n case \"info\":\n console.log(logMessage);\n break;\n case \"warning\":\n console.warn(logMessage);\n break;\n case \"error\":\n console.error(logMessage);\n break;\n case \"trace\":\n console.trace(logMessage);\n break;\n }\n};\n\nexport async function createSyncedDb<Database, Props = undefined>(options: SyncedDbOptions<Database, Props>) {\n validateDbId(options.dbId);\n\n const perf = startPerformanceLogger(defaultLogger);\n\n const instanceId = generateId();\n const tabId = generateId();\n\n const broadcastChannels = createBroadcastChannels(options.dbId);\n\n const clientLockAcquired = createDeferredPromise<void>();\n const clientLockRelease = createDeferredPromise<void>();\n navigator.locks.request(`${syncDbClientLockName}-${options.dbId}`, { mode: \"shared\" }, () => {\n clientLockAcquired.resolve();\n return clientLockRelease.promise;\n });\n await clientLockAcquired.promise;\n\n const workerClient = await createWorkerDbClient({\n worker: options.worker,\n config: {\n clientId: generateId(),\n dbId: options.dbId,\n props: options.workerProps as never,\n },\n broadcastChannels,\n });\n\n const hlcCounter = new HLCCounter(tabId, () => Date.now());\n\n const workerClientSnapshot = await workerClient.getSnapshot();\n const reactiveDb = await createSQLiteReactiveDb<Database>({\n snapshot: workerClientSnapshot.file,\n logger: defaultLogger,\n });\n\n const memoryDbMigrator: SyncDbMigrator = {\n currentSchemaVersion: workerClientSnapshot.schemaVersion,\n latestSchemaVersion: workerClientSnapshot.schemaVersion,\n migrateDbToLatest: () => {\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvent: (event, targetVersion) => {\n if (event.schema_version === targetVersion) {\n return event;\n }\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvents: (events) => events,\n };\n const { crdtStorage } = await createMemoryDb({\n nodeId: tabId,\n migrator: memoryDbMigrator,\n reactiveDb: reactiveDb,\n hlcCounter,\n crdtTables: options.syncDbSchema.tablesConfig,\n syncDbSchema: options.syncDbSchema,\n });\n\n const pullSyncId = createStoredValue({\n initialValue: workerClientSnapshot.syncId,\n });\n const pushSyncId = createStoredValue({\n initialValue: 0,\n });\n const tabRemoteSource = createCrdtSyncRemoteSource({\n bufferSize: 500,\n pullSyncId,\n pushSyncId,\n storage: crdtStorage,\n nodeId: tabId,\n migrator: memoryDbMigrator,\n remoteFactory: ({ onEventsAvailable }) => {\n const subscription = workerClient.subscribe(\"new-event-chunk-applied\", (event) => {\n onEventsAvailable({ newSyncId: event.payload.newSyncId, remoteEventHlcSum: event.payload.eventHlcSum });\n });\n\n return {\n pullEvents: (request) => workerClient.pullEvents(request),\n pushEvents: (request) => workerClient.pushTabEvents(request),\n disconnect: () => {\n subscription.unsubscribe();\n },\n };\n },\n });\n tabRemoteSource.goOnline();\n\n const reloadRequestedSubscription = workerClient.subscribe(\"reload-requested\", () => {\n globalThis.location?.reload();\n });\n\n perf.logEnd(\"createSyncedDb\", \"initialized\", \"info\");\n\n let isDisposed = false;\n let unregisterDevtools: (() => void) | undefined;\n const dispose = async () => {\n if (isDisposed) return;\n isDisposed = true;\n\n unregisterDevtools?.();\n reloadRequestedSubscription.unsubscribe();\n clientLockRelease.resolve();\n await tabRemoteSource.dispose();\n broadcastChannels.requests.close();\n broadcastChannels.responses.close();\n workerClient.dispose();\n reactiveDb.dispose();\n };\n\n const syncedDb = {\n db: {\n execute: reactiveDb.db.execute.bind(reactiveDb.db),\n executeKysely: reactiveDb.db.executeKysely.bind(reactiveDb.db),\n executeTransaction: reactiveDb.db.executeTransaction.bind(reactiveDb.db),\n createLiveQuery: reactiveDb.createLiveQuery.bind(reactiveDb),\n getSharedLiveQuery: reactiveDb.getSharedLiveQuery.bind(reactiveDb),\n },\n state: {\n getState: workerClient.getState.bind(workerClient),\n subscribe: (onChange: () => void) => {\n const { unsubscribe } = workerClient.subscribe(\"state-changed\", onChange);\n return unsubscribe;\n },\n goOnline: workerClient.goOnline.bind(workerClient),\n goOffline: workerClient.goOffline.bind(workerClient),\n },\n /**\n * Ask the elected worker to broadcast a page reload to all tabs for this dbId.\n *\n * With `clean: true` the worker durably records a reset request epoch before\n * broadcasting, so the worker elected on the next startup initializes with\n * `clearOnInit: true` and wipes the persisted DB. Destructive — use as a\n * recovery path when the durable worker DB may be de-synced.\n *\n * Pending in-memory tab events are not preserved, and the returned promise\n * may never settle in the caller — the page typically unloads first.\n */\n requestReload: async (options: { clean: boolean }) => {\n await workerClient.requestReload(options);\n // Primary path: this tab receives the worker's \"reload-requested\" broadcast\n // like every other tab. Fallback in case the broadcast is missed — in the\n // normal case the page is already unloading and this timeout never fires.\n setTimeout(() => globalThis.location?.reload(), 250);\n },\n subscribe: workerClient.subscribe,\n dispose,\n _internal: {\n executeAsync: workerClient.execute.bind(workerClient),\n getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),\n getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),\n crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),\n crdtTablesConfig: options.syncDbSchema.tablesConfig,\n schemaVersion: workerClientSnapshot.schemaVersion,\n migrationVersions: Object.keys(options.syncDbSchema.migrations)\n .map(Number)\n .sort((a, b) => a - b),\n },\n };\n\n unregisterDevtools = getOrCreateSQLiteSyncDevtoolsRegistry().register({\n instanceId,\n dbId: options.dbId,\n createdAt: Date.now(),\n instance: syncedDb,\n });\n\n return syncedDb;\n}\n\nexport type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,uBAA+C;;;ACK/C,IAAM,WAAN,MAAqB;AAAA,EAClB,MAAM,oBAAI,IAAU;AAAA,EACpB;AAAA,EACA;AAAA,EAER,YAAY,MAA6B;AACvC,SAAK,UAAU,KAAK;AACpB,SAAK,WAAW,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,CAAC,KAAQ,UAAa;AAC1B,QAAI,KAAK,YAAY,KAAK,IAAI,IAAI,GAAG,GAAG;AACtC,YAAM,MAAM,KAAK,IAAI,IAAI,GAAG;AAC5B,WAAK,IAAI,IAAI,KAAK,KAAK;AACvB,WAAK,SAAS,KAAK,GAAG;AAAA,IACxB,OAAO;AACL,WAAK,IAAI,IAAI,KAAK,KAAK;AAAA,IACzB;AACA,QAAI,KAAK,IAAI,OAAO,KAAK,SAAS;AAChC,YAAM,WAAW,KAAK,IAAI,KAAK,EAAE,KAAK,EAAE;AACxC,WAAK,OAAO,QAAQ;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAM,CAAC,QAA0B;AAC/B,WAAO,KAAK,IAAI,IAAI,GAAG;AAAA,EACzB;AAAA,EAEA,SAAS,CAAC,QAAW;AACnB,QAAI,KAAK,YAAY,KAAK,IAAI,IAAI,GAAG,GAAG;AACtC,YAAM,QAAQ,KAAK,IAAI,IAAI,GAAG;AAC9B,WAAK,IAAI,OAAO,GAAG;AACnB,WAAK,SAAS,KAAK,KAAK;AAAA,IAC1B,OAAO;AACL,WAAK,IAAI,OAAO,GAAG;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,QAAQ,MAAM;AACZ,UAAM,WAAW,KAAK;AACtB,QAAI,UAAU;AACZ,WAAK,IAAI,QAAQ,CAAC,OAAO,QAAQ;AAC/B,iBAAS,KAAK,KAAK;AAAA,MACrB,CAAC;AAAA,IACH;AACA,SAAK,IAAI,MAAM;AAAA,EACjB;AACF;;;AD9CA,IAAI,eAAqC;AAuClC,SAAS,uBAAiC,MAA+B;AAC9E,SAAO,iBAAiB,OAAiB,IAAI;AAC/C;AAEO,IAAM,mBAAN,MAAM,kBAA2B;AAAA,EAC7B;AAAA,EACD;AAAA,EAES;AAAA,EAET,sBAA8F;AAAA,EAE9F,cAAc,uBAAkC;AAAA,EAEhD,YAAY,SAAwB,QAAgB;AAC1D,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,SAAK,KAAK,IAAI,gBAAgB;AAAA,MAC5B,IAAI,MAAM,IAAI,QAAQ,IAAI,GAAG,EAAE,UAAU,WAAW,CAAC;AAAA,MACrD,QAAQ,KAAK;AAAA,MACb,cAAc;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,OAAiB,MAA+B;AAC3D,UAAM,SAAS,KAAK;AACpB,UAAM,OAAO,uBAAuB,MAAM;AAC1C,QAAI,CAAC,cAAc;AACjB,qBAAe,MAAM,kBAAkB;AAAA,IACzC;AAEA,UAAM,KAAK,IAAI,kBAA2B,cAAc,MAAM;AAE9D,QAAI,KAAK,UAAU;AACjB,SAAG,YAAY,KAAK,QAAQ;AAAA,IAC9B;AACA,OAAG,gBAAgB;AAEnB,SAAK,OAAO,wBAAwB,WAAW,QAAQ;AAEvD,WAAO;AAAA,EACT;AAAA,EAEQ,sBAAsB,IAAI,SAAoD;AAAA,IACpF,SAAS;AAAA,IACT,SAAS,GAAG,OAAO;AACjB,YAAM,SAAS;AAAA,IACjB;AAAA,EACF,CAAC;AAAA,EAEO,oBAAoB,oBAAI,IAA6C;AAAA,EAE7E,gBAAyB,OAAwD;AAC/E,UAAM,YAAY,CAAC,eAAmC;AACpD,UAAI,YAAY,KAAK,oBAAoB,IAAI,MAAM,GAAG;AACtD,UAAI,CAAC,WAAW;AACd,oBAAY,KAAK,GAAG,QAAoB,MAAM,GAAG;AACjD,aAAK,oBAAoB,IAAI,MAAM,KAAK,SAAS;AAAA,MACnD;AACA,aAAO,UAAU,QAAQ,UAAiB;AAAA,IAC5C;AAEA,QAAI,OAAyB;AAE7B,UAAM,UAAU,MAAM;AACpB,UAAI,CAAC,MAAM;AACT,eAAO,UAAU,MAAM,UAAU;AAAA,MACnC;AACA,aAAO;AAAA,IACT;AAEA,QAAI,aAAkC;AAEtC,QAAI,iBAAqC,MAAM;AAC/C,UAAM,UAAU,CAAC,eAAoC;AACnD,UAAI,YAAY;AACd,yBAAiB;AAAA,MACnB;AACA,aAAO,UAAU,cAAc;AAC/B,mBAAa;AAAA,IACf;AAEA,UAAM,YAAY,CAAC,aAAyB;AAC1C,UAAI,YAAY;AACd,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AAEA,mBAAa;AACb,YAAM,eAAe,KAAK,wBAAwB;AAAA,QAChD,KAAK,MAAM;AAAA,QACX,cAAc;AAAA,MAChB,CAAC;AAED,aAAO,MAAM;AACX,qBAAa,YAAY;AACzB,qBAAa;AAAA,MACf;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,SAAS,UAAU;AAAA,EACvC;AAAA,EAEA,mBAA4B,OAAwD;AAClF,UAAM,gBAAgB,KAAK,kBACxB,IAAI,MAAM,GAAG,GACZ,KAAK,CAACA,WAAU,mBAAmBA,OAAM,YAAY,MAAM,UAAU,CAAC;AAC1E,QAAI,eAAe;AACjB,UAAI,cAAc,UAAU,SAAS,GAAG;AACtC,aAAK,+BAA+B,aAAa;AAAA,MACnD;AACA,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,KAAK,gBAAyB,KAAK;AACrD,QAAI,2BAA2B;AAC/B,UAAM,QAAuC;AAAA,MAC3C,KAAK,MAAM;AAAA,MACX,YAAY,MAAM;AAAA,MAClB,WAAW,oBAAI,IAAI;AAAA,MACnB,0BAA0B;AAAA,MAC1B,gBAAgB;AAAA,MAChB,SAAS,MAAM,UAAU,QAAQ;AAAA,MACjC,SAAS,MAAM;AACb,kBAAU,QAAQ;AAAA,MACpB;AAAA,MACA,oBAAoB,MAAM,MAAM,UAAU;AAAA,MAC1C,WAAW,CAAC,aAAa;AACvB,aAAK,6BAA6B,KAAK;AACvC,aAAK,6BAA6B,KAAsC;AACxE,cAAM,UAAU,IAAI,QAAQ;AAE5B,YAAI,CAAC,MAAM,0BAA0B;AACnC,gBAAM,2BAA2B,UAAU,UAAU,MAAM;AACzD,uBAAW,YAAY,MAAM,WAAW;AACtC,uBAAS;AAAA,YACX;AAAA,UACF,CAAC;AAID,cAAI,0BAA0B;AAC5B,uCAA2B;AAC3B,sBAAU,QAAQ;AAAA,UACpB;AAAA,QACF;AAEA,eAAO,MAAM;AACX,gBAAM,UAAU,OAAO,QAAQ;AAE/B,cAAI,MAAM,UAAU,SAAS,GAAG;AAC9B,kBAAM,2BAA2B;AACjC,kBAAM,2BAA2B;AACjC,uCAA2B;AAC3B,iBAAK,+BAA+B,KAAK;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,6BAA6B,KAAsC;AAGxE,SAAK,+BAA+B,KAAsC;AAE1E,WAAO;AAAA,EACT;AAAA,EAEQ,6BAA6B,OAAsC;AACzE,UAAM,qBAAqB,KAAK,kBAAkB,IAAI,MAAM,GAAG,KAAK,CAAC;AACrE,QAAI,CAAC,mBAAmB,SAAS,KAAK,GAAG;AACvC,yBAAmB,KAAK,KAAK;AAC7B,WAAK,kBAAkB,IAAI,MAAM,KAAK,kBAAkB;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,+BAA0D;AACxD,UAAM,WAAsC,CAAC;AAC7C,eAAW,WAAW,KAAK,kBAAkB,OAAO,GAAG;AACrD,iBAAW,SAAS,SAAS;AAC3B,iBAAS,KAAK;AAAA,UACZ,KAAK,MAAM;AAAA,UACX,YAAY,MAAM;AAAA,UAClB,iBAAiB,MAAM,UAAU;AAAA,QACnC,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,+BAA+B,OAAsC;AAC3E,SAAK,6BAA6B,KAAK;AACvC,UAAM,iBAAiB,WAAW,MAAM;AACtC,YAAM,iBAAiB;AACvB,WAAK,uBAAuB,KAAK;AAAA,IACnC,GAAG,CAAC;AAAA,EACN;AAAA,EAEQ,6BAA6B,OAAsC;AACzE,QAAI,MAAM,gBAAgB;AACxB,mBAAa,MAAM,cAAc;AACjC,YAAM,iBAAiB;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,uBAAuB,OAAsC;AACnE,QAAI,MAAM,UAAU,OAAO,KAAK,MAAM,0BAA0B;AAC9D;AAAA,IACF;AAEA,UAAM,qBAAqB,KAAK,kBAAkB,IAAI,MAAM,GAAG;AAC/D,QAAI,CAAC,oBAAoB;AACvB;AAAA,IACF;AAEA,UAAM,cAAc,mBAAmB,OAAO,CAAC,cAAc,cAAc,KAAK;AAChF,QAAI,YAAY,SAAS,GAAG;AAC1B,WAAK,kBAAkB,IAAI,MAAM,KAAK,WAAW;AAAA,IACnD,OAAO;AACL,WAAK,kBAAkB,OAAO,MAAM,GAAG;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,wBAAwB,QAAmD;AACzE,UAAM,EAAE,KAAK,aAAa,IAAI;AAE9B,UAAM,SAAS,KAAK,cAAc,GAAG;AACrC,UAAM,aAAa,oBAAI,IAAY;AACnC,eAAW,SAAS,QAAQ;AAC1B,UAAI,CAAC,WAAW,IAAI,MAAM,IAAI,GAAG;AAC/B,mBAAW,IAAI,MAAM,IAAI;AAAA,MAC3B,WAAW,MAAM,SAAS;AACxB,cAAM,IAAI,MAAM,iFAAiF;AAAA,MACnG;AAAA,IACF;AAEA,UAAM,mBAAmB,wBAAwB,MAAM;AACrD,mBAAa;AAAA,IACf,GAAG,EAAE;AAEL,eAAW,SAAS,YAAY;AAC9B,WAAK,YAAY,iBAAiB,SAAS,KAAK,IAAI,gBAAgB;AAAA,IACtE;AACA,SAAK,YAAY,iBAAiB,qBAAqB,gBAAgB;AAEvE,WAAO;AAAA,MACL,aAAa,MAAM;AACjB,mBAAW,SAAS,YAAY;AAC9B,eAAK,YAAY,oBAAoB,SAAS,KAAK,IAAI,gBAAgB;AAAA,QACzE;AACA,aAAK,YAAY,oBAAoB,qBAAqB,gBAAgB;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,wBAAwB,OAAe,WAAuB;AAC5D,SAAK,YAAY,iBAAiB,SAAS,KAAK,IAAI,SAAS;AAC7D,SAAK,YAAY,iBAAiB,qBAAqB,SAAS;AAChE,WAAO;AAAA,MACL,aAAa,MAAM;AACjB,aAAK,YAAY,oBAAoB,SAAS,KAAK,IAAI,SAAS;AAChE,aAAK,YAAY,oBAAoB,qBAAqB,SAAS;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc,OAAe;AAC3B,QAAI,CAAC,KAAK,qBAAqB;AAC7B,WAAK,sBAAsB,KAAK,GAAG;AAAA,QACjC;AAAA,QACA,EAAE,aAAa,SAAS;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,oBAAoB,QAAQ,CAAC,KAAK,CAAC;AAEvD,QAAI,OAAO,WAAW,KAAK,MAAM,YAAY,EAAE,SAAS,QAAQ,GAAG;AAEjE,aAAO,KAAK,GAAG,KAAK,iBAAiB,KAAK,CAAC;AAAA,IAC7C;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,OAAe;AACtC,UAAM,aAAa,KAAK,GAAG,QAIxB,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,SAAS,CAAC,EAAE;AAEhE,UAAM,yBAAyB,oBAAI,IAAY;AAC/C,eAAW,aAAa,YAAY;AAClC,UAAI,UAAU,WAAW,WAAW,UAAU,OAAO,GAAG;AACtD,+BAAuB,IAAI,UAAU,EAAE;AAAA,MACzC;AAAA,IACF;AAEA,QAAI,uBAAuB,SAAS,GAAG;AACrC,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,aAAa,KAAK,GAAG;AAAA,MACzB,2FAA2F,MAAM;AAAA,QAC/F;AAAA,MACF,EAAE,KAAK,GAAG,CAAC;AAAA,MACX,EAAE,aAAa,SAAS;AAAA,IAC1B,EAAE;AAEF,WAAO;AAAA,EACT;AAAA,EAEA,iBAA4C,MAAS,UAAqD;AACxG,SAAK,YAAY,iBAAiB,MAAM,QAAQ;AAAA,EAClD;AAAA,EAEA,oBAA+C,MAAS,UAAqD;AAC3G,SAAK,YAAY,oBAAoB,MAAM,QAAQ;AAAA,EACrD;AAAA,EAEQ,uBAAuB,SAAuE,MAAM;AAC1G,QAAI,CAAC,QAAQ;AACX,WAAK,YAAY,cAAc,qBAAqB,MAAS;AAC7D;AAAA,IACF;AAEA,eAAW,SAAS,QAAQ;AAC1B,WAAK,YAAY,cAAc,SAAS,KAAK,IAAI,MAAS;AAAA,IAC5D;AAAA,EACF;AAAA,EAEQ,kBAAkB;AACxB,QAAI,cAAc,oBAAI,IAAY;AAElC,SAAK,QAAQ,KAAK;AAAA,MAChB,KAAK,GAAG;AAAA,MACR,CAAC,MAAM,OAAO,KAAK,UAAU;AAC3B,oBAAY,IAAI,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAEA,SAAK,QAAQ,KAAK;AAAA,MAChB,KAAK,GAAG;AAAA,MACR,MAAM;AACJ,YAAI,YAAY,SAAS,GAAG;AAC1B,iBAAO;AAAA,QACT;AAEA,oBAAY,MAAM;AAClB,aAAK,YAAY,cAAc,2BAA2B,MAAS;AAEnE,eAAO;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAEA,SAAK,QAAQ,KAAK;AAAA,MAChB,KAAK,GAAG;AAAA,MACR,MAAM;AACJ,YAAI,YAAY,SAAS,GAAG;AAC1B,iBAAO;AAAA,QACT;AAEA,cAAM,SAAS;AACf,sBAAc,oBAAI,IAAY;AAC9B,aAAK,YAAY,cAAc,yBAAyB,MAAS;AAEjE,uBAAe,MAAM;AACnB,eAAK,uBAAuB,MAAM;AAAA,QACpC,CAAC;AACD,eAAO;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,UAAM,OAAO,uBAAuB,KAAK,MAAM;AAC/C,UAAM,WAAW,KAAK,QAAQ,KAAK,qBAAqB,KAAK,GAAG,QAAQ;AACxE,SAAK,OAAO,kBAAkB,kBAAkB,SAAS,UAAU,IAAI,MAAM;AAE7E,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,UAAuC;AACjD,SAAK,GAAG,YAAY,QAAQ;AAC5B,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEA,UAAU;AACR,eAAW,WAAW,KAAK,kBAAkB,OAAO,GAAG;AACrD,iBAAW,SAAS,SAAS;AAC3B,aAAK,6BAA6B,KAAK;AACvC,cAAM,2BAA2B;AACjC,cAAM,2BAA2B;AACjC,cAAM,UAAU,MAAM;AAAA,MACxB;AAAA,IACF;AACA,SAAK,kBAAkB,MAAM;AAC7B,SAAK,oBAAoB,MAAM;AAC/B,QAAI,KAAK,qBAAqB;AAC5B,WAAK,oBAAoB,SAAS;AAClC,WAAK,sBAAsB;AAAA,IAC7B;AACA,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;AAEA,SAAS,wBAAiD,UAAoC,OAAe;AAC3G,MAAI,UAA0B;AAC9B,MAAI,yBAAyB;AAE7B,SAAO,IAAI,SAAgB;AACzB,QAAI,wBAAwB;AAC1B,eAAS,GAAG,IAAI;AAChB,+BAAyB;AACzB;AAAA,IACF;AAEA,UAAM,SAAS,MAAM;AACnB,gBAAU;AACV,+BAAyB;AACzB,aAAO,SAAS,GAAG,IAAI;AAAA,IACzB;AAEA,QAAI,SAAS;AACX,mBAAa,OAAc;AAAA,IAC7B;AAEA,cAAU,WAAW,QAAQ,KAAK;AAAA,EACpC;AACF;AAEO,SAAS,mBAAmB,GAAmC,GAA4C;AAChH,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,QAAI,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG;AAC1B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;;;AEvbO,SAAS,iBAAkD;AAAA,EAChE;AAAA,EACA;AACF,GAA8D;AAC5D,QAAM,eAAkC,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,eAAe,KAAK,OAAO;AAAA,IAC9F;AAAA,IACA,eAAe,MAAM,YAAY,IAAI,aAAa;AAAA,EACpD,EAAE;AAEF,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,EAAE,eAAe,cAAc,KAAK,cAAc;AAC3D,eAAW,QAAQ,CAAC,eAAe,aAAa,GAAG;AACjD,UAAI,UAAU,IAAI,IAAI,GAAG;AACvB,cAAM,IAAI,MAAM,yBAAyB,IAAI,kBAAkB;AAAA,MACjE;AACA,gBAAU,IAAI,IAAI;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,IAAI,eAAe;AACjB,aAAO;AAAA,IACT;AAAA,IACA,IAAI,aAAa;AACf,aAAO;AAAA,IACT;AAAA,IACA,IAAI,kBAAyB;AAC3B,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AAAA,IACA,IAAI,kBAAyB;AAC3B,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AAAA,IACA,IAAI,qBAA4B;AAC9B,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AAAA,EACF;AACF;;;ACvEO,IAAM,gBAAN,MAAM,eAAyD;AAAA,EAGpE,YAAqB,MAAkB;AAAlB;AAAA,EAAmB;AAAA;AAAA,EAGxC,WAAoD;AAClD,WAAO,IAAI,eAAc,EAAE,GAAG,KAAK,MAAM,UAAU,KAAK,CAAC;AAAA,EAC3D;AAAA;AAAA,EAGA,QAAQ,OAA0C;AAChD,WAAO,IAAI,eAAc,EAAE,GAAG,KAAK,MAAM,YAAY,MAAM,cAAc,MAAM,CAAC;AAAA,EAClF;AAAA;AAAA,EAGA,QAAqE;AACnE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,aAAuD;AAC9D,WAAO,IAAI,eAAc,EAAE,GAAG,KAAK,MAAM,YAAY,CAAC;AAAA,EACxD;AACF;AA0BA,IAAM,mBAAmB,CAAC,MAAM,WAAW;AAE3C,IAAM,eAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AACf;AAEA,IAAM,sBAAkC;AAAA,EACtC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AACf;AAEO,IAAM,eAAN,MAAM,cAAyF;AAAA,EAQpG,YACW,aACT,SACA;AAFS;AAGT,eAAW,YAAY,kBAAkB;AACvC,UAAI,YAAY,aAAa;AAC3B,cAAM,IAAI,MAAM,WAAW,QAAQ,uEAAuE;AAAA,MAC5G;AAAA,IACF;AAEA,SAAK,UAAU;AAAA,MACb,IAAI;AAAA,MACJ,GAAG,OAAO,YAAY,OAAO,QAAQ,WAAW,EAAE,IAAI,CAAC,CAAC,MAAMC,OAAM,MAAM,CAAC,MAAMA,QAAO,IAAI,CAAC,CAAC;AAAA,MAC9F,WAAW;AAAA,IACb;AACA,SAAK,WAAW,SAAS;AACzB,SAAK,cAAc,SAAS;AAAA,EAC9B;AAAA;AAAA,EArBS;AAAA,EACA;AAAA,EACA;AAAA,EAqBT,SAAS,aAAmD;AAC1D,WAAO,IAAI,cAAa,KAAK,aAAa,EAAE,UAAU,KAAK,UAAU,YAAY,CAAC;AAAA,EACpF;AAAA;AAAA,EAGA,IAAI,OAAuB;AACzB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBACE,SACA,SACyB;AACzB,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,SAAmB,CAAC;AAE1B,eAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,UAAI,EAAE,OAAO,KAAK,UAAU;AAC1B,eAAO,KAAK,mBAAmB,GAAG,GAAG;AAAA,MACvC;AAAA,IACF;AAEA,QAAI,UAAU,gBAAgB;AAC5B,UAAI,QAAQ,SAAS;AACnB,eAAO,KAAK,iEAAiE;AAAA,MAC/E;AACA,UAAI,QAAQ,cAAc,QAAQ,QAAQ,cAAc,GAAG;AACzD,eAAO,KAAK,4FAA4F;AAAA,MAC1G;AAAA,IACF;AAEA,QAAI,UAAU,gBAAgB;AAC5B,iBAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,YAAI,QAAQ,WAAW,SAAS,eAAe,KAAK,YAAY,KAAK,YAAY;AAC/E;AAAA,QACF;AACA,eAAO,KAAK,4BAA4B,IAAI,GAAG;AAAA,MACjD;AAAA,IACF;AAEA,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,YAAM,OAAO,KAAK,QAAQ,IAAI;AAC9B,UAAI,CAAC,QAAS,UAAU,kBAAkB,SAAS,MAAO;AACxD;AAAA,MACF;AACA,YAAM,QAAQ,cAAc,MAAM,OAAO,IAAI;AAC7C,UAAI,OAAO;AACT,eAAO,KAAK,KAAK;AAAA,MACnB;AAAA,IACF;AAEA,WAAO,OAAO,WAAW,IAAI,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,OAAO,OAAO;AAAA,EAC5E;AACF;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,SAAO,OAAO;AAChB;AAEA,SAAS,cAAc,MAAc,OAAgB,MAAiC;AACpF,MAAI,UAAU,MAAM;AAClB,WAAO,KAAK,WAAW,OAAO,WAAW,IAAI;AAAA,EAC/C;AAEA,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,OAAO,UAAU,WAAW,OAAO,WAAW,IAAI,uBAAuB,cAAc,KAAK,CAAC;AAAA,IACtG,KAAK;AACH,aAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,IACtD,OACA,WAAW,IAAI,6BAA6B,cAAc,KAAK,CAAC;AAAA,IACtE,KAAK;AACH,aAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IACrD,OACA,WAAW,IAAI,2BAA2B,cAAc,KAAK,CAAC;AAAA,IACpE,KAAK;AACH,aAAO,OAAO,UAAU,aAAa,UAAU,KAAK,UAAU,IAC1D,OACA,WAAW,IAAI,gDAAgD,cAAc,KAAK,CAAC;AAAA,IACzF,KAAK,QAAQ;AACX,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO,WAAW,IAAI,oBAAoB,iBAAiB,IAAI,CAAC,SAAS,cAAc,KAAK,CAAC;AAAA,MAC/F;AACA,aAAO,KAAK,YAAY,SAAS,KAAK,IAClC,OACA,WAAW,IAAI,oBAAoB,iBAAiB,IAAI,CAAC,UAAU,KAAK;AAAA,IAC9E;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,MAA0B;AAClD,UAAQ,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC,UAAU,IAAI,KAAK,GAAG,EAAE,KAAK,KAAK;AACxE;AAEA,SAAS,OAAc,MAAkB,SAAkD;AACzF,SAAO,IAAI,cAAqB,EAAE,MAAM,SAAS,UAAU,OAAO,YAAY,MAAM,CAAC;AACvF;AAEO,IAAM,IAAI;AAAA,EACf,MAAM,MAAM,OAAe,QAAQ,MAAM;AAAA,EACzC,SAAS,MAAM,OAAe,WAAW,SAAS;AAAA,EAClD,MAAM,MAAM,OAAe,QAAQ,MAAM;AAAA;AAAA,EAEzC,SAAS,MAAM,OAAgB,WAAW,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,MAAM,CAAsD,WAC1D,IAAI,cAA8B;AAAA,IAChC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,EACd,CAAC;AAAA,EACH,OAAO,CACL,SACA,YACG,IAAI,aAAa,SAAS,OAAO;AACxC;;;ACvNO,SAAS,yBAAmC,EAAE,QAAQ,GAA6B;AACxF,QAAM,oBAAoB,CAAC,UAA+E;AACxG,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,UACf,SAAS,MAAM;AAAA,UACf,SAAS,KAAK,UAAU,MAAM,OAAO;AAAA,QACvC;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,UACf,SAAS,MAAM;AAAA,UACf,SAAS,KAAK,UAAU,MAAM,OAAO;AAAA,QACvC;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,UACf,SAAS,MAAM;AAAA,UACf,SAAS;AAAA,QACX;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,WAAoE;AACzF,YAAQ,iBAAiB,OAAO,IAAI,iBAAiB,CAAC;AAAA,EACxD;AAEA,QAAM,cAAc,CAAwC,UAA+C;AACzG,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,CAAC,UAAiE;AACrF,YAAQ,iBAAiB,CAAC,kBAAkB,KAAK,CAAC,CAAC;AAAA,EACrD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,GAAG,SAAS,aAAa;AAE7C,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,SAAS,aAAa,YAAY;AAAA,EACpD;AAEA,QAAM,UAAU,IAAI,IAAI,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnE,QAAM,WAAW,QAAQ,IAAI,IAAI;AACjC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,UAAU,aAAa;AAAA,IACzB;AAAA,EACF;AACA,MAAI,SAAS,SAAS,YAAY,MAAM,QAAQ;AAC9C,UAAM,IAAI;AAAA,MACR,UAAU,aAAa,6CAA6C,SAAS,QAAQ;AAAA,IACvF;AAAA,EACF;AAEA,QAAM,kBAAkB,QAAQ,IAAI,WAAW;AAC/C,MAAI,CAAC,iBAAiB;AACpB,UAAM,IAAI;AAAA,MACR,UAAU,aAAa;AAAA,IACzB;AAAA,EACF;AACA,QAAM,gBAAgB,gBAAgB,SAAS,YAAY;AAC3D,MAAI,kBAAkB,aAAa,kBAAkB,WAAW;AAC9D,UAAM,IAAI;AAAA,MACR,UAAU,aAAa,kEAAkE,gBAAgB,QAAQ;AAAA,IACnH;AAAA,EACF;AAEA,KAAG;AAAA,IACD;AAAA,cACU,QAAQ,aAAa,CAAC;AAAA,gBACpB,QAAQ,aAAa,CAAC;AAAA;AAAA,IAElC,EAAE,aAAa,SAAS;AAAA,EAC1B;AAEA,QAAM,iBAAiB,YAAY,QAAQ,IAAI,CAACC,YAAWA,QAAO,IAAI;AAEtE,QAAM,cAAc,CAAC,SACnB,QAAQ,eAAe,IAAI,CAAC,QAAQ,KAAK,GAAG,mBAAmB,IAAI,IAAI,QAAQ,GAAG,CAAC,GAAG,EAAE,KAAK,SAAS,CAAC;AAEzG,KAAG;AAAA,IACD;AAAA,iBACa,QAAQ,GAAG,aAAa,UAAU,CAAC;AAAA,uBAC7B,QAAQ,aAAa,CAAC;AAAA;AAAA;AAAA,8BAGf,aAAa,MAAM,YAAY,KAAK,CAAC;AAAA;AAAA;AAAA,IAG/D,EAAE,aAAa,SAAS;AAAA,EAC1B;AAEA,KAAG;AAAA,IACD;AAAA,iBACa,QAAQ,GAAG,aAAa,UAAU,CAAC;AAAA,uBAC7B,QAAQ,aAAa,CAAC;AAAA;AAAA;AAAA;AAAA,KAIxC,aAAa;AAAA,IACd,YAAY,KAAK,CAAC;AAAA,IAClB,YAAY,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA,IAIlB,EAAE,aAAa,SAAS;AAAA,EAC1B;AAEA,KAAG;AAAA,IACD;AAAA,iBACa,QAAQ,GAAG,aAAa,UAAU,CAAC;AAAA,uBAC7B,QAAQ,aAAa,CAAC;AAAA;AAAA;AAAA;AAAA,8BAIf,aAAa;AAAA;AAAA;AAAA,IAGvC,EAAE,aAAa,SAAS;AAAA,EAC1B;AACF;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAGG;AACD,MAAI,eAAe;AAEnB,aAAW,GAAG,qBAAqB;AAAA,IACjC,MAAM;AAAA,IACN,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,UAAU,CAAC,SAAiB,eAAuB;AACjD,YAAM,UAAU,KAAK,MAAM,UAAU;AAErC,cAAQ,SAAS,6BAA6B,WAAW,IAAI;AAAA,QAC3D,MAAM;AAAA,QACN;AAAA,QACA,SAAS,QAAQ;AAAA,QACjB,SAAS;AAAA,MACX,CAAC;AAED,qBAAe;AACf,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,aAAW,GAAG,qBAAqB;AAAA,IACjC,MAAM;AAAA,IACN,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,UAAU,CAAC,SAAiB,eAAuB,kBAA0B;AAC3E,UAAI,kBAAkB,eAAe;AACnC,eAAO;AAAA,MACT;AAEA,YAAM,cAAc,WAAW,GAAG,SAAS,OAAO;AAElD,UAAI,CAAC,aAAa,SAAS;AACzB,cAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE;AAAA,MAC5D;AAEA,YAAM,aAAa,KAAK,MAAM,aAAa;AAC3C,YAAM,aAAa,KAAK,MAAM,aAAa;AAE3C,UAAI,UAAU;AACd,YAAM,gBAAgB,CAAC;AAEvB,iBAAWA,WAAU,YAAY,SAAS;AACxC,cAAM,WAAW,WAAWA,QAAO,IAAI;AACvC,cAAM,WAAW,WAAWA,QAAO,IAAI;AACvC,YAAI,aAAa,UAAU;AACzB;AAAA,QACF;AAEA,YAAIA,QAAO,SAAS,MAAM;AACxB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,kBAAU;AACV,sBAAcA,QAAO,IAAI,IAAI;AAAA,MAC/B;AAEA,UAAI,CAAC,SAAS;AACZ;AAAA,MACF;AAEA,cAAQ,SAAS,6BAA6B,WAAW,IAAI;AAAA,QAC3D,MAAM;AAAA,QACN;AAAA,QACA,SAAS,WAAW;AAAA,QACpB,SAAS,KAAK,UAAU,aAAa;AAAA,MACvC,CAAC;AAED,qBAAe;AACf,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,aAAW,GAAG,qBAAqB;AAAA,IACjC,MAAM;AAAA,IACN,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,UAAU,CAAC,SAAiB,WAAmB;AAC7C,cAAQ,SAAS,6BAA6B,WAAW,IAAI;AAAA,QAC3D,MAAM;AAAA,QACN;AAAA,QACA,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAED,qBAAe;AACf,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,aAAW,iBAAiB,yBAAyB,MAAM;AACzD,QAAI,cAAc;AAChB,qBAAe;AACf,WAAK,QAAQ,SAAS,sBAAsB;AAAA,IAC9C;AAAA,EACF,CAAC;AAED,aAAW,iBAAiB,2BAA2B,MAAM;AAC3D,mBAAe;AAAA,EACjB,CAAC;AACH;;;ACtNA,IAAM,YAAY;AAEX,SAAS,aAAa,MAAc;AACzC,MAAI,CAAC,UAAU,KAAK,IAAI,GAAG;AACzB,UAAM,IAAI,MAAM,iFAAiF;AAAA,EACnG;AACF;;;ACJA,IAAM,yBAAyB,OAAO,IAAI,uBAAuB;AAyBjE,SAAS,mCAA+D;AACtE,QAAM,YAAY,oBAAI,IAAwC;AAC9D,QAAM,YAAY,oBAAI,IAAgB;AACtC,MAAI,WAAuC;AAAA,IACzC,WAAW,CAAC;AAAA,EACd;AAEA,QAAM,SAAS,MAAM;AACnB,eAAW,YAAY,WAAW;AAChC,eAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,iBAAiB,MAAM;AAC3B,eAAW;AAAA,MACT,WAAW,MAAM,KAAK,UAAU,OAAO,CAAC;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,UAAU,UAAU;AAClB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,cAAc;AACZ,aAAO;AAAA,IACT;AAAA,IACA,SAAS,UAAU;AACjB,gBAAU,IAAI,SAAS,YAAY,QAAQ;AAC3C,qBAAe;AAEf,UAAI,iBAAiB;AACrB,aAAO,MAAM;AACX,YAAI,eAAgB;AACpB,yBAAiB;AAEjB,YAAI,CAAC,UAAU,OAAO,SAAS,UAAU,EAAG;AAC5C,uBAAe;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,wCAAoE;AAClF,QAAM,iBAAiB;AAEvB,iBAAe,sBAAsB,MAAM,iCAAiC;AAE5E,SAAO,eAAe,sBAAsB;AAC9C;;;AC1DA,eAAsB,eAAyB;AAAA,EAC7C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,OAAO,aAAa;AAE1B,QAAM,aAAa;AACnB,QAAM,KAAK,WAAW;AAEtB,MAAI,kBAAkB;AACpB,wBAAoB,EAAE;AACtB,eAAW,SAAS,YAAY;AAC9B,oBAAc;AAAA,QACZ;AAAA,QACA,eAAe,MAAM;AAAA,QACrB,eAAe,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,cAAc,kBAAkB;AAAA,IACpC;AAAA,IACA,oBAAoB,iBAAiB,iBAAiB,EAAE;AAAA,IACxD,KAAK;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,EACV,CAAC;AAED,wBAAsB;AAAA,IACpB;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AAED,SAAO;AAAA,IACL;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,IAAqC;AAC7D,SACE,GAAG,QAA4B,yEAAyE;AAAA,IACtG,aAAa;AAAA,EACf,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU;AAE1B;;;ACnDO,IAAM,uBAAuB,OAAO;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,QAAM,cAAc,uBAA2C;AAC/D,QAAM,oBAAoB,oBAAI,IAAsC;AACpE,MAAI,aAAa;AAEjB,QAAM,cAAc,CAClB,QACA,SACqD;AACrD,QAAI,YAAY;AACd,aAAO,QAAQ,OAAO,IAAI,MAAM,wBAAwB,CAAC;AAAA,IAC3D;AACA,UAAM,YAAY,OAAO,WAAW;AACpC,UAAM,UAAU,sBAA+B;AAAA,MAC7C,SAAS;AAAA,MACT,WAAW,MAAM,kBAAkB,OAAO,SAAS;AAAA,IACrD,CAAC;AACD,sBAAkB,IAAI,WAAW,OAAO;AAExC,UAAM,UAAyC;AAAA,MAC7C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,sBAAkB,SAAS,YAAY,OAAO;AAE9C,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,uBAAuB,CAAC,YAAmC;AAC/D,UAAM,UAAU,kBAAkB,IAAI,QAAQ,SAAS;AACvD,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,YAAQ,QAAQ,QAAQ,IAAI;AAC5B,sBAAkB,OAAO,QAAQ,SAAS;AAAA,EAC5C;AAEA,QAAM,oBAAoB,CAAC,YAAwC;AACjE,UAAM,UAAU,kBAAkB,IAAI,QAAQ,SAAS;AACvD,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,YAAQ,OAAO,IAAI,MAAM,QAAQ,KAAK,CAAC;AACvC,sBAAkB,OAAO,QAAQ,SAAS;AAAA,EAC5C;AAEA,oBAAkB,UAAU,YAAY,CAAC,UAAU;AACjD,UAAM,UAAU,MAAM;AAEtB,QAAI,wBAAwB,OAAO,GAAG;AACpC,2BAAqB,OAAO;AAAA,IAC9B,WAAW,6BAA6B,OAAO,GAAG;AAChD,wBAAkB,OAAO;AAAA,IAC3B,WAAW,4BAA4B,OAAO,GAAG;AAC/C,kBAAY,cAAc,QAAQ,kBAAkB,OAAO;AAAA,IAC7D;AAAA,EACF;AAEA,QAAM,MAA2B;AAAA,IAC/B,SAAS,CAAC,UAAU,YAAY,WAAW,CAAC,KAAK,CAAC;AAAA,IAClD,aAAa,MAAM,YAAY,eAAe,CAAC,CAAC;AAAA,IAChD,eAAe,CAAC,YAAY,YAAY,iBAAiB,CAAC,OAAO,CAAC;AAAA,IAClE,YAAY,CAAC,WAAW,YAAY,cAAc,CAAC,MAAM,CAAC;AAAA,IAC1D,WAAW,MAAM,YAAY,aAAa,CAAC,CAAC;AAAA,IAC5C,UAAU,MAAM,YAAY,YAAY,CAAC,CAAC;AAAA,IAC1C,WAAW,MAAM,YAAY,aAAa,CAAC,CAAC;AAAA,IAC5C,eAAe,CAAC,YAAY,YAAY,iBAAiB,CAAC,OAAO,CAAC;AAAA,EACpE;AAEA,QAAM,eAAe,iBAAiB,WAAW;AACjD,mBAAiB,QAAQ,MAAM;AAK/B,MAAI,UAAU,EAAE,MAAM,IAAI;AAE1B,MAAI,cAAc,MAAM;AAExB,cAAY,iBAAiB,iBAAiB,CAAC,UAAU;AACvD,kBAAc,MAAM,QAAQ;AAAA,EAC9B,CAAC;AAED,QAAM,UAAU,MAAM;AACpB,iBAAa;AACb,sBAAkB,UAAU,YAAY;AACxC,eAAW,CAAC,IAAI,QAAQ,KAAK,mBAAmB;AAC9C,eAAS,OAAO,IAAI,MAAM,wBAAwB,CAAC;AACnD,wBAAkB,OAAO,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,YAAY;AAAA,IACvB,UAAU,MAAM;AAAA,IAChB;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,aAAmD;AAC3E,QAAM,UAAU,sBAAmC,EAAE,SAAS,KAAO,CAAC;AAEtE,QAAM,eAAe,YAAY,iBAAiB,iBAAiB,CAAC,UAAU;AAC5E,YAAQ,QAAQ,MAAM,QAAQ,KAAK;AACnC,iBAAa,YAAY;AAAA,EAC3B,CAAC;AAED,SAAO,QAAQ;AACjB;AAEA,SAAS,iBAAiB,QAAgB,QAAsB;AAC9D,QAAM,gBAAmC;AAAA,IACvC,MAAM;AAAA,IACN;AAAA,EACF;AACA,SAAO,YAAY,aAAa;AAClC;;;ACvIA,IAAM,gBAAwB,CAAC,MAAM,SAAS,QAAQ,WAAW;AAC/D,QAAM,aAAa,IAAI,IAAI,KAAK,OAAO;AACvC,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,cAAQ,IAAI,UAAU;AACtB;AAAA,IACF,KAAK;AACH,cAAQ,KAAK,UAAU;AACvB;AAAA,IACF,KAAK;AACH,cAAQ,MAAM,UAAU;AACxB;AAAA,IACF,KAAK;AACH,cAAQ,MAAM,UAAU;AACxB;AAAA,EACJ;AACF;AAEA,eAAsB,eAA4C,SAA2C;AAC3G,eAAa,QAAQ,IAAI;AAEzB,QAAM,OAAO,uBAAuB,aAAa;AAEjD,QAAM,aAAa,WAAW;AAC9B,QAAM,QAAQ,WAAW;AAEzB,QAAM,oBAAoB,wBAAwB,QAAQ,IAAI;AAE9D,QAAM,qBAAqB,sBAA4B;AACvD,QAAM,oBAAoB,sBAA4B;AACtD,YAAU,MAAM,QAAQ,GAAG,oBAAoB,IAAI,QAAQ,IAAI,IAAI,EAAE,MAAM,SAAS,GAAG,MAAM;AAC3F,uBAAmB,QAAQ;AAC3B,WAAO,kBAAkB;AAAA,EAC3B,CAAC;AACD,QAAM,mBAAmB;AAEzB,QAAM,eAAe,MAAM,qBAAqB;AAAA,IAC9C,QAAQ,QAAQ;AAAA,IAChB,QAAQ;AAAA,MACN,UAAU,WAAW;AAAA,MACrB,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,IACjB;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,aAAa,IAAI,WAAW,OAAO,MAAM,KAAK,IAAI,CAAC;AAEzD,QAAM,uBAAuB,MAAM,aAAa,YAAY;AAC5D,QAAM,aAAa,MAAM,uBAAiC;AAAA,IACxD,UAAU,qBAAqB;AAAA,IAC/B,QAAQ;AAAA,EACV,CAAC;AAED,QAAM,mBAAmC;AAAA,IACvC,sBAAsB,qBAAqB;AAAA,IAC3C,qBAAqB,qBAAqB;AAAA,IAC1C,mBAAmB,MAAM;AACvB,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,IACA,cAAc,CAAC,OAAO,kBAAkB;AACtC,UAAI,MAAM,mBAAmB,eAAe;AAC1C,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,IACA,eAAe,CAAC,WAAW;AAAA,EAC7B;AACA,QAAM,EAAE,YAAY,IAAI,MAAM,eAAe;AAAA,IAC3C,QAAQ;AAAA,IACR,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,YAAY,QAAQ,aAAa;AAAA,IACjC,cAAc,QAAQ;AAAA,EACxB,CAAC;AAED,QAAM,aAAa,kBAAkB;AAAA,IACnC,cAAc,qBAAqB;AAAA,EACrC,CAAC;AACD,QAAM,aAAa,kBAAkB;AAAA,IACnC,cAAc;AAAA,EAChB,CAAC;AACD,QAAM,kBAAkB,2BAA2B;AAAA,IACjD,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,eAAe,CAAC,EAAE,kBAAkB,MAAM;AACxC,YAAM,eAAe,aAAa,UAAU,2BAA2B,CAAC,UAAU;AAChF,0BAAkB,EAAE,WAAW,MAAM,QAAQ,WAAW,mBAAmB,MAAM,QAAQ,YAAY,CAAC;AAAA,MACxG,CAAC;AAED,aAAO;AAAA,QACL,YAAY,CAAC,YAAY,aAAa,WAAW,OAAO;AAAA,QACxD,YAAY,CAAC,YAAY,aAAa,cAAc,OAAO;AAAA,QAC3D,YAAY,MAAM;AAChB,uBAAa,YAAY;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,kBAAgB,SAAS;AAEzB,QAAM,8BAA8B,aAAa,UAAU,oBAAoB,MAAM;AACnF,eAAW,UAAU,OAAO;AAAA,EAC9B,CAAC;AAED,OAAK,OAAO,kBAAkB,eAAe,MAAM;AAEnD,MAAI,aAAa;AACjB,MAAI;AACJ,QAAM,UAAU,YAAY;AAC1B,QAAI,WAAY;AAChB,iBAAa;AAEb,yBAAqB;AACrB,gCAA4B,YAAY;AACxC,sBAAkB,QAAQ;AAC1B,UAAM,gBAAgB,QAAQ;AAC9B,sBAAkB,SAAS,MAAM;AACjC,sBAAkB,UAAU,MAAM;AAClC,iBAAa,QAAQ;AACrB,eAAW,QAAQ;AAAA,EACrB;AAEA,QAAM,WAAW;AAAA,IACf,IAAI;AAAA,MACF,SAAS,WAAW,GAAG,QAAQ,KAAK,WAAW,EAAE;AAAA,MACjD,eAAe,WAAW,GAAG,cAAc,KAAK,WAAW,EAAE;AAAA,MAC7D,oBAAoB,WAAW,GAAG,mBAAmB,KAAK,WAAW,EAAE;AAAA,MACvE,iBAAiB,WAAW,gBAAgB,KAAK,UAAU;AAAA,MAC3D,oBAAoB,WAAW,mBAAmB,KAAK,UAAU;AAAA,IACnE;AAAA,IACA,OAAO;AAAA,MACL,UAAU,aAAa,SAAS,KAAK,YAAY;AAAA,MACjD,WAAW,CAAC,aAAyB;AACnC,cAAM,EAAE,YAAY,IAAI,aAAa,UAAU,iBAAiB,QAAQ;AACxE,eAAO;AAAA,MACT;AAAA,MACA,UAAU,aAAa,SAAS,KAAK,YAAY;AAAA,MACjD,WAAW,aAAa,UAAU,KAAK,YAAY;AAAA,IACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,eAAe,OAAOC,aAAgC;AACpD,YAAM,aAAa,cAAcA,QAAO;AAIxC,iBAAW,MAAM,WAAW,UAAU,OAAO,GAAG,GAAG;AAAA,IACrD;AAAA,IACA,WAAW,aAAa;AAAA,IACxB;AAAA,IACA,WAAW;AAAA,MACT,cAAc,aAAa,QAAQ,KAAK,YAAY;AAAA,MACpD,sBAAsB,WAAW,cAAc,KAAK,UAAU;AAAA,MAC9D,8BAA8B,WAAW,6BAA6B,KAAK,UAAU;AAAA,MACrF,gBAAgB,QAAQ,aAAa,aAAa,IAAI,CAAC,UAAU,MAAM,aAAa;AAAA,MACpF,kBAAkB,QAAQ,aAAa;AAAA,MACvC,eAAe,qBAAqB;AAAA,MACpC,mBAAmB,OAAO,KAAK,QAAQ,aAAa,UAAU,EAC3D,IAAI,MAAM,EACV,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IACzB;AAAA,EACF;AAEA,uBAAqB,sCAAsC,EAAE,SAAS;AAAA,IACpE;AAAA,IACA,MAAM,QAAQ;AAAA,IACd,WAAW,KAAK,IAAI;AAAA,IACpB,UAAU;AAAA,EACZ,CAAC;AAED,SAAO;AACT;","names":["entry","column","column","options"]}
|
|
1
|
+
{"version":3,"sources":["../src/export-import.ts","../src/memory-db/sqlite-reactive-db.ts","../src/bound-map.ts","../src/schema/define-sync-schema.ts","../src/schema/table-builder.ts","../src/sqlite-crdt/crdt-storage-mutator.ts","../src/sqlite-crdt/make-crdt-table.ts","../src/db-id.ts","../src/devtools-registry.ts","../src/memory-db/memory-db.ts","../src/worker-db/db-worker-client.ts","../src/sync-db.ts"],"sourcesContent":["import type { CrdtTableConfig } from \"./sqlite-crdt/crdt-schema\";\nimport type { CrdtStorage, OwnCrdtEvent } from \"./sqlite-crdt/crdt-storage\";\nimport type { ExecuteResult } from \"./sqlite-db-wrapper\";\nimport { quoteId } from \"./utils\";\n\n/**\n * A portable, schema-version-aware dump of every active entity in a synced DB.\n * Unlike a raw SQLite snapshot, it carries no event history — just the current\n * `tombstone = 0` rows, ready to be replayed as fresh create events on import.\n */\nexport type SyncedDbExport = {\n schemaVersion: number;\n exportedAt: string;\n /** crdt table name -> active rows (each includes `id`, excludes `tombstone`). */\n tables: Record<string, Array<Record<string, unknown>>>;\n};\n\ntype ExportImportReactiveDb = {\n db: { execute<T>(sql: string, meta: { loggerLevel: \"system\" }): ExecuteResult<T> };\n};\n\ntype CreateExportImportOptions = {\n reactiveDb: ExportImportReactiveDb;\n crdtStorage: CrdtStorage;\n tablesConfig: CrdtTableConfig[];\n schemaVersion: number;\n};\n\nexport function createExportImport({\n reactiveDb,\n crdtStorage,\n tablesConfig,\n schemaVersion,\n}: CreateExportImportOptions) {\n const crdtTableNames = tablesConfig.map((config) => config.crdtTableName);\n\n const resolveTables = (requested: string[] | undefined): string[] => {\n if (!requested) {\n return crdtTableNames;\n }\n for (const name of requested) {\n if (!crdtTableNames.includes(name)) {\n throw new Error(`Unknown table \"${name}\". Known synced tables: ${crdtTableNames.join(\", \")}`);\n }\n }\n return requested;\n };\n\n /**\n * Dump every active entity (the `tombstone = 0` rows) from the synced tables.\n *\n * Reads this tab's reactive (in-memory) DB — the state the user currently sees,\n * which may differ slightly from the worker's authoritative DB while local\n * writes are in flight.\n */\n const exportData = (opts?: { tables?: string[] }): SyncedDbExport => {\n const tables: Record<string, Array<Record<string, unknown>>> = {};\n\n for (const crdtTableName of resolveTables(opts?.tables)) {\n const { rows } = reactiveDb.db.execute<Record<string, unknown>>(`select * from ${quoteId(crdtTableName)}`, {\n loggerLevel: \"system\",\n });\n tables[crdtTableName] = rows.map(({ tombstone: _tombstone, ...rest }) => rest);\n }\n\n return {\n schemaVersion,\n exportedAt: new Date().toISOString(),\n tables,\n };\n };\n\n /**\n * Replay an export as a sequence of `item-created` CRDT events, seeding the\n * rows into local state and propagating them to the server like any other write.\n *\n * Overwrite-by-default: because the generated events carry fresh (newest) HLC\n * timestamps, importing a row whose `id` already exists overwrites every field\n * under last-write-wins, while new ids are inserted. Existing rows absent from\n * the dump are never touched. This is a restore/seed, not a CRDT merge —\n * original timestamps are not preserved.\n *\n * @param opts.validate When `false`, skip the schema-version match check. Per-row\n * payload validation always runs (it is intrinsic to applying own events).\n */\n const importData = (data: SyncedDbExport, opts?: { validate?: boolean }): { imported: number } => {\n const validate = opts?.validate ?? true;\n\n if (validate && data.schemaVersion !== schemaVersion) {\n throw new Error(\n `Cannot import data from schema version ${data.schemaVersion} into a database at schema version ${schemaVersion}.`,\n );\n }\n\n const events: OwnCrdtEvent[] = [];\n for (const [crdtTableName, rows] of Object.entries(data.tables)) {\n for (const row of rows) {\n events.push({\n type: \"item-created\",\n dataset: crdtTableName,\n item_id: row.id as string,\n payload: JSON.stringify(row),\n });\n }\n }\n\n crdtStorage.applyOwnEvents(events);\n\n return { imported: events.length };\n };\n\n return { exportData, importData };\n}\n","import sqlite3InitModule, { type Sqlite3Static } from \"@sqlite.org/sqlite-wasm\";\nimport { BoundMap } from \"../bound-map\";\nimport { type Logger, startPerformanceLogger } from \"../logger\";\nimport { type PreparedStatement, SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createTypedEventTarget, type TypedEvent } from \"../utils\";\n\nlet sqliteModule: Sqlite3Static | null = null;\n\ntype TableName<Database> = keyof Database extends string ? keyof Database : never;\n\ntype SQLiteReactiveDbOptions = {\n snapshot: Uint8Array<ArrayBufferLike>;\n logger: Logger;\n};\n\ntype EventsMap = {\n \"transaction-committed\": undefined;\n \"transaction-rolled-back\": undefined;\n \"any-table-changed\": undefined;\n} & Record<`table:${string}`, void>;\n\ntype LiveQuery<TResult> = {\n getRows: () => TResult[];\n refresh: () => void;\n subscribe: (onchange: () => void) => () => void;\n};\n\nexport type SharedLiveQuery<TResult> = LiveQuery<TResult> & {\n readonly sql: string;\n readonly parameters: readonly unknown[];\n getSubscriberCount: () => number;\n};\n\ntype SharedLiveQueryEntry<TResult> = SharedLiveQuery<TResult> & {\n listeners: Set<() => void>;\n unsubscribeFromLiveQuery: (() => void) | null;\n cleanupTimeout: ReturnType<typeof setTimeout> | null;\n};\n\nexport type SharedLiveQuerySnapshot = {\n sql: string;\n parameters: readonly unknown[];\n subscriberCount: number;\n};\n\nexport function createSQLiteReactiveDb<Database>(opts: SQLiteReactiveDbOptions) {\n return SQLiteReactiveDb.create<Database>(opts);\n}\n\nexport class SQLiteReactiveDb<Database> {\n readonly db: SQLiteDbWrapper<Database>;\n private sqlite3: Sqlite3Static;\n\n private readonly logger: Logger;\n\n private tablesUsedStatement: PreparedStatement<[string], { name: string; isWrite: boolean }> | null = null;\n\n private eventTarget = createTypedEventTarget<EventsMap>();\n\n private constructor(sqlite3: Sqlite3Static, logger: Logger) {\n this.sqlite3 = sqlite3;\n this.logger = logger;\n\n this.db = new SQLiteDbWrapper({\n db: () => new sqlite3.oo1.DB({ filename: \":memory:\" }),\n logger: this.logger,\n loggerPrefix: \"memory\",\n sqlite3,\n });\n }\n\n static async create<Database>(opts: SQLiteReactiveDbOptions) {\n const logger = opts.logger;\n const perf = startPerformanceLogger(logger);\n if (!sqliteModule) {\n sqliteModule = await sqlite3InitModule();\n }\n\n const db = new SQLiteReactiveDb<Database>(sqliteModule, logger);\n\n if (opts.snapshot) {\n db.useSnapshot(opts.snapshot);\n }\n db.registerDbHooks();\n\n perf.logEnd(\"createSQLiteMemoryDb\", \"success\", \"system\");\n\n return db;\n }\n\n private liveQueryStatements = new BoundMap<string, PreparedStatement<any[], unknown>>({\n maxSize: 100,\n onRemove(_, value) {\n value.finalize();\n },\n });\n\n private sharedLiveQueries = new Map<string, SharedLiveQueryEntry<unknown>[]>();\n\n createLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const fetchRows = (parameters: readonly unknown[]) => {\n let statement = this.liveQueryStatements.get(query.sql);\n if (!statement) {\n statement = this.db.prepare<any[], any>(query.sql);\n this.liveQueryStatements.set(query.sql, statement);\n }\n return statement.execute(parameters as any) as TResult[];\n };\n\n let rows: TResult[] | null = null;\n\n const getRows = () => {\n if (!rows) {\n rows = fetchRows(query.parameters);\n }\n return rows;\n };\n\n let subscriber: (() => void) | null = null;\n\n let lastParameters: readonly unknown[] = query.parameters;\n const refresh = (parameters?: readonly unknown[]) => {\n if (parameters) {\n lastParameters = parameters;\n }\n rows = fetchRows(lastParameters);\n subscriber?.();\n };\n\n const subscribe = (onchange: () => void) => {\n if (subscriber) {\n throw new Error(\"Subscriber already exists\");\n }\n\n subscriber = onchange;\n const subscription = this.subscribeToQueryChanges({\n sql: query.sql,\n onDataChange: refresh,\n });\n\n return () => {\n subscription.unsubscribe();\n subscriber = null;\n };\n };\n\n return { getRows, refresh, subscribe };\n }\n\n getSharedLiveQuery<TResult>(query: { sql: string; parameters: readonly unknown[] }) {\n const existingEntry = this.sharedLiveQueries\n .get(query.sql)\n ?.find((entry) => parametersAreEqual(entry.parameters, query.parameters));\n if (existingEntry) {\n if (existingEntry.listeners.size === 0) {\n this.scheduleSharedLiveQueryCleanup(existingEntry);\n }\n return existingEntry as SharedLiveQuery<TResult>;\n }\n\n const liveQuery = this.createLiveQuery<TResult>(query);\n let hasDetachedFromLiveQuery = false;\n const entry: SharedLiveQueryEntry<TResult> = {\n sql: query.sql,\n parameters: query.parameters,\n listeners: new Set(),\n unsubscribeFromLiveQuery: null,\n cleanupTimeout: null,\n getRows: () => liveQuery.getRows(),\n refresh: () => {\n liveQuery.refresh();\n },\n getSubscriberCount: () => entry.listeners.size,\n subscribe: (onchange) => {\n this.cancelSharedLiveQueryCleanup(entry);\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n entry.listeners.add(onchange);\n\n if (!entry.unsubscribeFromLiveQuery) {\n entry.unsubscribeFromLiveQuery = liveQuery.subscribe(() => {\n for (const listener of entry.listeners) {\n listener();\n }\n });\n\n // Rows may have gone stale while no subscriber was listening\n // for table changes.\n if (hasDetachedFromLiveQuery) {\n hasDetachedFromLiveQuery = false;\n liveQuery.refresh();\n }\n }\n\n return () => {\n entry.listeners.delete(onchange);\n\n if (entry.listeners.size === 0) {\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n hasDetachedFromLiveQuery = true;\n this.scheduleSharedLiveQueryCleanup(entry);\n }\n };\n },\n };\n\n this.registerSharedLiveQueryEntry(entry as SharedLiveQueryEntry<unknown>);\n\n // Evict the entry if no subscriber attaches by the next tick.\n this.scheduleSharedLiveQueryCleanup(entry as SharedLiveQueryEntry<unknown>);\n\n return entry;\n }\n\n private registerSharedLiveQueryEntry(entry: SharedLiveQueryEntry<unknown>) {\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql) ?? [];\n if (!matchingSqlEntries.includes(entry)) {\n matchingSqlEntries.push(entry);\n this.sharedLiveQueries.set(entry.sql, matchingSqlEntries);\n }\n }\n\n getSharedLiveQueriesSnapshot(): SharedLiveQuerySnapshot[] {\n const snapshot: SharedLiveQuerySnapshot[] = [];\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n snapshot.push({\n sql: entry.sql,\n parameters: entry.parameters,\n subscriberCount: entry.listeners.size,\n });\n }\n }\n return snapshot;\n }\n\n private scheduleSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.cleanupTimeout = setTimeout(() => {\n entry.cleanupTimeout = null;\n this.releaseSharedLiveQuery(entry);\n }, 0);\n }\n\n private cancelSharedLiveQueryCleanup(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.cleanupTimeout) {\n clearTimeout(entry.cleanupTimeout);\n entry.cleanupTimeout = null;\n }\n }\n\n private releaseSharedLiveQuery(entry: SharedLiveQueryEntry<unknown>) {\n if (entry.listeners.size > 0 || entry.unsubscribeFromLiveQuery) {\n return;\n }\n\n const matchingSqlEntries = this.sharedLiveQueries.get(entry.sql);\n if (!matchingSqlEntries) {\n return;\n }\n\n const nextEntries = matchingSqlEntries.filter((candidate) => candidate !== entry);\n if (nextEntries.length > 0) {\n this.sharedLiveQueries.set(entry.sql, nextEntries);\n } else {\n this.sharedLiveQueries.delete(entry.sql);\n }\n }\n\n subscribeToQueryChanges(params: { sql: string; onDataChange: () => void }) {\n const { sql, onDataChange } = params;\n\n const tables = this.getTablesUsed(sql);\n const readTables = new Set<string>();\n for (const table of tables) {\n if (!readTables.has(table.name)) {\n readTables.add(table.name);\n } else if (table.isWrite) {\n throw new Error(\"This query writes and reads from the same table. This may cause infinite loops.\");\n }\n }\n\n const notifyDataChange = createDebouncedCallback(() => {\n onDataChange();\n }, 30);\n\n for (const table of readTables) {\n this.eventTarget.addEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.addEventListener(\"any-table-changed\", notifyDataChange);\n\n return {\n unsubscribe: () => {\n for (const table of readTables) {\n this.eventTarget.removeEventListener(`table:${table}`, notifyDataChange);\n }\n this.eventTarget.removeEventListener(\"any-table-changed\", notifyDataChange);\n },\n };\n }\n\n subscribeToTableChanges(table: string, onChanges: () => void) {\n this.eventTarget.addEventListener(`table:${table}`, onChanges);\n this.eventTarget.addEventListener(\"any-table-changed\", onChanges);\n return {\n unsubscribe: () => {\n this.eventTarget.removeEventListener(`table:${table}`, onChanges);\n this.eventTarget.removeEventListener(\"any-table-changed\", onChanges);\n },\n };\n }\n\n getTablesUsed(query: string) {\n if (!this.tablesUsedStatement) {\n this.tablesUsedStatement = this.db.prepare<[string], { name: string; isWrite: boolean }>(\n \"select t.tbl_name as name, u.wr as isWrite from tables_used(?) as u inner join sqlite_master as t on t.name = u.name where u.schema = 'main'\",\n { loggerLevel: \"system\" },\n );\n }\n\n const tables = this.tablesUsedStatement.execute([query]);\n\n if (tables.length === 0 && query.toLowerCase().includes(\"delete\")) {\n // tables_used function does not work with delete queries that clear entire tables\n tables.push(...this.getClearedTables(query));\n }\n\n return tables;\n }\n\n private getClearedTables(query: string) {\n const operations = this.db.execute<{\n opcode: string;\n p1: number;\n p2: number;\n }>(`EXPLAIN ${query.split(\";\")[0]}`, { loggerLevel: \"system\" }).rows;\n\n const clearedTablesRootPages = new Set<number>();\n for (const operation of operations) {\n if (operation.opcode === \"Clear\" && operation.p2 === 0) {\n clearedTablesRootPages.add(operation.p1);\n }\n }\n\n if (clearedTablesRootPages.size === 0) {\n return [];\n }\n\n const tableNames = this.db.execute<{ name: string; isWrite: boolean }>(\n `select t.tbl_name as name, true as isWrite from sqlite_master as t where t.rootpage in (${Array.from(\n clearedTablesRootPages,\n ).join(\",\")})`,\n { loggerLevel: \"system\" },\n ).rows;\n\n return tableNames;\n }\n\n addEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.addEventListener(type, listener);\n }\n\n removeEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void) {\n this.eventTarget.removeEventListener(type, listener);\n }\n\n private notifyTableSubscribers(tables: (TableName<Database> | (string & {}))[] | Set<string> | null = null) {\n if (!tables) {\n this.eventTarget.dispatchEvent(\"any-table-changed\", undefined);\n return;\n }\n\n for (const table of tables) {\n this.eventTarget.dispatchEvent(`table:${table}`, undefined);\n }\n }\n\n private registerDbHooks() {\n let updateQueue = new Set<string>();\n\n this.sqlite3.capi.sqlite3_update_hook(\n this.db.ensureDb,\n (_ctx, _opId, _db, table) => {\n updateQueue.add(table);\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_rollback_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n updateQueue.clear();\n this.eventTarget.dispatchEvent(\"transaction-rolled-back\", undefined);\n\n return 0;\n },\n 0,\n );\n\n this.sqlite3.capi.sqlite3_commit_hook(\n this.db.ensureDb,\n () => {\n if (updateQueue.size === 0) {\n return 0;\n }\n\n const tables = updateQueue;\n updateQueue = new Set<string>();\n this.eventTarget.dispatchEvent(\"transaction-committed\", undefined);\n\n queueMicrotask(() => {\n this.notifyTableSubscribers(tables);\n });\n return 0;\n },\n 0,\n );\n }\n\n createSnapshot() {\n const perf = startPerformanceLogger(this.logger);\n const snapshot = this.sqlite3.capi.sqlite3_js_db_export(this.db.ensureDb);\n perf.logEnd(\"createSnapshot\", `snapshot size: ${snapshot.byteLength}`, \"info\");\n\n return snapshot;\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n this.db.useSnapshot(snapshot);\n this.notifyTableSubscribers();\n }\n\n dispose() {\n for (const entries of this.sharedLiveQueries.values()) {\n for (const entry of entries) {\n this.cancelSharedLiveQueryCleanup(entry);\n entry.unsubscribeFromLiveQuery?.();\n entry.unsubscribeFromLiveQuery = null;\n entry.listeners.clear();\n }\n }\n this.sharedLiveQueries.clear();\n this.liveQueryStatements.clear();\n if (this.tablesUsedStatement) {\n this.tablesUsedStatement.finalize();\n this.tablesUsedStatement = null;\n }\n this.db.close();\n }\n}\n\nfunction createDebouncedCallback<TArgs extends unknown[]>(callback: (...args: TArgs) => void, delay: number) {\n let timeout: unknown | null = null;\n let shouldCallWithoutDelay = true;\n\n return (...args: TArgs) => {\n if (shouldCallWithoutDelay) {\n callback(...args);\n shouldCallWithoutDelay = false;\n return;\n }\n\n const effect = () => {\n timeout = null;\n shouldCallWithoutDelay = true;\n return callback(...args);\n };\n\n if (timeout) {\n clearTimeout(timeout as any);\n }\n\n timeout = setTimeout(effect, delay);\n };\n}\n\nexport function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) {\n return false;\n }\n }\n return true;\n}\n","interface BoundMapOptions<K, V> {\n maxSize: number;\n onRemove: ((key: K, value: V) => void) | undefined;\n}\n\nexport class BoundMap<K, V> {\n private map = new Map<K, V>();\n private maxSize: number;\n private onRemove: ((key: K, value: V) => void) | undefined;\n\n constructor(opts: BoundMapOptions<K, V>) {\n this.maxSize = opts.maxSize;\n this.onRemove = opts.onRemove;\n }\n\n set = (key: K, value: V) => {\n if (this.onRemove && this.map.has(key)) {\n const old = this.map.get(key) as V;\n this.map.set(key, value);\n this.onRemove(key, old);\n } else {\n this.map.set(key, value);\n }\n if (this.map.size > this.maxSize) {\n const firstKey = this.map.keys().next().value as K;\n this.delete(firstKey);\n }\n };\n\n get = (key: K): V | undefined => {\n return this.map.get(key);\n };\n\n delete = (key: K) => {\n if (this.onRemove && this.map.has(key)) {\n const value = this.map.get(key) as V;\n this.map.delete(key);\n this.onRemove(key, value);\n } else {\n this.map.delete(key);\n }\n };\n\n clear = () => {\n const onRemove = this.onRemove;\n if (onRemove) {\n this.map.forEach((value, key) => {\n onRemove(key, value);\n });\n }\n this.map.clear();\n };\n}\n","import type { Migrations } from \"../migrations/migrator\";\nimport type { CrdtTableConfig, ReadonlyTable, SyncDbSchema } from \"../sqlite-crdt/crdt-schema\";\nimport type { AnyTableBuilder, InferRow, SyncSchemaTables, TableBuilder, TableColumns } from \"./table-builder\";\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\ntype RowOf<Table extends AnyTableBuilder> =\n Table extends TableBuilder<infer Cols extends TableColumns, any> ? InferRow<Cols> : never;\n\n// Falls back to the \"_\" convention unless ~baseName is a string *literal* — inference can\n// resolve an omitted override to its constraint (string | undefined) rather than undefined.\ntype BaseNameOf<CrdtName, Table extends AnyTableBuilder> = string extends Table[\"~baseName\"]\n ? `_${CrdtName & string}`\n : [Table[\"~baseName\"]] extends [string]\n ? Table[\"~baseName\"]\n : `_${CrdtName & string}`;\n\ntype ClientSchemaOf<Tables extends SyncSchemaTables> = Simplify<\n { [K in keyof Tables]: RowOf<Tables[K]> } & {\n [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>;\n }\n>;\n\ntype ServerSchemaOf<Tables extends SyncSchemaTables> = Simplify<\n { [K in keyof Tables]: ReadonlyTable<RowOf<Tables[K]>> } & {\n [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>;\n }\n>;\n\ntype MutationsSchemaOf<Tables extends SyncSchemaTables> = Simplify<{\n [K in keyof Tables as BaseNameOf<K, Tables[K]>]: RowOf<Tables[K]>;\n}>;\n\nexport interface DefinedSyncSchema<Tables extends SyncSchemaTables>\n extends SyncDbSchema<ClientSchemaOf<Tables>, ServerSchemaOf<Tables>, MutationsSchemaOf<Tables>> {\n /** The table builders, for type extraction (`typeof schema.tables.item.$row`) and runtime metadata. */\n tables: Tables;\n}\n\nexport type DefineSyncSchemaConfig<Tables extends SyncSchemaTables> = {\n tables: Tables;\n /** Full migration history (including the initial createTable version), built with `createMigrations`. */\n migrations: Migrations;\n};\n\n/**\n * Define a sync database schema from `t.table()` builders.\n *\n * Record keys are the crdt (view) table names; base table names default to the key\n * prefixed with \"_\", overridable per table via `t.table(cols, { baseName })`.\n */\nexport function defineSyncSchema<Tables extends SyncSchemaTables>({\n tables,\n migrations,\n}: DefineSyncSchemaConfig<Tables>): DefinedSyncSchema<Tables> {\n const tablesConfig: CrdtTableConfig[] = Object.entries(tables).map(([crdtTableName, table]) => ({\n crdtTableName,\n baseTableName: table.baseName ?? `_${crdtTableName}`,\n }));\n\n const seenNames = new Set<string>();\n for (const { crdtTableName, baseTableName } of tablesConfig) {\n for (const name of [crdtTableName, baseTableName]) {\n if (seenNames.has(name)) {\n throw new Error(`Duplicate table name \"${name}\" in sync schema`);\n }\n seenNames.add(name);\n }\n }\n\n return {\n tables,\n get tablesConfig() {\n return tablesConfig;\n },\n get migrations() {\n return migrations;\n },\n get \"~clientSchema\"(): never {\n throw new Error(\"~clientSchema is type-only and cannot be accessed at runtime\");\n },\n get \"~serverSchema\"(): never {\n throw new Error(\"~serverSchema is type-only and cannot be accessed at runtime\");\n },\n get \"~mutationsSchema\"(): never {\n throw new Error(\"~mutationsSchema is type-only and cannot be accessed at runtime\");\n },\n };\n}\n","export type ColumnKind = \"text\" | \"integer\" | \"real\" | \"boolean\" | \"enum\";\n\nexport type SqliteStorageType = \"text\" | \"integer\" | \"real\";\n\nexport type ColumnMeta = {\n kind: ColumnKind;\n /** Storage type used in generated DDL. Booleans store as integer 0/1. */\n sqlType: SqliteStorageType;\n nullable: boolean;\n hasDefault: boolean;\n /** Declared default in JS form (booleans as booleans). */\n defaultValue?: unknown;\n /** Allowed values for `enum` columns. */\n enumValues?: readonly string[];\n description?: string;\n};\n\nexport class ColumnBuilder<Value, HasDefault extends boolean = false> {\n declare readonly \"~types\": { value: Value; hasDefault: HasDefault };\n\n constructor(readonly meta: ColumnMeta) {}\n\n /** Allow SQL NULL; widens the value type with `null`. */\n nullable(): ColumnBuilder<Value | null, HasDefault> {\n return new ColumnBuilder({ ...this.meta, nullable: true });\n }\n\n /** Declare a column default. The value is used both in DDL and when migrating older events. */\n default(value: Value): ColumnBuilder<Value, true> {\n return new ColumnBuilder({ ...this.meta, hasDefault: true, defaultValue: value });\n }\n\n /** Narrow the TypeScript value type without changing storage, e.g. `t.text().$type<\"movie\" | \"tv\">()`. */\n $type<Narrowed extends Value>(): ColumnBuilder<Narrowed, HasDefault> {\n return this as unknown as ColumnBuilder<Narrowed, HasDefault>;\n }\n\n /** Human/AI-readable description, surfaced in generated schema docs. */\n describe(description: string): ColumnBuilder<Value, HasDefault> {\n return new ColumnBuilder({ ...this.meta, description });\n }\n}\n\nexport type AnyColumnBuilder = ColumnBuilder<any, boolean>;\n\nexport type TableColumns = Record<string, AnyColumnBuilder>;\n\nexport type AnyTableBuilder = TableBuilder<any, any>;\n\nexport type SyncSchemaTables = Record<string, AnyTableBuilder>;\n\nexport type TableOptions<BaseName extends string | undefined = string | undefined> = {\n /** Override the materialized base table name (defaults to the crdt table name prefixed with \"_\"). */\n baseName?: BaseName;\n description?: string;\n};\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\ntype ColumnValue<Column> = Column extends ColumnBuilder<infer Value, boolean> ? Value : never;\n\nexport type InferRow<Cols extends TableColumns> = Simplify<\n { id: string } & { [K in keyof Cols]: ColumnValue<Cols[K]> } & { tombstone?: boolean }\n>;\n\nexport type PayloadValidationResult = { success: true } | { success: false; errors: string[] };\n\nconst RESERVED_COLUMNS = [\"id\", \"tombstone\"] as const;\n\nconst idColumnMeta: ColumnMeta = {\n kind: \"text\",\n sqlType: \"text\",\n nullable: false,\n hasDefault: false,\n description: \"Unique immutable item id\",\n};\n\nconst tombstoneColumnMeta: ColumnMeta = {\n kind: \"boolean\",\n sqlType: \"integer\",\n nullable: false,\n hasDefault: true,\n defaultValue: false,\n description: \"Soft-delete marker\",\n};\n\nexport class TableBuilder<Cols extends TableColumns, BaseName extends string | undefined = undefined> {\n declare readonly \"~baseName\": BaseName;\n\n /** All columns in DDL order, including the auto-injected `id` and `tombstone`. */\n readonly columns: Record<string, ColumnMeta>;\n readonly baseName: BaseName;\n readonly description: string | undefined;\n\n constructor(\n readonly userColumns: Cols,\n options?: TableOptions<BaseName>,\n ) {\n for (const reserved of RESERVED_COLUMNS) {\n if (reserved in userColumns) {\n throw new Error(`Column \"${reserved}\" is added automatically to every synced table and cannot be declared`);\n }\n }\n\n this.columns = {\n id: idColumnMeta,\n ...Object.fromEntries(Object.entries(userColumns).map(([name, column]) => [name, column.meta])),\n tombstone: tombstoneColumnMeta,\n };\n this.baseName = options?.baseName as BaseName;\n this.description = options?.description;\n }\n\n describe(description: string): TableBuilder<Cols, BaseName> {\n return new TableBuilder(this.userColumns, { baseName: this.baseName, description });\n }\n\n /** Type-only: the row shape returned by queries. Do not access at runtime. */\n get $row(): InferRow<Cols> {\n return null as never;\n }\n\n /**\n * Validate a CRDT event payload against the declared columns.\n * `item-created` payloads must contain every column without a default (nullable columns may be omitted);\n * `item-updated` payloads are partial and must not touch `id` or set `tombstone` to a deleted value.\n */\n validatePayload(\n payload: Record<string, unknown>,\n options?: { event?: \"item-created\" | \"item-updated\" },\n ): PayloadValidationResult {\n const event = options?.event ?? \"item-created\";\n const errors: string[] = [];\n\n for (const key of Object.keys(payload)) {\n if (!(key in this.columns)) {\n errors.push(`Unknown column \"${key}\"`);\n }\n }\n\n if (event === \"item-updated\") {\n if (\"id\" in payload) {\n errors.push(`Column \"id\" is immutable and cannot appear in an update payload`);\n }\n if (payload.tombstone === true || payload.tombstone === 1) {\n errors.push(`Column \"tombstone\" cannot be set to true/1 in an update payload; use an item-deleted event`);\n }\n }\n\n if (event === \"item-created\") {\n for (const [name, meta] of Object.entries(this.columns)) {\n if (name in payload || name === \"tombstone\" || meta.nullable || meta.hasDefault) {\n continue;\n }\n errors.push(`Missing required column \"${name}\"`);\n }\n }\n\n for (const [name, value] of Object.entries(payload)) {\n const meta = this.columns[name];\n if (!meta || (event === \"item-updated\" && name === \"id\")) {\n continue;\n }\n const error = validateValue(name, value, meta);\n if (error) {\n errors.push(error);\n }\n }\n\n return errors.length === 0 ? { success: true } : { success: false, errors };\n }\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"array\";\n return typeof value;\n}\n\nfunction validateValue(name: string, value: unknown, meta: ColumnMeta): string | null {\n if (value === null) {\n return meta.nullable ? null : `Column \"${name}\" is not nullable, got null`;\n }\n\n switch (meta.kind) {\n case \"text\":\n return typeof value === \"string\" ? null : `Column \"${name}\" expects text, got ${describeValue(value)}`;\n case \"integer\":\n return typeof value === \"number\" && Number.isInteger(value)\n ? null\n : `Column \"${name}\" expects an integer, got ${describeValue(value)}`;\n case \"real\":\n return typeof value === \"number\" && Number.isFinite(value)\n ? null\n : `Column \"${name}\" expects a number, got ${describeValue(value)}`;\n case \"boolean\":\n return typeof value === \"boolean\" || value === 0 || value === 1\n ? null\n : `Column \"${name}\" expects a boolean (true/false or 0/1), got ${describeValue(value)}`;\n case \"enum\": {\n if (typeof value !== \"string\") {\n return `Column \"${name}\" expects one of ${formatEnumValues(meta)}, got ${describeValue(value)}`;\n }\n return meta.enumValues?.includes(value)\n ? null\n : `Column \"${name}\" expects one of ${formatEnumValues(meta)}, got \"${value}\"`;\n }\n }\n}\n\nfunction formatEnumValues(meta: ColumnMeta): string {\n return (meta.enumValues ?? []).map((value) => `\"${value}\"`).join(\" | \");\n}\n\nfunction column<Value>(kind: ColumnKind, sqlType: SqliteStorageType): ColumnBuilder<Value> {\n return new ColumnBuilder<Value>({ kind, sqlType, nullable: false, hasDefault: false });\n}\n\nexport const t = {\n text: () => column<string>(\"text\", \"text\"),\n integer: () => column<number>(\"integer\", \"integer\"),\n real: () => column<number>(\"real\", \"real\"),\n /** Stored as INTEGER 0/1; always bind booleans as 0/1 when writing raw SQL. */\n boolean: () => column<boolean>(\"boolean\", \"integer\"),\n /**\n * Union of string literals stored as TEXT, e.g. `t.enum([\"movie\", \"tv\"])`. Unlike `$type`, the\n * allowed values are kept as runtime metadata, so payloads are validated against them.\n * For an open-ended set, use `t.text().$type<\"idle\" | (string & {})>()` instead.\n */\n enum: <const Values extends readonly [string, ...string[]]>(values: Values) =>\n new ColumnBuilder<Values[number]>({\n kind: \"enum\",\n sqlType: \"text\",\n nullable: false,\n hasDefault: false,\n enumValues: values,\n }),\n table: <Cols extends TableColumns, const BaseName extends string | undefined = undefined>(\n columns: Cols,\n options?: TableOptions<BaseName>,\n ) => new TableBuilder(columns, options),\n};\n","import type { CrdtStorage, OwnCrdtEvent } from \"./crdt-storage\";\n\nexport type CrdtStorageMutator<Database> = ReturnType<typeof createCrdtStorageMutator<Database>>;\n\ntype CommitEventOptions<Database, Table extends keyof Database & string> =\n | {\n type: \"item-created\";\n dataset: Table;\n item_id: string;\n payload: CreateEventPayload<Database, Table>;\n }\n | {\n type: \"item-updated\";\n dataset: Table;\n item_id: string;\n payload: UpdateEventPayload<Database, Table>;\n }\n | {\n type: \"item-deleted\";\n dataset: Table;\n item_id: string;\n };\n\ntype CreateEventPayload<Database, Table extends keyof Database> = Omit<Database[Table], \"tombstone\">;\ntype UpdateEventPayload<Database, Table extends keyof Database> = Omit<Partial<Database[Table]>, \"id\" | \"tombstone\">;\n\nexport function createCrdtStorageMutator<Database>({ storage }: { storage: CrdtStorage }) {\n const mapToStorageEvent = (event: CommitEventOptions<Database, keyof Database & string>): OwnCrdtEvent => {\n switch (event.type) {\n case \"item-created\":\n return {\n type: \"item-created\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-updated\":\n return {\n type: \"item-updated\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: JSON.stringify(event.payload),\n };\n case \"item-deleted\":\n return {\n type: \"item-deleted\",\n dataset: event.dataset,\n item_id: event.item_id,\n payload: \"{}\",\n };\n }\n };\n\n const enqueueEvents = (events: CommitEventOptions<Database, keyof Database & string>[]) => {\n storage.enqueueOwnEvents(events.map(mapToStorageEvent));\n };\n\n const createEvent = <Table extends keyof Database & string>(event: CommitEventOptions<Database, Table>) => {\n return event;\n };\n\n const enqueueEvent = (event: CommitEventOptions<Database, keyof Database & string>) => {\n storage.enqueueOwnEvents([mapToStorageEvent(event)]);\n };\n\n return {\n enqueueEvents,\n createEvent,\n enqueueEvent,\n };\n}\n","import type { SQLiteReactiveDb } from \"../memory-db/sqlite-reactive-db\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { quoteId } from \"../utils\";\nimport type { InternalCrdtStorage } from \"./crdt-storage\";\n\nexport function makeCrdtTable({\n db,\n baseTableName,\n crdtTableName,\n}: {\n db: SQLiteDbWrapper<any>;\n baseTableName: string;\n crdtTableName: string;\n}) {\n const tableSchema = db.dbSchema[baseTableName];\n\n if (!tableSchema) {\n throw new Error(`Table ${baseTableName} not found`);\n }\n\n const columns = new Map(tableSchema.columns.map((c) => [c.name, c]));\n\n const idColumn = columns.get(\"id\");\n if (!idColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"id\" column. CRDT tables must have an \"id\" column to identify items.`,\n );\n }\n if (idColumn.dataType.toUpperCase() !== \"TEXT\") {\n throw new Error(\n `Table \"${baseTableName}\": \"id\" column must be of type TEXT, got \"${idColumn.dataType}\". CRDT item IDs are stored as strings.`,\n );\n }\n\n const tombstoneColumn = columns.get(\"tombstone\");\n if (!tombstoneColumn) {\n throw new Error(\n `Table \"${baseTableName}\" is missing a required \"tombstone\" column. CRDT tables must have a \"tombstone\" INTEGER column for soft deletes.`,\n );\n }\n const tombstoneType = tombstoneColumn.dataType.toUpperCase();\n if (tombstoneType !== \"INTEGER\" && tombstoneType !== \"BOOLEAN\") {\n throw new Error(\n `Table \"${baseTableName}\": \"tombstone\" column must be of type INTEGER or BOOLEAN, got \"${tombstoneColumn.dataType}\". It is compared as 0/1 for soft deletes.`,\n );\n }\n\n db.execute(\n `\ncreate view ${quoteId(crdtTableName)} as\nselect * from ${quoteId(baseTableName)}\nwhere tombstone = 0;`,\n { loggerLevel: \"system\" },\n );\n\n const allColumnNames = tableSchema.columns.map((column) => column.name);\n\n const jsonPayload = (from: \"new\" | \"old\") =>\n `'{'||${allColumnNames.map((col) => `'\"${col}\":'||json_quote(${from}.${quoteId(col)})`).join(\"||','||\")}||'}'`;\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_created`)}\ninstead of insert on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_created('${baseTableName}', ${jsonPayload(\"new\")});\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_updated`)}\ninstead of update on ${quoteId(crdtTableName)}\nfor each row\nbegin\nselect handle_item_updated(\n '${baseTableName}',\n ${jsonPayload(\"old\")},\n ${jsonPayload(\"new\")}\n);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n\n db.execute(\n `\ncreate trigger ${quoteId(`${crdtTableName}_deleted`)}\ninstead of delete on ${quoteId(crdtTableName)}\nfor each row\nwhen old.tombstone = 0\nbegin\nselect handle_item_deleted('${baseTableName}', old.id);\nend;\n`,\n { loggerLevel: \"system\" },\n );\n}\n\nexport function registerCrdtFunctions({\n reactiveDb,\n storage,\n}: {\n reactiveDb: SQLiteReactiveDb<any>;\n storage: InternalCrdtStorage;\n}) {\n let eventApplied = false;\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_created\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, payloadRaw: string) => {\n const payload = JSON.parse(payloadRaw) as { id: string };\n\n storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {\n type: \"item-created\",\n dataset,\n item_id: payload.id,\n payload: payloadRaw,\n });\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_updated\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, oldPayloadRaw: string, newPayloadRaw: string) => {\n if (oldPayloadRaw === newPayloadRaw) {\n return undefined;\n }\n\n const tableSchema = reactiveDb.db.dbSchema[dataset];\n\n if (!tableSchema?.columns) {\n throw new Error(`Schema not found for dataset: ${dataset}`);\n }\n\n const oldPayload = JSON.parse(oldPayloadRaw);\n const newPayload = JSON.parse(newPayloadRaw);\n\n let hasDiff = false;\n const updatePayload = {} as Record<string, unknown>;\n\n for (const column of tableSchema.columns) {\n const oldValue = oldPayload[column.name];\n const newValue = newPayload[column.name];\n if (oldValue === newValue) {\n continue;\n }\n\n if (column.name === \"id\") {\n throw new Error(\n `Cannot update the \"id\" column of an item. It is used to identify the item and must be immutable.`,\n );\n }\n\n hasDiff = true;\n updatePayload[column.name] = newValue;\n }\n\n if (!hasDiff) {\n return;\n }\n\n storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {\n type: \"item-updated\",\n dataset,\n item_id: oldPayload.id,\n payload: JSON.stringify(updatePayload),\n });\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.db.createScalarFunction({\n name: \"handle_item_deleted\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, itemId: string) => {\n storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {\n type: \"item-deleted\",\n dataset,\n item_id: itemId,\n payload: \"{}\",\n });\n\n eventApplied = true;\n return undefined;\n },\n });\n\n reactiveDb.addEventListener(\"transaction-committed\", () => {\n if (eventApplied) {\n eventApplied = false;\n void storage.internal.processEnqueuedEvents();\n }\n });\n\n reactiveDb.addEventListener(\"transaction-rolled-back\", () => {\n eventApplied = false;\n });\n}\n","const dbIdRegex = /^[a-zA-Z][a-zA-Z\\-0-9]{2,63}$/;\n\nexport function validateDbId(dbId: string) {\n if (!dbIdRegex.test(dbId)) {\n throw new Error(\"Invalid dbId. Must be between 3 and 64 characters long and start with a letter.\");\n }\n}\n","import type { SyncedDb } from \"./sync-db\";\n\nconst devtoolsRegistrySymbol = Symbol.for(\"@sqlite-sync/devtools\");\n\nexport type SQLiteSyncDevtoolsInstance = {\n instanceId: string;\n dbId: string;\n createdAt: number;\n instance: SyncedDb<any>;\n};\n\nexport type SQLiteSyncDevtoolsSnapshot = {\n instances: readonly SQLiteSyncDevtoolsInstance[];\n};\n\nexport type SQLiteSyncDevtoolsRegistry = {\n version: 1;\n instances: Map<string, SQLiteSyncDevtoolsInstance>;\n subscribe(listener: () => void): () => void;\n getSnapshot(): SQLiteSyncDevtoolsSnapshot;\n register(instance: SQLiteSyncDevtoolsInstance): () => void;\n};\n\ntype RegistryGlobal = typeof globalThis & {\n [key: symbol]: SQLiteSyncDevtoolsRegistry | undefined;\n};\n\nfunction createSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const instances = new Map<string, SQLiteSyncDevtoolsInstance>();\n const listeners = new Set<() => void>();\n let snapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n };\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n const updateSnapshot = () => {\n snapshot = {\n instances: Array.from(instances.values()),\n };\n notify();\n };\n\n return {\n version: 1,\n instances,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return snapshot;\n },\n register(instance) {\n instances.set(instance.instanceId, instance);\n updateSnapshot();\n\n let isUnregistered = false;\n return () => {\n if (isUnregistered) return;\n isUnregistered = true;\n\n if (!instances.delete(instance.instanceId)) return;\n updateSnapshot();\n };\n },\n };\n}\n\nexport function getOrCreateSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const registryGlobal = globalThis as RegistryGlobal;\n\n registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();\n\n return registryGlobal[devtoolsRegistrySymbol];\n}\n","import { xxhash } from \"../hash\";\nimport type { HLCCounter } from \"../hlc\";\nimport type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { applyMemoryDbSchema, type MemoryDbSchema, memoryDbConfig } from \"../migrations/system-schema\";\nimport type { CrdtTableConfig, SyncDbSchema } from \"../sqlite-crdt/crdt-schema\";\nimport { createCrdtStorage } from \"../sqlite-crdt/crdt-storage\";\nimport { makeCrdtTable, registerCrdtFunctions } from \"../sqlite-crdt/make-crdt-table\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { SQLiteReactiveDb } from \"./sqlite-reactive-db\";\n\ntype MemoryDbOptions<Database> = {\n nodeId: string;\n migrator: SyncDbMigrator;\n reactiveDb: SQLiteReactiveDb<Database>;\n hlcCounter: HLCCounter;\n crdtTables: CrdtTableConfig[];\n initializeSchema?: boolean;\n initialSyncId?: number;\n eventHlcAccumulator?: StoredValue<string>;\n syncDbSchema: Pick<SyncDbSchema, \"tables\" | \"tablesConfig\">;\n};\n\nexport async function createMemoryDb<Database>({\n nodeId,\n migrator,\n reactiveDb: _reactiveDb,\n hlcCounter,\n crdtTables,\n initializeSchema = true,\n initialSyncId,\n eventHlcAccumulator,\n syncDbSchema,\n}: MemoryDbOptions<Database>) {\n await xxhash.ensureLoaded();\n\n const reactiveDb = _reactiveDb as unknown as SQLiteReactiveDb<MemoryDbSchema>;\n const db = reactiveDb.db;\n\n if (initializeSchema) {\n applyMemoryDbSchema(db);\n for (const table of crdtTables) {\n makeCrdtTable({\n db,\n baseTableName: table.baseTableName,\n crdtTableName: table.crdtTableName,\n });\n }\n }\n\n const crdtStorage = createCrdtStorage({\n nodeId,\n initialLocalSyncId: initialSyncId ?? getCurrentSyncId(db),\n hlc: hlcCounter,\n migrator,\n db,\n dbConfig: memoryDbConfig,\n eventHlcAccumulator,\n schema: syncDbSchema,\n });\n\n registerCrdtFunctions({\n reactiveDb,\n storage: crdtStorage,\n });\n\n return {\n crdtStorage,\n };\n}\n\nfunction getCurrentSyncId(db: SQLiteDbWrapper<MemoryDbSchema>) {\n return (\n db.execute<{ syncId: number }>(\"SELECT coalesce(max(sync_id), 0) AS syncId FROM persisted_crdt_events\", {\n loggerLevel: \"system\",\n }).rows[0]?.syncId ?? 0\n );\n}\n","import {\n createDeferredPromise,\n createTypedEventTarget,\n type DeferredPromise,\n noop,\n type TypedEventTarget,\n} from \"../utils\";\nimport type {\n AsyncRpc,\n WorkerBroadcastChannels,\n WorkerConfig,\n WorkerErrorResponseMessage,\n WorkerInitMessage,\n WorkerNotificationMessage,\n WorkerRequestMessage,\n WorkerRequestMethod,\n WorkerResponseMessage,\n WorkerRpc,\n WorkerState,\n} from \"./worker-common\";\nimport { isWorkerErrorResponseMessage, isWorkerNotificationMessage, isWorkerResponseMessage } from \"./worker-common\";\n\ntype NotificationEvents = {\n [K in WorkerNotificationMessage[\"notificationType\"]]: Extract<WorkerNotificationMessage, { notificationType: K }>;\n};\n\nexport const createWorkerDbClient = async ({\n broadcastChannels,\n worker,\n config,\n}: {\n broadcastChannels: WorkerBroadcastChannels;\n worker: Worker;\n config: WorkerConfig;\n}) => {\n const eventTarget = createTypedEventTarget<NotificationEvents>();\n const workerRequestsMap = new Map<string, DeferredPromise<unknown>>();\n let isDisposed = false;\n\n const queryWorker = <TMethod extends WorkerRequestMethod>(\n method: TMethod,\n args: Parameters<WorkerRpc[TMethod]>,\n ): Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>> => {\n if (isDisposed) {\n return Promise.reject(new Error(\"Worker client disposed\"));\n }\n const requestId = crypto.randomUUID();\n const promise = createDeferredPromise<unknown>({\n timeout: 30_000,\n onTimeout: () => workerRequestsMap.delete(requestId),\n });\n workerRequestsMap.set(requestId, promise);\n\n const request: WorkerRequestMessage<TMethod> = {\n type: \"request\",\n requestId,\n method,\n args,\n };\n\n broadcastChannels.requests.postMessage(request);\n\n return promise.promise as Promise<Awaited<ReturnType<WorkerRpc[TMethod]>>>;\n };\n\n const handleWorkerResponse = (message: WorkerResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.resolve(message.data);\n workerRequestsMap.delete(message.requestId);\n };\n\n const handleWorkerError = (message: WorkerErrorResponseMessage) => {\n const promise = workerRequestsMap.get(message.requestId);\n if (!promise) {\n return;\n }\n\n promise.reject(new Error(message.error));\n workerRequestsMap.delete(message.requestId);\n };\n\n broadcastChannels.responses.onmessage = (event) => {\n const message = event.data;\n\n if (isWorkerResponseMessage(message)) {\n handleWorkerResponse(message);\n } else if (isWorkerErrorResponseMessage(message)) {\n handleWorkerError(message);\n } else if (isWorkerNotificationMessage(message)) {\n eventTarget.dispatchEvent(message.notificationType, message);\n }\n };\n\n const rpc: AsyncRpc<WorkerRpc> = {\n execute: (query) => queryWorker(\"execute\", [query]),\n getSnapshot: () => queryWorker(\"getSnapshot\", []),\n pushTabEvents: (request) => queryWorker(\"pushTabEvents\", [request]),\n pullEvents: (params) => queryWorker(\"pullEvents\", [params]),\n postState: () => queryWorker(\"postState\", []),\n goOnline: () => queryWorker(\"goOnline\", []),\n goOffline: () => queryWorker(\"goOffline\", []),\n requestReload: (options) => queryWorker(\"requestReload\", [options]),\n };\n\n const statePromise = awaitWorkerState(eventTarget);\n postWorkerConfig(worker, config);\n // On first tab, the worker may not have its BroadcastChannel listener ready yet,\n // so this request can be silently dropped and timeout. The worker will independently\n // post state at the end of init. For subsequent tabs, this triggers the already-running\n // worker to send its current state.\n rpc.postState().catch(noop);\n\n let workerState = await statePromise;\n\n eventTarget.addEventListener(\"state-changed\", (event) => {\n workerState = event.payload.state;\n });\n\n const dispose = () => {\n isDisposed = true;\n broadcastChannels.responses.onmessage = null;\n for (const [id, deferred] of workerRequestsMap) {\n deferred.reject(new Error(\"Worker client disposed\"));\n workerRequestsMap.delete(id);\n }\n };\n\n return {\n ...rpc,\n subscribe: eventTarget.addEventListener,\n getState: () => workerState,\n dispose,\n };\n};\n\nfunction awaitWorkerState(eventTarget: TypedEventTarget<NotificationEvents>) {\n const promise = createDeferredPromise<WorkerState>({ timeout: 15_000 });\n\n const subscription = eventTarget.addEventListener(\"state-changed\", (event) => {\n promise.resolve(event.payload.state);\n subscription.unsubscribe();\n });\n\n return promise.promise;\n}\n\nfunction postWorkerConfig(worker: Worker, config: WorkerConfig) {\n const configMessage: WorkerInitMessage = {\n type: \"init\",\n config,\n };\n worker.postMessage(configMessage);\n}\n","import { validateDbId } from \"./db-id\";\nimport { getOrCreateSQLiteSyncDevtoolsRegistry } from \"./devtools-registry\";\nimport { createExportImport } from \"./export-import\";\nimport { HLCCounter } from \"./hlc\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\nimport { createMemoryDb } from \"./memory-db/memory-db\";\nimport { createSQLiteReactiveDb } from \"./memory-db/sqlite-reactive-db\";\nimport type { SyncDbMigrator } from \"./migrations/migrator\";\nimport type { SyncDbSchema } from \"./sqlite-crdt/crdt-schema\";\nimport { createCrdtSyncRemoteSource } from \"./sqlite-crdt/crdt-sync-remote-source\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport { createDeferredPromise, generateId } from \"./utils\";\nimport { createWorkerDbClient } from \"./worker-db/db-worker-client\";\nimport { createBroadcastChannels, syncDbClientLockName } from \"./worker-db/worker-common\";\n\ntype SyncedDbOptions<Database, Props = undefined> = {\n dbId: string;\n worker: Worker;\n workerProps: Props;\n syncDbSchema: SyncDbSchema<Database>;\n};\n\nconst defaultLogger: Logger = (type, message, level = \"info\") => {\n const logMessage = `[${type}] ${message}`;\n switch (level) {\n case \"info\":\n console.log(logMessage);\n break;\n case \"warning\":\n console.warn(logMessage);\n break;\n case \"error\":\n console.error(logMessage);\n break;\n case \"trace\":\n console.trace(logMessage);\n break;\n }\n};\n\nexport async function createSyncedDb<Database, Props = undefined>(options: SyncedDbOptions<Database, Props>) {\n validateDbId(options.dbId);\n\n const perf = startPerformanceLogger(defaultLogger);\n\n const instanceId = generateId();\n const tabId = generateId();\n\n const broadcastChannels = createBroadcastChannels(options.dbId);\n\n const clientLockAcquired = createDeferredPromise<void>();\n const clientLockRelease = createDeferredPromise<void>();\n navigator.locks.request(`${syncDbClientLockName}-${options.dbId}`, { mode: \"shared\" }, () => {\n clientLockAcquired.resolve();\n return clientLockRelease.promise;\n });\n await clientLockAcquired.promise;\n\n const workerClient = await createWorkerDbClient({\n worker: options.worker,\n config: {\n clientId: generateId(),\n dbId: options.dbId,\n props: options.workerProps as never,\n },\n broadcastChannels,\n });\n\n const hlcCounter = new HLCCounter(tabId, () => Date.now());\n\n const workerClientSnapshot = await workerClient.getSnapshot();\n const reactiveDb = await createSQLiteReactiveDb<Database>({\n snapshot: workerClientSnapshot.file,\n logger: defaultLogger,\n });\n\n const memoryDbMigrator: SyncDbMigrator = {\n currentSchemaVersion: workerClientSnapshot.schemaVersion,\n latestSchemaVersion: workerClientSnapshot.schemaVersion,\n migrateDbToLatest: () => {\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvent: (event, targetVersion) => {\n if (event.schema_version === targetVersion) {\n return event;\n }\n throw new Error(\"Memory DB migrations are not implemented\");\n },\n migrateEvents: (events) => events,\n };\n const { crdtStorage } = await createMemoryDb({\n nodeId: tabId,\n migrator: memoryDbMigrator,\n reactiveDb: reactiveDb,\n hlcCounter,\n crdtTables: options.syncDbSchema.tablesConfig,\n syncDbSchema: options.syncDbSchema,\n });\n\n const pullSyncId = createStoredValue({\n initialValue: workerClientSnapshot.syncId,\n });\n const pushSyncId = createStoredValue({\n initialValue: 0,\n });\n const tabRemoteSource = createCrdtSyncRemoteSource({\n bufferSize: 500,\n pullSyncId,\n pushSyncId,\n storage: crdtStorage,\n nodeId: tabId,\n migrator: memoryDbMigrator,\n remoteFactory: ({ onEventsAvailable }) => {\n const subscription = workerClient.subscribe(\"new-event-chunk-applied\", (event) => {\n onEventsAvailable({ newSyncId: event.payload.newSyncId, remoteEventHlcSum: event.payload.eventHlcSum });\n });\n\n return {\n pullEvents: (request) => workerClient.pullEvents(request),\n pushEvents: (request) => workerClient.pushTabEvents(request),\n disconnect: () => {\n subscription.unsubscribe();\n },\n };\n },\n });\n tabRemoteSource.goOnline();\n\n const reloadRequestedSubscription = workerClient.subscribe(\"reload-requested\", () => {\n globalThis.location?.reload();\n });\n\n perf.logEnd(\"createSyncedDb\", \"initialized\", \"info\");\n\n const { exportData, importData } = createExportImport({\n reactiveDb,\n crdtStorage,\n tablesConfig: options.syncDbSchema.tablesConfig,\n schemaVersion: workerClientSnapshot.schemaVersion,\n });\n\n let isDisposed = false;\n let unregisterDevtools: (() => void) | undefined;\n const dispose = async () => {\n if (isDisposed) return;\n isDisposed = true;\n\n unregisterDevtools?.();\n reloadRequestedSubscription.unsubscribe();\n clientLockRelease.resolve();\n await tabRemoteSource.dispose();\n broadcastChannels.requests.close();\n broadcastChannels.responses.close();\n workerClient.dispose();\n reactiveDb.dispose();\n };\n\n const syncedDb = {\n db: {\n execute: reactiveDb.db.execute.bind(reactiveDb.db),\n executeKysely: reactiveDb.db.executeKysely.bind(reactiveDb.db),\n executeTransaction: reactiveDb.db.executeTransaction.bind(reactiveDb.db),\n createLiveQuery: reactiveDb.createLiveQuery.bind(reactiveDb),\n getSharedLiveQuery: reactiveDb.getSharedLiveQuery.bind(reactiveDb),\n },\n state: {\n getState: workerClient.getState.bind(workerClient),\n subscribe: (onChange: () => void) => {\n const { unsubscribe } = workerClient.subscribe(\"state-changed\", onChange);\n return unsubscribe;\n },\n goOnline: workerClient.goOnline.bind(workerClient),\n goOffline: workerClient.goOffline.bind(workerClient),\n },\n /**\n * Ask the elected worker to broadcast a page reload to all tabs for this dbId.\n *\n * With `clean: true` the worker durably records a reset request epoch before\n * broadcasting, so the worker elected on the next startup initializes with\n * `clearOnInit: true` and wipes the persisted DB. Destructive — use as a\n * recovery path when the durable worker DB may be de-synced.\n *\n * Pending in-memory tab events are not preserved, and the returned promise\n * may never settle in the caller — the page typically unloads first.\n */\n requestReload: async (options: { clean: boolean }) => {\n await workerClient.requestReload(options);\n // Primary path: this tab receives the worker's \"reload-requested\" broadcast\n // like every other tab. Fallback in case the broadcast is missed — in the\n // normal case the page is already unloading and this timeout never fires.\n setTimeout(() => globalThis.location?.reload(), 250);\n },\n subscribe: workerClient.subscribe,\n exportData,\n importData,\n dispose,\n _internal: {\n executeAsync: workerClient.execute.bind(workerClient),\n getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),\n getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),\n crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),\n crdtTablesConfig: options.syncDbSchema.tablesConfig,\n schemaVersion: workerClientSnapshot.schemaVersion,\n migrationVersions: Object.keys(options.syncDbSchema.migrations)\n .map(Number)\n .sort((a, b) => a - b),\n },\n };\n\n unregisterDevtools = getOrCreateSQLiteSyncDevtoolsRegistry().register({\n instanceId,\n dbId: options.dbId,\n createdAt: Date.now(),\n instance: syncedDb,\n });\n\n return syncedDb;\n}\n\nexport type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;\n"],"mappings":"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","names":["entry","column","column","options"]}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { aB as EventsPullResponse, aa as EventsPushResponse } from './crdt-sync-remote-source-
|
|
2
|
-
export { ar as jsonSafeParse } from './crdt-sync-remote-source-
|
|
1
|
+
import { aB as EventsPullResponse, aa as EventsPushResponse } from './crdt-sync-remote-source-yXp-iMEd.js';
|
|
2
|
+
export { ar as jsonSafeParse } from './crdt-sync-remote-source-yXp-iMEd.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import 'kysely';
|
|
5
5
|
import '@sqlite.org/sqlite-wasm';
|
package/dist/worker.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { az as CreateRemoteSourceFactory, ax as WorkerConfig,
|
|
2
|
-
export { a8 as EventsPullRequest, a9 as EventsPushRequest, aa as EventsPushResponse, aA as GetEventsBatch } from './crdt-sync-remote-source-
|
|
1
|
+
import { az as CreateRemoteSourceFactory, ax as WorkerConfig, d as SyncDbSchema, L as Logger } from './crdt-sync-remote-source-yXp-iMEd.js';
|
|
2
|
+
export { a8 as EventsPullRequest, a9 as EventsPushRequest, aa as EventsPushResponse, aA as GetEventsBatch } from './crdt-sync-remote-source-yXp-iMEd.js';
|
|
3
3
|
import { b as ResetStore } from './reset-state-D6UslXaj.js';
|
|
4
4
|
import 'kysely';
|
|
5
5
|
import '@sqlite.org/sqlite-wasm';
|