@powersync/common 0.0.0-dev-20250922104723 → 0.0.0-dev-20250922105207
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 +4 -4
- package/dist/bundle.mjs +5 -5
- package/dist/index.d.cts +845 -1054
- package/lib/client/AbstractPowerSyncDatabase.d.ts +4 -16
- package/lib/client/AbstractPowerSyncDatabase.js +26 -36
- package/lib/client/ConnectionManager.d.ts +2 -26
- package/lib/client/ConnectionManager.js +2 -114
- package/lib/client/SQLOpenFactory.d.ts +2 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +1 -9
- package/lib/client/sync/bucket/BucketStorageAdapter.js +0 -1
- package/lib/client/sync/stream/AbstractRemote.js +0 -3
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +3 -24
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +39 -54
- package/lib/client/sync/stream/core-instruction.d.ts +1 -20
- package/lib/client/sync/stream/core-instruction.js +1 -26
- package/lib/client/triggers/TriggerManager.d.ts +1 -1
- package/lib/client/watched/WatchedQuery.d.ts +0 -2
- package/lib/client/watched/WatchedQuery.js +0 -1
- package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +1 -2
- package/lib/client/watched/processors/AbstractQueryProcessor.js +15 -30
- package/lib/client/watched/processors/DifferentialQueryProcessor.js +1 -7
- package/lib/client/watched/processors/OnChangeQueryProcessor.js +1 -7
- package/lib/db/crud/SyncStatus.d.ts +1 -37
- package/lib/db/crud/SyncStatus.js +0 -61
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/package.json +1 -1
- package/lib/client/sync/sync-streams.d.ts +0 -98
- package/lib/client/sync/sync-streams.js +0 -1
|
@@ -5,7 +5,7 @@ import { SyncStatus } from '../db/crud/SyncStatus.js';
|
|
|
5
5
|
import { UploadQueueStats } from '../db/crud/UploadQueueStatus.js';
|
|
6
6
|
import { Schema } from '../db/schema/Schema.js';
|
|
7
7
|
import { BaseObserver } from '../utils/BaseObserver.js';
|
|
8
|
-
import { ConnectionManager
|
|
8
|
+
import { ConnectionManager } from './ConnectionManager.js';
|
|
9
9
|
import { ArrayQueryDefinition, Query } from './Query.js';
|
|
10
10
|
import { SQLOpenFactory, SQLOpenOptions } from './SQLOpenFactory.js';
|
|
11
11
|
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector.js';
|
|
@@ -16,7 +16,6 @@ import { StreamingSyncImplementation, StreamingSyncImplementationListener, type
|
|
|
16
16
|
import { TriggerManager } from './triggers/TriggerManager.js';
|
|
17
17
|
import { WatchCompatibleQuery } from './watched/WatchedQuery.js';
|
|
18
18
|
import { WatchedQueryComparator } from './watched/processors/comparators.js';
|
|
19
|
-
import { SyncStream } from './sync/sync-streams.js';
|
|
20
19
|
export interface DisconnectAndClearOptions {
|
|
21
20
|
/** When set to false, data in local-only tables is preserved. */
|
|
22
21
|
clearLocal?: boolean;
|
|
@@ -130,7 +129,6 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
130
129
|
protected bucketStorageAdapter: BucketStorageAdapter;
|
|
131
130
|
protected _isReadyPromise: Promise<void>;
|
|
132
131
|
protected connectionManager: ConnectionManager;
|
|
133
|
-
private subscriptions;
|
|
134
132
|
get syncStreamImplementation(): StreamingSyncImplementation | null;
|
|
135
133
|
protected _schema: Schema;
|
|
136
134
|
private _database;
|
|
@@ -166,7 +164,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
166
164
|
* Opens the DBAdapter given open options using a default open factory
|
|
167
165
|
*/
|
|
168
166
|
protected abstract openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;
|
|
169
|
-
protected abstract generateSyncStreamImplementation(connector: PowerSyncBackendConnector, options:
|
|
167
|
+
protected abstract generateSyncStreamImplementation(connector: PowerSyncBackendConnector, options: RequiredAdditionalConnectionOptions): StreamingSyncImplementation;
|
|
170
168
|
protected abstract generateBucketStorageAdapter(): BucketStorageAdapter;
|
|
171
169
|
/**
|
|
172
170
|
* @returns A promise which will resolve once initialization is completed.
|
|
@@ -185,7 +183,6 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
185
183
|
signal?: AbortSignal;
|
|
186
184
|
priority?: number;
|
|
187
185
|
}): Promise<void>;
|
|
188
|
-
private waitForStatus;
|
|
189
186
|
/**
|
|
190
187
|
* Allows for extended implementations to execute custom initialization
|
|
191
188
|
* logic as part of the total init process
|
|
@@ -197,7 +194,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
197
194
|
*/
|
|
198
195
|
protected initialize(): Promise<void>;
|
|
199
196
|
private _loadVersion;
|
|
200
|
-
protected
|
|
197
|
+
protected updateHasSynced(): Promise<void>;
|
|
201
198
|
/**
|
|
202
199
|
* Replace the schema with a new version. This is for advanced use cases - typically the schema should just be specified once in the constructor.
|
|
203
200
|
*
|
|
@@ -209,7 +206,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
209
206
|
* While initializing is automatic, this helps to catch and report initialization errors.
|
|
210
207
|
*/
|
|
211
208
|
init(): Promise<void>;
|
|
212
|
-
|
|
209
|
+
resolvedConnectionOptions(options?: PowerSyncConnectionOptions): RequiredAdditionalConnectionOptions;
|
|
213
210
|
/**
|
|
214
211
|
* @deprecated Use {@link AbstractPowerSyncDatabase#close} instead.
|
|
215
212
|
* Clears all listeners registered by {@link AbstractPowerSyncDatabase#registerListener}.
|
|
@@ -239,15 +236,6 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
239
236
|
* To preserve data in local-only tables, set clearLocal to false.
|
|
240
237
|
*/
|
|
241
238
|
disconnectAndClear(options?: DisconnectAndClearOptions): Promise<void>;
|
|
242
|
-
/**
|
|
243
|
-
* Create a sync stream to query its status or to subscribe to it.
|
|
244
|
-
*
|
|
245
|
-
* @param name The name of the stream to subscribe to.
|
|
246
|
-
* @param params Optional parameters for the stream subscription.
|
|
247
|
-
* @returns A {@link SyncStream} instance that can be subscribed to.
|
|
248
|
-
* @experimental Sync streams are currently in alpha.
|
|
249
|
-
*/
|
|
250
|
-
syncStream(name: string, params?: Record<string, any>): SyncStream;
|
|
251
239
|
/**
|
|
252
240
|
* Close the database, releasing resources.
|
|
253
241
|
*
|
|
@@ -2,6 +2,7 @@ import { Mutex } from 'async-mutex';
|
|
|
2
2
|
import { EventIterator } from 'event-iterator';
|
|
3
3
|
import Logger from 'js-logger';
|
|
4
4
|
import { isBatchedUpdateNotification } from '../db/DBAdapter.js';
|
|
5
|
+
import { FULL_SYNC_PRIORITY } from '../db/crud/SyncProgress.js';
|
|
5
6
|
import { SyncStatus } from '../db/crud/SyncStatus.js';
|
|
6
7
|
import { UploadQueueStats } from '../db/crud/UploadQueueStatus.js';
|
|
7
8
|
import { BaseObserver } from '../utils/BaseObserver.js';
|
|
@@ -18,7 +19,6 @@ import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS, DEFAULT_RETRY_DELAY_MS } from './sync/
|
|
|
18
19
|
import { TriggerManagerImpl } from './triggers/TriggerManagerImpl.js';
|
|
19
20
|
import { DEFAULT_WATCH_THROTTLE_MS } from './watched/WatchedQuery.js';
|
|
20
21
|
import { OnChangeQueryProcessor } from './watched/processors/OnChangeQueryProcessor.js';
|
|
21
|
-
import { coreStatusToJs } from './sync/stream/core-instruction.js';
|
|
22
22
|
const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
|
|
23
23
|
const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
|
|
24
24
|
clearLocal: true
|
|
@@ -59,7 +59,6 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
59
59
|
bucketStorageAdapter;
|
|
60
60
|
_isReadyPromise;
|
|
61
61
|
connectionManager;
|
|
62
|
-
subscriptions;
|
|
63
62
|
get syncStreamImplementation() {
|
|
64
63
|
return this.connectionManager.syncStreamImplementation;
|
|
65
64
|
}
|
|
@@ -101,15 +100,6 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
101
100
|
this.sdkVersion = '';
|
|
102
101
|
this.runExclusiveMutex = new Mutex();
|
|
103
102
|
// Start async init
|
|
104
|
-
this.subscriptions = {
|
|
105
|
-
firstStatusMatching: (predicate, abort) => this.waitForStatus(predicate, abort),
|
|
106
|
-
resolveOfflineSyncStatus: () => this.resolveOfflineSyncStatus(),
|
|
107
|
-
rustSubscriptionsCommand: async (payload) => {
|
|
108
|
-
await this.writeTransaction((tx) => {
|
|
109
|
-
return tx.execute('select powersync_control(?,?)', ['subscriptions', JSON.stringify(payload)]);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
103
|
this.connectionManager = new ConnectionManager({
|
|
114
104
|
createSyncImplementation: async (connector, options) => {
|
|
115
105
|
await this.waitForReady();
|
|
@@ -186,16 +176,13 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
186
176
|
const statusMatches = priority === undefined
|
|
187
177
|
? (status) => status.hasSynced
|
|
188
178
|
: (status) => status.statusForPriority(priority).hasSynced;
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
async waitForStatus(predicate, signal) {
|
|
192
|
-
if (predicate(this.currentStatus)) {
|
|
179
|
+
if (statusMatches(this.currentStatus)) {
|
|
193
180
|
return;
|
|
194
181
|
}
|
|
195
182
|
return new Promise((resolve) => {
|
|
196
183
|
const dispose = this.registerListener({
|
|
197
184
|
statusChanged: (status) => {
|
|
198
|
-
if (
|
|
185
|
+
if (statusMatches(status)) {
|
|
199
186
|
dispose();
|
|
200
187
|
resolve();
|
|
201
188
|
}
|
|
@@ -216,7 +203,7 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
216
203
|
await this.bucketStorageAdapter.init();
|
|
217
204
|
await this._loadVersion();
|
|
218
205
|
await this.updateSchema(this.options.schema);
|
|
219
|
-
await this.
|
|
206
|
+
await this.updateHasSynced();
|
|
220
207
|
await this.database.execute('PRAGMA RECURSIVE_TRIGGERS=TRUE');
|
|
221
208
|
this.ready = true;
|
|
222
209
|
this.iterateListeners((cb) => cb.initialized?.());
|
|
@@ -236,19 +223,33 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
236
223
|
.map((n) => parseInt(n));
|
|
237
224
|
}
|
|
238
225
|
catch (e) {
|
|
239
|
-
throw new Error(`Unsupported powersync extension version. Need >=0.
|
|
226
|
+
throw new Error(`Unsupported powersync extension version. Need >=0.3.11 <1.0.0, got: ${this.sdkVersion}. Details: ${e.message}`);
|
|
240
227
|
}
|
|
241
|
-
// Validate >=0.
|
|
242
|
-
if (versionInts[0] != 0 || versionInts[1] <
|
|
243
|
-
throw new Error(`Unsupported powersync extension version. Need >=0.
|
|
228
|
+
// Validate >=0.3.11 <1.0.0
|
|
229
|
+
if (versionInts[0] != 0 || versionInts[1] < 3 || (versionInts[1] == 3 && versionInts[2] < 11)) {
|
|
230
|
+
throw new Error(`Unsupported powersync extension version. Need >=0.3.11 <1.0.0, got: ${this.sdkVersion}`);
|
|
244
231
|
}
|
|
245
232
|
}
|
|
246
|
-
async
|
|
247
|
-
const result = await this.database.
|
|
248
|
-
|
|
233
|
+
async updateHasSynced() {
|
|
234
|
+
const result = await this.database.getAll('SELECT priority, last_synced_at FROM ps_sync_state ORDER BY priority DESC');
|
|
235
|
+
let lastCompleteSync;
|
|
236
|
+
const priorityStatusEntries = [];
|
|
237
|
+
for (const { priority, last_synced_at } of result) {
|
|
238
|
+
const parsedDate = new Date(last_synced_at + 'Z');
|
|
239
|
+
if (priority == FULL_SYNC_PRIORITY) {
|
|
240
|
+
// This lowest-possible priority represents a complete sync.
|
|
241
|
+
lastCompleteSync = parsedDate;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
priorityStatusEntries.push({ priority, hasSynced: true, lastSyncedAt: parsedDate });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const hasSynced = lastCompleteSync != null;
|
|
249
248
|
const updatedStatus = new SyncStatus({
|
|
250
249
|
...this.currentStatus.toJSON(),
|
|
251
|
-
|
|
250
|
+
hasSynced,
|
|
251
|
+
priorityStatusEntries,
|
|
252
|
+
lastSyncedAt: lastCompleteSync
|
|
252
253
|
});
|
|
253
254
|
if (!updatedStatus.isEqual(this.currentStatus)) {
|
|
254
255
|
this.currentStatus = updatedStatus;
|
|
@@ -345,17 +346,6 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
345
346
|
this.currentStatus = new SyncStatus({});
|
|
346
347
|
this.iterateListeners((l) => l.statusChanged?.(this.currentStatus));
|
|
347
348
|
}
|
|
348
|
-
/**
|
|
349
|
-
* Create a sync stream to query its status or to subscribe to it.
|
|
350
|
-
*
|
|
351
|
-
* @param name The name of the stream to subscribe to.
|
|
352
|
-
* @param params Optional parameters for the stream subscription.
|
|
353
|
-
* @returns A {@link SyncStream} instance that can be subscribed to.
|
|
354
|
-
* @experimental Sync streams are currently in alpha.
|
|
355
|
-
*/
|
|
356
|
-
syncStream(name, params) {
|
|
357
|
-
return this.connectionManager.stream(this.subscriptions, name, params ?? null);
|
|
358
|
-
}
|
|
359
349
|
/**
|
|
360
350
|
* Close the database, releasing resources.
|
|
361
351
|
*
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { ILogger } from 'js-logger';
|
|
2
2
|
import { BaseListener, BaseObserver } from '../utils/BaseObserver.js';
|
|
3
3
|
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector.js';
|
|
4
|
-
import {
|
|
5
|
-
import { SyncStream } from './sync/sync-streams.js';
|
|
6
|
-
import { SyncStatus } from '../db/crud/SyncStatus.js';
|
|
4
|
+
import { InternalConnectionOptions, StreamingSyncImplementation } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
7
5
|
/**
|
|
8
6
|
* @internal
|
|
9
7
|
*/
|
|
@@ -15,24 +13,11 @@ export interface ConnectionManagerSyncImplementationResult {
|
|
|
15
13
|
*/
|
|
16
14
|
onDispose: () => Promise<void> | void;
|
|
17
15
|
}
|
|
18
|
-
/**
|
|
19
|
-
* The subset of {@link AbstractStreamingSyncImplementationOptions} managed by the connection manager.
|
|
20
|
-
*
|
|
21
|
-
* @internal
|
|
22
|
-
*/
|
|
23
|
-
export interface CreateSyncImplementationOptions extends AdditionalConnectionOptions {
|
|
24
|
-
subscriptions: SubscribedStream[];
|
|
25
|
-
}
|
|
26
|
-
export interface InternalSubscriptionAdapter {
|
|
27
|
-
firstStatusMatching(predicate: (status: SyncStatus) => any, abort?: AbortSignal): Promise<void>;
|
|
28
|
-
resolveOfflineSyncStatus(): Promise<void>;
|
|
29
|
-
rustSubscriptionsCommand(payload: any): Promise<void>;
|
|
30
|
-
}
|
|
31
16
|
/**
|
|
32
17
|
* @internal
|
|
33
18
|
*/
|
|
34
19
|
export interface ConnectionManagerOptions {
|
|
35
|
-
createSyncImplementation(connector: PowerSyncBackendConnector, options:
|
|
20
|
+
createSyncImplementation(connector: PowerSyncBackendConnector, options: InternalConnectionOptions): Promise<ConnectionManagerSyncImplementationResult>;
|
|
36
21
|
logger: ILogger;
|
|
37
22
|
}
|
|
38
23
|
type StoredConnectionOptions = {
|
|
@@ -78,12 +63,6 @@ export declare class ConnectionManager extends BaseObserver<ConnectionManagerLis
|
|
|
78
63
|
* is disposed.
|
|
79
64
|
*/
|
|
80
65
|
protected syncDisposer: (() => Promise<void> | void) | null;
|
|
81
|
-
/**
|
|
82
|
-
* Subscriptions managed in this connection manager.
|
|
83
|
-
*
|
|
84
|
-
* On the web, these local subscriptions are merged across tabs by a shared worker.
|
|
85
|
-
*/
|
|
86
|
-
private locallyActiveSubscriptions;
|
|
87
66
|
constructor(options: ConnectionManagerOptions);
|
|
88
67
|
get logger(): ILogger;
|
|
89
68
|
close(): Promise<void>;
|
|
@@ -97,8 +76,5 @@ export declare class ConnectionManager extends BaseObserver<ConnectionManagerLis
|
|
|
97
76
|
disconnect(): Promise<void>;
|
|
98
77
|
protected disconnectInternal(): Promise<void>;
|
|
99
78
|
protected performDisconnect(): Promise<void>;
|
|
100
|
-
stream(adapter: InternalSubscriptionAdapter, name: string, parameters: Record<string, any> | null): SyncStream;
|
|
101
|
-
private get activeStreams();
|
|
102
|
-
private subscriptionsMayHaveChanged;
|
|
103
79
|
}
|
|
104
80
|
export {};
|
|
@@ -32,12 +32,6 @@ export class ConnectionManager extends BaseObserver {
|
|
|
32
32
|
* is disposed.
|
|
33
33
|
*/
|
|
34
34
|
syncDisposer;
|
|
35
|
-
/**
|
|
36
|
-
* Subscriptions managed in this connection manager.
|
|
37
|
-
*
|
|
38
|
-
* On the web, these local subscriptions are merged across tabs by a shared worker.
|
|
39
|
-
*/
|
|
40
|
-
locallyActiveSubscriptions = new Map();
|
|
41
35
|
constructor(options) {
|
|
42
36
|
super();
|
|
43
37
|
this.options = options;
|
|
@@ -61,7 +55,7 @@ export class ConnectionManager extends BaseObserver {
|
|
|
61
55
|
// Update pending options to the latest values
|
|
62
56
|
this.pendingConnectionOptions = {
|
|
63
57
|
connector,
|
|
64
|
-
options
|
|
58
|
+
options: options ?? {}
|
|
65
59
|
};
|
|
66
60
|
// Disconnecting here provides aborting in progress connection attempts.
|
|
67
61
|
// The connectInternal method will clear pending options once it starts connecting (with the options).
|
|
@@ -120,10 +114,7 @@ export class ConnectionManager extends BaseObserver {
|
|
|
120
114
|
const { connector, options } = this.pendingConnectionOptions;
|
|
121
115
|
appliedOptions = options;
|
|
122
116
|
this.pendingConnectionOptions = null;
|
|
123
|
-
const { sync, onDispose } = await this.options.createSyncImplementation(connector,
|
|
124
|
-
subscriptions: this.activeStreams,
|
|
125
|
-
...options
|
|
126
|
-
});
|
|
117
|
+
const { sync, onDispose } = await this.options.createSyncImplementation(connector, options);
|
|
127
118
|
this.iterateListeners((l) => l.syncStreamCreated?.(sync));
|
|
128
119
|
this.syncStreamImplementation = sync;
|
|
129
120
|
this.syncDisposer = onDispose;
|
|
@@ -180,107 +171,4 @@ export class ConnectionManager extends BaseObserver {
|
|
|
180
171
|
await sync?.dispose();
|
|
181
172
|
await disposer?.();
|
|
182
173
|
}
|
|
183
|
-
stream(adapter, name, parameters) {
|
|
184
|
-
const desc = { name, parameters };
|
|
185
|
-
const waitForFirstSync = (abort) => {
|
|
186
|
-
return adapter.firstStatusMatching((s) => s.forStream(desc)?.subscription.hasSynced, abort);
|
|
187
|
-
};
|
|
188
|
-
return {
|
|
189
|
-
...desc,
|
|
190
|
-
subscribe: async (options) => {
|
|
191
|
-
// NOTE: We also run this command if a subscription already exists, because this increases the expiry date
|
|
192
|
-
// (relevant if the app is closed before connecting again, where the last subscribe call determines the ttl).
|
|
193
|
-
await adapter.rustSubscriptionsCommand({
|
|
194
|
-
subscribe: {
|
|
195
|
-
stream: {
|
|
196
|
-
name,
|
|
197
|
-
params: parameters
|
|
198
|
-
},
|
|
199
|
-
ttl: options?.ttl,
|
|
200
|
-
priority: options?.priority
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
if (!this.syncStreamImplementation) {
|
|
204
|
-
// We're not connected. So, update the offline sync status to reflect the new subscription.
|
|
205
|
-
// (With an active iteration, the sync client would include it in its state).
|
|
206
|
-
await adapter.resolveOfflineSyncStatus();
|
|
207
|
-
}
|
|
208
|
-
const key = `${name}|${JSON.stringify(parameters)}`;
|
|
209
|
-
let subscription = this.locallyActiveSubscriptions.get(key);
|
|
210
|
-
if (subscription == null) {
|
|
211
|
-
const clearSubscription = () => {
|
|
212
|
-
this.locallyActiveSubscriptions.delete(key);
|
|
213
|
-
this.subscriptionsMayHaveChanged();
|
|
214
|
-
};
|
|
215
|
-
subscription = new ActiveSubscription(name, parameters, this.logger, waitForFirstSync, clearSubscription);
|
|
216
|
-
this.locallyActiveSubscriptions.set(key, subscription);
|
|
217
|
-
this.subscriptionsMayHaveChanged();
|
|
218
|
-
}
|
|
219
|
-
return new SyncStreamSubscriptionHandle(subscription);
|
|
220
|
-
},
|
|
221
|
-
unsubscribeAll: async () => {
|
|
222
|
-
await adapter.rustSubscriptionsCommand({ unsubscribe: { name, params: parameters } });
|
|
223
|
-
this.subscriptionsMayHaveChanged();
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
get activeStreams() {
|
|
228
|
-
return [...this.locallyActiveSubscriptions.values()].map((a) => ({ name: a.name, params: a.parameters }));
|
|
229
|
-
}
|
|
230
|
-
subscriptionsMayHaveChanged() {
|
|
231
|
-
if (this.syncStreamImplementation) {
|
|
232
|
-
this.syncStreamImplementation.updateSubscriptions(this.activeStreams);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
class ActiveSubscription {
|
|
237
|
-
name;
|
|
238
|
-
parameters;
|
|
239
|
-
logger;
|
|
240
|
-
waitForFirstSync;
|
|
241
|
-
clearSubscription;
|
|
242
|
-
refcount = 0;
|
|
243
|
-
constructor(name, parameters, logger, waitForFirstSync, clearSubscription) {
|
|
244
|
-
this.name = name;
|
|
245
|
-
this.parameters = parameters;
|
|
246
|
-
this.logger = logger;
|
|
247
|
-
this.waitForFirstSync = waitForFirstSync;
|
|
248
|
-
this.clearSubscription = clearSubscription;
|
|
249
|
-
}
|
|
250
|
-
decrementRefCount() {
|
|
251
|
-
this.refcount--;
|
|
252
|
-
if (this.refcount == 0) {
|
|
253
|
-
this.clearSubscription();
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
class SyncStreamSubscriptionHandle {
|
|
258
|
-
subscription;
|
|
259
|
-
active = true;
|
|
260
|
-
constructor(subscription) {
|
|
261
|
-
this.subscription = subscription;
|
|
262
|
-
subscription.refcount++;
|
|
263
|
-
_finalizer?.register(this, subscription);
|
|
264
|
-
}
|
|
265
|
-
get name() {
|
|
266
|
-
return this.subscription.name;
|
|
267
|
-
}
|
|
268
|
-
get parameters() {
|
|
269
|
-
return this.subscription.parameters;
|
|
270
|
-
}
|
|
271
|
-
waitForFirstSync(abort) {
|
|
272
|
-
return this.subscription.waitForFirstSync(abort);
|
|
273
|
-
}
|
|
274
|
-
unsubscribe() {
|
|
275
|
-
if (this.active) {
|
|
276
|
-
this.active = false;
|
|
277
|
-
_finalizer?.unregister(this);
|
|
278
|
-
this.subscription.decrementRefCount();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
174
|
}
|
|
282
|
-
const _finalizer = 'FinalizationRegistry' in globalThis
|
|
283
|
-
? new FinalizationRegistry((sub) => {
|
|
284
|
-
sub.logger.warn(`A subscription to ${sub.name} with params ${JSON.stringify(sub.parameters)} leaked! Please ensure calling unsubscribe() when you don't need a subscription anymore. For global subscriptions, consider storing them in global fields to avoid this warning.`);
|
|
285
|
-
})
|
|
286
|
-
: null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ILogger } from 'js-logger';
|
|
1
2
|
import { DBAdapter } from '../db/DBAdapter.js';
|
|
2
3
|
export interface SQLOpenOptions {
|
|
3
4
|
/**
|
|
@@ -21,6 +22,7 @@ export interface SQLOpenOptions {
|
|
|
21
22
|
* debugMode: process.env.NODE_ENV !== 'production'
|
|
22
23
|
*/
|
|
23
24
|
debugMode?: boolean;
|
|
25
|
+
logger?: ILogger;
|
|
24
26
|
}
|
|
25
27
|
export interface SQLOpenFactory {
|
|
26
28
|
/**
|
|
@@ -10,7 +10,6 @@ export interface Checkpoint {
|
|
|
10
10
|
last_op_id: OpId;
|
|
11
11
|
buckets: BucketChecksum[];
|
|
12
12
|
write_checkpoint?: string;
|
|
13
|
-
streams?: any[];
|
|
14
13
|
}
|
|
15
14
|
export interface BucketState {
|
|
16
15
|
bucket: string;
|
|
@@ -44,12 +43,6 @@ export interface BucketChecksum {
|
|
|
44
43
|
* Count of operations - informational only.
|
|
45
44
|
*/
|
|
46
45
|
count?: number;
|
|
47
|
-
/**
|
|
48
|
-
* The JavaScript client does not use this field, which is why it's defined to be `any`. We rely on the structure of
|
|
49
|
-
* this interface to pass custom `BucketChecksum`s to the Rust client in unit tests, which so all fields need to be
|
|
50
|
-
* present.
|
|
51
|
-
*/
|
|
52
|
-
subscriptions?: any;
|
|
53
46
|
}
|
|
54
47
|
export declare enum PSInternalTable {
|
|
55
48
|
DATA = "ps_data",
|
|
@@ -64,8 +57,7 @@ export declare enum PowerSyncControlCommand {
|
|
|
64
57
|
STOP = "stop",
|
|
65
58
|
START = "start",
|
|
66
59
|
NOTIFY_TOKEN_REFRESHED = "refreshed_token",
|
|
67
|
-
NOTIFY_CRUD_UPLOAD_COMPLETED = "completed_upload"
|
|
68
|
-
UPDATE_SUBSCRIPTIONS = "update_subscriptions"
|
|
60
|
+
NOTIFY_CRUD_UPLOAD_COMPLETED = "completed_upload"
|
|
69
61
|
}
|
|
70
62
|
export interface BucketStorageListener extends BaseListener {
|
|
71
63
|
crudUpdate: () => void;
|
|
@@ -14,5 +14,4 @@ export var PowerSyncControlCommand;
|
|
|
14
14
|
PowerSyncControlCommand["START"] = "start";
|
|
15
15
|
PowerSyncControlCommand["NOTIFY_TOKEN_REFRESHED"] = "refreshed_token";
|
|
16
16
|
PowerSyncControlCommand["NOTIFY_CRUD_UPLOAD_COMPLETED"] = "completed_upload";
|
|
17
|
-
PowerSyncControlCommand["UPDATE_SUBSCRIPTIONS"] = "update_subscriptions";
|
|
18
17
|
})(PowerSyncControlCommand || (PowerSyncControlCommand = {}));
|
|
@@ -382,9 +382,6 @@ export class AbstractRemote {
|
|
|
382
382
|
* Aborting the active fetch request while it is being consumed seems to throw
|
|
383
383
|
* an unhandled exception on the window level.
|
|
384
384
|
*/
|
|
385
|
-
if (abortSignal?.aborted) {
|
|
386
|
-
throw new AbortOperation('Abort request received before making postStreamRaw request');
|
|
387
|
-
}
|
|
388
385
|
const controller = new AbortController();
|
|
389
386
|
let requestResolved = false;
|
|
390
387
|
abortSignal?.addEventListener('abort', () => {
|
|
@@ -62,9 +62,8 @@ export interface LockOptions<T> {
|
|
|
62
62
|
type: LockType;
|
|
63
63
|
signal?: AbortSignal;
|
|
64
64
|
}
|
|
65
|
-
export interface AbstractStreamingSyncImplementationOptions extends
|
|
65
|
+
export interface AbstractStreamingSyncImplementationOptions extends AdditionalConnectionOptions {
|
|
66
66
|
adapter: BucketStorageAdapter;
|
|
67
|
-
subscriptions: SubscribedStream[];
|
|
68
67
|
uploadCrud: () => Promise<void>;
|
|
69
68
|
/**
|
|
70
69
|
* An identifier for which PowerSync DB this sync implementation is
|
|
@@ -116,12 +115,6 @@ export interface BaseConnectionOptions {
|
|
|
116
115
|
* These parameters are passed to the sync rules, and will be available under the`user_parameters` object.
|
|
117
116
|
*/
|
|
118
117
|
params?: Record<string, StreamingSyncRequestParameterType>;
|
|
119
|
-
/**
|
|
120
|
-
* Whether to include streams that have `auto_subscribe: true` in their definition.
|
|
121
|
-
*
|
|
122
|
-
* This defaults to `true`.
|
|
123
|
-
*/
|
|
124
|
-
includeDefaultStreams?: boolean;
|
|
125
118
|
/**
|
|
126
119
|
* The serialized schema - mainly used to forward information about raw tables to the sync client.
|
|
127
120
|
*/
|
|
@@ -142,9 +135,7 @@ export interface AdditionalConnectionOptions {
|
|
|
142
135
|
crudUploadThrottleMs?: number;
|
|
143
136
|
}
|
|
144
137
|
/** @internal */
|
|
145
|
-
export
|
|
146
|
-
subscriptions: SubscribedStream[];
|
|
147
|
-
}
|
|
138
|
+
export type RequiredAdditionalConnectionOptions = Required<AdditionalConnectionOptions>;
|
|
148
139
|
export interface StreamingSyncImplementation extends BaseObserverInterface<StreamingSyncImplementationListener>, Disposable {
|
|
149
140
|
/**
|
|
150
141
|
* Connects to the sync service
|
|
@@ -164,7 +155,6 @@ export interface StreamingSyncImplementation extends BaseObserverInterface<Strea
|
|
|
164
155
|
waitForReady(): Promise<void>;
|
|
165
156
|
waitForStatus(status: SyncStatusOptions): Promise<void>;
|
|
166
157
|
waitUntilStatusMatches(predicate: (status: SyncStatus) => boolean): Promise<void>;
|
|
167
|
-
updateSubscriptions(subscriptions: SubscribedStream[]): void;
|
|
168
158
|
}
|
|
169
159
|
export declare const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
170
160
|
export declare const DEFAULT_RETRY_DELAY_MS = 5000;
|
|
@@ -174,10 +164,6 @@ export declare const DEFAULT_STREAMING_SYNC_OPTIONS: {
|
|
|
174
164
|
};
|
|
175
165
|
export type RequiredPowerSyncConnectionOptions = Required<BaseConnectionOptions>;
|
|
176
166
|
export declare const DEFAULT_STREAM_CONNECTION_OPTIONS: RequiredPowerSyncConnectionOptions;
|
|
177
|
-
export type SubscribedStream = {
|
|
178
|
-
name: string;
|
|
179
|
-
params: Record<string, any> | null;
|
|
180
|
-
};
|
|
181
167
|
export declare abstract class AbstractStreamingSyncImplementation extends BaseObserver<StreamingSyncImplementationListener> implements StreamingSyncImplementation {
|
|
182
168
|
protected _lastSyncedAt: Date | null;
|
|
183
169
|
protected options: AbstractStreamingSyncImplementationOptions;
|
|
@@ -186,10 +172,8 @@ export declare abstract class AbstractStreamingSyncImplementation extends BaseOb
|
|
|
186
172
|
protected crudUpdateListener?: () => void;
|
|
187
173
|
protected streamingSyncPromise?: Promise<void>;
|
|
188
174
|
protected logger: ILogger;
|
|
189
|
-
private activeStreams;
|
|
190
175
|
private isUploadingCrud;
|
|
191
176
|
private notifyCompletedUploads?;
|
|
192
|
-
private handleActiveStreamsChange?;
|
|
193
177
|
syncStatus: SyncStatus;
|
|
194
178
|
triggerCrudUpload: () => void;
|
|
195
179
|
constructor(options: AbstractStreamingSyncImplementationOptions);
|
|
@@ -226,16 +210,11 @@ export declare abstract class AbstractStreamingSyncImplementation extends BaseOb
|
|
|
226
210
|
* @returns Whether the database is now using the new, fixed subkey format.
|
|
227
211
|
*/
|
|
228
212
|
private requireKeyFormat;
|
|
229
|
-
protected streamingSyncIteration(signal: AbortSignal, options?: PowerSyncConnectionOptions): Promise<
|
|
213
|
+
protected streamingSyncIteration(signal: AbortSignal, options?: PowerSyncConnectionOptions): Promise<void>;
|
|
230
214
|
private legacyStreamingSyncIteration;
|
|
231
215
|
private rustSyncIteration;
|
|
232
216
|
private updateSyncStatusForStartingCheckpoint;
|
|
233
217
|
private applyCheckpoint;
|
|
234
218
|
protected updateSyncStatus(options: SyncStatusOptions): void;
|
|
235
219
|
private delayRetry;
|
|
236
|
-
updateSubscriptions(subscriptions: SubscribedStream[]): void;
|
|
237
|
-
}
|
|
238
|
-
interface RustIterationResult {
|
|
239
|
-
immediateRestart: boolean;
|
|
240
220
|
}
|
|
241
|
-
export {};
|