@powersync/web 1.13.1 → 1.14.1
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/index.umd.js +36 -14
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +81 -67
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +59 -57
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/lib/package.json +4 -8
- package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +1 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +1 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +4 -2
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +5 -2
- package/lib/src/db/adapters/web-sql-flags.d.ts +10 -0
- package/lib/src/db/adapters/web-sql-flags.js +1 -0
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +3 -3
- package/lib/src/worker/sync/SharedSyncImplementation.js +23 -10
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -9
package/lib/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powersync/web",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.1",
|
|
4
4
|
"description": "A Web SDK for JourneyApps PowerSync",
|
|
5
5
|
"main": "lib/src/index.js",
|
|
6
6
|
"types": "lib/src/index.d.ts",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"license": "Apache-2.0",
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"@journeyapps/wa-sqlite": "^1.2.0",
|
|
64
|
-
"@powersync/common": "workspace:^1.
|
|
64
|
+
"@powersync/common": "workspace:^1.24.0"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@powersync/common": "workspace:*",
|
|
@@ -74,20 +74,16 @@
|
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"@journeyapps/wa-sqlite": "^1.2.0",
|
|
76
76
|
"@types/uuid": "^9.0.6",
|
|
77
|
-
"@vitest/browser": "^2.1.4",
|
|
78
77
|
"crypto-browserify": "^3.12.0",
|
|
79
78
|
"p-defer": "^4.0.1",
|
|
80
79
|
"source-map-loader": "^5.0.0",
|
|
81
80
|
"stream-browserify": "^3.0.0",
|
|
82
81
|
"terser-webpack-plugin": "^5.3.9",
|
|
83
|
-
"typescript": "^5.5.3",
|
|
84
82
|
"uuid": "^9.0.1",
|
|
85
|
-
"vite": "^
|
|
86
|
-
"vite-plugin-top-level-await": "^1.4.
|
|
83
|
+
"vite": "^6.1.0",
|
|
84
|
+
"vite-plugin-top-level-await": "^1.4.4",
|
|
87
85
|
"vite-plugin-wasm": "^3.3.0",
|
|
88
|
-
"vitest": "^2.1.4",
|
|
89
86
|
"vm-browserify": "^1.1.2",
|
|
90
|
-
"webdriverio": "^8.40.6",
|
|
91
87
|
"webpack": "^5.90.1",
|
|
92
88
|
"webpack-cli": "^5.1.4",
|
|
93
89
|
"webpack-node-externals": "^3.0.0"
|
|
@@ -184,6 +184,7 @@ export class WASqliteConnection extends BaseObserver {
|
|
|
184
184
|
await this.openDB();
|
|
185
185
|
this.registerBroadcastListeners();
|
|
186
186
|
await this.executeSingleStatement(`PRAGMA temp_store = ${this.options.temporaryStorage};`);
|
|
187
|
+
await this.executeSingleStatement(`PRAGMA cache_size = -${this.options.cacheSizeKb};`);
|
|
187
188
|
await this.executeEncryptionPragma();
|
|
188
189
|
this.sqliteAPI.update_hook(this.dbP, (updateType, dbName, tableName) => {
|
|
189
190
|
if (!tableName) {
|
|
@@ -17,6 +17,7 @@ export interface WASQLiteDBAdapterOptions extends Omit<PowerSyncOpenFactoryOptio
|
|
|
17
17
|
worker?: string | URL | ((options: ResolvedWebSQLOpenOptions) => Worker | SharedWorker);
|
|
18
18
|
vfs?: WASQLiteVFS;
|
|
19
19
|
temporaryStorage?: TemporaryStorageOption;
|
|
20
|
+
cacheSizeKb?: number;
|
|
20
21
|
/**
|
|
21
22
|
* Encryption key for the database.
|
|
22
23
|
* If set, the database will be encrypted using multiple-ciphers.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
2
|
import { resolveWebPowerSyncFlags } from '../../PowerSyncDatabase';
|
|
3
3
|
import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter';
|
|
4
|
-
import { TemporaryStorageOption } from '../web-sql-flags';
|
|
4
|
+
import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption } from '../web-sql-flags';
|
|
5
5
|
import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection';
|
|
6
6
|
import { WASQLiteOpenFactory } from './WASQLiteOpenFactory';
|
|
7
7
|
/**
|
|
@@ -12,7 +12,7 @@ export class WASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
|
|
|
12
12
|
super({
|
|
13
13
|
name: options.dbFilename,
|
|
14
14
|
openConnection: async () => {
|
|
15
|
-
const { workerPort, temporaryStorage } = options;
|
|
15
|
+
const { workerPort, temporaryStorage, cacheSizeKb } = options;
|
|
16
16
|
if (workerPort) {
|
|
17
17
|
const remote = Comlink.wrap(workerPort);
|
|
18
18
|
return new WorkerWrappedAsyncDatabaseConnection({
|
|
@@ -21,6 +21,7 @@ export class WASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
|
|
|
21
21
|
baseConnection: await remote({
|
|
22
22
|
...options,
|
|
23
23
|
temporaryStorage: temporaryStorage ?? TemporaryStorageOption.MEMORY,
|
|
24
|
+
cacheSizeKb: cacheSizeKb ?? DEFAULT_CACHE_SIZE_KB,
|
|
24
25
|
flags: resolveWebPowerSyncFlags(options.flags),
|
|
25
26
|
encryptionKey: options.encryptionKey
|
|
26
27
|
})
|
|
@@ -32,6 +33,7 @@ export class WASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
|
|
|
32
33
|
debugMode: options.debugMode,
|
|
33
34
|
flags: options.flags,
|
|
34
35
|
temporaryStorage,
|
|
36
|
+
cacheSizeKb,
|
|
35
37
|
logger: options.logger,
|
|
36
38
|
vfs: options.vfs,
|
|
37
39
|
encryptionKey: options.encryptionKey,
|
|
@@ -2,7 +2,7 @@ import * as Comlink from 'comlink';
|
|
|
2
2
|
import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database';
|
|
3
3
|
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
|
|
4
4
|
import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter';
|
|
5
|
-
import { TemporaryStorageOption } from '../web-sql-flags';
|
|
5
|
+
import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption } from '../web-sql-flags';
|
|
6
6
|
import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection';
|
|
7
7
|
import { WASqliteConnection, WASQLiteVFS } from './WASQLiteConnection';
|
|
8
8
|
/**
|
|
@@ -27,7 +27,7 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
|
27
27
|
}
|
|
28
28
|
async openConnection() {
|
|
29
29
|
const { enableMultiTabs, useWebWorker } = this.resolvedFlags;
|
|
30
|
-
const { vfs = WASQLiteVFS.IDBBatchAtomicVFS, temporaryStorage = TemporaryStorageOption.MEMORY, encryptionKey } = this.waOptions;
|
|
30
|
+
const { vfs = WASQLiteVFS.IDBBatchAtomicVFS, temporaryStorage = TemporaryStorageOption.MEMORY, cacheSizeKb = DEFAULT_CACHE_SIZE_KB, encryptionKey } = this.waOptions;
|
|
31
31
|
if (!enableMultiTabs) {
|
|
32
32
|
this.logger.warn('Multiple tabs are not enabled in this browser');
|
|
33
33
|
}
|
|
@@ -37,6 +37,7 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
|
37
37
|
? resolveWorkerDatabasePortFactory(() => optionsDbWorker({
|
|
38
38
|
...this.options,
|
|
39
39
|
temporaryStorage,
|
|
40
|
+
cacheSizeKb,
|
|
40
41
|
flags: this.resolvedFlags,
|
|
41
42
|
encryptionKey
|
|
42
43
|
}))
|
|
@@ -48,6 +49,7 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
|
48
49
|
dbFilename: this.options.dbFilename,
|
|
49
50
|
vfs,
|
|
50
51
|
temporaryStorage,
|
|
52
|
+
cacheSizeKb,
|
|
51
53
|
flags: this.resolvedFlags,
|
|
52
54
|
encryptionKey: encryptionKey
|
|
53
55
|
}),
|
|
@@ -70,6 +72,7 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
|
70
72
|
debugMode: this.options.debugMode,
|
|
71
73
|
vfs,
|
|
72
74
|
temporaryStorage,
|
|
75
|
+
cacheSizeKb,
|
|
73
76
|
flags: this.resolvedFlags,
|
|
74
77
|
encryptionKey: encryptionKey
|
|
75
78
|
});
|
|
@@ -39,6 +39,7 @@ export interface ResolvedWebSQLOpenOptions extends SQLOpenOptions {
|
|
|
39
39
|
* Setting this to `FILESYSTEM` can cause issues with larger queries or datasets.
|
|
40
40
|
*/
|
|
41
41
|
temporaryStorage: TemporaryStorageOption;
|
|
42
|
+
cacheSizeKb: number;
|
|
42
43
|
/**
|
|
43
44
|
* Encryption key for the database.
|
|
44
45
|
* If set, the database will be encrypted using ChaCha20.
|
|
@@ -49,6 +50,7 @@ export declare enum TemporaryStorageOption {
|
|
|
49
50
|
MEMORY = "memory",
|
|
50
51
|
FILESYSTEM = "file"
|
|
51
52
|
}
|
|
53
|
+
export declare const DEFAULT_CACHE_SIZE_KB: number;
|
|
52
54
|
/**
|
|
53
55
|
* Options for opening a Web SQL connection
|
|
54
56
|
*/
|
|
@@ -65,8 +67,16 @@ export interface WebSQLOpenFactoryOptions extends SQLOpenOptions {
|
|
|
65
67
|
/**
|
|
66
68
|
* Where to store SQLite temporary files. Defaults to 'MEMORY'.
|
|
67
69
|
* Setting this to `FILESYSTEM` can cause issues with larger queries or datasets.
|
|
70
|
+
*
|
|
71
|
+
* For details, see: https://www.sqlite.org/pragma.html#pragma_temp_store
|
|
68
72
|
*/
|
|
69
73
|
temporaryStorage?: TemporaryStorageOption;
|
|
74
|
+
/**
|
|
75
|
+
* Maximum SQLite cache size. Defaults to 50MB.
|
|
76
|
+
*
|
|
77
|
+
* For details, see: https://www.sqlite.org/pragma.html#pragma_cache_size
|
|
78
|
+
*/
|
|
79
|
+
cacheSizeKb?: number;
|
|
70
80
|
/**
|
|
71
81
|
* Encryption key for the database.
|
|
72
82
|
* If set, the database will be encrypted using ChaCha20.
|
|
@@ -3,6 +3,7 @@ export var TemporaryStorageOption;
|
|
|
3
3
|
TemporaryStorageOption["MEMORY"] = "memory";
|
|
4
4
|
TemporaryStorageOption["FILESYSTEM"] = "file";
|
|
5
5
|
})(TemporaryStorageOption || (TemporaryStorageOption = {}));
|
|
6
|
+
export const DEFAULT_CACHE_SIZE_KB = 50 * 1024;
|
|
6
7
|
export function isServerSide() {
|
|
7
8
|
return typeof window == 'undefined';
|
|
8
9
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
2
|
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
|
|
3
3
|
import { SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation';
|
|
4
|
-
import { resolveWebSQLFlags, TemporaryStorageOption } from '../adapters/web-sql-flags';
|
|
4
|
+
import { DEFAULT_CACHE_SIZE_KB, resolveWebSQLFlags, TemporaryStorageOption } from '../adapters/web-sql-flags';
|
|
5
5
|
import { WebStreamingSyncImplementation } from './WebStreamingSyncImplementation';
|
|
6
6
|
/**
|
|
7
7
|
* The shared worker will trigger methods on this side of the message port
|
|
@@ -86,10 +86,10 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
86
86
|
* This worker will manage all syncing operations remotely.
|
|
87
87
|
*/
|
|
88
88
|
const resolvedWorkerOptions = {
|
|
89
|
-
...options,
|
|
90
89
|
dbFilename: this.options.identifier,
|
|
91
|
-
// TODO
|
|
92
90
|
temporaryStorage: TemporaryStorageOption.MEMORY,
|
|
91
|
+
cacheSizeKb: DEFAULT_CACHE_SIZE_KB,
|
|
92
|
+
...options,
|
|
93
93
|
flags: resolveWebSQLFlags(options.flags)
|
|
94
94
|
};
|
|
95
95
|
const syncWorker = options.sync?.worker;
|
|
@@ -102,6 +102,9 @@ export class SharedSyncImplementation extends BaseObserver {
|
|
|
102
102
|
await this.waitForReady();
|
|
103
103
|
// This effectively queues connect and disconnect calls. Ensuring multiple tabs' requests are synchronized
|
|
104
104
|
return getNavigatorLocks().request('shared-sync-connect', async () => {
|
|
105
|
+
if (!this.dbAdapter) {
|
|
106
|
+
await this.openInternalDB();
|
|
107
|
+
}
|
|
105
108
|
this.syncStreamClient = this.generateStreamingImplementation();
|
|
106
109
|
this.lastConnectOptions = options;
|
|
107
110
|
this.syncStreamClient.registerListener({
|
|
@@ -147,11 +150,7 @@ export class SharedSyncImplementation extends BaseObserver {
|
|
|
147
150
|
return;
|
|
148
151
|
}
|
|
149
152
|
const trackedPort = this.ports[index];
|
|
150
|
-
|
|
151
|
-
trackedPort.db.close();
|
|
152
|
-
}
|
|
153
|
-
// Release proxy
|
|
154
|
-
trackedPort.clientProvider[Comlink.releaseProxy]();
|
|
153
|
+
// Remove from the list of active ports
|
|
155
154
|
this.ports.splice(index, 1);
|
|
156
155
|
/**
|
|
157
156
|
* The port might currently be in use. Any active functions might
|
|
@@ -162,12 +161,22 @@ export class SharedSyncImplementation extends BaseObserver {
|
|
|
162
161
|
abortController.controller.abort(new AbortOperation('Closing pending requests after client port is removed'));
|
|
163
162
|
}
|
|
164
163
|
});
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
const shouldReconnect = !!this.syncStreamClient;
|
|
165
|
+
if (this.dbAdapter && this.dbAdapter == trackedPort.db) {
|
|
166
|
+
if (shouldReconnect) {
|
|
167
|
+
await this.disconnect();
|
|
168
|
+
}
|
|
169
|
+
// Clearing the adapter will result in a new one being opened in connect
|
|
170
|
+
this.dbAdapter = null;
|
|
171
|
+
if (shouldReconnect) {
|
|
172
|
+
await this.connect(this.lastConnectOptions);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (trackedPort.db) {
|
|
176
|
+
trackedPort.db.close();
|
|
170
177
|
}
|
|
178
|
+
// Release proxy
|
|
179
|
+
trackedPort.clientProvider[Comlink.releaseProxy]();
|
|
171
180
|
}
|
|
172
181
|
triggerCrudUpload() {
|
|
173
182
|
this.waitForReady().then(() => this.syncStreamClient?.triggerCrudUpload());
|
|
@@ -241,6 +250,10 @@ export class SharedSyncImplementation extends BaseObserver {
|
|
|
241
250
|
}
|
|
242
251
|
async openInternalDB() {
|
|
243
252
|
const lastClient = this.ports[this.ports.length - 1];
|
|
253
|
+
if (!lastClient) {
|
|
254
|
+
// Should not really happen in practice
|
|
255
|
+
throw new Error(`Could not open DB connection since no client is connected.`);
|
|
256
|
+
}
|
|
244
257
|
const workerPort = await lastClient.clientProvider.getDBWorkerPort();
|
|
245
258
|
const remote = Comlink.wrap(workerPort);
|
|
246
259
|
const identifier = this.syncParams.dbParams.dbFilename;
|