@powersync/web 1.30.0 → 1.32.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/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js +1867 -0
- package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js.map +1 -0
- package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530150.index.umd.js +555 -0
- package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530150.index.umd.js.map +1 -0
- package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530151.index.umd.js +555 -0
- package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530151.index.umd.js.map +1 -0
- package/dist/index.umd.js +5022 -38504
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +819 -2220
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +524 -2121
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/dist/worker/{node_modules_bson_lib_bson_mjs.umd.js → node_modules_pnpm_bson_6_10_4_node_modules_bson_lib_bson_mjs.umd.js} +8 -8
- package/dist/worker/node_modules_pnpm_bson_6_10_4_node_modules_bson_lib_bson_mjs.umd.js.map +1 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-3a94cf.umd.js +44 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-3a94cf.umd.js.map +1 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-868779.umd.js +44 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-868779.umd.js.map +1 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-f60d0d.umd.js +44 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-f60d0d.umd.js.map +1 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +44 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -0
- package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-0d2437.umd.js} +32 -32
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-0d2437.umd.js.map +1 -0
- package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-1d4e74.umd.js} +24 -24
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-1d4e74.umd.js.map +1 -0
- package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-3622cf.umd.js} +24 -24
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-3622cf.umd.js.map +1 -0
- package/lib/package.json +27 -23
- package/lib/src/db/NavigatorTriggerClaimManager.d.ts +6 -0
- package/lib/src/db/NavigatorTriggerClaimManager.js +20 -0
- package/lib/src/db/PowerSyncDatabase.d.ts +5 -2
- package/lib/src/db/PowerSyncDatabase.js +49 -11
- package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.d.ts +1 -1
- package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +1 -1
- package/lib/src/db/adapters/AbstractWebSQLOpenFactory.d.ts +2 -2
- package/lib/src/db/adapters/AbstractWebSQLOpenFactory.js +2 -2
- package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +1 -1
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +21 -4
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +116 -22
- package/lib/src/db/adapters/WebDBAdapter.d.ts +5 -2
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +7 -3
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +14 -7
- package/lib/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.d.ts +12 -0
- package/lib/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.js +19 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.d.ts +2 -2
- package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +11 -2
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +4 -4
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +6 -6
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +5 -5
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +7 -7
- package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.d.ts +1 -1
- package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +3 -3
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +6 -9
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +54 -38
- package/lib/src/db/sync/WebRemote.js +1 -1
- package/lib/src/db/sync/WebStreamingSyncImplementation.d.ts +1 -1
- package/lib/src/db/sync/WebStreamingSyncImplementation.js +1 -1
- package/lib/src/index.d.ts +12 -12
- package/lib/src/index.js +12 -12
- package/lib/src/worker/db/SharedWASQLiteConnection.d.ts +2 -2
- package/lib/src/worker/db/WASQLiteDB.worker.js +3 -3
- package/lib/src/worker/db/WorkerWASQLiteConnection.d.ts +2 -2
- package/lib/src/worker/db/WorkerWASQLiteConnection.js +1 -1
- package/lib/src/worker/db/open-worker-database.d.ts +2 -2
- package/lib/src/worker/db/open-worker-database.js +1 -1
- package/lib/src/worker/sync/BroadcastLogger.d.ts +1 -1
- package/lib/src/worker/sync/SharedSyncImplementation.d.ts +21 -11
- package/lib/src/worker/sync/SharedSyncImplementation.js +209 -113
- package/lib/src/worker/sync/SharedSyncImplementation.worker.js +3 -3
- package/lib/src/worker/sync/WorkerClient.d.ts +4 -5
- package/lib/src/worker/sync/WorkerClient.js +8 -10
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -19
- package/src/db/NavigatorTriggerClaimManager.ts +23 -0
- package/src/db/PowerSyncDatabase.ts +64 -22
- package/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.ts +1 -1
- package/src/db/adapters/AbstractWebSQLOpenFactory.ts +3 -3
- package/src/db/adapters/AsyncDatabaseConnection.ts +1 -1
- package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +138 -33
- package/src/db/adapters/WebDBAdapter.ts +6 -2
- package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +20 -8
- package/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.ts +23 -0
- package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +13 -5
- package/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts +8 -8
- package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +9 -9
- package/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.ts +3 -3
- package/src/db/sync/SharedWebStreamingSyncImplementation.ts +69 -51
- package/src/db/sync/WebRemote.ts +1 -1
- package/src/db/sync/WebStreamingSyncImplementation.ts +2 -2
- package/src/index.ts +12 -12
- package/src/worker/db/SharedWASQLiteConnection.ts +2 -2
- package/src/worker/db/WASQLiteDB.worker.ts +5 -6
- package/src/worker/db/WorkerWASQLiteConnection.ts +2 -2
- package/src/worker/db/open-worker-database.ts +2 -2
- package/src/worker/sync/BroadcastLogger.ts +1 -1
- package/src/worker/sync/SharedSyncImplementation.ts +241 -126
- package/src/worker/sync/SharedSyncImplementation.worker.ts +3 -3
- package/src/worker/sync/WorkerClient.ts +10 -14
- package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +0 -44
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +0 -44
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +0 -44
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +0 -44
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +0 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +0 -1
- /package/bin/{powersync.js → powersync.cjs} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BaseObserver, createLogger } from '@powersync/common';
|
|
2
|
-
import { getNavigatorLocks } from '
|
|
3
|
-
import { WorkerWrappedAsyncDatabaseConnection } from './WorkerWrappedAsyncDatabaseConnection';
|
|
4
|
-
import { WASQLiteVFS } from './wa-sqlite/WASQLiteConnection';
|
|
1
|
+
import { BaseObserver, ConnectionClosedError, createLogger } from '@powersync/common';
|
|
2
|
+
import { getNavigatorLocks } from '../../shared/navigator.js';
|
|
3
|
+
import { WorkerWrappedAsyncDatabaseConnection } from './WorkerWrappedAsyncDatabaseConnection.js';
|
|
4
|
+
import { WASQLiteVFS } from './wa-sqlite/WASQLiteConnection.js';
|
|
5
5
|
/**
|
|
6
6
|
* @internal
|
|
7
7
|
* Wraps a {@link AsyncDatabaseConnection} and provides exclusive locking functions in
|
|
@@ -19,6 +19,7 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
19
19
|
_config = null;
|
|
20
20
|
pendingAbortControllers;
|
|
21
21
|
requiresHolds;
|
|
22
|
+
databaseOpenPromise = null;
|
|
22
23
|
closing;
|
|
23
24
|
closed;
|
|
24
25
|
constructor(options) {
|
|
@@ -68,22 +69,79 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
68
69
|
async init() {
|
|
69
70
|
return this.initPromise;
|
|
70
71
|
}
|
|
72
|
+
async openInternalDB() {
|
|
73
|
+
/**
|
|
74
|
+
* Execute opening of the db in a lock in order not to interfere with other operations.
|
|
75
|
+
*/
|
|
76
|
+
return this._acquireLock(async () => {
|
|
77
|
+
// Dispose any previous table change listener.
|
|
78
|
+
this._disposeTableChangeListener?.();
|
|
79
|
+
this._disposeTableChangeListener = null;
|
|
80
|
+
this._db?.close().catch((ex) => this.logger.warn(`Error closing database before opening new instance`, ex));
|
|
81
|
+
const isReOpen = !!this._db;
|
|
82
|
+
this._db = null;
|
|
83
|
+
this._db = await this.options.openConnection();
|
|
84
|
+
await this._db.init();
|
|
85
|
+
this._config = await this._db.getConfig();
|
|
86
|
+
await this.registerOnChangeListener(this._db);
|
|
87
|
+
if (isReOpen) {
|
|
88
|
+
this.iterateListeners((cb) => cb.databaseReOpened?.());
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* This is only required for the long-lived shared IndexedDB connections.
|
|
92
|
+
*/
|
|
93
|
+
this.requiresHolds = this._config.vfs == WASQLiteVFS.IDBBatchAtomicVFS;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
_reOpen() {
|
|
97
|
+
this.databaseOpenPromise = this.openInternalDB().finally(() => {
|
|
98
|
+
this.databaseOpenPromise = null;
|
|
99
|
+
});
|
|
100
|
+
return this.databaseOpenPromise;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Re-opens the underlying database.
|
|
104
|
+
* Returns a pending operation if one is already in progress.
|
|
105
|
+
*/
|
|
106
|
+
async reOpenInternalDB() {
|
|
107
|
+
if (!this.options.reOpenOnConnectionClosed) {
|
|
108
|
+
throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
|
|
109
|
+
}
|
|
110
|
+
if (this.databaseOpenPromise) {
|
|
111
|
+
return this.databaseOpenPromise;
|
|
112
|
+
}
|
|
113
|
+
return this._reOpen();
|
|
114
|
+
}
|
|
71
115
|
async _init() {
|
|
72
|
-
this._db = await this.options.openConnection();
|
|
73
|
-
await this._db.init();
|
|
74
|
-
this._config = await this._db.getConfig();
|
|
75
|
-
await this.registerOnChangeListener(this._db);
|
|
76
|
-
this.iterateListeners((cb) => cb.initialized?.());
|
|
77
116
|
/**
|
|
78
|
-
*
|
|
117
|
+
* For OPFS, we can see this open call sometimes fail due to NoModificationAllowedError.
|
|
118
|
+
* We should be able to recover from this by re-opening the database.
|
|
79
119
|
*/
|
|
80
|
-
|
|
120
|
+
const maxAttempts = 3;
|
|
121
|
+
for (let count = 0; count < maxAttempts; count++) {
|
|
122
|
+
try {
|
|
123
|
+
await this.openInternalDB();
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
catch (ex) {
|
|
127
|
+
if (count == maxAttempts - 1) {
|
|
128
|
+
throw ex;
|
|
129
|
+
}
|
|
130
|
+
this.logger.warn(`Attempt ${count + 1} of ${maxAttempts} to open database failed, retrying in 1 second...`, ex);
|
|
131
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
this.iterateListeners((cb) => cb.initialized?.());
|
|
81
135
|
}
|
|
82
136
|
getConfiguration() {
|
|
83
137
|
if (!this._config) {
|
|
84
138
|
throw new Error(`Cannot get config before initialization is completed`);
|
|
85
139
|
}
|
|
86
|
-
return
|
|
140
|
+
return {
|
|
141
|
+
...this._config,
|
|
142
|
+
// This can be overridden by the adapter later
|
|
143
|
+
requiresPersistentTriggers: false
|
|
144
|
+
};
|
|
87
145
|
}
|
|
88
146
|
async waitForInitialized() {
|
|
89
147
|
// Awaiting this will expose errors on function calls like .execute etc
|
|
@@ -124,7 +182,14 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
124
182
|
*/
|
|
125
183
|
async close() {
|
|
126
184
|
this.closing = true;
|
|
127
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Note that we obtain a reference to the callback to avoid calling the callback with `this` as the context.
|
|
187
|
+
* This is to avoid Comlink attempting to clone `this` when calling the method.
|
|
188
|
+
*/
|
|
189
|
+
const dispose = this._disposeTableChangeListener;
|
|
190
|
+
if (dispose) {
|
|
191
|
+
dispose();
|
|
192
|
+
}
|
|
128
193
|
this.pendingAbortControllers.forEach((controller) => controller.abort('Closed'));
|
|
129
194
|
await this.baseDB?.close?.();
|
|
130
195
|
this.closed = true;
|
|
@@ -144,24 +209,23 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
144
209
|
async readLock(fn, options) {
|
|
145
210
|
await this.waitForInitialized();
|
|
146
211
|
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
|
|
147
|
-
timeoutMs: options?.timeoutMs
|
|
212
|
+
timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
|
|
148
213
|
});
|
|
149
214
|
}
|
|
150
215
|
async writeLock(fn, options) {
|
|
151
216
|
await this.waitForInitialized();
|
|
152
217
|
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
|
|
153
|
-
timeoutMs: options?.timeoutMs
|
|
218
|
+
timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
|
|
154
219
|
});
|
|
155
220
|
}
|
|
156
|
-
async
|
|
157
|
-
await this.waitForInitialized();
|
|
221
|
+
async _acquireLock(callback, options) {
|
|
158
222
|
if (this.closing) {
|
|
159
223
|
throw new Error(`Cannot acquire lock, the database is closing`);
|
|
160
224
|
}
|
|
161
225
|
const abortController = new AbortController();
|
|
162
226
|
this.pendingAbortControllers.add(abortController);
|
|
163
227
|
const { timeoutMs } = options ?? {};
|
|
164
|
-
const
|
|
228
|
+
const timeoutId = timeoutMs
|
|
165
229
|
? setTimeout(() => {
|
|
166
230
|
abortController.abort(`Timeout after ${timeoutMs}ms`);
|
|
167
231
|
this.pendingAbortControllers.delete(abortController);
|
|
@@ -169,19 +233,49 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
169
233
|
: null;
|
|
170
234
|
return getNavigatorLocks().request(`db-lock-${this._dbIdentifier}`, { signal: abortController.signal }, async () => {
|
|
171
235
|
this.pendingAbortControllers.delete(abortController);
|
|
172
|
-
if (
|
|
173
|
-
clearTimeout(
|
|
236
|
+
if (timeoutId) {
|
|
237
|
+
clearTimeout(timeoutId);
|
|
174
238
|
}
|
|
175
|
-
|
|
239
|
+
return await callback();
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async acquireLock(callback, options) {
|
|
243
|
+
await this.waitForInitialized();
|
|
244
|
+
// The database is being opened in the background. Wait for it here.
|
|
245
|
+
if (this.databaseOpenPromise) {
|
|
246
|
+
await this.databaseOpenPromise;
|
|
247
|
+
}
|
|
248
|
+
return this._acquireLock(async () => {
|
|
249
|
+
let holdId = null;
|
|
176
250
|
try {
|
|
251
|
+
/**
|
|
252
|
+
* We can't await this since it uses the same lock as we're in now.
|
|
253
|
+
* If there is a pending open, this call will throw.
|
|
254
|
+
* If there is no pending open, but there is also no database - the open
|
|
255
|
+
* might have failed. We need to re-open the database.
|
|
256
|
+
*/
|
|
257
|
+
if (this.databaseOpenPromise || !this._db) {
|
|
258
|
+
throw new ConnectionClosedError('Connection is busy re-opening');
|
|
259
|
+
}
|
|
260
|
+
holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
|
|
177
261
|
return await callback();
|
|
178
262
|
}
|
|
263
|
+
catch (ex) {
|
|
264
|
+
if (ConnectionClosedError.MATCHES(ex)) {
|
|
265
|
+
if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
|
|
266
|
+
// Immediately re-open the database. We need to miss as little table updates as possible.
|
|
267
|
+
// Note, don't await this since it uses the same lock as we're in now.
|
|
268
|
+
this.reOpenInternalDB();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
throw ex;
|
|
272
|
+
}
|
|
179
273
|
finally {
|
|
180
274
|
if (holdId) {
|
|
181
275
|
await this.baseDB.releaseHold(holdId);
|
|
182
276
|
}
|
|
183
277
|
}
|
|
184
|
-
});
|
|
278
|
+
}, options);
|
|
185
279
|
}
|
|
186
280
|
async readTransaction(fn, options) {
|
|
187
281
|
return this.readLock(this.wrapTransaction(fn));
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { DBAdapter } from '@powersync/common';
|
|
2
|
-
import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
|
|
2
|
+
import { ResolvedWebSQLOpenOptions } from './web-sql-flags.js';
|
|
3
3
|
export type SharedConnectionWorker = {
|
|
4
4
|
identifier: string;
|
|
5
5
|
port: MessagePort;
|
|
6
6
|
};
|
|
7
|
+
export type WebDBAdapterConfiguration = ResolvedWebSQLOpenOptions & {
|
|
8
|
+
requiresPersistentTriggers: boolean;
|
|
9
|
+
};
|
|
7
10
|
export interface WebDBAdapter extends DBAdapter {
|
|
8
11
|
/**
|
|
9
12
|
* Get a MessagePort which can be used to share the internals of this connection.
|
|
@@ -13,5 +16,5 @@ export interface WebDBAdapter extends DBAdapter {
|
|
|
13
16
|
* Get the config options used to open this connection.
|
|
14
17
|
* This is useful for sharing connections.
|
|
15
18
|
*/
|
|
16
|
-
getConfiguration():
|
|
19
|
+
getConfiguration(): WebDBAdapterConfiguration;
|
|
17
20
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { BaseObserver } from '@powersync/common';
|
|
1
2
|
import * as Comlink from 'comlink';
|
|
2
|
-
import { AsyncDatabaseConnection, OnTableChangeCallback, OpenAsyncDatabaseConnection, ProxiedQueryResult } from './AsyncDatabaseConnection';
|
|
3
|
-
import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
|
|
3
|
+
import { AsyncDatabaseConnection, OnTableChangeCallback, OpenAsyncDatabaseConnection, ProxiedQueryResult } from './AsyncDatabaseConnection.js';
|
|
4
|
+
import { ResolvedWebSQLOpenOptions } from './web-sql-flags.js';
|
|
4
5
|
export type SharedConnectionWorker = {
|
|
5
6
|
identifier: string;
|
|
6
7
|
port: MessagePort;
|
|
@@ -15,11 +16,14 @@ export type WrappedWorkerConnectionOptions<Config extends ResolvedWebSQLOpenOpti
|
|
|
15
16
|
remote: Comlink.Remote<OpenAsyncDatabaseConnection<Config>>;
|
|
16
17
|
onClose?: () => void;
|
|
17
18
|
};
|
|
19
|
+
export type WorkerWrappedAsyncDatabaseConnectionListener = {
|
|
20
|
+
closing: () => void;
|
|
21
|
+
};
|
|
18
22
|
/**
|
|
19
23
|
* Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
|
|
20
24
|
* functions for worker listeners.
|
|
21
25
|
*/
|
|
22
|
-
export declare class WorkerWrappedAsyncDatabaseConnection<Config extends ResolvedWebSQLOpenOptions = ResolvedWebSQLOpenOptions> implements AsyncDatabaseConnection {
|
|
26
|
+
export declare class WorkerWrappedAsyncDatabaseConnection<Config extends ResolvedWebSQLOpenOptions = ResolvedWebSQLOpenOptions> extends BaseObserver<WorkerWrappedAsyncDatabaseConnectionListener> implements AsyncDatabaseConnection {
|
|
23
27
|
protected options: WrappedWorkerConnectionOptions<Config>;
|
|
24
28
|
protected lockAbortController: AbortController;
|
|
25
29
|
protected notifyRemoteClosed: AbortController | undefined;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import { BaseObserver, ConnectionClosedError } from '@powersync/common';
|
|
1
2
|
import * as Comlink from 'comlink';
|
|
2
3
|
/**
|
|
3
4
|
* Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
|
|
4
5
|
* functions for worker listeners.
|
|
5
6
|
*/
|
|
6
|
-
export class WorkerWrappedAsyncDatabaseConnection {
|
|
7
|
+
export class WorkerWrappedAsyncDatabaseConnection extends BaseObserver {
|
|
7
8
|
options;
|
|
8
9
|
lockAbortController = new AbortController();
|
|
9
10
|
notifyRemoteClosed;
|
|
10
11
|
constructor(options) {
|
|
12
|
+
super();
|
|
11
13
|
this.options = options;
|
|
12
14
|
if (options.remoteCanCloseUnexpectedly) {
|
|
13
15
|
this.notifyRemoteClosed = new AbortController();
|
|
@@ -40,17 +42,20 @@ export class WorkerWrappedAsyncDatabaseConnection {
|
|
|
40
42
|
isAutoCommit() {
|
|
41
43
|
return this.withRemote(() => this.baseConnection.isAutoCommit());
|
|
42
44
|
}
|
|
43
|
-
withRemote(workerPromise) {
|
|
45
|
+
withRemote(workerPromise, fireActionOnAbort = false) {
|
|
44
46
|
const controller = this.notifyRemoteClosed;
|
|
45
47
|
if (controller) {
|
|
46
48
|
return new Promise((resolve, reject) => {
|
|
47
49
|
if (controller.signal.aborted) {
|
|
48
|
-
reject(new
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
reject(new ConnectionClosedError('Called operation on closed remote'));
|
|
51
|
+
if (!fireActionOnAbort) {
|
|
52
|
+
// Don't run the operation if we're going to reject
|
|
53
|
+
// We might want to fire-and-forget the operation in some cases (like a close operation)
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
function handleAbort() {
|
|
53
|
-
reject(new
|
|
58
|
+
reject(new ConnectionClosedError('Remote peer closed with request in flight'));
|
|
54
59
|
}
|
|
55
60
|
function completePromise(action) {
|
|
56
61
|
controller.signal.removeEventListener('abort', handleAbort);
|
|
@@ -118,11 +123,13 @@ export class WorkerWrappedAsyncDatabaseConnection {
|
|
|
118
123
|
// Abort any pending lock requests.
|
|
119
124
|
this.lockAbortController.abort();
|
|
120
125
|
try {
|
|
121
|
-
|
|
126
|
+
// fire and forget the close operation
|
|
127
|
+
await this.withRemote(() => this.baseConnection.close(), true);
|
|
122
128
|
}
|
|
123
129
|
finally {
|
|
124
130
|
this.options.remote[Comlink.releaseProxy]();
|
|
125
131
|
this.options.onClose?.();
|
|
132
|
+
this.iterateListeners((l) => l.closing?.());
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
135
|
execute(sql, params) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter.js';
|
|
2
|
+
import { WebDBAdapterConfiguration } from '../WebDBAdapter.js';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
* An intermediary implementation of WASQLiteDBAdapter, which takes the same
|
|
6
|
+
* constructor arguments as {@link LockedAsyncDatabaseAdapter}, but provides some
|
|
7
|
+
* basic WA-SQLite specific functionality.
|
|
8
|
+
* This base class is used to avoid requiring overloading the constructor of {@link WASQLiteDBAdapter}
|
|
9
|
+
*/
|
|
10
|
+
export declare class InternalWASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
|
|
11
|
+
getConfiguration(): WebDBAdapterConfiguration;
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter.js';
|
|
2
|
+
import { WASQLiteVFS } from './WASQLiteConnection.js';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
* An intermediary implementation of WASQLiteDBAdapter, which takes the same
|
|
6
|
+
* constructor arguments as {@link LockedAsyncDatabaseAdapter}, but provides some
|
|
7
|
+
* basic WA-SQLite specific functionality.
|
|
8
|
+
* This base class is used to avoid requiring overloading the constructor of {@link WASQLiteDBAdapter}
|
|
9
|
+
*/
|
|
10
|
+
export class InternalWASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
|
|
11
|
+
getConfiguration() {
|
|
12
|
+
// This is valid since we only handle WASQLite connections
|
|
13
|
+
const baseConfig = super.getConfiguration();
|
|
14
|
+
return {
|
|
15
|
+
...super.getConfiguration(),
|
|
16
|
+
requiresPersistentTriggers: baseConfig.vfs == WASQLiteVFS.OPFSCoopSyncVFS || baseConfig.vfs == WASQLiteVFS.AccessHandlePoolVFS
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as SQLite from '@journeyapps/wa-sqlite';
|
|
2
2
|
import { BaseObserver, BatchedUpdateNotification } from '@powersync/common';
|
|
3
3
|
import { Mutex } from 'async-mutex';
|
|
4
|
-
import { AsyncDatabaseConnection, OnTableChangeCallback, ProxiedQueryResult } from '../AsyncDatabaseConnection';
|
|
5
|
-
import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory';
|
|
4
|
+
import { AsyncDatabaseConnection, OnTableChangeCallback, ProxiedQueryResult } from '../AsyncDatabaseConnection.js';
|
|
5
|
+
import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory.js';
|
|
6
6
|
/**
|
|
7
7
|
* List of currently tested virtual filesystems
|
|
8
8
|
*/
|
|
@@ -82,9 +82,10 @@ export const DEFAULT_MODULE_FACTORIES = {
|
|
|
82
82
|
}
|
|
83
83
|
// @ts-expect-error The types for this static method are missing upstream
|
|
84
84
|
const { OPFSCoopSyncVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js');
|
|
85
|
+
const vfs = await OPFSCoopSyncVFS.create(options.dbFileName, module);
|
|
85
86
|
return {
|
|
86
87
|
module,
|
|
87
|
-
vfs
|
|
88
|
+
vfs
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
91
|
};
|
|
@@ -310,7 +311,15 @@ export class WASqliteConnection extends BaseObserver {
|
|
|
310
311
|
}
|
|
311
312
|
async close() {
|
|
312
313
|
this.broadcastChannel?.close();
|
|
313
|
-
await this.
|
|
314
|
+
await this.acquireExecuteLock(async () => {
|
|
315
|
+
/**
|
|
316
|
+
* Running the close operation inside the same execute mutex prevents errors like:
|
|
317
|
+
* ```
|
|
318
|
+
* unable to close due to unfinalized statements or unfinished backups
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
await this.sqliteAPI.close(this.dbP);
|
|
322
|
+
});
|
|
314
323
|
}
|
|
315
324
|
async registerOnTableChange(callback) {
|
|
316
325
|
return this.registerListener({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type PowerSyncOpenFactoryOptions } from '@powersync/common';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { WASQLiteVFS } from './WASQLiteConnection';
|
|
2
|
+
import { ResolvedWebSQLOpenOptions, TemporaryStorageOption, WebSQLFlags } from '../web-sql-flags.js';
|
|
3
|
+
import { InternalWASQLiteDBAdapter } from './InternalWASQLiteDBAdapter.js';
|
|
4
|
+
import { WASQLiteVFS } from './WASQLiteConnection.js';
|
|
5
5
|
/**
|
|
6
6
|
* These flags are the same as {@link WebSQLFlags}.
|
|
7
7
|
* This export is maintained only for API consistency
|
|
@@ -27,6 +27,6 @@ export interface WASQLiteDBAdapterOptions extends Omit<PowerSyncOpenFactoryOptio
|
|
|
27
27
|
/**
|
|
28
28
|
* Adapter for WA-SQLite SQLite connections.
|
|
29
29
|
*/
|
|
30
|
-
export declare class WASQLiteDBAdapter extends
|
|
30
|
+
export declare class WASQLiteDBAdapter extends InternalWASQLiteDBAdapter {
|
|
31
31
|
constructor(options: WASQLiteDBAdapterOptions);
|
|
32
32
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
|
-
import { resolveWebPowerSyncFlags } from '../../PowerSyncDatabase';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { WASQLiteOpenFactory } from './WASQLiteOpenFactory';
|
|
2
|
+
import { resolveWebPowerSyncFlags } from '../../PowerSyncDatabase.js';
|
|
3
|
+
import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption } from '../web-sql-flags.js';
|
|
4
|
+
import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection.js';
|
|
5
|
+
import { InternalWASQLiteDBAdapter } from './InternalWASQLiteDBAdapter.js';
|
|
6
|
+
import { WASQLiteOpenFactory } from './WASQLiteOpenFactory.js';
|
|
7
7
|
/**
|
|
8
8
|
* Adapter for WA-SQLite SQLite connections.
|
|
9
9
|
*/
|
|
10
|
-
export class WASQLiteDBAdapter extends
|
|
10
|
+
export class WASQLiteDBAdapter extends InternalWASQLiteDBAdapter {
|
|
11
11
|
constructor(options) {
|
|
12
12
|
super({
|
|
13
13
|
name: options.dbFilename,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type ILogLevel
|
|
2
|
-
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
|
|
3
|
-
import { AsyncDatabaseConnection } from '../AsyncDatabaseConnection';
|
|
4
|
-
import { ResolvedWebSQLOpenOptions, WebSQLOpenFactoryOptions } from '../web-sql-flags';
|
|
5
|
-
import { WASQLiteVFS } from './WASQLiteConnection';
|
|
1
|
+
import { DBAdapter, type ILogLevel } from '@powersync/common';
|
|
2
|
+
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory.js';
|
|
3
|
+
import { AsyncDatabaseConnection } from '../AsyncDatabaseConnection.js';
|
|
4
|
+
import { ResolvedWebSQLOpenOptions, WebSQLOpenFactoryOptions } from '../web-sql-flags.js';
|
|
5
|
+
import { WASQLiteVFS } from './WASQLiteConnection.js';
|
|
6
6
|
export interface WASQLiteOpenFactoryOptions extends WebSQLOpenFactoryOptions {
|
|
7
7
|
vfs?: WASQLiteVFS;
|
|
8
8
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
|
-
import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database';
|
|
3
|
-
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
|
|
4
|
-
import {
|
|
5
|
-
import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption } from '../web-sql-flags';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database.js';
|
|
3
|
+
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory.js';
|
|
4
|
+
import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection.js';
|
|
5
|
+
import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption } from '../web-sql-flags.js';
|
|
6
|
+
import { InternalWASQLiteDBAdapter } from './InternalWASQLiteDBAdapter.js';
|
|
7
|
+
import { WASQLiteVFS, WASqliteConnection } from './WASQLiteConnection.js';
|
|
8
8
|
/**
|
|
9
9
|
* Opens a SQLite connection using WA-SQLite.
|
|
10
10
|
*/
|
|
@@ -18,7 +18,7 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
|
18
18
|
return this.options;
|
|
19
19
|
}
|
|
20
20
|
openAdapter() {
|
|
21
|
-
return new
|
|
21
|
+
return new InternalWASQLiteDBAdapter({
|
|
22
22
|
name: this.options.dbFilename,
|
|
23
23
|
openConnection: () => this.openConnection(),
|
|
24
24
|
debugMode: this.options.debugMode,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractPowerSyncDatabase, DBAdapter, PowerSyncDatabaseOptions } from '@powersync/common';
|
|
2
|
-
import { AbstractWebPowerSyncDatabaseOpenFactory } from '../AbstractWebPowerSyncDatabaseOpenFactory';
|
|
2
|
+
import { AbstractWebPowerSyncDatabaseOpenFactory } from '../AbstractWebPowerSyncDatabaseOpenFactory.js';
|
|
3
3
|
/**
|
|
4
4
|
* @deprecated {@link PowerSyncDatabase} can now be constructed directly
|
|
5
5
|
* @example
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PowerSyncDatabase } from '../../../db/PowerSyncDatabase';
|
|
2
|
-
import { AbstractWebPowerSyncDatabaseOpenFactory } from '../AbstractWebPowerSyncDatabaseOpenFactory';
|
|
3
|
-
import { WASQLiteOpenFactory } from './WASQLiteOpenFactory';
|
|
1
|
+
import { PowerSyncDatabase } from '../../../db/PowerSyncDatabase.js';
|
|
2
|
+
import { AbstractWebPowerSyncDatabaseOpenFactory } from '../AbstractWebPowerSyncDatabaseOpenFactory.js';
|
|
3
|
+
import { WASQLiteOpenFactory } from './WASQLiteOpenFactory.js';
|
|
4
4
|
/**
|
|
5
5
|
* @deprecated {@link PowerSyncDatabase} can now be constructed directly
|
|
6
6
|
* @example
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { PowerSyncConnectionOptions, PowerSyncCredentials, SubscribedStream, SyncStatusOptions } from '@powersync/common';
|
|
2
2
|
import * as Comlink from 'comlink';
|
|
3
|
-
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider.js';
|
|
4
|
+
import { WorkerClient } from '../../worker/sync/WorkerClient.js';
|
|
5
|
+
import { WebDBAdapter } from '../adapters/WebDBAdapter.js';
|
|
6
|
+
import { WebStreamingSyncImplementation, WebStreamingSyncImplementationOptions } from './WebStreamingSyncImplementation.js';
|
|
7
7
|
/**
|
|
8
8
|
* The shared worker will trigger methods on this side of the message port
|
|
9
9
|
* via this client provider.
|
|
@@ -17,7 +17,7 @@ declare class SharedSyncClientProvider extends AbstractSharedSyncClientProvider
|
|
|
17
17
|
invalidateCredentials(): void;
|
|
18
18
|
fetchCredentials(): Promise<PowerSyncCredentials | null>;
|
|
19
19
|
uploadCrud(): Promise<void>;
|
|
20
|
-
get logger(): import("
|
|
20
|
+
get logger(): import("@powersync/common").ILogger | undefined;
|
|
21
21
|
trace(...x: any[]): void;
|
|
22
22
|
debug(...x: any[]): void;
|
|
23
23
|
info(...x: any[]): void;
|
|
@@ -41,6 +41,7 @@ export declare class SharedWebStreamingSyncImplementation extends WebStreamingSy
|
|
|
41
41
|
protected dbAdapter: WebDBAdapter;
|
|
42
42
|
private abortOnClose;
|
|
43
43
|
constructor(options: SharedWebStreamingSyncImplementationOptions);
|
|
44
|
+
protected _init(): Promise<void>;
|
|
44
45
|
/**
|
|
45
46
|
* Starts the sync process, this effectively acts as a call to
|
|
46
47
|
* `connect` if not yet connected.
|
|
@@ -52,9 +53,5 @@ export declare class SharedWebStreamingSyncImplementation extends WebStreamingSy
|
|
|
52
53
|
dispose(): Promise<void>;
|
|
53
54
|
waitForReady(): Promise<void>;
|
|
54
55
|
updateSubscriptions(subscriptions: SubscribedStream[]): void;
|
|
55
|
-
/**
|
|
56
|
-
* Used in tests to force a connection states
|
|
57
|
-
*/
|
|
58
|
-
private _testUpdateStatus;
|
|
59
56
|
}
|
|
60
57
|
export {};
|