@powersync/web 0.0.0-dev-20240712065121 → 0.0.0-dev-20240715124012
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/lib/src/db/PowerSyncDatabase.js +28 -24
- package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +7 -1
- package/lib/src/db/adapters/AbstractWebSQLOpenFactory.js +2 -0
- package/lib/src/db/adapters/SSRDBAdapter.js +28 -48
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +100 -119
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +4 -1
- package/lib/src/db/adapters/web-sql-flags.js +6 -3
- package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js +2 -0
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +66 -95
- package/lib/src/db/sync/WebRemote.js +10 -20
- package/lib/src/shared/open-db.js +149 -180
- package/lib/src/worker/db/SharedWASQLiteDB.worker.js +15 -23
- package/lib/src/worker/db/WASQLiteDB.worker.js +1 -10
- package/lib/src/worker/sync/BroadcastLogger.js +16 -19
- package/lib/src/worker/sync/SharedSyncImplementation.js +96 -115
- package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -7
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { AbstractPowerSyncDatabase, SqliteBucketStorage, DEFAULT_POWERSYNC_CLOSE_OPTIONS } from '@powersync/common';
|
|
11
2
|
import { Mutex } from 'async-mutex';
|
|
12
3
|
import { WebRemote } from './sync/WebRemote';
|
|
@@ -15,9 +6,16 @@ import { SSRStreamingSyncImplementation } from './sync/SSRWebStreamingSyncImplem
|
|
|
15
6
|
import { WebStreamingSyncImplementation } from './sync/WebStreamingSyncImplementation';
|
|
16
7
|
import { WASQLiteOpenFactory } from './adapters/wa-sqlite/WASQLiteOpenFactory';
|
|
17
8
|
import { DEFAULT_WEB_SQL_FLAGS, resolveWebSQLFlags } from './adapters/web-sql-flags';
|
|
18
|
-
export const DEFAULT_POWERSYNC_FLAGS =
|
|
9
|
+
export const DEFAULT_POWERSYNC_FLAGS = {
|
|
10
|
+
...DEFAULT_WEB_SQL_FLAGS,
|
|
11
|
+
externallyUnload: false
|
|
12
|
+
};
|
|
19
13
|
export const resolveWebPowerSyncFlags = (flags) => {
|
|
20
|
-
return
|
|
14
|
+
return {
|
|
15
|
+
...DEFAULT_POWERSYNC_FLAGS,
|
|
16
|
+
...flags,
|
|
17
|
+
...resolveWebSQLFlags(flags)
|
|
18
|
+
};
|
|
21
19
|
};
|
|
22
20
|
/**
|
|
23
21
|
* A PowerSync database which provides SQLite functionality
|
|
@@ -34,6 +32,10 @@ export const resolveWebPowerSyncFlags = (flags) => {
|
|
|
34
32
|
* ```
|
|
35
33
|
*/
|
|
36
34
|
export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
35
|
+
options;
|
|
36
|
+
static SHARED_MUTEX = new Mutex();
|
|
37
|
+
unloadListener;
|
|
38
|
+
resolvedFlags;
|
|
37
39
|
constructor(options) {
|
|
38
40
|
super(options);
|
|
39
41
|
this.options = options;
|
|
@@ -43,11 +45,9 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
43
45
|
window.addEventListener('unload', this.unloadListener);
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
|
-
_initialize() {
|
|
47
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
48
|
-
}
|
|
48
|
+
async _initialize() { }
|
|
49
49
|
openDBAdapter(options) {
|
|
50
|
-
const defaultFactory = new WASQLiteOpenFactory(
|
|
50
|
+
const defaultFactory = new WASQLiteOpenFactory({ ...options, flags: this.resolvedFlags });
|
|
51
51
|
return defaultFactory.openDB();
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
@@ -56,13 +56,12 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
56
56
|
* multiple tabs are not enabled.
|
|
57
57
|
*/
|
|
58
58
|
close(options = DEFAULT_POWERSYNC_CLOSE_OPTIONS) {
|
|
59
|
-
var _a;
|
|
60
59
|
if (this.unloadListener) {
|
|
61
60
|
window.removeEventListener('unload', this.unloadListener);
|
|
62
61
|
}
|
|
63
62
|
return super.close({
|
|
64
63
|
// Don't disconnect by default if multiple tabs are enabled
|
|
65
|
-
disconnect:
|
|
64
|
+
disconnect: options.disconnect ?? !this.resolvedFlags.enableMultiTabs
|
|
66
65
|
});
|
|
67
66
|
}
|
|
68
67
|
connect(connector, options) {
|
|
@@ -72,8 +71,7 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
72
71
|
* connection attempts.
|
|
73
72
|
*/
|
|
74
73
|
return this.runExclusive(() => {
|
|
75
|
-
|
|
76
|
-
(_a = this.options.logger) === null || _a === void 0 ? void 0 : _a.debug('Attempting to connect to PowerSync instance');
|
|
74
|
+
this.options.logger?.debug('Attempting to connect to PowerSync instance');
|
|
77
75
|
return super.connect(connector, options);
|
|
78
76
|
});
|
|
79
77
|
}
|
|
@@ -88,10 +86,17 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
88
86
|
}
|
|
89
87
|
generateSyncStreamImplementation(connector) {
|
|
90
88
|
const remote = new WebRemote(connector);
|
|
91
|
-
const syncOptions =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
const syncOptions = {
|
|
90
|
+
...this.options,
|
|
91
|
+
flags: this.resolvedFlags,
|
|
92
|
+
adapter: this.bucketStorageAdapter,
|
|
93
|
+
remote,
|
|
94
|
+
uploadCrud: async () => {
|
|
95
|
+
await this.waitForReady();
|
|
96
|
+
await connector.uploadData(this);
|
|
97
|
+
},
|
|
98
|
+
identifier: this.database.name
|
|
99
|
+
};
|
|
95
100
|
switch (true) {
|
|
96
101
|
case this.resolvedFlags.ssrMode:
|
|
97
102
|
return new SSRStreamingSyncImplementation(syncOptions);
|
|
@@ -110,4 +115,3 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
|
-
PowerSyncDatabase.SHARED_MUTEX = new Mutex();
|
|
@@ -7,12 +7,18 @@ import { PowerSyncDatabase, resolveWebPowerSyncFlags } from '../../db/PowerSyncD
|
|
|
7
7
|
* empty query results in SSR which will allow for generating server partial views.
|
|
8
8
|
*/
|
|
9
9
|
export class AbstractWebPowerSyncDatabaseOpenFactory extends AbstractPowerSyncDatabaseOpenFactory {
|
|
10
|
+
options;
|
|
10
11
|
constructor(options) {
|
|
11
12
|
super(options);
|
|
12
13
|
this.options = options;
|
|
13
14
|
}
|
|
14
15
|
generateOptions() {
|
|
15
|
-
return
|
|
16
|
+
return {
|
|
17
|
+
...this.options,
|
|
18
|
+
database: this.openDB(),
|
|
19
|
+
schema: this.schema,
|
|
20
|
+
flags: resolveWebPowerSyncFlags(this.options.flags)
|
|
21
|
+
};
|
|
16
22
|
}
|
|
17
23
|
generateInstance(options) {
|
|
18
24
|
return new PowerSyncDatabase(options);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SSRDBAdapter } from './SSRDBAdapter';
|
|
2
2
|
import { isServerSide, resolveWebSQLFlags } from './web-sql-flags';
|
|
3
3
|
export class AbstractWebSQLOpenFactory {
|
|
4
|
+
options;
|
|
5
|
+
resolvedFlags;
|
|
4
6
|
constructor(options) {
|
|
5
7
|
this.options = options;
|
|
6
8
|
this.resolvedFlags = resolveWebSQLFlags(options.flags);
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { BaseObserver } from '@powersync/common';
|
|
11
2
|
import { Mutex } from 'async-mutex';
|
|
12
3
|
const MOCK_QUERY_RESPONSE = {
|
|
@@ -18,6 +9,9 @@ const MOCK_QUERY_RESPONSE = {
|
|
|
18
9
|
* server rendered views to initially generate scaffolding components
|
|
19
10
|
*/
|
|
20
11
|
export class SSRDBAdapter extends BaseObserver {
|
|
12
|
+
name;
|
|
13
|
+
readMutex;
|
|
14
|
+
writeMutex;
|
|
21
15
|
constructor() {
|
|
22
16
|
super();
|
|
23
17
|
this.name = 'SSR DB';
|
|
@@ -25,50 +19,32 @@ export class SSRDBAdapter extends BaseObserver {
|
|
|
25
19
|
this.writeMutex = new Mutex();
|
|
26
20
|
}
|
|
27
21
|
close() { }
|
|
28
|
-
readLock(fn, options) {
|
|
29
|
-
return
|
|
30
|
-
return this.readMutex.runExclusive(() => fn(this));
|
|
31
|
-
});
|
|
22
|
+
async readLock(fn, options) {
|
|
23
|
+
return this.readMutex.runExclusive(() => fn(this));
|
|
32
24
|
}
|
|
33
|
-
readTransaction(fn, options) {
|
|
34
|
-
return
|
|
35
|
-
return this.readLock(() => fn(this.generateMockTransactionContext()));
|
|
36
|
-
});
|
|
25
|
+
async readTransaction(fn, options) {
|
|
26
|
+
return this.readLock(() => fn(this.generateMockTransactionContext()));
|
|
37
27
|
}
|
|
38
|
-
writeLock(fn, options) {
|
|
39
|
-
return
|
|
40
|
-
return this.writeMutex.runExclusive(() => fn(this));
|
|
41
|
-
});
|
|
28
|
+
async writeLock(fn, options) {
|
|
29
|
+
return this.writeMutex.runExclusive(() => fn(this));
|
|
42
30
|
}
|
|
43
|
-
writeTransaction(fn, options) {
|
|
44
|
-
return
|
|
45
|
-
return this.writeLock(() => fn(this.generateMockTransactionContext()));
|
|
46
|
-
});
|
|
31
|
+
async writeTransaction(fn, options) {
|
|
32
|
+
return this.writeLock(() => fn(this.generateMockTransactionContext()));
|
|
47
33
|
}
|
|
48
|
-
execute(query, params) {
|
|
49
|
-
return
|
|
50
|
-
return this.writeMutex.runExclusive(() => __awaiter(this, void 0, void 0, function* () { return MOCK_QUERY_RESPONSE; }));
|
|
51
|
-
});
|
|
34
|
+
async execute(query, params) {
|
|
35
|
+
return this.writeMutex.runExclusive(async () => MOCK_QUERY_RESPONSE);
|
|
52
36
|
}
|
|
53
|
-
executeBatch(query, params) {
|
|
54
|
-
return
|
|
55
|
-
return this.writeMutex.runExclusive(() => __awaiter(this, void 0, void 0, function* () { return MOCK_QUERY_RESPONSE; }));
|
|
56
|
-
});
|
|
37
|
+
async executeBatch(query, params) {
|
|
38
|
+
return this.writeMutex.runExclusive(async () => MOCK_QUERY_RESPONSE);
|
|
57
39
|
}
|
|
58
|
-
getAll(sql, parameters) {
|
|
59
|
-
return
|
|
60
|
-
return [];
|
|
61
|
-
});
|
|
40
|
+
async getAll(sql, parameters) {
|
|
41
|
+
return [];
|
|
62
42
|
}
|
|
63
|
-
getOptional(sql, parameters) {
|
|
64
|
-
return
|
|
65
|
-
return null;
|
|
66
|
-
});
|
|
43
|
+
async getOptional(sql, parameters) {
|
|
44
|
+
return null;
|
|
67
45
|
}
|
|
68
|
-
get(sql, parameters) {
|
|
69
|
-
|
|
70
|
-
throw new Error(`No values are returned in SSR mode`);
|
|
71
|
-
});
|
|
46
|
+
async get(sql, parameters) {
|
|
47
|
+
throw new Error(`No values are returned in SSR mode`);
|
|
72
48
|
}
|
|
73
49
|
/**
|
|
74
50
|
* Generates a mock context for use in read/write transactions.
|
|
@@ -76,10 +52,14 @@ export class SSRDBAdapter extends BaseObserver {
|
|
|
76
52
|
* are added here
|
|
77
53
|
*/
|
|
78
54
|
generateMockTransactionContext() {
|
|
79
|
-
return
|
|
55
|
+
return {
|
|
56
|
+
...this,
|
|
57
|
+
commit: async () => {
|
|
80
58
|
return MOCK_QUERY_RESPONSE;
|
|
81
|
-
}
|
|
59
|
+
},
|
|
60
|
+
rollback: async () => {
|
|
82
61
|
return MOCK_QUERY_RESPONSE;
|
|
83
|
-
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
84
64
|
}
|
|
85
65
|
}
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { BaseObserver } from '@powersync/common';
|
|
11
2
|
import * as Comlink from 'comlink';
|
|
12
3
|
import Logger from 'js-logger';
|
|
@@ -16,25 +7,14 @@ import { getWorkerDatabaseOpener } from '../../../worker/db/open-worker-database
|
|
|
16
7
|
* Adapter for WA-SQLite SQLite connections.
|
|
17
8
|
*/
|
|
18
9
|
export class WASQLiteDBAdapter extends BaseObserver {
|
|
10
|
+
options;
|
|
11
|
+
initialized;
|
|
12
|
+
logger;
|
|
13
|
+
dbGetHelpers;
|
|
14
|
+
methods;
|
|
19
15
|
constructor(options) {
|
|
20
16
|
super();
|
|
21
17
|
this.options = options;
|
|
22
|
-
/**
|
|
23
|
-
* Wraps the worker execute function, awaiting for it to be available
|
|
24
|
-
*/
|
|
25
|
-
this._execute = (sql, bindings) => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
yield this.initialized;
|
|
27
|
-
const result = yield this.methods.execute(sql, bindings);
|
|
28
|
-
return Object.assign(Object.assign({}, result), { rows: Object.assign(Object.assign({}, result.rows), { item: (idx) => result.rows._array[idx] }) });
|
|
29
|
-
});
|
|
30
|
-
/**
|
|
31
|
-
* Wraps the worker executeBatch function, awaiting for it to be available
|
|
32
|
-
*/
|
|
33
|
-
this._executeBatch = (query, params) => __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
yield this.initialized;
|
|
35
|
-
const result = yield this.methods.executeBatch(query, params);
|
|
36
|
-
return Object.assign(Object.assign({}, result), { rows: undefined });
|
|
37
|
-
});
|
|
38
18
|
this.logger = Logger.get('WASQLite');
|
|
39
19
|
this.dbGetHelpers = null;
|
|
40
20
|
this.methods = null;
|
|
@@ -45,88 +25,93 @@ export class WASQLiteDBAdapter extends BaseObserver {
|
|
|
45
25
|
return this.options.dbFilename;
|
|
46
26
|
}
|
|
47
27
|
get flags() {
|
|
48
|
-
|
|
49
|
-
return (_a = this.options.flags) !== null && _a !== void 0 ? _a : {};
|
|
28
|
+
return this.options.flags ?? {};
|
|
50
29
|
}
|
|
51
30
|
getWorker() { }
|
|
52
|
-
init() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.
|
|
70
|
-
this.iterateListeners((cb) => { var _a; return (_a = cb.tablesUpdated) === null || _a === void 0 ? void 0 : _a.call(cb, { opType, table: tableName, rowId }); });
|
|
71
|
-
});
|
|
31
|
+
async init() {
|
|
32
|
+
const { enableMultiTabs, useWebWorker } = this.flags;
|
|
33
|
+
if (!enableMultiTabs) {
|
|
34
|
+
this.logger.warn('Multiple tabs are not enabled in this browser');
|
|
35
|
+
}
|
|
36
|
+
if (useWebWorker) {
|
|
37
|
+
const dbOpener = this.options.workerPort
|
|
38
|
+
? Comlink.wrap(this.options.workerPort)
|
|
39
|
+
: getWorkerDatabaseOpener(this.options.dbFilename, enableMultiTabs);
|
|
40
|
+
this.methods = await dbOpener(this.options.dbFilename);
|
|
41
|
+
this.methods.registerOnTableChange(Comlink.proxy((opType, tableName, rowId) => {
|
|
42
|
+
this.iterateListeners((cb) => cb.tablesUpdated?.({ opType, table: tableName, rowId }));
|
|
43
|
+
}));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.methods = await _openDB(this.options.dbFilename, { useWebWorker: false });
|
|
47
|
+
this.methods.registerOnTableChange((opType, tableName, rowId) => {
|
|
48
|
+
this.iterateListeners((cb) => cb.tablesUpdated?.({ opType, table: tableName, rowId }));
|
|
72
49
|
});
|
|
73
50
|
}
|
|
74
|
-
execute(query, params) {
|
|
75
|
-
return
|
|
76
|
-
return this.writeLock((ctx) => ctx.execute(query, params));
|
|
77
|
-
});
|
|
51
|
+
async execute(query, params) {
|
|
52
|
+
return this.writeLock((ctx) => ctx.execute(query, params));
|
|
78
53
|
}
|
|
79
|
-
executeBatch(query, params) {
|
|
80
|
-
return
|
|
81
|
-
return this.writeLock((ctx) => this._executeBatch(query, params));
|
|
82
|
-
});
|
|
54
|
+
async executeBatch(query, params) {
|
|
55
|
+
return this.writeLock((ctx) => this._executeBatch(query, params));
|
|
83
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Wraps the worker execute function, awaiting for it to be available
|
|
59
|
+
*/
|
|
60
|
+
_execute = async (sql, bindings) => {
|
|
61
|
+
await this.initialized;
|
|
62
|
+
const result = await this.methods.execute(sql, bindings);
|
|
63
|
+
return {
|
|
64
|
+
...result,
|
|
65
|
+
rows: {
|
|
66
|
+
...result.rows,
|
|
67
|
+
item: (idx) => result.rows._array[idx]
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Wraps the worker executeBatch function, awaiting for it to be available
|
|
73
|
+
*/
|
|
74
|
+
_executeBatch = async (query, params) => {
|
|
75
|
+
await this.initialized;
|
|
76
|
+
const result = await this.methods.executeBatch(query, params);
|
|
77
|
+
return {
|
|
78
|
+
...result,
|
|
79
|
+
rows: undefined
|
|
80
|
+
};
|
|
81
|
+
};
|
|
84
82
|
/**
|
|
85
83
|
* Attempts to close the connection.
|
|
86
84
|
* Shared workers might not actually close the connection if other
|
|
87
85
|
* tabs are still using it.
|
|
88
86
|
*/
|
|
89
87
|
close() {
|
|
90
|
-
|
|
91
|
-
(_b = (_a = this.methods) === null || _a === void 0 ? void 0 : _a.close) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
88
|
+
this.methods?.close?.();
|
|
92
89
|
}
|
|
93
|
-
getAll(sql, parameters) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return this.dbGetHelpers.getAll(sql, parameters);
|
|
97
|
-
});
|
|
90
|
+
async getAll(sql, parameters) {
|
|
91
|
+
await this.initialized;
|
|
92
|
+
return this.dbGetHelpers.getAll(sql, parameters);
|
|
98
93
|
}
|
|
99
|
-
getOptional(sql, parameters) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return this.dbGetHelpers.getOptional(sql, parameters);
|
|
103
|
-
});
|
|
94
|
+
async getOptional(sql, parameters) {
|
|
95
|
+
await this.initialized;
|
|
96
|
+
return this.dbGetHelpers.getOptional(sql, parameters);
|
|
104
97
|
}
|
|
105
|
-
get(sql, parameters) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return this.dbGetHelpers.get(sql, parameters);
|
|
109
|
-
});
|
|
98
|
+
async get(sql, parameters) {
|
|
99
|
+
await this.initialized;
|
|
100
|
+
return this.dbGetHelpers.get(sql, parameters);
|
|
110
101
|
}
|
|
111
|
-
readLock(fn, options) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return this.acquireLock(() => __awaiter(this, void 0, void 0, function* () { return fn(this.generateDBHelpers({ execute: this._execute })); }));
|
|
115
|
-
});
|
|
102
|
+
async readLock(fn, options) {
|
|
103
|
+
await this.initialized;
|
|
104
|
+
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute })));
|
|
116
105
|
}
|
|
117
|
-
writeLock(fn, options) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return this.acquireLock(() => __awaiter(this, void 0, void 0, function* () { return fn(this.generateDBHelpers({ execute: this._execute })); }));
|
|
121
|
-
});
|
|
106
|
+
async writeLock(fn, options) {
|
|
107
|
+
await this.initialized;
|
|
108
|
+
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute })));
|
|
122
109
|
}
|
|
123
110
|
acquireLock(callback) {
|
|
124
111
|
return navigator.locks.request(`db-lock-${this.options.dbFilename}`, callback);
|
|
125
112
|
}
|
|
126
|
-
readTransaction(fn, options) {
|
|
127
|
-
return
|
|
128
|
-
return this.readLock(this.wrapTransaction(fn));
|
|
129
|
-
});
|
|
113
|
+
async readTransaction(fn, options) {
|
|
114
|
+
return this.readLock(this.wrapTransaction(fn));
|
|
130
115
|
}
|
|
131
116
|
writeTransaction(fn, options) {
|
|
132
117
|
return this.writeLock(this.wrapTransaction(fn));
|
|
@@ -135,70 +120,66 @@ export class WASQLiteDBAdapter extends BaseObserver {
|
|
|
135
120
|
* Wraps a lock context into a transaction context
|
|
136
121
|
*/
|
|
137
122
|
wrapTransaction(cb) {
|
|
138
|
-
return (tx) =>
|
|
139
|
-
|
|
123
|
+
return async (tx) => {
|
|
124
|
+
await this._execute('BEGIN TRANSACTION');
|
|
140
125
|
let finalized = false;
|
|
141
|
-
const commit = () =>
|
|
126
|
+
const commit = async () => {
|
|
142
127
|
if (finalized) {
|
|
143
128
|
return { rowsAffected: 0 };
|
|
144
129
|
}
|
|
145
130
|
finalized = true;
|
|
146
131
|
return this._execute('COMMIT');
|
|
147
|
-
}
|
|
132
|
+
};
|
|
148
133
|
const rollback = () => {
|
|
149
134
|
finalized = true;
|
|
150
135
|
return this._execute('ROLLBACK');
|
|
151
136
|
};
|
|
152
137
|
try {
|
|
153
|
-
const result =
|
|
154
|
-
|
|
138
|
+
const result = await cb({
|
|
139
|
+
...tx,
|
|
140
|
+
commit,
|
|
141
|
+
rollback
|
|
142
|
+
});
|
|
155
143
|
if (!finalized) {
|
|
156
|
-
|
|
144
|
+
await commit();
|
|
157
145
|
}
|
|
158
146
|
return result;
|
|
159
147
|
}
|
|
160
148
|
catch (ex) {
|
|
161
149
|
this.logger.debug('Caught ex in transaction', ex);
|
|
162
|
-
|
|
150
|
+
await rollback();
|
|
163
151
|
throw ex;
|
|
164
152
|
}
|
|
165
|
-
}
|
|
153
|
+
};
|
|
166
154
|
}
|
|
167
155
|
generateDBHelpers(tx) {
|
|
168
|
-
return
|
|
156
|
+
return {
|
|
157
|
+
...tx,
|
|
169
158
|
/**
|
|
170
159
|
* Execute a read-only query and return results
|
|
171
160
|
*/
|
|
172
|
-
getAll(sql, parameters) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const res = yield tx.execute(sql, parameters);
|
|
176
|
-
return (_b = (_a = res.rows) === null || _a === void 0 ? void 0 : _a._array) !== null && _b !== void 0 ? _b : [];
|
|
177
|
-
});
|
|
161
|
+
async getAll(sql, parameters) {
|
|
162
|
+
const res = await tx.execute(sql, parameters);
|
|
163
|
+
return res.rows?._array ?? [];
|
|
178
164
|
},
|
|
179
165
|
/**
|
|
180
166
|
* Execute a read-only query and return the first result, or null if the ResultSet is empty.
|
|
181
167
|
*/
|
|
182
|
-
getOptional(sql, parameters) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const res = yield tx.execute(sql, parameters);
|
|
186
|
-
return (_b = (_a = res.rows) === null || _a === void 0 ? void 0 : _a.item(0)) !== null && _b !== void 0 ? _b : null;
|
|
187
|
-
});
|
|
168
|
+
async getOptional(sql, parameters) {
|
|
169
|
+
const res = await tx.execute(sql, parameters);
|
|
170
|
+
return res.rows?.item(0) ?? null;
|
|
188
171
|
},
|
|
189
172
|
/**
|
|
190
173
|
* Execute a read-only query and return the first result, error if the ResultSet is empty.
|
|
191
174
|
*/
|
|
192
|
-
get(sql, parameters) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
});
|
|
202
|
-
} });
|
|
175
|
+
async get(sql, parameters) {
|
|
176
|
+
const res = await tx.execute(sql, parameters);
|
|
177
|
+
const first = res.rows?.item(0);
|
|
178
|
+
if (!first) {
|
|
179
|
+
throw new Error('Result set is empty');
|
|
180
|
+
}
|
|
181
|
+
return first;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
203
184
|
}
|
|
204
185
|
}
|
|
@@ -5,6 +5,9 @@ import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
|
|
|
5
5
|
*/
|
|
6
6
|
export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
|
|
7
7
|
openAdapter() {
|
|
8
|
-
return new WASQLiteDBAdapter(
|
|
8
|
+
return new WASQLiteDBAdapter({
|
|
9
|
+
...this.options,
|
|
10
|
+
flags: this.resolvedFlags
|
|
11
|
+
});
|
|
9
12
|
}
|
|
10
13
|
}
|
|
@@ -16,11 +16,14 @@ export const DEFAULT_WEB_SQL_FLAGS = {
|
|
|
16
16
|
useWebWorker: true
|
|
17
17
|
};
|
|
18
18
|
export function resolveWebSQLFlags(flags) {
|
|
19
|
-
const resolvedFlags =
|
|
20
|
-
|
|
19
|
+
const resolvedFlags = {
|
|
20
|
+
...DEFAULT_WEB_SQL_FLAGS,
|
|
21
|
+
...(flags ?? {})
|
|
22
|
+
};
|
|
23
|
+
if (typeof flags?.enableMultiTabs != 'undefined') {
|
|
21
24
|
resolvedFlags.enableMultiTabs = flags.enableMultiTabs;
|
|
22
25
|
}
|
|
23
|
-
if (
|
|
26
|
+
if (flags?.useWebWorker === false) {
|
|
24
27
|
resolvedFlags.enableMultiTabs = false;
|
|
25
28
|
}
|
|
26
29
|
return resolvedFlags;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { AbstractStreamingSyncImplementation, LockType } from '@powersync/common';
|
|
2
2
|
import { Mutex } from 'async-mutex';
|
|
3
3
|
export class SSRStreamingSyncImplementation extends AbstractStreamingSyncImplementation {
|
|
4
|
+
syncMutex;
|
|
5
|
+
crudMutex;
|
|
4
6
|
constructor(options) {
|
|
5
7
|
super(options);
|
|
6
8
|
this.syncMutex = new Mutex();
|