@sqlite-sync/core 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import * as kysely from 'kysely';
2
2
  import { Kysely, SchemaModule } from 'kysely';
3
- import { S as SQLiteDbWrapper, L as Logger, T as TypedEvent, I as InternalSQLiteWrapper, a as StoredValue, C as CrdtStorage, E as ExecuteParams, b as ExecuteResult, Q as QueryBuilderOutput, K as KyselyQueryFactory, c as SQLiteTransactionWrapper, W as WorkerState, D as DeSyncDetectedReason } from './crdt-sync-remote-source-CJrVzW-B.js';
4
- export { R as CRDT_EVENT_NO_OP_PAYLOAD, U as CrdtEventOrigin, V as CrdtEventStatus, X as CrdtEventType, F as CrdtSyncRemoteSource, Y as CrdtUpdateLogItem, Z as CrdtUpdateLogPayload, g as DatabaseIntrospection, a5 as DeferredPromise, a6 as DistributiveOmit, J as EventsPullRequest, N as EventsPushRequest, O as EventsPushResponse, H as HLC, f as HLCCounter, a1 as KyselyStatementFactory, j as LogLevel, M as MigratableEvent, n as Migrations, o as MigrationsDb, P as PendingCrdtEvent, $ as PersistedCrdtEvent, a2 as PreparedStatement, p as SyncDbMigrator, w as SystemDbConfig, x as SystemMigration, y as SystemMigrationContext, h as TableMetadata, aa as TypedBroadcastChannel, ab as TypedEventTarget, ae as WorkerConfig, af as WorkerNotificationMessage, q as applyMemoryDbSchema, r as applyWorkerDbSchema, t as baseSystemMigrations, d as compareHLC, z as createCrdtApplyFunction, B as createCrdtStorage, G as createCrdtSyncRemoteSource, a3 as createDeferredPromise, l as createMigrations, m as createMigrator, A as createSQLiteCrdtApplyFunction, a0 as createStoredValue, u as createSystemDbConfig, a4 as createTypedEventTarget, e as deserializeHLC, a7 as generateId, i as introspectDb, _ as isNoOpCrdtEventPayload, a8 as jsonSafeParse, a9 as quoteId, v as runSystemMigrations, s as serializeHLC, k as startPerformanceLogger, ac as tryCatch, ad as tryCatchAsync } from './crdt-sync-remote-source-CJrVzW-B.js';
5
- import { S as SyncDbSchema, C as CrdtTableConfig } from './reset-state-Comk7IC0.js';
6
- export { a as CreateCrdtSchemaOptions, R as RESET_REQUEST_TTL_MS, b as ResetRequest, d as ResetStore, c as createSyncDbSchema } from './reset-state-Comk7IC0.js';
3
+ import { S as SQLiteDbWrapper, L as Logger, T as TypedEvent, I as InternalSQLiteWrapper, a as StoredValue, b as SyncSchemaTables, c as SyncDbSchema, A as AnyTableBuilder, d as TableBuilder, e as TableColumns, f as InferRow, R as ReadonlyTable, M as Migrations, N as NewCrdtEvent, C as CrdtStorage, E as ExecuteParams, g as ExecuteResult, Q as QueryBuilderOutput, K as KyselyQueryFactory, h as SQLiteTransactionWrapper, W as WorkerState, D as DeSyncDetectedReason, i as CrdtTableConfig } from './crdt-sync-remote-source-BFl7v5_I.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-BFl7v5_I.js';
5
+ export { R as RESET_REQUEST_TTL_MS, a as ResetRequest, b as ResetStore } from './reset-state-D6UslXaj.js';
7
6
  import '@sqlite.org/sqlite-wasm';
8
7
 
9
8
  declare const dummyKysely: Kysely<any>;
@@ -106,6 +105,72 @@ declare function createSQLiteKvStore({ db, metaTableName }: {
106
105
  createNumberStoredValue: (key: string, defaultValue: number) => StoredValue<number>;
107
106
  };
108
107
 
108
+ type Simplify<T> = {
109
+ [K in keyof T]: T[K];
110
+ } & {};
111
+ type RowOf<Table extends AnyTableBuilder> = Table extends TableBuilder<infer Cols extends TableColumns, any> ? InferRow<Cols> : never;
112
+ type BaseNameOf<CrdtName, Table extends AnyTableBuilder> = string extends Table["~baseName"] ? `_${CrdtName & string}` : [Table["~baseName"]] extends [string] ? Table["~baseName"] : `_${CrdtName & string}`;
113
+ type ClientSchemaOf<Tables extends SyncSchemaTables> = Simplify<{
114
+ [K in keyof Tables]: RowOf<Tables[K]>;
115
+ } & {
116
+ [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>;
117
+ }>;
118
+ type ServerSchemaOf<Tables extends SyncSchemaTables> = Simplify<{
119
+ [K in keyof Tables]: ReadonlyTable<RowOf<Tables[K]>>;
120
+ } & {
121
+ [K in keyof Tables as BaseNameOf<K, Tables[K]>]: ReadonlyTable<RowOf<Tables[K]>>;
122
+ }>;
123
+ type MutationsSchemaOf<Tables extends SyncSchemaTables> = Simplify<{
124
+ [K in keyof Tables as BaseNameOf<K, Tables[K]>]: RowOf<Tables[K]>;
125
+ }>;
126
+ interface DefinedSyncSchema<Tables extends SyncSchemaTables> extends SyncDbSchema<ClientSchemaOf<Tables>, ServerSchemaOf<Tables>, MutationsSchemaOf<Tables>> {
127
+ /** The table builders, for type extraction (`typeof schema.tables.item.$row`) and runtime metadata. */
128
+ tables: Tables;
129
+ }
130
+ type DefineSyncSchemaConfig<Tables extends SyncSchemaTables> = {
131
+ tables: Tables;
132
+ /** Full migration history (including the initial createTable version), built with `createMigrations`. */
133
+ migrations: Migrations;
134
+ };
135
+ /**
136
+ * Define a sync database schema from `t.table()` builders.
137
+ *
138
+ * Record keys are the crdt (view) table names; base table names default to the key
139
+ * prefixed with "_", overridable per table via `t.table(cols, { baseName })`.
140
+ */
141
+ declare function defineSyncSchema<Tables extends SyncSchemaTables>({ tables, migrations, }: DefineSyncSchemaConfig<Tables>): DefinedSyncSchema<Tables>;
142
+
143
+ type NewCrdtEventValidationResult = {
144
+ success: true;
145
+ event: NewCrdtEvent;
146
+ } | {
147
+ success: false;
148
+ errors: string[];
149
+ };
150
+ declare class CrdtEventValidationError extends Error {
151
+ readonly errors: string[];
152
+ constructor(errors: string[]);
153
+ }
154
+ declare function validateNewCrdtEvent(schema: Pick<SyncDbSchema, "tables" | "tablesConfig">, input: unknown): NewCrdtEventValidationResult;
155
+
156
+ type SchemaVerificationIssue = {
157
+ table: string;
158
+ column?: string;
159
+ message: string;
160
+ };
161
+ /**
162
+ * Verify that replaying the full migration history on a fresh database produces
163
+ * exactly the declared table schema. Creates a throwaway in-memory SQLite db,
164
+ * applies all migrations, introspects the result, and diffs it against the
165
+ * `t.table()` declarations.
166
+ *
167
+ * Returns an empty array when migrations and schema agree. Intended for dev-time
168
+ * checks (`startDbWorker({ verifySchema: true })`) and tests:
169
+ * `expect(await verifySyncSchema(syncDbSchema)).toEqual([])`.
170
+ */
171
+ declare function verifySyncSchema(schema: SyncDbSchema): Promise<SchemaVerificationIssue[]>;
172
+ declare function formatSchemaVerificationIssues(issues: SchemaVerificationIssue[]): string;
173
+
109
174
  type CrdtStorageMutator<Database> = ReturnType<typeof createCrdtStorageMutator<Database>>;
110
175
  type CommitEventOptions<Database, Table extends keyof Database & string> = {
111
176
  type: "item-created";
@@ -238,4 +303,4 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
238
303
  }>;
239
304
  type SyncedDb<Database> = Awaited<ReturnType<typeof createSyncedDb<Database>>>;
240
305
 
241
- export { CrdtStorage, type CrdtStorageMutator, CrdtTableConfig, ExecuteParams, ExecuteResult, InternalSQLiteWrapper, type KvStoreItem, KyselyQueryFactory, Logger, QueryBuilderOutput, SQLiteDbWrapper, SQLiteReactiveDb, SQLiteTransactionWrapper, type SharedLiveQuery, type SharedLiveQuerySnapshot, StoredValue, SyncDbSchema, type SyncedDb, TypedEvent, WorkerState, createCrdtStorageMutator, createCrdtSyncProducer, createKvStoreTableQuery, createSQLiteKvStore, createSyncedDb, dummyKysely, makeCrdtTable, parametersAreEqual, xxhash };
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 };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  CRDT_EVENT_NO_OP_PAYLOAD,
3
+ CrdtEventValidationError,
3
4
  HLCCounter,
4
5
  RESET_REQUEST_TTL_MS,
5
6
  SQLiteDbWrapper,
@@ -21,6 +22,7 @@ import {
21
22
  createSystemDbConfig,
22
23
  deserializeHLC,
23
24
  dummyKysely,
25
+ formatSchemaVerificationIssues,
24
26
  introspectDb,
25
27
  isNoOpCrdtEventPayload,
26
28
  isWorkerErrorResponseMessage,
@@ -31,8 +33,10 @@ import {
31
33
  serializeHLC,
32
34
  startPerformanceLogger,
33
35
  syncDbClientLockName,
36
+ validateNewCrdtEvent,
37
+ verifySyncSchema,
34
38
  xxhash
35
- } from "./chunk-NZDRISFS.js";
39
+ } from "./chunk-LBYL5L4O.js";
36
40
  import {
37
41
  TypedBroadcastChannel,
38
42
  TypedEvent,
@@ -458,45 +462,202 @@ function parametersAreEqual(a, b) {
458
462
  return true;
459
463
  }
460
464
 
461
- // src/sqlite-crdt/crdt-schema.ts
462
- function createSyncDbSchema({ migrations }) {
463
- return new CrdtSchemaBuilder({ tables: [], migrations });
465
+ // src/schema/define-sync-schema.ts
466
+ function defineSyncSchema({
467
+ tables,
468
+ migrations
469
+ }) {
470
+ const tablesConfig = Object.entries(tables).map(([crdtTableName, table]) => ({
471
+ crdtTableName,
472
+ baseTableName: table.baseName ?? `_${crdtTableName}`
473
+ }));
474
+ const seenNames = /* @__PURE__ */ new Set();
475
+ for (const { crdtTableName, baseTableName } of tablesConfig) {
476
+ for (const name of [crdtTableName, baseTableName]) {
477
+ if (seenNames.has(name)) {
478
+ throw new Error(`Duplicate table name "${name}" in sync schema`);
479
+ }
480
+ seenNames.add(name);
481
+ }
482
+ }
483
+ return {
484
+ tables,
485
+ get tablesConfig() {
486
+ return tablesConfig;
487
+ },
488
+ get migrations() {
489
+ return migrations;
490
+ },
491
+ get "~clientSchema"() {
492
+ throw new Error("~clientSchema is type-only and cannot be accessed at runtime");
493
+ },
494
+ get "~serverSchema"() {
495
+ throw new Error("~serverSchema is type-only and cannot be accessed at runtime");
496
+ },
497
+ get "~mutationsSchema"() {
498
+ throw new Error("~mutationsSchema is type-only and cannot be accessed at runtime");
499
+ }
500
+ };
464
501
  }
465
- var CrdtSchemaBuilder = class _CrdtSchemaBuilder {
466
- constructor(config) {
467
- this.config = config;
502
+
503
+ // src/schema/table-builder.ts
504
+ var ColumnBuilder = class _ColumnBuilder {
505
+ constructor(meta) {
506
+ this.meta = meta;
468
507
  }
469
- get tablesConfig() {
470
- return this.config.tables;
508
+ /** Allow SQL NULL; widens the value type with `null`. */
509
+ nullable() {
510
+ return new _ColumnBuilder({ ...this.meta, nullable: true });
471
511
  }
472
- get migrations() {
473
- return this.config.migrations;
512
+ /** Declare a column default. The value is used both in DDL and when migrating older events. */
513
+ default(value) {
514
+ return new _ColumnBuilder({ ...this.meta, hasDefault: true, defaultValue: value });
474
515
  }
475
- get "~clientSchema"() {
476
- console.warn("~clientSchema should not be accessed on the client");
477
- return null;
516
+ /** Narrow the TypeScript value type without changing storage, e.g. `t.text().$type<"movie" | "tv">()`. */
517
+ $type() {
518
+ return this;
478
519
  }
479
- get "~serverSchema"() {
480
- console.warn("~serverSchema should not be accessed on the server");
481
- return null;
520
+ /** Human/AI-readable description, surfaced in generated schema docs. */
521
+ describe(description) {
522
+ return new _ColumnBuilder({ ...this.meta, description });
482
523
  }
483
- get "~mutationsSchema"() {
484
- console.warn("~mutationsSchema should not be accessed on the client");
524
+ };
525
+ var RESERVED_COLUMNS = ["id", "tombstone"];
526
+ var idColumnMeta = {
527
+ kind: "text",
528
+ sqlType: "text",
529
+ nullable: false,
530
+ hasDefault: false,
531
+ description: "Unique immutable item id"
532
+ };
533
+ var tombstoneColumnMeta = {
534
+ kind: "boolean",
535
+ sqlType: "integer",
536
+ nullable: false,
537
+ hasDefault: true,
538
+ defaultValue: false,
539
+ description: "Soft-delete marker"
540
+ };
541
+ var TableBuilder = class _TableBuilder {
542
+ constructor(userColumns, options) {
543
+ this.userColumns = userColumns;
544
+ for (const reserved of RESERVED_COLUMNS) {
545
+ if (reserved in userColumns) {
546
+ throw new Error(`Column "${reserved}" is added automatically to every synced table and cannot be declared`);
547
+ }
548
+ }
549
+ this.columns = {
550
+ id: idColumnMeta,
551
+ ...Object.fromEntries(Object.entries(userColumns).map(([name, column2]) => [name, column2.meta])),
552
+ tombstone: tombstoneColumnMeta
553
+ };
554
+ this.baseName = options?.baseName;
555
+ this.description = options?.description;
556
+ }
557
+ /** All columns in DDL order, including the auto-injected `id` and `tombstone`. */
558
+ columns;
559
+ baseName;
560
+ description;
561
+ describe(description) {
562
+ return new _TableBuilder(this.userColumns, { baseName: this.baseName, description });
563
+ }
564
+ /** Type-only: the row shape returned by queries. Do not access at runtime. */
565
+ get $row() {
485
566
  return null;
486
567
  }
487
- addTable() {
488
- const withConfig = ({
489
- baseTableName,
490
- crdtTableName
491
- }) => {
492
- this.config.tables.push({ baseTableName, crdtTableName });
493
- return new _CrdtSchemaBuilder(this.config);
494
- };
495
- return { withConfig };
568
+ /**
569
+ * Validate a CRDT event payload against the declared columns.
570
+ * `item-created` payloads must contain every column without a default (nullable columns may be omitted);
571
+ * `item-updated` payloads are partial and must not touch `id` or set `tombstone` to a deleted value.
572
+ */
573
+ validatePayload(payload, options) {
574
+ const event = options?.event ?? "item-created";
575
+ const errors = [];
576
+ for (const key of Object.keys(payload)) {
577
+ if (!(key in this.columns)) {
578
+ errors.push(`Unknown column "${key}"`);
579
+ }
580
+ }
581
+ if (event === "item-updated") {
582
+ if ("id" in payload) {
583
+ errors.push(`Column "id" is immutable and cannot appear in an update payload`);
584
+ }
585
+ if (payload.tombstone === true || payload.tombstone === 1) {
586
+ errors.push(`Column "tombstone" cannot be set to true/1 in an update payload; use an item-deleted event`);
587
+ }
588
+ }
589
+ if (event === "item-created") {
590
+ for (const [name, meta] of Object.entries(this.columns)) {
591
+ if (name in payload || name === "tombstone" || meta.nullable || meta.hasDefault) {
592
+ continue;
593
+ }
594
+ errors.push(`Missing required column "${name}"`);
595
+ }
596
+ }
597
+ for (const [name, value] of Object.entries(payload)) {
598
+ const meta = this.columns[name];
599
+ if (!meta || event === "item-updated" && name === "id") {
600
+ continue;
601
+ }
602
+ const error = validateValue(name, value, meta);
603
+ if (error) {
604
+ errors.push(error);
605
+ }
606
+ }
607
+ return errors.length === 0 ? { success: true } : { success: false, errors };
496
608
  }
497
- build() {
498
- return this;
609
+ };
610
+ function describeValue(value) {
611
+ if (value === null) return "null";
612
+ if (Array.isArray(value)) return "array";
613
+ return typeof value;
614
+ }
615
+ function validateValue(name, value, meta) {
616
+ if (value === null) {
617
+ return meta.nullable ? null : `Column "${name}" is not nullable, got null`;
499
618
  }
619
+ switch (meta.kind) {
620
+ case "text":
621
+ return typeof value === "string" ? null : `Column "${name}" expects text, got ${describeValue(value)}`;
622
+ case "integer":
623
+ return typeof value === "number" && Number.isInteger(value) ? null : `Column "${name}" expects an integer, got ${describeValue(value)}`;
624
+ case "real":
625
+ return typeof value === "number" && Number.isFinite(value) ? null : `Column "${name}" expects a number, got ${describeValue(value)}`;
626
+ case "boolean":
627
+ return typeof value === "boolean" || value === 0 || value === 1 ? null : `Column "${name}" expects a boolean (true/false or 0/1), got ${describeValue(value)}`;
628
+ case "enum": {
629
+ if (typeof value !== "string") {
630
+ return `Column "${name}" expects one of ${formatEnumValues(meta)}, got ${describeValue(value)}`;
631
+ }
632
+ return meta.enumValues?.includes(value) ? null : `Column "${name}" expects one of ${formatEnumValues(meta)}, got "${value}"`;
633
+ }
634
+ }
635
+ }
636
+ function formatEnumValues(meta) {
637
+ return (meta.enumValues ?? []).map((value) => `"${value}"`).join(" | ");
638
+ }
639
+ function column(kind, sqlType) {
640
+ return new ColumnBuilder({ kind, sqlType, nullable: false, hasDefault: false });
641
+ }
642
+ var t = {
643
+ text: () => column("text", "text"),
644
+ integer: () => column("integer", "integer"),
645
+ real: () => column("real", "real"),
646
+ /** Stored as INTEGER 0/1; always bind booleans as 0/1 when writing raw SQL. */
647
+ boolean: () => column("boolean", "integer"),
648
+ /**
649
+ * Union of string literals stored as TEXT, e.g. `t.enum(["movie", "tv"])`. Unlike `$type`, the
650
+ * allowed values are kept as runtime metadata, so payloads are validated against them.
651
+ * For an open-ended set, use `t.text().$type<"idle" | (string & {})>()` instead.
652
+ */
653
+ enum: (values) => new ColumnBuilder({
654
+ kind: "enum",
655
+ sqlType: "text",
656
+ nullable: false,
657
+ hasDefault: false,
658
+ enumValues: values
659
+ }),
660
+ table: (columns, options) => new TableBuilder(columns, options)
500
661
  };
501
662
 
502
663
  // src/sqlite-crdt/crdt-storage-mutator.ts
@@ -583,7 +744,7 @@ select * from ${quoteId(baseTableName)}
583
744
  where tombstone = 0;`,
584
745
  { loggerLevel: "system" }
585
746
  );
586
- const allColumnNames = tableSchema.columns.map((column) => column.name);
747
+ const allColumnNames = tableSchema.columns.map((column2) => column2.name);
587
748
  const jsonPayload = (from) => `'{'||${allColumnNames.map((col) => `'"${col}":'||json_quote(${from}.${quoteId(col)})`).join("||','||")}||'}'`;
588
749
  db.execute(
589
750
  `
@@ -636,17 +797,12 @@ function registerCrdtFunctions({
636
797
  innocuous: false,
637
798
  callback: (dataset, payloadRaw) => {
638
799
  const payload = JSON.parse(payloadRaw);
639
- storage.applyOwnEvent(
640
- {
641
- type: "item-created",
642
- dataset,
643
- item_id: payload.id,
644
- payload: payloadRaw
645
- },
646
- {
647
- wrapInTransaction: false
648
- }
649
- );
800
+ storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {
801
+ type: "item-created",
802
+ dataset,
803
+ item_id: payload.id,
804
+ payload: payloadRaw
805
+ });
650
806
  eventApplied = true;
651
807
  return void 0;
652
808
  }
@@ -668,34 +824,29 @@ function registerCrdtFunctions({
668
824
  const newPayload = JSON.parse(newPayloadRaw);
669
825
  let hasDiff = false;
670
826
  const updatePayload = {};
671
- for (const column of tableSchema.columns) {
672
- const oldValue = oldPayload[column.name];
673
- const newValue = newPayload[column.name];
827
+ for (const column2 of tableSchema.columns) {
828
+ const oldValue = oldPayload[column2.name];
829
+ const newValue = newPayload[column2.name];
674
830
  if (oldValue === newValue) {
675
831
  continue;
676
832
  }
677
- if (column.name === "id") {
833
+ if (column2.name === "id") {
678
834
  throw new Error(
679
835
  `Cannot update the "id" column of an item. It is used to identify the item and must be immutable.`
680
836
  );
681
837
  }
682
838
  hasDiff = true;
683
- updatePayload[column.name] = newValue;
839
+ updatePayload[column2.name] = newValue;
684
840
  }
685
841
  if (!hasDiff) {
686
842
  return;
687
843
  }
688
- storage.applyOwnEvent(
689
- {
690
- type: "item-updated",
691
- dataset,
692
- item_id: oldPayload.id,
693
- payload: JSON.stringify(updatePayload)
694
- },
695
- {
696
- wrapInTransaction: false
697
- }
698
- );
844
+ storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {
845
+ type: "item-updated",
846
+ dataset,
847
+ item_id: oldPayload.id,
848
+ payload: JSON.stringify(updatePayload)
849
+ });
699
850
  eventApplied = true;
700
851
  return void 0;
701
852
  }
@@ -706,17 +857,12 @@ function registerCrdtFunctions({
706
857
  directOnly: false,
707
858
  innocuous: false,
708
859
  callback: (dataset, itemId) => {
709
- storage.applyOwnEvent(
710
- {
711
- type: "item-deleted",
712
- dataset,
713
- item_id: itemId,
714
- payload: "{}"
715
- },
716
- {
717
- wrapInTransaction: false
718
- }
719
- );
860
+ storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {
861
+ type: "item-deleted",
862
+ dataset,
863
+ item_id: itemId,
864
+ payload: "{}"
865
+ });
720
866
  eventApplied = true;
721
867
  return void 0;
722
868
  }
@@ -724,7 +870,7 @@ function registerCrdtFunctions({
724
870
  reactiveDb.addEventListener("transaction-committed", () => {
725
871
  if (eventApplied) {
726
872
  eventApplied = false;
727
- storage.dispatchEventsApplied();
873
+ void storage.internal.processEnqueuedEvents();
728
874
  }
729
875
  });
730
876
  reactiveDb.addEventListener("transaction-rolled-back", () => {
@@ -799,7 +945,8 @@ async function createMemoryDb({
799
945
  crdtTables,
800
946
  initializeSchema = true,
801
947
  initialSyncId,
802
- eventHlcAccumulator
948
+ eventHlcAccumulator,
949
+ syncDbSchema
803
950
  }) {
804
951
  await xxhash.ensureLoaded();
805
952
  const reactiveDb = _reactiveDb;
@@ -821,7 +968,8 @@ async function createMemoryDb({
821
968
  migrator,
822
969
  db,
823
970
  dbConfig: memoryDbConfig,
824
- eventHlcAccumulator
971
+ eventHlcAccumulator,
972
+ schema: syncDbSchema
825
973
  });
826
974
  registerCrdtFunctions({
827
975
  reactiveDb,
@@ -1004,7 +1152,8 @@ async function createSyncedDb(options) {
1004
1152
  migrator: memoryDbMigrator,
1005
1153
  reactiveDb,
1006
1154
  hlcCounter,
1007
- crdtTables: options.syncDbSchema.tablesConfig
1155
+ crdtTables: options.syncDbSchema.tablesConfig,
1156
+ syncDbSchema: options.syncDbSchema
1008
1157
  });
1009
1158
  const pullSyncId = createStoredValue({
1010
1159
  initialValue: workerClientSnapshot.syncId
@@ -1105,10 +1254,13 @@ async function createSyncedDb(options) {
1105
1254
  }
1106
1255
  export {
1107
1256
  CRDT_EVENT_NO_OP_PAYLOAD,
1257
+ ColumnBuilder,
1258
+ CrdtEventValidationError,
1108
1259
  HLCCounter,
1109
1260
  RESET_REQUEST_TTL_MS,
1110
1261
  SQLiteDbWrapper,
1111
1262
  SQLiteReactiveDb,
1263
+ TableBuilder,
1112
1264
  TypedBroadcastChannel,
1113
1265
  TypedEvent,
1114
1266
  applyMemoryDbSchema,
@@ -1127,12 +1279,13 @@ export {
1127
1279
  createSQLiteCrdtApplyFunction,
1128
1280
  createSQLiteKvStore,
1129
1281
  createStoredValue,
1130
- createSyncDbSchema,
1131
1282
  createSyncedDb,
1132
1283
  createSystemDbConfig,
1133
1284
  createTypedEventTarget,
1285
+ defineSyncSchema,
1134
1286
  deserializeHLC,
1135
1287
  dummyKysely,
1288
+ formatSchemaVerificationIssues,
1136
1289
  generateId,
1137
1290
  introspectDb,
1138
1291
  isNoOpCrdtEventPayload,
@@ -1143,8 +1296,11 @@ export {
1143
1296
  runSystemMigrations,
1144
1297
  serializeHLC,
1145
1298
  startPerformanceLogger,
1299
+ t,
1146
1300
  tryCatch,
1147
1301
  tryCatchAsync,
1302
+ validateNewCrdtEvent,
1303
+ verifySyncSchema,
1148
1304
  xxhash
1149
1305
  };
1150
1306
  //# sourceMappingURL=index.js.map