@powersync/common 0.0.0-dev-20240903063630 → 0.0.0-dev-20240920093037
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.mjs +18 -0
- package/dist/bundle.mjs.map +1 -0
- package/lib/client/AbstractPowerSyncDatabase.d.ts +22 -15
- package/lib/client/AbstractPowerSyncDatabase.js +51 -36
- package/lib/client/AbstractPowerSyncOpenFactory.d.ts +5 -5
- package/lib/client/AbstractPowerSyncOpenFactory.js +0 -1
- package/lib/client/SQLOpenFactory.d.ts +1 -1
- package/lib/client/SQLOpenFactory.js +0 -1
- package/lib/client/connection/PowerSyncBackendConnector.d.ts +2 -2
- package/lib/client/connection/PowerSyncBackendConnector.js +0 -1
- package/lib/client/connection/PowerSyncCredentials.js +0 -1
- package/lib/client/constants.js +0 -1
- package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +8 -4
- package/lib/client/sync/bucket/BucketStorageAdapter.js +0 -1
- package/lib/client/sync/bucket/CrudBatch.d.ts +1 -1
- package/lib/client/sync/bucket/CrudBatch.js +0 -1
- package/lib/client/sync/bucket/CrudEntry.js +0 -1
- package/lib/client/sync/bucket/CrudTransaction.d.ts +2 -2
- package/lib/client/sync/bucket/CrudTransaction.js +1 -2
- package/lib/client/sync/bucket/OpType.js +0 -1
- package/lib/client/sync/bucket/OplogEntry.d.ts +2 -2
- package/lib/client/sync/bucket/OplogEntry.js +1 -2
- package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +9 -6
- package/lib/client/sync/bucket/SqliteBucketStorage.js +28 -13
- package/lib/client/sync/bucket/SyncDataBatch.d.ts +1 -1
- package/lib/client/sync/bucket/SyncDataBatch.js +1 -2
- package/lib/client/sync/bucket/SyncDataBucket.d.ts +2 -2
- package/lib/client/sync/bucket/SyncDataBucket.js +1 -2
- package/lib/client/sync/stream/AbstractRemote.d.ts +8 -6
- package/lib/client/sync/stream/AbstractRemote.js +17 -7
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +8 -8
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +14 -11
- package/lib/client/sync/stream/streaming-sync-types.d.ts +4 -3
- package/lib/client/sync/stream/streaming-sync-types.js +0 -1
- package/lib/db/DBAdapter.d.ts +1 -1
- package/lib/db/DBAdapter.js +0 -1
- package/lib/db/crud/SyncStatus.js +0 -1
- package/lib/db/crud/UploadQueueStatus.js +0 -1
- package/lib/db/schema/Column.d.ts +30 -0
- package/lib/db/{Column.js → schema/Column.js} +17 -1
- package/lib/db/schema/Index.d.ts +3 -3
- package/lib/db/schema/Index.js +1 -2
- package/lib/db/schema/IndexedColumn.d.ts +2 -2
- package/lib/db/schema/IndexedColumn.js +1 -2
- package/lib/db/schema/Schema.d.ts +6 -7
- package/lib/db/schema/Schema.js +11 -3
- package/lib/db/schema/Table.d.ts +90 -10
- package/lib/db/schema/Table.js +61 -11
- package/lib/db/schema/TableV2.d.ts +8 -30
- package/lib/db/schema/TableV2.js +5 -62
- package/lib/index.d.ts +34 -35
- package/lib/index.js +34 -36
- package/lib/types/types.js +0 -1
- package/lib/utils/AbortOperation.js +0 -1
- package/lib/utils/BaseObserver.js +0 -1
- package/lib/utils/ControlledExecutor.js +0 -1
- package/lib/utils/DataStream.d.ts +1 -1
- package/lib/utils/DataStream.js +1 -2
- package/lib/utils/mutex.js +0 -1
- package/lib/utils/parseQuery.d.ts +1 -1
- package/lib/utils/parseQuery.js +0 -1
- package/lib/utils/throttle.d.ts +14 -0
- package/lib/utils/throttle.js +45 -0
- package/package.json +13 -5
- package/dist/index.js +0 -16
- package/lib/client/AbstractPowerSyncDatabase.js.map +0 -1
- package/lib/client/AbstractPowerSyncOpenFactory.js.map +0 -1
- package/lib/client/SQLOpenFactory.js.map +0 -1
- package/lib/client/connection/PowerSyncBackendConnector.js.map +0 -1
- package/lib/client/connection/PowerSyncCredentials.js.map +0 -1
- package/lib/client/constants.js.map +0 -1
- package/lib/client/sync/bucket/BucketStorageAdapter.js.map +0 -1
- package/lib/client/sync/bucket/CrudBatch.js.map +0 -1
- package/lib/client/sync/bucket/CrudEntry.js.map +0 -1
- package/lib/client/sync/bucket/CrudTransaction.js.map +0 -1
- package/lib/client/sync/bucket/OpType.js.map +0 -1
- package/lib/client/sync/bucket/OplogEntry.js.map +0 -1
- package/lib/client/sync/bucket/SqliteBucketStorage.js.map +0 -1
- package/lib/client/sync/bucket/SyncDataBatch.js.map +0 -1
- package/lib/client/sync/bucket/SyncDataBucket.js.map +0 -1
- package/lib/client/sync/stream/AbstractRemote.js.map +0 -1
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +0 -1
- package/lib/client/sync/stream/streaming-sync-types.js.map +0 -1
- package/lib/db/Column.d.ts +0 -19
- package/lib/db/Column.js.map +0 -1
- package/lib/db/DBAdapter.js.map +0 -1
- package/lib/db/crud/SyncStatus.js.map +0 -1
- package/lib/db/crud/UploadQueueStatus.js.map +0 -1
- package/lib/db/schema/Index.js.map +0 -1
- package/lib/db/schema/IndexedColumn.js.map +0 -1
- package/lib/db/schema/Schema.js.map +0 -1
- package/lib/db/schema/Table.js.map +0 -1
- package/lib/db/schema/TableV2.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/types/types.js.map +0 -1
- package/lib/utils/AbortOperation.js.map +0 -1
- package/lib/utils/BaseObserver.js.map +0 -1
- package/lib/utils/ControlledExecutor.js.map +0 -1
- package/lib/utils/DataStream.js.map +0 -1
- package/lib/utils/mutex.js.map +0 -1
- package/lib/utils/parseQuery.js.map +0 -1
- package/lib/utils/strings.d.ts +0 -3
- package/lib/utils/strings.js +0 -10
- package/lib/utils/strings.js.map +0 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { Mutex } from 'async-mutex';
|
|
2
|
-
import { ILogger } from 'js-logger';
|
|
3
|
-
import { DBAdapter, QueryResult, Transaction } from '../db/DBAdapter';
|
|
4
|
-
import { SyncStatus } from '../db/crud/SyncStatus';
|
|
5
|
-
import { UploadQueueStats } from '../db/crud/UploadQueueStatus';
|
|
6
|
-
import { Schema } from '../db/schema/Schema';
|
|
7
|
-
import { BaseObserver } from '../utils/BaseObserver';
|
|
8
|
-
import { SQLOpenFactory, SQLOpenOptions } from './SQLOpenFactory';
|
|
9
|
-
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector';
|
|
10
|
-
import { BucketStorageAdapter } from './sync/bucket/BucketStorageAdapter';
|
|
11
|
-
import { CrudBatch } from './sync/bucket/CrudBatch';
|
|
12
|
-
import { CrudTransaction } from './sync/bucket/CrudTransaction';
|
|
13
|
-
import {
|
|
2
|
+
import Logger, { ILogger } from 'js-logger';
|
|
3
|
+
import { DBAdapter, QueryResult, Transaction } from '../db/DBAdapter.js';
|
|
4
|
+
import { SyncStatus } from '../db/crud/SyncStatus.js';
|
|
5
|
+
import { UploadQueueStats } from '../db/crud/UploadQueueStatus.js';
|
|
6
|
+
import { Schema } from '../db/schema/Schema.js';
|
|
7
|
+
import { BaseObserver } from '../utils/BaseObserver.js';
|
|
8
|
+
import { SQLOpenFactory, SQLOpenOptions } from './SQLOpenFactory.js';
|
|
9
|
+
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector.js';
|
|
10
|
+
import { BucketStorageAdapter } from './sync/bucket/BucketStorageAdapter.js';
|
|
11
|
+
import { CrudBatch } from './sync/bucket/CrudBatch.js';
|
|
12
|
+
import { CrudTransaction } from './sync/bucket/CrudTransaction.js';
|
|
13
|
+
import { PowerSyncConnectionOptions, StreamingSyncImplementation, StreamingSyncImplementationListener } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
14
14
|
export interface DisconnectAndClearOptions {
|
|
15
15
|
/** When set to false, data in local-only tables is preserved. */
|
|
16
16
|
clearLocal?: boolean;
|
|
@@ -87,7 +87,7 @@ export declare const DEFAULT_POWERSYNC_CLOSE_OPTIONS: PowerSyncCloseOptions;
|
|
|
87
87
|
export declare const DEFAULT_WATCH_THROTTLE_MS = 30;
|
|
88
88
|
export declare const DEFAULT_POWERSYNC_DB_OPTIONS: {
|
|
89
89
|
retryDelay: number;
|
|
90
|
-
logger: ILogger;
|
|
90
|
+
logger: Logger.ILogger;
|
|
91
91
|
crudUploadThrottleMs: number;
|
|
92
92
|
};
|
|
93
93
|
/**
|
|
@@ -132,7 +132,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
132
132
|
* Schema used for the local database.
|
|
133
133
|
*/
|
|
134
134
|
get schema(): Schema<{
|
|
135
|
-
[x: string]: import("
|
|
135
|
+
[x: string]: import("../index.js").Table<any>;
|
|
136
136
|
}>;
|
|
137
137
|
/**
|
|
138
138
|
* The underlying database.
|
|
@@ -148,7 +148,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
148
148
|
* Opens the DBAdapter given open options using a default open factory
|
|
149
149
|
*/
|
|
150
150
|
protected abstract openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;
|
|
151
|
-
protected abstract generateSyncStreamImplementation(connector: PowerSyncBackendConnector):
|
|
151
|
+
protected abstract generateSyncStreamImplementation(connector: PowerSyncBackendConnector): StreamingSyncImplementation;
|
|
152
152
|
protected abstract generateBucketStorageAdapter(): BucketStorageAdapter;
|
|
153
153
|
/**
|
|
154
154
|
* @returns A promise which will resolve once initialization is completed.
|
|
@@ -168,6 +168,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
168
168
|
* This is to be automatically executed in the constructor.
|
|
169
169
|
*/
|
|
170
170
|
protected initialize(): Promise<void>;
|
|
171
|
+
private _loadVersion;
|
|
171
172
|
protected updateHasSynced(): Promise<void>;
|
|
172
173
|
/**
|
|
173
174
|
* Replace the schema with a new version. This is for advanced use cases - typically the schema should just be specified once in the constructor.
|
|
@@ -244,6 +245,12 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
244
245
|
* All data for the transaction is loaded into memory.
|
|
245
246
|
*/
|
|
246
247
|
getNextCrudTransaction(): Promise<CrudTransaction | null>;
|
|
248
|
+
/**
|
|
249
|
+
* Get an unique client id for this database.
|
|
250
|
+
*
|
|
251
|
+
* The id is not reset when the database is cleared, only when the database is deleted.
|
|
252
|
+
*/
|
|
253
|
+
getClientId(): Promise<string>;
|
|
247
254
|
private handleCrudCheckpoint;
|
|
248
255
|
/**
|
|
249
256
|
* Execute a write (INSERT/UPDATE/DELETE) query
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { Mutex } from 'async-mutex';
|
|
2
2
|
import { EventIterator } from 'event-iterator';
|
|
3
3
|
import Logger from 'js-logger';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS } from './sync/stream/AbstractStreamingSyncImplementation';
|
|
4
|
+
import { isBatchedUpdateNotification } from '../db/DBAdapter.js';
|
|
5
|
+
import { SyncStatus } from '../db/crud/SyncStatus.js';
|
|
6
|
+
import { UploadQueueStats } from '../db/crud/UploadQueueStatus.js';
|
|
7
|
+
import { BaseObserver } from '../utils/BaseObserver.js';
|
|
8
|
+
import { ControlledExecutor } from '../utils/ControlledExecutor.js';
|
|
9
|
+
import { mutexRunExclusive } from '../utils/mutex.js';
|
|
10
|
+
import { throttleTrailing } from '../utils/throttle.js';
|
|
11
|
+
import { isDBAdapter, isSQLOpenFactory, isSQLOpenOptions } from './SQLOpenFactory.js';
|
|
12
|
+
import { PSInternalTable } from './sync/bucket/BucketStorageAdapter.js';
|
|
13
|
+
import { CrudBatch } from './sync/bucket/CrudBatch.js';
|
|
14
|
+
import { CrudEntry } from './sync/bucket/CrudEntry.js';
|
|
15
|
+
import { CrudTransaction } from './sync/bucket/CrudTransaction.js';
|
|
16
|
+
import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
18
17
|
const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
|
|
19
18
|
const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
|
|
20
19
|
clearLocal: true
|
|
@@ -151,19 +150,41 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
151
150
|
async initialize() {
|
|
152
151
|
await this._initialize();
|
|
153
152
|
await this.bucketStorageAdapter.init();
|
|
154
|
-
|
|
155
|
-
this.sdkVersion = version.rows?.item(0)['powersync_rs_version()'] ?? '';
|
|
153
|
+
await this._loadVersion();
|
|
156
154
|
await this.updateSchema(this.options.schema);
|
|
157
155
|
await this.updateHasSynced();
|
|
158
156
|
await this.database.execute('PRAGMA RECURSIVE_TRIGGERS=TRUE');
|
|
159
157
|
this.ready = true;
|
|
160
158
|
this.iterateListeners((cb) => cb.initialized?.());
|
|
161
159
|
}
|
|
160
|
+
async _loadVersion() {
|
|
161
|
+
try {
|
|
162
|
+
const { version } = await this.database.get('SELECT powersync_rs_version() as version');
|
|
163
|
+
this.sdkVersion = version;
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
throw new Error(`The powersync extension is not loaded correctly. Details: ${e.message}`);
|
|
167
|
+
}
|
|
168
|
+
let versionInts;
|
|
169
|
+
try {
|
|
170
|
+
versionInts = this.sdkVersion.split(/[.\/]/)
|
|
171
|
+
.slice(0, 3)
|
|
172
|
+
.map((n) => parseInt(n));
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
throw new Error(`Unsupported powersync extension version. Need ^0.2.0, got: ${this.sdkVersion}. Details: ${e.message}`);
|
|
176
|
+
}
|
|
177
|
+
// Validate ^0.2.0
|
|
178
|
+
if (versionInts[0] != 0 || versionInts[1] != 2 || versionInts[2] < 0) {
|
|
179
|
+
throw new Error(`Unsupported powersync extension version. Need ^0.2.0, got: ${this.sdkVersion}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
162
182
|
async updateHasSynced() {
|
|
163
|
-
const result = await this.database.
|
|
164
|
-
const hasSynced =
|
|
183
|
+
const result = await this.database.get('SELECT powersync_last_synced_at() as synced_at');
|
|
184
|
+
const hasSynced = result.synced_at != null;
|
|
185
|
+
const syncedAt = result.synced_at != null ? new Date(result.synced_at + 'Z') : undefined;
|
|
165
186
|
if (hasSynced != this.currentStatus.hasSynced) {
|
|
166
|
-
this.currentStatus = new SyncStatus({ ...this.currentStatus.toJSON(), hasSynced });
|
|
187
|
+
this.currentStatus = new SyncStatus({ ...this.currentStatus.toJSON(), hasSynced, lastSyncedAt: syncedAt });
|
|
167
188
|
this.iterateListeners((l) => l.statusChanged?.(this.currentStatus));
|
|
168
189
|
}
|
|
169
190
|
}
|
|
@@ -247,20 +268,7 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
247
268
|
const { clearLocal } = options;
|
|
248
269
|
// TODO DB name, verify this is necessary with extension
|
|
249
270
|
await this.database.writeTransaction(async (tx) => {
|
|
250
|
-
await tx.execute(
|
|
251
|
-
await tx.execute(`DELETE FROM ${PSInternalTable.CRUD}`);
|
|
252
|
-
await tx.execute(`DELETE FROM ${PSInternalTable.BUCKETS}`);
|
|
253
|
-
await tx.execute(`DELETE FROM ${PSInternalTable.UNTYPED}`);
|
|
254
|
-
const tableGlob = clearLocal ? 'ps_data_*' : 'ps_data__*';
|
|
255
|
-
const existingTableRows = await tx.execute(`
|
|
256
|
-
SELECT name FROM sqlite_master WHERE type='table' AND name GLOB ?
|
|
257
|
-
`, [tableGlob]);
|
|
258
|
-
if (!existingTableRows.rows?.length) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
for (const row of existingTableRows.rows._array) {
|
|
262
|
-
await tx.execute(`DELETE FROM ${quoteIdentifier(row.name)} WHERE 1`);
|
|
263
|
-
}
|
|
271
|
+
await tx.execute('SELECT powersync_clear(?)', [clearLocal ? 1 : 0]);
|
|
264
272
|
});
|
|
265
273
|
// The data has been deleted - reset the sync status
|
|
266
274
|
this.currentStatus = new SyncStatus({});
|
|
@@ -364,6 +372,14 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
364
372
|
return new CrudTransaction(all, async (writeCheckpoint) => this.handleCrudCheckpoint(last.clientId, writeCheckpoint), txId);
|
|
365
373
|
});
|
|
366
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* Get an unique client id for this database.
|
|
377
|
+
*
|
|
378
|
+
* The id is not reset when the database is cleared, only when the database is deleted.
|
|
379
|
+
*/
|
|
380
|
+
async getClientId() {
|
|
381
|
+
return this.bucketStorageAdapter.getClientId();
|
|
382
|
+
}
|
|
367
383
|
async handleCrudCheckpoint(lastClientId, writeCheckpoint) {
|
|
368
384
|
return this.writeTransaction(async (tx) => {
|
|
369
385
|
await tx.execute(`DELETE FROM ${PSInternalTable.CRUD} WHERE id <= ?`, [lastClientId]);
|
|
@@ -578,11 +594,11 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
578
594
|
const executor = new ControlledExecutor(async (e) => {
|
|
579
595
|
await onChange(e);
|
|
580
596
|
});
|
|
581
|
-
const flushTableUpdates =
|
|
597
|
+
const flushTableUpdates = throttleTrailing(() => this.handleTableChanges(changedTables, watchedTables, (intersection) => {
|
|
582
598
|
if (resolvedOptions?.signal?.aborted)
|
|
583
599
|
return;
|
|
584
600
|
executor.schedule({ changedTables: intersection });
|
|
585
|
-
}), throttleMs
|
|
601
|
+
}), throttleMs);
|
|
586
602
|
const dispose = this.database.registerListener({
|
|
587
603
|
tablesUpdated: async (update) => {
|
|
588
604
|
try {
|
|
@@ -660,4 +676,3 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
660
676
|
return this.database.readLock((tx) => tx.execute(sql, params));
|
|
661
677
|
}
|
|
662
678
|
}
|
|
663
|
-
//# sourceMappingURL=AbstractPowerSyncDatabase.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DBAdapter } from '../db/DBAdapter';
|
|
2
|
-
import { Schema } from '../db/schema/Schema';
|
|
3
|
-
import { AbstractPowerSyncDatabase, PowerSyncDatabaseOptions } from './AbstractPowerSyncDatabase';
|
|
4
|
-
import { SQLOpenOptions } from './SQLOpenFactory';
|
|
1
|
+
import { DBAdapter } from '../db/DBAdapter.js';
|
|
2
|
+
import { Schema } from '../db/schema/Schema.js';
|
|
3
|
+
import { AbstractPowerSyncDatabase, PowerSyncDatabaseOptions } from './AbstractPowerSyncDatabase.js';
|
|
4
|
+
import { SQLOpenOptions } from './SQLOpenFactory.js';
|
|
5
5
|
export interface PowerSyncOpenFactoryOptions extends Partial<PowerSyncDatabaseOptions>, SQLOpenOptions {
|
|
6
6
|
/** Schema used for the local database. */
|
|
7
7
|
schema: Schema;
|
|
@@ -13,7 +13,7 @@ export declare abstract class AbstractPowerSyncDatabaseOpenFactory {
|
|
|
13
13
|
* Schema used for the local database.
|
|
14
14
|
*/
|
|
15
15
|
get schema(): Schema<{
|
|
16
|
-
[x: string]: import("
|
|
16
|
+
[x: string]: import("../index.js").Table<any>;
|
|
17
17
|
}>;
|
|
18
18
|
protected abstract openDB(): DBAdapter;
|
|
19
19
|
generateOptions(): PowerSyncDatabaseOptions;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PowerSyncCredentials } from './PowerSyncCredentials';
|
|
2
|
-
import type { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase';
|
|
1
|
+
import { PowerSyncCredentials } from './PowerSyncCredentials.js';
|
|
2
|
+
import type { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
|
|
3
3
|
export interface PowerSyncBackendConnector {
|
|
4
4
|
/** Allows the PowerSync client to retrieve an authentication token from your backend
|
|
5
5
|
* which is used to authenticate against the PowerSync service.
|
package/lib/client/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BaseListener, BaseObserver, Disposable } from '../../../utils/BaseObserver';
|
|
2
|
-
import { CrudBatch } from './CrudBatch';
|
|
3
|
-
import { CrudEntry, OpId } from './CrudEntry';
|
|
4
|
-
import { SyncDataBatch } from './SyncDataBatch';
|
|
1
|
+
import { BaseListener, BaseObserver, Disposable } from '../../../utils/BaseObserver.js';
|
|
2
|
+
import { CrudBatch } from './CrudBatch.js';
|
|
3
|
+
import { CrudEntry, OpId } from './CrudEntry.js';
|
|
4
|
+
import { SyncDataBatch } from './SyncDataBatch.js';
|
|
5
5
|
export interface Checkpoint {
|
|
6
6
|
last_op_id: OpId;
|
|
7
7
|
buckets: BucketChecksum[];
|
|
@@ -70,4 +70,8 @@ export interface BucketStorageAdapter extends BaseObserver<BucketStorageListener
|
|
|
70
70
|
*/
|
|
71
71
|
forceCompact(): Promise<void>;
|
|
72
72
|
getMaxOpId(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Get an unique client id.
|
|
75
|
+
*/
|
|
76
|
+
getClientId(): Promise<string>;
|
|
73
77
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CrudBatch } from './CrudBatch';
|
|
2
|
-
import { CrudEntry } from './CrudEntry';
|
|
1
|
+
import { CrudBatch } from './CrudBatch.js';
|
|
2
|
+
import { CrudEntry } from './CrudEntry.js';
|
|
3
3
|
export declare class CrudTransaction extends CrudBatch {
|
|
4
4
|
/**
|
|
5
5
|
* List of client-side changes.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CrudBatch } from './CrudBatch';
|
|
1
|
+
import { CrudBatch } from './CrudBatch.js';
|
|
2
2
|
export class CrudTransaction extends CrudBatch {
|
|
3
3
|
crud;
|
|
4
4
|
complete;
|
|
@@ -22,4 +22,3 @@ export class CrudTransaction extends CrudBatch {
|
|
|
22
22
|
this.transactionId = transactionId;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
//# sourceMappingURL=CrudTransaction.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Mutex } from 'async-mutex';
|
|
2
2
|
import { ILogger } from 'js-logger';
|
|
3
|
-
import { DBAdapter, Transaction } from '../../../db/DBAdapter';
|
|
4
|
-
import { BaseObserver } from '../../../utils/BaseObserver';
|
|
5
|
-
import { BucketState, BucketStorageAdapter, BucketStorageListener, Checkpoint, SyncLocalDatabaseResult } from './BucketStorageAdapter';
|
|
6
|
-
import { CrudBatch } from './CrudBatch';
|
|
7
|
-
import { CrudEntry } from './CrudEntry';
|
|
8
|
-
import { SyncDataBatch } from './SyncDataBatch';
|
|
3
|
+
import { DBAdapter, Transaction } from '../../../db/DBAdapter.js';
|
|
4
|
+
import { BaseObserver } from '../../../utils/BaseObserver.js';
|
|
5
|
+
import { BucketState, BucketStorageAdapter, BucketStorageListener, Checkpoint, SyncLocalDatabaseResult } from './BucketStorageAdapter.js';
|
|
6
|
+
import { CrudBatch } from './CrudBatch.js';
|
|
7
|
+
import { CrudEntry } from './CrudEntry.js';
|
|
8
|
+
import { SyncDataBatch } from './SyncDataBatch.js';
|
|
9
9
|
export declare class SqliteBucketStorage extends BaseObserver<BucketStorageListener> implements BucketStorageAdapter {
|
|
10
10
|
private db;
|
|
11
11
|
private mutex;
|
|
@@ -14,6 +14,7 @@ export declare class SqliteBucketStorage extends BaseObserver<BucketStorageListe
|
|
|
14
14
|
private pendingBucketDeletes;
|
|
15
15
|
private _hasCompletedSync;
|
|
16
16
|
private updateListener;
|
|
17
|
+
private _clientId?;
|
|
17
18
|
/**
|
|
18
19
|
* Count up, and do a compact on startup.
|
|
19
20
|
*/
|
|
@@ -21,6 +22,8 @@ export declare class SqliteBucketStorage extends BaseObserver<BucketStorageListe
|
|
|
21
22
|
constructor(db: DBAdapter, mutex: Mutex, logger?: ILogger);
|
|
22
23
|
init(): Promise<void>;
|
|
23
24
|
dispose(): Promise<void>;
|
|
25
|
+
_getClientId(): Promise<string>;
|
|
26
|
+
getClientId(): Promise<string>;
|
|
24
27
|
getMaxOpId(): string;
|
|
25
28
|
/**
|
|
26
29
|
* Reset any caches.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import Logger from 'js-logger';
|
|
2
|
-
import { extractTableUpdates } from '../../../db/DBAdapter';
|
|
3
|
-
import { BaseObserver } from '../../../utils/BaseObserver';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { CrudEntry } from './CrudEntry';
|
|
2
|
+
import { extractTableUpdates } from '../../../db/DBAdapter.js';
|
|
3
|
+
import { BaseObserver } from '../../../utils/BaseObserver.js';
|
|
4
|
+
import { MAX_OP_ID } from '../../constants.js';
|
|
5
|
+
import { PSInternalTable } from './BucketStorageAdapter.js';
|
|
6
|
+
import { CrudEntry } from './CrudEntry.js';
|
|
7
7
|
const COMPACT_OPERATION_INTERVAL = 1_000;
|
|
8
8
|
export class SqliteBucketStorage extends BaseObserver {
|
|
9
9
|
db;
|
|
@@ -13,6 +13,7 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
13
13
|
pendingBucketDeletes;
|
|
14
14
|
_hasCompletedSync;
|
|
15
15
|
updateListener;
|
|
16
|
+
_clientId;
|
|
16
17
|
/**
|
|
17
18
|
* Count up, and do a compact on startup.
|
|
18
19
|
*/
|
|
@@ -44,6 +45,16 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
44
45
|
async dispose() {
|
|
45
46
|
this.updateListener?.();
|
|
46
47
|
}
|
|
48
|
+
async _getClientId() {
|
|
49
|
+
const row = await this.db.get('SELECT powersync_client_id() as client_id');
|
|
50
|
+
return row['client_id'];
|
|
51
|
+
}
|
|
52
|
+
getClientId() {
|
|
53
|
+
if (this._clientId == null) {
|
|
54
|
+
this._clientId = this._getClientId();
|
|
55
|
+
}
|
|
56
|
+
return this._clientId;
|
|
57
|
+
}
|
|
47
58
|
getMaxOpId() {
|
|
48
59
|
return MAX_OP_ID;
|
|
49
60
|
}
|
|
@@ -88,8 +99,8 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
88
99
|
if (this._hasCompletedSync) {
|
|
89
100
|
return true;
|
|
90
101
|
}
|
|
91
|
-
const r = await this.db.
|
|
92
|
-
const completed =
|
|
102
|
+
const r = await this.db.get(`SELECT powersync_last_synced_at() as synced_at`);
|
|
103
|
+
const completed = r.synced_at != null;
|
|
93
104
|
if (completed) {
|
|
94
105
|
this._hasCompletedSync = true;
|
|
95
106
|
}
|
|
@@ -177,8 +188,7 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
177
188
|
async deletePendingBuckets() {
|
|
178
189
|
if (this.pendingBucketDeletes !== false) {
|
|
179
190
|
await this.writeTransaction(async (tx) => {
|
|
180
|
-
await tx.execute('
|
|
181
|
-
await tx.execute('DELETE FROM ps_buckets WHERE pending_delete = 1 AND last_applied_op = last_op AND last_op >= target_op');
|
|
191
|
+
await tx.execute('INSERT INTO powersync_operations(op, data) VALUES (?, ?)', ['delete_pending_buckets', '']);
|
|
182
192
|
});
|
|
183
193
|
// Executed once after start-up, and again when there are pending deletes.
|
|
184
194
|
this.pendingBucketDeletes = false;
|
|
@@ -228,7 +238,9 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
228
238
|
// New crud data may have been uploaded since we got the checkpoint. Abort.
|
|
229
239
|
return false;
|
|
230
240
|
}
|
|
231
|
-
const response = await tx.execute("UPDATE ps_buckets SET target_op = ? WHERE name='$local'", [
|
|
241
|
+
const response = await tx.execute("UPDATE ps_buckets SET target_op = CAST(? as INTEGER) WHERE name='$local'", [
|
|
242
|
+
opId
|
|
243
|
+
]);
|
|
232
244
|
this.logger.debug(['[updateLocalTarget] Response from updating target_op ', JSON.stringify(response)]);
|
|
233
245
|
return true;
|
|
234
246
|
});
|
|
@@ -270,11 +282,15 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
270
282
|
if (writeCheckpoint) {
|
|
271
283
|
const crudResult = await tx.execute('SELECT 1 FROM ps_crud LIMIT 1');
|
|
272
284
|
if (crudResult.rows?.length) {
|
|
273
|
-
await tx.execute("UPDATE ps_buckets SET target_op = ? WHERE name='$local'", [
|
|
285
|
+
await tx.execute("UPDATE ps_buckets SET target_op = CAST(? as INTEGER) WHERE name='$local'", [
|
|
286
|
+
writeCheckpoint
|
|
287
|
+
]);
|
|
274
288
|
}
|
|
275
289
|
}
|
|
276
290
|
else {
|
|
277
|
-
await tx.execute("UPDATE ps_buckets SET target_op = ? WHERE name='$local'", [
|
|
291
|
+
await tx.execute("UPDATE ps_buckets SET target_op = CAST(? as INTEGER) WHERE name='$local'", [
|
|
292
|
+
this.getMaxOpId()
|
|
293
|
+
]);
|
|
278
294
|
}
|
|
279
295
|
});
|
|
280
296
|
}
|
|
@@ -290,4 +306,3 @@ export class SqliteBucketStorage extends BaseObserver {
|
|
|
290
306
|
// No-op for now
|
|
291
307
|
}
|
|
292
308
|
}
|
|
293
|
-
//# sourceMappingURL=SqliteBucketStorage.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SyncDataBucket } from './SyncDataBucket';
|
|
1
|
+
import { SyncDataBucket } from './SyncDataBucket.js';
|
|
2
2
|
// TODO JSON
|
|
3
3
|
export class SyncDataBatch {
|
|
4
4
|
buckets;
|
|
@@ -9,4 +9,3 @@ export class SyncDataBatch {
|
|
|
9
9
|
this.buckets = buckets;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
//# sourceMappingURL=SyncDataBatch.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { OpId } from './CrudEntry';
|
|
2
|
-
import { OplogEntry, OplogEntryJSON } from './OplogEntry';
|
|
1
|
+
import { OpId } from './CrudEntry.js';
|
|
2
|
+
import { OplogEntry, OplogEntryJSON } from './OplogEntry.js';
|
|
3
3
|
export type SyncDataBucketJSON = {
|
|
4
4
|
bucket: string;
|
|
5
5
|
has_more?: boolean;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ILogger } from 'js-logger';
|
|
2
|
-
import { type fetch } from 'cross-fetch';
|
|
3
|
-
import { PowerSyncCredentials } from '../../connection/PowerSyncCredentials';
|
|
4
|
-
import { StreamingSyncLine, StreamingSyncRequest } from './streaming-sync-types';
|
|
5
|
-
import { DataStream } from '../../../utils/DataStream';
|
|
6
1
|
import type { BSON } from 'bson';
|
|
2
|
+
import { type fetch } from 'cross-fetch';
|
|
3
|
+
import Logger, { ILogger } from 'js-logger';
|
|
4
|
+
import { DataStream } from '../../../utils/DataStream.js';
|
|
5
|
+
import { PowerSyncCredentials } from '../../connection/PowerSyncCredentials.js';
|
|
6
|
+
import { StreamingSyncLine, StreamingSyncRequest } from './streaming-sync-types.js';
|
|
7
7
|
export type BSONImplementation = typeof BSON;
|
|
8
8
|
export type RemoteConnector = {
|
|
9
9
|
fetchCredentials: () => Promise<PowerSyncCredentials | null>;
|
|
10
10
|
};
|
|
11
|
-
export declare const DEFAULT_REMOTE_LOGGER: ILogger;
|
|
11
|
+
export declare const DEFAULT_REMOTE_LOGGER: Logger.ILogger;
|
|
12
12
|
export type SyncStreamOptions = {
|
|
13
13
|
path: string;
|
|
14
14
|
data: StreamingSyncRequest;
|
|
@@ -53,11 +53,13 @@ export declare abstract class AbstractRemote {
|
|
|
53
53
|
*/
|
|
54
54
|
get fetch(): FetchImplementation;
|
|
55
55
|
getCredentials(): Promise<PowerSyncCredentials | null>;
|
|
56
|
+
getUserAgent(): string;
|
|
56
57
|
protected buildRequest(path: string): Promise<{
|
|
57
58
|
url: string;
|
|
58
59
|
headers: {
|
|
59
60
|
'content-type': string;
|
|
60
61
|
Authorization: string;
|
|
62
|
+
'x-user-agent': string;
|
|
61
63
|
};
|
|
62
64
|
}>;
|
|
63
65
|
post(path: string, data: any, headers?: Record<string, string>): Promise<any>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { DataStream } from '../../../utils/DataStream';
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
3
2
|
import ndjsonStream from 'can-ndjson-stream';
|
|
3
|
+
import Logger from 'js-logger';
|
|
4
4
|
import { RSocketConnector } from 'rsocket-core';
|
|
5
5
|
import { WebsocketClientTransport } from 'rsocket-websocket-client';
|
|
6
|
-
import { AbortOperation } from '../../../utils/AbortOperation';
|
|
7
|
-
import {
|
|
6
|
+
import { AbortOperation } from '../../../utils/AbortOperation.js';
|
|
7
|
+
import { DataStream } from '../../../utils/DataStream.js';
|
|
8
|
+
import { version as POWERSYNC_JS_VERSION } from '../../../../package.json';
|
|
8
9
|
// Refresh at least 30 sec before it expires
|
|
9
10
|
const REFRESH_CREDENTIALS_SAFETY_PERIOD_MS = 30_000;
|
|
10
11
|
const SYNC_QUEUE_REQUEST_N = 10;
|
|
@@ -62,6 +63,9 @@ export class AbstractRemote {
|
|
|
62
63
|
this.credentials = await this.connector.fetchCredentials();
|
|
63
64
|
return this.credentials;
|
|
64
65
|
}
|
|
66
|
+
getUserAgent() {
|
|
67
|
+
return `powersync-js/${POWERSYNC_JS_VERSION}`;
|
|
68
|
+
}
|
|
65
69
|
async buildRequest(path) {
|
|
66
70
|
const credentials = await this.getCredentials();
|
|
67
71
|
if (credentials != null && (credentials.endpoint == null || credentials.endpoint == '')) {
|
|
@@ -72,11 +76,13 @@ export class AbstractRemote {
|
|
|
72
76
|
error.status = 401;
|
|
73
77
|
throw error;
|
|
74
78
|
}
|
|
79
|
+
const userAgent = this.getUserAgent();
|
|
75
80
|
return {
|
|
76
81
|
url: credentials.endpoint + path,
|
|
77
82
|
headers: {
|
|
78
83
|
'content-type': 'application/json',
|
|
79
|
-
Authorization: `Token ${credentials.token}
|
|
84
|
+
Authorization: `Token ${credentials.token}`,
|
|
85
|
+
'x-user-agent': userAgent
|
|
80
86
|
}
|
|
81
87
|
};
|
|
82
88
|
}
|
|
@@ -137,6 +143,10 @@ export class AbstractRemote {
|
|
|
137
143
|
const { path } = options;
|
|
138
144
|
const request = await this.buildRequest(path);
|
|
139
145
|
const bson = await this.getBSON();
|
|
146
|
+
// Add the user agent in the setup payload - we can't set custom
|
|
147
|
+
// headers with websockets on web. The browser userAgent is however added
|
|
148
|
+
// automatically as a header.
|
|
149
|
+
const userAgent = this.getUserAgent();
|
|
140
150
|
const connector = new RSocketConnector({
|
|
141
151
|
transport: new WebsocketClientTransport({
|
|
142
152
|
url: this.options.socketUrlTransformer(request.url)
|
|
@@ -149,7 +159,8 @@ export class AbstractRemote {
|
|
|
149
159
|
payload: {
|
|
150
160
|
data: null,
|
|
151
161
|
metadata: Buffer.from(bson.serialize({
|
|
152
|
-
token: request.headers.Authorization
|
|
162
|
+
token: request.headers.Authorization,
|
|
163
|
+
user_agent: userAgent
|
|
153
164
|
}))
|
|
154
165
|
}
|
|
155
166
|
}
|
|
@@ -383,4 +394,3 @@ export class AbstractRemote {
|
|
|
383
394
|
return stream;
|
|
384
395
|
}
|
|
385
396
|
}
|
|
386
|
-
//# sourceMappingURL=AbstractRemote.js.map
|