@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.node.cjs
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
var eventIterator = require('event-iterator');
|
|
4
4
|
var node_buffer = require('node:buffer');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @see https://www.sqlite.org/lang_expr.html#castexpr
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
7
10
|
exports.ColumnType = void 0;
|
|
8
11
|
(function (ColumnType) {
|
|
9
12
|
ColumnType["TEXT"] = "TEXT";
|
|
@@ -19,14 +22,24 @@ const integer = {
|
|
|
19
22
|
const real = {
|
|
20
23
|
type: exports.ColumnType.REAL
|
|
21
24
|
};
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
/**
|
|
26
|
+
* powersync-sqlite-core limits the number of column per table to 1999, due to internal SQLite limits.
|
|
27
|
+
* In earlier versions this was limited to 63.
|
|
28
|
+
*
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
24
31
|
const MAX_AMOUNT_OF_COLUMNS = 1999;
|
|
32
|
+
/**
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
25
35
|
const column = {
|
|
26
36
|
text,
|
|
27
37
|
integer,
|
|
28
38
|
real
|
|
29
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
30
43
|
class Column {
|
|
31
44
|
options;
|
|
32
45
|
constructor(options) {
|
|
@@ -46,9 +59,15 @@ class Column {
|
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
49
65
|
const DEFAULT_INDEX_COLUMN_OPTIONS = {
|
|
50
66
|
ascending: true
|
|
51
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
52
71
|
class IndexedColumn {
|
|
53
72
|
options;
|
|
54
73
|
static createAscending(column) {
|
|
@@ -75,9 +94,15 @@ class IndexedColumn {
|
|
|
75
94
|
}
|
|
76
95
|
}
|
|
77
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
78
100
|
const DEFAULT_INDEX_OPTIONS = {
|
|
79
101
|
columns: []
|
|
80
102
|
};
|
|
103
|
+
/**
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
81
106
|
class Index {
|
|
82
107
|
options;
|
|
83
108
|
static createAscending(options, columnNames) {
|
|
@@ -119,6 +144,9 @@ function encodeTableOptions(options) {
|
|
|
119
144
|
};
|
|
120
145
|
}
|
|
121
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @internal
|
|
149
|
+
*/
|
|
122
150
|
const DEFAULT_TABLE_OPTIONS = {
|
|
123
151
|
indexes: [],
|
|
124
152
|
insertOnly: false,
|
|
@@ -127,7 +155,13 @@ const DEFAULT_TABLE_OPTIONS = {
|
|
|
127
155
|
trackMetadata: false,
|
|
128
156
|
ignoreEmptyUpdates: false
|
|
129
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* @internal
|
|
160
|
+
*/
|
|
130
161
|
const InvalidSQLCharacters = /["'%,.#\s[\]]/;
|
|
162
|
+
/**
|
|
163
|
+
* @public
|
|
164
|
+
*/
|
|
131
165
|
class Table {
|
|
132
166
|
options;
|
|
133
167
|
_mappedColumns;
|
|
@@ -318,6 +352,11 @@ class Table {
|
|
|
318
352
|
}
|
|
319
353
|
}
|
|
320
354
|
|
|
355
|
+
/**
|
|
356
|
+
* The default name of the local table storing attachment data.
|
|
357
|
+
*
|
|
358
|
+
* @alpha
|
|
359
|
+
*/
|
|
321
360
|
const ATTACHMENT_TABLE = 'attachments';
|
|
322
361
|
/**
|
|
323
362
|
* Maps a database row to an AttachmentRecord.
|
|
@@ -325,7 +364,7 @@ const ATTACHMENT_TABLE = 'attachments';
|
|
|
325
364
|
* @param row - The database row object
|
|
326
365
|
* @returns The corresponding AttachmentRecord
|
|
327
366
|
*
|
|
328
|
-
* @
|
|
367
|
+
* @alpha
|
|
329
368
|
*/
|
|
330
369
|
function attachmentFromSql(row) {
|
|
331
370
|
return {
|
|
@@ -343,7 +382,7 @@ function attachmentFromSql(row) {
|
|
|
343
382
|
/**
|
|
344
383
|
* AttachmentState represents the current synchronization state of an attachment.
|
|
345
384
|
*
|
|
346
|
-
* @
|
|
385
|
+
* @alpha
|
|
347
386
|
*/
|
|
348
387
|
exports.AttachmentState = void 0;
|
|
349
388
|
(function (AttachmentState) {
|
|
@@ -356,7 +395,7 @@ exports.AttachmentState = void 0;
|
|
|
356
395
|
/**
|
|
357
396
|
* AttachmentTable defines the schema for the attachment queue table.
|
|
358
397
|
*
|
|
359
|
-
* @
|
|
398
|
+
* @alpha
|
|
360
399
|
*/
|
|
361
400
|
class AttachmentTable extends Table {
|
|
362
401
|
constructor(options) {
|
|
@@ -384,7 +423,8 @@ class AttachmentTable extends Table {
|
|
|
384
423
|
* Provides methods to query, insert, update, and delete attachment records with
|
|
385
424
|
* proper transaction management through PowerSync.
|
|
386
425
|
*
|
|
387
|
-
* @
|
|
426
|
+
* @experimental
|
|
427
|
+
* @alpha
|
|
388
428
|
*/
|
|
389
429
|
class AttachmentContext {
|
|
390
430
|
/** PowerSync database instance for executing queries */
|
|
@@ -606,6 +646,9 @@ class AttachmentContext {
|
|
|
606
646
|
}
|
|
607
647
|
}
|
|
608
648
|
|
|
649
|
+
/**
|
|
650
|
+
* @public
|
|
651
|
+
*/
|
|
609
652
|
exports.WatchedQueryListenerEvent = void 0;
|
|
610
653
|
(function (WatchedQueryListenerEvent) {
|
|
611
654
|
WatchedQueryListenerEvent["ON_DATA"] = "onData";
|
|
@@ -614,176 +657,18 @@ exports.WatchedQueryListenerEvent = void 0;
|
|
|
614
657
|
WatchedQueryListenerEvent["SETTINGS_WILL_UPDATE"] = "settingsWillUpdate";
|
|
615
658
|
WatchedQueryListenerEvent["CLOSED"] = "closed";
|
|
616
659
|
})(exports.WatchedQueryListenerEvent || (exports.WatchedQueryListenerEvent = {}));
|
|
660
|
+
/**
|
|
661
|
+
* @internal
|
|
662
|
+
*/
|
|
617
663
|
const DEFAULT_WATCH_THROTTLE_MS = 30;
|
|
664
|
+
/**
|
|
665
|
+
* @internal
|
|
666
|
+
*/
|
|
618
667
|
const DEFAULT_WATCH_QUERY_OPTIONS = {
|
|
619
668
|
throttleMs: DEFAULT_WATCH_THROTTLE_MS,
|
|
620
669
|
reportFetching: true
|
|
621
670
|
};
|
|
622
671
|
|
|
623
|
-
/**
|
|
624
|
-
* Orchestrates attachment synchronization between local and remote storage.
|
|
625
|
-
* Handles uploads, downloads, deletions, and state transitions.
|
|
626
|
-
*
|
|
627
|
-
* @internal
|
|
628
|
-
*/
|
|
629
|
-
class SyncingService {
|
|
630
|
-
attachmentService;
|
|
631
|
-
localStorage;
|
|
632
|
-
remoteStorage;
|
|
633
|
-
logger;
|
|
634
|
-
errorHandler;
|
|
635
|
-
constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
|
|
636
|
-
this.attachmentService = attachmentService;
|
|
637
|
-
this.localStorage = localStorage;
|
|
638
|
-
this.remoteStorage = remoteStorage;
|
|
639
|
-
this.logger = logger;
|
|
640
|
-
this.errorHandler = errorHandler;
|
|
641
|
-
}
|
|
642
|
-
/**
|
|
643
|
-
* Processes attachments based on their state (upload, download, or delete).
|
|
644
|
-
* All updates are saved in a single batch after processing.
|
|
645
|
-
*
|
|
646
|
-
* @param attachments - Array of attachment records to process
|
|
647
|
-
* @param context - Attachment context for database operations
|
|
648
|
-
* @returns Promise that resolves when all attachments have been processed and saved
|
|
649
|
-
*/
|
|
650
|
-
async processAttachments(attachments, context) {
|
|
651
|
-
const updatedAttachments = [];
|
|
652
|
-
for (const attachment of attachments) {
|
|
653
|
-
switch (attachment.state) {
|
|
654
|
-
case exports.AttachmentState.QUEUED_UPLOAD:
|
|
655
|
-
const uploaded = await this.uploadAttachment(attachment);
|
|
656
|
-
updatedAttachments.push(uploaded);
|
|
657
|
-
break;
|
|
658
|
-
case exports.AttachmentState.QUEUED_DOWNLOAD:
|
|
659
|
-
const downloaded = await this.downloadAttachment(attachment);
|
|
660
|
-
updatedAttachments.push(downloaded);
|
|
661
|
-
break;
|
|
662
|
-
case exports.AttachmentState.QUEUED_DELETE:
|
|
663
|
-
const deleted = await this.deleteAttachment(attachment, context);
|
|
664
|
-
updatedAttachments.push(deleted);
|
|
665
|
-
break;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
await context.saveAttachments(updatedAttachments);
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
* Uploads an attachment from local storage to remote storage.
|
|
672
|
-
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
673
|
-
*
|
|
674
|
-
* @param attachment - The attachment record to upload
|
|
675
|
-
* @returns Updated attachment record with new state
|
|
676
|
-
* @throws Error if the attachment has no localUri
|
|
677
|
-
*/
|
|
678
|
-
async uploadAttachment(attachment) {
|
|
679
|
-
this.logger.info(`Uploading attachment ${attachment.filename}`);
|
|
680
|
-
try {
|
|
681
|
-
if (attachment.localUri == null) {
|
|
682
|
-
throw new Error(`No localUri for attachment ${attachment.id}`);
|
|
683
|
-
}
|
|
684
|
-
const fileBlob = await this.localStorage.readFile(attachment.localUri);
|
|
685
|
-
await this.remoteStorage.uploadFile(fileBlob, attachment);
|
|
686
|
-
return {
|
|
687
|
-
...attachment,
|
|
688
|
-
state: exports.AttachmentState.SYNCED,
|
|
689
|
-
hasSynced: true
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
catch (error) {
|
|
693
|
-
const shouldRetry = (await this.errorHandler?.onUploadError(attachment, error)) ?? true;
|
|
694
|
-
if (!shouldRetry) {
|
|
695
|
-
return {
|
|
696
|
-
...attachment,
|
|
697
|
-
state: exports.AttachmentState.ARCHIVED
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
|
-
return attachment;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
/**
|
|
704
|
-
* Downloads an attachment from remote storage to local storage.
|
|
705
|
-
* Retrieves the file, converts to base64, and saves locally.
|
|
706
|
-
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
707
|
-
*
|
|
708
|
-
* @param attachment - The attachment record to download
|
|
709
|
-
* @returns Updated attachment record with local URI and new state
|
|
710
|
-
*/
|
|
711
|
-
async downloadAttachment(attachment) {
|
|
712
|
-
this.logger.info(`Downloading attachment ${attachment.filename}`);
|
|
713
|
-
try {
|
|
714
|
-
const fileData = await this.remoteStorage.downloadFile(attachment);
|
|
715
|
-
const localUri = this.localStorage.getLocalUri(attachment.filename);
|
|
716
|
-
await this.localStorage.saveFile(localUri, fileData);
|
|
717
|
-
return {
|
|
718
|
-
...attachment,
|
|
719
|
-
state: exports.AttachmentState.SYNCED,
|
|
720
|
-
localUri: localUri,
|
|
721
|
-
hasSynced: true
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
catch (error) {
|
|
725
|
-
const shouldRetry = (await this.errorHandler?.onDownloadError(attachment, error)) ?? true;
|
|
726
|
-
if (!shouldRetry) {
|
|
727
|
-
return {
|
|
728
|
-
...attachment,
|
|
729
|
-
state: exports.AttachmentState.ARCHIVED
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
return attachment;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* Deletes an attachment from both remote and local storage.
|
|
737
|
-
* Removes the remote file, local file (if exists), and the attachment record.
|
|
738
|
-
* On failure, defers to error handler or archives.
|
|
739
|
-
*
|
|
740
|
-
* @param attachment - The attachment record to delete
|
|
741
|
-
* @param context - Attachment context for database operations
|
|
742
|
-
* @returns Updated attachment record
|
|
743
|
-
*/
|
|
744
|
-
async deleteAttachment(attachment, context) {
|
|
745
|
-
try {
|
|
746
|
-
await this.remoteStorage.deleteFile(attachment);
|
|
747
|
-
if (attachment.localUri) {
|
|
748
|
-
await this.localStorage.deleteFile(attachment.localUri);
|
|
749
|
-
}
|
|
750
|
-
await context.deleteAttachment(attachment.id);
|
|
751
|
-
return {
|
|
752
|
-
...attachment,
|
|
753
|
-
state: exports.AttachmentState.ARCHIVED
|
|
754
|
-
};
|
|
755
|
-
}
|
|
756
|
-
catch (error) {
|
|
757
|
-
const shouldRetry = (await this.errorHandler?.onDeleteError(attachment, error)) ?? true;
|
|
758
|
-
if (!shouldRetry) {
|
|
759
|
-
return {
|
|
760
|
-
...attachment,
|
|
761
|
-
state: exports.AttachmentState.ARCHIVED
|
|
762
|
-
};
|
|
763
|
-
}
|
|
764
|
-
return attachment;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
/**
|
|
768
|
-
* Performs cleanup of archived attachments by removing their local files and records.
|
|
769
|
-
* Errors during local file deletion are logged but do not prevent record deletion.
|
|
770
|
-
*/
|
|
771
|
-
async deleteArchivedAttachments(context) {
|
|
772
|
-
return await context.deleteArchivedAttachments(async (archivedAttachments) => {
|
|
773
|
-
for (const attachment of archivedAttachments) {
|
|
774
|
-
if (attachment.localUri) {
|
|
775
|
-
try {
|
|
776
|
-
await this.localStorage.deleteFile(attachment.localUri);
|
|
777
|
-
}
|
|
778
|
-
catch (error) {
|
|
779
|
-
this.logger.error('Error deleting local file for archived attachment', error);
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
672
|
/**
|
|
788
673
|
* A simple fixed-capacity queue implementation.
|
|
789
674
|
*
|
|
@@ -969,6 +854,9 @@ class Mutex {
|
|
|
969
854
|
}
|
|
970
855
|
}
|
|
971
856
|
}
|
|
857
|
+
/**
|
|
858
|
+
* @internal
|
|
859
|
+
*/
|
|
972
860
|
function timeoutSignal(timeout) {
|
|
973
861
|
if (timeout == null)
|
|
974
862
|
return;
|
|
@@ -997,36 +885,200 @@ class AttachmentService {
|
|
|
997
885
|
this.context = new AttachmentContext(db, tableName, logger, archivedCacheLimit);
|
|
998
886
|
}
|
|
999
887
|
/**
|
|
1000
|
-
* Creates a differential watch query for active attachments requiring synchronization.
|
|
1001
|
-
* @returns Watch query that emits changes for queued uploads, downloads, and deletes
|
|
888
|
+
* Creates a differential watch query for active attachments requiring synchronization.
|
|
889
|
+
* @returns Watch query that emits changes for queued uploads, downloads, and deletes
|
|
890
|
+
*/
|
|
891
|
+
watchActiveAttachments({ throttleMs } = {}) {
|
|
892
|
+
this.logger.info('Watching active attachments...');
|
|
893
|
+
const watch = this.db
|
|
894
|
+
.query({
|
|
895
|
+
sql: /* sql */ `
|
|
896
|
+
SELECT
|
|
897
|
+
*
|
|
898
|
+
FROM
|
|
899
|
+
${this.tableName}
|
|
900
|
+
WHERE
|
|
901
|
+
state = ?
|
|
902
|
+
OR state = ?
|
|
903
|
+
OR state = ?
|
|
904
|
+
ORDER BY
|
|
905
|
+
timestamp ASC
|
|
906
|
+
`,
|
|
907
|
+
parameters: [exports.AttachmentState.QUEUED_UPLOAD, exports.AttachmentState.QUEUED_DOWNLOAD, exports.AttachmentState.QUEUED_DELETE]
|
|
908
|
+
})
|
|
909
|
+
.differentialWatch({ throttleMs });
|
|
910
|
+
return watch;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Executes a callback with exclusive access to the attachment context.
|
|
914
|
+
*/
|
|
915
|
+
async withContext(callback) {
|
|
916
|
+
return this.mutex.runExclusive(async () => {
|
|
917
|
+
return callback(this.context);
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* Orchestrates attachment synchronization between local and remote storage.
|
|
924
|
+
* Handles uploads, downloads, deletions, and state transitions.
|
|
925
|
+
*
|
|
926
|
+
* @internal
|
|
927
|
+
*/
|
|
928
|
+
class SyncingService {
|
|
929
|
+
attachmentService;
|
|
930
|
+
localStorage;
|
|
931
|
+
remoteStorage;
|
|
932
|
+
logger;
|
|
933
|
+
errorHandler;
|
|
934
|
+
constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
|
|
935
|
+
this.attachmentService = attachmentService;
|
|
936
|
+
this.localStorage = localStorage;
|
|
937
|
+
this.remoteStorage = remoteStorage;
|
|
938
|
+
this.logger = logger;
|
|
939
|
+
this.errorHandler = errorHandler;
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Processes attachments based on their state (upload, download, or delete).
|
|
943
|
+
* All updates are saved in a single batch after processing.
|
|
944
|
+
*
|
|
945
|
+
* @param attachments - Array of attachment records to process
|
|
946
|
+
* @param context - Attachment context for database operations
|
|
947
|
+
* @returns Promise that resolves when all attachments have been processed and saved
|
|
948
|
+
*/
|
|
949
|
+
async processAttachments(attachments, context) {
|
|
950
|
+
const updatedAttachments = [];
|
|
951
|
+
for (const attachment of attachments) {
|
|
952
|
+
switch (attachment.state) {
|
|
953
|
+
case exports.AttachmentState.QUEUED_UPLOAD:
|
|
954
|
+
const uploaded = await this.uploadAttachment(attachment);
|
|
955
|
+
updatedAttachments.push(uploaded);
|
|
956
|
+
break;
|
|
957
|
+
case exports.AttachmentState.QUEUED_DOWNLOAD:
|
|
958
|
+
const downloaded = await this.downloadAttachment(attachment);
|
|
959
|
+
updatedAttachments.push(downloaded);
|
|
960
|
+
break;
|
|
961
|
+
case exports.AttachmentState.QUEUED_DELETE:
|
|
962
|
+
const deleted = await this.deleteAttachment(attachment, context);
|
|
963
|
+
updatedAttachments.push(deleted);
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
await context.saveAttachments(updatedAttachments);
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Uploads an attachment from local storage to remote storage.
|
|
971
|
+
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
972
|
+
*
|
|
973
|
+
* @param attachment - The attachment record to upload
|
|
974
|
+
* @returns Updated attachment record with new state
|
|
975
|
+
* @throws Error if the attachment has no localUri
|
|
976
|
+
*/
|
|
977
|
+
async uploadAttachment(attachment) {
|
|
978
|
+
this.logger.info(`Uploading attachment ${attachment.filename}`);
|
|
979
|
+
try {
|
|
980
|
+
if (attachment.localUri == null) {
|
|
981
|
+
throw new Error(`No localUri for attachment ${attachment.id}`);
|
|
982
|
+
}
|
|
983
|
+
const fileBlob = await this.localStorage.readFile(attachment.localUri);
|
|
984
|
+
await this.remoteStorage.uploadFile(fileBlob, attachment);
|
|
985
|
+
return {
|
|
986
|
+
...attachment,
|
|
987
|
+
state: exports.AttachmentState.SYNCED,
|
|
988
|
+
hasSynced: true
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
catch (error) {
|
|
992
|
+
const shouldRetry = (await this.errorHandler?.onUploadError(attachment, error)) ?? true;
|
|
993
|
+
if (!shouldRetry) {
|
|
994
|
+
return {
|
|
995
|
+
...attachment,
|
|
996
|
+
state: exports.AttachmentState.ARCHIVED
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
return attachment;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Downloads an attachment from remote storage to local storage.
|
|
1004
|
+
* Retrieves the file, converts to base64, and saves locally.
|
|
1005
|
+
* On success, marks as SYNCED. On failure, defers to error handler or archives.
|
|
1006
|
+
*
|
|
1007
|
+
* @param attachment - The attachment record to download
|
|
1008
|
+
* @returns Updated attachment record with local URI and new state
|
|
1009
|
+
*/
|
|
1010
|
+
async downloadAttachment(attachment) {
|
|
1011
|
+
this.logger.info(`Downloading attachment ${attachment.filename}`);
|
|
1012
|
+
try {
|
|
1013
|
+
const fileData = await this.remoteStorage.downloadFile(attachment);
|
|
1014
|
+
const localUri = this.localStorage.getLocalUri(attachment.filename);
|
|
1015
|
+
await this.localStorage.saveFile(localUri, fileData);
|
|
1016
|
+
return {
|
|
1017
|
+
...attachment,
|
|
1018
|
+
state: exports.AttachmentState.SYNCED,
|
|
1019
|
+
localUri: localUri,
|
|
1020
|
+
hasSynced: true
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
catch (error) {
|
|
1024
|
+
const shouldRetry = (await this.errorHandler?.onDownloadError(attachment, error)) ?? true;
|
|
1025
|
+
if (!shouldRetry) {
|
|
1026
|
+
return {
|
|
1027
|
+
...attachment,
|
|
1028
|
+
state: exports.AttachmentState.ARCHIVED
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
return attachment;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Deletes an attachment from both remote and local storage.
|
|
1036
|
+
* Removes the remote file, local file (if exists), and the attachment record.
|
|
1037
|
+
* On failure, defers to error handler or archives.
|
|
1038
|
+
*
|
|
1039
|
+
* @param attachment - The attachment record to delete
|
|
1040
|
+
* @param context - Attachment context for database operations
|
|
1041
|
+
* @returns Updated attachment record
|
|
1002
1042
|
*/
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
.
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1043
|
+
async deleteAttachment(attachment, context) {
|
|
1044
|
+
try {
|
|
1045
|
+
await this.remoteStorage.deleteFile(attachment);
|
|
1046
|
+
if (attachment.localUri) {
|
|
1047
|
+
await this.localStorage.deleteFile(attachment.localUri);
|
|
1048
|
+
}
|
|
1049
|
+
await context.deleteAttachment(attachment.id);
|
|
1050
|
+
return {
|
|
1051
|
+
...attachment,
|
|
1052
|
+
state: exports.AttachmentState.ARCHIVED
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
catch (error) {
|
|
1056
|
+
const shouldRetry = (await this.errorHandler?.onDeleteError(attachment, error)) ?? true;
|
|
1057
|
+
if (!shouldRetry) {
|
|
1058
|
+
return {
|
|
1059
|
+
...attachment,
|
|
1060
|
+
state: exports.AttachmentState.ARCHIVED
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
return attachment;
|
|
1064
|
+
}
|
|
1023
1065
|
}
|
|
1024
1066
|
/**
|
|
1025
|
-
*
|
|
1067
|
+
* Performs cleanup of archived attachments by removing their local files and records.
|
|
1068
|
+
* Errors during local file deletion are logged but do not prevent record deletion.
|
|
1026
1069
|
*/
|
|
1027
|
-
async
|
|
1028
|
-
return
|
|
1029
|
-
|
|
1070
|
+
async deleteArchivedAttachments(context) {
|
|
1071
|
+
return await context.deleteArchivedAttachments(async (archivedAttachments) => {
|
|
1072
|
+
for (const attachment of archivedAttachments) {
|
|
1073
|
+
if (attachment.localUri) {
|
|
1074
|
+
try {
|
|
1075
|
+
await this.localStorage.deleteFile(attachment.localUri);
|
|
1076
|
+
}
|
|
1077
|
+
catch (error) {
|
|
1078
|
+
this.logger.error('Error deleting local file for archived attachment', error);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1030
1082
|
});
|
|
1031
1083
|
}
|
|
1032
1084
|
}
|
|
@@ -1087,16 +1139,6 @@ class AttachmentQueue {
|
|
|
1087
1139
|
* Creates a new AttachmentQueue instance.
|
|
1088
1140
|
*
|
|
1089
1141
|
* @param options - Configuration options
|
|
1090
|
-
* @param options.db - PowerSync database instance
|
|
1091
|
-
* @param options.remoteStorage - Remote storage adapter for upload/download operations
|
|
1092
|
-
* @param options.localStorage - Local storage adapter for file persistence
|
|
1093
|
-
* @param options.watchAttachments - Callback for monitoring attachment changes in your data model
|
|
1094
|
-
* @param options.tableName - Name of the table to store attachment records. Default: 'ps_attachment_queue'
|
|
1095
|
-
* @param options.logger - Logger instance. Defaults to db.logger
|
|
1096
|
-
* @param options.syncIntervalMs - Periodic polling interval in milliseconds for retrying failed uploads/downloads. Default: 30000
|
|
1097
|
-
* @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
|
|
1098
|
-
* @param options.downloadAttachments - Whether to automatically download remote attachments. Default: true
|
|
1099
|
-
* @param options.archivedCacheLimit - Maximum archived attachments before cleanup. Default: 100
|
|
1100
1142
|
*/
|
|
1101
1143
|
constructor({ db, localStorage, remoteStorage, watchAttachments, logger, tableName = ATTACHMENT_TABLE, syncIntervalMs = 30 * 1000, syncThrottleDuration = DEFAULT_WATCH_THROTTLE_MS, downloadAttachments = true, archivedCacheLimit = 100, errorHandler }) {
|
|
1102
1144
|
this.db = db;
|
|
@@ -1185,6 +1227,7 @@ class AttachmentQueue {
|
|
|
1185
1227
|
state: exports.AttachmentState.QUEUED_DOWNLOAD,
|
|
1186
1228
|
hasSynced: false,
|
|
1187
1229
|
metaData: watchedAttachment.metaData,
|
|
1230
|
+
mediaType: watchedAttachment.mediaType,
|
|
1188
1231
|
timestamp: new Date().getTime()
|
|
1189
1232
|
});
|
|
1190
1233
|
continue;
|
|
@@ -1272,17 +1315,24 @@ class AttachmentQueue {
|
|
|
1272
1315
|
this.statusListenerDispose = undefined;
|
|
1273
1316
|
}
|
|
1274
1317
|
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Provides an {@link AttachmentContext} to a callback.
|
|
1320
|
+
*
|
|
1321
|
+
* The callback runs while the attachment queue mutex is held. Do not call
|
|
1322
|
+
* other {@link AttachmentQueue} methods from within the callback, as they may
|
|
1323
|
+
* attempt to acquire the same mutex and block indefinitely.
|
|
1324
|
+
*/
|
|
1325
|
+
withAttachmentContext(callback) {
|
|
1326
|
+
/**
|
|
1327
|
+
* AttachmentService is internal and private in this class.
|
|
1328
|
+
* We only need to expose its locking and context functionality for extending classes.
|
|
1329
|
+
*/
|
|
1330
|
+
return this.attachmentService.withContext(callback);
|
|
1331
|
+
}
|
|
1275
1332
|
/**
|
|
1276
1333
|
* Saves a file to local storage and queues it for upload to remote storage.
|
|
1277
1334
|
*
|
|
1278
1335
|
* @param options - File save options
|
|
1279
|
-
* @param options.data - The file data as ArrayBuffer, Blob, or base64 string
|
|
1280
|
-
* @param options.fileExtension - File extension (e.g., 'jpg', 'pdf')
|
|
1281
|
-
* @param options.mediaType - MIME type of the file (e.g., 'image/jpeg')
|
|
1282
|
-
* @param options.metaData - Optional metadata to associate with the attachment
|
|
1283
|
-
* @param options.id - Optional custom ID. If not provided, a UUID will be generated
|
|
1284
|
-
* @param options.updateHook - Optional callback to execute additional database operations
|
|
1285
|
-
* within the same transaction as the attachment creation
|
|
1286
1336
|
* @returns Promise resolving to the created attachment record
|
|
1287
1337
|
*/
|
|
1288
1338
|
async saveFile({ data, fileExtension, mediaType, metaData, id, updateHook }) {
|
|
@@ -1395,6 +1445,9 @@ class AttachmentQueue {
|
|
|
1395
1445
|
}
|
|
1396
1446
|
}
|
|
1397
1447
|
|
|
1448
|
+
/**
|
|
1449
|
+
* @alpha
|
|
1450
|
+
*/
|
|
1398
1451
|
exports.EncodingType = void 0;
|
|
1399
1452
|
(function (EncodingType) {
|
|
1400
1453
|
EncodingType["UTF8"] = "utf8";
|
|
@@ -1703,7 +1756,9 @@ var Logger = /*@__PURE__*/getDefaultExportFromCjs(loggerExports);
|
|
|
1703
1756
|
* different SQLite DB implementations.
|
|
1704
1757
|
*/
|
|
1705
1758
|
/**
|
|
1706
|
-
* Implements {@link DBGetUtils} on a {@link
|
|
1759
|
+
* Implements {@link DBGetUtils} on a {@link SqlExecutor}.
|
|
1760
|
+
*
|
|
1761
|
+
* @internal
|
|
1707
1762
|
*/
|
|
1708
1763
|
function DBGetUtilsDefaultMixin(Base) {
|
|
1709
1764
|
return class extends Base {
|
|
@@ -1747,6 +1802,8 @@ function DBGetUtilsDefaultMixin(Base) {
|
|
|
1747
1802
|
}
|
|
1748
1803
|
/**
|
|
1749
1804
|
* Update table operation numbers from SQLite
|
|
1805
|
+
*
|
|
1806
|
+
* @public
|
|
1750
1807
|
*/
|
|
1751
1808
|
exports.RowUpdateType = void 0;
|
|
1752
1809
|
(function (RowUpdateType) {
|
|
@@ -1755,8 +1812,10 @@ exports.RowUpdateType = void 0;
|
|
|
1755
1812
|
RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
|
|
1756
1813
|
})(exports.RowUpdateType || (exports.RowUpdateType = {}));
|
|
1757
1814
|
/**
|
|
1758
|
-
* A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool
|
|
1759
|
-
* {@link ConnectionPool
|
|
1815
|
+
* A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool#readLock} and
|
|
1816
|
+
* {@link ConnectionPool#writeLock}.
|
|
1817
|
+
*
|
|
1818
|
+
* @internal
|
|
1760
1819
|
*/
|
|
1761
1820
|
function DBAdapterDefaultMixin(Base) {
|
|
1762
1821
|
return class extends Base {
|
|
@@ -1844,9 +1903,15 @@ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction)
|
|
|
1844
1903
|
}
|
|
1845
1904
|
}
|
|
1846
1905
|
}
|
|
1906
|
+
/**
|
|
1907
|
+
* @internal
|
|
1908
|
+
*/
|
|
1847
1909
|
function isBatchedUpdateNotification(update) {
|
|
1848
1910
|
return 'tables' in update;
|
|
1849
1911
|
}
|
|
1912
|
+
/**
|
|
1913
|
+
* @internal
|
|
1914
|
+
*/
|
|
1850
1915
|
function extractTableUpdates(update) {
|
|
1851
1916
|
return isBatchedUpdateNotification(update) ? update.tables : [update.table];
|
|
1852
1917
|
}
|
|
@@ -1874,6 +1939,8 @@ const FULL_SYNC_PRIORITY = 2147483647;
|
|
|
1874
1939
|
*
|
|
1875
1940
|
* Also note that data is downloaded in bulk, which means that individual counters are unlikely
|
|
1876
1941
|
* to be updated one-by-one.
|
|
1942
|
+
*
|
|
1943
|
+
* @public
|
|
1877
1944
|
*/
|
|
1878
1945
|
class SyncProgress {
|
|
1879
1946
|
internal;
|
|
@@ -1912,6 +1979,9 @@ class SyncProgress {
|
|
|
1912
1979
|
}
|
|
1913
1980
|
}
|
|
1914
1981
|
|
|
1982
|
+
/**
|
|
1983
|
+
* @public
|
|
1984
|
+
*/
|
|
1915
1985
|
class SyncStatus {
|
|
1916
1986
|
options;
|
|
1917
1987
|
constructor(options) {
|
|
@@ -1922,6 +1992,8 @@ class SyncStatus {
|
|
|
1922
1992
|
* implementation).
|
|
1923
1993
|
*
|
|
1924
1994
|
* This information is only available after a connection has been requested.
|
|
1995
|
+
*
|
|
1996
|
+
* @deprecated This always returns the Rust client (the only option).
|
|
1925
1997
|
*/
|
|
1926
1998
|
get clientImplementation() {
|
|
1927
1999
|
return this.options.clientImplementation;
|
|
@@ -1929,7 +2001,7 @@ class SyncStatus {
|
|
|
1929
2001
|
/**
|
|
1930
2002
|
* Indicates if the client is currently connected to the PowerSync service.
|
|
1931
2003
|
*
|
|
1932
|
-
* @returns
|
|
2004
|
+
* @returns True if connected, false otherwise. Defaults to false if not specified.
|
|
1933
2005
|
*/
|
|
1934
2006
|
get connected() {
|
|
1935
2007
|
return this.options.connected ?? false;
|
|
@@ -1937,7 +2009,7 @@ class SyncStatus {
|
|
|
1937
2009
|
/**
|
|
1938
2010
|
* Indicates if the client is in the process of establishing a connection to the PowerSync service.
|
|
1939
2011
|
*
|
|
1940
|
-
* @returns
|
|
2012
|
+
* @returns True if connecting, false otherwise. Defaults to false if not specified.
|
|
1941
2013
|
*/
|
|
1942
2014
|
get connecting() {
|
|
1943
2015
|
return this.options.connecting ?? false;
|
|
@@ -1946,7 +2018,7 @@ class SyncStatus {
|
|
|
1946
2018
|
* Time that a last sync has fully completed, if any.
|
|
1947
2019
|
* This timestamp is reset to null after a restart of the PowerSync service.
|
|
1948
2020
|
*
|
|
1949
|
-
* @returns
|
|
2021
|
+
* @returns The timestamp of the last successful sync, or undefined if no sync has completed.
|
|
1950
2022
|
*/
|
|
1951
2023
|
get lastSyncedAt() {
|
|
1952
2024
|
return this.options.lastSyncedAt;
|
|
@@ -1954,7 +2026,7 @@ class SyncStatus {
|
|
|
1954
2026
|
/**
|
|
1955
2027
|
* Indicates whether there has been at least one full sync completed since initialization.
|
|
1956
2028
|
*
|
|
1957
|
-
* @returns
|
|
2029
|
+
* @returns True if at least one sync has completed, false if no sync has completed,
|
|
1958
2030
|
* or undefined when the state is still being loaded from the database.
|
|
1959
2031
|
*/
|
|
1960
2032
|
get hasSynced() {
|
|
@@ -1963,10 +2035,10 @@ class SyncStatus {
|
|
|
1963
2035
|
/**
|
|
1964
2036
|
* Provides the current data flow status regarding uploads and downloads.
|
|
1965
2037
|
*
|
|
1966
|
-
* @returns
|
|
2038
|
+
* @returns An object containing:
|
|
1967
2039
|
* - downloading: True if actively downloading changes (only when connected is also true)
|
|
1968
2040
|
* - uploading: True if actively uploading changes
|
|
1969
|
-
* Defaults to {downloading: false, uploading: false} if not specified.
|
|
2041
|
+
* Defaults to `{downloading: false, uploading: false}` if not specified.
|
|
1970
2042
|
*/
|
|
1971
2043
|
get dataFlowStatus() {
|
|
1972
2044
|
return (this.options.dataFlow ?? {
|
|
@@ -1991,7 +2063,7 @@ class SyncStatus {
|
|
|
1991
2063
|
return this.options.dataFlow?.internalStreamSubscriptions?.map((core) => new SyncStreamStatusView(this, core));
|
|
1992
2064
|
}
|
|
1993
2065
|
/**
|
|
1994
|
-
* If the `stream` appears in {@link syncStreams}, returns the current status for that stream.
|
|
2066
|
+
* If the `stream` appears in {@link SyncStatus.syncStreams}, returns the current status for that stream.
|
|
1995
2067
|
*/
|
|
1996
2068
|
forStream(stream) {
|
|
1997
2069
|
const asJson = JSON.stringify(stream.parameters);
|
|
@@ -2001,7 +2073,7 @@ class SyncStatus {
|
|
|
2001
2073
|
/**
|
|
2002
2074
|
* Provides sync status information for all bucket priorities, sorted by priority (highest first).
|
|
2003
2075
|
*
|
|
2004
|
-
* @returns
|
|
2076
|
+
* @returns An array of status entries for different sync priority levels,
|
|
2005
2077
|
* sorted with highest priorities (lower numbers) first.
|
|
2006
2078
|
*/
|
|
2007
2079
|
get priorityStatusEntries() {
|
|
@@ -2036,8 +2108,8 @@ class SyncStatus {
|
|
|
2036
2108
|
* For example, if PowerSync just finished synchronizing buckets in priority level 3, calling this method
|
|
2037
2109
|
* with a priority of 1 may return information for priority level 3.
|
|
2038
2110
|
*
|
|
2039
|
-
* @param
|
|
2040
|
-
* @returns
|
|
2111
|
+
* @param priority - The bucket priority for which the status should be reported
|
|
2112
|
+
* @returns Status information for the requested priority level or the next higher level with available status
|
|
2041
2113
|
*/
|
|
2042
2114
|
statusForPriority(priority) {
|
|
2043
2115
|
// priorityStatusEntries are sorted by ascending priorities (so higher numbers to lower numbers).
|
|
@@ -2058,8 +2130,8 @@ class SyncStatus {
|
|
|
2058
2130
|
* Compares this SyncStatus instance with another to determine if they are equal.
|
|
2059
2131
|
* Equality is determined by comparing the serialized JSON representation of both instances.
|
|
2060
2132
|
*
|
|
2061
|
-
* @param
|
|
2062
|
-
* @returns
|
|
2133
|
+
* @param status - The SyncStatus instance to compare against
|
|
2134
|
+
* @returns True if the instances are considered equal, false otherwise
|
|
2063
2135
|
*/
|
|
2064
2136
|
isEqual(status) {
|
|
2065
2137
|
/**
|
|
@@ -2082,7 +2154,7 @@ class SyncStatus {
|
|
|
2082
2154
|
* Creates a human-readable string representation of the current sync status.
|
|
2083
2155
|
* Includes information about connection state, sync completion, and data flow.
|
|
2084
2156
|
*
|
|
2085
|
-
* @returns
|
|
2157
|
+
* @returns A string representation of the sync status
|
|
2086
2158
|
*/
|
|
2087
2159
|
getMessage() {
|
|
2088
2160
|
const dataFlow = this.dataFlowStatus;
|
|
@@ -2091,7 +2163,7 @@ class SyncStatus {
|
|
|
2091
2163
|
/**
|
|
2092
2164
|
* Serializes the SyncStatus instance to a plain object.
|
|
2093
2165
|
*
|
|
2094
|
-
* @returns
|
|
2166
|
+
* @returns A plain object representation of the sync status
|
|
2095
2167
|
*/
|
|
2096
2168
|
toJSON() {
|
|
2097
2169
|
return {
|
|
@@ -2157,6 +2229,9 @@ class SyncStreamStatusView {
|
|
|
2157
2229
|
}
|
|
2158
2230
|
}
|
|
2159
2231
|
|
|
2232
|
+
/**
|
|
2233
|
+
* @public
|
|
2234
|
+
*/
|
|
2160
2235
|
class UploadQueueStats {
|
|
2161
2236
|
count;
|
|
2162
2237
|
size;
|
|
@@ -2182,6 +2257,9 @@ class UploadQueueStats {
|
|
|
2182
2257
|
}
|
|
2183
2258
|
}
|
|
2184
2259
|
|
|
2260
|
+
/**
|
|
2261
|
+
* @internal
|
|
2262
|
+
*/
|
|
2185
2263
|
class BaseObserver {
|
|
2186
2264
|
listeners = new Set();
|
|
2187
2265
|
constructor() { }
|
|
@@ -2209,6 +2287,9 @@ class BaseObserver {
|
|
|
2209
2287
|
}
|
|
2210
2288
|
}
|
|
2211
2289
|
|
|
2290
|
+
/**
|
|
2291
|
+
* @internal
|
|
2292
|
+
*/
|
|
2212
2293
|
class ControlledExecutor {
|
|
2213
2294
|
task;
|
|
2214
2295
|
/**
|
|
@@ -2278,30 +2359,44 @@ function throttleTrailing(func, wait) {
|
|
|
2278
2359
|
}
|
|
2279
2360
|
};
|
|
2280
2361
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2362
|
+
function asyncNotifier() {
|
|
2363
|
+
let waitingConsumer = null;
|
|
2364
|
+
let hasPendingNotification = false;
|
|
2365
|
+
return {
|
|
2366
|
+
notify() {
|
|
2367
|
+
if (waitingConsumer != null) {
|
|
2368
|
+
waitingConsumer();
|
|
2369
|
+
waitingConsumer = null;
|
|
2370
|
+
}
|
|
2371
|
+
else {
|
|
2372
|
+
hasPendingNotification = true;
|
|
2373
|
+
}
|
|
2374
|
+
},
|
|
2375
|
+
waitForNotification(signal) {
|
|
2376
|
+
return new Promise((resolve) => {
|
|
2377
|
+
if (waitingConsumer != null) {
|
|
2378
|
+
throw new Error('Illegal call to waitForNotification, already has a waiter.');
|
|
2379
|
+
}
|
|
2380
|
+
if (signal.aborted) {
|
|
2381
|
+
resolve();
|
|
2382
|
+
}
|
|
2383
|
+
else if (hasPendingNotification) {
|
|
2384
|
+
resolve();
|
|
2385
|
+
hasPendingNotification = false;
|
|
2386
|
+
}
|
|
2387
|
+
else {
|
|
2388
|
+
function complete() {
|
|
2389
|
+
signal.removeEventListener('abort', onAbort);
|
|
2390
|
+
resolve();
|
|
2391
|
+
}
|
|
2392
|
+
function onAbort() {
|
|
2393
|
+
waitingConsumer = null;
|
|
2394
|
+
resolve();
|
|
2395
|
+
}
|
|
2396
|
+
waitingConsumer = complete;
|
|
2397
|
+
signal.addEventListener('abort', onAbort);
|
|
2398
|
+
}
|
|
2399
|
+
});
|
|
2305
2400
|
}
|
|
2306
2401
|
};
|
|
2307
2402
|
}
|
|
@@ -2462,7 +2557,7 @@ class ConnectionManager extends BaseObserver {
|
|
|
2462
2557
|
/**
|
|
2463
2558
|
* Close the sync connection.
|
|
2464
2559
|
*
|
|
2465
|
-
* Use {@link connect} to connect again.
|
|
2560
|
+
* Use {@link ConnectionManager.connect} to connect again.
|
|
2466
2561
|
*/
|
|
2467
2562
|
async disconnect() {
|
|
2468
2563
|
// This will help abort pending connects
|
|
@@ -2602,6 +2697,8 @@ const _finalizer = 'FinalizationRegistry' in globalThis
|
|
|
2602
2697
|
/**
|
|
2603
2698
|
* An efficient comparator for {@link WatchedQuery} created with {@link Query#watch}. This has the ability to determine if a query
|
|
2604
2699
|
* result has changes without necessarily processing all items in the result.
|
|
2700
|
+
*
|
|
2701
|
+
* @public
|
|
2605
2702
|
*/
|
|
2606
2703
|
class ArrayComparator {
|
|
2607
2704
|
options;
|
|
@@ -2629,6 +2726,8 @@ class ArrayComparator {
|
|
|
2629
2726
|
}
|
|
2630
2727
|
/**
|
|
2631
2728
|
* Watched query comparator that always reports changed result sets.
|
|
2729
|
+
*
|
|
2730
|
+
* @public
|
|
2632
2731
|
*/
|
|
2633
2732
|
const FalsyComparator = {
|
|
2634
2733
|
checkEquality: () => false // Default comparator that always returns false
|
|
@@ -2836,6 +2935,8 @@ class AbstractQueryProcessor extends MetaBaseObserver {
|
|
|
2836
2935
|
/**
|
|
2837
2936
|
* An empty differential result set.
|
|
2838
2937
|
* This is used as the initial state for differential incrementally watched queries.
|
|
2938
|
+
*
|
|
2939
|
+
* @internal
|
|
2839
2940
|
*/
|
|
2840
2941
|
const EMPTY_DIFFERENTIAL = {
|
|
2841
2942
|
added: [],
|
|
@@ -2848,6 +2949,8 @@ const EMPTY_DIFFERENTIAL = {
|
|
|
2848
2949
|
* Default implementation of the {@link DifferentialWatchedQueryComparator} for watched queries.
|
|
2849
2950
|
* It keys items by their `id` property if available, alternatively it uses JSON stringification
|
|
2850
2951
|
* of the entire item for the key and comparison.
|
|
2952
|
+
*
|
|
2953
|
+
* @internal
|
|
2851
2954
|
*/
|
|
2852
2955
|
const DEFAULT_ROW_COMPARATOR = {
|
|
2853
2956
|
keyBy: (item) => {
|
|
@@ -3128,6 +3231,8 @@ class CustomQuery {
|
|
|
3128
3231
|
|
|
3129
3232
|
/**
|
|
3130
3233
|
* Tests if the input is a {@link SQLOpenOptions}
|
|
3234
|
+
*
|
|
3235
|
+
* @internal
|
|
3131
3236
|
*/
|
|
3132
3237
|
const isSQLOpenOptions = (test) => {
|
|
3133
3238
|
// typeof null is `object`, but you cannot use the `in` operator on `null.
|
|
@@ -3135,17 +3240,24 @@ const isSQLOpenOptions = (test) => {
|
|
|
3135
3240
|
};
|
|
3136
3241
|
/**
|
|
3137
3242
|
* Tests if input is a {@link SQLOpenFactory}
|
|
3243
|
+
*
|
|
3244
|
+
* @internal
|
|
3138
3245
|
*/
|
|
3139
3246
|
const isSQLOpenFactory = (test) => {
|
|
3140
3247
|
return typeof test?.openDB == 'function';
|
|
3141
3248
|
};
|
|
3142
3249
|
/**
|
|
3143
3250
|
* Tests if input is a {@link DBAdapter}
|
|
3251
|
+
*
|
|
3252
|
+
* @internal
|
|
3144
3253
|
*/
|
|
3145
3254
|
const isDBAdapter = (test) => {
|
|
3146
3255
|
return typeof test?.writeTransaction == 'function';
|
|
3147
3256
|
};
|
|
3148
3257
|
|
|
3258
|
+
/**
|
|
3259
|
+
* @internal
|
|
3260
|
+
*/
|
|
3149
3261
|
exports.PSInternalTable = void 0;
|
|
3150
3262
|
(function (PSInternalTable) {
|
|
3151
3263
|
PSInternalTable["DATA"] = "ps_data";
|
|
@@ -3154,6 +3266,9 @@ exports.PSInternalTable = void 0;
|
|
|
3154
3266
|
PSInternalTable["OPLOG"] = "ps_oplog";
|
|
3155
3267
|
PSInternalTable["UNTYPED"] = "ps_untyped";
|
|
3156
3268
|
})(exports.PSInternalTable || (exports.PSInternalTable = {}));
|
|
3269
|
+
/**
|
|
3270
|
+
* @internal
|
|
3271
|
+
*/
|
|
3157
3272
|
exports.PowerSyncControlCommand = void 0;
|
|
3158
3273
|
(function (PowerSyncControlCommand) {
|
|
3159
3274
|
PowerSyncControlCommand["PROCESS_TEXT_LINE"] = "line_text";
|
|
@@ -3171,6 +3286,8 @@ exports.PowerSyncControlCommand = void 0;
|
|
|
3171
3286
|
|
|
3172
3287
|
/**
|
|
3173
3288
|
* A batch of client-side changes.
|
|
3289
|
+
*
|
|
3290
|
+
* @public
|
|
3174
3291
|
*/
|
|
3175
3292
|
class CrudBatch {
|
|
3176
3293
|
crud;
|
|
@@ -3197,6 +3314,8 @@ class CrudBatch {
|
|
|
3197
3314
|
|
|
3198
3315
|
/**
|
|
3199
3316
|
* Type of local change.
|
|
3317
|
+
*
|
|
3318
|
+
* @public
|
|
3200
3319
|
*/
|
|
3201
3320
|
exports.UpdateType = void 0;
|
|
3202
3321
|
(function (UpdateType) {
|
|
@@ -3209,6 +3328,8 @@ exports.UpdateType = void 0;
|
|
|
3209
3328
|
})(exports.UpdateType || (exports.UpdateType = {}));
|
|
3210
3329
|
/**
|
|
3211
3330
|
* A single client-side change.
|
|
3331
|
+
*
|
|
3332
|
+
* @public
|
|
3212
3333
|
*/
|
|
3213
3334
|
class CrudEntry {
|
|
3214
3335
|
/**
|
|
@@ -3305,6 +3426,9 @@ class CrudEntry {
|
|
|
3305
3426
|
}
|
|
3306
3427
|
}
|
|
3307
3428
|
|
|
3429
|
+
/**
|
|
3430
|
+
* @public
|
|
3431
|
+
*/
|
|
3308
3432
|
class CrudTransaction extends CrudBatch {
|
|
3309
3433
|
crud;
|
|
3310
3434
|
complete;
|
|
@@ -3333,6 +3457,8 @@ class CrudTransaction extends CrudBatch {
|
|
|
3333
3457
|
* Calls to Abortcontroller.abort(reason: any) will result in the
|
|
3334
3458
|
* `reason` being thrown. This is not necessarily an error,
|
|
3335
3459
|
* but extends error for better logging purposes.
|
|
3460
|
+
*
|
|
3461
|
+
* @internal
|
|
3336
3462
|
*/
|
|
3337
3463
|
class AbortOperation extends Error {
|
|
3338
3464
|
reason;
|
|
@@ -8132,7 +8258,7 @@ function requireDist () {
|
|
|
8132
8258
|
|
|
8133
8259
|
var distExports = requireDist();
|
|
8134
8260
|
|
|
8135
|
-
var version = "1.
|
|
8261
|
+
var version = "1.54.0";
|
|
8136
8262
|
var PACKAGE = {
|
|
8137
8263
|
version: version};
|
|
8138
8264
|
|
|
@@ -8262,7 +8388,8 @@ class WebsocketClientTransport {
|
|
|
8262
8388
|
removeListeners();
|
|
8263
8389
|
resolve(new WebsocketDuplexConnectionExports.WebsocketDuplexConnection(websocket, new distExports.Deserializer(), multiplexerDemultiplexerFactory));
|
|
8264
8390
|
};
|
|
8265
|
-
const errorListener = (
|
|
8391
|
+
const errorListener = (event) => {
|
|
8392
|
+
const ev = event;
|
|
8266
8393
|
removeListeners();
|
|
8267
8394
|
// We add a default error in that case.
|
|
8268
8395
|
if (ev.error != null) {
|
|
@@ -8505,7 +8632,13 @@ const SOCKET_TIMEOUT_MS = 30_000;
|
|
|
8505
8632
|
// If there is a backlog of messages (for example on slow connections), keepalive messages could be delayed
|
|
8506
8633
|
// significantly. Therefore this is longer than the socket timeout.
|
|
8507
8634
|
const KEEP_ALIVE_LIFETIME_MS = 90_000;
|
|
8635
|
+
/**
|
|
8636
|
+
* @internal
|
|
8637
|
+
*/
|
|
8508
8638
|
const DEFAULT_REMOTE_LOGGER = Logger.get('PowerSyncRemote');
|
|
8639
|
+
/**
|
|
8640
|
+
* @public
|
|
8641
|
+
*/
|
|
8509
8642
|
exports.FetchStrategy = void 0;
|
|
8510
8643
|
(function (FetchStrategy) {
|
|
8511
8644
|
/**
|
|
@@ -8524,12 +8657,17 @@ exports.FetchStrategy = void 0;
|
|
|
8524
8657
|
* The class wrapper is used to distinguish the fetchImplementation
|
|
8525
8658
|
* option in [AbstractRemoteOptions] from the general fetch method
|
|
8526
8659
|
* which is typeof "function"
|
|
8660
|
+
*
|
|
8661
|
+
* @internal
|
|
8527
8662
|
*/
|
|
8528
8663
|
class FetchImplementationProvider {
|
|
8529
8664
|
getFetch() {
|
|
8530
8665
|
throw new Error('Unspecified fetch implementation');
|
|
8531
8666
|
}
|
|
8532
8667
|
}
|
|
8668
|
+
/**
|
|
8669
|
+
* @internal
|
|
8670
|
+
*/
|
|
8533
8671
|
const DEFAULT_REMOTE_OPTIONS = {
|
|
8534
8672
|
socketUrlTransformer: (url) => url.replace(/^https?:\/\//, function (match) {
|
|
8535
8673
|
return match === 'https://' ? 'wss://' : 'ws://';
|
|
@@ -8537,6 +8675,9 @@ const DEFAULT_REMOTE_OPTIONS = {
|
|
|
8537
8675
|
fetchImplementation: new FetchImplementationProvider(),
|
|
8538
8676
|
fetchOptions: {}
|
|
8539
8677
|
};
|
|
8678
|
+
/**
|
|
8679
|
+
* @internal
|
|
8680
|
+
*/
|
|
8540
8681
|
class AbstractRemote {
|
|
8541
8682
|
connector;
|
|
8542
8683
|
logger;
|
|
@@ -8946,7 +9087,7 @@ class AbstractRemote {
|
|
|
8946
9087
|
* Posts a `/sync/stream` request.
|
|
8947
9088
|
*
|
|
8948
9089
|
* Depending on the `Content-Type` of the response, this returns strings for sync lines or encoded BSON documents as
|
|
8949
|
-
*
|
|
9090
|
+
* `Uint8Array`s.
|
|
8950
9091
|
*/
|
|
8951
9092
|
async fetchStream(options) {
|
|
8952
9093
|
const { isBson, stream } = await this.fetchStreamRaw(options);
|
|
@@ -8988,16 +9129,26 @@ function isInterruptingInstruction(instruction) {
|
|
|
8988
9129
|
return 'EstablishSyncStream' in instruction || 'CloseSyncStream' in instruction;
|
|
8989
9130
|
}
|
|
8990
9131
|
|
|
9132
|
+
/**
|
|
9133
|
+
* @internal
|
|
9134
|
+
*/
|
|
8991
9135
|
exports.LockType = void 0;
|
|
8992
9136
|
(function (LockType) {
|
|
8993
9137
|
LockType["CRUD"] = "crud";
|
|
8994
9138
|
LockType["SYNC"] = "sync";
|
|
8995
9139
|
})(exports.LockType || (exports.LockType = {}));
|
|
9140
|
+
/**
|
|
9141
|
+
* @public
|
|
9142
|
+
*/
|
|
8996
9143
|
exports.SyncStreamConnectionMethod = void 0;
|
|
8997
9144
|
(function (SyncStreamConnectionMethod) {
|
|
8998
9145
|
SyncStreamConnectionMethod["HTTP"] = "http";
|
|
8999
9146
|
SyncStreamConnectionMethod["WEB_SOCKET"] = "web-socket";
|
|
9000
9147
|
})(exports.SyncStreamConnectionMethod || (exports.SyncStreamConnectionMethod = {}));
|
|
9148
|
+
/**
|
|
9149
|
+
* @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
|
|
9150
|
+
* @public
|
|
9151
|
+
*/
|
|
9001
9152
|
exports.SyncClientImplementation = void 0;
|
|
9002
9153
|
(function (SyncClientImplementation) {
|
|
9003
9154
|
/**
|
|
@@ -9009,8 +9160,8 @@ exports.SyncClientImplementation = void 0;
|
|
|
9009
9160
|
* ## Compatibility warning
|
|
9010
9161
|
*
|
|
9011
9162
|
* The Rust sync client stores sync data in a format that is slightly different than the one used
|
|
9012
|
-
* by the old JavaScript client. When adopting the {@link RUST} client on existing databases,
|
|
9013
|
-
* migrate the format automatically.
|
|
9163
|
+
* by the old JavaScript client. When adopting the {@link SyncClientImplementation.RUST} client on existing databases,
|
|
9164
|
+
* the PowerSync SDK will migrate the format automatically.
|
|
9014
9165
|
*
|
|
9015
9166
|
* SDK versions supporting both the JavaScript and the Rust client support both formats with the JavaScript client
|
|
9016
9167
|
* implementaiton. However, downgrading to an SDK version that only supports the JavaScript client would not be
|
|
@@ -9020,14 +9171,29 @@ exports.SyncClientImplementation = void 0;
|
|
|
9020
9171
|
})(exports.SyncClientImplementation || (exports.SyncClientImplementation = {}));
|
|
9021
9172
|
/**
|
|
9022
9173
|
* The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}.
|
|
9174
|
+
*
|
|
9175
|
+
* @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
|
|
9176
|
+
* @public
|
|
9023
9177
|
*/
|
|
9024
9178
|
const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = exports.SyncClientImplementation.RUST;
|
|
9179
|
+
/**
|
|
9180
|
+
* @internal
|
|
9181
|
+
*/
|
|
9025
9182
|
const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
9183
|
+
/**
|
|
9184
|
+
* @internal
|
|
9185
|
+
*/
|
|
9026
9186
|
const DEFAULT_RETRY_DELAY_MS = 5000;
|
|
9187
|
+
/**
|
|
9188
|
+
* @internal
|
|
9189
|
+
*/
|
|
9027
9190
|
const DEFAULT_STREAMING_SYNC_OPTIONS = {
|
|
9028
9191
|
retryDelayMs: DEFAULT_RETRY_DELAY_MS,
|
|
9029
9192
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
9030
9193
|
};
|
|
9194
|
+
/**
|
|
9195
|
+
* @internal
|
|
9196
|
+
*/
|
|
9031
9197
|
const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
9032
9198
|
appMetadata: {},
|
|
9033
9199
|
connectionMethod: exports.SyncStreamConnectionMethod.WEB_SOCKET,
|
|
@@ -9037,22 +9203,21 @@ const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
|
9037
9203
|
serializedSchema: undefined,
|
|
9038
9204
|
includeDefaultStreams: true
|
|
9039
9205
|
};
|
|
9206
|
+
/**
|
|
9207
|
+
* @internal
|
|
9208
|
+
*/
|
|
9040
9209
|
class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
9041
9210
|
options;
|
|
9042
9211
|
abortController;
|
|
9043
|
-
// In rare cases, mostly for tests, uploads can be triggered without being properly connected.
|
|
9044
|
-
// This allows ensuring that all upload processes can be aborted.
|
|
9045
|
-
uploadAbortController;
|
|
9046
9212
|
crudUpdateListener;
|
|
9047
9213
|
streamingSyncPromise;
|
|
9048
9214
|
logger;
|
|
9049
9215
|
activeStreams;
|
|
9050
9216
|
connectionMayHaveChanged = false;
|
|
9051
|
-
|
|
9217
|
+
crudUploadNotifier = asyncNotifier();
|
|
9052
9218
|
notifyCompletedUploads;
|
|
9053
9219
|
handleActiveStreamsChange;
|
|
9054
9220
|
syncStatus;
|
|
9055
|
-
triggerCrudUpload;
|
|
9056
9221
|
constructor(options) {
|
|
9057
9222
|
super();
|
|
9058
9223
|
this.options = options;
|
|
@@ -9068,16 +9233,9 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
9068
9233
|
}
|
|
9069
9234
|
});
|
|
9070
9235
|
this.abortController = null;
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
}
|
|
9075
|
-
this.isUploadingCrud = true;
|
|
9076
|
-
this._uploadAllCrud().finally(() => {
|
|
9077
|
-
this.notifyCompletedUploads?.();
|
|
9078
|
-
this.isUploadingCrud = false;
|
|
9079
|
-
});
|
|
9080
|
-
}, this.options.crudUploadThrottleMs);
|
|
9236
|
+
}
|
|
9237
|
+
triggerCrudUpload() {
|
|
9238
|
+
this.crudUploadNotifier.notify();
|
|
9081
9239
|
}
|
|
9082
9240
|
async waitForReady() { }
|
|
9083
9241
|
waitForStatus(status) {
|
|
@@ -9125,7 +9283,6 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
9125
9283
|
super.dispose();
|
|
9126
9284
|
this.crudUpdateListener?.();
|
|
9127
9285
|
this.crudUpdateListener = undefined;
|
|
9128
|
-
this.uploadAbortController?.abort();
|
|
9129
9286
|
}
|
|
9130
9287
|
async getWriteCheckpoint() {
|
|
9131
9288
|
const clientId = await this.options.adapter.getClientId();
|
|
@@ -9135,7 +9292,17 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
9135
9292
|
this.logger.debug(`Created write checkpoint: ${checkpoint}`);
|
|
9136
9293
|
return checkpoint;
|
|
9137
9294
|
}
|
|
9138
|
-
async
|
|
9295
|
+
async crudUploadLoop(signal) {
|
|
9296
|
+
while (!signal.aborted) {
|
|
9297
|
+
await Promise.all([
|
|
9298
|
+
// Start the initial CRUD upload on connect. Then, keep polling until we're done.
|
|
9299
|
+
this._uploadAllCrud(signal),
|
|
9300
|
+
this.delayRetry(signal, this.options.crudUploadThrottleMs)
|
|
9301
|
+
]);
|
|
9302
|
+
await this.crudUploadNotifier.waitForNotification(signal);
|
|
9303
|
+
}
|
|
9304
|
+
}
|
|
9305
|
+
async _uploadAllCrud(signal) {
|
|
9139
9306
|
return this.obtainLock({
|
|
9140
9307
|
type: exports.LockType.CRUD,
|
|
9141
9308
|
callback: async () => {
|
|
@@ -9143,12 +9310,7 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
9143
9310
|
* Keep track of the first item in the CRUD queue for the last `uploadCrud` iteration.
|
|
9144
9311
|
*/
|
|
9145
9312
|
let checkedCrudItem;
|
|
9146
|
-
|
|
9147
|
-
this.uploadAbortController = controller;
|
|
9148
|
-
this.abortController?.signal.addEventListener('abort', () => {
|
|
9149
|
-
controller.abort();
|
|
9150
|
-
}, { once: true });
|
|
9151
|
-
while (!controller.signal.aborted) {
|
|
9313
|
+
while (!signal.aborted) {
|
|
9152
9314
|
try {
|
|
9153
9315
|
/**
|
|
9154
9316
|
* This is the first item in the FIFO CRUD queue.
|
|
@@ -9178,7 +9340,10 @@ The next upload iteration will be delayed.`);
|
|
|
9178
9340
|
else {
|
|
9179
9341
|
// Uploading is completed
|
|
9180
9342
|
const neededUpdate = await this.options.adapter.updateLocalTarget(() => this.getWriteCheckpoint());
|
|
9181
|
-
if (neededUpdate
|
|
9343
|
+
if (neededUpdate) {
|
|
9344
|
+
this.notifyCompletedUploads?.();
|
|
9345
|
+
}
|
|
9346
|
+
else if (checkedCrudItem != null) {
|
|
9182
9347
|
// Only log this if there was something to upload
|
|
9183
9348
|
this.logger.debug('Upload complete, no write checkpoint needed.');
|
|
9184
9349
|
}
|
|
@@ -9193,7 +9358,7 @@ The next upload iteration will be delayed.`);
|
|
|
9193
9358
|
uploadError: ex
|
|
9194
9359
|
}
|
|
9195
9360
|
});
|
|
9196
|
-
await this.delayRetry(
|
|
9361
|
+
await this.delayRetry(signal);
|
|
9197
9362
|
if (!this.isConnected) {
|
|
9198
9363
|
// Exit the upload loop if the sync stream is no longer connected
|
|
9199
9364
|
break;
|
|
@@ -9208,7 +9373,6 @@ The next upload iteration will be delayed.`);
|
|
|
9208
9373
|
});
|
|
9209
9374
|
}
|
|
9210
9375
|
}
|
|
9211
|
-
this.uploadAbortController = undefined;
|
|
9212
9376
|
}
|
|
9213
9377
|
});
|
|
9214
9378
|
}
|
|
@@ -9218,7 +9382,10 @@ The next upload iteration will be delayed.`);
|
|
|
9218
9382
|
}
|
|
9219
9383
|
const controller = new AbortController();
|
|
9220
9384
|
this.abortController = controller;
|
|
9221
|
-
this.streamingSyncPromise =
|
|
9385
|
+
this.streamingSyncPromise = Promise.all([
|
|
9386
|
+
this.crudUploadLoop(controller.signal).catch((ex) => this.logger.error('Error in crud upload loop', ex)),
|
|
9387
|
+
this.streamingSync(controller.signal, options)
|
|
9388
|
+
]);
|
|
9222
9389
|
// Return a promise that resolves when the connection status is updated to indicate that we're connected.
|
|
9223
9390
|
return new Promise((resolve) => {
|
|
9224
9391
|
const disposer = this.registerListener({
|
|
@@ -9256,14 +9423,7 @@ The next upload iteration will be delayed.`);
|
|
|
9256
9423
|
this.abortController = null;
|
|
9257
9424
|
this.updateSyncStatus({ connected: false, connecting: false });
|
|
9258
9425
|
}
|
|
9259
|
-
/**
|
|
9260
|
-
* @deprecated use [connect instead]
|
|
9261
|
-
*/
|
|
9262
9426
|
async streamingSync(signal, options) {
|
|
9263
|
-
if (!signal) {
|
|
9264
|
-
this.abortController = new AbortController();
|
|
9265
|
-
signal = this.abortController.signal;
|
|
9266
|
-
}
|
|
9267
9427
|
/**
|
|
9268
9428
|
* Listen for CRUD updates and trigger upstream uploads
|
|
9269
9429
|
*/
|
|
@@ -9369,7 +9529,7 @@ The next upload iteration will be delayed.`);
|
|
|
9369
9529
|
this.handleActiveStreamsChange?.();
|
|
9370
9530
|
}
|
|
9371
9531
|
/**
|
|
9372
|
-
* Older versions of the JS SDK used to encode subkeys as JSON in
|
|
9532
|
+
* Older versions of the JS SDK used to encode subkeys as JSON in `OplogEntry.toJSON`.
|
|
9373
9533
|
* Because subkeys are always strings, this leads to quotes being added around them in `ps_oplog`.
|
|
9374
9534
|
* While this is not a problem as long as it's done consistently, it causes issues when a database
|
|
9375
9535
|
* created by the JS SDK is used with other SDKs, or (more likely) when the new Rust sync client
|
|
@@ -9379,7 +9539,7 @@ The next upload iteration will be delayed.`);
|
|
|
9379
9539
|
* migration is only triggered when necessary (for now). The function returns whether the new format
|
|
9380
9540
|
* should be used, so that the JS SDK is able to write to updated databases.
|
|
9381
9541
|
*
|
|
9382
|
-
* @param requireFixedKeyFormat Whether we require the new format or also support the old one.
|
|
9542
|
+
* @param requireFixedKeyFormat - Whether we require the new format or also support the old one.
|
|
9383
9543
|
* The Rust client requires the new subkey format.
|
|
9384
9544
|
* @returns Whether the database is now using the new, fixed subkey format.
|
|
9385
9545
|
*/
|
|
@@ -9637,14 +9797,13 @@ The next upload iteration will be delayed.`);
|
|
|
9637
9797
|
// trigger this for all updates
|
|
9638
9798
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
9639
9799
|
}
|
|
9640
|
-
async delayRetry(signal) {
|
|
9800
|
+
async delayRetry(signal, delay = this.options.retryDelayMs) {
|
|
9641
9801
|
return new Promise((resolve) => {
|
|
9642
9802
|
if (signal?.aborted) {
|
|
9643
9803
|
// If the signal is already aborted, resolve immediately
|
|
9644
9804
|
resolve();
|
|
9645
9805
|
return;
|
|
9646
9806
|
}
|
|
9647
|
-
const { retryDelayMs } = this.options;
|
|
9648
9807
|
let timeoutId;
|
|
9649
9808
|
const endDelay = () => {
|
|
9650
9809
|
resolve();
|
|
@@ -9655,7 +9814,7 @@ The next upload iteration will be delayed.`);
|
|
|
9655
9814
|
signal?.removeEventListener('abort', endDelay);
|
|
9656
9815
|
};
|
|
9657
9816
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
9658
|
-
timeoutId = setTimeout(endDelay,
|
|
9817
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
9659
9818
|
});
|
|
9660
9819
|
}
|
|
9661
9820
|
updateSubscriptions(subscriptions) {
|
|
@@ -9687,7 +9846,8 @@ const MEMORY_TRIGGER_CLAIM_MANAGER = {
|
|
|
9687
9846
|
|
|
9688
9847
|
/**
|
|
9689
9848
|
* SQLite operations to track changes for with {@link TriggerManager}
|
|
9690
|
-
*
|
|
9849
|
+
*
|
|
9850
|
+
* @experimental @alpha
|
|
9691
9851
|
*/
|
|
9692
9852
|
exports.DiffTriggerOperation = void 0;
|
|
9693
9853
|
(function (DiffTriggerOperation) {
|
|
@@ -9749,8 +9909,8 @@ class TriggerManagerImpl {
|
|
|
9749
9909
|
get db() {
|
|
9750
9910
|
return this.options.db;
|
|
9751
9911
|
}
|
|
9752
|
-
async getUUID() {
|
|
9753
|
-
const { id: uuid } = await this.db.get(/* sql */ `
|
|
9912
|
+
async getUUID(ctx) {
|
|
9913
|
+
const { id: uuid } = await (ctx ?? this.db).get(/* sql */ `
|
|
9754
9914
|
SELECT
|
|
9755
9915
|
uuid () as id
|
|
9756
9916
|
`);
|
|
@@ -9863,7 +10023,7 @@ class TriggerManagerImpl {
|
|
|
9863
10023
|
const replicatedColumns = columns ?? sourceDefinition.columns.map((col) => col.name);
|
|
9864
10024
|
const internalSource = sourceDefinition.internalName;
|
|
9865
10025
|
const triggerIds = [];
|
|
9866
|
-
const id = await this.getUUID();
|
|
10026
|
+
const id = await this.getUUID(setupContext);
|
|
9867
10027
|
const releaseStorageClaim = useStorage ? await this.options.claimManager.obtainClaim(id) : null;
|
|
9868
10028
|
/**
|
|
9869
10029
|
* We default to replicating all columns if no columns array is provided.
|
|
@@ -10103,18 +10263,29 @@ const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
|
|
|
10103
10263
|
const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
|
|
10104
10264
|
clearLocal: true
|
|
10105
10265
|
};
|
|
10266
|
+
/**
|
|
10267
|
+
* @internal
|
|
10268
|
+
*/
|
|
10106
10269
|
const DEFAULT_POWERSYNC_CLOSE_OPTIONS = {
|
|
10107
10270
|
disconnect: true
|
|
10108
10271
|
};
|
|
10272
|
+
/**
|
|
10273
|
+
* @internal
|
|
10274
|
+
*/
|
|
10109
10275
|
const DEFAULT_POWERSYNC_DB_OPTIONS = {
|
|
10110
10276
|
retryDelayMs: 5000,
|
|
10111
10277
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
10112
10278
|
};
|
|
10279
|
+
/**
|
|
10280
|
+
* @internal
|
|
10281
|
+
*/
|
|
10113
10282
|
const DEFAULT_CRUD_BATCH_LIMIT = 100;
|
|
10114
10283
|
/**
|
|
10115
10284
|
* Requesting nested or recursive locks can block the application in some circumstances.
|
|
10116
10285
|
* This default lock timeout will act as a failsafe to throw an error if a lock cannot
|
|
10117
10286
|
* be obtained.
|
|
10287
|
+
*
|
|
10288
|
+
* @internal
|
|
10118
10289
|
*/
|
|
10119
10290
|
const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins
|
|
10120
10291
|
/**
|
|
@@ -10124,6 +10295,9 @@ const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins
|
|
|
10124
10295
|
const isPowerSyncDatabaseOptionsWithSettings = (test) => {
|
|
10125
10296
|
return typeof test == 'object' && isSQLOpenOptions(test.database);
|
|
10126
10297
|
};
|
|
10298
|
+
/**
|
|
10299
|
+
* @public
|
|
10300
|
+
*/
|
|
10127
10301
|
class AbstractPowerSyncDatabase extends BaseObserver {
|
|
10128
10302
|
options;
|
|
10129
10303
|
/**
|
|
@@ -10281,7 +10455,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
10281
10455
|
/**
|
|
10282
10456
|
* Wait for the first sync operation to complete.
|
|
10283
10457
|
*
|
|
10284
|
-
* @param request Either an abort signal (after which the promise will complete regardless of
|
|
10458
|
+
* @param request - Either an abort signal (after which the promise will complete regardless of
|
|
10285
10459
|
* whether a full sync was completed) or an object providing an abort signal and a priority target.
|
|
10286
10460
|
* When a priority target is set, the promise may complete when all buckets with the given (or higher)
|
|
10287
10461
|
* priorities have been synchronized. This can be earlier than a complete sync.
|
|
@@ -10436,7 +10610,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
10436
10610
|
/**
|
|
10437
10611
|
* Close the sync connection.
|
|
10438
10612
|
*
|
|
10439
|
-
* Use {@link connect} to connect again.
|
|
10613
|
+
* Use {@link AbstractPowerSyncDatabase.connect} to connect again.
|
|
10440
10614
|
*/
|
|
10441
10615
|
async disconnect() {
|
|
10442
10616
|
return this.connectionManager.disconnect();
|
|
@@ -10463,8 +10637,8 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
10463
10637
|
/**
|
|
10464
10638
|
* Create a sync stream to query its status or to subscribe to it.
|
|
10465
10639
|
*
|
|
10466
|
-
* @param name The name of the stream to subscribe to.
|
|
10467
|
-
* @param params Optional parameters for the stream subscription.
|
|
10640
|
+
* @param name - The name of the stream to subscribe to.
|
|
10641
|
+
* @param params - Optional parameters for the stream subscription.
|
|
10468
10642
|
* @returns A {@link SyncStream} instance that can be subscribed to.
|
|
10469
10643
|
* @experimental Sync streams are currently in alpha.
|
|
10470
10644
|
*/
|
|
@@ -10522,14 +10696,14 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
10522
10696
|
* Once the data have been successfully uploaded, call {@link CrudBatch.complete} before
|
|
10523
10697
|
* requesting the next batch.
|
|
10524
10698
|
*
|
|
10525
|
-
* Use
|
|
10699
|
+
* Use the `limit` parameter to specify the maximum number of updates to return in a single
|
|
10526
10700
|
* batch.
|
|
10527
10701
|
*
|
|
10528
10702
|
* This method does include transaction ids in the result, but does not group
|
|
10529
10703
|
* data by transaction. One batch may contain data from multiple transactions,
|
|
10530
10704
|
* and a single transaction may be split over multiple batches.
|
|
10531
10705
|
*
|
|
10532
|
-
* @param limit Maximum number of CRUD entries to include in the batch
|
|
10706
|
+
* @param limit - Maximum number of CRUD entries to include in the batch
|
|
10533
10707
|
* @returns A batch of CRUD operations to upload, or null if there are none
|
|
10534
10708
|
*/
|
|
10535
10709
|
async getCrudBatch(limit = DEFAULT_CRUD_BATCH_LIMIT) {
|
|
@@ -10556,7 +10730,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
10556
10730
|
* Once the data have been successfully uploaded, call {@link CrudTransaction.complete} before
|
|
10557
10731
|
* requesting the next transaction.
|
|
10558
10732
|
*
|
|
10559
|
-
* Unlike {@link getCrudBatch}, this only returns data from a single transaction at a time.
|
|
10733
|
+
* Unlike {@link AbstractPowerSyncDatabase.getCrudBatch}, this only returns data from a single transaction at a time.
|
|
10560
10734
|
* All data for the transaction is loaded into memory.
|
|
10561
10735
|
*
|
|
10562
10736
|
* @returns A transaction of CRUD operations to upload, or null if there are none
|
|
@@ -10571,7 +10745,7 @@ class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
10571
10745
|
* This is typically used from the {@link PowerSyncBackendConnector.uploadData} callback. Each entry emitted by the
|
|
10572
10746
|
* returned iterator is a full transaction containing all local writes made while that transaction was active.
|
|
10573
10747
|
*
|
|
10574
|
-
* Unlike {@link getNextCrudTransaction}, which always returns the oldest transaction that hasn't been
|
|
10748
|
+
* Unlike {@link AbstractPowerSyncDatabase.getNextCrudTransaction}, which always returns the oldest transaction that hasn't been
|
|
10575
10749
|
* {@link CrudTransaction.complete}d yet, this iterator can be used to receive multiple transactions. Calling
|
|
10576
10750
|
* {@link CrudTransaction.complete} will mark that and all prior transactions emitted by the iterator as completed.
|
|
10577
10751
|
*
|
|
@@ -10665,8 +10839,8 @@ SELECT * FROM crud_entries;
|
|
|
10665
10839
|
* the returned result's `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
|
|
10666
10840
|
* Use a `RETURNING` clause and inspect `result.rows` when you need to confirm which rows changed.
|
|
10667
10841
|
*
|
|
10668
|
-
* @param sql The SQL query to execute
|
|
10669
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10842
|
+
* @param sql - The SQL query to execute
|
|
10843
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
10670
10844
|
* @returns The query result as an object with structured key-value pairs
|
|
10671
10845
|
*/
|
|
10672
10846
|
async execute(sql, parameters) {
|
|
@@ -10676,8 +10850,8 @@ SELECT * FROM crud_entries;
|
|
|
10676
10850
|
* Execute a SQL write (INSERT/UPDATE/DELETE) query directly on the database without any PowerSync processing.
|
|
10677
10851
|
* This bypasses certain PowerSync abstractions and is useful for accessing the raw database results.
|
|
10678
10852
|
*
|
|
10679
|
-
* @param sql The SQL query to execute
|
|
10680
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10853
|
+
* @param sql - The SQL query to execute
|
|
10854
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
10681
10855
|
* @returns The raw query result from the underlying database as a nested array of raw values, where each row is
|
|
10682
10856
|
* represented as an array of column values without field names.
|
|
10683
10857
|
*/
|
|
@@ -10690,8 +10864,8 @@ SELECT * FROM crud_entries;
|
|
|
10690
10864
|
* and optionally return results.
|
|
10691
10865
|
* This is faster than executing separately with each parameter set.
|
|
10692
10866
|
*
|
|
10693
|
-
* @param sql The SQL query to execute
|
|
10694
|
-
* @param parameters Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
|
|
10867
|
+
* @param sql - The SQL query to execute
|
|
10868
|
+
* @param parameters - Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
|
|
10695
10869
|
* @returns The query result
|
|
10696
10870
|
*/
|
|
10697
10871
|
async executeBatch(sql, parameters) {
|
|
@@ -10701,8 +10875,8 @@ SELECT * FROM crud_entries;
|
|
|
10701
10875
|
/**
|
|
10702
10876
|
* Execute a read-only query and return results.
|
|
10703
10877
|
*
|
|
10704
|
-
* @param sql The SQL query to execute
|
|
10705
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10878
|
+
* @param sql - The SQL query to execute
|
|
10879
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
10706
10880
|
* @returns An array of results
|
|
10707
10881
|
*/
|
|
10708
10882
|
async getAll(sql, parameters) {
|
|
@@ -10712,8 +10886,8 @@ SELECT * FROM crud_entries;
|
|
|
10712
10886
|
/**
|
|
10713
10887
|
* Execute a read-only query and return the first result, or null if the ResultSet is empty.
|
|
10714
10888
|
*
|
|
10715
|
-
* @param sql The SQL query to execute
|
|
10716
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10889
|
+
* @param sql - The SQL query to execute
|
|
10890
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
10717
10891
|
* @returns The first result if found, or null if no results are returned
|
|
10718
10892
|
*/
|
|
10719
10893
|
async getOptional(sql, parameters) {
|
|
@@ -10723,8 +10897,8 @@ SELECT * FROM crud_entries;
|
|
|
10723
10897
|
/**
|
|
10724
10898
|
* Execute a read-only query and return the first result, error if the ResultSet is empty.
|
|
10725
10899
|
*
|
|
10726
|
-
* @param sql The SQL query to execute
|
|
10727
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10900
|
+
* @param sql - The SQL query to execute
|
|
10901
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
10728
10902
|
* @returns The first result matching the query
|
|
10729
10903
|
* @throws Error if no rows are returned
|
|
10730
10904
|
*/
|
|
@@ -10734,7 +10908,7 @@ SELECT * FROM crud_entries;
|
|
|
10734
10908
|
}
|
|
10735
10909
|
/**
|
|
10736
10910
|
* Takes a read lock, without starting a transaction.
|
|
10737
|
-
* In most cases, {@link readTransaction} should be used instead.
|
|
10911
|
+
* In most cases, {@link AbstractPowerSyncDatabase.readTransaction} should be used instead.
|
|
10738
10912
|
*/
|
|
10739
10913
|
async readLock(callback) {
|
|
10740
10914
|
await this.waitForReady();
|
|
@@ -10742,7 +10916,7 @@ SELECT * FROM crud_entries;
|
|
|
10742
10916
|
}
|
|
10743
10917
|
/**
|
|
10744
10918
|
* Takes a global lock, without starting a transaction.
|
|
10745
|
-
* In most cases, {@link writeTransaction} should be used instead.
|
|
10919
|
+
* In most cases, {@link AbstractPowerSyncDatabase.writeTransaction} should be used instead.
|
|
10746
10920
|
*/
|
|
10747
10921
|
async writeLock(callback) {
|
|
10748
10922
|
await this.waitForReady();
|
|
@@ -10753,8 +10927,8 @@ SELECT * FROM crud_entries;
|
|
|
10753
10927
|
* Read transactions can run concurrently to a write transaction.
|
|
10754
10928
|
* Changes from any write transaction are not visible to read transactions started before it.
|
|
10755
10929
|
*
|
|
10756
|
-
* @param callback Function to execute within the transaction
|
|
10757
|
-
* @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
|
|
10930
|
+
* @param callback - Function to execute within the transaction
|
|
10931
|
+
* @param lockTimeout - Time in milliseconds to wait for a lock before throwing an error
|
|
10758
10932
|
* @returns The result of the callback
|
|
10759
10933
|
* @throws Error if the lock cannot be obtained within the timeout period
|
|
10760
10934
|
*/
|
|
@@ -10771,8 +10945,8 @@ SELECT * FROM crud_entries;
|
|
|
10771
10945
|
* This takes a global lock - only one write transaction can execute against the database at a time.
|
|
10772
10946
|
* Statements within the transaction must be done on the provided {@link Transaction} interface.
|
|
10773
10947
|
*
|
|
10774
|
-
* @param callback Function to execute within the transaction
|
|
10775
|
-
* @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
|
|
10948
|
+
* @param callback - Function to execute within the transaction
|
|
10949
|
+
* @param lockTimeout - Time in milliseconds to wait for a lock before throwing an error
|
|
10776
10950
|
* @returns The result of the callback
|
|
10777
10951
|
* @throws Error if the lock cannot be obtained within the timeout period
|
|
10778
10952
|
*/
|
|
@@ -10849,15 +11023,15 @@ SELECT * FROM crud_entries;
|
|
|
10849
11023
|
}
|
|
10850
11024
|
/**
|
|
10851
11025
|
* Execute a read query every time the source tables are modified.
|
|
10852
|
-
* Use {@link
|
|
11026
|
+
* Use {@link SQLOnChangeOptions.throttleMs} to specify the minimum interval between queries.
|
|
10853
11027
|
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
|
|
10854
11028
|
*
|
|
10855
11029
|
* Note that the `onChange` callback member of the handler is required.
|
|
10856
11030
|
*
|
|
10857
|
-
* @param sql The SQL query to execute
|
|
10858
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10859
|
-
* @param handler Callbacks for handling results and errors
|
|
10860
|
-
* @param options Options for configuring watch behavior
|
|
11031
|
+
* @param sql - The SQL query to execute
|
|
11032
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
11033
|
+
* @param handler - Callbacks for handling results and errors
|
|
11034
|
+
* @param options - Options for configuring watch behavior
|
|
10861
11035
|
*/
|
|
10862
11036
|
watchWithCallback(sql, parameters, handler, options) {
|
|
10863
11037
|
const { onResult, onError = (e) => this.logger.error(e) } = handler ?? {};
|
|
@@ -10870,7 +11044,7 @@ SELECT * FROM crud_entries;
|
|
|
10870
11044
|
const watchedQuery = new OnChangeQueryProcessor({
|
|
10871
11045
|
db: this,
|
|
10872
11046
|
comparator,
|
|
10873
|
-
placeholderData: null,
|
|
11047
|
+
placeholderData: null, // FIXME
|
|
10874
11048
|
watchOptions: {
|
|
10875
11049
|
query: {
|
|
10876
11050
|
compile: () => ({
|
|
@@ -10903,12 +11077,12 @@ SELECT * FROM crud_entries;
|
|
|
10903
11077
|
}
|
|
10904
11078
|
/**
|
|
10905
11079
|
* Execute a read query every time the source tables are modified.
|
|
10906
|
-
* Use {@link
|
|
11080
|
+
* Use {@link SQLOnChangeOptions.throttleMs} to specify the minimum interval between queries.
|
|
10907
11081
|
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
|
|
10908
11082
|
*
|
|
10909
|
-
* @param sql The SQL query to execute
|
|
10910
|
-
* @param parameters Optional array of parameters to bind to the query
|
|
10911
|
-
* @param options Options for configuring watch behavior
|
|
11083
|
+
* @param sql - The SQL query to execute
|
|
11084
|
+
* @param parameters - Optional array of parameters to bind to the query
|
|
11085
|
+
* @param options - Options for configuring watch behavior
|
|
10912
11086
|
* @returns An AsyncIterable that yields QueryResults whenever the data changes
|
|
10913
11087
|
*/
|
|
10914
11088
|
watchWithAsyncGenerator(sql, parameters, options) {
|
|
@@ -10932,9 +11106,9 @@ SELECT * FROM crud_entries;
|
|
|
10932
11106
|
* If tables are specified in the options, those are used directly.
|
|
10933
11107
|
* Otherwise, analyzes the query using EXPLAIN to determine which tables are accessed.
|
|
10934
11108
|
*
|
|
10935
|
-
* @param sql The SQL query to analyze
|
|
10936
|
-
* @param parameters Optional parameters for the SQL query
|
|
10937
|
-
* @param options Optional watch options that may contain explicit table list
|
|
11109
|
+
* @param sql - The SQL query to analyze
|
|
11110
|
+
* @param parameters - Optional parameters for the SQL query
|
|
11111
|
+
* @param options - Optional watch options that may contain explicit table list
|
|
10938
11112
|
* @returns Array of table names that the query depends on
|
|
10939
11113
|
*/
|
|
10940
11114
|
async resolveTables(sql, parameters, options) {
|
|
@@ -10963,13 +11137,13 @@ SELECT * FROM crud_entries;
|
|
|
10963
11137
|
/**
|
|
10964
11138
|
* Invoke the provided callback on any changes to any of the specified tables.
|
|
10965
11139
|
*
|
|
10966
|
-
* This is preferred over {@link watchWithCallback} when multiple queries need to be performed
|
|
11140
|
+
* This is preferred over {@link AbstractPowerSyncDatabase.watchWithCallback} when multiple queries need to be performed
|
|
10967
11141
|
* together when data is changed.
|
|
10968
11142
|
*
|
|
10969
11143
|
* Note that the `onChange` callback member of the handler is required.
|
|
10970
11144
|
*
|
|
10971
|
-
* @param handler Callbacks for handling change events and errors
|
|
10972
|
-
* @param options Options for configuring watch behavior
|
|
11145
|
+
* @param handler - Callbacks for handling change events and errors
|
|
11146
|
+
* @param options - Options for configuring watch behavior
|
|
10973
11147
|
* @returns A dispose function to stop watching for changes
|
|
10974
11148
|
*/
|
|
10975
11149
|
onChangeWithCallback(handler, options) {
|
|
@@ -11012,12 +11186,12 @@ SELECT * FROM crud_entries;
|
|
|
11012
11186
|
/**
|
|
11013
11187
|
* Create a Stream of changes to any of the specified tables.
|
|
11014
11188
|
*
|
|
11015
|
-
* This is preferred over {@link watchWithAsyncGenerator} when multiple queries need to be
|
|
11016
|
-
* together when data is changed.
|
|
11189
|
+
* This is preferred over {@link AbstractPowerSyncDatabase.watchWithAsyncGenerator} when multiple queries need to be
|
|
11190
|
+
* performed together when data is changed.
|
|
11017
11191
|
*
|
|
11018
11192
|
* Note: do not declare this as `async *onChange` as it will not work in React Native.
|
|
11019
11193
|
*
|
|
11020
|
-
* @param options Options for configuring watch behavior
|
|
11194
|
+
* @param options - Options for configuring watch behavior
|
|
11021
11195
|
* @returns An AsyncIterable that yields change events whenever the specified tables change
|
|
11022
11196
|
*/
|
|
11023
11197
|
onChangeWithAsyncGenerator(options) {
|
|
@@ -11055,15 +11229,15 @@ SELECT * FROM crud_entries;
|
|
|
11055
11229
|
changedTables.add(table);
|
|
11056
11230
|
}
|
|
11057
11231
|
}
|
|
11058
|
-
/**
|
|
11059
|
-
* @ignore
|
|
11060
|
-
*/
|
|
11061
11232
|
async executeReadOnly(sql, params) {
|
|
11062
11233
|
await this.waitForReady();
|
|
11063
11234
|
return this.database.readLock((tx) => tx.execute(sql, params));
|
|
11064
11235
|
}
|
|
11065
11236
|
}
|
|
11066
11237
|
|
|
11238
|
+
/**
|
|
11239
|
+
* @internal
|
|
11240
|
+
*/
|
|
11067
11241
|
class AbstractPowerSyncDatabaseOpenFactory {
|
|
11068
11242
|
options;
|
|
11069
11243
|
constructor(options) {
|
|
@@ -11088,6 +11262,9 @@ class AbstractPowerSyncDatabaseOpenFactory {
|
|
|
11088
11262
|
}
|
|
11089
11263
|
}
|
|
11090
11264
|
|
|
11265
|
+
/**
|
|
11266
|
+
* @internal
|
|
11267
|
+
*/
|
|
11091
11268
|
function runOnSchemaChange(callback, db, options) {
|
|
11092
11269
|
const triggerWatchedQuery = () => {
|
|
11093
11270
|
const abortController = new AbortController();
|
|
@@ -11112,6 +11289,9 @@ function runOnSchemaChange(callback, db, options) {
|
|
|
11112
11289
|
triggerWatchedQuery();
|
|
11113
11290
|
}
|
|
11114
11291
|
|
|
11292
|
+
/**
|
|
11293
|
+
* @public
|
|
11294
|
+
*/
|
|
11115
11295
|
function compilableQueryWatch(db, query, handler, options) {
|
|
11116
11296
|
const { onResult, onError = (e) => { } } = handler ?? {};
|
|
11117
11297
|
if (!onResult) {
|
|
@@ -11149,8 +11329,14 @@ function compilableQueryWatch(db, query, handler, options) {
|
|
|
11149
11329
|
runOnSchemaChange(watchQuery, db, options);
|
|
11150
11330
|
}
|
|
11151
11331
|
|
|
11332
|
+
/**
|
|
11333
|
+
* @internal
|
|
11334
|
+
*/
|
|
11152
11335
|
const MAX_OP_ID = '9223372036854775807';
|
|
11153
11336
|
|
|
11337
|
+
/**
|
|
11338
|
+
* @internal
|
|
11339
|
+
*/
|
|
11154
11340
|
class SqliteBucketStorage extends BaseObserver {
|
|
11155
11341
|
db;
|
|
11156
11342
|
logger;
|
|
@@ -11311,6 +11497,8 @@ class SqliteBucketStorage extends BaseObserver {
|
|
|
11311
11497
|
* Thrown when an underlying database connection is closed.
|
|
11312
11498
|
* This is particularly relevant when worker connections are marked as closed while
|
|
11313
11499
|
* operations are still in progress.
|
|
11500
|
+
*
|
|
11501
|
+
* @internal
|
|
11314
11502
|
*/
|
|
11315
11503
|
class ConnectionClosedError extends Error {
|
|
11316
11504
|
static NAME = 'ConnectionClosedError';
|
|
@@ -11330,6 +11518,8 @@ class ConnectionClosedError extends Error {
|
|
|
11330
11518
|
|
|
11331
11519
|
/**
|
|
11332
11520
|
* A schema is a collection of tables. It is used to define the structure of a database.
|
|
11521
|
+
*
|
|
11522
|
+
* @public
|
|
11333
11523
|
*/
|
|
11334
11524
|
class Schema {
|
|
11335
11525
|
/*
|
|
@@ -11366,7 +11556,7 @@ class Schema {
|
|
|
11366
11556
|
* Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
|
|
11367
11557
|
* using client-side table and column constraints.
|
|
11368
11558
|
*
|
|
11369
|
-
* @param tables An object of (table name, raw table definition) entries.
|
|
11559
|
+
* @param tables - An object of (table name, raw table definition) entries.
|
|
11370
11560
|
*/
|
|
11371
11561
|
withRawTables(tables) {
|
|
11372
11562
|
for (const [name, rawTableDefinition] of Object.entries(tables)) {
|
|
@@ -11412,6 +11602,8 @@ class Schema {
|
|
|
11412
11602
|
Generate a new table from the columns and indexes
|
|
11413
11603
|
@deprecated You should use {@link Table} instead as it now allows TableV2 syntax.
|
|
11414
11604
|
This will be removed in the next major release.
|
|
11605
|
+
|
|
11606
|
+
@public
|
|
11415
11607
|
*/
|
|
11416
11608
|
class TableV2 extends Table {
|
|
11417
11609
|
}
|
|
@@ -11422,6 +11614,8 @@ function sanitizeString(input) {
|
|
|
11422
11614
|
/**
|
|
11423
11615
|
* Helper function for sanitizing UUID input strings.
|
|
11424
11616
|
* Typically used with {@link sanitizeSQL}.
|
|
11617
|
+
*
|
|
11618
|
+
* @alpha
|
|
11425
11619
|
*/
|
|
11426
11620
|
function sanitizeUUID(uuid) {
|
|
11427
11621
|
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;
|
|
@@ -11458,6 +11652,8 @@ function sanitizeUUID(uuid) {
|
|
|
11458
11652
|
* // Incorrect:
|
|
11459
11653
|
* sanitizeSQL`New.id = '${myID}'` // Produces double quotes: New.id = ''O''Reilly''
|
|
11460
11654
|
* ```
|
|
11655
|
+
*
|
|
11656
|
+
* @alpha
|
|
11461
11657
|
*/
|
|
11462
11658
|
function sanitizeSQL(strings, ...values) {
|
|
11463
11659
|
let result = '';
|
|
@@ -11487,6 +11683,8 @@ function sanitizeSQL(strings, ...values) {
|
|
|
11487
11683
|
|
|
11488
11684
|
/**
|
|
11489
11685
|
* Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
|
|
11686
|
+
*
|
|
11687
|
+
* @public
|
|
11490
11688
|
*/
|
|
11491
11689
|
class GetAllQuery {
|
|
11492
11690
|
options;
|
|
@@ -11511,6 +11709,9 @@ class GetAllQuery {
|
|
|
11511
11709
|
}
|
|
11512
11710
|
|
|
11513
11711
|
const TypedLogger = Logger;
|
|
11712
|
+
/**
|
|
11713
|
+
* @public
|
|
11714
|
+
*/
|
|
11514
11715
|
const LogLevel = {
|
|
11515
11716
|
TRACE: TypedLogger.TRACE,
|
|
11516
11717
|
DEBUG: TypedLogger.DEBUG,
|
|
@@ -11527,6 +11728,7 @@ const LogLevel = {
|
|
|
11527
11728
|
* across all loggers created with `createLogger`. Adjusting settings on this
|
|
11528
11729
|
* base logger affects all loggers derived from it unless explicitly overridden.
|
|
11529
11730
|
*
|
|
11731
|
+
* @public
|
|
11530
11732
|
*/
|
|
11531
11733
|
function createBaseLogger() {
|
|
11532
11734
|
return Logger;
|
|
@@ -11537,6 +11739,8 @@ function createBaseLogger() {
|
|
|
11537
11739
|
* Named loggers allow specific modules or areas of your application to have
|
|
11538
11740
|
* their own logging levels and behaviors. These loggers inherit configuration
|
|
11539
11741
|
* from the base logger by default but can override settings independently.
|
|
11742
|
+
*
|
|
11743
|
+
* @public
|
|
11540
11744
|
*/
|
|
11541
11745
|
function createLogger(name, options = {}) {
|
|
11542
11746
|
const logger = Logger.get(name);
|
|
@@ -11546,6 +11750,9 @@ function createLogger(name, options = {}) {
|
|
|
11546
11750
|
return logger;
|
|
11547
11751
|
}
|
|
11548
11752
|
|
|
11753
|
+
/**
|
|
11754
|
+
* @internal
|
|
11755
|
+
*/
|
|
11549
11756
|
const parseQuery = (query, parameters) => {
|
|
11550
11757
|
let sqlStatement;
|
|
11551
11758
|
if (typeof query == 'string') {
|