@sqlite-sync/core 0.8.2 → 0.9.1

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.
@@ -0,0 +1,1203 @@
1
+ import { ColumnDataType, ColumnDefinitionBuilderCallback, ColumnType, Compilable, CompiledQuery, CreateIndexBuilder, CreateTableBuilder, Expression, Kysely, SchemaModule } from "kysely";
2
+ import { Database, FunctionOptions, SqlValue, Sqlite3Static } from "@sqlite.org/sqlite-wasm";
3
+ //#region src/dummy-kysely.d.ts
4
+ declare const dummyKysely: Kysely<any>;
5
+ //#endregion
6
+ //#region src/sqlite-crdt/crdt-table-schema.d.ts
7
+ type NewCrdtEvent = {
8
+ type: CrdtEventType;
9
+ dataset: string;
10
+ item_id: string;
11
+ payload: Record<string, unknown>;
12
+ };
13
+ type CrdtEventType = "item-created" | "item-updated" | "item-deleted";
14
+ type CrdtEventStatus = "pending" | "applied" | "failed" | "deduped";
15
+ /** Persisted on applied events that were accepted but did not mutate materialized state. */
16
+ declare const CRDT_EVENT_NO_OP_PAYLOAD = "no-op";
17
+ declare function isNoOpCrdtEventPayload(payload: string): payload is "no-op";
18
+ type CrdtEventOrigin = "remote" | "own" | "own-applied" | "local";
19
+ type PersistedCrdtEvent = {
20
+ schema_version: number;
21
+ sync_id: number;
22
+ status: CrdtEventStatus;
23
+ type: CrdtEventType;
24
+ timestamp: string;
25
+ origin: CrdtEventOrigin;
26
+ source_node_id: string;
27
+ dataset: string;
28
+ item_id: string;
29
+ payload: string;
30
+ };
31
+ type CrdtUpdateLogItem = {
32
+ dataset: string;
33
+ item_id: string;
34
+ payload: string;
35
+ };
36
+ type CrdtUpdateLogPayload = Record<string, string>;
37
+ //#endregion
38
+ //#region src/sqlite-crdt/stored-value.d.ts
39
+ type StoredValue<T> = {
40
+ get current(): T;
41
+ set current(newValue: T);
42
+ };
43
+ declare function createStoredValue<T>({ initialValue, saveToStorage }: {
44
+ initialValue: T;
45
+ saveToStorage?: (value: T) => void;
46
+ }): StoredValue<T>;
47
+ //#endregion
48
+ //#region src/migrations/migrator.d.ts
49
+ type MigratableEvent = {
50
+ schema_version: number;
51
+ type: CrdtEventType;
52
+ dataset: string;
53
+ item_id: string;
54
+ payload: string;
55
+ };
56
+ type CrdtEventTransformer = (event: NewCrdtEvent) => NewCrdtEvent | null;
57
+ type MigrationStepSql = {
58
+ sql: string;
59
+ parameters?: readonly unknown[];
60
+ } | Compilable | ((db: Kysely<unknown>) => Compilable);
61
+ type UpdateLogMutation = {
62
+ type: "rename-table";
63
+ oldTable: string;
64
+ newTable: string;
65
+ } | {
66
+ type: "drop-table";
67
+ table: string;
68
+ } | {
69
+ type: "rename-column";
70
+ table: string;
71
+ oldColumn: string;
72
+ newColumn: string;
73
+ } | {
74
+ type: "add-column";
75
+ table: string;
76
+ column: string;
77
+ } | {
78
+ type: "drop-column";
79
+ table: string;
80
+ column: string;
81
+ };
82
+ type MigrationStep = {
83
+ sql: MigrationStepSql | MigrationStepSql[];
84
+ eventTransformer?: MigrationEventTransformers;
85
+ updateLogMutations?: UpdateLogMutation[];
86
+ };
87
+ type RawMigrationStep = {
88
+ sql: MigrationSql[];
89
+ eventTransformer?: CompiledMigrationEventTransformer;
90
+ updateLogMutations?: UpdateLogMutation[];
91
+ };
92
+ type MigrationSql = {
93
+ sql: string;
94
+ parameters: readonly unknown[];
95
+ };
96
+ type DataTypeExpression = ColumnDataType | Expression<any>;
97
+ declare const migrationSteps: {
98
+ createTable: (table: string, build: (table: CreateTableBuilder<string, never>) => Compilable) => MigrationStep;
99
+ dropTable: (table: string) => MigrationStep;
100
+ createIndex: (indexName: string, build: (index: CreateIndexBuilder) => Compilable) => MigrationStep;
101
+ dropIndex: (indexName: string) => MigrationStep;
102
+ renameTable: ({ oldTable, newTable }: {
103
+ oldTable: string;
104
+ newTable: string;
105
+ }) => MigrationStep;
106
+ renameColumn: ({ table, oldColumn, newColumn }: {
107
+ table: string;
108
+ oldColumn: string;
109
+ newColumn: string;
110
+ }) => MigrationStep;
111
+ addColumn: ({ table, column, type, defaultValue, build }: {
112
+ table: string;
113
+ column: string;
114
+ type: DataTypeExpression;
115
+ defaultValue: number | boolean | string | null;
116
+ build?: ColumnDefinitionBuilderCallback;
117
+ }) => MigrationStep;
118
+ dropColumn: ({ table, column }: {
119
+ table: string;
120
+ column: string;
121
+ }) => MigrationStep;
122
+ };
123
+ type MigrationEventTransformers = Record<string, CrdtEventTransformer>;
124
+ type CompiledMigrationEventTransformer = (event: NewCrdtEvent) => NewCrdtEvent | null;
125
+ declare function createMigrations(buildMigrations: (builder: typeof migrationSteps) => Record<number, MigrationStep[]>): Record<number, RawMigrationStep>;
126
+ type Migrations = ReturnType<typeof createMigrations>;
127
+ type MigrationsDb = {
128
+ startTransaction: (callback: (tx: MigrationsTransaction) => void) => void;
129
+ };
130
+ type MigrationsTransaction = {
131
+ execute: (sql: string, parameters: readonly unknown[], meta?: {
132
+ loggerLevel?: "system";
133
+ }) => void;
134
+ };
135
+ declare function createMigrator({ migrations, schemaVersion, updateLogTableName }: {
136
+ migrations: Migrations;
137
+ schemaVersion: StoredValue<number>;
138
+ updateLogTableName?: string;
139
+ }): {
140
+ latestSchemaVersion: number;
141
+ readonly currentSchemaVersion: number;
142
+ migrateDbToLatest: (db: MigrationsDb) => void;
143
+ migrateEvent: <Event extends MigratableEvent>(event: Event, targetVersion?: number) => Event | null;
144
+ migrateEvents: <Event extends MigratableEvent>(events: Event[], targetVersion?: number) => Event[];
145
+ };
146
+ type SyncDbMigrator = ReturnType<typeof createMigrator>;
147
+ //#endregion
148
+ //#region src/schema/table-builder.d.ts
149
+ type ColumnKind = "text" | "integer" | "real" | "boolean" | "enum";
150
+ type SqliteStorageType = "text" | "integer" | "real";
151
+ /**
152
+ * How much of a table an AI agent may use. Consumed by `@sqlite-sync/ai`, which rejects
153
+ * mutations to `read-only` tables, and leaves `hidden` tables out of the generated schema doc
154
+ * while rejecting queries that read them.
155
+ */
156
+ type AiAccess = "read-write" | "read-only" | "hidden";
157
+ /**
158
+ * Which replicas may author CRDT events for a table. `"any"` (the default) lets every replica
159
+ * write. `"server"` events are dropped from client pushes.
160
+ */
161
+ type WriteOrigin = "any" | "server";
162
+ type ColumnMeta = {
163
+ kind: ColumnKind;
164
+ /** Storage type used in generated DDL. Booleans store as integer 0/1. */
165
+ sqlType: SqliteStorageType;
166
+ nullable: boolean;
167
+ hasDefault: boolean;
168
+ /** Declared default in JS form (booleans as booleans). */
169
+ defaultValue?: unknown;
170
+ /** Allowed values for `enum` columns. */
171
+ enumValues?: readonly string[];
172
+ description?: string;
173
+ };
174
+ declare class ColumnBuilder<Value, HasDefault extends boolean = false> {
175
+ readonly meta: ColumnMeta;
176
+ readonly "~types": {
177
+ value: Value;
178
+ hasDefault: HasDefault;
179
+ };
180
+ constructor(meta: ColumnMeta);
181
+ /** Allow SQL NULL; widens the value type with `null`. */
182
+ nullable(): ColumnBuilder<Value | null, HasDefault>;
183
+ /** Declare a column default. The value is used both in DDL and when migrating older events. */
184
+ default(value: Value): ColumnBuilder<Value, true>;
185
+ /** Narrow the TypeScript value type without changing storage, e.g. `t.text().$type<"movie" | "tv">()`. */
186
+ $type<Narrowed extends Value>(): ColumnBuilder<Narrowed, HasDefault>;
187
+ /** Human/AI-readable description, surfaced in generated schema docs. */
188
+ describe(description: string): ColumnBuilder<Value, HasDefault>;
189
+ }
190
+ type AnyColumnBuilder = ColumnBuilder<any, boolean>;
191
+ type TableColumns = Record<string, AnyColumnBuilder>;
192
+ type AnyTableBuilder = TableBuilder<any, any>;
193
+ type SyncSchemaTables = Record<string, AnyTableBuilder>;
194
+ type TableOptions<BaseName extends string | undefined = string | undefined> = {
195
+ /** Override the materialized base table name (defaults to the crdt table name prefixed with "_"). */
196
+ baseName?: BaseName;
197
+ description?: string;
198
+ };
199
+ type Simplify$1<T> = { [K in keyof T]: T[K]; } & {};
200
+ type ColumnValue<Column> = Column extends ColumnBuilder<infer Value, boolean> ? Value : never;
201
+ type InferRow<Cols extends TableColumns> = Simplify$1<{
202
+ id: string;
203
+ } & { [K in keyof Cols]: ColumnValue<Cols[K]>; } & {
204
+ tombstone?: boolean;
205
+ }>;
206
+ type PayloadValidationResult = {
207
+ success: true;
208
+ } | {
209
+ success: false;
210
+ errors: string[];
211
+ };
212
+ declare class TableBuilder<Cols extends TableColumns, BaseName extends string | undefined = undefined> {
213
+ #private;
214
+ readonly userColumns: Cols;
215
+ readonly "~baseName": BaseName;
216
+ /** All columns in DDL order, including the auto-injected `id` and `tombstone`. */
217
+ readonly columns: Record<string, ColumnMeta>;
218
+ readonly baseName: BaseName;
219
+ readonly description: string | undefined;
220
+ /** AI access declared via `.ai()`; "read-write" unless narrowed. */
221
+ get aiAccess(): AiAccess;
222
+ /** Who may author events for this table; "any" unless narrowed via `.writes()`. */
223
+ get writeOrigin(): WriteOrigin;
224
+ constructor(userColumns: Cols, options?: TableOptions<BaseName>);
225
+ /** Rebuilds the table with `overrides` applied, carrying over state kept outside the options. */
226
+ private withOptions;
227
+ describe(description: string): TableBuilder<Cols, BaseName>;
228
+ /** Restrict what an AI agent may do with this table; see {@link AiAccess}. */
229
+ ai(access: AiAccess): TableBuilder<Cols, BaseName>;
230
+ /** Restrict which replicas may author events for this table; see {@link WriteOrigin}. */
231
+ writes(origin: WriteOrigin): TableBuilder<Cols, BaseName>;
232
+ /** Type-only: the row shape returned by queries. Do not access at runtime. */
233
+ get $row(): InferRow<Cols>;
234
+ /**
235
+ * Validate a CRDT event payload against the declared columns.
236
+ * `item-created` payloads must contain every column without a default (nullable columns may be omitted);
237
+ * `item-updated` payloads are partial and must not touch `id` or set `tombstone` to a deleted value.
238
+ */
239
+ validatePayload(payload: Record<string, unknown>, options?: {
240
+ event?: "item-created" | "item-updated";
241
+ }): PayloadValidationResult;
242
+ }
243
+ declare const t: {
244
+ text: () => ColumnBuilder<string, false>;
245
+ integer: () => ColumnBuilder<number, false>;
246
+ real: () => ColumnBuilder<number, false>;
247
+ /** Stored as INTEGER 0/1; always bind booleans as 0/1 when writing raw SQL. */
248
+ boolean: () => ColumnBuilder<boolean, false>;
249
+ /**
250
+ * Union of string literals stored as TEXT, e.g. `t.enum(["movie", "tv"])`. Unlike `$type`, the
251
+ * allowed values are kept as runtime metadata, so payloads are validated against them.
252
+ * For an open-ended set, use `t.text().$type<"idle" | (string & {})>()` instead.
253
+ */
254
+ enum: <const Values extends readonly [string, ...string[]]>(values: Values) => ColumnBuilder<Values[number], false>;
255
+ table: <Cols extends TableColumns, const BaseName extends string | undefined = undefined>(columns: Cols, options?: TableOptions<BaseName>) => TableBuilder<Cols, BaseName>;
256
+ };
257
+ //#endregion
258
+ //#region src/sqlite-crdt/crdt-schema.d.ts
259
+ type CrdtTableConfig = {
260
+ baseTableName: string;
261
+ crdtTableName: string;
262
+ };
263
+ interface SyncDbSchema<ClientDB = {}, ServerDB = {}, MutationsDB = {}> {
264
+ get tablesConfig(): CrdtTableConfig[];
265
+ get migrations(): Migrations;
266
+ get tables(): SyncSchemaTables;
267
+ "~clientSchema": ClientDB;
268
+ "~serverSchema": ServerDB;
269
+ "~mutationsSchema": MutationsDB;
270
+ }
271
+ type ReadonlyTable<Table extends Record<string, unknown>> = { [K in keyof Table]: ColumnType<Table[K], never, never>; };
272
+ //#endregion
273
+ //#region src/hlc.d.ts
274
+ interface HLC {
275
+ timestamp: number;
276
+ counter: number;
277
+ nodeId: string;
278
+ }
279
+ declare class HLCCounter {
280
+ private timestamp;
281
+ private counter;
282
+ private nodeId;
283
+ private readonly getTimestamp;
284
+ private readonly maxDrift;
285
+ constructor(nodeId: string, getTimestamp: () => number, maxDrift?: number);
286
+ getCurrentHLC(): HLC;
287
+ getNextHLC(): HLC;
288
+ mergeHLC(hlc: HLC): void;
289
+ }
290
+ declare function serializeHLC(hlc: HLC): string;
291
+ declare function deserializeHLC(serialized: string): HLC;
292
+ declare function compareHLC(one: HLC, two: HLC): number;
293
+ //#endregion
294
+ //#region src/introspection.d.ts
295
+ type TableMetadata = {
296
+ name: string;
297
+ isView: boolean;
298
+ columns: ColumnMetadata[];
299
+ };
300
+ type DatabaseIntrospection = Record<string, TableMetadata>;
301
+ type ColumnMetadata = {
302
+ name: string;
303
+ dataType: string;
304
+ isNullable: boolean;
305
+ isAutoIncrementing: boolean;
306
+ hasDefaultValue: boolean;
307
+ defaultValueSql: string | null;
308
+ isPrimaryKey: boolean;
309
+ comment: undefined;
310
+ };
311
+ declare function introspectDb<BaseDatabase>(_db: SQLiteDbWrapper<BaseDatabase>): DatabaseIntrospection;
312
+ //#endregion
313
+ //#region src/logger.d.ts
314
+ type LogLevel = "info" | "warning" | "error" | "trace" | "system";
315
+ type Logger = (type: string, message: string, level?: LogLevel) => void;
316
+ type PerformanceLogger = {
317
+ restart: () => void;
318
+ logEnd: (type: string, message: string, level?: LogLevel) => void;
319
+ };
320
+ declare const startPerformanceLogger: (logger: Logger | undefined, level?: LogLevel) => PerformanceLogger;
321
+ //#endregion
322
+ //#region src/sqlite-db-wrapper.d.ts
323
+ type ExecuteParams = {
324
+ sql: string;
325
+ parameters: readonly unknown[];
326
+ };
327
+ type ExecuteResult<T> = {
328
+ rows: T[];
329
+ };
330
+ type PreparedStatement<TParams extends unknown[], TResult> = {
331
+ execute: (parameters: TParams) => TResult[];
332
+ finalize: () => void;
333
+ isFinalized: boolean;
334
+ };
335
+ type ScalarFunctionOptions<TArgs extends readonly SqlValue[], TResult extends SqlValue | undefined> = {
336
+ name: string;
337
+ callback: (...args: TArgs) => TResult;
338
+ } & Pick<FunctionOptions, "deterministic" | "directOnly" | "innocuous">;
339
+ type SqliteWrapperOptions = {
340
+ logger?: Logger;
341
+ loggerPrefix?: string;
342
+ sqlite3: Sqlite3Static;
343
+ db: () => Database;
344
+ };
345
+ type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<SQLiteDbWrapper<TDatabase>, "sql" | "execute" | "executePrepared" | "executePreparedRaw" | "executeKysely">;
346
+ type InternalSQLiteTransactionWrapper<TDatabase = unknown> = Pick<SQLiteDbWrapper<TDatabase>, "executePrepared" | "executePreparedRaw">;
347
+ type InternalSQLiteWrapper<TDatabase = unknown> = InternalSQLiteTransactionWrapper<TDatabase> & {
348
+ executeTransaction: (callback: (db: InternalSQLiteTransactionWrapper<TDatabase>) => void) => void;
349
+ };
350
+ type QueryMetaOpts = {
351
+ loggerLevel?: "info" | "system";
352
+ };
353
+ /** Runs after user SQL succeeds, before its transaction or savepoint is committed. */
354
+ type AfterMutatingStatement<TDatabase> = (db: InternalSQLiteTransactionWrapper<TDatabase>) => void;
355
+ type ExecuteOptions = QueryMetaOpts & {
356
+ /** For internal mutations whose effects must not be processed by afterMutatingStatement. */
357
+ skipAfterMutatingStatement?: boolean;
358
+ };
359
+ declare class SQLiteDbWrapper<TDatabase = unknown> {
360
+ private db;
361
+ private sqlite3;
362
+ private logger?;
363
+ private loggerPrefix?;
364
+ private loadedDbSchema;
365
+ private readonly dataPointers;
366
+ private preparedStatements;
367
+ private preparedStatementsMap;
368
+ private preparedRawStatementsMap;
369
+ private afterMutatingStatement;
370
+ constructor(opts: SqliteWrapperOptions);
371
+ get ensureDb(): Database;
372
+ get dbSchema(): DatabaseIntrospection;
373
+ private executeSql;
374
+ execute<T = unknown>(opts: ExecuteParams | string | CompiledQuery<T>, options?: ExecuteOptions): ExecuteResult<T>;
375
+ setAfterMutatingStatement(callback: AfterMutatingStatement<TDatabase>): void;
376
+ executeTransaction<T>(callback: (db: SQLiteTransactionWrapper<TDatabase>) => T): T;
377
+ isInTransaction(): boolean;
378
+ beginTransaction(): {
379
+ commit: () => void;
380
+ rollback: () => void;
381
+ };
382
+ private beginStatementTransaction;
383
+ prepare<TParams extends unknown[], TResult>(sql: string, opts?: QueryMetaOpts): PreparedStatement<TParams, TResult>;
384
+ prepareKysely<TParams extends Record<string, unknown>>(opts?: QueryMetaOpts): <TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>) => TypedStatement<TParams, TResult>;
385
+ executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyQueryFactory<TDatabase, TQuery, TResult>, options?: ExecuteOptions): ExecuteResult<TResult>;
386
+ 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[];
387
+ executePreparedRaw<TParams extends unknown[], TResult>({ key, sql, params, meta }: {
388
+ key: string;
389
+ sql: string;
390
+ params?: TParams;
391
+ meta?: QueryMetaOpts;
392
+ }): TResult[];
393
+ sql<T = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]): ExecuteResult<T>;
394
+ createScalarFunction<TArgs extends SqlValue[], TResult extends SqlValue | undefined>({ name, callback, deterministic, directOnly, innocuous }: ScalarFunctionOptions<TArgs, TResult>): Database;
395
+ useSnapshot(snapshot: Uint8Array<ArrayBufferLike>): void;
396
+ createSnapshot(): Uint8Array<ArrayBuffer>;
397
+ invalidateDbSchema(): void;
398
+ cleanup(): void;
399
+ close(): void;
400
+ }
401
+ type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;
402
+ type ParamsGetter<TParams> = <TKey extends keyof TParams>(key: TKey) => TParams[TKey];
403
+ type TypedStatement<TParams extends Record<string, unknown>, TResult> = {
404
+ execute: (parameters: TParams) => TResult[];
405
+ };
406
+ type KyselyStatementFactory<TParams extends Record<string, unknown>, TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;
407
+ type KyselyQueryFactory<TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (kysely: Kysely<TDatabase>) => TQuery;
408
+ //#endregion
409
+ //#region src/sqlite-kv-store.d.ts
410
+ type KvStoreItem = {
411
+ key: string;
412
+ value: string;
413
+ };
414
+ declare function createKvStoreTableQuery(schema: SchemaModule, tableName: string): import("kysely").CreateTableBuilder<string, "key" | "value">;
415
+ declare function createSQLiteKvStore({ db, metaTableName }: {
416
+ db: InternalSQLiteWrapper<any>;
417
+ metaTableName: string;
418
+ }): {
419
+ get: (key: string) => string | null;
420
+ set: (key: string, value: string) => void;
421
+ remove: (key: string) => void;
422
+ createStringStoredValue: (key: string, defaultValue: string) => StoredValue<string>;
423
+ createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
424
+ };
425
+ //#endregion
426
+ //#region src/utils.d.ts
427
+ type DeferredPromise<T> = {
428
+ promise: Promise<T>;
429
+ resolve: (value: T) => void;
430
+ reject: (error: Error) => void;
431
+ };
432
+ type DeferredPromiseOptions = {
433
+ timeout?: number;
434
+ onTimeout?: () => void;
435
+ };
436
+ declare function createDeferredPromise<T>(opts?: DeferredPromiseOptions): DeferredPromise<T>;
437
+ declare const generateId: () => `${string}-${string}-${string}-${string}-${string}`;
438
+ type DistributiveOmit<T, K extends keyof T> = T extends any ? Omit<T, K> : never;
439
+ declare class TypedBroadcastChannel<TMessage> {
440
+ private readonly channel;
441
+ constructor(name: string);
442
+ postMessage(message: TMessage): void;
443
+ set onmessage(callback: ((event: MessageEvent<TMessage>) => void) | null);
444
+ close(): void;
445
+ }
446
+ declare class TypedEvent<T = unknown> extends Event {
447
+ readonly payload: T;
448
+ constructor(type: string, payload: T);
449
+ }
450
+ type TypedEventTarget<T extends Record<string, unknown>> = {
451
+ addEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => {
452
+ unsubscribe: () => void;
453
+ };
454
+ removeEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => void;
455
+ dispatchEvent: <K extends keyof T & string>(type: K, payload: T[K]) => void;
456
+ };
457
+ declare const createTypedEventTarget: <T extends Record<string, unknown>>() => TypedEventTarget<T>;
458
+ type TryCatchResult<T> = {
459
+ success: true;
460
+ data: T;
461
+ } | {
462
+ success: false;
463
+ error: unknown;
464
+ };
465
+ declare function tryCatch<T>(fn: () => T): TryCatchResult<T>;
466
+ declare function tryCatchAsync<T>(fn: () => Promise<T>): Promise<TryCatchResult<T>>;
467
+ declare function jsonSafeParse<T>(json: string): TryCatchResult<T>;
468
+ /** Quote a SQLite identifier (table/column name), handling dot-separated schema qualifiers. */
469
+ declare function quoteId(name: string): string;
470
+ type ParsedTableName = {
471
+ schema: "main" | (string & {});
472
+ table: string;
473
+ fullIdentifier: string;
474
+ };
475
+ //#endregion
476
+ //#region src/migrations/system-schema.d.ts
477
+ type SystemDbConfig = {
478
+ eventsTable: ParsedTableName;
479
+ updateLogTable: ParsedTableName;
480
+ };
481
+ declare function createSystemDbConfig({ eventsTableName, updateLogTableName }: {
482
+ eventsTableName: string;
483
+ updateLogTableName: string;
484
+ }): SystemDbConfig;
485
+ type SystemMigrationContext = SystemDbConfig & {
486
+ execute: (sql: string) => void;
487
+ };
488
+ type SystemMigration = {
489
+ version: number;
490
+ up: (ctx: SystemMigrationContext) => void;
491
+ };
492
+ declare const baseSystemMigrations: SystemMigration[];
493
+ declare function runSystemMigrations(opts: {
494
+ version: StoredValue<number>;
495
+ migrations: SystemMigration[];
496
+ dbConfig: SystemDbConfig;
497
+ execute: (sql: string) => void;
498
+ transaction: (callback: () => void) => void;
499
+ }): void;
500
+ declare function applyWorkerDbSchema(db: SQLiteDbWrapper<any>): {
501
+ kvStore: {
502
+ get: (key: string) => string | null;
503
+ set: (key: string, value: string) => void;
504
+ remove: (key: string) => void;
505
+ createStringStoredValue: (key: string, defaultValue: string) => StoredValue<string>;
506
+ createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
507
+ };
508
+ };
509
+ declare function applyMemoryDbSchema(db: SQLiteDbWrapper<any>): void;
510
+ //#endregion
511
+ //#region src/sqlite-crdt/crdt-storage.d.ts
512
+ type LocalCrdtEvent = {
513
+ type: CrdtEventType;
514
+ dataset: string;
515
+ item_id: string;
516
+ payload: string;
517
+ timestamp: string;
518
+ schema_version: number;
519
+ };
520
+ type OwnCrdtEvent = {
521
+ type: CrdtEventType;
522
+ dataset: string;
523
+ item_id: string;
524
+ payload: string;
525
+ timestamp?: undefined;
526
+ schema_version?: undefined;
527
+ };
528
+ type OwnCrdtSnapshot = {
529
+ dataset: string;
530
+ item_id: string;
531
+ patch: Record<string, unknown>;
532
+ };
533
+ type CrdtChangeIntent = {
534
+ seq: number;
535
+ dataset: string;
536
+ type: CrdtEventType;
537
+ item_id: string;
538
+ new_item_id: string | null;
539
+ payload_json: string;
540
+ };
541
+ type RemoteCrdtEvent = {
542
+ type: CrdtEventType;
543
+ dataset: string;
544
+ item_id: string;
545
+ payload: string;
546
+ timestamp: string;
547
+ schema_version: number;
548
+ };
549
+ type GetEventsBatchQuery = {
550
+ afterSyncId: number;
551
+ status: CrdtEventStatus;
552
+ limit: number;
553
+ } & ({
554
+ excludeOrigin: CrdtEventOrigin;
555
+ excludeNodeId?: undefined;
556
+ } | {
557
+ excludeOrigin?: undefined;
558
+ excludeNodeId: string;
559
+ });
560
+ type GetEventsBatch = {
561
+ events: PersistedCrdtEvent[];
562
+ hasMore: boolean;
563
+ nextSyncId: number;
564
+ };
565
+ type EnqueueEventsResult = {
566
+ beforeSyncId: number;
567
+ afterSyncId: number;
568
+ /** Resolves when the enqueued events have been processed (applied/deduped/failed). */
569
+ processed: Promise<void>;
570
+ };
571
+ type StorageHLC = Pick<HLCCounter, "getNextHLC" | "mergeHLC">;
572
+ type DbSyncerStorage = {
573
+ nodeId: string;
574
+ initialLocalSyncId: number;
575
+ migrator: SyncDbMigrator;
576
+ db: InternalSQLiteWrapper<any>;
577
+ dbConfig: SystemDbConfig;
578
+ hlc: StorageHLC;
579
+ eventHlcAccumulator?: StoredValue<string>;
580
+ onEventApplied?: (event: PersistedCrdtEvent) => void;
581
+ schema: Pick<SyncDbSchema, "tables" | "tablesConfig">;
582
+ };
583
+ type CrdtStorage = Omit<ReturnType<typeof createCrdtStorage>, "internal">;
584
+ type InternalCrdtStorage = ReturnType<typeof createCrdtStorage>;
585
+ type EventsAppliedPayload = {
586
+ syncId: number;
587
+ eventHlcSum: string | null;
588
+ };
589
+ type InternalDbSchema = {
590
+ _crdt_events: PersistedCrdtEvent;
591
+ _crdt_update_log: CrdtUpdateLogItem;
592
+ };
593
+ declare function createCrdtStorage(storage: DbSyncerStorage): {
594
+ getEventsBatch: (options: GetEventsBatchQuery) => GetEventsBatch;
595
+ enqueueLocalEvents: (events: LocalCrdtEvent[], sourceNodeId: string) => EnqueueEventsResult;
596
+ enqueueOwnEvents: (events: OwnCrdtEvent[]) => EnqueueEventsResult;
597
+ enqueueRemoteEvents: (events: RemoteCrdtEvent[]) => EnqueueEventsResult;
598
+ applyOwnEvents: (events: OwnCrdtEvent[]) => void;
599
+ applyOwnSnapshot: (snapshot: OwnCrdtSnapshot) => void;
600
+ checkIsQuiescent: (pushedSyncId: number) => boolean;
601
+ getEventHlcAccumulator: () => string | null;
602
+ addEventListener: <K extends "events-applied" | "remote-event-apply-failed">(type: K, listener: (event: TypedEvent<{
603
+ "events-applied": EventsAppliedPayload;
604
+ "remote-event-apply-failed": {
605
+ syncId: number;
606
+ };
607
+ }[K]>) => void) => {
608
+ unsubscribe: () => void;
609
+ };
610
+ removeEventListener: <K extends "events-applied" | "remote-event-apply-failed">(type: K, listener: (event: TypedEvent<{
611
+ "events-applied": EventsAppliedPayload;
612
+ "remote-event-apply-failed": {
613
+ syncId: number;
614
+ };
615
+ }[K]>) => void) => void;
616
+ internal: {
617
+ applyOwnEventFromTransaction: (tx: InternalSQLiteTransactionWrapper<InternalDbSchema>, event: OwnCrdtEvent) => void;
618
+ applyOwnIntentsFromTransaction: (tx: InternalSQLiteTransactionWrapper<InternalDbSchema>, intents: CrdtChangeIntent[]) => {
619
+ appliedEvents: number;
620
+ };
621
+ processEnqueuedEvents: {
622
+ (): Promise<void>;
623
+ promise(): Promise<void> | null;
624
+ isExecuting(): boolean;
625
+ };
626
+ };
627
+ };
628
+ //#endregion
629
+ //#region src/export-import.d.ts
630
+ /**
631
+ * A portable, schema-version-aware dump of every active entity in a synced DB.
632
+ * Unlike a raw SQLite snapshot, it carries no event history — just the current
633
+ * `tombstone = 0` rows, ready to be replayed as fresh create events on import.
634
+ */
635
+ type SyncedDbExport = {
636
+ schemaVersion: number;
637
+ exportedAt: string;
638
+ /** base table name -> active rows (each includes `id`, excludes `tombstone`). */
639
+ tables: Record<string, Array<Record<string, unknown>>>;
640
+ };
641
+ type ImportDataOptions = {
642
+ validate?: boolean;
643
+ };
644
+ type ImportDataResult = {
645
+ imported: number;
646
+ };
647
+ type ExportImportReactiveDb = {
648
+ db: {
649
+ execute<T>(sql: string, meta: {
650
+ loggerLevel: "system";
651
+ }): ExecuteResult<T>;
652
+ };
653
+ };
654
+ type ApplyImportEvents = (events: OwnCrdtEvent[]) => void | Promise<void>;
655
+ type ImportMigrator = Pick<SyncDbMigrator, "currentSchemaVersion" | "migrateEvents">;
656
+ type CreateExportDataOptions = {
657
+ reactiveDb: ExportImportReactiveDb;
658
+ tablesConfig: CrdtTableConfig[];
659
+ schemaVersion: number;
660
+ };
661
+ type CreateImportDataOptions = {
662
+ migrator: ImportMigrator;
663
+ tablesConfig?: CrdtTableConfig[];
664
+ applyEvents: ApplyImportEvents;
665
+ };
666
+ declare function createImportData({ migrator, tablesConfig, applyEvents }: CreateImportDataOptions): (data: SyncedDbExport, opts?: ImportDataOptions) => ImportDataResult | Promise<ImportDataResult>;
667
+ declare function createExportData({ reactiveDb, tablesConfig, schemaVersion }: CreateExportDataOptions): (opts?: {
668
+ tables?: string[];
669
+ }) => SyncedDbExport;
670
+ //#endregion
671
+ //#region src/hash.d.ts
672
+ declare function ensureLoaded(): Promise<void>;
673
+ declare function h64(input: string, seed?: bigint): bigint;
674
+ declare const xxhash: {
675
+ ensureLoaded: typeof ensureLoaded;
676
+ h64: typeof h64;
677
+ };
678
+ //#endregion
679
+ //#region src/memory-db/sqlite-reactive-db.d.ts
680
+ type SQLiteReactiveDbOptions = {
681
+ snapshot: Uint8Array<ArrayBufferLike>;
682
+ logger: Logger;
683
+ };
684
+ type EventsMap = {
685
+ "transaction-committed": undefined;
686
+ "transaction-rolled-back": undefined;
687
+ "any-table-changed": undefined;
688
+ } & Record<`table:${string}`, void>;
689
+ type LiveQuery<TResult> = {
690
+ getRows: () => TResult[];
691
+ refresh: () => void;
692
+ subscribe: (onchange: () => void) => () => void;
693
+ };
694
+ type SharedLiveQuery<TResult> = LiveQuery<TResult> & {
695
+ readonly sql: string;
696
+ readonly parameters: readonly unknown[];
697
+ getSubscriberCount: () => number;
698
+ };
699
+ type SharedLiveQuerySnapshot = {
700
+ sql: string;
701
+ parameters: readonly unknown[];
702
+ subscriberCount: number;
703
+ };
704
+ declare class SQLiteReactiveDb<Database> {
705
+ readonly db: SQLiteDbWrapper<Database>;
706
+ private sqlite3;
707
+ private readonly logger;
708
+ private tablesUsedStatement;
709
+ private eventTarget;
710
+ private mutationVersion;
711
+ private tableMutationVersions;
712
+ private constructor();
713
+ static create<Database>(opts: SQLiteReactiveDbOptions): Promise<SQLiteReactiveDb<Database>>;
714
+ private liveQueryStatements;
715
+ private sharedLiveQueries;
716
+ createLiveQuery<TResult>(query: {
717
+ sql: string;
718
+ parameters: readonly unknown[];
719
+ }): {
720
+ getRows: () => TResult[];
721
+ refresh: (parameters?: readonly unknown[]) => void;
722
+ subscribe: (onchange: () => void) => () => void;
723
+ };
724
+ getSharedLiveQuery<TResult>(query: {
725
+ sql: string;
726
+ parameters: readonly unknown[];
727
+ }): SharedLiveQuery<TResult>;
728
+ private registerSharedLiveQueryEntry;
729
+ getSharedLiveQueriesSnapshot(): SharedLiveQuerySnapshot[];
730
+ private scheduleSharedLiveQueryCleanup;
731
+ private cancelSharedLiveQueryCleanup;
732
+ private releaseSharedLiveQuery;
733
+ subscribeToQueryChanges(params: {
734
+ sql: string;
735
+ onDataChange: () => void;
736
+ }): {
737
+ unsubscribe: () => void;
738
+ };
739
+ subscribeToTableChanges(table: string, onChanges: () => void): {
740
+ unsubscribe: () => void;
741
+ };
742
+ getTablesUsed(query: string): {
743
+ name: string;
744
+ isWrite: boolean;
745
+ }[];
746
+ private getClearedTables;
747
+ addEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void): void;
748
+ removeEventListener<K extends keyof EventsMap>(type: K, listener: (event: TypedEvent<EventsMap[K]>) => void): void;
749
+ getTableMutationVersion(table: string): number;
750
+ private notifyTableSubscribers;
751
+ private registerDbHooks;
752
+ createSnapshot(): Uint8Array<ArrayBuffer>;
753
+ useSnapshot(snapshot: Uint8Array<ArrayBufferLike>): void;
754
+ dispose(): void;
755
+ }
756
+ declare function parametersAreEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean;
757
+ //#endregion
758
+ //#region src/schema/admit-client-events.d.ts
759
+ type AdmitClientEventsResult<T> = {
760
+ admitted: T[];
761
+ skipped: T[];
762
+ };
763
+ type SchemaForAdmitClientEvents = Pick<SyncDbSchema, "tables" | "tablesConfig"> & {
764
+ writeOriginByName?: ReadonlyMap<string, WriteOrigin>;
765
+ };
766
+ /**
767
+ * Splits a client push into events the hub should persist and events for tables declared
768
+ * `.writes("server")`. Unknown datasets stay admitted. Resolves either the crdt or the base
769
+ * table name.
770
+ */
771
+ declare function admitClientEvents<T extends {
772
+ dataset: string;
773
+ }>(opts: {
774
+ syncDbSchema: SchemaForAdmitClientEvents;
775
+ events: readonly T[];
776
+ }): AdmitClientEventsResult<T>;
777
+ //#endregion
778
+ //#region src/schema/define-sync-schema.d.ts
779
+ type Simplify<T> = { [K in keyof T]: T[K]; } & {};
780
+ type RowOf<Table extends AnyTableBuilder> = Table extends TableBuilder<infer Cols extends TableColumns, any> ? InferRow<Cols> : never;
781
+ type BaseNameOf<CrdtName, Table extends AnyTableBuilder> = string extends Table["~baseName"] ? `_${CrdtName & string}` : [Table["~baseName"]] extends [string] ? Table["~baseName"] : `_${CrdtName & string}`;
782
+ type ClientSchemaOf<Tables extends SyncSchemaTables> = Simplify<{ [K in keyof Tables]: RowOf<Tables[K]>; } & { [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>; }>;
783
+ type ServerSchemaOf<Tables extends SyncSchemaTables> = Simplify<{ [K in keyof Tables]: ReadonlyTable<RowOf<Tables[K]>>; } & { [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>; }>;
784
+ type MutationsSchemaOf<Tables extends SyncSchemaTables> = Simplify<{ [K in keyof Tables as BaseNameOf<K, Tables[K]>]: RowOf<Tables[K]>; }>;
785
+ interface DefinedSyncSchema<Tables extends SyncSchemaTables> extends SyncDbSchema<ClientSchemaOf<Tables>, ServerSchemaOf<Tables>, MutationsSchemaOf<Tables>> {
786
+ /** The table builders, for type extraction (`typeof schema.tables.item.$row`) and runtime metadata. */
787
+ tables: Tables;
788
+ /** Write origin keyed by crdt and base table name. */
789
+ writeOriginByName: ReadonlyMap<string, WriteOrigin>;
790
+ }
791
+ type DefineSyncSchemaConfig<Tables extends SyncSchemaTables> = {
792
+ tables: Tables;
793
+ /** Full migration history (including the initial createTable version), built with `createMigrations`. */
794
+ migrations: Migrations;
795
+ };
796
+ /**
797
+ * Define a sync database schema from `t.table()` builders.
798
+ *
799
+ * Record keys are the crdt (view) table names; base table names default to the key
800
+ * prefixed with "_", overridable per table via `t.table(cols, { baseName })`.
801
+ */
802
+ declare function defineSyncSchema<Tables extends SyncSchemaTables>({ tables, migrations }: DefineSyncSchemaConfig<Tables>): DefinedSyncSchema<Tables>;
803
+ //#endregion
804
+ //#region src/schema/validate-crdt-event.d.ts
805
+ type NewCrdtEventValidationResult = {
806
+ success: true;
807
+ event: NewCrdtEvent;
808
+ } | {
809
+ success: false;
810
+ errors: string[];
811
+ };
812
+ declare class CrdtEventValidationError extends Error {
813
+ readonly errors: string[];
814
+ constructor(errors: string[]);
815
+ }
816
+ declare function validateNewCrdtEvent(schema: Pick<SyncDbSchema, "tables" | "tablesConfig">, input: unknown): NewCrdtEventValidationResult;
817
+ //#endregion
818
+ //#region src/schema/verify-sync-schema.d.ts
819
+ type SchemaVerificationIssue = {
820
+ table: string;
821
+ column?: string;
822
+ message: string;
823
+ };
824
+ /**
825
+ * Verify that replaying the full migration history on a fresh database produces
826
+ * exactly the declared table schema. Creates a throwaway in-memory SQLite db,
827
+ * applies all migrations, introspects the result, and diffs it against the
828
+ * `t.table()` declarations.
829
+ *
830
+ * Returns an empty array when migrations and schema agree. Intended for dev-time
831
+ * checks (`startDbWorker({ verifySchema: true })`) and tests:
832
+ * `expect(await verifySyncSchema(syncDbSchema)).toEqual([])`.
833
+ */
834
+ declare function verifySyncSchema(schema: SyncDbSchema): Promise<SchemaVerificationIssue[]>;
835
+ declare function formatSchemaVerificationIssues(issues: SchemaVerificationIssue[]): string;
836
+ //#endregion
837
+ //#region src/sqlite-crdt/apply-crdt-event.d.ts
838
+ type PendingCrdtEvent = {
839
+ type: CrdtEventType;
840
+ dataset: string;
841
+ item_id: string;
842
+ timestamp: string;
843
+ payload: string;
844
+ };
845
+ declare const createSQLiteCrdtApplyFunction: ({ db, dbConfig }: {
846
+ db: InternalSQLiteWrapper<any>;
847
+ dbConfig: SystemDbConfig;
848
+ }) => (event: PendingCrdtEvent) => void;
849
+ type CreateCrdtApplyOpts = {
850
+ getCrdtUpdateLog: (opts: {
851
+ itemId: string;
852
+ dataset: string;
853
+ }) => CrdtUpdateLogPayload | null;
854
+ insertItem: (opts: {
855
+ dataset: string;
856
+ payload: Record<string, unknown>;
857
+ }) => void;
858
+ insertCrdtUpdateLog: (opts: {
859
+ dataset: string;
860
+ itemId: string;
861
+ payload: string;
862
+ }) => void;
863
+ updateItem: (opts: {
864
+ dataset: string;
865
+ itemId: string;
866
+ payload: Record<string, unknown>;
867
+ }) => void;
868
+ updateCrdtUpdateLog: (opts: {
869
+ dataset: string;
870
+ itemId: string;
871
+ payload: string;
872
+ }) => void;
873
+ };
874
+ declare function createCrdtApplyFunction({ getCrdtUpdateLog, insertItem, insertCrdtUpdateLog, updateItem, updateCrdtUpdateLog }: CreateCrdtApplyOpts): (event: PendingCrdtEvent) => void;
875
+ //#endregion
876
+ //#region src/sqlite-crdt/crdt-storage-mutator.d.ts
877
+ type CrdtStorageMutator<Database> = ReturnType<typeof createCrdtStorageMutator<Database>>;
878
+ type CommitEventOptions<Database, Table extends keyof Database & string> = {
879
+ type: "item-created";
880
+ dataset: Table;
881
+ item_id: string;
882
+ payload: CreateEventPayload<Database, Table>;
883
+ } | {
884
+ type: "item-updated";
885
+ dataset: Table;
886
+ item_id: string;
887
+ payload: UpdateEventPayload<Database, Table>;
888
+ } | {
889
+ type: "item-deleted";
890
+ dataset: Table;
891
+ item_id: string;
892
+ };
893
+ type CreateEventPayload<Database, Table extends keyof Database> = Omit<Database[Table], "tombstone">;
894
+ type UpdateEventPayload<Database, Table extends keyof Database> = Omit<Partial<Database[Table]>, "id" | "tombstone">;
895
+ type SnapshotOptions<Database, Table extends keyof Database & string> = {
896
+ dataset: Table;
897
+ id: string;
898
+ patch: UpdateEventPayload<Database, Table>;
899
+ };
900
+ declare function createCrdtStorageMutator<Database>({ storage }: {
901
+ storage: CrdtStorage;
902
+ }): {
903
+ enqueueEvents: (events: CommitEventOptions<Database, keyof Database & string>[]) => void;
904
+ createEvent: <Table extends keyof Database & string>(event: CommitEventOptions<Database, Table>) => CommitEventOptions<Database, Table>;
905
+ enqueueEvent: (event: CommitEventOptions<Database, keyof Database & string>) => void;
906
+ enqueueSnapshot: <Table extends keyof Database & string>(snapshot: SnapshotOptions<Database, Table>) => void;
907
+ };
908
+ //#endregion
909
+ //#region src/sqlite-crdt/crdt-sync-producer.d.ts
910
+ type CrdtSyncProducer = {
911
+ storage: CrdtStorage;
912
+ broadcastEvents: (request: {
913
+ newSyncId: number;
914
+ eventHlcSum: string | null;
915
+ }) => void;
916
+ };
917
+ declare const createCrdtSyncProducer: ({ storage, broadcastEvents }: CrdtSyncProducer) => void;
918
+ //#endregion
919
+ //#region src/worker-db/worker-common.d.ts
920
+ type WorkerNotificationMessage = {
921
+ notificationType: "new-event-chunk-applied";
922
+ newSyncId: number;
923
+ /** Worker's HLC checksum after applying up to `newSyncId`. */
924
+ eventHlcSum: string | null;
925
+ } | {
926
+ notificationType: "state-changed";
927
+ state: WorkerState;
928
+ } | {
929
+ notificationType: "reload-requested";
930
+ reloadEpoch: string;
931
+ clean: boolean;
932
+ } | {
933
+ notificationType: "de-sync-detected";
934
+ reason: DeSyncDetectedReason;
935
+ } | {
936
+ notificationType: "remote-schema-version-mismatch";
937
+ remoteSchemaVersion: number;
938
+ localSchemaVersion: number;
939
+ };
940
+ type WorkerState = {
941
+ remoteState: "online" | "offline" | "pending";
942
+ deSynced: boolean;
943
+ schemaVersionMismatched: boolean;
944
+ };
945
+ type EventsPullResponse = {
946
+ events: {
947
+ schema_version: number;
948
+ type: CrdtEventType;
949
+ timestamp: string;
950
+ dataset: string;
951
+ item_id: string;
952
+ payload: string;
953
+ }[];
954
+ hasMore: boolean;
955
+ nextSyncId: number;
956
+ };
957
+ type WorkerConfig<Props = any> = {
958
+ dbId: string;
959
+ clientId: string;
960
+ props: Props;
961
+ };
962
+ //#endregion
963
+ //#region src/sqlite-crdt/crdt-sync-remote-source.d.ts
964
+ type CrdtSyncRemoteSourceConfig = {
965
+ bufferSize: number;
966
+ storage: CrdtStorage;
967
+ migrator: SyncDbMigrator;
968
+ pullSyncId: StoredValue<number>;
969
+ pushSyncId: StoredValue<number>;
970
+ nodeId: string;
971
+ remoteFactory?: CreateRemoteSourceFactory;
972
+ };
973
+ type EventsPullRequest = {
974
+ afterSyncId: number;
975
+ excludeNodeId?: string;
976
+ };
977
+ type EventsPushRequest = {
978
+ nodeId: string;
979
+ events: (PendingCrdtEvent & {
980
+ schema_version: number;
981
+ })[];
982
+ };
983
+ type EventsPushResponse = {
984
+ ok: boolean;
985
+ /** Remote sync_id right before the pushed events were enqueued. */
986
+ beforeSyncId?: number;
987
+ /** Remote sync_id right after the pushed events were enqueued. */
988
+ afterSyncId?: number;
989
+ };
990
+ type CrdtSyncRemoteSource = ReturnType<typeof createCrdtSyncRemoteSource>;
991
+ type EventsAvailable = {
992
+ newSyncId: number;
993
+ remoteEventHlcSum: string | null;
994
+ };
995
+ type CreateRemoteSourceFactory = (opts: {
996
+ onEventsAvailable: (event: EventsAvailable) => void;
997
+ }) => RemoteSource | Promise<RemoteSource>;
998
+ type RemoteSource = {
999
+ pullEvents: (request: EventsPullRequest) => Promise<EventsPullResponse>;
1000
+ pushEvents: (request: EventsPushRequest) => Promise<EventsPushResponse>;
1001
+ disconnect?: () => void | Promise<void>;
1002
+ };
1003
+ type RemoteSourceState = {
1004
+ type: "pending";
1005
+ deSynced: boolean;
1006
+ schemaVersionMismatched: boolean;
1007
+ } | {
1008
+ type: "offline";
1009
+ reason: OfflineReason;
1010
+ deSynced: boolean;
1011
+ schemaVersionMismatched: boolean;
1012
+ } | {
1013
+ type: "online";
1014
+ source: RemoteSource;
1015
+ deSynced: boolean;
1016
+ schemaVersionMismatched: boolean;
1017
+ };
1018
+ type OfflineReason = "NOT_INITIALIZED" | "INITIALIZATION_FAILED" | "REMOTE_PUSH_ERROR" | "REMOTE_PULL_ERROR" | "DISCONNECTED";
1019
+ type DeSyncDetectedReason = "CHECKSUM_MISMATCH" | "ERROR_APPLYING_REMOTE_EVENT";
1020
+ declare const createCrdtSyncRemoteSource: ({ bufferSize, storage, migrator, pullSyncId, pushSyncId, nodeId, remoteFactory }: CrdtSyncRemoteSourceConfig) => {
1021
+ goOnline: () => Promise<void>;
1022
+ goOffline: {
1023
+ (reason: OfflineReason): Promise<void>;
1024
+ promise(): Promise<void> | null;
1025
+ isExecuting(): boolean;
1026
+ };
1027
+ syncWithRemote: {
1028
+ (): Promise<void>;
1029
+ promise(): Promise<void> | null;
1030
+ isExecuting(): boolean;
1031
+ };
1032
+ getState: () => WorkerState;
1033
+ dispose: () => Promise<void>;
1034
+ addEventListener: <K extends "state-changed" | "de-sync-detected" | "remote-schema-version-mismatch">(type: K, listener: (event: TypedEvent<{
1035
+ "state-changed": RemoteSourceState["type"];
1036
+ "de-sync-detected": {
1037
+ reason: DeSyncDetectedReason;
1038
+ };
1039
+ "remote-schema-version-mismatch": {
1040
+ remoteSchemaVersion: number;
1041
+ localSchemaVersion: number;
1042
+ };
1043
+ }[K]>) => void) => {
1044
+ unsubscribe: () => void;
1045
+ };
1046
+ removeEventListener: <K extends "state-changed" | "de-sync-detected" | "remote-schema-version-mismatch">(type: K, listener: (event: TypedEvent<{
1047
+ "state-changed": RemoteSourceState["type"];
1048
+ "de-sync-detected": {
1049
+ reason: DeSyncDetectedReason;
1050
+ };
1051
+ "remote-schema-version-mismatch": {
1052
+ remoteSchemaVersion: number;
1053
+ localSchemaVersion: number;
1054
+ };
1055
+ }[K]>) => void) => void;
1056
+ };
1057
+ //#endregion
1058
+ //#region src/sqlite-crdt/make-crdt-table.d.ts
1059
+ declare const CRDT_CHANGE_INTENTS_TABLE = "crdt_change_intents";
1060
+ declare function makeCrdtTable({ db, baseTableName, crdtTableName }: {
1061
+ db: SQLiteDbWrapper<any>;
1062
+ baseTableName: string;
1063
+ crdtTableName: string;
1064
+ }): void;
1065
+ declare function createCrdtViewStatements({ baseTableName, crdtTableName, columnNames }: {
1066
+ baseTableName: string;
1067
+ crdtTableName: string;
1068
+ columnNames: string[];
1069
+ }): string[];
1070
+ declare function drainCrdtChangeIntents({ tx, storage }: {
1071
+ tx: InternalSQLiteTransactionWrapper<any>;
1072
+ storage: InternalCrdtStorage;
1073
+ }): boolean;
1074
+ //#endregion
1075
+ //#region src/sync-db.d.ts
1076
+ type SyncedDbOptions<Database, Props = undefined> = {
1077
+ dbId: string;
1078
+ worker: Worker;
1079
+ workerProps: Props;
1080
+ syncDbSchema: SyncDbSchema<Database>;
1081
+ };
1082
+ /** SQL execution that participates in CRDT intent draining. */
1083
+ type SyncedDbSqlExecutor<Database> = {
1084
+ execute<TResult = unknown>(query: ExecuteParams | string | CompiledQuery<TResult>): ExecuteResult<TResult>;
1085
+ executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(factory: KyselyQueryFactory<Database, TQuery, TResult>): ExecuteResult<TResult>;
1086
+ };
1087
+ /**
1088
+ * SQL execution that deliberately bypasses CRDT intent draining.
1089
+ *
1090
+ * Mutating a synced view through this executor can leave undrained intents and
1091
+ * must only be done by sqlite-sync internals or recovery tooling.
1092
+ */
1093
+ type UnsafeSyncedDbSqlExecutor<Database> = SyncedDbSqlExecutor<Database>;
1094
+ type SyncedDbTransaction<Database> = SyncedDbSqlExecutor<Database> & {
1095
+ unsafe: UnsafeSyncedDbSqlExecutor<Database>;
1096
+ sql<TResult = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]): ExecuteResult<TResult>;
1097
+ };
1098
+ type SyncedDbDatabase<Database> = SyncedDbSqlExecutor<Database> & {
1099
+ unsafe: UnsafeSyncedDbSqlExecutor<Database>;
1100
+ executeTransaction<TResult>(callback: (tx: SyncedDbTransaction<Database>) => TResult): TResult;
1101
+ createLiveQuery<TResult>(query: {
1102
+ sql: string;
1103
+ parameters: readonly unknown[];
1104
+ }): {
1105
+ getRows: () => TResult[];
1106
+ refresh: (parameters?: readonly unknown[]) => void;
1107
+ subscribe: (onchange: () => void) => () => void;
1108
+ };
1109
+ getSharedLiveQuery<TResult>(query: {
1110
+ sql: string;
1111
+ parameters: readonly unknown[];
1112
+ }): SharedLiveQuery<TResult>;
1113
+ };
1114
+ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOptions<Database, Props>): Promise<{
1115
+ db: SyncedDbDatabase<Database>;
1116
+ state: {
1117
+ getState: () => WorkerState;
1118
+ subscribe: (onChange: () => void) => () => void;
1119
+ goOnline: () => Promise<void>;
1120
+ goOffline: () => Promise<void>;
1121
+ };
1122
+ /**
1123
+ * Ask the elected worker to broadcast a page reload to all tabs for this dbId.
1124
+ *
1125
+ * With `clean: true` the worker durably records a reset request epoch before
1126
+ * broadcasting, so the worker elected on the next startup initializes with
1127
+ * `clearOnInit: true` and wipes the persisted DB. Destructive — use as a
1128
+ * recovery path when the durable worker DB may be de-synced.
1129
+ *
1130
+ * Pending in-memory tab events are not preserved, and the returned promise
1131
+ * may never settle in the caller — the page typically unloads first.
1132
+ */
1133
+ requestReload: (options: {
1134
+ clean: boolean;
1135
+ }) => Promise<void>;
1136
+ subscribe: <K extends "state-changed" | "de-sync-detected" | "remote-schema-version-mismatch" | "new-event-chunk-applied" | "reload-requested">(type: K, listener: (event: TypedEvent<{
1137
+ "state-changed": {
1138
+ notificationType: "state-changed";
1139
+ state: WorkerState;
1140
+ };
1141
+ "de-sync-detected": {
1142
+ notificationType: "de-sync-detected";
1143
+ reason: DeSyncDetectedReason;
1144
+ };
1145
+ "remote-schema-version-mismatch": {
1146
+ notificationType: "remote-schema-version-mismatch";
1147
+ remoteSchemaVersion: number;
1148
+ localSchemaVersion: number;
1149
+ };
1150
+ "new-event-chunk-applied": {
1151
+ notificationType: "new-event-chunk-applied";
1152
+ newSyncId: number;
1153
+ eventHlcSum: string | null;
1154
+ };
1155
+ "reload-requested": {
1156
+ notificationType: "reload-requested";
1157
+ reloadEpoch: string;
1158
+ clean: boolean;
1159
+ };
1160
+ }[K]>) => void) => {
1161
+ unsubscribe: () => void;
1162
+ };
1163
+ exportData: (opts?: {
1164
+ tables?: string[];
1165
+ }) => SyncedDbExport;
1166
+ importData: (data: SyncedDbExport, opts?: ImportDataOptions) => Promise<ImportDataResult>;
1167
+ dispose: () => Promise<void>;
1168
+ _internal: {
1169
+ executeAsync: (query: ExecuteParams) => Promise<ExecuteResult<unknown>>;
1170
+ getMemoryQueryTables: (query: string) => {
1171
+ name: string;
1172
+ isWrite: boolean;
1173
+ }[];
1174
+ getSharedLiveQueriesSnapshot: () => SharedLiveQuerySnapshot[];
1175
+ crdtTableNames: string[];
1176
+ crdtTablesConfig: CrdtTableConfig[];
1177
+ schemaVersion: number;
1178
+ migrationVersions: number[];
1179
+ };
1180
+ }>;
1181
+ type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;
1182
+ //#endregion
1183
+ //#region src/worker-db/reset-state.d.ts
1184
+ type ResetRequest = {
1185
+ epoch: string;
1186
+ requestedAt: number;
1187
+ };
1188
+ /** Durable async key-value storage for reset state. Injectable for tests. */
1189
+ type ResetStore = {
1190
+ get: <T>(key: string) => Promise<T | undefined>;
1191
+ set: (key: string, value: unknown) => Promise<void>;
1192
+ delete: (key: string) => Promise<void>;
1193
+ };
1194
+ /**
1195
+ * A clean reset is a recovery action for a de-sync detected now. If the reload
1196
+ * never happens (broadcast lost, tab crashed mid-reload, browser killed the page),
1197
+ * the request must not fire on an arbitrary later cold start and silently wipe
1198
+ * local-only writes accumulated since.
1199
+ */
1200
+ declare const RESET_REQUEST_TTL_MS: number;
1201
+ //#endregion
1202
+ export { CrdtChangeIntent as $, AnyColumnBuilder as $t, createCrdtApplyFunction as A, InternalSQLiteWrapper as At, defineSyncSchema as B, ColumnMetadata as Bt, WorkerNotificationMessage as C, CrdtEventStatus as Cn, tryCatch as Ct, SnapshotOptions as D, PersistedCrdtEvent as Dn, createSQLiteKvStore as Dt, CrdtStorageMutator as E, CrdtUpdateLogPayload as En, createKvStoreTableQuery as Et, CrdtEventValidationError as F, SQLiteDbWrapper as Ft, SharedLiveQuerySnapshot as G, HLCCounter as Gt, admitClientEvents as H, TableMetadata as Ht, NewCrdtEventValidationResult as I, SQLiteTransactionWrapper as It, ImportDataOptions as J, serializeHLC as Jt, parametersAreEqual as K, compareHLC as Kt, validateNewCrdtEvent as L, LogLevel as Lt, SchemaVerificationIssue as M, KyselyStatementFactory as Mt, formatSchemaVerificationIssues as N, PreparedStatement as Nt, createCrdtStorageMutator as O, isNoOpCrdtEventPayload as On, ExecuteParams as Ot, verifySyncSchema as P, QueryBuilderOutput as Pt, createImportData as Q, AiAccess as Qt, DefineSyncSchemaConfig as R, Logger as Rt, WorkerConfig as S, CrdtEventOrigin as Sn, quoteId as St, createCrdtSyncProducer as T, CrdtUpdateLogItem as Tn, KvStoreItem as Tt, SQLiteReactiveDb as U, introspectDb as Ut, AdmitClientEventsResult as V, DatabaseIntrospection as Vt, SharedLiveQuery as W, HLC as Wt, SyncedDbExport as X, ReadonlyTable as Xt, ImportDataResult as Y, CrdtTableConfig as Yt, createExportData as Z, SyncDbSchema as Zt, EventsPullRequest as _, createMigrations as _n, TypedEventTarget as _t, SyncedDbDatabase as a, PayloadValidationResult as an, SystemDbConfig as at, createCrdtSyncRemoteSource as b, createStoredValue as bn, generateId as bt, SyncedDbTransaction as c, TableBuilder as cn, applyMemoryDbSchema as ct, CRDT_CHANGE_INTENTS_TABLE as d, WriteOrigin as dn, createSystemDbConfig as dt, AnyTableBuilder as en, CrdtStorage as et, createCrdtViewStatements as f, t as fn, runSystemMigrations as ft, CreateRemoteSourceFactory as g, SyncDbMigrator as gn, TypedEvent as gt, CrdtSyncRemoteSource as h, MigrationsDb as hn, TypedBroadcastChannel as ht, SyncedDb as i, InferRow as in, createCrdtStorage as it, createSQLiteCrdtApplyFunction as j, KyselyQueryFactory as jt, PendingCrdtEvent as k, dummyKysely as kn, ExecuteResult as kt, UnsafeSyncedDbSqlExecutor as l, TableColumns as ln, applyWorkerDbSchema as lt, makeCrdtTable as m, Migrations as mn, DistributiveOmit as mt, ResetRequest as n, ColumnKind as nn, OwnCrdtEvent as nt, SyncedDbOptions as o, SqliteStorageType as on, SystemMigration as ot, drainCrdtChangeIntents as p, MigratableEvent as pn, DeferredPromise as pt, xxhash as q, deserializeHLC as qt, ResetStore as r, ColumnMeta as rn, OwnCrdtSnapshot as rt, SyncedDbSqlExecutor as s, SyncSchemaTables as sn, SystemMigrationContext as st, RESET_REQUEST_TTL_MS as t, ColumnBuilder as tn, GetEventsBatch as tt, createSyncedDb as u, TableOptions as un, baseSystemMigrations as ut, EventsPushRequest as v, createMigrator as vn, createDeferredPromise as vt, WorkerState as w, CrdtEventType as wn, tryCatchAsync as wt, EventsPullResponse as x, CRDT_EVENT_NO_OP_PAYLOAD as xn, jsonSafeParse as xt, EventsPushResponse as y, StoredValue as yn, createTypedEventTarget as yt, DefinedSyncSchema as z, startPerformanceLogger as zt };
1203
+ //# sourceMappingURL=index-BB-tsxEF.d.ts.map