@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
|
@@ -2,6 +2,9 @@ import { BaseListener, BaseObserverInterface, Disposable } from '../../../utils/
|
|
|
2
2
|
import { CrudBatch } from './CrudBatch.js';
|
|
3
3
|
import { CrudEntry } from './CrudEntry.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
5
8
|
export enum PSInternalTable {
|
|
6
9
|
DATA = 'ps_data',
|
|
7
10
|
CRUD = 'ps_crud',
|
|
@@ -10,6 +13,9 @@ export enum PSInternalTable {
|
|
|
10
13
|
UNTYPED = 'ps_untyped'
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
13
19
|
export enum PowerSyncControlCommand {
|
|
14
20
|
PROCESS_TEXT_LINE = 'line_text',
|
|
15
21
|
PROCESS_BSON_LINE = 'line_binary',
|
|
@@ -24,10 +30,16 @@ export enum PowerSyncControlCommand {
|
|
|
24
30
|
CONNECTION_STATE = 'connection'
|
|
25
31
|
}
|
|
26
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
27
36
|
export interface BucketStorageListener extends BaseListener {
|
|
28
37
|
crudUpdate: () => void;
|
|
29
38
|
}
|
|
30
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
31
43
|
export interface BucketStorageAdapter extends BaseObserverInterface<BucketStorageListener>, Disposable {
|
|
32
44
|
init(): Promise<void>;
|
|
33
45
|
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
* 64-bit unsigned integer stored as a string in base-10.
|
|
3
3
|
*
|
|
4
4
|
* Not sortable as a string.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
5
7
|
*/
|
|
6
8
|
export type OpId = string;
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Type of local change.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
10
14
|
*/
|
|
11
15
|
export enum UpdateType {
|
|
12
16
|
/** Insert or replace existing row. All non-null columns are included in the data. Generated by INSERT statements. */
|
|
@@ -17,6 +21,9 @@ export enum UpdateType {
|
|
|
17
21
|
DELETE = 'DELETE'
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
20
27
|
export type CrudEntryJSON = {
|
|
21
28
|
id: string;
|
|
22
29
|
data: string;
|
|
@@ -48,6 +55,8 @@ type CrudEntryOutputJSON = {
|
|
|
48
55
|
|
|
49
56
|
/**
|
|
50
57
|
* A single client-side change.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
51
60
|
*/
|
|
52
61
|
export class CrudEntry {
|
|
53
62
|
/**
|
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
import { CrudBatch } from './CrudBatch.js';
|
|
12
12
|
import { CrudEntry, CrudEntryJSON } from './CrudEntry.js';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
14
17
|
export class SqliteBucketStorage extends BaseObserver<BucketStorageListener> implements BucketStorageAdapter {
|
|
15
18
|
public tableNames: Set<string>;
|
|
16
19
|
private updateListener: () => void;
|
|
@@ -14,6 +14,9 @@ import {
|
|
|
14
14
|
import { EventIterator } from 'event-iterator';
|
|
15
15
|
import type { Queue } from 'event-iterator/lib/event-iterator.js';
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
17
20
|
export type RemoteConnector = {
|
|
18
21
|
fetchCredentials: () => Promise<PowerSyncCredentials | null>;
|
|
19
22
|
invalidateCredentials?: () => void;
|
|
@@ -36,8 +39,14 @@ const SOCKET_TIMEOUT_MS = 30_000;
|
|
|
36
39
|
// significantly. Therefore this is longer than the socket timeout.
|
|
37
40
|
const KEEP_ALIVE_LIFETIME_MS = 90_000;
|
|
38
41
|
|
|
42
|
+
/**
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
39
45
|
export const DEFAULT_REMOTE_LOGGER = Logger.get('PowerSyncRemote');
|
|
40
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
41
50
|
export type SyncStreamOptions = {
|
|
42
51
|
path: string;
|
|
43
52
|
data: unknown;
|
|
@@ -46,6 +55,9 @@ export type SyncStreamOptions = {
|
|
|
46
55
|
fetchOptions?: Request;
|
|
47
56
|
};
|
|
48
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
49
61
|
export enum FetchStrategy {
|
|
50
62
|
/**
|
|
51
63
|
* Queues multiple sync events before processing, reducing round-trips.
|
|
@@ -60,10 +72,16 @@ export enum FetchStrategy {
|
|
|
60
72
|
Sequential = 'sequential'
|
|
61
73
|
}
|
|
62
74
|
|
|
75
|
+
/**
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
63
78
|
export type SocketSyncStreamOptions = SyncStreamOptions & {
|
|
64
79
|
fetchStrategy: FetchStrategy;
|
|
65
80
|
};
|
|
66
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
67
85
|
export type FetchImplementation = typeof fetch;
|
|
68
86
|
|
|
69
87
|
/**
|
|
@@ -71,6 +89,8 @@ export type FetchImplementation = typeof fetch;
|
|
|
71
89
|
* The class wrapper is used to distinguish the fetchImplementation
|
|
72
90
|
* option in [AbstractRemoteOptions] from the general fetch method
|
|
73
91
|
* which is typeof "function"
|
|
92
|
+
*
|
|
93
|
+
* @internal
|
|
74
94
|
*/
|
|
75
95
|
export class FetchImplementationProvider {
|
|
76
96
|
getFetch(): FetchImplementation {
|
|
@@ -78,6 +98,9 @@ export class FetchImplementationProvider {
|
|
|
78
98
|
}
|
|
79
99
|
}
|
|
80
100
|
|
|
101
|
+
/**
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
81
104
|
export type AbstractRemoteOptions = {
|
|
82
105
|
/**
|
|
83
106
|
* Transforms the PowerSync base URL which might contain
|
|
@@ -102,6 +125,9 @@ export type AbstractRemoteOptions = {
|
|
|
102
125
|
fetchOptions?: {};
|
|
103
126
|
};
|
|
104
127
|
|
|
128
|
+
/**
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
105
131
|
export const DEFAULT_REMOTE_OPTIONS: AbstractRemoteOptions = {
|
|
106
132
|
socketUrlTransformer: (url) =>
|
|
107
133
|
url.replace(/^https?:\/\//, function (match) {
|
|
@@ -111,6 +137,9 @@ export const DEFAULT_REMOTE_OPTIONS: AbstractRemoteOptions = {
|
|
|
111
137
|
fetchOptions: {}
|
|
112
138
|
};
|
|
113
139
|
|
|
140
|
+
/**
|
|
141
|
+
* @internal
|
|
142
|
+
*/
|
|
114
143
|
export abstract class AbstractRemote {
|
|
115
144
|
protected credentials: PowerSyncCredentials | null = null;
|
|
116
145
|
protected options: AbstractRemoteOptions;
|
|
@@ -589,7 +618,7 @@ export abstract class AbstractRemote {
|
|
|
589
618
|
* Posts a `/sync/stream` request.
|
|
590
619
|
*
|
|
591
620
|
* Depending on the `Content-Type` of the response, this returns strings for sync lines or encoded BSON documents as
|
|
592
|
-
*
|
|
621
|
+
* `Uint8Array`s.
|
|
593
622
|
*/
|
|
594
623
|
async fetchStream(options: SyncStreamOptions): Promise<SimpleAsyncIterator<Uint8Array | string>> {
|
|
595
624
|
const { isBson, stream } = await this.fetchStreamRaw(options);
|
|
@@ -3,7 +3,6 @@ import Logger, { ILogger } from 'js-logger';
|
|
|
3
3
|
import { SyncStatus, SyncStatusOptions } from '../../../db/crud/SyncStatus.js';
|
|
4
4
|
import { AbortOperation } from '../../../utils/AbortOperation.js';
|
|
5
5
|
import { BaseListener, BaseObserver, BaseObserverInterface, Disposable } from '../../../utils/BaseObserver.js';
|
|
6
|
-
import { throttleLeadingTrailing } from '../../../utils/async.js';
|
|
7
6
|
import { BucketStorageAdapter, PowerSyncControlCommand } from '../bucket/BucketStorageAdapter.js';
|
|
8
7
|
import { CrudEntry } from '../bucket/CrudEntry.js';
|
|
9
8
|
import { AbstractRemote, FetchStrategy, SyncStreamOptions } from './AbstractRemote.js';
|
|
@@ -17,22 +16,32 @@ import {
|
|
|
17
16
|
doneResult,
|
|
18
17
|
injectable,
|
|
19
18
|
InjectableIterator,
|
|
20
|
-
map,
|
|
21
19
|
SimpleAsyncIterator,
|
|
22
20
|
valueResult
|
|
23
21
|
} from '../../../utils/stream_transform.js';
|
|
22
|
+
import { asyncNotifier } from '../../../utils/async.js';
|
|
24
23
|
import { StreamingSyncRequestParameterType } from './JsonValue.js';
|
|
25
24
|
|
|
25
|
+
/**
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
26
28
|
export enum LockType {
|
|
27
29
|
CRUD = 'crud',
|
|
28
30
|
SYNC = 'sync'
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
31
36
|
export enum SyncStreamConnectionMethod {
|
|
32
37
|
HTTP = 'http',
|
|
33
38
|
WEB_SOCKET = 'web-socket'
|
|
34
39
|
}
|
|
35
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
36
45
|
export enum SyncClientImplementation {
|
|
37
46
|
/**
|
|
38
47
|
* This implementation offloads the sync line decoding and handling into the PowerSync
|
|
@@ -43,8 +52,8 @@ export enum SyncClientImplementation {
|
|
|
43
52
|
* ## Compatibility warning
|
|
44
53
|
*
|
|
45
54
|
* The Rust sync client stores sync data in a format that is slightly different than the one used
|
|
46
|
-
* by the old JavaScript client. When adopting the {@link RUST} client on existing databases,
|
|
47
|
-
* migrate the format automatically.
|
|
55
|
+
* by the old JavaScript client. When adopting the {@link SyncClientImplementation.RUST} client on existing databases,
|
|
56
|
+
* the PowerSync SDK will migrate the format automatically.
|
|
48
57
|
*
|
|
49
58
|
* SDK versions supporting both the JavaScript and the Rust client support both formats with the JavaScript client
|
|
50
59
|
* implementaiton. However, downgrading to an SDK version that only supports the JavaScript client would not be
|
|
@@ -55,11 +64,16 @@ export enum SyncClientImplementation {
|
|
|
55
64
|
|
|
56
65
|
/**
|
|
57
66
|
* The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}.
|
|
67
|
+
*
|
|
68
|
+
* @deprecated Deprecated since {@link SyncClientImplementation.RUST} is the only option.
|
|
69
|
+
* @public
|
|
58
70
|
*/
|
|
59
71
|
export const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.RUST;
|
|
60
72
|
|
|
61
73
|
/**
|
|
62
74
|
* Abstract Lock to be implemented by various JS environments
|
|
75
|
+
*
|
|
76
|
+
* @internal
|
|
63
77
|
*/
|
|
64
78
|
export interface LockOptions<T> {
|
|
65
79
|
callback: () => Promise<T>;
|
|
@@ -67,6 +81,9 @@ export interface LockOptions<T> {
|
|
|
67
81
|
signal?: AbortSignal;
|
|
68
82
|
}
|
|
69
83
|
|
|
84
|
+
/**
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
70
87
|
export interface AbstractStreamingSyncImplementationOptions extends RequiredAdditionalConnectionOptions {
|
|
71
88
|
adapter: BucketStorageAdapter;
|
|
72
89
|
subscriptions: SubscribedStream[];
|
|
@@ -80,6 +97,9 @@ export interface AbstractStreamingSyncImplementationOptions extends RequiredAddi
|
|
|
80
97
|
remote: AbstractRemote;
|
|
81
98
|
}
|
|
82
99
|
|
|
100
|
+
/**
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
83
103
|
export interface StreamingSyncImplementationListener extends BaseListener {
|
|
84
104
|
/**
|
|
85
105
|
* Triggered whenever a status update has been attempted to be made or
|
|
@@ -95,12 +115,17 @@ export interface StreamingSyncImplementationListener extends BaseListener {
|
|
|
95
115
|
/**
|
|
96
116
|
* Configurable options to be used when connecting to the PowerSync
|
|
97
117
|
* backend instance.
|
|
118
|
+
*
|
|
119
|
+
* @public
|
|
98
120
|
*/
|
|
99
121
|
export type PowerSyncConnectionOptions = Omit<InternalConnectionOptions, 'serializedSchema'>;
|
|
100
122
|
|
|
123
|
+
/**
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
101
126
|
export interface InternalConnectionOptions extends BaseConnectionOptions, AdditionalConnectionOptions {}
|
|
102
127
|
|
|
103
|
-
/** @
|
|
128
|
+
/** @public */
|
|
104
129
|
export interface BaseConnectionOptions {
|
|
105
130
|
/**
|
|
106
131
|
* A set of metadata to be included in service logs.
|
|
@@ -162,6 +187,9 @@ export interface RequiredAdditionalConnectionOptions extends Required<Additional
|
|
|
162
187
|
subscriptions: SubscribedStream[];
|
|
163
188
|
}
|
|
164
189
|
|
|
190
|
+
/**
|
|
191
|
+
* @internal
|
|
192
|
+
*/
|
|
165
193
|
export interface StreamingSyncImplementation
|
|
166
194
|
extends BaseObserverInterface<StreamingSyncImplementationListener>, Disposable {
|
|
167
195
|
/**
|
|
@@ -184,16 +212,31 @@ export interface StreamingSyncImplementation
|
|
|
184
212
|
markConnectionMayHaveChanged(): void;
|
|
185
213
|
}
|
|
186
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @internal
|
|
217
|
+
*/
|
|
187
218
|
export const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
219
|
+
/**
|
|
220
|
+
* @internal
|
|
221
|
+
*/
|
|
188
222
|
export const DEFAULT_RETRY_DELAY_MS = 5000;
|
|
189
223
|
|
|
224
|
+
/**
|
|
225
|
+
* @internal
|
|
226
|
+
*/
|
|
190
227
|
export const DEFAULT_STREAMING_SYNC_OPTIONS = {
|
|
191
228
|
retryDelayMs: DEFAULT_RETRY_DELAY_MS,
|
|
192
229
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
193
230
|
};
|
|
194
231
|
|
|
232
|
+
/**
|
|
233
|
+
* @internal
|
|
234
|
+
*/
|
|
195
235
|
export type RequiredPowerSyncConnectionOptions = Required<BaseConnectionOptions>;
|
|
196
236
|
|
|
237
|
+
/**
|
|
238
|
+
* @internal
|
|
239
|
+
*/
|
|
197
240
|
export const DEFAULT_STREAM_CONNECTION_OPTIONS: RequiredPowerSyncConnectionOptions = {
|
|
198
241
|
appMetadata: {},
|
|
199
242
|
connectionMethod: SyncStreamConnectionMethod.WEB_SOCKET,
|
|
@@ -204,38 +247,34 @@ export const DEFAULT_STREAM_CONNECTION_OPTIONS: RequiredPowerSyncConnectionOptio
|
|
|
204
247
|
includeDefaultStreams: true
|
|
205
248
|
};
|
|
206
249
|
|
|
250
|
+
/**
|
|
251
|
+
* @internal
|
|
252
|
+
*/
|
|
207
253
|
export type SubscribedStream = {
|
|
208
254
|
name: string;
|
|
209
255
|
params: Record<string, any> | null;
|
|
210
256
|
};
|
|
211
257
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
// messages.
|
|
216
|
-
const FALLBACK_PRIORITY = 3;
|
|
217
|
-
|
|
258
|
+
/**
|
|
259
|
+
* @internal
|
|
260
|
+
*/
|
|
218
261
|
export abstract class AbstractStreamingSyncImplementation
|
|
219
262
|
extends BaseObserver<StreamingSyncImplementationListener>
|
|
220
263
|
implements StreamingSyncImplementation
|
|
221
264
|
{
|
|
222
265
|
protected options: AbstractStreamingSyncImplementationOptions;
|
|
223
266
|
protected abortController: AbortController | null;
|
|
224
|
-
// In rare cases, mostly for tests, uploads can be triggered without being properly connected.
|
|
225
|
-
// This allows ensuring that all upload processes can be aborted.
|
|
226
|
-
protected uploadAbortController: AbortController | undefined;
|
|
227
267
|
protected crudUpdateListener?: () => void;
|
|
228
|
-
protected streamingSyncPromise?: Promise<void>;
|
|
268
|
+
protected streamingSyncPromise?: Promise<[void, void]>;
|
|
229
269
|
protected logger: ILogger;
|
|
230
270
|
private activeStreams: SubscribedStream[];
|
|
231
271
|
private connectionMayHaveChanged = false;
|
|
272
|
+
private crudUploadNotifier = asyncNotifier();
|
|
232
273
|
|
|
233
|
-
private isUploadingCrud: boolean = false;
|
|
234
274
|
private notifyCompletedUploads?: () => void;
|
|
235
275
|
private handleActiveStreamsChange?: () => void;
|
|
236
276
|
|
|
237
277
|
syncStatus: SyncStatus;
|
|
238
|
-
triggerCrudUpload: () => void;
|
|
239
278
|
|
|
240
279
|
constructor(options: AbstractStreamingSyncImplementationOptions) {
|
|
241
280
|
super();
|
|
@@ -253,18 +292,10 @@ export abstract class AbstractStreamingSyncImplementation
|
|
|
253
292
|
}
|
|
254
293
|
});
|
|
255
294
|
this.abortController = null;
|
|
295
|
+
}
|
|
256
296
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
this.isUploadingCrud = true;
|
|
263
|
-
this._uploadAllCrud().finally(() => {
|
|
264
|
-
this.notifyCompletedUploads?.();
|
|
265
|
-
this.isUploadingCrud = false;
|
|
266
|
-
});
|
|
267
|
-
}, this.options.crudUploadThrottleMs!);
|
|
297
|
+
triggerCrudUpload() {
|
|
298
|
+
this.crudUploadNotifier.notify();
|
|
268
299
|
}
|
|
269
300
|
|
|
270
301
|
async waitForReady() {}
|
|
@@ -320,7 +351,6 @@ export abstract class AbstractStreamingSyncImplementation
|
|
|
320
351
|
super.dispose();
|
|
321
352
|
this.crudUpdateListener?.();
|
|
322
353
|
this.crudUpdateListener = undefined;
|
|
323
|
-
this.uploadAbortController?.abort();
|
|
324
354
|
}
|
|
325
355
|
|
|
326
356
|
abstract obtainLock<T>(lockOptions: LockOptions<T>): Promise<T>;
|
|
@@ -334,7 +364,19 @@ export abstract class AbstractStreamingSyncImplementation
|
|
|
334
364
|
return checkpoint;
|
|
335
365
|
}
|
|
336
366
|
|
|
337
|
-
|
|
367
|
+
private async crudUploadLoop(signal: AbortSignal): Promise<void> {
|
|
368
|
+
while (!signal.aborted) {
|
|
369
|
+
await Promise.all([
|
|
370
|
+
// Start the initial CRUD upload on connect. Then, keep polling until we're done.
|
|
371
|
+
this._uploadAllCrud(signal),
|
|
372
|
+
this.delayRetry(signal, this.options.crudUploadThrottleMs!)
|
|
373
|
+
]);
|
|
374
|
+
|
|
375
|
+
await this.crudUploadNotifier.waitForNotification(signal);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
private async _uploadAllCrud(signal: AbortSignal): Promise<void> {
|
|
338
380
|
return this.obtainLock({
|
|
339
381
|
type: LockType.CRUD,
|
|
340
382
|
callback: async () => {
|
|
@@ -343,17 +385,7 @@ export abstract class AbstractStreamingSyncImplementation
|
|
|
343
385
|
*/
|
|
344
386
|
let checkedCrudItem: CrudEntry | undefined;
|
|
345
387
|
|
|
346
|
-
|
|
347
|
-
this.uploadAbortController = controller;
|
|
348
|
-
this.abortController?.signal.addEventListener(
|
|
349
|
-
'abort',
|
|
350
|
-
() => {
|
|
351
|
-
controller.abort();
|
|
352
|
-
},
|
|
353
|
-
{ once: true }
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
while (!controller.signal.aborted) {
|
|
388
|
+
while (!signal.aborted) {
|
|
357
389
|
try {
|
|
358
390
|
/**
|
|
359
391
|
* This is the first item in the FIFO CRUD queue.
|
|
@@ -384,7 +416,9 @@ The next upload iteration will be delayed.`);
|
|
|
384
416
|
} else {
|
|
385
417
|
// Uploading is completed
|
|
386
418
|
const neededUpdate = await this.options.adapter.updateLocalTarget(() => this.getWriteCheckpoint());
|
|
387
|
-
if (neededUpdate
|
|
419
|
+
if (neededUpdate) {
|
|
420
|
+
this.notifyCompletedUploads?.();
|
|
421
|
+
} else if (checkedCrudItem != null) {
|
|
388
422
|
// Only log this if there was something to upload
|
|
389
423
|
this.logger.debug('Upload complete, no write checkpoint needed.');
|
|
390
424
|
}
|
|
@@ -398,7 +432,7 @@ The next upload iteration will be delayed.`);
|
|
|
398
432
|
uploadError: ex as Error
|
|
399
433
|
}
|
|
400
434
|
});
|
|
401
|
-
await this.delayRetry(
|
|
435
|
+
await this.delayRetry(signal);
|
|
402
436
|
if (!this.isConnected) {
|
|
403
437
|
// Exit the upload loop if the sync stream is no longer connected
|
|
404
438
|
break;
|
|
@@ -414,7 +448,6 @@ The next upload iteration will be delayed.`);
|
|
|
414
448
|
});
|
|
415
449
|
}
|
|
416
450
|
}
|
|
417
|
-
this.uploadAbortController = undefined;
|
|
418
451
|
}
|
|
419
452
|
});
|
|
420
453
|
}
|
|
@@ -426,7 +459,10 @@ The next upload iteration will be delayed.`);
|
|
|
426
459
|
|
|
427
460
|
const controller = new AbortController();
|
|
428
461
|
this.abortController = controller;
|
|
429
|
-
this.streamingSyncPromise =
|
|
462
|
+
this.streamingSyncPromise = Promise.all([
|
|
463
|
+
this.crudUploadLoop(controller.signal).catch((ex) => this.logger.error('Error in crud upload loop', ex)),
|
|
464
|
+
this.streamingSync(controller.signal, options)
|
|
465
|
+
]);
|
|
430
466
|
|
|
431
467
|
// Return a promise that resolves when the connection status is updated to indicate that we're connected.
|
|
432
468
|
return new Promise<void>((resolve) => {
|
|
@@ -469,15 +505,7 @@ The next upload iteration will be delayed.`);
|
|
|
469
505
|
this.updateSyncStatus({ connected: false, connecting: false });
|
|
470
506
|
}
|
|
471
507
|
|
|
472
|
-
|
|
473
|
-
* @deprecated use [connect instead]
|
|
474
|
-
*/
|
|
475
|
-
async streamingSync(signal?: AbortSignal, options?: PowerSyncConnectionOptions): Promise<void> {
|
|
476
|
-
if (!signal) {
|
|
477
|
-
this.abortController = new AbortController();
|
|
478
|
-
signal = this.abortController.signal;
|
|
479
|
-
}
|
|
480
|
-
|
|
508
|
+
private async streamingSync(signal: AbortSignal, options?: PowerSyncConnectionOptions): Promise<void> {
|
|
481
509
|
/**
|
|
482
510
|
* Listen for CRUD updates and trigger upstream uploads
|
|
483
511
|
*/
|
|
@@ -592,7 +620,7 @@ The next upload iteration will be delayed.`);
|
|
|
592
620
|
}
|
|
593
621
|
|
|
594
622
|
/**
|
|
595
|
-
* Older versions of the JS SDK used to encode subkeys as JSON in
|
|
623
|
+
* Older versions of the JS SDK used to encode subkeys as JSON in `OplogEntry.toJSON`.
|
|
596
624
|
* Because subkeys are always strings, this leads to quotes being added around them in `ps_oplog`.
|
|
597
625
|
* While this is not a problem as long as it's done consistently, it causes issues when a database
|
|
598
626
|
* created by the JS SDK is used with other SDKs, or (more likely) when the new Rust sync client
|
|
@@ -602,7 +630,7 @@ The next upload iteration will be delayed.`);
|
|
|
602
630
|
* migration is only triggered when necessary (for now). The function returns whether the new format
|
|
603
631
|
* should be used, so that the JS SDK is able to write to updated databases.
|
|
604
632
|
*
|
|
605
|
-
* @param requireFixedKeyFormat Whether we require the new format or also support the old one.
|
|
633
|
+
* @param requireFixedKeyFormat - Whether we require the new format or also support the old one.
|
|
606
634
|
* The Rust client requires the new subkey format.
|
|
607
635
|
* @returns Whether the database is now using the new, fixed subkey format.
|
|
608
636
|
*/
|
|
@@ -902,14 +930,13 @@ The next upload iteration will be delayed.`);
|
|
|
902
930
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
903
931
|
}
|
|
904
932
|
|
|
905
|
-
private async delayRetry(signal?: AbortSignal): Promise<void> {
|
|
933
|
+
private async delayRetry(signal?: AbortSignal, delay = this.options.retryDelayMs): Promise<void> {
|
|
906
934
|
return new Promise((resolve) => {
|
|
907
935
|
if (signal?.aborted) {
|
|
908
936
|
// If the signal is already aborted, resolve immediately
|
|
909
937
|
resolve();
|
|
910
938
|
return;
|
|
911
939
|
}
|
|
912
|
-
const { retryDelayMs } = this.options;
|
|
913
940
|
|
|
914
941
|
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
915
942
|
|
|
@@ -923,7 +950,7 @@ The next upload iteration will be delayed.`);
|
|
|
923
950
|
};
|
|
924
951
|
|
|
925
952
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
926
|
-
timeoutId = setTimeout(endDelay,
|
|
953
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
927
954
|
});
|
|
928
955
|
}
|
|
929
956
|
|
|
@@ -42,7 +42,9 @@ export class WebsocketClientTransport implements ClientTransport {
|
|
|
42
42
|
resolve(new WebsocketDuplexConnection(websocket, new Deserializer(), multiplexerDemultiplexerFactory));
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const errorListener = (
|
|
45
|
+
const errorListener = (event: Event) => {
|
|
46
|
+
const ev = event as ErrorEvent;
|
|
47
|
+
|
|
46
48
|
removeListeners();
|
|
47
49
|
// We add a default error in that case.
|
|
48
50
|
if (ev.error != null) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* A description of a sync stream, consisting of its {@link name} and the
|
|
2
|
+
* A description of a sync stream, consisting of its {@link SyncStreamDescription.name} and the
|
|
3
|
+
* {@link SyncStreamDescription.parameters} used when subscribing.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
5
6
|
*/
|
|
6
7
|
export interface SyncStreamDescription {
|
|
7
8
|
/**
|
|
@@ -21,6 +22,8 @@ export interface SyncStreamDescription {
|
|
|
21
22
|
* Information about a subscribed sync stream.
|
|
22
23
|
*
|
|
23
24
|
* This includes the {@link SyncStreamDescription}, along with information about the current sync status.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
24
27
|
*/
|
|
25
28
|
export interface SyncSubscriptionDescription extends SyncStreamDescription {
|
|
26
29
|
active: boolean;
|
|
@@ -28,15 +31,17 @@ export interface SyncSubscriptionDescription extends SyncStreamDescription {
|
|
|
28
31
|
* Whether this stream subscription is included by default, regardless of whether the stream has explicitly been
|
|
29
32
|
* subscribed to or not.
|
|
30
33
|
*
|
|
31
|
-
* It's possible for both {@link isDefault} and
|
|
32
|
-
*
|
|
34
|
+
* It's possible for both {@link SyncSubscriptionDescription.isDefault} and
|
|
35
|
+
* {@link SyncSubscriptionDescription.hasExplicitSubscription} to be true at the same time - this happens when a
|
|
36
|
+
* default stream was subscribed explicitly.
|
|
33
37
|
*/
|
|
34
38
|
isDefault: boolean;
|
|
35
39
|
/**
|
|
36
40
|
* Whether this stream has been subscribed to explicitly.
|
|
37
41
|
*
|
|
38
|
-
* It's possible for both {@link isDefault} and
|
|
39
|
-
*
|
|
42
|
+
* It's possible for both {@link SyncSubscriptionDescription.isDefault} and
|
|
43
|
+
* {@link SyncSubscriptionDescription.hasExplicitSubscription} to be true at the same time - this happens when a
|
|
44
|
+
* default stream was subscribed explicitly.
|
|
40
45
|
*/
|
|
41
46
|
hasExplicitSubscription: boolean;
|
|
42
47
|
/**
|
|
@@ -49,11 +54,14 @@ export interface SyncSubscriptionDescription extends SyncStreamDescription {
|
|
|
49
54
|
*/
|
|
50
55
|
hasSynced: boolean;
|
|
51
56
|
/**
|
|
52
|
-
* If {@link hasSynced} is true, the last time data from this stream has been synced.
|
|
57
|
+
* If {@link SyncSubscriptionDescription.hasSynced} is true, the last time data from this stream has been synced.
|
|
53
58
|
*/
|
|
54
59
|
lastSyncedAt: Date | null;
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
57
65
|
export interface SyncStreamSubscribeOptions {
|
|
58
66
|
/**
|
|
59
67
|
* A "time to live" for this stream subscription, in seconds.
|
|
@@ -74,6 +82,8 @@ export interface SyncStreamSubscribeOptions {
|
|
|
74
82
|
* A handle to a {@link SyncStreamDescription} that allows subscribing to the stream.
|
|
75
83
|
*
|
|
76
84
|
* To obtain an instance of {@link SyncStream}, call {@link AbstractPowerSyncDatabase.syncStream}.
|
|
85
|
+
*
|
|
86
|
+
* @public
|
|
77
87
|
*/
|
|
78
88
|
export interface SyncStream extends SyncStreamDescription {
|
|
79
89
|
/**
|
|
@@ -82,7 +92,7 @@ export interface SyncStream extends SyncStreamDescription {
|
|
|
82
92
|
* You should keep a reference to the returned {@link SyncStreamSubscription} object along as you need data for that
|
|
83
93
|
* stream. As soon as {@link SyncStreamSubscription.unsubscribe} is called for all subscriptions on this stream
|
|
84
94
|
* (including subscriptions created on other tabs), the {@link SyncStreamSubscribeOptions.ttl} starts ticking and will
|
|
85
|
-
* eventually evict the stream (unless {@link subscribe} is called again).
|
|
95
|
+
* eventually evict the stream (unless {@link SyncStream.subscribe} is called again).
|
|
86
96
|
*/
|
|
87
97
|
subscribe(options?: SyncStreamSubscribeOptions): Promise<SyncStreamSubscription>;
|
|
88
98
|
|
|
@@ -94,6 +104,9 @@ export interface SyncStream extends SyncStreamDescription {
|
|
|
94
104
|
unsubscribeAll(): Promise<void>;
|
|
95
105
|
}
|
|
96
106
|
|
|
107
|
+
/**
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
97
110
|
export interface SyncStreamSubscription extends SyncStreamDescription {
|
|
98
111
|
/**
|
|
99
112
|
* A promise that resolves once data from in this sync stream has been synced and applied.
|