@powersync/common 1.53.1 → 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.cjs +560 -353
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +560 -353
- package/dist/bundle.mjs.map +1 -1
- package/dist/bundle.node.cjs +560 -353
- package/dist/bundle.node.cjs.map +1 -1
- package/dist/bundle.node.mjs +560 -353
- package/dist/bundle.node.mjs.map +1 -1
- package/dist/index.d.cts +733 -198
- package/lib/attachments/AttachmentContext.d.ts +7 -6
- package/lib/attachments/AttachmentContext.js +2 -1
- package/lib/attachments/AttachmentContext.js.map +1 -1
- package/lib/attachments/AttachmentErrorHandler.d.ts +6 -6
- package/lib/attachments/AttachmentQueue.d.ts +61 -20
- package/lib/attachments/AttachmentQueue.js +16 -18
- package/lib/attachments/AttachmentQueue.js.map +1 -1
- package/lib/attachments/LocalStorageAdapter.d.ts +14 -8
- package/lib/attachments/LocalStorageAdapter.js +3 -0
- package/lib/attachments/LocalStorageAdapter.js.map +1 -1
- package/lib/attachments/RemoteStorageAdapter.d.ts +4 -4
- package/lib/attachments/Schema.d.ts +12 -4
- package/lib/attachments/Schema.js +8 -3
- package/lib/attachments/Schema.js.map +1 -1
- package/lib/attachments/WatchedAttachmentItem.d.ts +3 -1
- package/lib/client/AbstractPowerSyncDatabase.d.ts +110 -58
- package/lib/client/AbstractPowerSyncDatabase.js +59 -48
- package/lib/client/AbstractPowerSyncDatabase.js.map +1 -1
- package/lib/client/AbstractPowerSyncOpenFactory.d.ts +6 -0
- package/lib/client/AbstractPowerSyncOpenFactory.js +3 -0
- package/lib/client/AbstractPowerSyncOpenFactory.js.map +1 -1
- package/lib/client/ConnectionManager.d.ts +4 -1
- package/lib/client/ConnectionManager.js +1 -1
- package/lib/client/ConnectionManager.js.map +1 -1
- package/lib/client/Query.d.ts +9 -0
- package/lib/client/SQLOpenFactory.d.ts +12 -0
- package/lib/client/SQLOpenFactory.js +6 -0
- package/lib/client/SQLOpenFactory.js.map +1 -1
- package/lib/client/compilableQueryWatch.d.ts +6 -0
- package/lib/client/compilableQueryWatch.js +3 -0
- package/lib/client/compilableQueryWatch.js.map +1 -1
- package/lib/client/connection/PowerSyncBackendConnector.d.ts +3 -0
- package/lib/client/connection/PowerSyncCredentials.d.ts +3 -0
- package/lib/client/constants.d.ts +3 -0
- package/lib/client/constants.js +3 -0
- package/lib/client/constants.js.map +1 -1
- package/lib/client/runOnSchemaChange.d.ts +3 -0
- package/lib/client/runOnSchemaChange.js +3 -0
- package/lib/client/runOnSchemaChange.js.map +1 -1
- package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +12 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js +6 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -1
- package/lib/client/sync/bucket/CrudBatch.d.ts +2 -0
- package/lib/client/sync/bucket/CrudBatch.js +2 -0
- package/lib/client/sync/bucket/CrudBatch.js.map +1 -1
- package/lib/client/sync/bucket/CrudEntry.d.ts +9 -0
- package/lib/client/sync/bucket/CrudEntry.js +4 -0
- package/lib/client/sync/bucket/CrudEntry.js.map +1 -1
- package/lib/client/sync/bucket/CrudTransaction.d.ts +3 -0
- package/lib/client/sync/bucket/CrudTransaction.js +3 -0
- package/lib/client/sync/bucket/CrudTransaction.js.map +1 -1
- package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +3 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.js +3 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -1
- package/lib/client/sync/stream/AbstractRemote.d.ts +30 -1
- package/lib/client/sync/stream/AbstractRemote.js +15 -1
- package/lib/client/sync/stream/AbstractRemote.js.map +1 -1
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +61 -14
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +60 -47
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -1
- package/lib/client/sync/stream/JsonValue.d.ts +3 -0
- package/lib/client/sync/stream/WebsocketClientTransport.js +2 -1
- package/lib/client/sync/stream/WebsocketClientTransport.js.map +1 -1
- package/lib/client/sync/sync-streams.d.ts +22 -7
- package/lib/client/triggers/TriggerManager.d.ts +19 -18
- package/lib/client/triggers/TriggerManager.js +2 -1
- package/lib/client/triggers/TriggerManager.js.map +1 -1
- package/lib/client/triggers/TriggerManagerImpl.d.ts +1 -1
- package/lib/client/triggers/TriggerManagerImpl.js +3 -3
- package/lib/client/triggers/TriggerManagerImpl.js.map +1 -1
- package/lib/client/triggers/sanitizeSQL.d.ts +4 -0
- package/lib/client/triggers/sanitizeSQL.js +4 -0
- package/lib/client/triggers/sanitizeSQL.js.map +1 -1
- package/lib/client/watched/GetAllQuery.d.ts +4 -0
- package/lib/client/watched/GetAllQuery.js +2 -0
- package/lib/client/watched/GetAllQuery.js.map +1 -1
- package/lib/client/watched/WatchedQuery.d.ts +24 -2
- package/lib/client/watched/WatchedQuery.js +9 -0
- package/lib/client/watched/WatchedQuery.js.map +1 -1
- package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +1 -1
- package/lib/client/watched/processors/AbstractQueryProcessor.js.map +1 -1
- package/lib/client/watched/processors/DifferentialQueryProcessor.d.ts +20 -0
- package/lib/client/watched/processors/DifferentialQueryProcessor.js +4 -0
- package/lib/client/watched/processors/DifferentialQueryProcessor.js.map +1 -1
- package/lib/client/watched/processors/OnChangeQueryProcessor.d.ts +4 -0
- package/lib/client/watched/processors/OnChangeQueryProcessor.js.map +1 -1
- package/lib/client/watched/processors/comparators.d.ts +8 -0
- package/lib/client/watched/processors/comparators.js +4 -0
- package/lib/client/watched/processors/comparators.js.map +1 -1
- package/lib/db/ConnectionClosedError.d.ts +2 -0
- package/lib/db/ConnectionClosedError.js +2 -0
- package/lib/db/ConnectionClosedError.js.map +1 -1
- package/lib/db/DBAdapter.d.ts +56 -6
- package/lib/db/DBAdapter.js +15 -3
- package/lib/db/DBAdapter.js.map +1 -1
- package/lib/db/crud/SyncProgress.d.ts +6 -1
- package/lib/db/crud/SyncProgress.js +2 -0
- package/lib/db/crud/SyncProgress.js.map +1 -1
- package/lib/db/crud/SyncStatus.d.ts +36 -38
- package/lib/db/crud/SyncStatus.js +19 -14
- package/lib/db/crud/SyncStatus.js.map +1 -1
- package/lib/db/crud/UploadQueueStatus.d.ts +3 -0
- package/lib/db/crud/UploadQueueStatus.js +3 -0
- package/lib/db/crud/UploadQueueStatus.js.map +1 -1
- package/lib/db/schema/Column.d.ts +28 -0
- package/lib/db/schema/Column.js +16 -3
- package/lib/db/schema/Column.js.map +1 -1
- package/lib/db/schema/Index.d.ts +9 -0
- package/lib/db/schema/Index.js +6 -0
- package/lib/db/schema/Index.js.map +1 -1
- package/lib/db/schema/IndexedColumn.d.ts +9 -0
- package/lib/db/schema/IndexedColumn.js +6 -0
- package/lib/db/schema/IndexedColumn.js.map +1 -1
- package/lib/db/schema/RawTable.d.ts +7 -1
- package/lib/db/schema/Schema.d.ts +6 -1
- package/lib/db/schema/Schema.js +3 -1
- package/lib/db/schema/Schema.js.map +1 -1
- package/lib/db/schema/Table.d.ts +27 -3
- package/lib/db/schema/Table.js +9 -0
- package/lib/db/schema/Table.js.map +1 -1
- package/lib/db/schema/TableV2.d.ts +2 -0
- package/lib/db/schema/TableV2.js +2 -0
- package/lib/db/schema/TableV2.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/types/types.d.ts +6 -0
- package/lib/utils/AbortOperation.d.ts +2 -0
- package/lib/utils/AbortOperation.js +2 -0
- package/lib/utils/AbortOperation.js.map +1 -1
- package/lib/utils/BaseObserver.d.ts +12 -0
- package/lib/utils/BaseObserver.js +3 -0
- package/lib/utils/BaseObserver.js.map +1 -1
- package/lib/utils/ControlledExecutor.d.ts +6 -0
- package/lib/utils/ControlledExecutor.js +3 -0
- package/lib/utils/ControlledExecutor.js.map +1 -1
- package/lib/utils/Logger.d.ts +9 -0
- package/lib/utils/Logger.js +6 -0
- package/lib/utils/Logger.js.map +1 -1
- package/lib/utils/async.d.ts +13 -7
- package/lib/utils/async.js +38 -24
- package/lib/utils/async.js.map +1 -1
- package/lib/utils/mutex.d.ts +8 -0
- package/lib/utils/mutex.js +3 -0
- package/lib/utils/mutex.js.map +1 -1
- package/lib/utils/parseQuery.d.ts +6 -0
- package/lib/utils/parseQuery.js +3 -0
- package/lib/utils/parseQuery.js.map +1 -1
- package/lib/utils/stream_transform.d.ts +3 -1
- package/lib/utils/stream_transform.js.map +1 -1
- package/package.json +3 -2
- package/src/attachments/AttachmentContext.ts +7 -6
- package/src/attachments/AttachmentErrorHandler.ts +6 -6
- package/src/attachments/AttachmentQueue.ts +71 -23
- package/src/attachments/LocalStorageAdapter.ts +14 -8
- package/src/attachments/README.md +2 -0
- package/src/attachments/RemoteStorageAdapter.ts +4 -4
- package/src/attachments/Schema.ts +12 -4
- package/src/attachments/WatchedAttachmentItem.ts +3 -1
- package/src/client/AbstractPowerSyncDatabase.ts +117 -62
- package/src/client/AbstractPowerSyncOpenFactory.ts +6 -0
- package/src/client/ConnectionManager.ts +4 -1
- package/src/client/Query.ts +9 -0
- package/src/client/SQLOpenFactory.ts +12 -0
- package/src/client/compilableQueryWatch.ts +6 -0
- package/src/client/connection/PowerSyncBackendConnector.ts +3 -0
- package/src/client/connection/PowerSyncCredentials.ts +3 -0
- package/src/client/constants.ts +3 -0
- package/src/client/runOnSchemaChange.ts +3 -0
- package/src/client/sync/bucket/BucketStorageAdapter.ts +12 -0
- package/src/client/sync/bucket/CrudBatch.ts +2 -0
- package/src/client/sync/bucket/CrudEntry.ts +9 -0
- package/src/client/sync/bucket/CrudTransaction.ts +3 -0
- package/src/client/sync/bucket/SqliteBucketStorage.ts +3 -0
- package/src/client/sync/stream/AbstractRemote.ts +30 -1
- package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +86 -59
- package/src/client/sync/stream/JsonValue.ts +3 -0
- package/src/client/sync/stream/WebsocketClientTransport.ts +3 -1
- package/src/client/sync/sync-streams.ts +22 -9
- package/src/client/triggers/TriggerManager.ts +19 -18
- package/src/client/triggers/TriggerManagerImpl.ts +5 -5
- package/src/client/triggers/sanitizeSQL.ts +5 -0
- package/src/client/watched/GetAllQuery.ts +5 -1
- package/src/client/watched/WatchedQuery.ts +24 -2
- package/src/client/watched/processors/AbstractQueryProcessor.ts +6 -6
- package/src/client/watched/processors/DifferentialQueryProcessor.ts +28 -5
- package/src/client/watched/processors/OnChangeQueryProcessor.ts +9 -3
- package/src/client/watched/processors/comparators.ts +8 -0
- package/src/db/ConnectionClosedError.ts +2 -0
- package/src/db/DBAdapter.ts +58 -6
- package/src/db/crud/SyncProgress.ts +6 -1
- package/src/db/crud/SyncStatus.ts +40 -21
- package/src/db/crud/UploadQueueStatus.ts +3 -0
- package/src/db/schema/Column.ts +28 -3
- package/src/db/schema/Index.ts +9 -0
- package/src/db/schema/IndexedColumn.ts +9 -0
- package/src/db/schema/RawTable.ts +7 -1
- package/src/db/schema/Schema.ts +8 -3
- package/src/db/schema/Table.ts +30 -5
- package/src/db/schema/TableV2.ts +2 -0
- package/src/index.ts +1 -1
- package/src/types/types.ts +6 -0
- package/src/utils/AbortOperation.ts +2 -0
- package/src/utils/BaseObserver.ts +12 -0
- package/src/utils/ControlledExecutor.ts +6 -0
- package/src/utils/Logger.ts +9 -0
- package/src/utils/async.ts +51 -24
- package/src/utils/mutex.ts +12 -0
- package/src/utils/parseQuery.ts +6 -0
- package/src/utils/stream_transform.ts +3 -1
package/dist/bundle.cjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @see https://www.sqlite.org/lang_expr.html#castexpr
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
4
7
|
exports.ColumnType = void 0;
|
|
5
8
|
(function (ColumnType) {
|
|
6
9
|
ColumnType["TEXT"] = "TEXT";
|
|
@@ -16,14 +19,24 @@ const integer = {
|
|
|
16
19
|
const real = {
|
|
17
20
|
type: exports.ColumnType.REAL
|
|
18
21
|
};
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
/**
|
|
23
|
+
* powersync-sqlite-core limits the number of column per table to 1999, due to internal SQLite limits.
|
|
24
|
+
* In earlier versions this was limited to 63.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
21
28
|
const MAX_AMOUNT_OF_COLUMNS = 1999;
|
|
29
|
+
/**
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
22
32
|
const column = {
|
|
23
33
|
text,
|
|
24
34
|
integer,
|
|
25
35
|
real
|
|
26
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
27
40
|
class Column {
|
|
28
41
|
options;
|
|
29
42
|
constructor(options) {
|
|
@@ -43,9 +56,15 @@ class Column {
|
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
|
|
59
|
+
/**
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
46
62
|
const DEFAULT_INDEX_COLUMN_OPTIONS = {
|
|
47
63
|
ascending: true
|
|
48
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
49
68
|
class IndexedColumn {
|
|
50
69
|
options;
|
|
51
70
|
static createAscending(column) {
|
|
@@ -72,9 +91,15 @@ class IndexedColumn {
|
|
|
72
91
|
}
|
|
73
92
|
}
|
|
74
93
|
|
|
94
|
+
/**
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
75
97
|
const DEFAULT_INDEX_OPTIONS = {
|
|
76
98
|
columns: []
|
|
77
99
|
};
|
|
100
|
+
/**
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
78
103
|
class Index {
|
|
79
104
|
options;
|
|
80
105
|
static createAscending(options, columnNames) {
|
|
@@ -116,6 +141,9 @@ function encodeTableOptions(options) {
|
|
|
116
141
|
};
|
|
117
142
|
}
|
|
118
143
|
|
|
144
|
+
/**
|
|
145
|
+
* @internal
|
|
146
|
+
*/
|
|
119
147
|
const DEFAULT_TABLE_OPTIONS = {
|
|
120
148
|
indexes: [],
|
|
121
149
|
insertOnly: false,
|
|
@@ -124,7 +152,13 @@ const DEFAULT_TABLE_OPTIONS = {
|
|
|
124
152
|
trackMetadata: false,
|
|
125
153
|
ignoreEmptyUpdates: false
|
|
126
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
127
158
|
const InvalidSQLCharacters = /["'%,.#\s[\]]/;
|
|
159
|
+
/**
|
|
160
|
+
* @public
|
|
161
|
+
*/
|
|
128
162
|
class Table {
|
|
129
163
|
options;
|
|
130
164
|
_mappedColumns;
|
|
@@ -315,6 +349,11 @@ class Table {
|
|
|
315
349
|
}
|
|
316
350
|
}
|
|
317
351
|
|
|
352
|
+
/**
|
|
353
|
+
* The default name of the local table storing attachment data.
|
|
354
|
+
*
|
|
355
|
+
* @alpha
|
|
356
|
+
*/
|
|
318
357
|
const ATTACHMENT_TABLE = 'attachments';
|
|
319
358
|
/**
|
|
320
359
|
* Maps a database row to an AttachmentRecord.
|
|
@@ -322,7 +361,7 @@ const ATTACHMENT_TABLE = 'attachments';
|
|
|
322
361
|
* @param row - The database row object
|
|
323
362
|
* @returns The corresponding AttachmentRecord
|
|
324
363
|
*
|
|
325
|
-
* @
|
|
364
|
+
* @alpha
|
|
326
365
|
*/
|
|
327
366
|
function attachmentFromSql(row) {
|
|
328
367
|
return {
|
|
@@ -340,7 +379,7 @@ function attachmentFromSql(row) {
|
|
|
340
379
|
/**
|
|
341
380
|
* AttachmentState represents the current synchronization state of an attachment.
|
|
342
381
|
*
|
|
343
|
-
* @
|
|
382
|
+
* @alpha
|
|
344
383
|
*/
|
|
345
384
|
exports.AttachmentState = void 0;
|
|
346
385
|
(function (AttachmentState) {
|
|
@@ -353,7 +392,7 @@ exports.AttachmentState = void 0;
|
|
|
353
392
|
/**
|
|
354
393
|
* AttachmentTable defines the schema for the attachment queue table.
|
|
355
394
|
*
|
|
356
|
-
* @
|
|
395
|
+
* @alpha
|
|
357
396
|
*/
|
|
358
397
|
class AttachmentTable extends Table {
|
|
359
398
|
constructor(options) {
|
|
@@ -381,7 +420,8 @@ class AttachmentTable extends Table {
|
|
|
381
420
|
* Provides methods to query, insert, update, and delete attachment records with
|
|
382
421
|
* proper transaction management through PowerSync.
|
|
383
422
|
*
|
|
384
|
-
* @
|
|
423
|
+
* @experimental
|
|
424
|
+
* @alpha
|
|
385
425
|
*/
|
|
386
426
|
class AttachmentContext {
|
|
387
427
|
/** PowerSync database instance for executing queries */
|
|
@@ -603,6 +643,9 @@ class AttachmentContext {
|
|
|
603
643
|
}
|
|
604
644
|
}
|
|
605
645
|
|
|
646
|
+
/**
|
|
647
|
+
* @public
|
|
648
|
+
*/
|
|
606
649
|
exports.WatchedQueryListenerEvent = void 0;
|
|
607
650
|
(function (WatchedQueryListenerEvent) {
|
|
608
651
|
WatchedQueryListenerEvent["ON_DATA"] = "onData";
|
|
@@ -611,176 +654,18 @@ exports.WatchedQueryListenerEvent = void 0;
|
|
|
611
654
|
WatchedQueryListenerEvent["SETTINGS_WILL_UPDATE"] = "settingsWillUpdate";
|
|
612
655
|
WatchedQueryListenerEvent["CLOSED"] = "closed";
|
|
613
656
|
})(exports.WatchedQueryListenerEvent || (exports.WatchedQueryListenerEvent = {}));
|
|
657
|
+
/**
|
|
658
|
+
* @internal
|
|
659
|
+
*/
|
|
614
660
|
const DEFAULT_WATCH_THROTTLE_MS = 30;
|
|
661
|
+
/**
|
|
662
|
+
* @internal
|
|
663
|
+
*/
|
|
615
664
|
const DEFAULT_WATCH_QUERY_OPTIONS = {
|
|
616
665
|
throttleMs: DEFAULT_WATCH_THROTTLE_MS,
|
|
617
666
|
reportFetching: true
|
|
618
667
|
};
|
|
619
668
|
|
|
620
|
-
/**
|
|
621
|
-
* Orchestrates attachment synchronization between local and remote storage.
|
|
622
|
-
* Handles uploads, downloads, deletions, and state transitions.
|
|
623
|
-
*
|
|
624
|
-
* @internal
|
|
625
|
-
*/
|
|
626
|
-
class SyncingService {
|
|
627
|
-
attachmentService;
|
|
628
|
-
localStorage;
|
|
629
|
-
remoteStorage;
|
|
630
|
-
logger;
|
|
631
|
-
errorHandler;
|
|
632
|
-
constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
|
|
633
|
-
this.attachmentService = attachmentService;
|
|
634
|
-
this.localStorage = localStorage;
|
|
635
|
-
this.remoteStorage = remoteStorage;
|
|
636
|
-
this.logger = logger;
|
|
637
|
-
this.errorHandler = errorHandler;
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
* Processes attachments based on their state (upload, download, or delete).
|
|
641
|
-
* All updates are saved in a single batch after processing.
|
|
642
|
-
*
|
|
643
|
-
* @param attachments - Array of attachment records to process
|
|
644
|
-
* @param context - Attachment context for database operations
|
|
645
|
-
* @returns Promise that resolves when all attachments have been processed and saved
|
|
646
|
-
*/
|
|
647
|
-
async processAttachments(attachments, context) {
|
|
648
|
-
const updatedAttachments = [];
|
|
649
|
-
for (const attachment of attachments) {
|
|
650
|
-
switch (attachment.state) {
|
|
651
|
-
case exports.AttachmentState.QUEUED_UPLOAD:
|
|
652
|
-
const uploaded = await this.uploadAttachment(attachment);
|
|
653
|
-
updatedAttachments.push(uploaded);
|
|
654
|
-
break;
|
|
655
|
-
case exports.AttachmentState.QUEUED_DOWNLOAD:
|
|
656
|
-
const downloaded = await this.downloadAttachment(attachment);
|
|
657
|
-
updatedAttachments.push(downloaded);
|
|
658
|
-
break;
|
|
659
|
-
case exports.AttachmentState.QUEUED_DELETE:
|
|
660
|
-
const deleted = await this.deleteAttachment(attachment, context);
|
|
661
|
-
updatedAttachments.push(deleted);
|
|
662
|
-
break;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
await context.saveAttachments(updatedAttachments);
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
* Uploads an attachment from local storage to remote storage.
|
|
669
|
-
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
670
|
-
*
|
|
671
|
-
* @param attachment - The attachment record to upload
|
|
672
|
-
* @returns Updated attachment record with new state
|
|
673
|
-
* @throws Error if the attachment has no localUri
|
|
674
|
-
*/
|
|
675
|
-
async uploadAttachment(attachment) {
|
|
676
|
-
this.logger.info(`Uploading attachment ${attachment.filename}`);
|
|
677
|
-
try {
|
|
678
|
-
if (attachment.localUri == null) {
|
|
679
|
-
throw new Error(`No localUri for attachment ${attachment.id}`);
|
|
680
|
-
}
|
|
681
|
-
const fileBlob = await this.localStorage.readFile(attachment.localUri);
|
|
682
|
-
await this.remoteStorage.uploadFile(fileBlob, attachment);
|
|
683
|
-
return {
|
|
684
|
-
...attachment,
|
|
685
|
-
state: exports.AttachmentState.SYNCED,
|
|
686
|
-
hasSynced: true
|
|
687
|
-
};
|
|
688
|
-
}
|
|
689
|
-
catch (error) {
|
|
690
|
-
const shouldRetry = (await this.errorHandler?.onUploadError(attachment, error)) ?? true;
|
|
691
|
-
if (!shouldRetry) {
|
|
692
|
-
return {
|
|
693
|
-
...attachment,
|
|
694
|
-
state: exports.AttachmentState.ARCHIVED
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
return attachment;
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Downloads an attachment from remote storage to local storage.
|
|
702
|
-
* Retrieves the file, converts to base64, and saves locally.
|
|
703
|
-
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
704
|
-
*
|
|
705
|
-
* @param attachment - The attachment record to download
|
|
706
|
-
* @returns Updated attachment record with local URI and new state
|
|
707
|
-
*/
|
|
708
|
-
async downloadAttachment(attachment) {
|
|
709
|
-
this.logger.info(`Downloading attachment ${attachment.filename}`);
|
|
710
|
-
try {
|
|
711
|
-
const fileData = await this.remoteStorage.downloadFile(attachment);
|
|
712
|
-
const localUri = this.localStorage.getLocalUri(attachment.filename);
|
|
713
|
-
await this.localStorage.saveFile(localUri, fileData);
|
|
714
|
-
return {
|
|
715
|
-
...attachment,
|
|
716
|
-
state: exports.AttachmentState.SYNCED,
|
|
717
|
-
localUri: localUri,
|
|
718
|
-
hasSynced: true
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
catch (error) {
|
|
722
|
-
const shouldRetry = (await this.errorHandler?.onDownloadError(attachment, error)) ?? true;
|
|
723
|
-
if (!shouldRetry) {
|
|
724
|
-
return {
|
|
725
|
-
...attachment,
|
|
726
|
-
state: exports.AttachmentState.ARCHIVED
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
return attachment;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
/**
|
|
733
|
-
* Deletes an attachment from both remote and local storage.
|
|
734
|
-
* Removes the remote file, local file (if exists), and the attachment record.
|
|
735
|
-
* On failure, defers to error handler or archives.
|
|
736
|
-
*
|
|
737
|
-
* @param attachment - The attachment record to delete
|
|
738
|
-
* @param context - Attachment context for database operations
|
|
739
|
-
* @returns Updated attachment record
|
|
740
|
-
*/
|
|
741
|
-
async deleteAttachment(attachment, context) {
|
|
742
|
-
try {
|
|
743
|
-
await this.remoteStorage.deleteFile(attachment);
|
|
744
|
-
if (attachment.localUri) {
|
|
745
|
-
await this.localStorage.deleteFile(attachment.localUri);
|
|
746
|
-
}
|
|
747
|
-
await context.deleteAttachment(attachment.id);
|
|
748
|
-
return {
|
|
749
|
-
...attachment,
|
|
750
|
-
state: exports.AttachmentState.ARCHIVED
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
catch (error) {
|
|
754
|
-
const shouldRetry = (await this.errorHandler?.onDeleteError(attachment, error)) ?? true;
|
|
755
|
-
if (!shouldRetry) {
|
|
756
|
-
return {
|
|
757
|
-
...attachment,
|
|
758
|
-
state: exports.AttachmentState.ARCHIVED
|
|
759
|
-
};
|
|
760
|
-
}
|
|
761
|
-
return attachment;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* Performs cleanup of archived attachments by removing their local files and records.
|
|
766
|
-
* Errors during local file deletion are logged but do not prevent record deletion.
|
|
767
|
-
*/
|
|
768
|
-
async deleteArchivedAttachments(context) {
|
|
769
|
-
return await context.deleteArchivedAttachments(async (archivedAttachments) => {
|
|
770
|
-
for (const attachment of archivedAttachments) {
|
|
771
|
-
if (attachment.localUri) {
|
|
772
|
-
try {
|
|
773
|
-
await this.localStorage.deleteFile(attachment.localUri);
|
|
774
|
-
}
|
|
775
|
-
catch (error) {
|
|
776
|
-
this.logger.error('Error deleting local file for archived attachment', error);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
669
|
/**
|
|
785
670
|
* A simple fixed-capacity queue implementation.
|
|
786
671
|
*
|
|
@@ -966,6 +851,9 @@ class Mutex {
|
|
|
966
851
|
}
|
|
967
852
|
}
|
|
968
853
|
}
|
|
854
|
+
/**
|
|
855
|
+
* @internal
|
|
856
|
+
*/
|
|
969
857
|
function timeoutSignal(timeout) {
|
|
970
858
|
if (timeout == null)
|
|
971
859
|
return;
|
|
@@ -994,36 +882,200 @@ class AttachmentService {
|
|
|
994
882
|
this.context = new AttachmentContext(db, tableName, logger, archivedCacheLimit);
|
|
995
883
|
}
|
|
996
884
|
/**
|
|
997
|
-
* Creates a differential watch query for active attachments requiring synchronization.
|
|
998
|
-
* @returns Watch query that emits changes for queued uploads, downloads, and deletes
|
|
885
|
+
* Creates a differential watch query for active attachments requiring synchronization.
|
|
886
|
+
* @returns Watch query that emits changes for queued uploads, downloads, and deletes
|
|
887
|
+
*/
|
|
888
|
+
watchActiveAttachments({ throttleMs } = {}) {
|
|
889
|
+
this.logger.info('Watching active attachments...');
|
|
890
|
+
const watch = this.db
|
|
891
|
+
.query({
|
|
892
|
+
sql: /* sql */ `
|
|
893
|
+
SELECT
|
|
894
|
+
*
|
|
895
|
+
FROM
|
|
896
|
+
${this.tableName}
|
|
897
|
+
WHERE
|
|
898
|
+
state = ?
|
|
899
|
+
OR state = ?
|
|
900
|
+
OR state = ?
|
|
901
|
+
ORDER BY
|
|
902
|
+
timestamp ASC
|
|
903
|
+
`,
|
|
904
|
+
parameters: [exports.AttachmentState.QUEUED_UPLOAD, exports.AttachmentState.QUEUED_DOWNLOAD, exports.AttachmentState.QUEUED_DELETE]
|
|
905
|
+
})
|
|
906
|
+
.differentialWatch({ throttleMs });
|
|
907
|
+
return watch;
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Executes a callback with exclusive access to the attachment context.
|
|
911
|
+
*/
|
|
912
|
+
async withContext(callback) {
|
|
913
|
+
return this.mutex.runExclusive(async () => {
|
|
914
|
+
return callback(this.context);
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Orchestrates attachment synchronization between local and remote storage.
|
|
921
|
+
* Handles uploads, downloads, deletions, and state transitions.
|
|
922
|
+
*
|
|
923
|
+
* @internal
|
|
924
|
+
*/
|
|
925
|
+
class SyncingService {
|
|
926
|
+
attachmentService;
|
|
927
|
+
localStorage;
|
|
928
|
+
remoteStorage;
|
|
929
|
+
logger;
|
|
930
|
+
errorHandler;
|
|
931
|
+
constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
|
|
932
|
+
this.attachmentService = attachmentService;
|
|
933
|
+
this.localStorage = localStorage;
|
|
934
|
+
this.remoteStorage = remoteStorage;
|
|
935
|
+
this.logger = logger;
|
|
936
|
+
this.errorHandler = errorHandler;
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Processes attachments based on their state (upload, download, or delete).
|
|
940
|
+
* All updates are saved in a single batch after processing.
|
|
941
|
+
*
|
|
942
|
+
* @param attachments - Array of attachment records to process
|
|
943
|
+
* @param context - Attachment context for database operations
|
|
944
|
+
* @returns Promise that resolves when all attachments have been processed and saved
|
|
945
|
+
*/
|
|
946
|
+
async processAttachments(attachments, context) {
|
|
947
|
+
const updatedAttachments = [];
|
|
948
|
+
for (const attachment of attachments) {
|
|
949
|
+
switch (attachment.state) {
|
|
950
|
+
case exports.AttachmentState.QUEUED_UPLOAD:
|
|
951
|
+
const uploaded = await this.uploadAttachment(attachment);
|
|
952
|
+
updatedAttachments.push(uploaded);
|
|
953
|
+
break;
|
|
954
|
+
case exports.AttachmentState.QUEUED_DOWNLOAD:
|
|
955
|
+
const downloaded = await this.downloadAttachment(attachment);
|
|
956
|
+
updatedAttachments.push(downloaded);
|
|
957
|
+
break;
|
|
958
|
+
case exports.AttachmentState.QUEUED_DELETE:
|
|
959
|
+
const deleted = await this.deleteAttachment(attachment, context);
|
|
960
|
+
updatedAttachments.push(deleted);
|
|
961
|
+
break;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
await context.saveAttachments(updatedAttachments);
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Uploads an attachment from local storage to remote storage.
|
|
968
|
+
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
969
|
+
*
|
|
970
|
+
* @param attachment - The attachment record to upload
|
|
971
|
+
* @returns Updated attachment record with new state
|
|
972
|
+
* @throws Error if the attachment has no localUri
|
|
973
|
+
*/
|
|
974
|
+
async uploadAttachment(attachment) {
|
|
975
|
+
this.logger.info(`Uploading attachment ${attachment.filename}`);
|
|
976
|
+
try {
|
|
977
|
+
if (attachment.localUri == null) {
|
|
978
|
+
throw new Error(`No localUri for attachment ${attachment.id}`);
|
|
979
|
+
}
|
|
980
|
+
const fileBlob = await this.localStorage.readFile(attachment.localUri);
|
|
981
|
+
await this.remoteStorage.uploadFile(fileBlob, attachment);
|
|
982
|
+
return {
|
|
983
|
+
...attachment,
|
|
984
|
+
state: exports.AttachmentState.SYNCED,
|
|
985
|
+
hasSynced: true
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
catch (error) {
|
|
989
|
+
const shouldRetry = (await this.errorHandler?.onUploadError(attachment, error)) ?? true;
|
|
990
|
+
if (!shouldRetry) {
|
|
991
|
+
return {
|
|
992
|
+
...attachment,
|
|
993
|
+
state: exports.AttachmentState.ARCHIVED
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
return attachment;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Downloads an attachment from remote storage to local storage.
|
|
1001
|
+
* Retrieves the file, converts to base64, and saves locally.
|
|
1002
|
+
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
1003
|
+
*
|
|
1004
|
+
* @param attachment - The attachment record to download
|
|
1005
|
+
* @returns Updated attachment record with local URI and new state
|
|
1006
|
+
*/
|
|
1007
|
+
async downloadAttachment(attachment) {
|
|
1008
|
+
this.logger.info(`Downloading attachment ${attachment.filename}`);
|
|
1009
|
+
try {
|
|
1010
|
+
const fileData = await this.remoteStorage.downloadFile(attachment);
|
|
1011
|
+
const localUri = this.localStorage.getLocalUri(attachment.filename);
|
|
1012
|
+
await this.localStorage.saveFile(localUri, fileData);
|
|
1013
|
+
return {
|
|
1014
|
+
...attachment,
|
|
1015
|
+
state: exports.AttachmentState.SYNCED,
|
|
1016
|
+
localUri: localUri,
|
|
1017
|
+
hasSynced: true
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
catch (error) {
|
|
1021
|
+
const shouldRetry = (await this.errorHandler?.onDownloadError(attachment, error)) ?? true;
|
|
1022
|
+
if (!shouldRetry) {
|
|
1023
|
+
return {
|
|
1024
|
+
...attachment,
|
|
1025
|
+
state: exports.AttachmentState.ARCHIVED
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
return attachment;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Deletes an attachment from both remote and local storage.
|
|
1033
|
+
* Removes the remote file, local file (if exists), and the attachment record.
|
|
1034
|
+
* On failure, defers to error handler or archives.
|
|
1035
|
+
*
|
|
1036
|
+
* @param attachment - The attachment record to delete
|
|
1037
|
+
* @param context - Attachment context for database operations
|
|
1038
|
+
* @returns Updated attachment record
|
|
999
1039
|
*/
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
.
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1040
|
+
async deleteAttachment(attachment, context) {
|
|
1041
|
+
try {
|
|
1042
|
+
await this.remoteStorage.deleteFile(attachment);
|
|
1043
|
+
if (attachment.localUri) {
|
|
1044
|
+
await this.localStorage.deleteFile(attachment.localUri);
|
|
1045
|
+
}
|
|
1046
|
+
await context.deleteAttachment(attachment.id);
|
|
1047
|
+
return {
|
|
1048
|
+
...attachment,
|
|
1049
|
+
state: exports.AttachmentState.ARCHIVED
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
catch (error) {
|
|
1053
|
+
const shouldRetry = (await this.errorHandler?.onDeleteError(attachment, error)) ?? true;
|
|
1054
|
+
if (!shouldRetry) {
|
|
1055
|
+
return {
|
|
1056
|
+
...attachment,
|
|
1057
|
+
state: exports.AttachmentState.ARCHIVED
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
return attachment;
|
|
1061
|
+
}
|
|
1020
1062
|
}
|
|
1021
1063
|
/**
|
|
1022
|
-
*
|
|
1064
|
+
* Performs cleanup of archived attachments by removing their local files and records.
|
|
1065
|
+
* Errors during local file deletion are logged but do not prevent record deletion.
|
|
1023
1066
|
*/
|
|
1024
|
-
async
|
|
1025
|
-
return
|
|
1026
|
-
|
|
1067
|
+
async deleteArchivedAttachments(context) {
|
|
1068
|
+
return await context.deleteArchivedAttachments(async (archivedAttachments) => {
|
|
1069
|
+
for (const attachment of archivedAttachments) {
|
|
1070
|
+
if (attachment.localUri) {
|
|
1071
|
+
try {
|
|
1072
|
+
await this.localStorage.deleteFile(attachment.localUri);
|
|
1073
|
+
}
|
|
1074
|
+
catch (error) {
|
|
1075
|
+
this.logger.error('Error deleting local file for archived attachment', error);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1027
1079
|
});
|
|
1028
1080
|
}
|
|
1029
1081
|
}
|
|
@@ -1084,16 +1136,6 @@ class AttachmentQueue {
|
|
|
1084
1136
|
* Creates a new AttachmentQueue instance.
|
|
1085
1137
|
*
|
|
1086
1138
|
* @param options - Configuration options
|
|
1087
|
-
* @param options.db - PowerSync database instance
|
|
1088
|
-
* @param options.remoteStorage - Remote storage adapter for upload/download operations
|
|
1089
|
-
* @param options.localStorage - Local storage adapter for file persistence
|
|
1090
|
-
* @param options.watchAttachments - Callback for monitoring attachment changes in your data model
|
|
1091
|
-
* @param options.tableName - Name of the table to store attachment records. Default: 'ps_attachment_queue'
|
|
1092
|
-
* @param options.logger - Logger instance. Defaults to db.logger
|
|
1093
|
-
* @param options.syncIntervalMs - Periodic polling interval in milliseconds for retrying failed uploads/downloads. Default: 30000
|
|
1094
|
-
* @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
|
|
1095
|
-
* @param options.downloadAttachments - Whether to automatically download remote attachments. Default: true
|
|
1096
|
-
* @param options.archivedCacheLimit - Maximum archived attachments before cleanup. Default: 100
|
|
1097
1139
|
*/
|
|
1098
1140
|
constructor({ db, localStorage, remoteStorage, watchAttachments, logger, tableName = ATTACHMENT_TABLE, syncIntervalMs = 30 * 1000, syncThrottleDuration = DEFAULT_WATCH_THROTTLE_MS, downloadAttachments = true, archivedCacheLimit = 100, errorHandler }) {
|
|
1099
1141
|
this.db = db;
|
|
@@ -1182,6 +1224,7 @@ class AttachmentQueue {
|
|
|
1182
1224
|
state: exports.AttachmentState.QUEUED_DOWNLOAD,
|
|
1183
1225
|
hasSynced: false,
|
|
1184
1226
|
metaData: watchedAttachment.metaData,
|
|
1227
|
+
mediaType: watchedAttachment.mediaType,
|
|
1185
1228
|
timestamp: new Date().getTime()
|
|
1186
1229
|
});
|
|
1187
1230
|
continue;
|
|
@@ -1269,17 +1312,24 @@ class AttachmentQueue {
|
|
|
1269
1312
|
this.statusListenerDispose = undefined;
|
|
1270
1313
|
}
|
|
1271
1314
|
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Provides an {@link AttachmentContext} to a callback.
|
|
1317
|
+
*
|
|
1318
|
+
* The callback runs while the attachment queue mutex is held. Do not call
|
|
1319
|
+
* other {@link AttachmentQueue} methods from within the callback, as they may
|
|
1320
|
+
* attempt to acquire the same mutex and block indefinitely.
|
|
1321
|
+
*/
|
|
1322
|
+
withAttachmentContext(callback) {
|
|
1323
|
+
/**
|
|
1324
|
+
* AttachmentService is internal and private in this class.
|
|
1325
|
+
* We only need to expose its locking and context functionality for extending classes.
|
|
1326
|
+
*/
|
|
1327
|
+
return this.attachmentService.withContext(callback);
|
|
1328
|
+
}
|
|
1272
1329
|
/**
|
|
1273
1330
|
* Saves a file to local storage and queues it for upload to remote storage.
|
|
1274
1331
|
*
|
|
1275
1332
|
* @param options - File save options
|
|
1276
|
-
* @param options.data - The file data as ArrayBuffer, Blob, or base64 string
|
|
1277
|
-
* @param options.fileExtension - File extension (e.g., 'jpg', 'pdf')
|
|
1278
|
-
* @param options.mediaType - MIME type of the file (e.g., 'image/jpeg')
|
|
1279
|
-
* @param options.metaData - Optional metadata to associate with the attachment
|
|
1280
|
-
* @param options.id - Optional custom ID. If not provided, a UUID will be generated
|
|
1281
|
-
* @param options.updateHook - Optional callback to execute additional database operations
|
|
1282
|
-
* within the same transaction as the attachment creation
|
|
1283
1333
|
* @returns Promise resolving to the created attachment record
|
|
1284
1334
|
*/
|
|
1285
1335
|
async saveFile({ data, fileExtension, mediaType, metaData, id, updateHook }) {
|
|
@@ -1392,6 +1442,9 @@ class AttachmentQueue {
|
|
|
1392
1442
|
}
|
|
1393
1443
|
}
|
|
1394
1444
|
|
|
1445
|
+
/**
|
|
1446
|
+
* @alpha
|
|
1447
|
+
*/
|
|
1395
1448
|
exports.EncodingType = void 0;
|
|
1396
1449
|
(function (EncodingType) {
|
|
1397
1450
|
EncodingType["UTF8"] = "utf8";
|
|
@@ -1855,7 +1908,9 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
|
|
|
1855
1908
|
* different SQLite DB implementations.
|
|
1856
1909
|
*/
|
|
1857
1910
|
/**
|
|
1858
|
-
* Implements {@link DBGetUtils} on a {@link
|
|
1911
|
+
* Implements {@link DBGetUtils} on a {@link SqlExecutor}.
|
|
1912
|
+
*
|
|
1913
|
+
* @internal
|
|
1859
1914
|
*/
|
|
1860
1915
|
function DBGetUtilsDefaultMixin(Base) {
|
|
1861
1916
|
return class extends Base {
|
|
@@ -1899,6 +1954,8 @@ function DBGetUtilsDefaultMixin(Base) {
|
|
|
1899
1954
|
}
|
|
1900
1955
|
/**
|
|
1901
1956
|
* Update table operation numbers from SQLite
|
|
1957
|
+
*
|
|
1958
|
+
* @public
|
|
1902
1959
|
*/
|
|
1903
1960
|
exports.RowUpdateType = void 0;
|
|
1904
1961
|
(function (RowUpdateType) {
|
|
@@ -1907,8 +1964,10 @@ exports.RowUpdateType = void 0;
|
|
|
1907
1964
|
RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
|
|
1908
1965
|
})(exports.RowUpdateType || (exports.RowUpdateType = {}));
|
|
1909
1966
|
/**
|
|
1910
|
-
* A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool
|
|
1911
|
-
* {@link ConnectionPool
|
|
1967
|
+
* A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool#readLock} and
|
|
1968
|
+
* {@link ConnectionPool#writeLock}.
|
|
1969
|
+
*
|
|
1970
|
+
* @internal
|
|
1912
1971
|
*/
|
|
1913
1972
|
function DBAdapterDefaultMixin(Base) {
|
|
1914
1973
|
return class extends Base {
|
|
@@ -1996,9 +2055,15 @@ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction)
|
|
|
1996
2055
|
}
|
|
1997
2056
|
}
|
|
1998
2057
|
}
|
|
2058
|
+
/**
|
|
2059
|
+
* @internal
|
|
2060
|
+
*/
|
|
1999
2061
|
function isBatchedUpdateNotification(update) {
|
|
2000
2062
|
return 'tables' in update;
|
|
2001
2063
|
}
|
|
2064
|
+
/**
|
|
2065
|
+
* @internal
|
|
2066
|
+
*/
|
|
2002
2067
|
function extractTableUpdates(update) {
|
|
2003
2068
|
return isBatchedUpdateNotification(update) ? update.tables : [update.table];
|
|
2004
2069
|
}
|
|
@@ -2026,6 +2091,8 @@ const FULL_SYNC_PRIORITY = 2147483647;
|
|
|
2026
2091
|
*
|
|
2027
2092
|
* Also note that data is downloaded in bulk, which means that individual counters are unlikely
|
|
2028
2093
|
* to be updated one-by-one.
|
|
2094
|
+
*
|
|
2095
|
+
* @public
|
|
2029
2096
|
*/
|
|
2030
2097
|
class SyncProgress {
|
|
2031
2098
|
internal;
|
|
@@ -2064,6 +2131,9 @@ class SyncProgress {
|
|
|
2064
2131
|
}
|
|
2065
2132
|
}
|
|
2066
2133
|
|
|
2134
|
+
/**
|
|
2135
|
+
* @public
|
|
2136
|
+
*/
|
|
2067
2137
|
class SyncStatus {
|
|
2068
2138
|
options;
|
|
2069
2139
|
constructor(options) {
|
|
@@ -2074,6 +2144,8 @@ class SyncStatus {
|
|
|
2074
2144
|
* implementation).
|
|
2075
2145
|
*
|
|
2076
2146
|
* This information is only available after a connection has been requested.
|
|
2147
|
+
*
|
|
2148
|
+
* @deprecated This always returns the Rust client (the only option).
|
|
2077
2149
|
*/
|
|
2078
2150
|
get clientImplementation() {
|
|
2079
2151
|
return this.options.clientImplementation;
|
|
@@ -2081,7 +2153,7 @@ class SyncStatus {
|
|
|
2081
2153
|
/**
|
|
2082
2154
|
* Indicates if the client is currently connected to the PowerSync service.
|
|
2083
2155
|
*
|
|
2084
|
-
* @returns
|
|
2156
|
+
* @returns True if connected, false otherwise. Defaults to false if not specified.
|
|
2085
2157
|
*/
|
|
2086
2158
|
get connected() {
|
|
2087
2159
|
return this.options.connected ?? false;
|
|
@@ -2089,7 +2161,7 @@ class SyncStatus {
|
|
|
2089
2161
|
/**
|
|
2090
2162
|
* Indicates if the client is in the process of establishing a connection to the PowerSync service.
|
|
2091
2163
|
*
|
|
2092
|
-
* @returns
|
|
2164
|
+
* @returns True if connecting, false otherwise. Defaults to false if not specified.
|
|
2093
2165
|
*/
|
|
2094
2166
|
get connecting() {
|
|
2095
2167
|
return this.options.connecting ?? false;
|
|
@@ -2098,7 +2170,7 @@ class SyncStatus {
|
|
|
2098
2170
|
* Time that a last sync has fully completed, if any.
|
|
2099
2171
|
* This timestamp is reset to null after a restart of the PowerSync service.
|
|
2100
2172
|
*
|
|
2101
|
-
* @returns
|
|
2173
|
+
* @returns The timestamp of the last successful sync, or undefined if no sync has completed.
|
|
2102
2174
|
*/
|
|
2103
2175
|
get lastSyncedAt() {
|
|
2104
2176
|
return this.options.lastSyncedAt;
|
|
@@ -2106,7 +2178,7 @@ class SyncStatus {
|
|
|
2106
2178
|
/**
|
|
2107
2179
|
* Indicates whether there has been at least one full sync completed since initialization.
|
|
2108
2180
|
*
|
|
2109
|
-
* @returns
|
|
2181
|
+
* @returns True if at least one sync has completed, false if no sync has completed,
|
|
2110
2182
|
* or undefined when the state is still being loaded from the database.
|
|
2111
2183
|
*/
|
|
2112
2184
|
get hasSynced() {
|
|
@@ -2115,10 +2187,10 @@ class SyncStatus {
|
|
|
2115
2187
|
/**
|
|
2116
2188
|
* Provides the current data flow status regarding uploads and downloads.
|
|
2117
2189
|
*
|
|
2118
|
-
* @returns
|
|
2190
|
+
* @returns An object containing:
|
|
2119
2191
|
* - downloading: True if actively downloading changes (only when connected is also true)
|
|
2120
2192
|
* - uploading: True if actively uploading changes
|
|
2121
|
-
* Defaults to {downloading: false, uploading: false} if not specified.
|
|
2193
|
+
* Defaults to `{downloading: false, uploading: false}` if not specified.
|
|
2122
2194
|
*/
|
|
2123
2195
|
get dataFlowStatus() {
|
|
2124
2196
|
return (this.options.dataFlow ?? {
|
|
@@ -2143,7 +2215,7 @@ class SyncStatus {
|
|
|
2143
2215
|
return this.options.dataFlow?.internalStreamSubscriptions?.map((core) => new SyncStreamStatusView(this, core));
|
|
2144
2216
|
}
|
|
2145
2217
|
/**
|
|
2146
|
-
* If the `stream` appears in {@link syncStreams}, returns the current status for that stream.
|
|
2218
|
+
* If the `stream` appears in {@link SyncStatus.syncStreams}, returns the current status for that stream.
|
|
2147
2219
|
*/
|
|
2148
2220
|
forStream(stream) {
|
|
2149
2221
|
const asJson = JSON.stringify(stream.parameters);
|
|
@@ -2153,7 +2225,7 @@ class SyncStatus {
|
|
|
2153
2225
|
/**
|
|
2154
2226
|
* Provides sync status information for all bucket priorities, sorted by priority (highest first).
|
|
2155
2227
|
*
|
|
2156
|
-
* @returns
|
|
2228
|
+
* @returns An array of status entries for different sync priority levels,
|
|
2157
2229
|
* sorted with highest priorities (lower numbers) first.
|
|
2158
2230
|
*/
|
|
2159
2231
|
get priorityStatusEntries() {
|
|
@@ -2188,8 +2260,8 @@ class SyncStatus {
|
|
|
2188
2260
|
* For example, if PowerSync just finished synchronizing buckets in priority level 3, calling this method
|
|
2189
2261
|
* with a priority of 1 may return information for priority level 3.
|
|
2190
2262
|
*
|
|
2191
|
-
* @param
|
|
2192
|
-
* @returns
|
|
2263
|
+
* @param priority - The bucket priority for which the status should be reported
|
|
2264
|
+
* @returns Status information for the requested priority level or the next higher level with available status
|
|
2193
2265
|
*/
|
|
2194
2266
|
statusForPriority(priority) {
|
|
2195
2267
|
// priorityStatusEntries are sorted by ascending priorities (so higher numbers to lower numbers).
|
|
@@ -2210,8 +2282,8 @@ class SyncStatus {
|
|
|
2210
2282
|
* Compares this SyncStatus instance with another to determine if they are equal.
|
|
2211
2283
|
* Equality is determined by comparing the serialized JSON representation of both instances.
|
|
2212
2284
|
*
|
|
2213
|
-
* @param
|
|
2214
|
-
* @returns
|
|
2285
|
+
* @param status - The SyncStatus instance to compare against
|
|
2286
|
+
* @returns True if the instances are considered equal, false otherwise
|
|
2215
2287
|
*/
|
|
2216
2288
|
isEqual(status) {
|
|
2217
2289
|
/**
|
|
@@ -2234,7 +2306,7 @@ class SyncStatus {
|
|
|
2234
2306
|
* Creates a human-readable string representation of the current sync status.
|
|
2235
2307
|
* Includes information about connection state, sync completion, and data flow.
|
|
2236
2308
|
*
|
|
2237
|
-
* @returns
|
|
2309
|
+
* @returns A string representation of the sync status
|
|
2238
2310
|
*/
|
|
2239
2311
|
getMessage() {
|
|
2240
2312
|
const dataFlow = this.dataFlowStatus;
|
|
@@ -2243,7 +2315,7 @@ class SyncStatus {
|
|
|
2243
2315
|
/**
|
|
2244
2316
|
* Serializes the SyncStatus instance to a plain object.
|
|
2245
2317
|
*
|
|
2246
|
-
* @returns
|
|
2318
|
+
* @returns A plain object representation of the sync status
|
|
2247
2319
|
*/
|
|
2248
2320
|
toJSON() {
|
|
2249
2321
|
return {
|
|
@@ -2309,6 +2381,9 @@ class SyncStreamStatusView {
|
|
|
2309
2381
|
}
|
|
2310
2382
|
}
|
|
2311
2383
|
|
|
2384
|
+
/**
|
|
2385
|
+
* @public
|
|
2386
|
+
*/
|
|
2312
2387
|
class UploadQueueStats {
|
|
2313
2388
|
count;
|
|
2314
2389
|
size;
|
|
@@ -2334,6 +2409,9 @@ class UploadQueueStats {
|
|
|
2334
2409
|
}
|
|
2335
2410
|
}
|
|
2336
2411
|
|
|
2412
|
+
/**
|
|
2413
|
+
* @internal
|
|
2414
|
+
*/
|
|
2337
2415
|
class BaseObserver {
|
|
2338
2416
|
listeners = new Set();
|
|
2339
2417
|
constructor() { }
|
|
@@ -2361,6 +2439,9 @@ class BaseObserver {
|
|
|
2361
2439
|
}
|
|
2362
2440
|
}
|
|
2363
2441
|
|
|
2442
|
+
/**
|
|
2443
|
+
* @internal
|
|
2444
|
+
*/
|
|
2364
2445
|
class ControlledExecutor {
|
|
2365
2446
|
task;
|
|
2366
2447
|
/**
|
|
@@ -2430,30 +2511,44 @@ function throttleTrailing(func, wait) {
|
|
|
2430
2511
|
}
|
|
2431
2512
|
};
|
|
2432
2513
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2514
|
+
function asyncNotifier() {
|
|
2515
|
+
let waitingConsumer = null;
|
|
2516
|
+
let hasPendingNotification = false;
|
|
2517
|
+
return {
|
|
2518
|
+
notify() {
|
|
2519
|
+
if (waitingConsumer != null) {
|
|
2520
|
+
waitingConsumer();
|
|
2521
|
+
waitingConsumer = null;
|
|
2522
|
+
}
|
|
2523
|
+
else {
|
|
2524
|
+
hasPendingNotification = true;
|
|
2525
|
+
}
|
|
2526
|
+
},
|
|
2527
|
+
waitForNotification(signal) {
|
|
2528
|
+
return new Promise((resolve) => {
|
|
2529
|
+
if (waitingConsumer != null) {
|
|
2530
|
+
throw new Error('Illegal call to waitForNotification, already has a waiter.');
|
|
2531
|
+
}
|
|
2532
|
+
if (signal.aborted) {
|
|
2533
|
+
resolve();
|
|
2534
|
+
}
|
|
2535
|
+
else if (hasPendingNotification) {
|
|
2536
|
+
resolve();
|
|
2537
|
+
hasPendingNotification = false;
|
|
2538
|
+
}
|
|
2539
|
+
else {
|
|
2540
|
+
function complete() {
|
|
2541
|
+
signal.removeEventListener('abort', onAbort);
|
|
2542
|
+
resolve();
|
|
2543
|
+
}
|
|
2544
|
+
function onAbort() {
|
|
2545
|
+
waitingConsumer = null;
|
|
2546
|
+
resolve();
|
|
2547
|
+
}
|
|
2548
|
+
waitingConsumer = complete;
|
|
2549
|
+
signal.addEventListener('abort', onAbort);
|
|
2550
|
+
}
|
|
2551
|
+
});
|
|
2457
2552
|
}
|
|
2458
2553
|
};
|
|
2459
2554
|
}
|
|
@@ -2614,7 +2709,7 @@ class ConnectionManager extends BaseObserver {
|
|
|
2614
2709
|
/**
|
|
2615
2710
|
* Close the sync connection.
|
|
2616
2711
|
*
|
|
2617
|
-
* Use {@link connect} to connect again.
|
|
2712
|
+
* Use {@link ConnectionManager.connect} to connect again.
|
|
2618
2713
|
*/
|
|
2619
2714
|
async disconnect() {
|
|
2620
2715
|
// This will help abort pending connects
|
|
@@ -2754,6 +2849,8 @@ const _finalizer = 'FinalizationRegistry' in globalThis
|
|
|
2754
2849
|
/**
|
|
2755
2850
|
* An efficient comparator for {@link WatchedQuery} created with {@link Query#watch}. This has the ability to determine if a query
|
|
2756
2851
|
* result has changes without necessarily processing all items in the result.
|
|
2852
|
+
*
|
|
2853
|
+
* @public
|
|
2757
2854
|
*/
|
|
2758
2855
|
class ArrayComparator {
|
|
2759
2856
|
options;
|
|
@@ -2781,6 +2878,8 @@ class ArrayComparator {
|
|
|
2781
2878
|
}
|
|
2782
2879
|
/**
|
|
2783
2880
|
* Watched query comparator that always reports changed result sets.
|
|
2881
|
+
*
|
|
2882
|
+
* @public
|
|
2784
2883
|
*/
|
|
2785
2884
|
const FalsyComparator = {
|
|
2786
2885
|
checkEquality: () => false // Default comparator that always returns false
|
|
@@ -2988,6 +3087,8 @@ class AbstractQueryProcessor extends MetaBaseObserver {
|
|
|
2988
3087
|
/**
|
|
2989
3088
|
* An empty differential result set.
|
|
2990
3089
|
* This is used as the initial state for differential incrementally watched queries.
|
|
3090
|
+
*
|
|
3091
|
+
* @internal
|
|
2991
3092
|
*/
|
|
2992
3093
|
const EMPTY_DIFFERENTIAL = {
|
|
2993
3094
|
added: [],
|
|
@@ -3000,6 +3101,8 @@ const EMPTY_DIFFERENTIAL = {
|
|
|
3000
3101
|
* Default implementation of the {@link DifferentialWatchedQueryComparator} for watched queries.
|
|
3001
3102
|
* It keys items by their `id` property if available, alternatively it uses JSON stringification
|
|
3002
3103
|
* of the entire item for the key and comparison.
|
|
3104
|
+
*
|
|
3105
|
+
* @internal
|
|
3003
3106
|
*/
|
|
3004
3107
|
const DEFAULT_ROW_COMPARATOR = {
|
|
3005
3108
|
keyBy: (item) => {
|
|
@@ -3280,6 +3383,8 @@ class CustomQuery {
|
|
|
3280
3383
|
|
|
3281
3384
|
/**
|
|
3282
3385
|
* Tests if the input is a {@link SQLOpenOptions}
|
|
3386
|
+
*
|
|
3387
|
+
* @internal
|
|
3283
3388
|
*/
|
|
3284
3389
|
const isSQLOpenOptions = (test) => {
|
|
3285
3390
|
// typeof null is `object`, but you cannot use the `in` operator on `null.
|
|
@@ -3287,17 +3392,24 @@ const isSQLOpenOptions = (test) => {
|
|
|
3287
3392
|
};
|
|
3288
3393
|
/**
|
|
3289
3394
|
* Tests if input is a {@link SQLOpenFactory}
|
|
3395
|
+
*
|
|
3396
|
+
* @internal
|
|
3290
3397
|
*/
|
|
3291
3398
|
const isSQLOpenFactory = (test) => {
|
|
3292
3399
|
return typeof test?.openDB == 'function';
|
|
3293
3400
|
};
|
|
3294
3401
|
/**
|
|
3295
3402
|
* Tests if input is a {@link DBAdapter}
|
|
3403
|
+
*
|
|
3404
|
+
* @internal
|
|
3296
3405
|
*/
|
|
3297
3406
|
const isDBAdapter = (test) => {
|
|
3298
3407
|
return typeof test?.writeTransaction == 'function';
|
|
3299
3408
|
};
|
|
3300
3409
|
|
|
3410
|
+
/**
|
|
3411
|
+
* @internal
|
|
3412
|
+
*/
|
|
3301
3413
|
exports.PSInternalTable = void 0;
|
|
3302
3414
|
(function (PSInternalTable) {
|
|
3303
3415
|
PSInternalTable["DATA"] = "ps_data";
|
|
@@ -3306,6 +3418,9 @@ exports.PSInternalTable = void 0;
|
|
|
3306
3418
|
PSInternalTable["OPLOG"] = "ps_oplog";
|
|
3307
3419
|
PSInternalTable["UNTYPED"] = "ps_untyped";
|
|
3308
3420
|
})(exports.PSInternalTable || (exports.PSInternalTable = {}));
|
|
3421
|
+
/**
|
|
3422
|
+
* @internal
|
|
3423
|
+
*/
|
|
3309
3424
|
exports.PowerSyncControlCommand = void 0;
|
|
3310
3425
|
(function (PowerSyncControlCommand) {
|
|
3311
3426
|
PowerSyncControlCommand["PROCESS_TEXT_LINE"] = "line_text";
|
|
@@ -3323,6 +3438,8 @@ exports.PowerSyncControlCommand = void 0;
|
|
|
3323
3438
|
|
|
3324
3439
|
/**
|
|
3325
3440
|
* A batch of client-side changes.
|
|
3441
|
+
*
|
|
3442
|
+
* @public
|
|
3326
3443
|
*/
|
|
3327
3444
|
class CrudBatch {
|
|
3328
3445
|
crud;
|
|
@@ -3349,6 +3466,8 @@ class CrudBatch {
|
|
|
3349
3466
|
|
|
3350
3467
|
/**
|
|
3351
3468
|
* Type of local change.
|
|
3469
|
+
*
|
|
3470
|
+
* @public
|
|
3352
3471
|
*/
|
|
3353
3472
|
exports.UpdateType = void 0;
|
|
3354
3473
|
(function (UpdateType) {
|
|
@@ -3361,6 +3480,8 @@ exports.UpdateType = void 0;
|
|
|
3361
3480
|
})(exports.UpdateType || (exports.UpdateType = {}));
|
|
3362
3481
|
/**
|
|
3363
3482
|
* A single client-side change.
|
|
3483
|
+
*
|
|
3484
|
+
* @public
|
|
3364
3485
|
*/
|
|
3365
3486
|
class CrudEntry {
|
|
3366
3487
|
/**
|
|
@@ -3457,6 +3578,9 @@ class CrudEntry {
|
|
|
3457
3578
|
}
|
|
3458
3579
|
}
|
|
3459
3580
|
|
|
3581
|
+
/**
|
|
3582
|
+
* @public
|
|
3583
|
+
*/
|
|
3460
3584
|
class CrudTransaction extends CrudBatch {
|
|
3461
3585
|
crud;
|
|
3462
3586
|
complete;
|
|
@@ -3485,6 +3609,8 @@ class CrudTransaction extends CrudBatch {
|
|
|
3485
3609
|
* Calls to Abortcontroller.abort(reason: any) will result in the
|
|
3486
3610
|
* `reason` being thrown. This is not necessarily an error,
|
|
3487
3611
|
* but extends error for better logging purposes.
|
|
3612
|
+
*
|
|
3613
|
+
* @internal
|
|
3488
3614
|
*/
|
|
3489
3615
|
class AbortOperation extends Error {
|
|
3490
3616
|
reason;
|
|
@@ -10655,7 +10781,7 @@ function requireDist () {
|
|
|
10655
10781
|
|
|
10656
10782
|
var distExports = requireDist();
|
|
10657
10783
|
|
|
10658
|
-
var version = "1.
|
|
10784
|
+
var version = "1.54.0";
|
|
10659
10785
|
var PACKAGE = {
|
|
10660
10786
|
version: version};
|
|
10661
10787
|
|
|
@@ -10785,7 +10911,8 @@ class WebsocketClientTransport {
|
|
|
10785
10911
|
removeListeners();
|
|
10786
10912
|
resolve(new WebsocketDuplexConnectionExports.WebsocketDuplexConnection(websocket, new distExports.Deserializer(), multiplexerDemultiplexerFactory));
|
|
10787
10913
|
};
|
|
10788
|
-
const errorListener = (
|
|
10914
|
+
const errorListener = (event) => {
|
|
10915
|
+
const ev = event;
|
|
10789
10916
|
removeListeners();
|
|
10790
10917
|
// We add a default error in that case.
|
|
10791
10918
|
if (ev.error != null) {
|
|
@@ -11028,7 +11155,13 @@ const SOCKET_TIMEOUT_MS = 30_000;
|
|
|
11028
11155
|
// If there is a backlog of messages (for example on slow connections), keepalive messages could be delayed
|
|
11029
11156
|
// significantly. Therefore this is longer than the socket timeout.
|
|
11030
11157
|
const KEEP_ALIVE_LIFETIME_MS = 90_000;
|
|
11158
|
+
/**
|
|
11159
|
+
* @internal
|
|
11160
|
+
*/
|
|
11031
11161
|
const DEFAULT_REMOTE_LOGGER = Logger.get('PowerSyncRemote');
|
|
11162
|
+
/**
|
|
11163
|
+
* @public
|
|
11164
|
+
*/
|
|
11032
11165
|
exports.FetchStrategy = void 0;
|
|
11033
11166
|
(function (FetchStrategy) {
|
|
11034
11167
|
/**
|
|
@@ -11047,12 +11180,17 @@ exports.FetchStrategy = void 0;
|
|
|
11047
11180
|
* The class wrapper is used to distinguish the fetchImplementation
|
|
11048
11181
|
* option in [AbstractRemoteOptions] from the general fetch method
|
|
11049
11182
|
* which is typeof "function"
|
|
11183
|
+
*
|
|
11184
|
+
* @internal
|
|
11050
11185
|
*/
|
|
11051
11186
|
class FetchImplementationProvider {
|
|
11052
11187
|
getFetch() {
|
|
11053
11188
|
throw new Error('Unspecified fetch implementation');
|
|
11054
11189
|
}
|
|
11055
11190
|
}
|
|
11191
|
+
/**
|
|
11192
|
+
* @internal
|
|
11193
|
+
*/
|
|
11056
11194
|
const DEFAULT_REMOTE_OPTIONS = {
|
|
11057
11195
|
socketUrlTransformer: (url) => url.replace(/^https?:\/\//, function (match) {
|
|
11058
11196
|
return match === 'https://' ? 'wss://' : 'ws://';
|
|
@@ -11060,6 +11198,9 @@ const DEFAULT_REMOTE_OPTIONS = {
|
|
|
11060
11198
|
fetchImplementation: new FetchImplementationProvider(),
|
|
11061
11199
|
fetchOptions: {}
|
|
11062
11200
|
};
|
|
11201
|
+
/**
|
|
11202
|
+
* @internal
|
|
11203
|
+
*/
|
|
11063
11204
|
class AbstractRemote {
|
|
11064
11205
|
connector;
|
|
11065
11206
|
logger;
|
|
@@ -11469,7 +11610,7 @@ class AbstractRemote {
|
|
|
11469
11610
|
* Posts a `/sync/stream` request.
|
|
11470
11611
|
*
|
|
11471
11612
|
* Depending on the `Content-Type` of the response, this returns strings for sync lines or encoded BSON documents as
|
|
11472
|
-
*
|
|
11613
|
+
* `Uint8Array`s.
|
|
11473
11614
|
*/
|
|
11474
11615
|
async fetchStream(options) {
|
|
11475
11616
|
const { isBson, stream } = await this.fetchStreamRaw(options);
|
|
@@ -11511,16 +11652,26 @@ function isInterruptingInstruction(instruction) {
|
|
|
11511
11652
|
return 'EstablishSyncStream' in instruction || 'CloseSyncStream' in instruction;
|
|
11512
11653
|
}
|
|
11513
11654
|
|
|
11655
|
+
/**
|
|
11656
|
+
* @internal
|
|
11657
|
+
*/
|
|
11514
11658
|
exports.LockType = void 0;
|
|
11515
11659
|
(function (LockType) {
|
|
11516
11660
|
LockType["CRUD"] = "crud";
|
|
11517
11661
|
LockType["SYNC"] = "sync";
|
|
11518
11662
|
})(exports.LockType || (exports.LockType = {}));
|
|
11663
|
+
/**
|
|
11664
|
+
* @public
|
|
11665
|
+
*/
|
|
11519
11666
|
exports.SyncStreamConnectionMethod = void 0;
|
|
11520
11667
|
(function (SyncStreamConnectionMethod) {
|
|
11521
11668
|
SyncStreamConnectionMethod["HTTP"] = "http";
|
|
11522
11669
|
SyncStreamConnectionMethod["WEB_SOCKET"] = "web-socket";
|
|
11523
11670
|
})(exports.SyncStreamConnectionMethod || (exports.SyncStreamConnectionMethod = {}));
|
|
11671
|
+
/**
|
|
11672
|
+
* @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
|
|
11673
|
+
* @public
|
|
11674
|
+
*/
|
|
11524
11675
|
exports.SyncClientImplementation = void 0;
|
|
11525
11676
|
(function (SyncClientImplementation) {
|
|
11526
11677
|
/**
|
|
@@ -11532,8 +11683,8 @@ exports.SyncClientImplementation = void 0;
|
|
|
11532
11683
|
* ## Compatibility warning
|
|
11533
11684
|
*
|
|
11534
11685
|
* The Rust sync client stores sync data in a format that is slightly different than the one used
|
|
11535
|
-
* by the old JavaScript client. When adopting the {@link RUST} client on existing databases,
|
|
11536
|
-
* migrate the format automatically.
|
|
11686
|
+
* by the old JavaScript client. When adopting the {@link SyncClientImplementation.RUST} client on existing databases,
|
|
11687
|
+
* the PowerSync SDK will migrate the format automatically.
|
|
11537
11688
|
*
|
|
11538
11689
|
* SDK versions supporting both the JavaScript and the Rust client support both formats with the JavaScript client
|
|
11539
11690
|
* implementaiton. However, downgrading to an SDK version that only supports the JavaScript client would not be
|
|
@@ -11543,14 +11694,29 @@ exports.SyncClientImplementation = void 0;
|
|
|
11543
11694
|
})(exports.SyncClientImplementation || (exports.SyncClientImplementation = {}));
|
|
11544
11695
|
/**
|
|
11545
11696
|
* The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}.
|
|
11697
|
+
*
|
|
11698
|
+
* @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
|
|
11699
|
+
* @public
|
|
11546
11700
|
*/
|
|
11547
11701
|
const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = exports.SyncClientImplementation.RUST;
|
|
11702
|
+
/**
|
|
11703
|
+
* @internal
|
|
11704
|
+
*/
|
|
11548
11705
|
const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
11706
|
+
/**
|
|
11707
|
+
* @internal
|
|
11708
|
+
*/
|
|
11549
11709
|
const DEFAULT_RETRY_DELAY_MS = 5000;
|
|
11710
|
+
/**
|
|
11711
|
+
* @internal
|
|
11712
|
+
*/
|
|
11550
11713
|
const DEFAULT_STREAMING_SYNC_OPTIONS = {
|
|
11551
11714
|
retryDelayMs: DEFAULT_RETRY_DELAY_MS,
|
|
11552
11715
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
11553
11716
|
};
|
|
11717
|
+
/**
|
|
11718
|
+
* @internal
|
|
11719
|
+
*/
|
|
11554
11720
|
const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
11555
11721
|
appMetadata: {},
|
|
11556
11722
|
connectionMethod: exports.SyncStreamConnectionMethod.WEB_SOCKET,
|
|
@@ -11560,22 +11726,21 @@ const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
|
11560
11726
|
serializedSchema: undefined,
|
|
11561
11727
|
includeDefaultStreams: true
|
|
11562
11728
|
};
|
|
11729
|
+
/**
|
|
11730
|
+
* @internal
|
|
11731
|
+
*/
|
|
11563
11732
|
class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
11564
11733
|
options;
|
|
11565
11734
|
abortController;
|
|
11566
|
-
// In rare cases, mostly for tests, uploads can be triggered without being properly connected.
|
|
11567
|
-
// This allows ensuring that all upload processes can be aborted.
|
|
11568
|
-
uploadAbortController;
|
|
11569
11735
|
crudUpdateListener;
|
|
11570
11736
|
streamingSyncPromise;
|
|
11571
11737
|
logger;
|
|
11572
11738
|
activeStreams;
|
|
11573
11739
|
connectionMayHaveChanged = false;
|
|
11574
|
-
|
|
11740
|
+
crudUploadNotifier = asyncNotifier();
|
|
11575
11741
|
notifyCompletedUploads;
|
|
11576
11742
|
handleActiveStreamsChange;
|
|
11577
11743
|
syncStatus;
|
|
11578
|
-
triggerCrudUpload;
|
|
11579
11744
|
constructor(options) {
|
|
11580
11745
|
super();
|
|
11581
11746
|
this.options = options;
|
|
@@ -11591,16 +11756,9 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11591
11756
|
}
|
|
11592
11757
|
});
|
|
11593
11758
|
this.abortController = null;
|
|
11594
|
-
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
}
|
|
11598
|
-
this.isUploadingCrud = true;
|
|
11599
|
-
this._uploadAllCrud().finally(() => {
|
|
11600
|
-
this.notifyCompletedUploads?.();
|
|
11601
|
-
this.isUploadingCrud = false;
|
|
11602
|
-
});
|
|
11603
|
-
}, this.options.crudUploadThrottleMs);
|
|
11759
|
+
}
|
|
11760
|
+
triggerCrudUpload() {
|
|
11761
|
+
this.crudUploadNotifier.notify();
|
|
11604
11762
|
}
|
|
11605
11763
|
async waitForReady() { }
|
|
11606
11764
|
waitForStatus(status) {
|
|
@@ -11648,7 +11806,6 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11648
11806
|
super.dispose();
|
|
11649
11807
|
this.crudUpdateListener?.();
|
|
11650
11808
|
this.crudUpdateListener = undefined;
|
|
11651
|
-
this.uploadAbortController?.abort();
|
|
11652
11809
|
}
|
|
11653
11810
|
async getWriteCheckpoint() {
|
|
11654
11811
|
const clientId = await this.options.adapter.getClientId();
|
|
@@ -11658,7 +11815,17 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11658
11815
|
this.logger.debug(`Created write checkpoint: ${checkpoint}`);
|
|
11659
11816
|
return checkpoint;
|
|
11660
11817
|
}
|
|
11661
|
-
async
|
|
11818
|
+
async crudUploadLoop(signal) {
|
|
11819
|
+
while (!signal.aborted) {
|
|
11820
|
+
await Promise.all([
|
|
11821
|
+
// Start the initial CRUD upload on connect. Then, keep polling until we're done.
|
|
11822
|
+
this._uploadAllCrud(signal),
|
|
11823
|
+
this.delayRetry(signal, this.options.crudUploadThrottleMs)
|
|
11824
|
+
]);
|
|
11825
|
+
await this.crudUploadNotifier.waitForNotification(signal);
|
|
11826
|
+
}
|
|
11827
|
+
}
|
|
11828
|
+
async _uploadAllCrud(signal) {
|
|
11662
11829
|
return this.obtainLock({
|
|
11663
11830
|
type: exports.LockType.CRUD,
|
|
11664
11831
|
callback: async () => {
|
|
@@ -11666,12 +11833,7 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11666
11833
|
* Keep track of the first item in the CRUD queue for the last `uploadCrud` iteration.
|
|
11667
11834
|
*/
|
|
11668
11835
|
let checkedCrudItem;
|
|
11669
|
-
|
|
11670
|
-
this.uploadAbortController = controller;
|
|
11671
|
-
this.abortController?.signal.addEventListener('abort', () => {
|
|
11672
|
-
controller.abort();
|
|
11673
|
-
}, { once: true });
|
|
11674
|
-
while (!controller.signal.aborted) {
|
|
11836
|
+
while (!signal.aborted) {
|
|
11675
11837
|
try {
|
|
11676
11838
|
/**
|
|
11677
11839
|
* This is the first item in the FIFO CRUD queue.
|
|
@@ -11701,7 +11863,10 @@ The next upload iteration will be delayed.`);
|
|
|
11701
11863
|
else {
|
|
11702
11864
|
// Uploading is completed
|
|
11703
11865
|
const neededUpdate = await this.options.adapter.updateLocalTarget(() => this.getWriteCheckpoint());
|
|
11704
|
-
if (neededUpdate
|
|
11866
|
+
if (neededUpdate) {
|
|
11867
|
+
this.notifyCompletedUploads?.();
|
|
11868
|
+
}
|
|
11869
|
+
else if (checkedCrudItem != null) {
|
|
11705
11870
|
// Only log this if there was something to upload
|
|
11706
11871
|
this.logger.debug('Upload complete, no write checkpoint needed.');
|
|
11707
11872
|
}
|
|
@@ -11716,7 +11881,7 @@ The next upload iteration will be delayed.`);
|
|
|
11716
11881
|
uploadError: ex
|
|
11717
11882
|
}
|
|
11718
11883
|
});
|
|
11719
|
-
await this.delayRetry(
|
|
11884
|
+
await this.delayRetry(signal);
|
|
11720
11885
|
if (!this.isConnected) {
|
|
11721
11886
|
// Exit the upload loop if the sync stream is no longer connected
|
|
11722
11887
|
break;
|
|
@@ -11731,7 +11896,6 @@ The next upload iteration will be delayed.`);
|
|
|
11731
11896
|
});
|
|
11732
11897
|
}
|
|
11733
11898
|
}
|
|
11734
|
-
this.uploadAbortController = undefined;
|
|
11735
11899
|
}
|
|
11736
11900
|
});
|
|
11737
11901
|
}
|
|
@@ -11741,7 +11905,10 @@ The next upload iteration will be delayed.`);
|
|
|
11741
11905
|
}
|
|
11742
11906
|
const controller = new AbortController();
|
|
11743
11907
|
this.abortController = controller;
|
|
11744
|
-
this.streamingSyncPromise =
|
|
11908
|
+
this.streamingSyncPromise = Promise.all([
|
|
11909
|
+
this.crudUploadLoop(controller.signal).catch((ex) => this.logger.error('Error in crud upload loop', ex)),
|
|
11910
|
+
this.streamingSync(controller.signal, options)
|
|
11911
|
+
]);
|
|
11745
11912
|
// Return a promise that resolves when the connection status is updated to indicate that we're connected.
|
|
11746
11913
|
return new Promise((resolve) => {
|
|
11747
11914
|
const disposer = this.registerListener({
|
|
@@ -11779,14 +11946,7 @@ The next upload iteration will be delayed.`);
|
|
|
11779
11946
|
this.abortController = null;
|
|
11780
11947
|
this.updateSyncStatus({ connected: false, connecting: false });
|
|
11781
11948
|
}
|
|
11782
|
-
/**
|
|
11783
|
-
* @deprecated use [connect instead]
|
|
11784
|
-
*/
|
|
11785
11949
|
async streamingSync(signal, options) {
|
|
11786
|
-
if (!signal) {
|
|
11787
|
-
this.abortController = new AbortController();
|
|
11788
|
-
signal = this.abortController.signal;
|
|
11789
|
-
}
|
|
11790
11950
|
/**
|
|
11791
11951
|
* Listen for CRUD updates and trigger upstream uploads
|
|
11792
11952
|
*/
|
|
@@ -11892,7 +12052,7 @@ The next upload iteration will be delayed.`);
|
|
|
11892
12052
|
this.handleActiveStreamsChange?.();
|
|
11893
12053
|
}
|
|
11894
12054
|
/**
|
|
11895
|
-
* Older versions of the JS SDK used to encode subkeys as JSON in
|
|
12055
|
+
* Older versions of the JS SDK used to encode subkeys as JSON in `OplogEntry.toJSON`.
|
|
11896
12056
|
* Because subkeys are always strings, this leads to quotes being added around them in `ps_oplog`.
|
|
11897
12057
|
* While this is not a problem as long as it's done consistently, it causes issues when a database
|
|
11898
12058
|
* created by the JS SDK is used with other SDKs, or (more likely) when the new Rust sync client
|
|
@@ -11902,7 +12062,7 @@ The next upload iteration will be delayed.`);
|
|
|
11902
12062
|
* migration is only triggered when necessary (for now). The function returns whether the new format
|
|
11903
12063
|
* should be used, so that the JS SDK is able to write to updated databases.
|
|
11904
12064
|
*
|
|
11905
|
-
* @param requireFixedKeyFormat Whether we require the new format or also support the old one.
|
|
12065
|
+
* @param requireFixedKeyFormat - Whether we require the new format or also support the old one.
|
|
11906
12066
|
* The Rust client requires the new subkey format.
|
|
11907
12067
|
* @returns Whether the database is now using the new, fixed subkey format.
|
|
11908
12068
|
*/
|
|
@@ -12160,14 +12320,13 @@ The next upload iteration will be delayed.`);
|
|
|
12160
12320
|
// trigger this for all updates
|
|
12161
12321
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
12162
12322
|
}
|
|
12163
|
-
async delayRetry(signal) {
|
|
12323
|
+
async delayRetry(signal, delay = this.options.retryDelayMs) {
|
|
12164
12324
|
return new Promise((resolve) => {
|
|
12165
12325
|
if (signal?.aborted) {
|
|
12166
12326
|
// If the signal is already aborted, resolve immediately
|
|
12167
12327
|
resolve();
|
|
12168
12328
|
return;
|
|
12169
12329
|
}
|
|
12170
|
-
const { retryDelayMs } = this.options;
|
|
12171
12330
|
let timeoutId;
|
|
12172
12331
|
const endDelay = () => {
|
|
12173
12332
|
resolve();
|
|
@@ -12178,7 +12337,7 @@ The next upload iteration will be delayed.`);
|
|
|
12178
12337
|
signal?.removeEventListener('abort', endDelay);
|
|
12179
12338
|
};
|
|
12180
12339
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
12181
|
-
timeoutId = setTimeout(endDelay,
|
|
12340
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
12182
12341
|
});
|
|
12183
12342
|
}
|
|
12184
12343
|
updateSubscriptions(subscriptions) {
|
|
@@ -12210,7 +12369,8 @@ const MEMORY_TRIGGER_CLAIM_MANAGER = {
|
|
|
12210
12369
|
|
|
12211
12370
|
/**
|
|
12212
12371
|
* SQLite operations to track changes for with {@link TriggerManager}
|
|
12213
|
-
*
|
|
12372
|
+
*
|
|
12373
|
+
* @experimental @alpha
|
|
12214
12374
|
*/
|
|
12215
12375
|
exports.DiffTriggerOperation = void 0;
|
|
12216
12376
|
(function (DiffTriggerOperation) {
|
|
@@ -12272,8 +12432,8 @@ class TriggerManagerImpl {
|
|
|
12272
12432
|
get db() {
|
|
12273
12433
|
return this.options.db;
|
|
12274
12434
|
}
|
|
12275
|
-
async getUUID() {
|
|
12276
|
-
const { id: uuid } = await this.db.get(/* sql */ `
|
|
12435
|
+
async getUUID(ctx) {
|
|
12436
|
+
const { id: uuid } = await (ctx ?? this.db).get(/* sql */ `
|
|
12277
12437
|
SELECT
|
|
12278
12438
|
uuid () as id
|
|
12279
12439
|
`);
|
|
@@ -12386,7 +12546,7 @@ class TriggerManagerImpl {
|
|
|
12386
12546
|
const replicatedColumns = columns ?? sourceDefinition.columns.map((col) => col.name);
|
|
12387
12547
|
const internalSource = sourceDefinition.internalName;
|
|
12388
12548
|
const triggerIds = [];
|
|
12389
|
-
const id = await this.getUUID();
|
|
12549
|
+
const id = await this.getUUID(setupContext);
|
|
12390
12550
|
const releaseStorageClaim = useStorage ? await this.options.claimManager.obtainClaim(id) : null;
|
|
12391
12551
|
/**
|
|
12392
12552
|
* We default to replicating all columns if no columns array is provided.
|
|
@@ -12626,18 +12786,29 @@ const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
|
|
|
12626
12786
|
const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
|
|
12627
12787
|
clearLocal: true
|
|
12628
12788
|
};
|
|
12789
|
+
/**
|
|
12790
|
+
* @internal
|
|
12791
|
+
*/
|
|
12629
12792
|
const DEFAULT_POWERSYNC_CLOSE_OPTIONS = {
|
|
12630
12793
|
disconnect: true
|
|
12631
12794
|
};
|
|
12795
|
+
/**
|
|
12796
|
+
* @internal
|
|
12797
|
+
*/
|
|
12632
12798
|
const DEFAULT_POWERSYNC_DB_OPTIONS = {
|
|
12633
12799
|
retryDelayMs: 5000,
|
|
12634
12800
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
12635
12801
|
};
|
|
12802
|
+
/**
|
|
12803
|
+
* @internal
|
|
12804
|
+
*/
|
|
12636
12805
|
const DEFAULT_CRUD_BATCH_LIMIT = 100;
|
|
12637
12806
|
/**
|
|
12638
12807
|
* Requesting nested or recursive locks can block the application in some circumstances.
|
|
12639
12808
|
* This default lock timeout will act as a failsafe to throw an error if a lock cannot
|
|
12640
12809
|
* be obtained.
|
|
12810
|
+
*
|
|
12811
|
+
* @internal
|
|
12641
12812
|
*/
|
|
12642
12813
|
const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins
|
|
12643
12814
|
/**
|
|
@@ -12647,6 +12818,9 @@ const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins
|
|
|
12647
12818
|
const isPowerSyncDatabaseOptionsWithSettings = (test) => {
|
|
12648
12819
|
return typeof test == 'object' && isSQLOpenOptions(test.database);
|
|
12649
12820
|
};
|
|
12821
|
+
/**
|
|
12822
|
+
* @public
|
|
12823
|
+
*/
|
|
12650
12824
|
class AbstractPowerSyncDatabase extends BaseObserver {
|
|
12651
12825
|
options;
|
|
12652
12826
|
/**
|
|
@@ -12804,7 +12978,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
12804
12978
|
/**
|
|
12805
12979
|
* Wait for the first sync operation to complete.
|
|
12806
12980
|
*
|
|
12807
|
-
* @param request Either an abort signal (after which the promise will complete regardless of
|
|
12981
|
+
* @param request - Either an abort signal (after which the promise will complete regardless of
|
|
12808
12982
|
* whether a full sync was completed) or an object providing an abort signal and a priority target.
|
|
12809
12983
|
* When a priority target is set, the promise may complete when all buckets with the given (or higher)
|
|
12810
12984
|
* priorities have been synchronized. This can be earlier than a complete sync.
|
|
@@ -12959,7 +13133,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
12959
13133
|
/**
|
|
12960
13134
|
* Close the sync connection.
|
|
12961
13135
|
*
|
|
12962
|
-
* Use {@link connect} to connect again.
|
|
13136
|
+
* Use {@link AbstractPowerSyncDatabase.connect} to connect again.
|
|
12963
13137
|
*/
|
|
12964
13138
|
async disconnect() {
|
|
12965
13139
|
return this.connectionManager.disconnect();
|
|
@@ -12986,8 +13160,8 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
12986
13160
|
/**
|
|
12987
13161
|
* Create a sync stream to query its status or to subscribe to it.
|
|
12988
13162
|
*
|
|
12989
|
-
* @param name The name of the stream to subscribe to.
|
|
12990
|
-
* @param params Optional parameters for the stream subscription.
|
|
13163
|
+
* @param name - The name of the stream to subscribe to.
|
|
13164
|
+
* @param params - Optional parameters for the stream subscription.
|
|
12991
13165
|
* @returns A {@link SyncStream} instance that can be subscribed to.
|
|
12992
13166
|
* @experimental Sync streams are currently in alpha.
|
|
12993
13167
|
*/
|
|
@@ -13045,14 +13219,14 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
13045
13219
|
* Once the data have been successfully uploaded, call {@link CrudBatch.complete} before
|
|
13046
13220
|
* requesting the next batch.
|
|
13047
13221
|
*
|
|
13048
|
-
* Use
|
|
13222
|
+
* Use the `limit` parameter to specify the maximum number of updates to return in a single
|
|
13049
13223
|
* batch.
|
|
13050
13224
|
*
|
|
13051
13225
|
* This method does include transaction ids in the result, but does not group
|
|
13052
13226
|
* data by transaction. One batch may contain data from multiple transactions,
|
|
13053
13227
|
* and a single transaction may be split over multiple batches.
|
|
13054
13228
|
*
|
|
13055
|
-
* @param limit Maximum number of CRUD entries to include in the batch
|
|
13229
|
+
* @param limit - Maximum number of CRUD entries to include in the batch
|
|
13056
13230
|
* @returns A batch of CRUD operations to upload, or null if there are none
|
|
13057
13231
|
*/
|
|
13058
13232
|
async getCrudBatch(limit = DEFAULT_CRUD_BATCH_LIMIT) {
|
|
@@ -13079,7 +13253,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
13079
13253
|
* Once the data have been successfully uploaded, call {@link CrudTransaction.complete} before
|
|
13080
13254
|
* requesting the next transaction.
|
|
13081
13255
|
*
|
|
13082
|
-
* Unlike {@link getCrudBatch}, this only returns data from a single transaction at a time.
|
|
13256
|
+
* Unlike {@link AbstractPowerSyncDatabase.getCrudBatch}, this only returns data from a single transaction at a time.
|
|
13083
13257
|
* All data for the transaction is loaded into memory.
|
|
13084
13258
|
*
|
|
13085
13259
|
* @returns A transaction of CRUD operations to upload, or null if there are none
|
|
@@ -13094,7 +13268,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
13094
13268
|
* This is typically used from the {@link PowerSyncBackendConnector.uploadData} callback. Each entry emitted by the
|
|
13095
13269
|
* returned iterator is a full transaction containing all local writes made while that transaction was active.
|
|
13096
13270
|
*
|
|
13097
|
-
* Unlike {@link getNextCrudTransaction}, which always returns the oldest transaction that hasn't been
|
|
13271
|
+
* Unlike {@link AbstractPowerSyncDatabase.getNextCrudTransaction}, which always returns the oldest transaction that hasn't been
|
|
13098
13272
|
* {@link CrudTransaction.complete}d yet, this iterator can be used to receive multiple transactions. Calling
|
|
13099
13273
|
* {@link CrudTransaction.complete} will mark that and all prior transactions emitted by the iterator as completed.
|
|
13100
13274
|
*
|
|
@@ -13188,8 +13362,8 @@ SELECT * FROM crud_entries;
|
|
|
13188
13362
|
* the returned result's `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
|
|
13189
13363
|
* Use a `RETURNING` clause and inspect `result.rows` when you need to confirm which rows changed.
|
|
13190
13364
|
*
|
|
13191
|
-
* @param sql The SQL query to execute
|
|
13192
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13365
|
+
* @param sql - The SQL query to execute
|
|
13366
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13193
13367
|
* @returns The query result as an object with structured key-value pairs
|
|
13194
13368
|
*/
|
|
13195
13369
|
async execute(sql, parameters) {
|
|
@@ -13199,8 +13373,8 @@ SELECT * FROM crud_entries;
|
|
|
13199
13373
|
* Execute a SQL write (INSERT/UPDATE/DELETE) query directly on the database without any PowerSync processing.
|
|
13200
13374
|
* This bypasses certain PowerSync abstractions and is useful for accessing the raw database results.
|
|
13201
13375
|
*
|
|
13202
|
-
* @param sql The SQL query to execute
|
|
13203
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13376
|
+
* @param sql - The SQL query to execute
|
|
13377
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13204
13378
|
* @returns The raw query result from the underlying database as a nested array of raw values, where each row is
|
|
13205
13379
|
* represented as an array of column values without field names.
|
|
13206
13380
|
*/
|
|
@@ -13213,8 +13387,8 @@ SELECT * FROM crud_entries;
|
|
|
13213
13387
|
* and optionally return results.
|
|
13214
13388
|
* This is faster than executing separately with each parameter set.
|
|
13215
13389
|
*
|
|
13216
|
-
* @param sql The SQL query to execute
|
|
13217
|
-
* @param parameters Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
|
|
13390
|
+
* @param sql - The SQL query to execute
|
|
13391
|
+
* @param parameters - Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
|
|
13218
13392
|
* @returns The query result
|
|
13219
13393
|
*/
|
|
13220
13394
|
async executeBatch(sql, parameters) {
|
|
@@ -13224,8 +13398,8 @@ SELECT * FROM crud_entries;
|
|
|
13224
13398
|
/**
|
|
13225
13399
|
* Execute a read-only query and return results.
|
|
13226
13400
|
*
|
|
13227
|
-
* @param sql The SQL query to execute
|
|
13228
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13401
|
+
* @param sql - The SQL query to execute
|
|
13402
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13229
13403
|
* @returns An array of results
|
|
13230
13404
|
*/
|
|
13231
13405
|
async getAll(sql, parameters) {
|
|
@@ -13235,8 +13409,8 @@ SELECT * FROM crud_entries;
|
|
|
13235
13409
|
/**
|
|
13236
13410
|
* Execute a read-only query and return the first result, or null if the ResultSet is empty.
|
|
13237
13411
|
*
|
|
13238
|
-
* @param sql The SQL query to execute
|
|
13239
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13412
|
+
* @param sql - The SQL query to execute
|
|
13413
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13240
13414
|
* @returns The first result if found, or null if no results are returned
|
|
13241
13415
|
*/
|
|
13242
13416
|
async getOptional(sql, parameters) {
|
|
@@ -13246,8 +13420,8 @@ SELECT * FROM crud_entries;
|
|
|
13246
13420
|
/**
|
|
13247
13421
|
* Execute a read-only query and return the first result, error if the ResultSet is empty.
|
|
13248
13422
|
*
|
|
13249
|
-
* @param sql The SQL query to execute
|
|
13250
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13423
|
+
* @param sql - The SQL query to execute
|
|
13424
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13251
13425
|
* @returns The first result matching the query
|
|
13252
13426
|
* @throws Error if no rows are returned
|
|
13253
13427
|
*/
|
|
@@ -13257,7 +13431,7 @@ SELECT * FROM crud_entries;
|
|
|
13257
13431
|
}
|
|
13258
13432
|
/**
|
|
13259
13433
|
* Takes a read lock, without starting a transaction.
|
|
13260
|
-
* In most cases, {@link readTransaction} should be used instead.
|
|
13434
|
+
* In most cases, {@link AbstractPowerSyncDatabase.readTransaction} should be used instead.
|
|
13261
13435
|
*/
|
|
13262
13436
|
async readLock(callback) {
|
|
13263
13437
|
await this.waitForReady();
|
|
@@ -13265,7 +13439,7 @@ SELECT * FROM crud_entries;
|
|
|
13265
13439
|
}
|
|
13266
13440
|
/**
|
|
13267
13441
|
* Takes a global lock, without starting a transaction.
|
|
13268
|
-
* In most cases, {@link writeTransaction} should be used instead.
|
|
13442
|
+
* In most cases, {@link AbstractPowerSyncDatabase.writeTransaction} should be used instead.
|
|
13269
13443
|
*/
|
|
13270
13444
|
async writeLock(callback) {
|
|
13271
13445
|
await this.waitForReady();
|
|
@@ -13276,8 +13450,8 @@ SELECT * FROM crud_entries;
|
|
|
13276
13450
|
* Read transactions can run concurrently to a write transaction.
|
|
13277
13451
|
* Changes from any write transaction are not visible to read transactions started before it.
|
|
13278
13452
|
*
|
|
13279
|
-
* @param callback Function to execute within the transaction
|
|
13280
|
-
* @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
|
|
13453
|
+
* @param callback - Function to execute within the transaction
|
|
13454
|
+
* @param lockTimeout - Time in milliseconds to wait for a lock before throwing an error
|
|
13281
13455
|
* @returns The result of the callback
|
|
13282
13456
|
* @throws Error if the lock cannot be obtained within the timeout period
|
|
13283
13457
|
*/
|
|
@@ -13294,8 +13468,8 @@ SELECT * FROM crud_entries;
|
|
|
13294
13468
|
* This takes a global lock - only one write transaction can execute against the database at a time.
|
|
13295
13469
|
* Statements within the transaction must be done on the provided {@link Transaction} interface.
|
|
13296
13470
|
*
|
|
13297
|
-
* @param callback Function to execute within the transaction
|
|
13298
|
-
* @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
|
|
13471
|
+
* @param callback - Function to execute within the transaction
|
|
13472
|
+
* @param lockTimeout - Time in milliseconds to wait for a lock before throwing an error
|
|
13299
13473
|
* @returns The result of the callback
|
|
13300
13474
|
* @throws Error if the lock cannot be obtained within the timeout period
|
|
13301
13475
|
*/
|
|
@@ -13372,15 +13546,15 @@ SELECT * FROM crud_entries;
|
|
|
13372
13546
|
}
|
|
13373
13547
|
/**
|
|
13374
13548
|
* Execute a read query every time the source tables are modified.
|
|
13375
|
-
* Use {@link
|
|
13549
|
+
* Use {@link SQLOnChangeOptions.throttleMs} to specify the minimum interval between queries.
|
|
13376
13550
|
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
|
|
13377
13551
|
*
|
|
13378
13552
|
* Note that the `onChange` callback member of the handler is required.
|
|
13379
13553
|
*
|
|
13380
|
-
* @param sql The SQL query to execute
|
|
13381
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13382
|
-
* @param handler Callbacks for handling results and errors
|
|
13383
|
-
* @param options Options for configuring watch behavior
|
|
13554
|
+
* @param sql - The SQL query to execute
|
|
13555
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13556
|
+
* @param handler - Callbacks for handling results and errors
|
|
13557
|
+
* @param options - Options for configuring watch behavior
|
|
13384
13558
|
*/
|
|
13385
13559
|
watchWithCallback(sql, parameters, handler, options) {
|
|
13386
13560
|
const { onResult, onError = (e) => this.logger.error(e) } = handler ?? {};
|
|
@@ -13393,7 +13567,7 @@ SELECT * FROM crud_entries;
|
|
|
13393
13567
|
const watchedQuery = new OnChangeQueryProcessor({
|
|
13394
13568
|
db: this,
|
|
13395
13569
|
comparator,
|
|
13396
|
-
placeholderData: null,
|
|
13570
|
+
placeholderData: null, // FIXME
|
|
13397
13571
|
watchOptions: {
|
|
13398
13572
|
query: {
|
|
13399
13573
|
compile: () => ({
|
|
@@ -13426,12 +13600,12 @@ SELECT * FROM crud_entries;
|
|
|
13426
13600
|
}
|
|
13427
13601
|
/**
|
|
13428
13602
|
* Execute a read query every time the source tables are modified.
|
|
13429
|
-
* Use {@link
|
|
13603
|
+
* Use {@link SQLOnChangeOptions.throttleMs} to specify the minimum interval between queries.
|
|
13430
13604
|
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
|
|
13431
13605
|
*
|
|
13432
|
-
* @param sql The SQL query to execute
|
|
13433
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
13434
|
-
* @param options Options for configuring watch behavior
|
|
13606
|
+
* @param sql - The SQL query to execute
|
|
13607
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
13608
|
+
* @param options - Options for configuring watch behavior
|
|
13435
13609
|
* @returns An AsyncIterable that yields QueryResults whenever the data changes
|
|
13436
13610
|
*/
|
|
13437
13611
|
watchWithAsyncGenerator(sql, parameters, options) {
|
|
@@ -13455,9 +13629,9 @@ SELECT * FROM crud_entries;
|
|
|
13455
13629
|
* If tables are specified in the options, those are used directly.
|
|
13456
13630
|
* Otherwise, analyzes the query using EXPLAIN to determine which tables are accessed.
|
|
13457
13631
|
*
|
|
13458
|
-
* @param sql The SQL query to analyze
|
|
13459
|
-
* @param parameters Optional parameters for the SQL query
|
|
13460
|
-
* @param options Optional watch options that may contain explicit table list
|
|
13632
|
+
* @param sql - The SQL query to analyze
|
|
13633
|
+
* @param parameters - Optional parameters for the SQL query
|
|
13634
|
+
* @param options - Optional watch options that may contain explicit table list
|
|
13461
13635
|
* @returns Array of table names that the query depends on
|
|
13462
13636
|
*/
|
|
13463
13637
|
async resolveTables(sql, parameters, options) {
|
|
@@ -13486,13 +13660,13 @@ SELECT * FROM crud_entries;
|
|
|
13486
13660
|
/**
|
|
13487
13661
|
* Invoke the provided callback on any changes to any of the specified tables.
|
|
13488
13662
|
*
|
|
13489
|
-
* This is preferred over {@link watchWithCallback} when multiple queries need to be performed
|
|
13663
|
+
* This is preferred over {@link AbstractPowerSyncDatabase.watchWithCallback} when multiple queries need to be performed
|
|
13490
13664
|
* together when data is changed.
|
|
13491
13665
|
*
|
|
13492
13666
|
* Note that the `onChange` callback member of the handler is required.
|
|
13493
13667
|
*
|
|
13494
|
-
* @param handler Callbacks for handling change events and errors
|
|
13495
|
-
* @param options Options for configuring watch behavior
|
|
13668
|
+
* @param handler - Callbacks for handling change events and errors
|
|
13669
|
+
* @param options - Options for configuring watch behavior
|
|
13496
13670
|
* @returns A dispose function to stop watching for changes
|
|
13497
13671
|
*/
|
|
13498
13672
|
onChangeWithCallback(handler, options) {
|
|
@@ -13535,12 +13709,12 @@ SELECT * FROM crud_entries;
|
|
|
13535
13709
|
/**
|
|
13536
13710
|
* Create a Stream of changes to any of the specified tables.
|
|
13537
13711
|
*
|
|
13538
|
-
* This is preferred over {@link watchWithAsyncGenerator} when multiple queries need to be
|
|
13539
|
-
* together when data is changed.
|
|
13712
|
+
* This is preferred over {@link AbstractPowerSyncDatabase.watchWithAsyncGenerator} when multiple queries need to be
|
|
13713
|
+
* performed together when data is changed.
|
|
13540
13714
|
*
|
|
13541
13715
|
* Note: do not declare this as `async *onChange` as it will not work in React Native.
|
|
13542
13716
|
*
|
|
13543
|
-
* @param options Options for configuring watch behavior
|
|
13717
|
+
* @param options - Options for configuring watch behavior
|
|
13544
13718
|
* @returns An AsyncIterable that yields change events whenever the specified tables change
|
|
13545
13719
|
*/
|
|
13546
13720
|
onChangeWithAsyncGenerator(options) {
|
|
@@ -13578,15 +13752,15 @@ SELECT * FROM crud_entries;
|
|
|
13578
13752
|
changedTables.add(table);
|
|
13579
13753
|
}
|
|
13580
13754
|
}
|
|
13581
|
-
/**
|
|
13582
|
-
* @ignore
|
|
13583
|
-
*/
|
|
13584
13755
|
async executeReadOnly(sql, params) {
|
|
13585
13756
|
await this.waitForReady();
|
|
13586
13757
|
return this.database.readLock((tx) => tx.execute(sql, params));
|
|
13587
13758
|
}
|
|
13588
13759
|
}
|
|
13589
13760
|
|
|
13761
|
+
/**
|
|
13762
|
+
* @internal
|
|
13763
|
+
*/
|
|
13590
13764
|
class AbstractPowerSyncDatabaseOpenFactory {
|
|
13591
13765
|
options;
|
|
13592
13766
|
constructor(options) {
|
|
@@ -13611,6 +13785,9 @@ class AbstractPowerSyncDatabaseOpenFactory {
|
|
|
13611
13785
|
}
|
|
13612
13786
|
}
|
|
13613
13787
|
|
|
13788
|
+
/**
|
|
13789
|
+
* @internal
|
|
13790
|
+
*/
|
|
13614
13791
|
function runOnSchemaChange(callback, db, options) {
|
|
13615
13792
|
const triggerWatchedQuery = () => {
|
|
13616
13793
|
const abortController = new AbortController();
|
|
@@ -13635,6 +13812,9 @@ function runOnSchemaChange(callback, db, options) {
|
|
|
13635
13812
|
triggerWatchedQuery();
|
|
13636
13813
|
}
|
|
13637
13814
|
|
|
13815
|
+
/**
|
|
13816
|
+
* @public
|
|
13817
|
+
*/
|
|
13638
13818
|
function compilableQueryWatch(db, query, handler, options) {
|
|
13639
13819
|
const { onResult, onError = (e) => { } } = handler ?? {};
|
|
13640
13820
|
if (!onResult) {
|
|
@@ -13672,8 +13852,14 @@ function compilableQueryWatch(db, query, handler, options) {
|
|
|
13672
13852
|
runOnSchemaChange(watchQuery, db, options);
|
|
13673
13853
|
}
|
|
13674
13854
|
|
|
13855
|
+
/**
|
|
13856
|
+
* @internal
|
|
13857
|
+
*/
|
|
13675
13858
|
const MAX_OP_ID = '9223372036854775807';
|
|
13676
13859
|
|
|
13860
|
+
/**
|
|
13861
|
+
* @internal
|
|
13862
|
+
*/
|
|
13677
13863
|
class SqliteBucketStorage extends BaseObserver {
|
|
13678
13864
|
db;
|
|
13679
13865
|
logger;
|
|
@@ -13834,6 +14020,8 @@ class SqliteBucketStorage extends BaseObserver {
|
|
|
13834
14020
|
* Thrown when an underlying database connection is closed.
|
|
13835
14021
|
* This is particularly relevant when worker connections are marked as closed while
|
|
13836
14022
|
* operations are still in progress.
|
|
14023
|
+
*
|
|
14024
|
+
* @internal
|
|
13837
14025
|
*/
|
|
13838
14026
|
class ConnectionClosedError extends Error {
|
|
13839
14027
|
static NAME = 'ConnectionClosedError';
|
|
@@ -13853,6 +14041,8 @@ class ConnectionClosedError extends Error {
|
|
|
13853
14041
|
|
|
13854
14042
|
/**
|
|
13855
14043
|
* A schema is a collection of tables. It is used to define the structure of a database.
|
|
14044
|
+
*
|
|
14045
|
+
* @public
|
|
13856
14046
|
*/
|
|
13857
14047
|
class Schema {
|
|
13858
14048
|
/*
|
|
@@ -13889,7 +14079,7 @@ class Schema {
|
|
|
13889
14079
|
* Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
|
|
13890
14080
|
* using client-side table and column constraints.
|
|
13891
14081
|
*
|
|
13892
|
-
* @param tables An object of (table name, raw table definition) entries.
|
|
14082
|
+
* @param tables - An object of (table name, raw table definition) entries.
|
|
13893
14083
|
*/
|
|
13894
14084
|
withRawTables(tables) {
|
|
13895
14085
|
for (const [name, rawTableDefinition] of Object.entries(tables)) {
|
|
@@ -13935,6 +14125,8 @@ class Schema {
|
|
|
13935
14125
|
Generate a new table from the columns and indexes
|
|
13936
14126
|
@deprecated You should use {@link Table} instead as it now allows TableV2 syntax.
|
|
13937
14127
|
This will be removed in the next major release.
|
|
14128
|
+
|
|
14129
|
+
@public
|
|
13938
14130
|
*/
|
|
13939
14131
|
class TableV2 extends Table {
|
|
13940
14132
|
}
|
|
@@ -13945,6 +14137,8 @@ function sanitizeString(input) {
|
|
|
13945
14137
|
/**
|
|
13946
14138
|
* Helper function for sanitizing UUID input strings.
|
|
13947
14139
|
* Typically used with {@link sanitizeSQL}.
|
|
14140
|
+
*
|
|
14141
|
+
* @alpha
|
|
13948
14142
|
*/
|
|
13949
14143
|
function sanitizeUUID(uuid) {
|
|
13950
14144
|
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;
|
|
@@ -13981,6 +14175,8 @@ function sanitizeUUID(uuid) {
|
|
|
13981
14175
|
* // Incorrect:
|
|
13982
14176
|
* sanitizeSQL`New.id = '${myID}'` // Produces double quotes: New.id = ''O''Reilly''
|
|
13983
14177
|
* ```
|
|
14178
|
+
*
|
|
14179
|
+
* @alpha
|
|
13984
14180
|
*/
|
|
13985
14181
|
function sanitizeSQL(strings, ...values) {
|
|
13986
14182
|
let result = '';
|
|
@@ -14010,6 +14206,8 @@ function sanitizeSQL(strings, ...values) {
|
|
|
14010
14206
|
|
|
14011
14207
|
/**
|
|
14012
14208
|
* Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
|
|
14209
|
+
*
|
|
14210
|
+
* @public
|
|
14013
14211
|
*/
|
|
14014
14212
|
class GetAllQuery {
|
|
14015
14213
|
options;
|
|
@@ -14034,6 +14232,9 @@ class GetAllQuery {
|
|
|
14034
14232
|
}
|
|
14035
14233
|
|
|
14036
14234
|
const TypedLogger = Logger;
|
|
14235
|
+
/**
|
|
14236
|
+
* @public
|
|
14237
|
+
*/
|
|
14037
14238
|
const LogLevel = {
|
|
14038
14239
|
TRACE: TypedLogger.TRACE,
|
|
14039
14240
|
DEBUG: TypedLogger.DEBUG,
|
|
@@ -14050,6 +14251,7 @@ const LogLevel = {
|
|
|
14050
14251
|
* across all loggers created with `createLogger`. Adjusting settings on this
|
|
14051
14252
|
* base logger affects all loggers derived from it unless explicitly overridden.
|
|
14052
14253
|
*
|
|
14254
|
+
* @public
|
|
14053
14255
|
*/
|
|
14054
14256
|
function createBaseLogger() {
|
|
14055
14257
|
return Logger;
|
|
@@ -14060,6 +14262,8 @@ function createBaseLogger() {
|
|
|
14060
14262
|
* Named loggers allow specific modules or areas of your application to have
|
|
14061
14263
|
* their own logging levels and behaviors. These loggers inherit configuration
|
|
14062
14264
|
* from the base logger by default but can override settings independently.
|
|
14265
|
+
*
|
|
14266
|
+
* @public
|
|
14063
14267
|
*/
|
|
14064
14268
|
function createLogger(name, options = {}) {
|
|
14065
14269
|
const logger = Logger.get(name);
|
|
@@ -14069,6 +14273,9 @@ function createLogger(name, options = {}) {
|
|
|
14069
14273
|
return logger;
|
|
14070
14274
|
}
|
|
14071
14275
|
|
|
14276
|
+
/**
|
|
14277
|
+
* @internal
|
|
14278
|
+
*/
|
|
14072
14279
|
const parseQuery = (query, parameters) => {
|
|
14073
14280
|
let sqlStatement;
|
|
14074
14281
|
if (typeof query == 'string') {
|