@syncular/client 0.0.1-60

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 (176) hide show
  1. package/dist/blobs/index.d.ts +7 -0
  2. package/dist/blobs/index.d.ts.map +1 -0
  3. package/dist/blobs/index.js +7 -0
  4. package/dist/blobs/index.js.map +1 -0
  5. package/dist/blobs/manager.d.ts +345 -0
  6. package/dist/blobs/manager.d.ts.map +1 -0
  7. package/dist/blobs/manager.js +749 -0
  8. package/dist/blobs/manager.js.map +1 -0
  9. package/dist/blobs/migrate.d.ts +14 -0
  10. package/dist/blobs/migrate.d.ts.map +1 -0
  11. package/dist/blobs/migrate.js +59 -0
  12. package/dist/blobs/migrate.js.map +1 -0
  13. package/dist/blobs/types.d.ts +62 -0
  14. package/dist/blobs/types.d.ts.map +1 -0
  15. package/dist/blobs/types.js +5 -0
  16. package/dist/blobs/types.js.map +1 -0
  17. package/dist/client.d.ts +338 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +834 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/conflicts.d.ts +31 -0
  22. package/dist/conflicts.d.ts.map +1 -0
  23. package/dist/conflicts.js +118 -0
  24. package/dist/conflicts.js.map +1 -0
  25. package/dist/create-client.d.ts +115 -0
  26. package/dist/create-client.d.ts.map +1 -0
  27. package/dist/create-client.js +162 -0
  28. package/dist/create-client.js.map +1 -0
  29. package/dist/engine/SyncEngine.d.ts +215 -0
  30. package/dist/engine/SyncEngine.d.ts.map +1 -0
  31. package/dist/engine/SyncEngine.js +1066 -0
  32. package/dist/engine/SyncEngine.js.map +1 -0
  33. package/dist/engine/index.d.ts +6 -0
  34. package/dist/engine/index.d.ts.map +1 -0
  35. package/dist/engine/index.js +6 -0
  36. package/dist/engine/index.js.map +1 -0
  37. package/dist/engine/types.d.ts +230 -0
  38. package/dist/engine/types.d.ts.map +1 -0
  39. package/dist/engine/types.js +7 -0
  40. package/dist/engine/types.js.map +1 -0
  41. package/dist/handlers/create-handler.d.ts +110 -0
  42. package/dist/handlers/create-handler.d.ts.map +1 -0
  43. package/dist/handlers/create-handler.js +140 -0
  44. package/dist/handlers/create-handler.js.map +1 -0
  45. package/dist/handlers/registry.d.ts +15 -0
  46. package/dist/handlers/registry.d.ts.map +1 -0
  47. package/dist/handlers/registry.js +29 -0
  48. package/dist/handlers/registry.js.map +1 -0
  49. package/dist/handlers/types.d.ts +83 -0
  50. package/dist/handlers/types.d.ts.map +1 -0
  51. package/dist/handlers/types.js +5 -0
  52. package/dist/handlers/types.js.map +1 -0
  53. package/dist/index.d.ts +24 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +24 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/migrate.d.ts +19 -0
  58. package/dist/migrate.d.ts.map +1 -0
  59. package/dist/migrate.js +106 -0
  60. package/dist/migrate.js.map +1 -0
  61. package/dist/mutations.d.ts +138 -0
  62. package/dist/mutations.d.ts.map +1 -0
  63. package/dist/mutations.js +611 -0
  64. package/dist/mutations.js.map +1 -0
  65. package/dist/outbox.d.ts +112 -0
  66. package/dist/outbox.d.ts.map +1 -0
  67. package/dist/outbox.js +304 -0
  68. package/dist/outbox.js.map +1 -0
  69. package/dist/plugins/incrementing-version.d.ts +34 -0
  70. package/dist/plugins/incrementing-version.d.ts.map +1 -0
  71. package/dist/plugins/incrementing-version.js +83 -0
  72. package/dist/plugins/incrementing-version.js.map +1 -0
  73. package/dist/plugins/index.d.ts +3 -0
  74. package/dist/plugins/index.d.ts.map +1 -0
  75. package/dist/plugins/index.js +3 -0
  76. package/dist/plugins/index.js.map +1 -0
  77. package/dist/plugins/types.d.ts +49 -0
  78. package/dist/plugins/types.d.ts.map +1 -0
  79. package/dist/plugins/types.js +15 -0
  80. package/dist/plugins/types.js.map +1 -0
  81. package/dist/proxy/connection.d.ts +33 -0
  82. package/dist/proxy/connection.d.ts.map +1 -0
  83. package/dist/proxy/connection.js +153 -0
  84. package/dist/proxy/connection.js.map +1 -0
  85. package/dist/proxy/dialect.d.ts +46 -0
  86. package/dist/proxy/dialect.d.ts.map +1 -0
  87. package/dist/proxy/dialect.js +58 -0
  88. package/dist/proxy/dialect.js.map +1 -0
  89. package/dist/proxy/driver.d.ts +42 -0
  90. package/dist/proxy/driver.d.ts.map +1 -0
  91. package/dist/proxy/driver.js +78 -0
  92. package/dist/proxy/driver.js.map +1 -0
  93. package/dist/proxy/index.d.ts +10 -0
  94. package/dist/proxy/index.d.ts.map +1 -0
  95. package/dist/proxy/index.js +10 -0
  96. package/dist/proxy/index.js.map +1 -0
  97. package/dist/proxy/mutations.d.ts +9 -0
  98. package/dist/proxy/mutations.d.ts.map +1 -0
  99. package/dist/proxy/mutations.js +11 -0
  100. package/dist/proxy/mutations.js.map +1 -0
  101. package/dist/pull-engine.d.ts +45 -0
  102. package/dist/pull-engine.d.ts.map +1 -0
  103. package/dist/pull-engine.js +391 -0
  104. package/dist/pull-engine.js.map +1 -0
  105. package/dist/push-engine.d.ts +18 -0
  106. package/dist/push-engine.d.ts.map +1 -0
  107. package/dist/push-engine.js +155 -0
  108. package/dist/push-engine.js.map +1 -0
  109. package/dist/query/FingerprintCollector.d.ts +18 -0
  110. package/dist/query/FingerprintCollector.d.ts.map +1 -0
  111. package/dist/query/FingerprintCollector.js +28 -0
  112. package/dist/query/FingerprintCollector.js.map +1 -0
  113. package/dist/query/QueryContext.d.ts +33 -0
  114. package/dist/query/QueryContext.d.ts.map +1 -0
  115. package/dist/query/QueryContext.js +16 -0
  116. package/dist/query/QueryContext.js.map +1 -0
  117. package/dist/query/fingerprint.d.ts +61 -0
  118. package/dist/query/fingerprint.d.ts.map +1 -0
  119. package/dist/query/fingerprint.js +91 -0
  120. package/dist/query/fingerprint.js.map +1 -0
  121. package/dist/query/index.d.ts +7 -0
  122. package/dist/query/index.d.ts.map +1 -0
  123. package/dist/query/index.js +7 -0
  124. package/dist/query/index.js.map +1 -0
  125. package/dist/query/tracked-select.d.ts +18 -0
  126. package/dist/query/tracked-select.d.ts.map +1 -0
  127. package/dist/query/tracked-select.js +90 -0
  128. package/dist/query/tracked-select.js.map +1 -0
  129. package/dist/schema.d.ts +83 -0
  130. package/dist/schema.d.ts.map +1 -0
  131. package/dist/schema.js +7 -0
  132. package/dist/schema.js.map +1 -0
  133. package/dist/sync-loop.d.ts +32 -0
  134. package/dist/sync-loop.d.ts.map +1 -0
  135. package/dist/sync-loop.js +249 -0
  136. package/dist/sync-loop.js.map +1 -0
  137. package/dist/utils/id.d.ts +8 -0
  138. package/dist/utils/id.d.ts.map +1 -0
  139. package/dist/utils/id.js +19 -0
  140. package/dist/utils/id.js.map +1 -0
  141. package/package.json +58 -0
  142. package/src/blobs/index.ts +7 -0
  143. package/src/blobs/manager.ts +1027 -0
  144. package/src/blobs/migrate.ts +67 -0
  145. package/src/blobs/types.ts +84 -0
  146. package/src/client.ts +1222 -0
  147. package/src/conflicts.ts +180 -0
  148. package/src/create-client.ts +297 -0
  149. package/src/engine/SyncEngine.ts +1337 -0
  150. package/src/engine/index.ts +6 -0
  151. package/src/engine/types.ts +268 -0
  152. package/src/handlers/create-handler.ts +287 -0
  153. package/src/handlers/registry.ts +36 -0
  154. package/src/handlers/types.ts +102 -0
  155. package/src/index.ts +25 -0
  156. package/src/migrate.ts +122 -0
  157. package/src/mutations.ts +926 -0
  158. package/src/outbox.ts +397 -0
  159. package/src/plugins/incrementing-version.ts +133 -0
  160. package/src/plugins/index.ts +2 -0
  161. package/src/plugins/types.ts +63 -0
  162. package/src/proxy/connection.ts +191 -0
  163. package/src/proxy/dialect.ts +76 -0
  164. package/src/proxy/driver.ts +126 -0
  165. package/src/proxy/index.ts +10 -0
  166. package/src/proxy/mutations.ts +18 -0
  167. package/src/pull-engine.ts +518 -0
  168. package/src/push-engine.ts +201 -0
  169. package/src/query/FingerprintCollector.ts +29 -0
  170. package/src/query/QueryContext.ts +54 -0
  171. package/src/query/fingerprint.ts +109 -0
  172. package/src/query/index.ts +10 -0
  173. package/src/query/tracked-select.ts +139 -0
  174. package/src/schema.ts +94 -0
  175. package/src/sync-loop.ts +368 -0
  176. package/src/utils/id.ts +20 -0
@@ -0,0 +1,391 @@
1
+ /**
2
+ * @syncular/client - Sync pull engine
3
+ */
4
+ import { sql } from 'kysely';
5
+ // Simple JSON serialization cache to avoid repeated stringification
6
+ // of the same objects during pull operations
7
+ const jsonCache = new WeakMap();
8
+ const jsonCacheStats = { hits: 0, misses: 0 };
9
+ const SNAPSHOT_CHUNK_CONCURRENCY = 8;
10
+ function serializeJsonCached(obj) {
11
+ if (obj === null || typeof obj !== 'object') {
12
+ return JSON.stringify(obj);
13
+ }
14
+ const cached = jsonCache.get(obj);
15
+ if (cached !== undefined) {
16
+ jsonCacheStats.hits++;
17
+ return cached;
18
+ }
19
+ jsonCacheStats.misses++;
20
+ const serialized = JSON.stringify(obj);
21
+ // Only cache objects that are likely to be reused (not one-off empty objects)
22
+ if (Object.keys(obj).length > 0) {
23
+ jsonCache.set(obj, serialized);
24
+ }
25
+ return serialized;
26
+ }
27
+ function isGzipBytes(bytes) {
28
+ return bytes.length >= 2 && bytes[0] === 0x1f && bytes[1] === 0x8b;
29
+ }
30
+ async function maybeGunzip(bytes) {
31
+ if (!isGzipBytes(bytes))
32
+ return bytes;
33
+ // Prefer Web Streams decompression when available (browser/modern runtimes).
34
+ if (typeof DecompressionStream !== 'undefined') {
35
+ const stream = new ReadableStream({
36
+ start(controller) {
37
+ controller.enqueue(new Uint8Array(bytes));
38
+ controller.close();
39
+ },
40
+ });
41
+ const decompressed = stream.pipeThrough(new DecompressionStream('gzip'));
42
+ const reader = decompressed.getReader();
43
+ try {
44
+ const chunks = [];
45
+ let total = 0;
46
+ while (true) {
47
+ const { value, done } = await reader.read();
48
+ if (done)
49
+ break;
50
+ if (!value)
51
+ continue;
52
+ chunks.push(value);
53
+ total += value.length;
54
+ }
55
+ const out = new Uint8Array(total);
56
+ let offset = 0;
57
+ for (const chunk of chunks) {
58
+ out.set(chunk, offset);
59
+ offset += chunk.length;
60
+ }
61
+ return out;
62
+ }
63
+ finally {
64
+ reader.releaseLock();
65
+ }
66
+ }
67
+ // If the runtime didn't auto-decompress `Content-Encoding: gzip`, and doesn't
68
+ // support DecompressionStream, we can't safely decode the chunk.
69
+ throw new Error('Snapshot chunk appears gzip-compressed but gzip decompression is not available in this runtime');
70
+ }
71
+ function parseNdjsonRows(text) {
72
+ const rows = [];
73
+ for (const line of text.split('\n')) {
74
+ if (!line)
75
+ continue;
76
+ rows.push(JSON.parse(line));
77
+ }
78
+ return rows;
79
+ }
80
+ async function computeSha256Hex(bytes) {
81
+ // Use crypto.subtle if available (browsers, modern Node/Bun)
82
+ if (typeof crypto !== 'undefined' && crypto.subtle) {
83
+ // Create a fresh ArrayBuffer to satisfy crypto.subtle's type requirements
84
+ const buffer = new ArrayBuffer(bytes.length);
85
+ new Uint8Array(buffer).set(bytes);
86
+ const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
87
+ const hashArray = new Uint8Array(hashBuffer);
88
+ return Array.from(hashArray, (b) => b.toString(16).padStart(2, '0')).join('');
89
+ }
90
+ // Fallback for Node.js/Bun without crypto.subtle
91
+ if (typeof globalThis.require === 'function') {
92
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
93
+ const { createHash } = await import('node:crypto');
94
+ return createHash('sha256').update(Buffer.from(bytes)).digest('hex');
95
+ }
96
+ throw new Error('No crypto implementation available for SHA-256. ' +
97
+ 'Ensure crypto.subtle is available or running in Node.js/Bun.');
98
+ }
99
+ async function mapWithConcurrency(items, concurrency, mapper) {
100
+ if (items.length === 0)
101
+ return [];
102
+ const workerCount = Math.max(1, Math.min(concurrency, items.length));
103
+ const results = new Array(items.length);
104
+ let nextIndex = 0;
105
+ async function worker() {
106
+ while (nextIndex < items.length) {
107
+ const index = nextIndex;
108
+ nextIndex += 1;
109
+ const item = items[index];
110
+ if (item === undefined)
111
+ continue;
112
+ results[index] = await mapper(item, index);
113
+ }
114
+ }
115
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
116
+ return results;
117
+ }
118
+ async function materializeChunkedSnapshots(transport, response) {
119
+ const chunkCache = new Map();
120
+ const decoder = new TextDecoder();
121
+ const subscriptions = await Promise.all(response.subscriptions.map(async (sub) => {
122
+ if (!sub.bootstrap)
123
+ return sub;
124
+ if (!sub.snapshots || sub.snapshots.length === 0)
125
+ return sub;
126
+ const snapshots = await mapWithConcurrency(sub.snapshots, SNAPSHOT_CHUNK_CONCURRENCY, async (snapshot) => {
127
+ const chunks = snapshot.chunks ?? [];
128
+ if (chunks.length === 0) {
129
+ return snapshot;
130
+ }
131
+ const parsedRowsByChunk = await mapWithConcurrency(chunks, SNAPSHOT_CHUNK_CONCURRENCY, async (chunk) => {
132
+ const promise = chunkCache.get(chunk.id) ??
133
+ transport.fetchSnapshotChunk({ chunkId: chunk.id });
134
+ chunkCache.set(chunk.id, promise);
135
+ const raw = await promise;
136
+ const bytes = await maybeGunzip(raw);
137
+ // Verify chunk integrity using sha256 hash
138
+ if (chunk.sha256) {
139
+ const actualHash = await computeSha256Hex(bytes);
140
+ if (actualHash !== chunk.sha256) {
141
+ throw new Error(`Snapshot chunk integrity check failed: expected sha256 ${chunk.sha256}, got ${actualHash}`);
142
+ }
143
+ }
144
+ const text = decoder.decode(bytes);
145
+ return parseNdjsonRows(text);
146
+ });
147
+ const rows = [];
148
+ for (const parsedRows of parsedRowsByChunk) {
149
+ rows.push(...parsedRows);
150
+ }
151
+ return { ...snapshot, rows, chunks: undefined };
152
+ });
153
+ return { ...sub, snapshots };
154
+ }));
155
+ // Clear chunk cache after processing to prevent memory accumulation
156
+ chunkCache.clear();
157
+ return { ...response, subscriptions };
158
+ }
159
+ function parseBootstrapState(value) {
160
+ if (!value)
161
+ return null;
162
+ try {
163
+ // Handle both string (raw JSON) and object (already deserialized by SerializePlugin)
164
+ const parsed = typeof value === 'string'
165
+ ? JSON.parse(value)
166
+ : value;
167
+ if (!parsed || typeof parsed !== 'object')
168
+ return null;
169
+ if (typeof parsed.asOfCommitSeq !== 'number')
170
+ return null;
171
+ if (!Array.isArray(parsed.tables))
172
+ return null;
173
+ if (typeof parsed.tableIndex !== 'number')
174
+ return null;
175
+ if (parsed.rowCursor !== null && typeof parsed.rowCursor !== 'string')
176
+ return null;
177
+ return parsed;
178
+ }
179
+ catch {
180
+ return null;
181
+ }
182
+ }
183
+ /**
184
+ * Build a pull request from subscription state. Exported for use
185
+ * by the combined sync path in sync-loop.ts.
186
+ */
187
+ export async function buildPullRequest(db, options) {
188
+ const stateId = options.stateId ?? 'default';
189
+ const existingResult = await sql `
190
+ select
191
+ ${sql.ref('state_id')},
192
+ ${sql.ref('subscription_id')},
193
+ ${sql.ref('shape')},
194
+ ${sql.ref('scopes_json')},
195
+ ${sql.ref('params_json')},
196
+ ${sql.ref('cursor')},
197
+ ${sql.ref('bootstrap_state_json')},
198
+ ${sql.ref('status')},
199
+ ${sql.ref('created_at')},
200
+ ${sql.ref('updated_at')}
201
+ from ${sql.table('sync_subscription_state')}
202
+ where ${sql.ref('state_id')} = ${sql.val(stateId)}
203
+ `.execute(db);
204
+ const existing = existingResult.rows;
205
+ const existingById = new Map();
206
+ for (const row of existing)
207
+ existingById.set(row.subscription_id, row);
208
+ const request = {
209
+ clientId: options.clientId,
210
+ limitCommits: options.limitCommits ?? 50,
211
+ limitSnapshotRows: options.limitSnapshotRows ?? 1000,
212
+ maxSnapshotPages: options.maxSnapshotPages,
213
+ dedupeRows: options.dedupeRows,
214
+ subscriptions: (options.subscriptions ?? []).map((sub) => ({
215
+ ...sub,
216
+ cursor: Math.max(-1, existingById.get(sub.id)?.cursor ?? -1),
217
+ bootstrapState: parseBootstrapState(existingById.get(sub.id)?.bootstrap_state_json),
218
+ })),
219
+ };
220
+ return { request, existing, existingById, stateId };
221
+ }
222
+ /**
223
+ * Apply a pull response (run plugins + write to local DB).
224
+ * Exported for use by the combined sync path in sync-loop.ts.
225
+ */
226
+ export async function applyPullResponse(db, transport, shapes, options, pullState, rawResponse) {
227
+ const { request, existing, existingById, stateId } = pullState;
228
+ const hydrated = await materializeChunkedSnapshots(transport, rawResponse);
229
+ const ctx = {
230
+ actorId: options.actorId ?? 'unknown',
231
+ clientId: options.clientId,
232
+ };
233
+ const plugins = options.plugins ?? [];
234
+ let responseToApply = hydrated;
235
+ for (const plugin of plugins) {
236
+ if (!plugin.afterPull)
237
+ continue;
238
+ responseToApply = await plugin.afterPull(ctx, {
239
+ request,
240
+ response: responseToApply,
241
+ });
242
+ }
243
+ await db.transaction().execute(async (trx) => {
244
+ const desiredIds = new Set((options.subscriptions ?? []).map((s) => s.id));
245
+ // Remove local data for subscriptions that are no longer desired.
246
+ for (const row of existing) {
247
+ if (desiredIds.has(row.subscription_id))
248
+ continue;
249
+ // Clear data for this shape matching the subscription's scopes
250
+ if (row.shape) {
251
+ try {
252
+ const scopes = row.scopes_json
253
+ ? typeof row.scopes_json === 'string'
254
+ ? JSON.parse(row.scopes_json)
255
+ : row.scopes_json
256
+ : {};
257
+ await shapes.getOrThrow(row.shape).clearAll({ trx, scopes });
258
+ }
259
+ catch {
260
+ // ignore missing shape handler
261
+ }
262
+ }
263
+ await sql `
264
+ delete from ${sql.table('sync_subscription_state')}
265
+ where ${sql.ref('state_id')} = ${sql.val(stateId)}
266
+ and ${sql.ref('subscription_id')} = ${sql.val(row.subscription_id)}
267
+ `.execute(trx);
268
+ }
269
+ const subsById = new Map();
270
+ for (const s of options.subscriptions ?? [])
271
+ subsById.set(s.id, s);
272
+ for (const sub of responseToApply.subscriptions) {
273
+ const def = subsById.get(sub.id);
274
+ const prev = existingById.get(sub.id);
275
+ // Revoked: clear data and drop the subscription row.
276
+ if (sub.status === 'revoked') {
277
+ if (prev?.shape) {
278
+ try {
279
+ const scopes = prev.scopes_json
280
+ ? typeof prev.scopes_json === 'string'
281
+ ? JSON.parse(prev.scopes_json)
282
+ : prev.scopes_json
283
+ : {};
284
+ await shapes.getOrThrow(prev.shape).clearAll({ trx, scopes });
285
+ }
286
+ catch {
287
+ // ignore missing handler
288
+ }
289
+ }
290
+ await sql `
291
+ delete from ${sql.table('sync_subscription_state')}
292
+ where ${sql.ref('state_id')} = ${sql.val(stateId)}
293
+ and ${sql.ref('subscription_id')} = ${sql.val(sub.id)}
294
+ `.execute(trx);
295
+ continue;
296
+ }
297
+ // Apply snapshots (bootstrap mode)
298
+ if (sub.bootstrap) {
299
+ for (const snapshot of sub.snapshots ?? []) {
300
+ const handler = shapes.getOrThrow(snapshot.table);
301
+ // Call onSnapshotStart hook when starting a new snapshot
302
+ if (snapshot.isFirstPage && handler.onSnapshotStart) {
303
+ await handler.onSnapshotStart({
304
+ trx,
305
+ table: snapshot.table,
306
+ scopes: sub.scopes,
307
+ });
308
+ }
309
+ await handler.applySnapshot({ trx }, snapshot);
310
+ // Call onSnapshotEnd hook when snapshot is complete
311
+ if (snapshot.isLastPage && handler.onSnapshotEnd) {
312
+ await handler.onSnapshotEnd({
313
+ trx,
314
+ table: snapshot.table,
315
+ scopes: sub.scopes,
316
+ });
317
+ }
318
+ }
319
+ }
320
+ else {
321
+ // Apply incremental changes
322
+ for (const commit of sub.commits) {
323
+ for (const change of commit.changes) {
324
+ const handler = shapes.getOrThrow(change.table);
325
+ await handler.applyChange({ trx }, change);
326
+ }
327
+ }
328
+ }
329
+ // Persist subscription cursor + metadata.
330
+ // Use cached JSON serialization to avoid repeated stringification
331
+ const now = Date.now();
332
+ const paramsJson = serializeJsonCached(def?.params ?? {});
333
+ const scopesJson = serializeJsonCached(def?.scopes ?? {});
334
+ const bootstrapStateJson = sub.bootstrap
335
+ ? sub.bootstrapState
336
+ ? serializeJsonCached(sub.bootstrapState)
337
+ : null
338
+ : null;
339
+ const shape = def?.shape ?? 'unknown';
340
+ await sql `
341
+ insert into ${sql.table('sync_subscription_state')} (
342
+ ${sql.join([
343
+ sql.ref('state_id'),
344
+ sql.ref('subscription_id'),
345
+ sql.ref('shape'),
346
+ sql.ref('scopes_json'),
347
+ sql.ref('params_json'),
348
+ sql.ref('cursor'),
349
+ sql.ref('bootstrap_state_json'),
350
+ sql.ref('status'),
351
+ sql.ref('created_at'),
352
+ sql.ref('updated_at'),
353
+ ])}
354
+ ) values (
355
+ ${sql.join([
356
+ sql.val(stateId),
357
+ sql.val(sub.id),
358
+ sql.val(shape),
359
+ sql.val(scopesJson),
360
+ sql.val(paramsJson),
361
+ sql.val(sub.nextCursor),
362
+ sql.val(bootstrapStateJson),
363
+ sql.val('active'),
364
+ sql.val(now),
365
+ sql.val(now),
366
+ ])}
367
+ )
368
+ on conflict (${sql.join([sql.ref('state_id'), sql.ref('subscription_id')])})
369
+ do update set
370
+ ${sql.ref('shape')} = ${sql.val(shape)},
371
+ ${sql.ref('scopes_json')} = ${sql.val(scopesJson)},
372
+ ${sql.ref('params_json')} = ${sql.val(paramsJson)},
373
+ ${sql.ref('cursor')} = ${sql.val(sub.nextCursor)},
374
+ ${sql.ref('bootstrap_state_json')} = ${sql.val(bootstrapStateJson)},
375
+ ${sql.ref('status')} = ${sql.val('active')},
376
+ ${sql.ref('updated_at')} = ${sql.val(now)}
377
+ `.execute(trx);
378
+ }
379
+ });
380
+ return responseToApply;
381
+ }
382
+ export async function syncPullOnce(db, transport, shapes, options) {
383
+ const pullState = await buildPullRequest(db, options);
384
+ const { clientId, ...pullBody } = pullState.request;
385
+ const combined = await transport.sync({ clientId, pull: pullBody });
386
+ if (!combined.pull) {
387
+ return { ok: true, subscriptions: [] };
388
+ }
389
+ return applyPullResponse(db, transport, shapes, options, pullState, combined.pull);
390
+ }
391
+ //# sourceMappingURL=pull-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull-engine.js","sourceRoot":"","sources":["../src/pull-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @syncular/client - Sync push engine (commit-based)
3
+ */
4
+ import type { SyncPushResponse, SyncTransport } from '@syncular/core';
5
+ import type { Kysely } from 'kysely';
6
+ import type { SyncClientPlugin } from './plugins/types';
7
+ import type { SyncClientDb } from './schema';
8
+ export interface SyncPushOnceOptions {
9
+ clientId: string;
10
+ actorId?: string;
11
+ plugins?: SyncClientPlugin[];
12
+ }
13
+ export interface SyncPushOnceResult {
14
+ pushed: boolean;
15
+ response?: SyncPushResponse;
16
+ }
17
+ export declare function syncPushOnce<DB extends SyncClientDb>(db: Kysely<DB>, transport: SyncTransport, options: SyncPushOnceOptions): Promise<SyncPushOnceResult>;
18
+ //# sourceMappingURL=push-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-engine.d.ts","sourceRoot":"","sources":["../src/push-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQrC,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAiBD,wBAAsB,YAAY,CAAC,EAAE,SAAS,YAAY,EACxD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EACd,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAmJ7B"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @syncular/client - Sync push engine (commit-based)
3
+ */
4
+ import { upsertConflictsForRejectedCommit } from './conflicts';
5
+ import { getNextSendableOutboxCommit, markOutboxCommitAcked, markOutboxCommitFailed, markOutboxCommitPending, } from './outbox';
6
+ function hasPushViaWs(transport) {
7
+ return 'pushViaWs' in transport && typeof transport.pushViaWs === 'function';
8
+ }
9
+ function clonePushRequest(request) {
10
+ if (typeof structuredClone === 'function')
11
+ return structuredClone(request);
12
+ return JSON.parse(JSON.stringify(request));
13
+ }
14
+ export async function syncPushOnce(db, transport, options) {
15
+ // getNextSendableOutboxCommit now atomically claims the commit
16
+ // (marks it as 'sending' and returns it in one operation)
17
+ const next = await getNextSendableOutboxCommit(db);
18
+ if (!next)
19
+ return { pushed: false };
20
+ const request = {
21
+ clientId: options.clientId,
22
+ clientCommitId: next.client_commit_id,
23
+ operations: next.operations,
24
+ schemaVersion: next.schema_version,
25
+ };
26
+ const ctx = {
27
+ actorId: options.actorId ?? 'unknown',
28
+ clientId: options.clientId,
29
+ };
30
+ const plugins = options.plugins ?? [];
31
+ let requestToSend = request;
32
+ if (plugins.length > 0) {
33
+ try {
34
+ requestToSend = clonePushRequest(request);
35
+ for (const plugin of plugins) {
36
+ if (!plugin.beforePush)
37
+ continue;
38
+ requestToSend = await plugin.beforePush(ctx, requestToSend);
39
+ }
40
+ }
41
+ catch (err) {
42
+ const message = err instanceof Error ? err.message : 'Unknown error';
43
+ await markOutboxCommitPending(db, { id: next.id, error: message });
44
+ throw err;
45
+ }
46
+ }
47
+ let res;
48
+ try {
49
+ // Try WS push first if the transport supports it
50
+ let wsResponse = null;
51
+ if (hasPushViaWs(transport)) {
52
+ wsResponse = await transport.pushViaWs(requestToSend);
53
+ }
54
+ if (wsResponse) {
55
+ res = wsResponse;
56
+ }
57
+ else {
58
+ // Fall back to HTTP
59
+ const combined = await transport.sync({
60
+ clientId: requestToSend.clientId,
61
+ push: {
62
+ clientCommitId: requestToSend.clientCommitId,
63
+ operations: requestToSend.operations,
64
+ schemaVersion: requestToSend.schemaVersion,
65
+ },
66
+ });
67
+ if (!combined.push) {
68
+ throw new Error('Server returned no push response');
69
+ }
70
+ res = combined.push;
71
+ }
72
+ }
73
+ catch (err) {
74
+ const message = err instanceof Error ? err.message : 'Unknown error';
75
+ // Treat transport exceptions as retryable. The sync loop already applies backoff,
76
+ // and failed commits are reserved for terminal server rejections (e.g. conflicts).
77
+ await markOutboxCommitPending(db, { id: next.id, error: message });
78
+ throw err;
79
+ }
80
+ let responseToUse = res;
81
+ if (plugins.length > 0) {
82
+ try {
83
+ for (const plugin of plugins) {
84
+ if (!plugin.afterPush)
85
+ continue;
86
+ responseToUse = await plugin.afterPush(ctx, {
87
+ request: requestToSend,
88
+ response: responseToUse,
89
+ });
90
+ }
91
+ }
92
+ catch (err) {
93
+ // The server already received and processed this commit. Persist the raw response
94
+ // so we don't end up retrying a commit that was already applied.
95
+ const responseJson = JSON.stringify(res);
96
+ if (res.status === 'applied' || res.status === 'cached') {
97
+ await markOutboxCommitAcked(db, {
98
+ id: next.id,
99
+ commitSeq: res.commitSeq ?? null,
100
+ responseJson,
101
+ });
102
+ }
103
+ else {
104
+ await upsertConflictsForRejectedCommit(db, {
105
+ outboxCommitId: next.id,
106
+ clientCommitId: next.client_commit_id,
107
+ response: res,
108
+ });
109
+ await markOutboxCommitFailed(db, {
110
+ id: next.id,
111
+ error: 'REJECTED',
112
+ responseJson,
113
+ });
114
+ }
115
+ throw err;
116
+ }
117
+ }
118
+ const responseJson = JSON.stringify(responseToUse);
119
+ if (responseToUse.status === 'applied' || responseToUse.status === 'cached') {
120
+ await markOutboxCommitAcked(db, {
121
+ id: next.id,
122
+ commitSeq: responseToUse.commitSeq ?? null,
123
+ responseJson,
124
+ });
125
+ return { pushed: true, response: responseToUse };
126
+ }
127
+ // Check if all errors are retriable - if so, keep pending for retry
128
+ const errorResults = responseToUse.results.filter((r) => r.status === 'error');
129
+ const allRetriable = errorResults.length > 0 && errorResults.every((r) => r.retriable === true);
130
+ if (allRetriable) {
131
+ // All errors are retriable - keep commit pending for retry
132
+ const errorMessages = errorResults
133
+ .map((r) => r.error ?? 'Unknown error')
134
+ .join('; ');
135
+ await markOutboxCommitPending(db, {
136
+ id: next.id,
137
+ error: `Retriable: ${errorMessages}`,
138
+ responseJson,
139
+ });
140
+ return { pushed: true, response: responseToUse };
141
+ }
142
+ // Terminal rejection - mark as failed and record conflicts
143
+ await upsertConflictsForRejectedCommit(db, {
144
+ outboxCommitId: next.id,
145
+ clientCommitId: next.client_commit_id,
146
+ response: responseToUse,
147
+ });
148
+ await markOutboxCommitFailed(db, {
149
+ id: next.id,
150
+ error: 'REJECTED',
151
+ responseJson,
152
+ });
153
+ return { pushed: true, response: responseToUse };
154
+ }
155
+ //# sourceMappingURL=push-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-engine.js","sourceRoot":"","sources":["../src/push-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @syncular/client - Fingerprint Collector
3
+ *
4
+ * Accumulates fingerprint data from multiple queries.
5
+ */
6
+ /**
7
+ * Fingerprint collector accumulates fingerprint data from multiple queries
8
+ */
9
+ export declare class FingerprintCollector {
10
+ private fingerprints;
11
+ add(fingerprint: string): void;
12
+ /**
13
+ * Get combined fingerprint from all collected fingerprints
14
+ */
15
+ getCombined(): string;
16
+ clear(): void;
17
+ }
18
+ //# sourceMappingURL=FingerprintCollector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FingerprintCollector.d.ts","sourceRoot":"","sources":["../../src/query/FingerprintCollector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,YAAY,CAAgB;IAEpC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAE7B;IAED;;OAEG;IACH,WAAW,IAAI,MAAM,CAIpB;IAED,KAAK,IAAI,IAAI,CAEZ;CACF"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @syncular/client - Fingerprint Collector
3
+ *
4
+ * Accumulates fingerprint data from multiple queries.
5
+ */
6
+ /**
7
+ * Fingerprint collector accumulates fingerprint data from multiple queries
8
+ */
9
+ export class FingerprintCollector {
10
+ fingerprints = [];
11
+ add(fingerprint) {
12
+ this.fingerprints.push(fingerprint);
13
+ }
14
+ /**
15
+ * Get combined fingerprint from all collected fingerprints
16
+ */
17
+ getCombined() {
18
+ if (this.fingerprints.length === 0)
19
+ return '';
20
+ if (this.fingerprints.length === 1)
21
+ return this.fingerprints[0] ?? '';
22
+ return this.fingerprints.join('|');
23
+ }
24
+ clear() {
25
+ this.fingerprints = [];
26
+ }
27
+ }
28
+ //# sourceMappingURL=FingerprintCollector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FingerprintCollector.js","sourceRoot":"","sources":["../../src/query/FingerprintCollector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,OAAO,oBAAoB;IACvB,YAAY,GAAa,EAAE,CAAC;IAEpC,GAAG,CAAC,WAAmB,EAAQ;QAC7B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAAA,CACrC;IAED;;OAEG;IACH,WAAW,GAAW;QACpB,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9C,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAAA,CACpC;IAED,KAAK,GAAS;QACZ,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;IAAA,CACxB;CACF"}