@powersync/web 0.0.0-dev-20241119081147 → 0.0.0-dev-20241203152232
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/24cd027f23123a1360de.wasm +0 -0
- package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-_powersync_co-780aa20.index.umd.js +335 -0
- package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-_powersync_co-780aa20.index.umd.js.map +1 -0
- package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-_powersync_co-780aa21.index.umd.js +335 -0
- package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js-_powersync_co-780aa21.index.umd.js.map +1 -0
- package/dist/f042552714d86563f127.wasm +0 -0
- package/dist/index.umd.js +3493 -623
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +272 -2198
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +900 -395
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +2 -132
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +45 -0
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -0
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js +1470 -0
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js.map +1 -0
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +1707 -1372
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js +1602 -0
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +1 -0
- package/lib/package.json +5 -5
- package/lib/src/db/PowerSyncDatabase.d.ts +1 -1
- package/lib/src/db/PowerSyncDatabase.js +5 -2
- package/lib/src/db/adapters/AbstractWebSQLOpenFactory.d.ts +2 -0
- package/lib/src/db/adapters/AbstractWebSQLOpenFactory.js +3 -0
- package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +26 -0
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +82 -0
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +239 -0
- package/lib/src/db/adapters/WebDBAdapter.d.ts +17 -0
- package/lib/src/db/adapters/WebDBAdapter.js +1 -0
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +38 -0
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +45 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.d.ts +117 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +289 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +7 -43
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +34 -209
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +12 -0
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +57 -4
- package/lib/src/db/adapters/web-sql-flags.d.ts +16 -0
- package/lib/src/db/adapters/web-sql-flags.js +5 -0
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +9 -2
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +16 -10
- package/lib/src/db/sync/WebStreamingSyncImplementation.d.ts +0 -5
- package/lib/src/index.d.ts +8 -7
- package/lib/src/index.js +8 -7
- package/lib/src/worker/db/WASQLiteDB.worker.js +38 -20
- package/lib/src/worker/db/open-worker-database.d.ts +5 -4
- package/lib/src/worker/db/open-worker-database.js +5 -3
- package/lib/src/worker/sync/AbstractSharedSyncClientProvider.d.ts +1 -0
- package/lib/src/worker/sync/SharedSyncImplementation.d.ts +20 -3
- package/lib/src/worker/sync/SharedSyncImplementation.js +40 -11
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/dist/5fe5ed837a91c836c24f.wasm +0 -0
- package/lib/src/shared/open-db.d.ts +0 -5
- package/lib/src/shared/open-db.js +0 -192
- package/lib/src/shared/types.d.ts +0 -22
- /package/lib/src/{shared/types.js → db/adapters/AsyncDatabaseConnection.js} +0 -0
|
@@ -1,219 +1,44 @@
|
|
|
1
|
-
import { BaseObserver } from '@powersync/common';
|
|
2
1
|
import * as Comlink from 'comlink';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { resolveWebPowerSyncFlags } from '../../PowerSyncDatabase';
|
|
3
|
+
import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter';
|
|
4
|
+
import { TemporaryStorageOption } from '../web-sql-flags';
|
|
5
|
+
import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection';
|
|
6
|
+
import { WASQLiteOpenFactory } from './WASQLiteOpenFactory';
|
|
8
7
|
/**
|
|
9
8
|
* Adapter for WA-SQLite SQLite connections.
|
|
10
9
|
*/
|
|
11
|
-
export class WASQLiteDBAdapter extends
|
|
12
|
-
options;
|
|
13
|
-
initialized;
|
|
14
|
-
logger;
|
|
15
|
-
dbGetHelpers;
|
|
16
|
-
methods;
|
|
17
|
-
debugMode;
|
|
10
|
+
export class WASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
|
|
18
11
|
constructor(options) {
|
|
19
|
-
super(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
12
|
+
super({
|
|
13
|
+
name: options.dbFilename,
|
|
14
|
+
openConnection: async () => {
|
|
15
|
+
const { workerPort, temporaryStorage } = options;
|
|
16
|
+
if (workerPort) {
|
|
17
|
+
const remote = Comlink.wrap(workerPort);
|
|
18
|
+
return new WorkerWrappedAsyncDatabaseConnection({
|
|
19
|
+
remote,
|
|
20
|
+
identifier: options.dbFilename,
|
|
21
|
+
baseConnection: await remote({
|
|
22
|
+
...options,
|
|
23
|
+
temporaryStorage: temporaryStorage ?? TemporaryStorageOption.MEMORY,
|
|
24
|
+
flags: resolveWebPowerSyncFlags(options.flags)
|
|
25
|
+
})
|
|
26
|
+
});
|
|
33
27
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
get name() {
|
|
46
|
-
return this.options.dbFilename;
|
|
47
|
-
}
|
|
48
|
-
get flags() {
|
|
49
|
-
return resolveWebSQLFlags(this.options.flags ?? {});
|
|
50
|
-
}
|
|
51
|
-
getWorker() { }
|
|
52
|
-
async init() {
|
|
53
|
-
const { enableMultiTabs, useWebWorker } = this.flags;
|
|
54
|
-
if (!enableMultiTabs) {
|
|
55
|
-
this.logger.warn('Multiple tabs are not enabled in this browser');
|
|
56
|
-
}
|
|
57
|
-
if (useWebWorker) {
|
|
58
|
-
const optionsDbWorker = this.options.worker;
|
|
59
|
-
const dbOpener = this.options.workerPort
|
|
60
|
-
? Comlink.wrap(this.options.workerPort)
|
|
61
|
-
: typeof optionsDbWorker === 'function'
|
|
62
|
-
? Comlink.wrap(resolveWorkerDatabasePortFactory(() => optionsDbWorker({
|
|
63
|
-
...this.options,
|
|
64
|
-
flags: this.flags
|
|
65
|
-
})))
|
|
66
|
-
: getWorkerDatabaseOpener(this.options.dbFilename, enableMultiTabs, optionsDbWorker);
|
|
67
|
-
this.methods = await dbOpener(this.options.dbFilename);
|
|
68
|
-
this.methods.registerOnTableChange(Comlink.proxy((event) => {
|
|
69
|
-
this.iterateListeners((cb) => cb.tablesUpdated?.(event));
|
|
70
|
-
}));
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
this.methods = await _openDB(this.options.dbFilename, { useWebWorker: false });
|
|
74
|
-
this.methods.registerOnTableChange((event) => {
|
|
75
|
-
this.iterateListeners((cb) => cb.tablesUpdated?.(event));
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
async execute(query, params) {
|
|
79
|
-
return this.writeLock((ctx) => ctx.execute(query, params));
|
|
80
|
-
}
|
|
81
|
-
async executeBatch(query, params) {
|
|
82
|
-
return this.writeLock((ctx) => this._executeBatch(query, params));
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Wraps the worker execute function, awaiting for it to be available
|
|
86
|
-
*/
|
|
87
|
-
_execute = async (sql, bindings) => {
|
|
88
|
-
await this.initialized;
|
|
89
|
-
const result = await this.methods.execute(sql, bindings);
|
|
90
|
-
return {
|
|
91
|
-
...result,
|
|
92
|
-
rows: {
|
|
93
|
-
...result.rows,
|
|
94
|
-
item: (idx) => result.rows._array[idx]
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
/**
|
|
99
|
-
* Wraps the worker executeBatch function, awaiting for it to be available
|
|
100
|
-
*/
|
|
101
|
-
_executeBatch = async (query, params) => {
|
|
102
|
-
await this.initialized;
|
|
103
|
-
const result = await this.methods.executeBatch(query, params);
|
|
104
|
-
return {
|
|
105
|
-
...result,
|
|
106
|
-
rows: undefined
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
/**
|
|
110
|
-
* Attempts to close the connection.
|
|
111
|
-
* Shared workers might not actually close the connection if other
|
|
112
|
-
* tabs are still using it.
|
|
113
|
-
*/
|
|
114
|
-
close() {
|
|
115
|
-
this.methods?.close?.();
|
|
116
|
-
}
|
|
117
|
-
async getAll(sql, parameters) {
|
|
118
|
-
await this.initialized;
|
|
119
|
-
return this.dbGetHelpers.getAll(sql, parameters);
|
|
120
|
-
}
|
|
121
|
-
async getOptional(sql, parameters) {
|
|
122
|
-
await this.initialized;
|
|
123
|
-
return this.dbGetHelpers.getOptional(sql, parameters);
|
|
124
|
-
}
|
|
125
|
-
async get(sql, parameters) {
|
|
126
|
-
await this.initialized;
|
|
127
|
-
return this.dbGetHelpers.get(sql, parameters);
|
|
128
|
-
}
|
|
129
|
-
async readLock(fn, options) {
|
|
130
|
-
await this.initialized;
|
|
131
|
-
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute })));
|
|
132
|
-
}
|
|
133
|
-
async writeLock(fn, options) {
|
|
134
|
-
await this.initialized;
|
|
135
|
-
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute })));
|
|
136
|
-
}
|
|
137
|
-
acquireLock(callback) {
|
|
138
|
-
return getNavigatorLocks().request(`db-lock-${this.options.dbFilename}`, callback);
|
|
139
|
-
}
|
|
140
|
-
async readTransaction(fn, options) {
|
|
141
|
-
return this.readLock(this.wrapTransaction(fn));
|
|
142
|
-
}
|
|
143
|
-
writeTransaction(fn, options) {
|
|
144
|
-
return this.writeLock(this.wrapTransaction(fn));
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Wraps a lock context into a transaction context
|
|
148
|
-
*/
|
|
149
|
-
wrapTransaction(cb) {
|
|
150
|
-
return async (tx) => {
|
|
151
|
-
await this._execute('BEGIN TRANSACTION');
|
|
152
|
-
let finalized = false;
|
|
153
|
-
const commit = async () => {
|
|
154
|
-
if (finalized) {
|
|
155
|
-
return { rowsAffected: 0 };
|
|
156
|
-
}
|
|
157
|
-
finalized = true;
|
|
158
|
-
return this._execute('COMMIT');
|
|
159
|
-
};
|
|
160
|
-
const rollback = () => {
|
|
161
|
-
finalized = true;
|
|
162
|
-
return this._execute('ROLLBACK');
|
|
163
|
-
};
|
|
164
|
-
try {
|
|
165
|
-
const result = await cb({
|
|
166
|
-
...tx,
|
|
167
|
-
commit,
|
|
168
|
-
rollback
|
|
28
|
+
const openFactory = new WASQLiteOpenFactory({
|
|
29
|
+
dbFilename: options.dbFilename,
|
|
30
|
+
dbLocation: options.dbLocation,
|
|
31
|
+
debugMode: options.debugMode,
|
|
32
|
+
flags: options.flags,
|
|
33
|
+
temporaryStorage,
|
|
34
|
+
logger: options.logger,
|
|
35
|
+
vfs: options.vfs,
|
|
36
|
+
worker: options.worker
|
|
169
37
|
});
|
|
170
|
-
|
|
171
|
-
await commit();
|
|
172
|
-
}
|
|
173
|
-
return result;
|
|
174
|
-
}
|
|
175
|
-
catch (ex) {
|
|
176
|
-
this.logger.debug('Caught ex in transaction', ex);
|
|
177
|
-
try {
|
|
178
|
-
await rollback();
|
|
179
|
-
}
|
|
180
|
-
catch (ex2) {
|
|
181
|
-
// In rare cases, a rollback may fail.
|
|
182
|
-
// Safe to ignore.
|
|
183
|
-
}
|
|
184
|
-
throw ex;
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
generateDBHelpers(tx) {
|
|
189
|
-
return {
|
|
190
|
-
...tx,
|
|
191
|
-
/**
|
|
192
|
-
* Execute a read-only query and return results
|
|
193
|
-
*/
|
|
194
|
-
async getAll(sql, parameters) {
|
|
195
|
-
const res = await tx.execute(sql, parameters);
|
|
196
|
-
return res.rows?._array ?? [];
|
|
38
|
+
return openFactory.openConnection();
|
|
197
39
|
},
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
async getOptional(sql, parameters) {
|
|
202
|
-
const res = await tx.execute(sql, parameters);
|
|
203
|
-
return res.rows?.item(0) ?? null;
|
|
204
|
-
},
|
|
205
|
-
/**
|
|
206
|
-
* Execute a read-only query and return the first result, error if the ResultSet is empty.
|
|
207
|
-
*/
|
|
208
|
-
async get(sql, parameters) {
|
|
209
|
-
const res = await tx.execute(sql, parameters);
|
|
210
|
-
const first = res.rows?.item(0);
|
|
211
|
-
if (!first) {
|
|
212
|
-
throw new Error('Result set is empty');
|
|
213
|
-
}
|
|
214
|
-
return first;
|
|
215
|
-
}
|
|
216
|
-
};
|
|
40
|
+
debugMode: options.debugMode,
|
|
41
|
+
logger: options.logger
|
|
42
|
+
});
|
|
217
43
|
}
|
|
218
|
-
async refreshSchema() { }
|
|
219
44
|
}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { DBAdapter } from '@powersync/common';
|
|
2
2
|
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
|
|
3
|
+
import { AsyncDatabaseConnection } from '../AsyncDatabaseConnection';
|
|
4
|
+
import { ResolvedWebSQLOpenOptions, WebSQLOpenFactoryOptions } from '../web-sql-flags';
|
|
5
|
+
import { WASQLiteVFS } from './WASQLiteConnection';
|
|
6
|
+
export interface WASQLiteOpenFactoryOptions extends WebSQLOpenFactoryOptions {
|
|
7
|
+
vfs?: WASQLiteVFS;
|
|
8
|
+
}
|
|
9
|
+
export interface ResolvedWASQLiteOpenFactoryOptions extends ResolvedWebSQLOpenOptions {
|
|
10
|
+
vfs: WASQLiteVFS;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
13
|
* Opens a SQLite connection using WA-SQLite.
|
|
5
14
|
*/
|
|
6
15
|
export declare class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
16
|
+
constructor(options: WASQLiteOpenFactoryOptions);
|
|
17
|
+
get waOptions(): WASQLiteOpenFactoryOptions;
|
|
7
18
|
protected openAdapter(): DBAdapter;
|
|
19
|
+
openConnection(): Promise<AsyncDatabaseConnection>;
|
|
8
20
|
}
|
|
@@ -1,13 +1,66 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database';
|
|
2
3
|
import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
|
|
4
|
+
import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter';
|
|
5
|
+
import { TemporaryStorageOption } from '../web-sql-flags';
|
|
6
|
+
import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection';
|
|
7
|
+
import { WASqliteConnection, WASQLiteVFS } from './WASQLiteConnection';
|
|
3
8
|
/**
|
|
4
9
|
* Opens a SQLite connection using WA-SQLite.
|
|
5
10
|
*/
|
|
6
11
|
export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super(options);
|
|
14
|
+
}
|
|
15
|
+
get waOptions() {
|
|
16
|
+
// Cast to extended type
|
|
17
|
+
return this.options;
|
|
18
|
+
}
|
|
7
19
|
openAdapter() {
|
|
8
|
-
return new
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
return new LockedAsyncDatabaseAdapter({
|
|
21
|
+
name: this.options.dbFilename,
|
|
22
|
+
openConnection: () => this.openConnection(),
|
|
23
|
+
debugMode: this.options.debugMode,
|
|
24
|
+
logger: this.logger
|
|
11
25
|
});
|
|
12
26
|
}
|
|
27
|
+
async openConnection() {
|
|
28
|
+
const { enableMultiTabs, useWebWorker } = this.resolvedFlags;
|
|
29
|
+
const { vfs = WASQLiteVFS.IDBBatchAtomicVFS, temporaryStorage = TemporaryStorageOption.MEMORY } = this.waOptions;
|
|
30
|
+
if (!enableMultiTabs) {
|
|
31
|
+
this.logger.warn('Multiple tabs are not enabled in this browser');
|
|
32
|
+
}
|
|
33
|
+
if (useWebWorker) {
|
|
34
|
+
const optionsDbWorker = this.options.worker;
|
|
35
|
+
const workerPort = typeof optionsDbWorker == 'function'
|
|
36
|
+
? resolveWorkerDatabasePortFactory(() => optionsDbWorker({
|
|
37
|
+
...this.options,
|
|
38
|
+
temporaryStorage,
|
|
39
|
+
flags: this.resolvedFlags
|
|
40
|
+
}))
|
|
41
|
+
: openWorkerDatabasePort(this.options.dbFilename, enableMultiTabs, optionsDbWorker, this.waOptions.vfs);
|
|
42
|
+
const workerDBOpener = Comlink.wrap(workerPort);
|
|
43
|
+
return new WorkerWrappedAsyncDatabaseConnection({
|
|
44
|
+
remote: workerDBOpener,
|
|
45
|
+
baseConnection: await workerDBOpener({
|
|
46
|
+
dbFilename: this.options.dbFilename,
|
|
47
|
+
vfs,
|
|
48
|
+
temporaryStorage,
|
|
49
|
+
flags: this.resolvedFlags
|
|
50
|
+
}),
|
|
51
|
+
identifier: this.options.dbFilename
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Don't use a web worker
|
|
56
|
+
return new WASqliteConnection({
|
|
57
|
+
dbFilename: this.options.dbFilename,
|
|
58
|
+
dbLocation: this.options.dbLocation,
|
|
59
|
+
debugMode: this.options.debugMode,
|
|
60
|
+
vfs,
|
|
61
|
+
temporaryStorage,
|
|
62
|
+
flags: this.resolvedFlags
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
13
66
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SQLOpenOptions } from '@powersync/common';
|
|
2
|
+
import { ILogger } from 'js-logger';
|
|
2
3
|
/**
|
|
3
4
|
* Common settings used when creating SQL connections on web.
|
|
4
5
|
*/
|
|
@@ -33,6 +34,15 @@ export interface WebSQLFlags {
|
|
|
33
34
|
export type ResolvedWebSQLFlags = Required<WebSQLFlags>;
|
|
34
35
|
export interface ResolvedWebSQLOpenOptions extends SQLOpenOptions {
|
|
35
36
|
flags: ResolvedWebSQLFlags;
|
|
37
|
+
/**
|
|
38
|
+
* Where to store SQLite temporary files. Defaults to 'MEMORY'.
|
|
39
|
+
* Setting this to `FILESYSTEM` can cause issues with larger queries or datasets.
|
|
40
|
+
*/
|
|
41
|
+
temporaryStorage: TemporaryStorageOption;
|
|
42
|
+
}
|
|
43
|
+
export declare enum TemporaryStorageOption {
|
|
44
|
+
MEMORY = "memory",
|
|
45
|
+
FILESYSTEM = "file"
|
|
36
46
|
}
|
|
37
47
|
/**
|
|
38
48
|
* Options for opening a Web SQL connection
|
|
@@ -46,6 +56,12 @@ export interface WebSQLOpenFactoryOptions extends SQLOpenOptions {
|
|
|
46
56
|
* or a factory method that returns a worker.
|
|
47
57
|
*/
|
|
48
58
|
worker?: string | URL | ((options: ResolvedWebSQLOpenOptions) => Worker | SharedWorker);
|
|
59
|
+
logger?: ILogger;
|
|
60
|
+
/**
|
|
61
|
+
* Where to store SQLite temporary files. Defaults to 'MEMORY'.
|
|
62
|
+
* Setting this to `FILESYSTEM` can cause issues with larger queries or datasets.
|
|
63
|
+
*/
|
|
64
|
+
temporaryStorage?: TemporaryStorageOption;
|
|
49
65
|
}
|
|
50
66
|
export declare function isServerSide(): boolean;
|
|
51
67
|
export declare const DEFAULT_WEB_SQL_FLAGS: ResolvedWebSQLFlags;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export var TemporaryStorageOption;
|
|
2
|
+
(function (TemporaryStorageOption) {
|
|
3
|
+
TemporaryStorageOption["MEMORY"] = "memory";
|
|
4
|
+
TemporaryStorageOption["FILESYSTEM"] = "file";
|
|
5
|
+
})(TemporaryStorageOption || (TemporaryStorageOption = {}));
|
|
1
6
|
export function isServerSide() {
|
|
2
7
|
return typeof window == 'undefined';
|
|
3
8
|
}
|
|
@@ -2,6 +2,7 @@ import { PowerSyncConnectionOptions, PowerSyncCredentials, SyncStatusOptions } f
|
|
|
2
2
|
import * as Comlink from 'comlink';
|
|
3
3
|
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
|
|
4
4
|
import { SharedSyncImplementation } from '../../worker/sync/SharedSyncImplementation';
|
|
5
|
+
import { WebDBAdapter } from '../adapters/WebDBAdapter';
|
|
5
6
|
import { WebStreamingSyncImplementation, WebStreamingSyncImplementationOptions } from './WebStreamingSyncImplementation';
|
|
6
7
|
/**
|
|
7
8
|
* The shared worker will trigger methods on this side of the message port
|
|
@@ -10,7 +11,9 @@ import { WebStreamingSyncImplementation, WebStreamingSyncImplementationOptions }
|
|
|
10
11
|
declare class SharedSyncClientProvider extends AbstractSharedSyncClientProvider {
|
|
11
12
|
protected options: WebStreamingSyncImplementationOptions;
|
|
12
13
|
statusChanged: (status: SyncStatusOptions) => void;
|
|
13
|
-
|
|
14
|
+
protected webDB: WebDBAdapter;
|
|
15
|
+
constructor(options: WebStreamingSyncImplementationOptions, statusChanged: (status: SyncStatusOptions) => void, webDB: WebDBAdapter);
|
|
16
|
+
getDBWorkerPort(): Promise<MessagePort>;
|
|
14
17
|
fetchCredentials(): Promise<PowerSyncCredentials | null>;
|
|
15
18
|
uploadCrud(): Promise<void>;
|
|
16
19
|
get logger(): import("js-logger").ILogger | undefined;
|
|
@@ -23,12 +26,16 @@ declare class SharedSyncClientProvider extends AbstractSharedSyncClientProvider
|
|
|
23
26
|
time(label: string): void;
|
|
24
27
|
timeEnd(label: string): void;
|
|
25
28
|
}
|
|
29
|
+
export interface SharedWebStreamingSyncImplementationOptions extends WebStreamingSyncImplementationOptions {
|
|
30
|
+
db: WebDBAdapter;
|
|
31
|
+
}
|
|
26
32
|
export declare class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplementation {
|
|
27
33
|
protected syncManager: Comlink.Remote<SharedSyncImplementation>;
|
|
28
34
|
protected clientProvider: SharedSyncClientProvider;
|
|
29
35
|
protected messagePort: MessagePort;
|
|
30
36
|
protected isInitialized: Promise<void>;
|
|
31
|
-
|
|
37
|
+
protected dbAdapter: WebDBAdapter;
|
|
38
|
+
constructor(options: SharedWebStreamingSyncImplementationOptions);
|
|
32
39
|
/**
|
|
33
40
|
* Starts the sync process, this effectively acts as a call to
|
|
34
41
|
* `connect` if not yet connected.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
|
-
import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../worker/db/open-worker-database';
|
|
3
2
|
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
|
|
4
3
|
import { SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation';
|
|
4
|
+
import { resolveWebSQLFlags, TemporaryStorageOption } from '../adapters/web-sql-flags';
|
|
5
5
|
import { WebStreamingSyncImplementation } from './WebStreamingSyncImplementation';
|
|
6
|
-
import { resolveWebSQLFlags } from '../adapters/web-sql-flags';
|
|
7
6
|
/**
|
|
8
7
|
* The shared worker will trigger methods on this side of the message port
|
|
9
8
|
* via this client provider.
|
|
@@ -11,10 +10,16 @@ import { resolveWebSQLFlags } from '../adapters/web-sql-flags';
|
|
|
11
10
|
class SharedSyncClientProvider extends AbstractSharedSyncClientProvider {
|
|
12
11
|
options;
|
|
13
12
|
statusChanged;
|
|
14
|
-
|
|
13
|
+
webDB;
|
|
14
|
+
constructor(options, statusChanged, webDB) {
|
|
15
15
|
super();
|
|
16
16
|
this.options = options;
|
|
17
17
|
this.statusChanged = statusChanged;
|
|
18
|
+
this.webDB = webDB;
|
|
19
|
+
}
|
|
20
|
+
async getDBWorkerPort() {
|
|
21
|
+
const { port } = await this.webDB.shareConnection();
|
|
22
|
+
return Comlink.transfer(port, [port]);
|
|
18
23
|
}
|
|
19
24
|
async fetchCredentials() {
|
|
20
25
|
const credentials = await this.options.remote.getCredentials();
|
|
@@ -73,8 +78,10 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
73
78
|
clientProvider;
|
|
74
79
|
messagePort;
|
|
75
80
|
isInitialized;
|
|
81
|
+
dbAdapter;
|
|
76
82
|
constructor(options) {
|
|
77
83
|
super(options);
|
|
84
|
+
this.dbAdapter = options.db;
|
|
78
85
|
/**
|
|
79
86
|
* Configure or connect to the shared sync worker.
|
|
80
87
|
* This worker will manage all syncing operations remotely.
|
|
@@ -82,6 +89,8 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
82
89
|
const resolvedWorkerOptions = {
|
|
83
90
|
...options,
|
|
84
91
|
dbFilename: this.options.identifier,
|
|
92
|
+
// TODO
|
|
93
|
+
temporaryStorage: TemporaryStorageOption.MEMORY,
|
|
85
94
|
flags: resolveWebSQLFlags(options.flags)
|
|
86
95
|
};
|
|
87
96
|
const syncWorker = options.sync?.worker;
|
|
@@ -112,13 +121,9 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
112
121
|
* sync worker.
|
|
113
122
|
*/
|
|
114
123
|
const { crudUploadThrottleMs, identifier, retryDelayMs } = this.options;
|
|
115
|
-
const dbWorker = options.database?.options?.worker;
|
|
116
|
-
const dbOpenerPort = typeof dbWorker === 'function'
|
|
117
|
-
? resolveWorkerDatabasePortFactory(() => dbWorker(resolvedWorkerOptions))
|
|
118
|
-
: openWorkerDatabasePort(this.options.identifier, true, dbWorker);
|
|
119
124
|
const flags = { ...this.webOptions.flags, workers: undefined };
|
|
120
|
-
this.isInitialized = this.syncManager.
|
|
121
|
-
|
|
125
|
+
this.isInitialized = this.syncManager.setParams({
|
|
126
|
+
dbParams: this.dbAdapter.getConfiguration(),
|
|
122
127
|
streamOptions: {
|
|
123
128
|
crudUploadThrottleMs,
|
|
124
129
|
identifier,
|
|
@@ -131,7 +136,7 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
131
136
|
*/
|
|
132
137
|
this.clientProvider = new SharedSyncClientProvider(this.webOptions, (status) => {
|
|
133
138
|
this.iterateListeners((l) => this.updateSyncStatus(status));
|
|
134
|
-
});
|
|
139
|
+
}, options.db);
|
|
135
140
|
/**
|
|
136
141
|
* The sync worker will call this client provider when it needs
|
|
137
142
|
* to fetch credentials or upload data.
|
|
@@ -180,6 +185,7 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
180
185
|
* Used in tests to force a connection states
|
|
181
186
|
*/
|
|
182
187
|
async _testUpdateStatus(status) {
|
|
188
|
+
await this.isInitialized;
|
|
183
189
|
return this.syncManager['_testUpdateAllStatuses'](status.toJSON());
|
|
184
190
|
}
|
|
185
191
|
}
|
|
@@ -2,11 +2,6 @@ import { AbstractStreamingSyncImplementation, AbstractStreamingSyncImplementatio
|
|
|
2
2
|
import { ResolvedWebSQLOpenOptions, WebSQLFlags } from '../adapters/web-sql-flags';
|
|
3
3
|
export interface WebStreamingSyncImplementationOptions extends AbstractStreamingSyncImplementationOptions {
|
|
4
4
|
flags?: WebSQLFlags;
|
|
5
|
-
database?: {
|
|
6
|
-
options: {
|
|
7
|
-
worker?: string | URL | ((options: ResolvedWebSQLOpenOptions) => Worker | SharedWorker);
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
5
|
sync?: {
|
|
11
6
|
worker?: string | URL | ((options: ResolvedWebSQLOpenOptions) => SharedWorker);
|
|
12
7
|
};
|
package/lib/src/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export * from '@powersync/common';
|
|
2
|
-
export * from './db/PowerSyncDatabase';
|
|
3
|
-
export * from './db/sync/WebRemote';
|
|
4
|
-
export * from './db/sync/WebStreamingSyncImplementation';
|
|
5
|
-
export * from './db/sync/SharedWebStreamingSyncImplementation';
|
|
6
|
-
export * from './db/adapters/wa-sqlite/WASQLiteDBAdapter';
|
|
7
|
-
export * from './db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory';
|
|
8
2
|
export * from './db/adapters/AbstractWebPowerSyncDatabaseOpenFactory';
|
|
9
|
-
export * from './db/adapters/web-sql-flags';
|
|
10
3
|
export * from './db/adapters/AbstractWebSQLOpenFactory';
|
|
4
|
+
export * from './db/adapters/wa-sqlite/WASQLiteConnection';
|
|
5
|
+
export * from './db/adapters/wa-sqlite/WASQLiteDBAdapter';
|
|
11
6
|
export * from './db/adapters/wa-sqlite/WASQLiteOpenFactory';
|
|
7
|
+
export * from './db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory';
|
|
8
|
+
export * from './db/adapters/web-sql-flags';
|
|
9
|
+
export * from './db/PowerSyncDatabase';
|
|
10
|
+
export * from './db/sync/SharedWebStreamingSyncImplementation';
|
|
11
|
+
export * from './db/sync/WebRemote';
|
|
12
|
+
export * from './db/sync/WebStreamingSyncImplementation';
|
package/lib/src/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export * from '@powersync/common';
|
|
2
|
-
export * from './db/PowerSyncDatabase';
|
|
3
|
-
export * from './db/sync/WebRemote';
|
|
4
|
-
export * from './db/sync/WebStreamingSyncImplementation';
|
|
5
|
-
export * from './db/sync/SharedWebStreamingSyncImplementation';
|
|
6
|
-
export * from './db/adapters/wa-sqlite/WASQLiteDBAdapter';
|
|
7
|
-
export * from './db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory';
|
|
8
2
|
export * from './db/adapters/AbstractWebPowerSyncDatabaseOpenFactory';
|
|
9
|
-
export * from './db/adapters/web-sql-flags';
|
|
10
3
|
export * from './db/adapters/AbstractWebSQLOpenFactory';
|
|
4
|
+
export * from './db/adapters/wa-sqlite/WASQLiteConnection';
|
|
5
|
+
export * from './db/adapters/wa-sqlite/WASQLiteDBAdapter';
|
|
11
6
|
export * from './db/adapters/wa-sqlite/WASQLiteOpenFactory';
|
|
7
|
+
export * from './db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory';
|
|
8
|
+
export * from './db/adapters/web-sql-flags';
|
|
9
|
+
export * from './db/PowerSyncDatabase';
|
|
10
|
+
export * from './db/sync/SharedWebStreamingSyncImplementation';
|
|
11
|
+
export * from './db/sync/WebRemote';
|
|
12
|
+
export * from './db/sync/WebStreamingSyncImplementation';
|
|
@@ -3,46 +3,63 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import '@journeyapps/wa-sqlite';
|
|
5
5
|
import * as Comlink from 'comlink';
|
|
6
|
-
import {
|
|
6
|
+
import { WASqliteConnection } from '../../db/adapters/wa-sqlite/WASQLiteConnection';
|
|
7
7
|
import { getNavigatorLocks } from '../../shared/navigator';
|
|
8
8
|
const DBMap = new Map();
|
|
9
9
|
const OPEN_DB_LOCK = 'open-wasqlite-db';
|
|
10
10
|
let nextClientId = 1;
|
|
11
|
-
const
|
|
11
|
+
const openWorkerConnection = async (options) => {
|
|
12
|
+
const connection = new WASqliteConnection(options);
|
|
13
|
+
return {
|
|
14
|
+
init: Comlink.proxy(() => connection.init()),
|
|
15
|
+
getConfig: Comlink.proxy(() => connection.getConfig()),
|
|
16
|
+
close: Comlink.proxy(() => connection.close()),
|
|
17
|
+
execute: Comlink.proxy(async (sql, params) => connection.execute(sql, params)),
|
|
18
|
+
executeBatch: Comlink.proxy(async (sql, params) => connection.executeBatch(sql, params)),
|
|
19
|
+
registerOnTableChange: Comlink.proxy(async (callback) => {
|
|
20
|
+
// Proxy the callback remove function
|
|
21
|
+
return Comlink.proxy(await connection.registerOnTableChange(callback));
|
|
22
|
+
})
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const openDBShared = async (options) => {
|
|
12
26
|
// Prevent multiple simultaneous opens from causing race conditions
|
|
13
27
|
return getNavigatorLocks().request(OPEN_DB_LOCK, async () => {
|
|
14
28
|
const clientId = nextClientId++;
|
|
15
|
-
|
|
29
|
+
const { dbFilename } = options;
|
|
30
|
+
if (!DBMap.has(dbFilename)) {
|
|
16
31
|
const clientIds = new Set();
|
|
17
|
-
const connection = await
|
|
18
|
-
|
|
32
|
+
const connection = await openWorkerConnection(options);
|
|
33
|
+
await connection.init();
|
|
34
|
+
DBMap.set(dbFilename, {
|
|
19
35
|
clientIds,
|
|
20
36
|
db: connection
|
|
21
37
|
});
|
|
22
38
|
}
|
|
23
|
-
const dbEntry = DBMap.get(
|
|
39
|
+
const dbEntry = DBMap.get(dbFilename);
|
|
24
40
|
dbEntry.clientIds.add(clientId);
|
|
25
41
|
const { db } = dbEntry;
|
|
26
42
|
const wrappedConnection = {
|
|
27
43
|
...db,
|
|
44
|
+
init: Comlink.proxy(() => {
|
|
45
|
+
// the init has been done automatically
|
|
46
|
+
}),
|
|
28
47
|
close: Comlink.proxy(() => {
|
|
29
48
|
const { clientIds } = dbEntry;
|
|
49
|
+
console.debug(`Close requested from client ${clientId} of ${[...clientIds]}`);
|
|
30
50
|
clientIds.delete(clientId);
|
|
31
51
|
if (clientIds.size == 0) {
|
|
32
|
-
console.debug(`Closing connection to ${
|
|
33
|
-
DBMap.delete(
|
|
52
|
+
console.debug(`Closing connection to ${dbFilename}.`);
|
|
53
|
+
DBMap.delete(dbFilename);
|
|
34
54
|
return db.close?.();
|
|
35
55
|
}
|
|
36
|
-
console.debug(`Connection to ${
|
|
56
|
+
console.debug(`Connection to ${dbFilename} not closed yet due to active clients.`);
|
|
57
|
+
return;
|
|
37
58
|
})
|
|
38
59
|
};
|
|
39
60
|
return Comlink.proxy(wrappedConnection);
|
|
40
61
|
});
|
|
41
62
|
};
|
|
42
|
-
const openDBDedicated = async (dbFileName) => {
|
|
43
|
-
const connection = await _openDB(dbFileName);
|
|
44
|
-
return Comlink.proxy(connection);
|
|
45
|
-
};
|
|
46
63
|
// Check if we're in a SharedWorker context
|
|
47
64
|
if (typeof SharedWorkerGlobalScope !== 'undefined') {
|
|
48
65
|
const _self = self;
|
|
@@ -51,13 +68,14 @@ if (typeof SharedWorkerGlobalScope !== 'undefined') {
|
|
|
51
68
|
console.debug('Exposing shared db on port', port);
|
|
52
69
|
Comlink.expose(openDBShared, port);
|
|
53
70
|
};
|
|
54
|
-
addEventListener('unload', () => {
|
|
55
|
-
Array.from(DBMap.values()).forEach(async (dbConnection) => {
|
|
56
|
-
const db = await dbConnection.db;
|
|
57
|
-
db.close?.();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
71
|
}
|
|
61
72
|
else {
|
|
62
|
-
|
|
73
|
+
// A dedicated worker can be shared externally
|
|
74
|
+
Comlink.expose(openDBShared);
|
|
63
75
|
}
|
|
76
|
+
addEventListener('unload', () => {
|
|
77
|
+
Array.from(DBMap.values()).forEach(async (dbConnection) => {
|
|
78
|
+
const { db } = dbConnection;
|
|
79
|
+
db.close?.();
|
|
80
|
+
});
|
|
81
|
+
});
|