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