@quereus/plugin-sync 0.3.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.
Files changed (78) hide show
  1. package/README.md +154 -0
  2. package/dist/src/clock/hlc.d.ts +105 -0
  3. package/dist/src/clock/hlc.d.ts.map +1 -0
  4. package/dist/src/clock/hlc.js +251 -0
  5. package/dist/src/clock/hlc.js.map +1 -0
  6. package/dist/src/clock/index.d.ts +6 -0
  7. package/dist/src/clock/index.d.ts.map +1 -0
  8. package/dist/src/clock/index.js +6 -0
  9. package/dist/src/clock/index.js.map +1 -0
  10. package/dist/src/clock/site.d.ts +58 -0
  11. package/dist/src/clock/site.d.ts.map +1 -0
  12. package/dist/src/clock/site.js +137 -0
  13. package/dist/src/clock/site.js.map +1 -0
  14. package/dist/src/create-sync-module.d.ts +85 -0
  15. package/dist/src/create-sync-module.d.ts.map +1 -0
  16. package/dist/src/create-sync-module.js +54 -0
  17. package/dist/src/create-sync-module.js.map +1 -0
  18. package/dist/src/index.d.ts +31 -0
  19. package/dist/src/index.d.ts.map +1 -0
  20. package/dist/src/index.js +42 -0
  21. package/dist/src/index.js.map +1 -0
  22. package/dist/src/metadata/change-log.d.ts +67 -0
  23. package/dist/src/metadata/change-log.d.ts.map +1 -0
  24. package/dist/src/metadata/change-log.js +107 -0
  25. package/dist/src/metadata/change-log.js.map +1 -0
  26. package/dist/src/metadata/column-version.d.ts +58 -0
  27. package/dist/src/metadata/column-version.d.ts.map +1 -0
  28. package/dist/src/metadata/column-version.js +100 -0
  29. package/dist/src/metadata/column-version.js.map +1 -0
  30. package/dist/src/metadata/index.d.ts +11 -0
  31. package/dist/src/metadata/index.d.ts.map +1 -0
  32. package/dist/src/metadata/index.js +11 -0
  33. package/dist/src/metadata/index.js.map +1 -0
  34. package/dist/src/metadata/keys.d.ts +180 -0
  35. package/dist/src/metadata/keys.d.ts.map +1 -0
  36. package/dist/src/metadata/keys.js +390 -0
  37. package/dist/src/metadata/keys.js.map +1 -0
  38. package/dist/src/metadata/peer-state.d.ts +52 -0
  39. package/dist/src/metadata/peer-state.d.ts.map +1 -0
  40. package/dist/src/metadata/peer-state.js +87 -0
  41. package/dist/src/metadata/peer-state.js.map +1 -0
  42. package/dist/src/metadata/schema-migration.d.ts +60 -0
  43. package/dist/src/metadata/schema-migration.d.ts.map +1 -0
  44. package/dist/src/metadata/schema-migration.js +126 -0
  45. package/dist/src/metadata/schema-migration.js.map +1 -0
  46. package/dist/src/metadata/schema-version.d.ts +163 -0
  47. package/dist/src/metadata/schema-version.d.ts.map +1 -0
  48. package/dist/src/metadata/schema-version.js +307 -0
  49. package/dist/src/metadata/schema-version.js.map +1 -0
  50. package/dist/src/metadata/tombstones.d.ts +67 -0
  51. package/dist/src/metadata/tombstones.d.ts.map +1 -0
  52. package/dist/src/metadata/tombstones.js +125 -0
  53. package/dist/src/metadata/tombstones.js.map +1 -0
  54. package/dist/src/sync/events.d.ts +117 -0
  55. package/dist/src/sync/events.d.ts.map +1 -0
  56. package/dist/src/sync/events.js +56 -0
  57. package/dist/src/sync/events.js.map +1 -0
  58. package/dist/src/sync/index.d.ts +8 -0
  59. package/dist/src/sync/index.d.ts.map +1 -0
  60. package/dist/src/sync/index.js +8 -0
  61. package/dist/src/sync/index.js.map +1 -0
  62. package/dist/src/sync/manager.d.ts +146 -0
  63. package/dist/src/sync/manager.d.ts.map +1 -0
  64. package/dist/src/sync/manager.js +8 -0
  65. package/dist/src/sync/manager.js.map +1 -0
  66. package/dist/src/sync/protocol.d.ts +282 -0
  67. package/dist/src/sync/protocol.d.ts.map +1 -0
  68. package/dist/src/sync/protocol.js +16 -0
  69. package/dist/src/sync/protocol.js.map +1 -0
  70. package/dist/src/sync/store-adapter.d.ts +42 -0
  71. package/dist/src/sync/store-adapter.d.ts.map +1 -0
  72. package/dist/src/sync/store-adapter.js +232 -0
  73. package/dist/src/sync/store-adapter.js.map +1 -0
  74. package/dist/src/sync/sync-manager-impl.d.ts +91 -0
  75. package/dist/src/sync/sync-manager-impl.d.ts.map +1 -0
  76. package/dist/src/sync/sync-manager-impl.js +1123 -0
  77. package/dist/src/sync/sync-manager-impl.js.map +1 -0
  78. package/package.json +64 -0
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Sync protocol types - transport-agnostic data structures.
3
+ *
4
+ * These types define the sync protocol without assuming any transport layer.
5
+ * Applications can serialize these to JSON, MessagePack, protobuf, etc.
6
+ * and send via WebSocket, HTTP, WebRTC, or any other transport.
7
+ */
8
+ import type { Row, SqlValue } from '@quereus/quereus';
9
+ import type { HLC } from '../clock/hlc.js';
10
+ import type { SiteId } from '../clock/site.js';
11
+ /**
12
+ * A single column modification within a row.
13
+ */
14
+ export interface ColumnChange {
15
+ readonly type: 'column';
16
+ readonly schema: string;
17
+ readonly table: string;
18
+ readonly pk: SqlValue[];
19
+ readonly column: string;
20
+ readonly value: SqlValue;
21
+ readonly hlc: HLC;
22
+ }
23
+ /**
24
+ * A row deletion.
25
+ */
26
+ export interface RowDeletion {
27
+ readonly type: 'delete';
28
+ readonly schema: string;
29
+ readonly table: string;
30
+ readonly pk: SqlValue[];
31
+ readonly hlc: HLC;
32
+ }
33
+ /**
34
+ * Union type for all change kinds.
35
+ */
36
+ export type Change = ColumnChange | RowDeletion;
37
+ /**
38
+ * Types of schema migrations.
39
+ */
40
+ export type SchemaMigrationType = 'create_table' | 'drop_table' | 'add_column' | 'drop_column' | 'add_index' | 'drop_index' | 'alter_column';
41
+ /**
42
+ * A schema migration record.
43
+ */
44
+ export interface SchemaMigration {
45
+ readonly type: SchemaMigrationType;
46
+ readonly schema: string;
47
+ readonly table: string;
48
+ readonly ddl: string;
49
+ readonly hlc: HLC;
50
+ readonly schemaVersion: number;
51
+ }
52
+ /**
53
+ * A transaction's worth of changes.
54
+ * All changes within a ChangeSet are applied atomically.
55
+ */
56
+ export interface ChangeSet {
57
+ /** Origin replica */
58
+ readonly siteId: SiteId;
59
+ /** Unique transaction identifier */
60
+ readonly transactionId: string;
61
+ /** Transaction commit time */
62
+ readonly hlc: HLC;
63
+ /** Data changes in this transaction */
64
+ readonly changes: Change[];
65
+ /** Schema migrations in this transaction */
66
+ readonly schemaMigrations: SchemaMigration[];
67
+ }
68
+ /**
69
+ * Result of applying changes from a peer.
70
+ */
71
+ export interface ApplyResult {
72
+ /** Changes successfully applied (winner was remote) */
73
+ applied: number;
74
+ /** Changes skipped (already present or local won) */
75
+ skipped: number;
76
+ /** Conflicts resolved via LWW */
77
+ conflicts: number;
78
+ /** Number of transactions processed */
79
+ transactions: number;
80
+ }
81
+ /**
82
+ * Column version entry for snapshot.
83
+ */
84
+ export interface ColumnVersionEntry {
85
+ readonly hlc: HLC;
86
+ readonly value: SqlValue;
87
+ }
88
+ /**
89
+ * Full snapshot of a table for initial sync or recovery.
90
+ */
91
+ export interface TableSnapshot {
92
+ readonly schema: string;
93
+ readonly table: string;
94
+ readonly rows: Row[];
95
+ /** Column versions for each row, keyed by serialized PK + column name */
96
+ readonly columnVersions: Map<string, ColumnVersionEntry>;
97
+ }
98
+ /**
99
+ * Full database snapshot.
100
+ */
101
+ export interface Snapshot {
102
+ readonly siteId: SiteId;
103
+ readonly hlc: HLC;
104
+ readonly tables: TableSnapshot[];
105
+ readonly schemaMigrations: SchemaMigration[];
106
+ }
107
+ /**
108
+ * Snapshot chunk types for streaming.
109
+ */
110
+ export type SnapshotChunkType = 'header' | 'table-start' | 'column-versions' | 'table-end' | 'schema-migration' | 'footer';
111
+ /**
112
+ * Header chunk - sent first with metadata.
113
+ */
114
+ export interface SnapshotHeaderChunk {
115
+ readonly type: 'header';
116
+ readonly siteId: SiteId;
117
+ readonly hlc: HLC;
118
+ readonly tableCount: number;
119
+ readonly migrationCount: number;
120
+ /** Unique identifier for this snapshot transfer. */
121
+ readonly snapshotId: string;
122
+ }
123
+ /**
124
+ * Table start chunk - marks beginning of a table's data.
125
+ */
126
+ export interface SnapshotTableStartChunk {
127
+ readonly type: 'table-start';
128
+ readonly schema: string;
129
+ readonly table: string;
130
+ /** Estimated number of column version entries for this table. */
131
+ readonly estimatedEntries: number;
132
+ }
133
+ /**
134
+ * Column versions chunk - batch of column version entries.
135
+ */
136
+ export interface SnapshotColumnVersionsChunk {
137
+ readonly type: 'column-versions';
138
+ readonly schema: string;
139
+ readonly table: string;
140
+ /** Column versions as [versionKey, hlc, value] tuples. */
141
+ readonly entries: Array<[string, HLC, SqlValue]>;
142
+ }
143
+ /**
144
+ * Table end chunk - marks end of a table's data.
145
+ */
146
+ export interface SnapshotTableEndChunk {
147
+ readonly type: 'table-end';
148
+ readonly schema: string;
149
+ readonly table: string;
150
+ readonly entriesWritten: number;
151
+ }
152
+ /**
153
+ * Schema migration chunk.
154
+ */
155
+ export interface SnapshotSchemaMigrationChunk {
156
+ readonly type: 'schema-migration';
157
+ readonly migration: SchemaMigration;
158
+ }
159
+ /**
160
+ * Footer chunk - sent last with checksum/stats.
161
+ */
162
+ export interface SnapshotFooterChunk {
163
+ readonly type: 'footer';
164
+ readonly snapshotId: string;
165
+ readonly totalTables: number;
166
+ readonly totalEntries: number;
167
+ readonly totalMigrations: number;
168
+ }
169
+ /**
170
+ * Union of all snapshot chunk types.
171
+ */
172
+ export type SnapshotChunk = SnapshotHeaderChunk | SnapshotTableStartChunk | SnapshotColumnVersionsChunk | SnapshotTableEndChunk | SnapshotSchemaMigrationChunk | SnapshotFooterChunk;
173
+ /**
174
+ * Progress info during snapshot streaming.
175
+ */
176
+ export interface SnapshotProgress {
177
+ readonly snapshotId: string;
178
+ readonly tablesProcessed: number;
179
+ readonly totalTables: number;
180
+ readonly entriesProcessed: number;
181
+ readonly totalEntries: number;
182
+ readonly currentTable?: string;
183
+ }
184
+ /**
185
+ * Options for applying changes to the store.
186
+ */
187
+ export interface ApplyToStoreOptions {
188
+ /**
189
+ * Mark resulting events as remote (from sync).
190
+ * When true, the store should emit events with `remote: true`,
191
+ * preventing the SyncManager from re-recording CRDT metadata.
192
+ */
193
+ readonly remote: boolean;
194
+ }
195
+ /**
196
+ * A data change to apply to the store.
197
+ */
198
+ export interface DataChangeToApply {
199
+ readonly type: 'insert' | 'update' | 'delete';
200
+ readonly schema: string;
201
+ readonly table: string;
202
+ readonly pk: SqlValue[];
203
+ /** Column values to apply. Keys are column names, values are column values. */
204
+ readonly columns?: Record<string, SqlValue>;
205
+ }
206
+ /**
207
+ * A schema change to apply to the store.
208
+ */
209
+ export interface SchemaChangeToApply {
210
+ readonly type: SchemaMigrationType;
211
+ readonly schema: string;
212
+ readonly table: string;
213
+ /** The DDL statement to execute. */
214
+ readonly ddl: string;
215
+ }
216
+ /**
217
+ * Result of applying changes to the store.
218
+ */
219
+ export interface ApplyToStoreResult {
220
+ /** Number of data changes successfully applied. */
221
+ dataChangesApplied: number;
222
+ /** Number of schema changes successfully applied. */
223
+ schemaChangesApplied: number;
224
+ /** Errors encountered (empty if all succeeded). */
225
+ errors: Array<{
226
+ change: DataChangeToApply | SchemaChangeToApply;
227
+ error: Error;
228
+ }>;
229
+ }
230
+ /**
231
+ * Callback interface for applying remote changes to the store.
232
+ *
233
+ * The SyncManager uses this callback to apply changes from remote replicas.
234
+ * The implementation should:
235
+ * 1. Execute the changes against the actual data store
236
+ * 2. Emit events with `remote: true` when `options.remote` is true
237
+ *
238
+ * This allows the store plugin to handle the actual data manipulation
239
+ * while the sync module handles CRDT metadata.
240
+ */
241
+ export type ApplyToStoreCallback = (dataChanges: DataChangeToApply[], schemaChanges: SchemaChangeToApply[], options: ApplyToStoreOptions) => Promise<ApplyToStoreResult>;
242
+ /**
243
+ * Tracks sync state with a specific peer.
244
+ */
245
+ export interface PeerSyncState {
246
+ readonly peerSiteId: SiteId;
247
+ /** Last HLC we've synced up to with this peer */
248
+ readonly lastSyncHLC: HLC;
249
+ /** When we last successfully synced */
250
+ readonly lastSyncTime: number;
251
+ }
252
+ /**
253
+ * Sync module configuration.
254
+ */
255
+ export interface SyncConfig {
256
+ /**
257
+ * Tombstone retention period in milliseconds.
258
+ * After this period, delta sync may not be possible.
259
+ * Default: 30 days (30 * 24 * 60 * 60 * 1000)
260
+ */
261
+ tombstoneTTL: number;
262
+ /**
263
+ * Whether deleted rows can be resurrected by later writes.
264
+ * If false (default), a deletion prevents any column write with earlier HLC.
265
+ * If true, an insert/update with later HLC can resurrect a deleted row.
266
+ */
267
+ allowResurrection: boolean;
268
+ /**
269
+ * Maximum number of changes to return in a single sync batch.
270
+ * Default: 1000
271
+ */
272
+ batchSize: number;
273
+ /**
274
+ * Pre-configured site ID. If not provided, one will be generated.
275
+ */
276
+ siteId?: SiteId;
277
+ }
278
+ /**
279
+ * Default sync configuration.
280
+ */
281
+ export declare const DEFAULT_SYNC_CONFIG: SyncConfig;
282
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/sync/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Sync protocol types - transport-agnostic data structures.
3
+ *
4
+ * These types define the sync protocol without assuming any transport layer.
5
+ * Applications can serialize these to JSON, MessagePack, protobuf, etc.
6
+ * and send via WebSocket, HTTP, WebRTC, or any other transport.
7
+ */
8
+ /**
9
+ * Default sync configuration.
10
+ */
11
+ export const DEFAULT_SYNC_CONFIG = {
12
+ tombstoneTTL: 30 * 24 * 60 * 60 * 1000, // 30 days
13
+ allowResurrection: false,
14
+ batchSize: 1000,
15
+ };
16
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/sync/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkWH;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAG,UAAU;IACnD,iBAAiB,EAAE,KAAK;IACxB,SAAS,EAAE,IAAI;CAChB,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Store adapter for applying remote sync changes.
3
+ *
4
+ * This module provides adapters that implement the ApplyToStoreCallback
5
+ * interface for LevelDB and IndexedDB stores, enabling the SyncManager
6
+ * to apply remote changes to the actual data store.
7
+ */
8
+ import type { Database, TableSchema } from '@quereus/quereus';
9
+ import type { KVStore, StoreEventEmitter } from '@quereus/plugin-store';
10
+ import type { ApplyToStoreCallback } from './protocol.js';
11
+ /**
12
+ * Options for creating a SyncStoreAdapter.
13
+ */
14
+ export interface SyncStoreAdapterOptions {
15
+ /** The Quereus database for executing DDL statements. */
16
+ db: Database;
17
+ /**
18
+ * Function to get the KV store for a specific table.
19
+ * Each table may have its own IndexedDB database, so we need to look up
20
+ * the correct store for each table when applying remote changes.
21
+ */
22
+ getKVStore: (schemaName: string, tableName: string) => Promise<KVStore>;
23
+ /** The event emitter for data change events. */
24
+ events: StoreEventEmitter;
25
+ /** Function to get table schema by name. */
26
+ getTableSchema: (schemaName: string, tableName: string) => TableSchema | undefined;
27
+ /** Collation for text key encoding. */
28
+ collation?: 'BINARY' | 'NOCASE';
29
+ }
30
+ /**
31
+ * Creates an ApplyToStoreCallback for applying remote sync changes.
32
+ *
33
+ * This adapter handles:
34
+ * - UPSERT semantics for column changes (insert if row doesn't exist, update if it does)
35
+ * - Row deletions by primary key
36
+ * - DDL execution for schema changes
37
+ *
38
+ * All data change events are emitted with `remote: true` to prevent
39
+ * the SyncManager from re-recording CRDT metadata.
40
+ */
41
+ export declare function createStoreAdapter(options: SyncStoreAdapterOptions): ApplyToStoreCallback;
42
+ //# sourceMappingURL=store-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-adapter.d.ts","sourceRoot":"","sources":["../../../src/sync/store-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAiB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,KAAK,EACV,oBAAoB,EAKrB,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,EAAE,EAAE,QAAQ,CAAC;IACb;;;;OAIG;IACH,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,gDAAgD;IAChD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,4CAA4C;IAC5C,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IACnF,uCAAuC;IACvC,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CACjC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,uBAAuB,GAAG,oBAAoB,CAyDzF"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Store adapter for applying remote sync changes.
3
+ *
4
+ * This module provides adapters that implement the ApplyToStoreCallback
5
+ * interface for LevelDB and IndexedDB stores, enabling the SyncManager
6
+ * to apply remote changes to the actual data store.
7
+ */
8
+ import { buildDataKey, serializeRow, deserializeRow } from '@quereus/plugin-store';
9
+ /**
10
+ * Creates an ApplyToStoreCallback for applying remote sync changes.
11
+ *
12
+ * This adapter handles:
13
+ * - UPSERT semantics for column changes (insert if row doesn't exist, update if it does)
14
+ * - Row deletions by primary key
15
+ * - DDL execution for schema changes
16
+ *
17
+ * All data change events are emitted with `remote: true` to prevent
18
+ * the SyncManager from re-recording CRDT metadata.
19
+ */
20
+ export function createStoreAdapter(options) {
21
+ const { db, getKVStore, events, getTableSchema, collation = 'NOCASE' } = options;
22
+ return async (dataChanges, schemaChanges, applyOptions) => {
23
+ const result = {
24
+ dataChangesApplied: 0,
25
+ schemaChangesApplied: 0,
26
+ errors: [],
27
+ };
28
+ // Apply schema changes first (DDL before DML)
29
+ for (const schemaChange of schemaChanges) {
30
+ try {
31
+ await applySchemaChange(db, events, schemaChange, applyOptions);
32
+ result.schemaChangesApplied++;
33
+ }
34
+ catch (error) {
35
+ result.errors.push({
36
+ change: schemaChange,
37
+ error: error instanceof Error ? error : new Error(String(error)),
38
+ });
39
+ }
40
+ }
41
+ // Group data changes by table for efficient batch operations
42
+ // Each table may have its own KV store (especially in IndexedDB)
43
+ const changesByTable = groupChangesByTable(dataChanges);
44
+ // Apply data changes per table
45
+ for (const [tableKey, tableChanges] of changesByTable) {
46
+ const [schemaName, tableName] = tableKey.split('.');
47
+ try {
48
+ // Get the correct KV store for this table
49
+ const kv = await getKVStore(schemaName, tableName);
50
+ // Group by row within the table
51
+ const changesByRow = groupChangesByRow(tableChanges);
52
+ for (const [rowKey, rowChanges] of changesByRow) {
53
+ await applyRowChanges(kv, events, getTableSchema, collation, rowKey, rowChanges, applyOptions);
54
+ result.dataChangesApplied += rowChanges.length;
55
+ }
56
+ }
57
+ catch (error) {
58
+ for (const change of tableChanges) {
59
+ result.errors.push({
60
+ change,
61
+ error: error instanceof Error ? error : new Error(String(error)),
62
+ });
63
+ }
64
+ }
65
+ }
66
+ return result;
67
+ };
68
+ }
69
+ /**
70
+ * Group data changes by table (schema.table).
71
+ */
72
+ function groupChangesByTable(changes) {
73
+ const grouped = new Map();
74
+ for (const change of changes) {
75
+ const tableKey = `${change.schema}.${change.table}`;
76
+ const existing = grouped.get(tableKey);
77
+ if (existing) {
78
+ existing.push(change);
79
+ }
80
+ else {
81
+ grouped.set(tableKey, [change]);
82
+ }
83
+ }
84
+ return grouped;
85
+ }
86
+ /**
87
+ * Group data changes by row (schema.table:pk).
88
+ */
89
+ function groupChangesByRow(changes) {
90
+ const grouped = new Map();
91
+ for (const change of changes) {
92
+ const rowKey = `${change.schema}.${change.table}:${JSON.stringify(change.pk)}`;
93
+ const existing = grouped.get(rowKey);
94
+ if (existing) {
95
+ existing.push(change);
96
+ }
97
+ else {
98
+ grouped.set(rowKey, [change]);
99
+ }
100
+ }
101
+ return grouped;
102
+ }
103
+ /**
104
+ * Apply schema changes (DDL) to the database.
105
+ */
106
+ async function applySchemaChange(db, events, change, _options) {
107
+ // Determine the event signature
108
+ const eventType = change.type.startsWith('drop') ? 'drop' : change.type.startsWith('create') ? 'create' : 'alter';
109
+ const objectType = change.type.includes('table') ? 'table' : 'index';
110
+ // Register this as an expected remote event BEFORE executing DDL.
111
+ // When IndexedDBModule.create() emits the event, it will be automatically
112
+ // marked as remote, so SyncManager won't re-record it.
113
+ // This approach avoids race conditions with concurrent local DDL.
114
+ events.expectRemoteSchemaEvent({
115
+ type: eventType,
116
+ objectType,
117
+ schemaName: change.schema,
118
+ objectName: change.table,
119
+ });
120
+ try {
121
+ // Execute the DDL statement
122
+ // The module will emit a schema event, which will be marked as remote
123
+ await db.exec(change.ddl);
124
+ }
125
+ catch (e) {
126
+ // Clear the expectation if DDL failed
127
+ events.clearExpectedRemoteSchemaEvent({
128
+ type: eventType,
129
+ objectType,
130
+ schemaName: change.schema,
131
+ objectName: change.table,
132
+ });
133
+ throw e;
134
+ }
135
+ // Note: We don't emit a separate event here anymore.
136
+ // The module's event is automatically marked as remote.
137
+ }
138
+ /**
139
+ * Apply data changes for a single row.
140
+ */
141
+ async function applyRowChanges(kv, events, getTableSchema, collation, _rowKey, changes, _options) {
142
+ // All changes in the group should be for the same row
143
+ const firstChange = changes[0];
144
+ const { schema, table, pk } = firstChange;
145
+ const tableSchema = getTableSchema(schema, table);
146
+ if (!tableSchema) {
147
+ throw new Error(`Table schema not found: ${schema}.${table}`);
148
+ }
149
+ const encodeOptions = { collation };
150
+ const dataKey = buildDataKey(schema, table, pk, encodeOptions);
151
+ // Check for delete operations first
152
+ const deleteChange = changes.find(c => c.type === 'delete');
153
+ if (deleteChange) {
154
+ await applyDelete(kv, events, tableSchema, dataKey, pk);
155
+ return;
156
+ }
157
+ // Apply column updates (UPSERT semantics)
158
+ await applyColumnUpdates(kv, events, tableSchema, dataKey, pk, changes, { serializeRow, deserializeRow });
159
+ }
160
+ /**
161
+ * Apply a delete operation for a row.
162
+ */
163
+ async function applyDelete(kv, events, tableSchema, dataKey, pk) {
164
+ await kv.delete(dataKey);
165
+ // Emit data change event with remote flag
166
+ events.emitDataChange({
167
+ type: 'delete',
168
+ schemaName: tableSchema.schemaName,
169
+ tableName: tableSchema.name,
170
+ key: pk,
171
+ remote: true,
172
+ });
173
+ }
174
+ /**
175
+ * Apply column updates with UPSERT semantics.
176
+ */
177
+ async function applyColumnUpdates(kv, events, tableSchema, dataKey, pk, changes, serialization) {
178
+ const { serializeRow, deserializeRow } = serialization;
179
+ // Read existing row if any
180
+ const existingData = await kv.get(dataKey);
181
+ let row;
182
+ let isInsert = false;
183
+ if (existingData) {
184
+ row = deserializeRow(existingData);
185
+ }
186
+ else {
187
+ // Create new row with nulls
188
+ row = new Array(tableSchema.columns.length).fill(null);
189
+ // Set PK values
190
+ for (let i = 0; i < tableSchema.primaryKeyDefinition.length; i++) {
191
+ const pkDef = tableSchema.primaryKeyDefinition[i];
192
+ row[pkDef.index] = pk[i];
193
+ }
194
+ isInsert = true;
195
+ }
196
+ // Apply column changes from all changes
197
+ const changedColumns = [];
198
+ for (const change of changes) {
199
+ if (change.columns) {
200
+ for (const [colName, value] of Object.entries(change.columns)) {
201
+ const colIndex = tableSchema.columnIndexMap.get(colName.toLowerCase());
202
+ if (colIndex !== undefined) {
203
+ row[colIndex] = value;
204
+ changedColumns.push(colName);
205
+ }
206
+ else {
207
+ // Column name not found in schema - this could be a sync bug
208
+ console.warn(`[Sync] Column '${colName}' not found in ${tableSchema.schemaName}.${tableSchema.name}. ` +
209
+ `Available columns: ${[...tableSchema.columnIndexMap.keys()].join(', ')}`);
210
+ }
211
+ }
212
+ }
213
+ }
214
+ // Check if any columns were actually applied
215
+ if (changedColumns.length === 0 && !isInsert) {
216
+ console.warn(`[Sync] No columns were applied for ${tableSchema.schemaName}.${tableSchema.name} pk=${JSON.stringify(pk)}. ` +
217
+ `This may indicate a column name mismatch between source and destination.`);
218
+ }
219
+ // Write updated row
220
+ await kv.put(dataKey, serializeRow(row));
221
+ // Emit data change event with remote flag
222
+ events.emitDataChange({
223
+ type: isInsert ? 'insert' : 'update',
224
+ schemaName: tableSchema.schemaName,
225
+ tableName: tableSchema.name,
226
+ key: pk,
227
+ newRow: row,
228
+ changedColumns: isInsert ? undefined : changedColumns,
229
+ remote: true,
230
+ });
231
+ }
232
+ //# sourceMappingURL=store-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-adapter.js","sourceRoot":"","sources":["../../../src/sync/store-adapter.ts"],"names":[],"mappings":"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"}