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