@powersync/web 1.38.2 → 1.38.3

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 (69) hide show
  1. package/dist/worker/SharedSyncImplementation.umd.js +548 -345
  2. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  3. package/dist/worker/WASQLiteDB.umd.js +548 -345
  4. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  5. package/lib/package.json +2 -2
  6. package/lib/src/attachments/IndexDBFileSystemAdapter.js +1 -0
  7. package/lib/src/attachments/IndexDBFileSystemAdapter.js.map +1 -0
  8. package/lib/src/db/NavigatorTriggerClaimManager.js +1 -0
  9. package/lib/src/db/NavigatorTriggerClaimManager.js.map +1 -0
  10. package/lib/src/db/PowerSyncDatabase.js +1 -0
  11. package/lib/src/db/PowerSyncDatabase.js.map +1 -0
  12. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +1 -0
  13. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js.map +1 -0
  14. package/lib/src/db/adapters/AsyncWebAdapter.js +1 -0
  15. package/lib/src/db/adapters/AsyncWebAdapter.js.map +1 -0
  16. package/lib/src/db/adapters/SSRDBAdapter.js +1 -0
  17. package/lib/src/db/adapters/SSRDBAdapter.js.map +1 -0
  18. package/lib/src/db/adapters/WebDBAdapter.js +1 -0
  19. package/lib/src/db/adapters/WebDBAdapter.js.map +1 -0
  20. package/lib/src/db/adapters/wa-sqlite/ConcurrentConnection.js +1 -0
  21. package/lib/src/db/adapters/wa-sqlite/ConcurrentConnection.js.map +1 -0
  22. package/lib/src/db/adapters/wa-sqlite/DatabaseClient.js +1 -0
  23. package/lib/src/db/adapters/wa-sqlite/DatabaseClient.js.map +1 -0
  24. package/lib/src/db/adapters/wa-sqlite/DatabaseServer.js +1 -0
  25. package/lib/src/db/adapters/wa-sqlite/DatabaseServer.js.map +1 -0
  26. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js +1 -0
  27. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js.map +1 -0
  28. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +1 -0
  29. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +1 -0
  30. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +1 -0
  31. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js.map +1 -0
  32. package/lib/src/db/adapters/wa-sqlite/vfs.js +1 -0
  33. package/lib/src/db/adapters/wa-sqlite/vfs.js.map +1 -0
  34. package/lib/src/db/adapters/web-sql-flags.js +1 -0
  35. package/lib/src/db/adapters/web-sql-flags.js.map +1 -0
  36. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js +1 -0
  37. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js.map +1 -0
  38. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +1 -0
  39. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js.map +1 -0
  40. package/lib/src/db/sync/WebRemote.js +1 -0
  41. package/lib/src/db/sync/WebRemote.js.map +1 -0
  42. package/lib/src/db/sync/WebStreamingSyncImplementation.js +1 -0
  43. package/lib/src/db/sync/WebStreamingSyncImplementation.js.map +1 -0
  44. package/lib/src/db/sync/userAgent.js +1 -0
  45. package/lib/src/db/sync/userAgent.js.map +1 -0
  46. package/lib/src/index.js +1 -0
  47. package/lib/src/index.js.map +1 -0
  48. package/lib/src/shared/navigator.js +1 -0
  49. package/lib/src/shared/navigator.js.map +1 -0
  50. package/lib/src/shared/tab_close_signal.js +1 -0
  51. package/lib/src/shared/tab_close_signal.js.map +1 -0
  52. package/lib/src/worker/db/MultiDatabaseServer.js +1 -0
  53. package/lib/src/worker/db/MultiDatabaseServer.js.map +1 -0
  54. package/lib/src/worker/db/WASQLiteDB.worker.js +1 -0
  55. package/lib/src/worker/db/WASQLiteDB.worker.js.map +1 -0
  56. package/lib/src/worker/db/open-worker-database.js +1 -0
  57. package/lib/src/worker/db/open-worker-database.js.map +1 -0
  58. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.js +1 -0
  59. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.js.map +1 -0
  60. package/lib/src/worker/sync/BroadcastLogger.js +1 -0
  61. package/lib/src/worker/sync/BroadcastLogger.js.map +1 -0
  62. package/lib/src/worker/sync/SharedSyncImplementation.js +1 -0
  63. package/lib/src/worker/sync/SharedSyncImplementation.js.map +1 -0
  64. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -0
  65. package/lib/src/worker/sync/SharedSyncImplementation.worker.js.map +1 -0
  66. package/lib/src/worker/sync/WorkerClient.js +1 -0
  67. package/lib/src/worker/sync/WorkerClient.js.map +1 -0
  68. package/lib/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +3 -3
@@ -2891,7 +2891,10 @@ __webpack_require__.r(__webpack_exports__);
2891
2891
  /* harmony export */ sanitizeUUID: () => (/* binding */ sanitizeUUID),
2892
2892
  /* harmony export */ timeoutSignal: () => (/* binding */ timeoutSignal)
2893
2893
  /* harmony export */ });
2894
- // https://www.sqlite.org/lang_expr.html#castexpr
2894
+ /**
2895
+ * @see https://www.sqlite.org/lang_expr.html#castexpr
2896
+ * @public
2897
+ */
2895
2898
  var ColumnType;
2896
2899
  (function (ColumnType) {
2897
2900
  ColumnType["TEXT"] = "TEXT";
@@ -2907,14 +2910,24 @@ const integer = {
2907
2910
  const real = {
2908
2911
  type: ColumnType.REAL
2909
2912
  };
2910
- // powersync-sqlite-core limits the number of column per table to 1999, due to internal SQLite limits.
2911
- // In earlier versions this was limited to 63.
2913
+ /**
2914
+ * powersync-sqlite-core limits the number of column per table to 1999, due to internal SQLite limits.
2915
+ * In earlier versions this was limited to 63.
2916
+ *
2917
+ * @internal
2918
+ */
2912
2919
  const MAX_AMOUNT_OF_COLUMNS = 1999;
2920
+ /**
2921
+ * @public
2922
+ */
2913
2923
  const column = {
2914
2924
  text,
2915
2925
  integer,
2916
2926
  real
2917
2927
  };
2928
+ /**
2929
+ * @public
2930
+ */
2918
2931
  class Column {
2919
2932
  options;
2920
2933
  constructor(options) {
@@ -2934,9 +2947,15 @@ class Column {
2934
2947
  }
2935
2948
  }
2936
2949
 
2950
+ /**
2951
+ * @internal
2952
+ */
2937
2953
  const DEFAULT_INDEX_COLUMN_OPTIONS = {
2938
2954
  ascending: true
2939
2955
  };
2956
+ /**
2957
+ * @public
2958
+ */
2940
2959
  class IndexedColumn {
2941
2960
  options;
2942
2961
  static createAscending(column) {
@@ -2963,9 +2982,15 @@ class IndexedColumn {
2963
2982
  }
2964
2983
  }
2965
2984
 
2985
+ /**
2986
+ * @internal
2987
+ */
2966
2988
  const DEFAULT_INDEX_OPTIONS = {
2967
2989
  columns: []
2968
2990
  };
2991
+ /**
2992
+ * @public
2993
+ */
2969
2994
  class Index {
2970
2995
  options;
2971
2996
  static createAscending(options, columnNames) {
@@ -3007,6 +3032,9 @@ function encodeTableOptions(options) {
3007
3032
  };
3008
3033
  }
3009
3034
 
3035
+ /**
3036
+ * @internal
3037
+ */
3010
3038
  const DEFAULT_TABLE_OPTIONS = {
3011
3039
  indexes: [],
3012
3040
  insertOnly: false,
@@ -3015,7 +3043,13 @@ const DEFAULT_TABLE_OPTIONS = {
3015
3043
  trackMetadata: false,
3016
3044
  ignoreEmptyUpdates: false
3017
3045
  };
3046
+ /**
3047
+ * @internal
3048
+ */
3018
3049
  const InvalidSQLCharacters = /["'%,.#\s[\]]/;
3050
+ /**
3051
+ * @public
3052
+ */
3019
3053
  class Table {
3020
3054
  options;
3021
3055
  _mappedColumns;
@@ -3206,6 +3240,11 @@ class Table {
3206
3240
  }
3207
3241
  }
3208
3242
 
3243
+ /**
3244
+ * The default name of the local table storing attachment data.
3245
+ *
3246
+ * @alpha
3247
+ */
3209
3248
  const ATTACHMENT_TABLE = 'attachments';
3210
3249
  /**
3211
3250
  * Maps a database row to an AttachmentRecord.
@@ -3213,7 +3252,7 @@ const ATTACHMENT_TABLE = 'attachments';
3213
3252
  * @param row - The database row object
3214
3253
  * @returns The corresponding AttachmentRecord
3215
3254
  *
3216
- * @experimental
3255
+ * @alpha
3217
3256
  */
3218
3257
  function attachmentFromSql(row) {
3219
3258
  return {
@@ -3231,7 +3270,7 @@ function attachmentFromSql(row) {
3231
3270
  /**
3232
3271
  * AttachmentState represents the current synchronization state of an attachment.
3233
3272
  *
3234
- * @experimental
3273
+ * @alpha
3235
3274
  */
3236
3275
  var AttachmentState;
3237
3276
  (function (AttachmentState) {
@@ -3244,7 +3283,7 @@ var AttachmentState;
3244
3283
  /**
3245
3284
  * AttachmentTable defines the schema for the attachment queue table.
3246
3285
  *
3247
- * @internal
3286
+ * @alpha
3248
3287
  */
3249
3288
  class AttachmentTable extends Table {
3250
3289
  constructor(options) {
@@ -3272,7 +3311,8 @@ class AttachmentTable extends Table {
3272
3311
  * Provides methods to query, insert, update, and delete attachment records with
3273
3312
  * proper transaction management through PowerSync.
3274
3313
  *
3275
- * @internal
3314
+ * @experimental
3315
+ * @alpha
3276
3316
  */
3277
3317
  class AttachmentContext {
3278
3318
  /** PowerSync database instance for executing queries */
@@ -3494,6 +3534,9 @@ class AttachmentContext {
3494
3534
  }
3495
3535
  }
3496
3536
 
3537
+ /**
3538
+ * @public
3539
+ */
3497
3540
  var WatchedQueryListenerEvent;
3498
3541
  (function (WatchedQueryListenerEvent) {
3499
3542
  WatchedQueryListenerEvent["ON_DATA"] = "onData";
@@ -3502,176 +3545,18 @@ var WatchedQueryListenerEvent;
3502
3545
  WatchedQueryListenerEvent["SETTINGS_WILL_UPDATE"] = "settingsWillUpdate";
3503
3546
  WatchedQueryListenerEvent["CLOSED"] = "closed";
3504
3547
  })(WatchedQueryListenerEvent || (WatchedQueryListenerEvent = {}));
3548
+ /**
3549
+ * @internal
3550
+ */
3505
3551
  const DEFAULT_WATCH_THROTTLE_MS = 30;
3552
+ /**
3553
+ * @internal
3554
+ */
3506
3555
  const DEFAULT_WATCH_QUERY_OPTIONS = {
3507
3556
  throttleMs: DEFAULT_WATCH_THROTTLE_MS,
3508
3557
  reportFetching: true
3509
3558
  };
3510
3559
 
3511
- /**
3512
- * Orchestrates attachment synchronization between local and remote storage.
3513
- * Handles uploads, downloads, deletions, and state transitions.
3514
- *
3515
- * @internal
3516
- */
3517
- class SyncingService {
3518
- attachmentService;
3519
- localStorage;
3520
- remoteStorage;
3521
- logger;
3522
- errorHandler;
3523
- constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
3524
- this.attachmentService = attachmentService;
3525
- this.localStorage = localStorage;
3526
- this.remoteStorage = remoteStorage;
3527
- this.logger = logger;
3528
- this.errorHandler = errorHandler;
3529
- }
3530
- /**
3531
- * Processes attachments based on their state (upload, download, or delete).
3532
- * All updates are saved in a single batch after processing.
3533
- *
3534
- * @param attachments - Array of attachment records to process
3535
- * @param context - Attachment context for database operations
3536
- * @returns Promise that resolves when all attachments have been processed and saved
3537
- */
3538
- async processAttachments(attachments, context) {
3539
- const updatedAttachments = [];
3540
- for (const attachment of attachments) {
3541
- switch (attachment.state) {
3542
- case AttachmentState.QUEUED_UPLOAD:
3543
- const uploaded = await this.uploadAttachment(attachment);
3544
- updatedAttachments.push(uploaded);
3545
- break;
3546
- case AttachmentState.QUEUED_DOWNLOAD:
3547
- const downloaded = await this.downloadAttachment(attachment);
3548
- updatedAttachments.push(downloaded);
3549
- break;
3550
- case AttachmentState.QUEUED_DELETE:
3551
- const deleted = await this.deleteAttachment(attachment, context);
3552
- updatedAttachments.push(deleted);
3553
- break;
3554
- }
3555
- }
3556
- await context.saveAttachments(updatedAttachments);
3557
- }
3558
- /**
3559
- * Uploads an attachment from local storage to remote storage.
3560
- * On success, marks as SYNCED. On failure, defers to error handler or archives.
3561
- *
3562
- * @param attachment - The attachment record to upload
3563
- * @returns Updated attachment record with new state
3564
- * @throws Error if the attachment has no localUri
3565
- */
3566
- async uploadAttachment(attachment) {
3567
- this.logger.info(`Uploading attachment ${attachment.filename}`);
3568
- try {
3569
- if (attachment.localUri == null) {
3570
- throw new Error(`No localUri for attachment ${attachment.id}`);
3571
- }
3572
- const fileBlob = await this.localStorage.readFile(attachment.localUri);
3573
- await this.remoteStorage.uploadFile(fileBlob, attachment);
3574
- return {
3575
- ...attachment,
3576
- state: AttachmentState.SYNCED,
3577
- hasSynced: true
3578
- };
3579
- }
3580
- catch (error) {
3581
- const shouldRetry = (await this.errorHandler?.onUploadError(attachment, error)) ?? true;
3582
- if (!shouldRetry) {
3583
- return {
3584
- ...attachment,
3585
- state: AttachmentState.ARCHIVED
3586
- };
3587
- }
3588
- return attachment;
3589
- }
3590
- }
3591
- /**
3592
- * Downloads an attachment from remote storage to local storage.
3593
- * Retrieves the file, converts to base64, and saves locally.
3594
- * On success, marks as SYNCED. On failure, defers to error handler or archives.
3595
- *
3596
- * @param attachment - The attachment record to download
3597
- * @returns Updated attachment record with local URI and new state
3598
- */
3599
- async downloadAttachment(attachment) {
3600
- this.logger.info(`Downloading attachment ${attachment.filename}`);
3601
- try {
3602
- const fileData = await this.remoteStorage.downloadFile(attachment);
3603
- const localUri = this.localStorage.getLocalUri(attachment.filename);
3604
- await this.localStorage.saveFile(localUri, fileData);
3605
- return {
3606
- ...attachment,
3607
- state: AttachmentState.SYNCED,
3608
- localUri: localUri,
3609
- hasSynced: true
3610
- };
3611
- }
3612
- catch (error) {
3613
- const shouldRetry = (await this.errorHandler?.onDownloadError(attachment, error)) ?? true;
3614
- if (!shouldRetry) {
3615
- return {
3616
- ...attachment,
3617
- state: AttachmentState.ARCHIVED
3618
- };
3619
- }
3620
- return attachment;
3621
- }
3622
- }
3623
- /**
3624
- * Deletes an attachment from both remote and local storage.
3625
- * Removes the remote file, local file (if exists), and the attachment record.
3626
- * On failure, defers to error handler or archives.
3627
- *
3628
- * @param attachment - The attachment record to delete
3629
- * @param context - Attachment context for database operations
3630
- * @returns Updated attachment record
3631
- */
3632
- async deleteAttachment(attachment, context) {
3633
- try {
3634
- await this.remoteStorage.deleteFile(attachment);
3635
- if (attachment.localUri) {
3636
- await this.localStorage.deleteFile(attachment.localUri);
3637
- }
3638
- await context.deleteAttachment(attachment.id);
3639
- return {
3640
- ...attachment,
3641
- state: AttachmentState.ARCHIVED
3642
- };
3643
- }
3644
- catch (error) {
3645
- const shouldRetry = (await this.errorHandler?.onDeleteError(attachment, error)) ?? true;
3646
- if (!shouldRetry) {
3647
- return {
3648
- ...attachment,
3649
- state: AttachmentState.ARCHIVED
3650
- };
3651
- }
3652
- return attachment;
3653
- }
3654
- }
3655
- /**
3656
- * Performs cleanup of archived attachments by removing their local files and records.
3657
- * Errors during local file deletion are logged but do not prevent record deletion.
3658
- */
3659
- async deleteArchivedAttachments(context) {
3660
- return await context.deleteArchivedAttachments(async (archivedAttachments) => {
3661
- for (const attachment of archivedAttachments) {
3662
- if (attachment.localUri) {
3663
- try {
3664
- await this.localStorage.deleteFile(attachment.localUri);
3665
- }
3666
- catch (error) {
3667
- this.logger.error('Error deleting local file for archived attachment', error);
3668
- }
3669
- }
3670
- }
3671
- });
3672
- }
3673
- }
3674
-
3675
3560
  /**
3676
3561
  * A simple fixed-capacity queue implementation.
3677
3562
  *
@@ -3828,93 +3713,260 @@ class Semaphore {
3828
3713
  return { release, item: items[0] };
3829
3714
  }
3830
3715
  /**
3831
- * Requests access to all items from the pool.
3716
+ * Requests access to all items from the pool.
3717
+ *
3718
+ * The returned `release` callback must be invoked to return items into the pool.
3719
+ */
3720
+ requestAll(abort) {
3721
+ return this.requestPermits(this.size, abort);
3722
+ }
3723
+ }
3724
+ /**
3725
+ * An asynchronous mutex implementation.
3726
+ *
3727
+ * @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
3728
+ */
3729
+ class Mutex {
3730
+ inner = new Semaphore([null]);
3731
+ async acquire(abort) {
3732
+ const { release } = await this.inner.requestOne(abort);
3733
+ return release;
3734
+ }
3735
+ async runExclusive(fn, abort) {
3736
+ const returnMutex = await this.acquire(abort);
3737
+ try {
3738
+ return await fn();
3739
+ }
3740
+ finally {
3741
+ returnMutex();
3742
+ }
3743
+ }
3744
+ }
3745
+ /**
3746
+ * @internal
3747
+ */
3748
+ function timeoutSignal(timeout) {
3749
+ if (timeout == null)
3750
+ return;
3751
+ if ('timeout' in AbortSignal)
3752
+ return AbortSignal.timeout(timeout);
3753
+ const controller = new AbortController();
3754
+ setTimeout(() => controller.abort(new Error('Timeout waiting for lock')), timeout);
3755
+ return controller.signal;
3756
+ }
3757
+
3758
+ /**
3759
+ * Service for querying and watching attachment records in the database.
3760
+ *
3761
+ * @internal
3762
+ */
3763
+ class AttachmentService {
3764
+ db;
3765
+ logger;
3766
+ tableName;
3767
+ mutex = new Mutex();
3768
+ context;
3769
+ constructor(db, logger, tableName = 'attachments', archivedCacheLimit = 100) {
3770
+ this.db = db;
3771
+ this.logger = logger;
3772
+ this.tableName = tableName;
3773
+ this.context = new AttachmentContext(db, tableName, logger, archivedCacheLimit);
3774
+ }
3775
+ /**
3776
+ * Creates a differential watch query for active attachments requiring synchronization.
3777
+ * @returns Watch query that emits changes for queued uploads, downloads, and deletes
3778
+ */
3779
+ watchActiveAttachments({ throttleMs } = {}) {
3780
+ this.logger.info('Watching active attachments...');
3781
+ const watch = this.db
3782
+ .query({
3783
+ sql: /* sql */ `
3784
+ SELECT
3785
+ *
3786
+ FROM
3787
+ ${this.tableName}
3788
+ WHERE
3789
+ state = ?
3790
+ OR state = ?
3791
+ OR state = ?
3792
+ ORDER BY
3793
+ timestamp ASC
3794
+ `,
3795
+ parameters: [AttachmentState.QUEUED_UPLOAD, AttachmentState.QUEUED_DOWNLOAD, AttachmentState.QUEUED_DELETE]
3796
+ })
3797
+ .differentialWatch({ throttleMs });
3798
+ return watch;
3799
+ }
3800
+ /**
3801
+ * Executes a callback with exclusive access to the attachment context.
3802
+ */
3803
+ async withContext(callback) {
3804
+ return this.mutex.runExclusive(async () => {
3805
+ return callback(this.context);
3806
+ });
3807
+ }
3808
+ }
3809
+
3810
+ /**
3811
+ * Orchestrates attachment synchronization between local and remote storage.
3812
+ * Handles uploads, downloads, deletions, and state transitions.
3813
+ *
3814
+ * @internal
3815
+ */
3816
+ class SyncingService {
3817
+ attachmentService;
3818
+ localStorage;
3819
+ remoteStorage;
3820
+ logger;
3821
+ errorHandler;
3822
+ constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
3823
+ this.attachmentService = attachmentService;
3824
+ this.localStorage = localStorage;
3825
+ this.remoteStorage = remoteStorage;
3826
+ this.logger = logger;
3827
+ this.errorHandler = errorHandler;
3828
+ }
3829
+ /**
3830
+ * Processes attachments based on their state (upload, download, or delete).
3831
+ * All updates are saved in a single batch after processing.
3832
+ *
3833
+ * @param attachments - Array of attachment records to process
3834
+ * @param context - Attachment context for database operations
3835
+ * @returns Promise that resolves when all attachments have been processed and saved
3836
+ */
3837
+ async processAttachments(attachments, context) {
3838
+ const updatedAttachments = [];
3839
+ for (const attachment of attachments) {
3840
+ switch (attachment.state) {
3841
+ case AttachmentState.QUEUED_UPLOAD:
3842
+ const uploaded = await this.uploadAttachment(attachment);
3843
+ updatedAttachments.push(uploaded);
3844
+ break;
3845
+ case AttachmentState.QUEUED_DOWNLOAD:
3846
+ const downloaded = await this.downloadAttachment(attachment);
3847
+ updatedAttachments.push(downloaded);
3848
+ break;
3849
+ case AttachmentState.QUEUED_DELETE:
3850
+ const deleted = await this.deleteAttachment(attachment, context);
3851
+ updatedAttachments.push(deleted);
3852
+ break;
3853
+ }
3854
+ }
3855
+ await context.saveAttachments(updatedAttachments);
3856
+ }
3857
+ /**
3858
+ * Uploads an attachment from local storage to remote storage.
3859
+ * On success, marks as SYNCED. On failure, defers to error handler or archives.
3860
+ *
3861
+ * @param attachment - The attachment record to upload
3862
+ * @returns Updated attachment record with new state
3863
+ * @throws Error if the attachment has no localUri
3864
+ */
3865
+ async uploadAttachment(attachment) {
3866
+ this.logger.info(`Uploading attachment ${attachment.filename}`);
3867
+ try {
3868
+ if (attachment.localUri == null) {
3869
+ throw new Error(`No localUri for attachment ${attachment.id}`);
3870
+ }
3871
+ const fileBlob = await this.localStorage.readFile(attachment.localUri);
3872
+ await this.remoteStorage.uploadFile(fileBlob, attachment);
3873
+ return {
3874
+ ...attachment,
3875
+ state: AttachmentState.SYNCED,
3876
+ hasSynced: true
3877
+ };
3878
+ }
3879
+ catch (error) {
3880
+ const shouldRetry = (await this.errorHandler?.onUploadError(attachment, error)) ?? true;
3881
+ if (!shouldRetry) {
3882
+ return {
3883
+ ...attachment,
3884
+ state: AttachmentState.ARCHIVED
3885
+ };
3886
+ }
3887
+ return attachment;
3888
+ }
3889
+ }
3890
+ /**
3891
+ * Downloads an attachment from remote storage to local storage.
3892
+ * Retrieves the file, converts to base64, and saves locally.
3893
+ * On success, marks as SYNCED. On failure, defers to error handler or archives.
3894
+ *
3895
+ * @param attachment - The attachment record to download
3896
+ * @returns Updated attachment record with local URI and new state
3897
+ */
3898
+ async downloadAttachment(attachment) {
3899
+ this.logger.info(`Downloading attachment ${attachment.filename}`);
3900
+ try {
3901
+ const fileData = await this.remoteStorage.downloadFile(attachment);
3902
+ const localUri = this.localStorage.getLocalUri(attachment.filename);
3903
+ await this.localStorage.saveFile(localUri, fileData);
3904
+ return {
3905
+ ...attachment,
3906
+ state: AttachmentState.SYNCED,
3907
+ localUri: localUri,
3908
+ hasSynced: true
3909
+ };
3910
+ }
3911
+ catch (error) {
3912
+ const shouldRetry = (await this.errorHandler?.onDownloadError(attachment, error)) ?? true;
3913
+ if (!shouldRetry) {
3914
+ return {
3915
+ ...attachment,
3916
+ state: AttachmentState.ARCHIVED
3917
+ };
3918
+ }
3919
+ return attachment;
3920
+ }
3921
+ }
3922
+ /**
3923
+ * Deletes an attachment from both remote and local storage.
3924
+ * Removes the remote file, local file (if exists), and the attachment record.
3925
+ * On failure, defers to error handler or archives.
3832
3926
  *
3833
- * The returned `release` callback must be invoked to return items into the pool.
3927
+ * @param attachment - The attachment record to delete
3928
+ * @param context - Attachment context for database operations
3929
+ * @returns Updated attachment record
3834
3930
  */
3835
- requestAll(abort) {
3836
- return this.requestPermits(this.size, abort);
3837
- }
3838
- }
3839
- /**
3840
- * An asynchronous mutex implementation.
3841
- *
3842
- * @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
3843
- */
3844
- class Mutex {
3845
- inner = new Semaphore([null]);
3846
- async acquire(abort) {
3847
- const { release } = await this.inner.requestOne(abort);
3848
- return release;
3849
- }
3850
- async runExclusive(fn, abort) {
3851
- const returnMutex = await this.acquire(abort);
3931
+ async deleteAttachment(attachment, context) {
3852
3932
  try {
3853
- return await fn();
3933
+ await this.remoteStorage.deleteFile(attachment);
3934
+ if (attachment.localUri) {
3935
+ await this.localStorage.deleteFile(attachment.localUri);
3936
+ }
3937
+ await context.deleteAttachment(attachment.id);
3938
+ return {
3939
+ ...attachment,
3940
+ state: AttachmentState.ARCHIVED
3941
+ };
3854
3942
  }
3855
- finally {
3856
- returnMutex();
3943
+ catch (error) {
3944
+ const shouldRetry = (await this.errorHandler?.onDeleteError(attachment, error)) ?? true;
3945
+ if (!shouldRetry) {
3946
+ return {
3947
+ ...attachment,
3948
+ state: AttachmentState.ARCHIVED
3949
+ };
3950
+ }
3951
+ return attachment;
3857
3952
  }
3858
3953
  }
3859
- }
3860
- function timeoutSignal(timeout) {
3861
- if (timeout == null)
3862
- return;
3863
- if ('timeout' in AbortSignal)
3864
- return AbortSignal.timeout(timeout);
3865
- const controller = new AbortController();
3866
- setTimeout(() => controller.abort(new Error('Timeout waiting for lock')), timeout);
3867
- return controller.signal;
3868
- }
3869
-
3870
- /**
3871
- * Service for querying and watching attachment records in the database.
3872
- *
3873
- * @internal
3874
- */
3875
- class AttachmentService {
3876
- db;
3877
- logger;
3878
- tableName;
3879
- mutex = new Mutex();
3880
- context;
3881
- constructor(db, logger, tableName = 'attachments', archivedCacheLimit = 100) {
3882
- this.db = db;
3883
- this.logger = logger;
3884
- this.tableName = tableName;
3885
- this.context = new AttachmentContext(db, tableName, logger, archivedCacheLimit);
3886
- }
3887
- /**
3888
- * Creates a differential watch query for active attachments requiring synchronization.
3889
- * @returns Watch query that emits changes for queued uploads, downloads, and deletes
3890
- */
3891
- watchActiveAttachments({ throttleMs } = {}) {
3892
- this.logger.info('Watching active attachments...');
3893
- const watch = this.db
3894
- .query({
3895
- sql: /* sql */ `
3896
- SELECT
3897
- *
3898
- FROM
3899
- ${this.tableName}
3900
- WHERE
3901
- state = ?
3902
- OR state = ?
3903
- OR state = ?
3904
- ORDER BY
3905
- timestamp ASC
3906
- `,
3907
- parameters: [AttachmentState.QUEUED_UPLOAD, AttachmentState.QUEUED_DOWNLOAD, AttachmentState.QUEUED_DELETE]
3908
- })
3909
- .differentialWatch({ throttleMs });
3910
- return watch;
3911
- }
3912
3954
  /**
3913
- * Executes a callback with exclusive access to the attachment context.
3955
+ * Performs cleanup of archived attachments by removing their local files and records.
3956
+ * Errors during local file deletion are logged but do not prevent record deletion.
3914
3957
  */
3915
- async withContext(callback) {
3916
- return this.mutex.runExclusive(async () => {
3917
- return callback(this.context);
3958
+ async deleteArchivedAttachments(context) {
3959
+ return await context.deleteArchivedAttachments(async (archivedAttachments) => {
3960
+ for (const attachment of archivedAttachments) {
3961
+ if (attachment.localUri) {
3962
+ try {
3963
+ await this.localStorage.deleteFile(attachment.localUri);
3964
+ }
3965
+ catch (error) {
3966
+ this.logger.error('Error deleting local file for archived attachment', error);
3967
+ }
3968
+ }
3969
+ }
3918
3970
  });
3919
3971
  }
3920
3972
  }
@@ -3975,16 +4027,6 @@ class AttachmentQueue {
3975
4027
  * Creates a new AttachmentQueue instance.
3976
4028
  *
3977
4029
  * @param options - Configuration options
3978
- * @param options.db - PowerSync database instance
3979
- * @param options.remoteStorage - Remote storage adapter for upload/download operations
3980
- * @param options.localStorage - Local storage adapter for file persistence
3981
- * @param options.watchAttachments - Callback for monitoring attachment changes in your data model
3982
- * @param options.tableName - Name of the table to store attachment records. Default: 'ps_attachment_queue'
3983
- * @param options.logger - Logger instance. Defaults to db.logger
3984
- * @param options.syncIntervalMs - Periodic polling interval in milliseconds for retrying failed uploads/downloads. Default: 30000
3985
- * @param options.syncThrottleDuration - Throttle duration in milliseconds for the reactive watch query that detects attachment changes. Prevents rapid-fire syncs during bulk changes. Default: 30
3986
- * @param options.downloadAttachments - Whether to automatically download remote attachments. Default: true
3987
- * @param options.archivedCacheLimit - Maximum archived attachments before cleanup. Default: 100
3988
4030
  */
3989
4031
  constructor({ db, localStorage, remoteStorage, watchAttachments, logger, tableName = ATTACHMENT_TABLE, syncIntervalMs = 30 * 1000, syncThrottleDuration = DEFAULT_WATCH_THROTTLE_MS, downloadAttachments = true, archivedCacheLimit = 100, errorHandler }) {
3990
4032
  this.db = db;
@@ -4073,6 +4115,7 @@ class AttachmentQueue {
4073
4115
  state: AttachmentState.QUEUED_DOWNLOAD,
4074
4116
  hasSynced: false,
4075
4117
  metaData: watchedAttachment.metaData,
4118
+ mediaType: watchedAttachment.mediaType,
4076
4119
  timestamp: new Date().getTime()
4077
4120
  });
4078
4121
  continue;
@@ -4160,17 +4203,24 @@ class AttachmentQueue {
4160
4203
  this.statusListenerDispose = undefined;
4161
4204
  }
4162
4205
  }
4206
+ /**
4207
+ * Provides an {@link AttachmentContext} to a callback.
4208
+ *
4209
+ * The callback runs while the attachment queue mutex is held. Do not call
4210
+ * other {@link AttachmentQueue} methods from within the callback, as they may
4211
+ * attempt to acquire the same mutex and block indefinitely.
4212
+ */
4213
+ withAttachmentContext(callback) {
4214
+ /**
4215
+ * AttachmentService is internal and private in this class.
4216
+ * We only need to expose its locking and context functionality for extending classes.
4217
+ */
4218
+ return this.attachmentService.withContext(callback);
4219
+ }
4163
4220
  /**
4164
4221
  * Saves a file to local storage and queues it for upload to remote storage.
4165
4222
  *
4166
4223
  * @param options - File save options
4167
- * @param options.data - The file data as ArrayBuffer, Blob, or base64 string
4168
- * @param options.fileExtension - File extension (e.g., 'jpg', 'pdf')
4169
- * @param options.mediaType - MIME type of the file (e.g., 'image/jpeg')
4170
- * @param options.metaData - Optional metadata to associate with the attachment
4171
- * @param options.id - Optional custom ID. If not provided, a UUID will be generated
4172
- * @param options.updateHook - Optional callback to execute additional database operations
4173
- * within the same transaction as the attachment creation
4174
4224
  * @returns Promise resolving to the created attachment record
4175
4225
  */
4176
4226
  async saveFile({ data, fileExtension, mediaType, metaData, id, updateHook }) {
@@ -4283,6 +4333,9 @@ class AttachmentQueue {
4283
4333
  }
4284
4334
  }
4285
4335
 
4336
+ /**
4337
+ * @alpha
4338
+ */
4286
4339
  var EncodingType;
4287
4340
  (function (EncodingType) {
4288
4341
  EncodingType["UTF8"] = "utf8";
@@ -4746,7 +4799,9 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
4746
4799
  * different SQLite DB implementations.
4747
4800
  */
4748
4801
  /**
4749
- * Implements {@link DBGetUtils} on a {@link SqlRunner}.
4802
+ * Implements {@link DBGetUtils} on a {@link SqlExecutor}.
4803
+ *
4804
+ * @internal
4750
4805
  */
4751
4806
  function DBGetUtilsDefaultMixin(Base) {
4752
4807
  return class extends Base {
@@ -4790,6 +4845,8 @@ function DBGetUtilsDefaultMixin(Base) {
4790
4845
  }
4791
4846
  /**
4792
4847
  * Update table operation numbers from SQLite
4848
+ *
4849
+ * @public
4793
4850
  */
4794
4851
  var RowUpdateType;
4795
4852
  (function (RowUpdateType) {
@@ -4798,8 +4855,10 @@ var RowUpdateType;
4798
4855
  RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
4799
4856
  })(RowUpdateType || (RowUpdateType = {}));
4800
4857
  /**
4801
- * A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool.readLock} and
4802
- * {@link ConnectionPool.writeLock}.
4858
+ * A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool#readLock} and
4859
+ * {@link ConnectionPool#writeLock}.
4860
+ *
4861
+ * @internal
4803
4862
  */
4804
4863
  function DBAdapterDefaultMixin(Base) {
4805
4864
  return class extends Base {
@@ -4887,9 +4946,15 @@ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction)
4887
4946
  }
4888
4947
  }
4889
4948
  }
4949
+ /**
4950
+ * @internal
4951
+ */
4890
4952
  function isBatchedUpdateNotification(update) {
4891
4953
  return 'tables' in update;
4892
4954
  }
4955
+ /**
4956
+ * @internal
4957
+ */
4893
4958
  function extractTableUpdates(update) {
4894
4959
  return isBatchedUpdateNotification(update) ? update.tables : [update.table];
4895
4960
  }
@@ -4917,6 +4982,8 @@ const FULL_SYNC_PRIORITY = 2147483647;
4917
4982
  *
4918
4983
  * Also note that data is downloaded in bulk, which means that individual counters are unlikely
4919
4984
  * to be updated one-by-one.
4985
+ *
4986
+ * @public
4920
4987
  */
4921
4988
  class SyncProgress {
4922
4989
  internal;
@@ -4955,6 +5022,9 @@ class SyncProgress {
4955
5022
  }
4956
5023
  }
4957
5024
 
5025
+ /**
5026
+ * @public
5027
+ */
4958
5028
  class SyncStatus {
4959
5029
  options;
4960
5030
  constructor(options) {
@@ -4965,6 +5035,8 @@ class SyncStatus {
4965
5035
  * implementation).
4966
5036
  *
4967
5037
  * This information is only available after a connection has been requested.
5038
+ *
5039
+ * @deprecated This always returns the Rust client (the only option).
4968
5040
  */
4969
5041
  get clientImplementation() {
4970
5042
  return this.options.clientImplementation;
@@ -4972,7 +5044,7 @@ class SyncStatus {
4972
5044
  /**
4973
5045
  * Indicates if the client is currently connected to the PowerSync service.
4974
5046
  *
4975
- * @returns {boolean} True if connected, false otherwise. Defaults to false if not specified.
5047
+ * @returns True if connected, false otherwise. Defaults to false if not specified.
4976
5048
  */
4977
5049
  get connected() {
4978
5050
  return this.options.connected ?? false;
@@ -4980,7 +5052,7 @@ class SyncStatus {
4980
5052
  /**
4981
5053
  * Indicates if the client is in the process of establishing a connection to the PowerSync service.
4982
5054
  *
4983
- * @returns {boolean} True if connecting, false otherwise. Defaults to false if not specified.
5055
+ * @returns True if connecting, false otherwise. Defaults to false if not specified.
4984
5056
  */
4985
5057
  get connecting() {
4986
5058
  return this.options.connecting ?? false;
@@ -4989,7 +5061,7 @@ class SyncStatus {
4989
5061
  * Time that a last sync has fully completed, if any.
4990
5062
  * This timestamp is reset to null after a restart of the PowerSync service.
4991
5063
  *
4992
- * @returns {Date | undefined} The timestamp of the last successful sync, or undefined if no sync has completed.
5064
+ * @returns The timestamp of the last successful sync, or undefined if no sync has completed.
4993
5065
  */
4994
5066
  get lastSyncedAt() {
4995
5067
  return this.options.lastSyncedAt;
@@ -4997,7 +5069,7 @@ class SyncStatus {
4997
5069
  /**
4998
5070
  * Indicates whether there has been at least one full sync completed since initialization.
4999
5071
  *
5000
- * @returns {boolean | undefined} True if at least one sync has completed, false if no sync has completed,
5072
+ * @returns True if at least one sync has completed, false if no sync has completed,
5001
5073
  * or undefined when the state is still being loaded from the database.
5002
5074
  */
5003
5075
  get hasSynced() {
@@ -5006,10 +5078,10 @@ class SyncStatus {
5006
5078
  /**
5007
5079
  * Provides the current data flow status regarding uploads and downloads.
5008
5080
  *
5009
- * @returns {SyncDataFlowStatus} An object containing:
5081
+ * @returns An object containing:
5010
5082
  * - downloading: True if actively downloading changes (only when connected is also true)
5011
5083
  * - uploading: True if actively uploading changes
5012
- * Defaults to {downloading: false, uploading: false} if not specified.
5084
+ * Defaults to `{downloading: false, uploading: false}` if not specified.
5013
5085
  */
5014
5086
  get dataFlowStatus() {
5015
5087
  return (this.options.dataFlow ?? {
@@ -5034,7 +5106,7 @@ class SyncStatus {
5034
5106
  return this.options.dataFlow?.internalStreamSubscriptions?.map((core) => new SyncStreamStatusView(this, core));
5035
5107
  }
5036
5108
  /**
5037
- * If the `stream` appears in {@link syncStreams}, returns the current status for that stream.
5109
+ * If the `stream` appears in {@link SyncStatus.syncStreams}, returns the current status for that stream.
5038
5110
  */
5039
5111
  forStream(stream) {
5040
5112
  const asJson = JSON.stringify(stream.parameters);
@@ -5044,7 +5116,7 @@ class SyncStatus {
5044
5116
  /**
5045
5117
  * Provides sync status information for all bucket priorities, sorted by priority (highest first).
5046
5118
  *
5047
- * @returns {SyncPriorityStatus[]} An array of status entries for different sync priority levels,
5119
+ * @returns An array of status entries for different sync priority levels,
5048
5120
  * sorted with highest priorities (lower numbers) first.
5049
5121
  */
5050
5122
  get priorityStatusEntries() {
@@ -5079,8 +5151,8 @@ class SyncStatus {
5079
5151
  * For example, if PowerSync just finished synchronizing buckets in priority level 3, calling this method
5080
5152
  * with a priority of 1 may return information for priority level 3.
5081
5153
  *
5082
- * @param {number} priority The bucket priority for which the status should be reported
5083
- * @returns {SyncPriorityStatus} Status information for the requested priority level or the next higher level with available status
5154
+ * @param priority - The bucket priority for which the status should be reported
5155
+ * @returns Status information for the requested priority level or the next higher level with available status
5084
5156
  */
5085
5157
  statusForPriority(priority) {
5086
5158
  // priorityStatusEntries are sorted by ascending priorities (so higher numbers to lower numbers).
@@ -5101,8 +5173,8 @@ class SyncStatus {
5101
5173
  * Compares this SyncStatus instance with another to determine if they are equal.
5102
5174
  * Equality is determined by comparing the serialized JSON representation of both instances.
5103
5175
  *
5104
- * @param {SyncStatus} status The SyncStatus instance to compare against
5105
- * @returns {boolean} True if the instances are considered equal, false otherwise
5176
+ * @param status - The SyncStatus instance to compare against
5177
+ * @returns True if the instances are considered equal, false otherwise
5106
5178
  */
5107
5179
  isEqual(status) {
5108
5180
  /**
@@ -5125,7 +5197,7 @@ class SyncStatus {
5125
5197
  * Creates a human-readable string representation of the current sync status.
5126
5198
  * Includes information about connection state, sync completion, and data flow.
5127
5199
  *
5128
- * @returns {string} A string representation of the sync status
5200
+ * @returns A string representation of the sync status
5129
5201
  */
5130
5202
  getMessage() {
5131
5203
  const dataFlow = this.dataFlowStatus;
@@ -5134,7 +5206,7 @@ class SyncStatus {
5134
5206
  /**
5135
5207
  * Serializes the SyncStatus instance to a plain object.
5136
5208
  *
5137
- * @returns {SyncStatusOptions} A plain object representation of the sync status
5209
+ * @returns A plain object representation of the sync status
5138
5210
  */
5139
5211
  toJSON() {
5140
5212
  return {
@@ -5200,6 +5272,9 @@ class SyncStreamStatusView {
5200
5272
  }
5201
5273
  }
5202
5274
 
5275
+ /**
5276
+ * @public
5277
+ */
5203
5278
  class UploadQueueStats {
5204
5279
  count;
5205
5280
  size;
@@ -5225,6 +5300,9 @@ class UploadQueueStats {
5225
5300
  }
5226
5301
  }
5227
5302
 
5303
+ /**
5304
+ * @internal
5305
+ */
5228
5306
  class BaseObserver {
5229
5307
  listeners = new Set();
5230
5308
  constructor() { }
@@ -5252,6 +5330,9 @@ class BaseObserver {
5252
5330
  }
5253
5331
  }
5254
5332
 
5333
+ /**
5334
+ * @internal
5335
+ */
5255
5336
  class ControlledExecutor {
5256
5337
  task;
5257
5338
  /**
@@ -5519,7 +5600,7 @@ class ConnectionManager extends BaseObserver {
5519
5600
  /**
5520
5601
  * Close the sync connection.
5521
5602
  *
5522
- * Use {@link connect} to connect again.
5603
+ * Use {@link ConnectionManager.connect} to connect again.
5523
5604
  */
5524
5605
  async disconnect() {
5525
5606
  // This will help abort pending connects
@@ -5659,6 +5740,8 @@ const _finalizer = 'FinalizationRegistry' in globalThis
5659
5740
  /**
5660
5741
  * An efficient comparator for {@link WatchedQuery} created with {@link Query#watch}. This has the ability to determine if a query
5661
5742
  * result has changes without necessarily processing all items in the result.
5743
+ *
5744
+ * @public
5662
5745
  */
5663
5746
  class ArrayComparator {
5664
5747
  options;
@@ -5686,6 +5769,8 @@ class ArrayComparator {
5686
5769
  }
5687
5770
  /**
5688
5771
  * Watched query comparator that always reports changed result sets.
5772
+ *
5773
+ * @public
5689
5774
  */
5690
5775
  const FalsyComparator = {
5691
5776
  checkEquality: () => false // Default comparator that always returns false
@@ -5893,6 +5978,8 @@ class AbstractQueryProcessor extends MetaBaseObserver {
5893
5978
  /**
5894
5979
  * An empty differential result set.
5895
5980
  * This is used as the initial state for differential incrementally watched queries.
5981
+ *
5982
+ * @internal
5896
5983
  */
5897
5984
  const EMPTY_DIFFERENTIAL = {
5898
5985
  added: [],
@@ -5905,6 +5992,8 @@ const EMPTY_DIFFERENTIAL = {
5905
5992
  * Default implementation of the {@link DifferentialWatchedQueryComparator} for watched queries.
5906
5993
  * It keys items by their `id` property if available, alternatively it uses JSON stringification
5907
5994
  * of the entire item for the key and comparison.
5995
+ *
5996
+ * @internal
5908
5997
  */
5909
5998
  const DEFAULT_ROW_COMPARATOR = {
5910
5999
  keyBy: (item) => {
@@ -6185,6 +6274,8 @@ class CustomQuery {
6185
6274
 
6186
6275
  /**
6187
6276
  * Tests if the input is a {@link SQLOpenOptions}
6277
+ *
6278
+ * @internal
6188
6279
  */
6189
6280
  const isSQLOpenOptions = (test) => {
6190
6281
  // typeof null is `object`, but you cannot use the `in` operator on `null.
@@ -6192,17 +6283,24 @@ const isSQLOpenOptions = (test) => {
6192
6283
  };
6193
6284
  /**
6194
6285
  * Tests if input is a {@link SQLOpenFactory}
6286
+ *
6287
+ * @internal
6195
6288
  */
6196
6289
  const isSQLOpenFactory = (test) => {
6197
6290
  return typeof test?.openDB == 'function';
6198
6291
  };
6199
6292
  /**
6200
6293
  * Tests if input is a {@link DBAdapter}
6294
+ *
6295
+ * @internal
6201
6296
  */
6202
6297
  const isDBAdapter = (test) => {
6203
6298
  return typeof test?.writeTransaction == 'function';
6204
6299
  };
6205
6300
 
6301
+ /**
6302
+ * @internal
6303
+ */
6206
6304
  var PSInternalTable;
6207
6305
  (function (PSInternalTable) {
6208
6306
  PSInternalTable["DATA"] = "ps_data";
@@ -6211,6 +6309,9 @@ var PSInternalTable;
6211
6309
  PSInternalTable["OPLOG"] = "ps_oplog";
6212
6310
  PSInternalTable["UNTYPED"] = "ps_untyped";
6213
6311
  })(PSInternalTable || (PSInternalTable = {}));
6312
+ /**
6313
+ * @internal
6314
+ */
6214
6315
  var PowerSyncControlCommand;
6215
6316
  (function (PowerSyncControlCommand) {
6216
6317
  PowerSyncControlCommand["PROCESS_TEXT_LINE"] = "line_text";
@@ -6228,6 +6329,8 @@ var PowerSyncControlCommand;
6228
6329
 
6229
6330
  /**
6230
6331
  * A batch of client-side changes.
6332
+ *
6333
+ * @public
6231
6334
  */
6232
6335
  class CrudBatch {
6233
6336
  crud;
@@ -6254,6 +6357,8 @@ class CrudBatch {
6254
6357
 
6255
6358
  /**
6256
6359
  * Type of local change.
6360
+ *
6361
+ * @public
6257
6362
  */
6258
6363
  var UpdateType;
6259
6364
  (function (UpdateType) {
@@ -6266,6 +6371,8 @@ var UpdateType;
6266
6371
  })(UpdateType || (UpdateType = {}));
6267
6372
  /**
6268
6373
  * A single client-side change.
6374
+ *
6375
+ * @public
6269
6376
  */
6270
6377
  class CrudEntry {
6271
6378
  /**
@@ -6362,6 +6469,9 @@ class CrudEntry {
6362
6469
  }
6363
6470
  }
6364
6471
 
6472
+ /**
6473
+ * @public
6474
+ */
6365
6475
  class CrudTransaction extends CrudBatch {
6366
6476
  crud;
6367
6477
  complete;
@@ -6390,6 +6500,8 @@ class CrudTransaction extends CrudBatch {
6390
6500
  * Calls to Abortcontroller.abort(reason: any) will result in the
6391
6501
  * `reason` being thrown. This is not necessarily an error,
6392
6502
  * but extends error for better logging purposes.
6503
+ *
6504
+ * @internal
6393
6505
  */
6394
6506
  class AbortOperation extends Error {
6395
6507
  reason;
@@ -13560,7 +13672,7 @@ function requireDist () {
13560
13672
 
13561
13673
  var distExports = requireDist();
13562
13674
 
13563
- var version = "1.53.2";
13675
+ var version = "1.54.0";
13564
13676
  var PACKAGE = {
13565
13677
  version: version};
13566
13678
 
@@ -13690,7 +13802,8 @@ class WebsocketClientTransport {
13690
13802
  removeListeners();
13691
13803
  resolve(new WebsocketDuplexConnectionExports.WebsocketDuplexConnection(websocket, new distExports.Deserializer(), multiplexerDemultiplexerFactory));
13692
13804
  };
13693
- const errorListener = (ev) => {
13805
+ const errorListener = (event) => {
13806
+ const ev = event;
13694
13807
  removeListeners();
13695
13808
  // We add a default error in that case.
13696
13809
  if (ev.error != null) {
@@ -13933,7 +14046,13 @@ const SOCKET_TIMEOUT_MS = 30_000;
13933
14046
  // If there is a backlog of messages (for example on slow connections), keepalive messages could be delayed
13934
14047
  // significantly. Therefore this is longer than the socket timeout.
13935
14048
  const KEEP_ALIVE_LIFETIME_MS = 90_000;
14049
+ /**
14050
+ * @internal
14051
+ */
13936
14052
  const DEFAULT_REMOTE_LOGGER = Logger.get('PowerSyncRemote');
14053
+ /**
14054
+ * @public
14055
+ */
13937
14056
  var FetchStrategy;
13938
14057
  (function (FetchStrategy) {
13939
14058
  /**
@@ -13952,12 +14071,17 @@ var FetchStrategy;
13952
14071
  * The class wrapper is used to distinguish the fetchImplementation
13953
14072
  * option in [AbstractRemoteOptions] from the general fetch method
13954
14073
  * which is typeof "function"
14074
+ *
14075
+ * @internal
13955
14076
  */
13956
14077
  class FetchImplementationProvider {
13957
14078
  getFetch() {
13958
14079
  throw new Error('Unspecified fetch implementation');
13959
14080
  }
13960
14081
  }
14082
+ /**
14083
+ * @internal
14084
+ */
13961
14085
  const DEFAULT_REMOTE_OPTIONS = {
13962
14086
  socketUrlTransformer: (url) => url.replace(/^https?:\/\//, function (match) {
13963
14087
  return match === 'https://' ? 'wss://' : 'ws://';
@@ -13965,6 +14089,9 @@ const DEFAULT_REMOTE_OPTIONS = {
13965
14089
  fetchImplementation: new FetchImplementationProvider(),
13966
14090
  fetchOptions: {}
13967
14091
  };
14092
+ /**
14093
+ * @internal
14094
+ */
13968
14095
  class AbstractRemote {
13969
14096
  connector;
13970
14097
  logger;
@@ -14374,7 +14501,7 @@ class AbstractRemote {
14374
14501
  * Posts a `/sync/stream` request.
14375
14502
  *
14376
14503
  * Depending on the `Content-Type` of the response, this returns strings for sync lines or encoded BSON documents as
14377
- * {@link Uint8Array}s.
14504
+ * `Uint8Array`s.
14378
14505
  */
14379
14506
  async fetchStream(options) {
14380
14507
  const { isBson, stream } = await this.fetchStreamRaw(options);
@@ -14416,16 +14543,26 @@ function isInterruptingInstruction(instruction) {
14416
14543
  return 'EstablishSyncStream' in instruction || 'CloseSyncStream' in instruction;
14417
14544
  }
14418
14545
 
14546
+ /**
14547
+ * @internal
14548
+ */
14419
14549
  var LockType;
14420
14550
  (function (LockType) {
14421
14551
  LockType["CRUD"] = "crud";
14422
14552
  LockType["SYNC"] = "sync";
14423
14553
  })(LockType || (LockType = {}));
14554
+ /**
14555
+ * @public
14556
+ */
14424
14557
  var SyncStreamConnectionMethod;
14425
14558
  (function (SyncStreamConnectionMethod) {
14426
14559
  SyncStreamConnectionMethod["HTTP"] = "http";
14427
14560
  SyncStreamConnectionMethod["WEB_SOCKET"] = "web-socket";
14428
14561
  })(SyncStreamConnectionMethod || (SyncStreamConnectionMethod = {}));
14562
+ /**
14563
+ * @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
14564
+ * @public
14565
+ */
14429
14566
  var SyncClientImplementation;
14430
14567
  (function (SyncClientImplementation) {
14431
14568
  /**
@@ -14437,8 +14574,8 @@ var SyncClientImplementation;
14437
14574
  * ## Compatibility warning
14438
14575
  *
14439
14576
  * The Rust sync client stores sync data in a format that is slightly different than the one used
14440
- * by the old JavaScript client. When adopting the {@link RUST} client on existing databases, the PowerSync SDK will
14441
- * migrate the format automatically.
14577
+ * by the old JavaScript client. When adopting the {@link SyncClientImplementation.RUST} client on existing databases,
14578
+ * the PowerSync SDK will migrate the format automatically.
14442
14579
  *
14443
14580
  * SDK versions supporting both the JavaScript and the Rust client support both formats with the JavaScript client
14444
14581
  * implementaiton. However, downgrading to an SDK version that only supports the JavaScript client would not be
@@ -14448,14 +14585,29 @@ var SyncClientImplementation;
14448
14585
  })(SyncClientImplementation || (SyncClientImplementation = {}));
14449
14586
  /**
14450
14587
  * The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}.
14588
+ *
14589
+ * @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
14590
+ * @public
14451
14591
  */
14452
14592
  const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.RUST;
14593
+ /**
14594
+ * @internal
14595
+ */
14453
14596
  const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
14597
+ /**
14598
+ * @internal
14599
+ */
14454
14600
  const DEFAULT_RETRY_DELAY_MS = 5000;
14601
+ /**
14602
+ * @internal
14603
+ */
14455
14604
  const DEFAULT_STREAMING_SYNC_OPTIONS = {
14456
14605
  retryDelayMs: DEFAULT_RETRY_DELAY_MS,
14457
14606
  crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
14458
14607
  };
14608
+ /**
14609
+ * @internal
14610
+ */
14459
14611
  const DEFAULT_STREAM_CONNECTION_OPTIONS = {
14460
14612
  appMetadata: {},
14461
14613
  connectionMethod: SyncStreamConnectionMethod.WEB_SOCKET,
@@ -14465,6 +14617,9 @@ const DEFAULT_STREAM_CONNECTION_OPTIONS = {
14465
14617
  serializedSchema: undefined,
14466
14618
  includeDefaultStreams: true
14467
14619
  };
14620
+ /**
14621
+ * @internal
14622
+ */
14468
14623
  class AbstractStreamingSyncImplementation extends BaseObserver {
14469
14624
  options;
14470
14625
  abortController;
@@ -14788,7 +14943,7 @@ The next upload iteration will be delayed.`);
14788
14943
  this.handleActiveStreamsChange?.();
14789
14944
  }
14790
14945
  /**
14791
- * Older versions of the JS SDK used to encode subkeys as JSON in {@link OplogEntry.toJSON}.
14946
+ * Older versions of the JS SDK used to encode subkeys as JSON in `OplogEntry.toJSON`.
14792
14947
  * Because subkeys are always strings, this leads to quotes being added around them in `ps_oplog`.
14793
14948
  * While this is not a problem as long as it's done consistently, it causes issues when a database
14794
14949
  * created by the JS SDK is used with other SDKs, or (more likely) when the new Rust sync client
@@ -14798,7 +14953,7 @@ The next upload iteration will be delayed.`);
14798
14953
  * migration is only triggered when necessary (for now). The function returns whether the new format
14799
14954
  * should be used, so that the JS SDK is able to write to updated databases.
14800
14955
  *
14801
- * @param requireFixedKeyFormat Whether we require the new format or also support the old one.
14956
+ * @param requireFixedKeyFormat - Whether we require the new format or also support the old one.
14802
14957
  * The Rust client requires the new subkey format.
14803
14958
  * @returns Whether the database is now using the new, fixed subkey format.
14804
14959
  */
@@ -15105,7 +15260,8 @@ const MEMORY_TRIGGER_CLAIM_MANAGER = {
15105
15260
 
15106
15261
  /**
15107
15262
  * SQLite operations to track changes for with {@link TriggerManager}
15108
- * @experimental
15263
+ *
15264
+ * @experimental @alpha
15109
15265
  */
15110
15266
  var DiffTriggerOperation;
15111
15267
  (function (DiffTriggerOperation) {
@@ -15167,8 +15323,8 @@ class TriggerManagerImpl {
15167
15323
  get db() {
15168
15324
  return this.options.db;
15169
15325
  }
15170
- async getUUID() {
15171
- const { id: uuid } = await this.db.get(/* sql */ `
15326
+ async getUUID(ctx) {
15327
+ const { id: uuid } = await (ctx ?? this.db).get(/* sql */ `
15172
15328
  SELECT
15173
15329
  uuid () as id
15174
15330
  `);
@@ -15281,7 +15437,7 @@ class TriggerManagerImpl {
15281
15437
  const replicatedColumns = columns ?? sourceDefinition.columns.map((col) => col.name);
15282
15438
  const internalSource = sourceDefinition.internalName;
15283
15439
  const triggerIds = [];
15284
- const id = await this.getUUID();
15440
+ const id = await this.getUUID(setupContext);
15285
15441
  const releaseStorageClaim = useStorage ? await this.options.claimManager.obtainClaim(id) : null;
15286
15442
  /**
15287
15443
  * We default to replicating all columns if no columns array is provided.
@@ -15521,18 +15677,29 @@ const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
15521
15677
  const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
15522
15678
  clearLocal: true
15523
15679
  };
15680
+ /**
15681
+ * @internal
15682
+ */
15524
15683
  const DEFAULT_POWERSYNC_CLOSE_OPTIONS = {
15525
15684
  disconnect: true
15526
15685
  };
15686
+ /**
15687
+ * @internal
15688
+ */
15527
15689
  const DEFAULT_POWERSYNC_DB_OPTIONS = {
15528
15690
  retryDelayMs: 5000,
15529
15691
  crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
15530
15692
  };
15693
+ /**
15694
+ * @internal
15695
+ */
15531
15696
  const DEFAULT_CRUD_BATCH_LIMIT = 100;
15532
15697
  /**
15533
15698
  * Requesting nested or recursive locks can block the application in some circumstances.
15534
15699
  * This default lock timeout will act as a failsafe to throw an error if a lock cannot
15535
15700
  * be obtained.
15701
+ *
15702
+ * @internal
15536
15703
  */
15537
15704
  const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins
15538
15705
  /**
@@ -15542,6 +15709,9 @@ const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins
15542
15709
  const isPowerSyncDatabaseOptionsWithSettings = (test) => {
15543
15710
  return typeof test == 'object' && isSQLOpenOptions(test.database);
15544
15711
  };
15712
+ /**
15713
+ * @public
15714
+ */
15545
15715
  class AbstractPowerSyncDatabase extends BaseObserver {
15546
15716
  options;
15547
15717
  /**
@@ -15699,7 +15869,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15699
15869
  /**
15700
15870
  * Wait for the first sync operation to complete.
15701
15871
  *
15702
- * @param request Either an abort signal (after which the promise will complete regardless of
15872
+ * @param request - Either an abort signal (after which the promise will complete regardless of
15703
15873
  * whether a full sync was completed) or an object providing an abort signal and a priority target.
15704
15874
  * When a priority target is set, the promise may complete when all buckets with the given (or higher)
15705
15875
  * priorities have been synchronized. This can be earlier than a complete sync.
@@ -15854,7 +16024,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15854
16024
  /**
15855
16025
  * Close the sync connection.
15856
16026
  *
15857
- * Use {@link connect} to connect again.
16027
+ * Use {@link AbstractPowerSyncDatabase.connect} to connect again.
15858
16028
  */
15859
16029
  async disconnect() {
15860
16030
  return this.connectionManager.disconnect();
@@ -15881,8 +16051,8 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15881
16051
  /**
15882
16052
  * Create a sync stream to query its status or to subscribe to it.
15883
16053
  *
15884
- * @param name The name of the stream to subscribe to.
15885
- * @param params Optional parameters for the stream subscription.
16054
+ * @param name - The name of the stream to subscribe to.
16055
+ * @param params - Optional parameters for the stream subscription.
15886
16056
  * @returns A {@link SyncStream} instance that can be subscribed to.
15887
16057
  * @experimental Sync streams are currently in alpha.
15888
16058
  */
@@ -15940,14 +16110,14 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15940
16110
  * Once the data have been successfully uploaded, call {@link CrudBatch.complete} before
15941
16111
  * requesting the next batch.
15942
16112
  *
15943
- * Use {@link limit} to specify the maximum number of updates to return in a single
16113
+ * Use the `limit` parameter to specify the maximum number of updates to return in a single
15944
16114
  * batch.
15945
16115
  *
15946
16116
  * This method does include transaction ids in the result, but does not group
15947
16117
  * data by transaction. One batch may contain data from multiple transactions,
15948
16118
  * and a single transaction may be split over multiple batches.
15949
16119
  *
15950
- * @param limit Maximum number of CRUD entries to include in the batch
16120
+ * @param limit - Maximum number of CRUD entries to include in the batch
15951
16121
  * @returns A batch of CRUD operations to upload, or null if there are none
15952
16122
  */
15953
16123
  async getCrudBatch(limit = DEFAULT_CRUD_BATCH_LIMIT) {
@@ -15974,7 +16144,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15974
16144
  * Once the data have been successfully uploaded, call {@link CrudTransaction.complete} before
15975
16145
  * requesting the next transaction.
15976
16146
  *
15977
- * Unlike {@link getCrudBatch}, this only returns data from a single transaction at a time.
16147
+ * Unlike {@link AbstractPowerSyncDatabase.getCrudBatch}, this only returns data from a single transaction at a time.
15978
16148
  * All data for the transaction is loaded into memory.
15979
16149
  *
15980
16150
  * @returns A transaction of CRUD operations to upload, or null if there are none
@@ -15989,7 +16159,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15989
16159
  * This is typically used from the {@link PowerSyncBackendConnector.uploadData} callback. Each entry emitted by the
15990
16160
  * returned iterator is a full transaction containing all local writes made while that transaction was active.
15991
16161
  *
15992
- * Unlike {@link getNextCrudTransaction}, which always returns the oldest transaction that hasn't been
16162
+ * Unlike {@link AbstractPowerSyncDatabase.getNextCrudTransaction}, which always returns the oldest transaction that hasn't been
15993
16163
  * {@link CrudTransaction.complete}d yet, this iterator can be used to receive multiple transactions. Calling
15994
16164
  * {@link CrudTransaction.complete} will mark that and all prior transactions emitted by the iterator as completed.
15995
16165
  *
@@ -16083,8 +16253,8 @@ SELECT * FROM crud_entries;
16083
16253
  * the returned result's `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
16084
16254
  * Use a `RETURNING` clause and inspect `result.rows` when you need to confirm which rows changed.
16085
16255
  *
16086
- * @param sql The SQL query to execute
16087
- * @param parameters Optional array of parameters to bind to the query
16256
+ * @param sql - The SQL query to execute
16257
+ * @param parameters - Optional array of parameters to bind to the query
16088
16258
  * @returns The query result as an object with structured key-value pairs
16089
16259
  */
16090
16260
  async execute(sql, parameters) {
@@ -16094,8 +16264,8 @@ SELECT * FROM crud_entries;
16094
16264
  * Execute a SQL write (INSERT/UPDATE/DELETE) query directly on the database without any PowerSync processing.
16095
16265
  * This bypasses certain PowerSync abstractions and is useful for accessing the raw database results.
16096
16266
  *
16097
- * @param sql The SQL query to execute
16098
- * @param parameters Optional array of parameters to bind to the query
16267
+ * @param sql - The SQL query to execute
16268
+ * @param parameters - Optional array of parameters to bind to the query
16099
16269
  * @returns The raw query result from the underlying database as a nested array of raw values, where each row is
16100
16270
  * represented as an array of column values without field names.
16101
16271
  */
@@ -16108,8 +16278,8 @@ SELECT * FROM crud_entries;
16108
16278
  * and optionally return results.
16109
16279
  * This is faster than executing separately with each parameter set.
16110
16280
  *
16111
- * @param sql The SQL query to execute
16112
- * @param parameters Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
16281
+ * @param sql - The SQL query to execute
16282
+ * @param parameters - Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
16113
16283
  * @returns The query result
16114
16284
  */
16115
16285
  async executeBatch(sql, parameters) {
@@ -16119,8 +16289,8 @@ SELECT * FROM crud_entries;
16119
16289
  /**
16120
16290
  * Execute a read-only query and return results.
16121
16291
  *
16122
- * @param sql The SQL query to execute
16123
- * @param parameters Optional array of parameters to bind to the query
16292
+ * @param sql - The SQL query to execute
16293
+ * @param parameters - Optional array of parameters to bind to the query
16124
16294
  * @returns An array of results
16125
16295
  */
16126
16296
  async getAll(sql, parameters) {
@@ -16130,8 +16300,8 @@ SELECT * FROM crud_entries;
16130
16300
  /**
16131
16301
  * Execute a read-only query and return the first result, or null if the ResultSet is empty.
16132
16302
  *
16133
- * @param sql The SQL query to execute
16134
- * @param parameters Optional array of parameters to bind to the query
16303
+ * @param sql - The SQL query to execute
16304
+ * @param parameters - Optional array of parameters to bind to the query
16135
16305
  * @returns The first result if found, or null if no results are returned
16136
16306
  */
16137
16307
  async getOptional(sql, parameters) {
@@ -16141,8 +16311,8 @@ SELECT * FROM crud_entries;
16141
16311
  /**
16142
16312
  * Execute a read-only query and return the first result, error if the ResultSet is empty.
16143
16313
  *
16144
- * @param sql The SQL query to execute
16145
- * @param parameters Optional array of parameters to bind to the query
16314
+ * @param sql - The SQL query to execute
16315
+ * @param parameters - Optional array of parameters to bind to the query
16146
16316
  * @returns The first result matching the query
16147
16317
  * @throws Error if no rows are returned
16148
16318
  */
@@ -16152,7 +16322,7 @@ SELECT * FROM crud_entries;
16152
16322
  }
16153
16323
  /**
16154
16324
  * Takes a read lock, without starting a transaction.
16155
- * In most cases, {@link readTransaction} should be used instead.
16325
+ * In most cases, {@link AbstractPowerSyncDatabase.readTransaction} should be used instead.
16156
16326
  */
16157
16327
  async readLock(callback) {
16158
16328
  await this.waitForReady();
@@ -16160,7 +16330,7 @@ SELECT * FROM crud_entries;
16160
16330
  }
16161
16331
  /**
16162
16332
  * Takes a global lock, without starting a transaction.
16163
- * In most cases, {@link writeTransaction} should be used instead.
16333
+ * In most cases, {@link AbstractPowerSyncDatabase.writeTransaction} should be used instead.
16164
16334
  */
16165
16335
  async writeLock(callback) {
16166
16336
  await this.waitForReady();
@@ -16171,8 +16341,8 @@ SELECT * FROM crud_entries;
16171
16341
  * Read transactions can run concurrently to a write transaction.
16172
16342
  * Changes from any write transaction are not visible to read transactions started before it.
16173
16343
  *
16174
- * @param callback Function to execute within the transaction
16175
- * @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
16344
+ * @param callback - Function to execute within the transaction
16345
+ * @param lockTimeout - Time in milliseconds to wait for a lock before throwing an error
16176
16346
  * @returns The result of the callback
16177
16347
  * @throws Error if the lock cannot be obtained within the timeout period
16178
16348
  */
@@ -16189,8 +16359,8 @@ SELECT * FROM crud_entries;
16189
16359
  * This takes a global lock - only one write transaction can execute against the database at a time.
16190
16360
  * Statements within the transaction must be done on the provided {@link Transaction} interface.
16191
16361
  *
16192
- * @param callback Function to execute within the transaction
16193
- * @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
16362
+ * @param callback - Function to execute within the transaction
16363
+ * @param lockTimeout - Time in milliseconds to wait for a lock before throwing an error
16194
16364
  * @returns The result of the callback
16195
16365
  * @throws Error if the lock cannot be obtained within the timeout period
16196
16366
  */
@@ -16267,15 +16437,15 @@ SELECT * FROM crud_entries;
16267
16437
  }
16268
16438
  /**
16269
16439
  * Execute a read query every time the source tables are modified.
16270
- * Use {@link SQLWatchOptions.throttleMs} to specify the minimum interval between queries.
16440
+ * Use {@link SQLOnChangeOptions.throttleMs} to specify the minimum interval between queries.
16271
16441
  * Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
16272
16442
  *
16273
16443
  * Note that the `onChange` callback member of the handler is required.
16274
16444
  *
16275
- * @param sql The SQL query to execute
16276
- * @param parameters Optional array of parameters to bind to the query
16277
- * @param handler Callbacks for handling results and errors
16278
- * @param options Options for configuring watch behavior
16445
+ * @param sql - The SQL query to execute
16446
+ * @param parameters - Optional array of parameters to bind to the query
16447
+ * @param handler - Callbacks for handling results and errors
16448
+ * @param options - Options for configuring watch behavior
16279
16449
  */
16280
16450
  watchWithCallback(sql, parameters, handler, options) {
16281
16451
  const { onResult, onError = (e) => this.logger.error(e) } = handler ?? {};
@@ -16288,7 +16458,7 @@ SELECT * FROM crud_entries;
16288
16458
  const watchedQuery = new OnChangeQueryProcessor({
16289
16459
  db: this,
16290
16460
  comparator,
16291
- placeholderData: null,
16461
+ placeholderData: null, // FIXME
16292
16462
  watchOptions: {
16293
16463
  query: {
16294
16464
  compile: () => ({
@@ -16321,12 +16491,12 @@ SELECT * FROM crud_entries;
16321
16491
  }
16322
16492
  /**
16323
16493
  * Execute a read query every time the source tables are modified.
16324
- * Use {@link SQLWatchOptions.throttleMs} to specify the minimum interval between queries.
16494
+ * Use {@link SQLOnChangeOptions.throttleMs} to specify the minimum interval between queries.
16325
16495
  * Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
16326
16496
  *
16327
- * @param sql The SQL query to execute
16328
- * @param parameters Optional array of parameters to bind to the query
16329
- * @param options Options for configuring watch behavior
16497
+ * @param sql - The SQL query to execute
16498
+ * @param parameters - Optional array of parameters to bind to the query
16499
+ * @param options - Options for configuring watch behavior
16330
16500
  * @returns An AsyncIterable that yields QueryResults whenever the data changes
16331
16501
  */
16332
16502
  watchWithAsyncGenerator(sql, parameters, options) {
@@ -16350,9 +16520,9 @@ SELECT * FROM crud_entries;
16350
16520
  * If tables are specified in the options, those are used directly.
16351
16521
  * Otherwise, analyzes the query using EXPLAIN to determine which tables are accessed.
16352
16522
  *
16353
- * @param sql The SQL query to analyze
16354
- * @param parameters Optional parameters for the SQL query
16355
- * @param options Optional watch options that may contain explicit table list
16523
+ * @param sql - The SQL query to analyze
16524
+ * @param parameters - Optional parameters for the SQL query
16525
+ * @param options - Optional watch options that may contain explicit table list
16356
16526
  * @returns Array of table names that the query depends on
16357
16527
  */
16358
16528
  async resolveTables(sql, parameters, options) {
@@ -16381,13 +16551,13 @@ SELECT * FROM crud_entries;
16381
16551
  /**
16382
16552
  * Invoke the provided callback on any changes to any of the specified tables.
16383
16553
  *
16384
- * This is preferred over {@link watchWithCallback} when multiple queries need to be performed
16554
+ * This is preferred over {@link AbstractPowerSyncDatabase.watchWithCallback} when multiple queries need to be performed
16385
16555
  * together when data is changed.
16386
16556
  *
16387
16557
  * Note that the `onChange` callback member of the handler is required.
16388
16558
  *
16389
- * @param handler Callbacks for handling change events and errors
16390
- * @param options Options for configuring watch behavior
16559
+ * @param handler - Callbacks for handling change events and errors
16560
+ * @param options - Options for configuring watch behavior
16391
16561
  * @returns A dispose function to stop watching for changes
16392
16562
  */
16393
16563
  onChangeWithCallback(handler, options) {
@@ -16430,12 +16600,12 @@ SELECT * FROM crud_entries;
16430
16600
  /**
16431
16601
  * Create a Stream of changes to any of the specified tables.
16432
16602
  *
16433
- * This is preferred over {@link watchWithAsyncGenerator} when multiple queries need to be performed
16434
- * together when data is changed.
16603
+ * This is preferred over {@link AbstractPowerSyncDatabase.watchWithAsyncGenerator} when multiple queries need to be
16604
+ * performed together when data is changed.
16435
16605
  *
16436
16606
  * Note: do not declare this as `async *onChange` as it will not work in React Native.
16437
16607
  *
16438
- * @param options Options for configuring watch behavior
16608
+ * @param options - Options for configuring watch behavior
16439
16609
  * @returns An AsyncIterable that yields change events whenever the specified tables change
16440
16610
  */
16441
16611
  onChangeWithAsyncGenerator(options) {
@@ -16473,15 +16643,15 @@ SELECT * FROM crud_entries;
16473
16643
  changedTables.add(table);
16474
16644
  }
16475
16645
  }
16476
- /**
16477
- * @ignore
16478
- */
16479
16646
  async executeReadOnly(sql, params) {
16480
16647
  await this.waitForReady();
16481
16648
  return this.database.readLock((tx) => tx.execute(sql, params));
16482
16649
  }
16483
16650
  }
16484
16651
 
16652
+ /**
16653
+ * @internal
16654
+ */
16485
16655
  class AbstractPowerSyncDatabaseOpenFactory {
16486
16656
  options;
16487
16657
  constructor(options) {
@@ -16506,6 +16676,9 @@ class AbstractPowerSyncDatabaseOpenFactory {
16506
16676
  }
16507
16677
  }
16508
16678
 
16679
+ /**
16680
+ * @internal
16681
+ */
16509
16682
  function runOnSchemaChange(callback, db, options) {
16510
16683
  const triggerWatchedQuery = () => {
16511
16684
  const abortController = new AbortController();
@@ -16530,6 +16703,9 @@ function runOnSchemaChange(callback, db, options) {
16530
16703
  triggerWatchedQuery();
16531
16704
  }
16532
16705
 
16706
+ /**
16707
+ * @public
16708
+ */
16533
16709
  function compilableQueryWatch(db, query, handler, options) {
16534
16710
  const { onResult, onError = (e) => { } } = handler ?? {};
16535
16711
  if (!onResult) {
@@ -16567,8 +16743,14 @@ function compilableQueryWatch(db, query, handler, options) {
16567
16743
  runOnSchemaChange(watchQuery, db, options);
16568
16744
  }
16569
16745
 
16746
+ /**
16747
+ * @internal
16748
+ */
16570
16749
  const MAX_OP_ID = '9223372036854775807';
16571
16750
 
16751
+ /**
16752
+ * @internal
16753
+ */
16572
16754
  class SqliteBucketStorage extends BaseObserver {
16573
16755
  db;
16574
16756
  logger;
@@ -16729,6 +16911,8 @@ class SqliteBucketStorage extends BaseObserver {
16729
16911
  * Thrown when an underlying database connection is closed.
16730
16912
  * This is particularly relevant when worker connections are marked as closed while
16731
16913
  * operations are still in progress.
16914
+ *
16915
+ * @internal
16732
16916
  */
16733
16917
  class ConnectionClosedError extends Error {
16734
16918
  static NAME = 'ConnectionClosedError';
@@ -16748,6 +16932,8 @@ class ConnectionClosedError extends Error {
16748
16932
 
16749
16933
  /**
16750
16934
  * A schema is a collection of tables. It is used to define the structure of a database.
16935
+ *
16936
+ * @public
16751
16937
  */
16752
16938
  class Schema {
16753
16939
  /*
@@ -16784,7 +16970,7 @@ class Schema {
16784
16970
  * Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
16785
16971
  * using client-side table and column constraints.
16786
16972
  *
16787
- * @param tables An object of (table name, raw table definition) entries.
16973
+ * @param tables - An object of (table name, raw table definition) entries.
16788
16974
  */
16789
16975
  withRawTables(tables) {
16790
16976
  for (const [name, rawTableDefinition] of Object.entries(tables)) {
@@ -16830,6 +17016,8 @@ class Schema {
16830
17016
  Generate a new table from the columns and indexes
16831
17017
  @deprecated You should use {@link Table} instead as it now allows TableV2 syntax.
16832
17018
  This will be removed in the next major release.
17019
+
17020
+ @public
16833
17021
  */
16834
17022
  class TableV2 extends Table {
16835
17023
  }
@@ -16840,6 +17028,8 @@ function sanitizeString(input) {
16840
17028
  /**
16841
17029
  * Helper function for sanitizing UUID input strings.
16842
17030
  * Typically used with {@link sanitizeSQL}.
17031
+ *
17032
+ * @alpha
16843
17033
  */
16844
17034
  function sanitizeUUID(uuid) {
16845
17035
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
@@ -16876,6 +17066,8 @@ function sanitizeUUID(uuid) {
16876
17066
  * // Incorrect:
16877
17067
  * sanitizeSQL`New.id = '${myID}'` // Produces double quotes: New.id = ''O''Reilly''
16878
17068
  * ```
17069
+ *
17070
+ * @alpha
16879
17071
  */
16880
17072
  function sanitizeSQL(strings, ...values) {
16881
17073
  let result = '';
@@ -16905,6 +17097,8 @@ function sanitizeSQL(strings, ...values) {
16905
17097
 
16906
17098
  /**
16907
17099
  * Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
17100
+ *
17101
+ * @public
16908
17102
  */
16909
17103
  class GetAllQuery {
16910
17104
  options;
@@ -16929,6 +17123,9 @@ class GetAllQuery {
16929
17123
  }
16930
17124
 
16931
17125
  const TypedLogger = Logger;
17126
+ /**
17127
+ * @public
17128
+ */
16932
17129
  const LogLevel = {
16933
17130
  TRACE: TypedLogger.TRACE,
16934
17131
  DEBUG: TypedLogger.DEBUG,
@@ -16945,6 +17142,7 @@ const LogLevel = {
16945
17142
  * across all loggers created with `createLogger`. Adjusting settings on this
16946
17143
  * base logger affects all loggers derived from it unless explicitly overridden.
16947
17144
  *
17145
+ * @public
16948
17146
  */
16949
17147
  function createBaseLogger() {
16950
17148
  return Logger;
@@ -16955,6 +17153,8 @@ function createBaseLogger() {
16955
17153
  * Named loggers allow specific modules or areas of your application to have
16956
17154
  * their own logging levels and behaviors. These loggers inherit configuration
16957
17155
  * from the base logger by default but can override settings independently.
17156
+ *
17157
+ * @public
16958
17158
  */
16959
17159
  function createLogger(name, options = {}) {
16960
17160
  const logger = Logger.get(name);
@@ -16964,6 +17164,9 @@ function createLogger(name, options = {}) {
16964
17164
  return logger;
16965
17165
  }
16966
17166
 
17167
+ /**
17168
+ * @internal
17169
+ */
16967
17170
  const parseQuery = (query, parameters) => {
16968
17171
  let sqlStatement;
16969
17172
  if (typeof query == 'string') {