@powersync/common 1.45.0 → 1.46.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.
Files changed (38) hide show
  1. package/dist/bundle.cjs +412 -2067
  2. package/dist/bundle.cjs.map +1 -1
  3. package/dist/bundle.mjs +410 -2068
  4. package/dist/bundle.mjs.map +1 -1
  5. package/dist/bundle.node.cjs +237 -63
  6. package/dist/bundle.node.cjs.map +1 -1
  7. package/dist/bundle.node.mjs +235 -64
  8. package/dist/bundle.node.mjs.map +1 -1
  9. package/dist/index.d.cts +94 -15
  10. package/lib/client/AbstractPowerSyncDatabase.d.ts +9 -2
  11. package/lib/client/AbstractPowerSyncDatabase.js +18 -5
  12. package/lib/client/AbstractPowerSyncDatabase.js.map +1 -1
  13. package/lib/client/sync/stream/AbstractRemote.js +41 -32
  14. package/lib/client/sync/stream/AbstractRemote.js.map +1 -1
  15. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +7 -12
  16. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +10 -12
  17. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -1
  18. package/lib/client/triggers/MemoryTriggerClaimManager.d.ts +6 -0
  19. package/lib/client/triggers/MemoryTriggerClaimManager.js +21 -0
  20. package/lib/client/triggers/MemoryTriggerClaimManager.js.map +1 -0
  21. package/lib/client/triggers/TriggerManager.d.ts +37 -0
  22. package/lib/client/triggers/TriggerManagerImpl.d.ts +24 -3
  23. package/lib/client/triggers/TriggerManagerImpl.js +133 -11
  24. package/lib/client/triggers/TriggerManagerImpl.js.map +1 -1
  25. package/lib/index.d.ts +3 -0
  26. package/lib/index.js +3 -0
  27. package/lib/index.js.map +1 -1
  28. package/lib/utils/DataStream.js +11 -2
  29. package/lib/utils/DataStream.js.map +1 -1
  30. package/package.json +4 -3
  31. package/src/client/AbstractPowerSyncDatabase.ts +21 -6
  32. package/src/client/sync/stream/AbstractRemote.ts +47 -35
  33. package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +11 -14
  34. package/src/client/triggers/MemoryTriggerClaimManager.ts +25 -0
  35. package/src/client/triggers/TriggerManager.ts +50 -6
  36. package/src/client/triggers/TriggerManagerImpl.ts +177 -13
  37. package/src/index.ts +3 -0
  38. package/src/utils/DataStream.ts +13 -2
@@ -67,6 +67,16 @@ export class DataStream extends BaseObserver {
67
67
  * @returns a Data payload or Null if the stream closed.
68
68
  */
69
69
  async read() {
70
+ if (this.closed) {
71
+ return null;
72
+ }
73
+ // Wait for any pending processing to complete first.
74
+ // This ensures we register our listener before calling processQueue(),
75
+ // avoiding a race where processQueue() sees no reader and returns early.
76
+ if (this.processingPromise) {
77
+ await this.processingPromise;
78
+ }
79
+ // Re-check after await - stream may have closed while we were waiting
70
80
  if (this.closed) {
71
81
  return null;
72
82
  }
@@ -106,7 +116,7 @@ export class DataStream extends BaseObserver {
106
116
  }
107
117
  const promise = (this.processingPromise = this._processQueue());
108
118
  promise.finally(() => {
109
- return (this.processingPromise = null);
119
+ this.processingPromise = null;
110
120
  });
111
121
  return promise;
112
122
  }
@@ -138,7 +148,6 @@ export class DataStream extends BaseObserver {
138
148
  this.notifyDataAdded = null;
139
149
  }
140
150
  if (this.dataQueue.length > 0) {
141
- // Next tick
142
151
  setTimeout(() => this.processQueue());
143
152
  }
144
153
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataStream.js","sourceRoot":"","sources":["../../src/utils/DataStream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DataStream.js","sourceRoot":"","sources":["../../src/utils/DataStream.ts"],"names":[],"mappings":"AAAA,OAAO,MAAmB,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAgB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA0B/D,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF;;;;GAIG;AACH,MAAM,OAAO,UAAyC,SAAQ,YAA4C;IAYlF;IAXtB,SAAS,CAAe;IAEd,QAAQ,CAAU;IAElB,iBAAiB,CAAuB;IACxC,eAAe,CAAsB;IAErC,MAAM,CAAU;IAEhB,OAAO,CAAmC;IAEpD,YAAsB,OAAmD;QACvE,KAAK,EAAE,CAAC;QADY,YAAO,GAAP,OAAO,CAA4C;QAEvE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAW,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE1D,IAAI,OAAO,EAAE,YAAY,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC;gBAC9B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;oBACZ,CAAC,EAAE,EAAE,CAAC;oBACN,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,CAAC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,IAAI,uBAAuB,CAAC,SAAS,CAAC;IACpF,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,IAAI,uBAAuB,CAAC,QAAQ,CAAC;IAClF,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,IAAI,CAAC,iBAAiB,CAAC;QAC7B,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3C,gCAAgC;QAChC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,IAAgB;QAC1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QAEzB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,qDAAqD;QACrD,uEAAuE;QACvE,yEAAyE;QACzE,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,iBAAiB,CAAC;QAC/B,CAAC;QAED,sEAAsE;QACtE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC;gBAC9B,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBACnB,OAAO,CAAC,IAAI,CAAC,CAAC;oBACd,sBAAsB;oBACtB,CAAC,EAAE,EAAE,CAAC;gBACR,CAAC;gBACD,MAAM,EAAE,GAAG,EAAE;oBACX,OAAO,CAAC,IAAI,CAAC,CAAC;oBACd,CAAC,EAAE,EAAE,CAAC;gBACR,CAAC;gBACD,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;oBACZ,MAAM,CAAC,EAAE,CAAC,CAAC;oBACX,CAAC,EAAE,EAAE,CAAC;gBACR,CAAC;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,QAAwC;QAC9C,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/C,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,gBAAgB,CAAC;YAC3B,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;IACL,CAAC;IAES,YAAY;QACpB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YACnB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,aAAa;QACrB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;IAES,KAAK,CAAC,aAAa;QAC3B;;;;WAIG;QACH,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAChD,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAG,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/C,MAAM,SAAS,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAC9C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;YACjC,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;YACvF,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAES,KAAK,CAAC,mBAAmB,CAAC,EAAiE;QACnG,iGAAiG;QACjG,yCAAyC;QACzC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,KAAK,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;YACd,CAAC;YAAC,OAAO,EAAE,EAAE,CAAC;gBACZ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACtB,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powersync/common",
3
- "version": "1.45.0",
3
+ "version": "1.46.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -56,10 +56,11 @@
56
56
  "@rollup/plugin-inject": "^5.0.5",
57
57
  "@rollup/plugin-json": "^6.1.0",
58
58
  "@rollup/plugin-node-resolve": "^16.0.3",
59
- "@types/node": "^20.5.9",
60
- "@types/uuid": "^9.0.1",
59
+ "@types/node": "^24.0.0",
60
+ "@types/uuid": "^9.0.6",
61
61
  "buffer": "^6.0.3",
62
62
  "rollup": "^4.52.5",
63
+ "rollup-plugin-dts": "^6.2.1",
63
64
  "cross-fetch": "^4.1.0",
64
65
  "js-logger": "^1.6.1",
65
66
  "rsocket-core": "1.0.0-alpha.3",
@@ -40,7 +40,8 @@ import {
40
40
  } from './sync/stream/AbstractStreamingSyncImplementation.js';
41
41
  import { CoreSyncStatus, coreStatusToJs } from './sync/stream/core-instruction.js';
42
42
  import { SyncStream } from './sync/sync-streams.js';
43
- import { TriggerManager } from './triggers/TriggerManager.js';
43
+ import { MEMORY_TRIGGER_CLAIM_MANAGER } from './triggers/MemoryTriggerClaimManager.js';
44
+ import { TriggerManager, TriggerManagerConfig } from './triggers/TriggerManager.js';
44
45
  import { TriggerManagerImpl } from './triggers/TriggerManagerImpl.js';
45
46
  import { DEFAULT_WATCH_THROTTLE_MS, WatchCompatibleQuery } from './watched/WatchedQuery.js';
46
47
  import { OnChangeQueryProcessor } from './watched/processors/OnChangeQueryProcessor.js';
@@ -222,6 +223,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
222
223
  * Allows creating SQLite triggers which can be used to track various operations on SQLite tables.
223
224
  */
224
225
  readonly triggers: TriggerManager;
226
+ protected triggersImpl: TriggerManagerImpl;
225
227
 
226
228
  logger: ILogger;
227
229
 
@@ -296,9 +298,10 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
296
298
 
297
299
  this._isReadyPromise = this.initialize();
298
300
 
299
- this.triggers = new TriggerManagerImpl({
301
+ this.triggers = this.triggersImpl = new TriggerManagerImpl({
300
302
  db: this,
301
- schema: this.schema
303
+ schema: this.schema,
304
+ ...this.generateTriggerManagerConfig()
302
305
  });
303
306
  }
304
307
 
@@ -334,6 +337,16 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
334
337
  */
335
338
  protected abstract openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;
336
339
 
340
+ /**
341
+ * Generates a base configuration for {@link TriggerManagerImpl}.
342
+ * Implementations should override this if necessary.
343
+ */
344
+ protected generateTriggerManagerConfig(): TriggerManagerConfig {
345
+ return {
346
+ claimManager: MEMORY_TRIGGER_CLAIM_MANAGER
347
+ };
348
+ }
349
+
337
350
  protected abstract generateSyncStreamImplementation(
338
351
  connector: PowerSyncBackendConnector,
339
352
  options: CreateSyncImplementationOptions & RequiredAdditionalConnectionOptions
@@ -416,15 +429,16 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
416
429
  protected async initialize() {
417
430
  await this._initialize();
418
431
  await this.bucketStorageAdapter.init();
419
- await this._loadVersion();
432
+ await this.loadVersion();
420
433
  await this.updateSchema(this.options.schema);
421
434
  await this.resolveOfflineSyncStatus();
422
435
  await this.database.execute('PRAGMA RECURSIVE_TRIGGERS=TRUE');
436
+ await this.triggersImpl.cleanupResources();
423
437
  this.ready = true;
424
438
  this.iterateListeners((cb) => cb.initialized?.());
425
439
  }
426
440
 
427
- private async _loadVersion() {
441
+ protected async loadVersion() {
428
442
  try {
429
443
  const { version } = await this.database.get<{ version: string }>('SELECT powersync_rs_version() as version');
430
444
  this.sdkVersion = version;
@@ -560,7 +574,6 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
560
574
 
561
575
  const { clearLocal } = options;
562
576
 
563
- // TODO DB name, verify this is necessary with extension
564
577
  await this.database.writeTransaction(async (tx) => {
565
578
  await tx.execute('SELECT powersync_clear(?)', [clearLocal ? 1 : 0]);
566
579
  });
@@ -597,6 +610,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
597
610
  return;
598
611
  }
599
612
 
613
+ this.triggersImpl.dispose();
614
+
600
615
  await this.iterateAsyncListeners(async (cb) => cb.closing?.());
601
616
 
602
617
  const { disconnect } = options;
@@ -573,7 +573,11 @@ export abstract class AbstractRemote {
573
573
 
574
574
  const stream = new DataStream<T, string>({
575
575
  logger: this.logger,
576
- mapLine: mapLine
576
+ mapLine: mapLine,
577
+ pressure: {
578
+ highWaterMark: 20,
579
+ lowWaterMark: 10
580
+ }
577
581
  });
578
582
 
579
583
  abortSignal?.addEventListener('abort', () => {
@@ -585,46 +589,54 @@ export abstract class AbstractRemote {
585
589
  let buffer = '';
586
590
 
587
591
 
592
+ const consumeStream = async () => {
593
+ while (!stream.closed && !abortSignal?.aborted && !readerReleased) {
594
+ const { done, value } = await reader.read();
595
+ if (done) {
596
+ const remaining = buffer.trim();
597
+ if (remaining.length != 0) {
598
+ stream.enqueueData(remaining);
599
+ }
588
600
 
589
- const l = stream.registerListener({
590
- lowWater: async () => {
591
- if (stream.closed || abortSignal?.aborted || readerReleased) {
592
- return
593
- }
594
- try {
595
- let didCompleteLine = false;
596
- while (!didCompleteLine) {
597
- const { done, value } = await reader.read();
598
- if (done) {
599
- const remaining = buffer.trim();
600
- if (remaining.length != 0) {
601
- stream.enqueueData(remaining);
602
- }
601
+ stream.close();
602
+ await closeReader();
603
+ return;
604
+ }
603
605
 
604
- stream.close();
605
- await closeReader();
606
- return;
607
- }
606
+ const data = decoder.decode(value, { stream: true });
607
+ buffer += data;
608
608
 
609
- const data = decoder.decode(value, { stream: true });
610
- buffer += data;
609
+ const lines = buffer.split('\n');
610
+ for (var i = 0; i < lines.length - 1; i++) {
611
+ var l = lines[i].trim();
612
+ if (l.length > 0) {
613
+ stream.enqueueData(l);
614
+ }
615
+ }
611
616
 
612
- const lines = buffer.split('\n');
613
- for (var i = 0; i < lines.length - 1; i++) {
614
- var l = lines[i].trim();
615
- if (l.length > 0) {
616
- stream.enqueueData(l);
617
- didCompleteLine = true;
617
+ buffer = lines[lines.length - 1];
618
+
619
+ // Implement backpressure by waiting for the low water mark to be reached
620
+ if (stream.dataQueue.length > stream.highWatermark) {
621
+ await new Promise<void>((resolve) => {
622
+ const dispose = stream.registerListener({
623
+ lowWater: async () => {
624
+ resolve();
625
+ dispose();
626
+ },
627
+ closed: () => {
628
+ resolve();
629
+ dispose();
618
630
  }
619
- }
620
-
621
- buffer = lines[lines.length - 1];
622
- }
623
- } catch (ex) {
624
- stream.close();
625
- throw ex;
631
+ })
632
+ })
626
633
  }
627
- },
634
+ }
635
+ }
636
+
637
+ consumeStream().catch(ex => this.logger.error('Error consuming stream', ex));
638
+
639
+ const l = stream.registerListener({
628
640
  closed: () => {
629
641
  closeReader();
630
642
  l?.();
@@ -47,18 +47,17 @@ export enum SyncClientImplementation {
47
47
  *
48
48
  * This is the default option.
49
49
  *
50
- * @deprecated Don't use {@link SyncClientImplementation.JAVASCRIPT} directly. Instead, use
51
- * {@link DEFAULT_SYNC_CLIENT_IMPLEMENTATION} or omit the option. The explicit choice to use
52
- * the JavaScript-based sync implementation will be removed from a future version of the SDK.
50
+ * @deprecated We recommend the {@link RUST} client implementation for all apps. If you have issues with
51
+ * the Rust client, please file an issue or reach out to us. The JavaScript client will be removed in a future
52
+ * version of the PowerSync SDK.
53
53
  */
54
54
  JAVASCRIPT = 'js',
55
55
  /**
56
56
  * This implementation offloads the sync line decoding and handling into the PowerSync
57
57
  * core extension.
58
58
  *
59
- * @experimental
60
- * While this implementation is more performant than {@link SyncClientImplementation.JAVASCRIPT},
61
- * it has seen less real-world testing and is marked as __experimental__ at the moment.
59
+ * This option is more performant than the {@link JAVASCRIPT} client, enabled by default and the
60
+ * recommended client implementation for all apps.
62
61
  *
63
62
  * ## Compatibility warning
64
63
  *
@@ -77,13 +76,9 @@ export enum SyncClientImplementation {
77
76
  }
78
77
 
79
78
  /**
80
- * The default {@link SyncClientImplementation} to use.
81
- *
82
- * Please use this field instead of {@link SyncClientImplementation.JAVASCRIPT} directly. A future version
83
- * of the PowerSync SDK will enable {@link SyncClientImplementation.RUST} by default and remove the JavaScript
84
- * option.
79
+ * The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}.
85
80
  */
86
- export const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.JAVASCRIPT;
81
+ export const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.RUST;
87
82
 
88
83
  /**
89
84
  * Abstract Lock to be implemented by various JS environments
@@ -194,8 +189,7 @@ export interface RequiredAdditionalConnectionOptions extends Required<Additional
194
189
  }
195
190
 
196
191
  export interface StreamingSyncImplementation
197
- extends BaseObserverInterface<StreamingSyncImplementationListener>,
198
- Disposable {
192
+ extends BaseObserverInterface<StreamingSyncImplementationListener>, Disposable {
199
193
  /**
200
194
  * Connects to the sync service
201
195
  */
@@ -693,6 +687,9 @@ The next upload iteration will be delayed.`);
693
687
  if (rawTables != null && rawTables.length) {
694
688
  this.logger.warn('Raw tables require the Rust-based sync client. The JS client will ignore them.');
695
689
  }
690
+ if (this.activeStreams.length) {
691
+ this.logger.error('Sync streams require `clientImplementation: SyncClientImplementation.RUST` when connecting.');
692
+ }
696
693
 
697
694
  this.logger.debug('Streaming sync iteration started');
698
695
  this.options.adapter.startSession();
@@ -0,0 +1,25 @@
1
+ import { TriggerClaimManager } from './TriggerManager.js';
2
+
3
+ const CLAIM_STORE = new Map<string, () => Promise<void>>();
4
+
5
+ /**
6
+ * @internal
7
+ * @experimental
8
+ */
9
+ export const MEMORY_TRIGGER_CLAIM_MANAGER: TriggerClaimManager = {
10
+ async obtainClaim(identifier: string): Promise<() => Promise<void>> {
11
+ if (CLAIM_STORE.has(identifier)) {
12
+ throw new Error(`A claim is already present for ${identifier}`);
13
+ }
14
+ const release = async () => {
15
+ CLAIM_STORE.delete(identifier);
16
+ };
17
+ CLAIM_STORE.set(identifier, release);
18
+
19
+ return release;
20
+ },
21
+
22
+ async checkClaim(identifier: string): Promise<boolean> {
23
+ return CLAIM_STORE.has(identifier);
24
+ }
25
+ };
@@ -47,8 +47,9 @@ export interface BaseTriggerDiffRecord<TOperationId extends string | number = nu
47
47
  * This record contains the new value and optionally the previous value.
48
48
  * Values are stored as JSON strings.
49
49
  */
50
- export interface TriggerDiffUpdateRecord<TOperationId extends string | number = number>
51
- extends BaseTriggerDiffRecord<TOperationId> {
50
+ export interface TriggerDiffUpdateRecord<
51
+ TOperationId extends string | number = number
52
+ > extends BaseTriggerDiffRecord<TOperationId> {
52
53
  operation: DiffTriggerOperation.UPDATE;
53
54
  /**
54
55
  * The updated state of the row in JSON string format.
@@ -65,8 +66,9 @@ export interface TriggerDiffUpdateRecord<TOperationId extends string | number =
65
66
  * Represents a diff record for a SQLite INSERT operation.
66
67
  * This record contains the new value represented as a JSON string.
67
68
  */
68
- export interface TriggerDiffInsertRecord<TOperationId extends string | number = number>
69
- extends BaseTriggerDiffRecord<TOperationId> {
69
+ export interface TriggerDiffInsertRecord<
70
+ TOperationId extends string | number = number
71
+ > extends BaseTriggerDiffRecord<TOperationId> {
70
72
  operation: DiffTriggerOperation.INSERT;
71
73
  /**
72
74
  * The value of the row, at the time of INSERT, in JSON string format.
@@ -79,8 +81,9 @@ export interface TriggerDiffInsertRecord<TOperationId extends string | number =
79
81
  * Represents a diff record for a SQLite DELETE operation.
80
82
  * This record contains the new value represented as a JSON string.
81
83
  */
82
- export interface TriggerDiffDeleteRecord<TOperationId extends string | number = number>
83
- extends BaseTriggerDiffRecord<TOperationId> {
84
+ export interface TriggerDiffDeleteRecord<
85
+ TOperationId extends string | number = number
86
+ > extends BaseTriggerDiffRecord<TOperationId> {
84
87
  operation: DiffTriggerOperation.DELETE;
85
88
  /**
86
89
  * The value of the row, before the DELETE operation, in JSON string format.
@@ -201,6 +204,12 @@ interface BaseCreateDiffTriggerOptions {
201
204
  * Hooks which allow execution during the trigger creation process.
202
205
  */
203
206
  hooks?: TriggerCreationHooks;
207
+
208
+ /**
209
+ * Use storage-backed (non-TEMP) tables and triggers that persist across sessions.
210
+ * These resources are still automatically disposed when no longer claimed.
211
+ */
212
+ useStorage?: boolean;
204
213
  }
205
214
 
206
215
  /**
@@ -449,3 +458,38 @@ export interface TriggerManager {
449
458
  */
450
459
  trackTableDiff(options: TrackDiffOptions): Promise<TriggerRemoveCallback>;
451
460
  }
461
+
462
+ /**
463
+ * @experimental
464
+ * @internal
465
+ * Manages claims on persisted SQLite triggers and destination tables to enable proper cleanup
466
+ * when they are no longer actively in use.
467
+ *
468
+ * When using persisted triggers (especially for OPFS multi-tab scenarios), we need a reliable way to determine which resources are still actively in use across different connections/tabs so stale resources can be safely cleaned up without interfering with active triggers.
469
+ *
470
+ * A cleanup process runs
471
+ * on database creation (and every 2 minutes) that:
472
+ * 1. Queries for existing managed persisted resources
473
+ * 2. Checks with the claim manager if any consumer is actively using those resources
474
+ * 3. Deletes unused resources
475
+ */
476
+
477
+ export interface TriggerClaimManager {
478
+ /**
479
+ * Obtains or marks a claim on a certain identifier.
480
+ * @returns a callback to release the claim.
481
+ */
482
+ obtainClaim: (identifier: string) => Promise<() => Promise<void>>;
483
+ /**
484
+ * Checks if a claim is present for an identifier.
485
+ */
486
+ checkClaim: (identifier: string) => Promise<boolean>;
487
+ }
488
+
489
+ /**
490
+ * @experimental
491
+ * @internal
492
+ */
493
+ export interface TriggerManagerConfig {
494
+ claimManager: TriggerClaimManager;
495
+ }