@powersync/node 0.0.0-dev-20260503073249 → 0.0.0-dev-20260630141119
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/attachments/NodeFileSystemAdapter.d.ts +1 -0
- package/lib/attachments/NodeFileSystemAdapter.d.ts.map +1 -0
- package/lib/db/AsyncDatabase.d.ts +8 -10
- package/lib/db/AsyncDatabase.d.ts.map +1 -0
- package/lib/db/BetterSqliteWorker.d.ts +6 -17
- package/lib/db/BetterSqliteWorker.d.ts.map +1 -0
- package/lib/db/BetterSqliteWorker.js +18 -9
- package/lib/db/BetterSqliteWorker.js.map +1 -1
- package/lib/db/DefaultWorker.d.ts +1 -0
- package/lib/db/DefaultWorker.d.ts.map +1 -0
- package/lib/db/NodeSqliteWorker.d.ts +6 -12
- package/lib/db/NodeSqliteWorker.d.ts.map +1 -0
- package/lib/db/NodeSqliteWorker.js +11 -9
- package/lib/db/NodeSqliteWorker.js.map +1 -1
- package/lib/db/PowerSyncDatabase.d.ts +7 -19
- package/lib/db/PowerSyncDatabase.d.ts.map +1 -0
- package/lib/db/PowerSyncDatabase.js +22 -29
- package/lib/db/PowerSyncDatabase.js.map +1 -1
- package/lib/db/RemoteConnection.d.ts +7 -18
- package/lib/db/RemoteConnection.d.ts.map +1 -0
- package/lib/db/RemoteConnection.js +10 -24
- package/lib/db/RemoteConnection.js.map +1 -1
- package/lib/db/SqliteWorker.d.ts +1 -0
- package/lib/db/SqliteWorker.d.ts.map +1 -0
- package/lib/db/SqliteWorker.js +3 -13
- package/lib/db/SqliteWorker.js.map +1 -1
- package/lib/db/WorkerConnectionPool.d.ts +5 -23
- package/lib/db/WorkerConnectionPool.d.ts.map +1 -0
- package/lib/db/WorkerConnectionPool.js +8 -22
- package/lib/db/WorkerConnectionPool.js.map +1 -1
- package/lib/db/options.d.ts +1 -0
- package/lib/db/options.d.ts.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/sync/stream/NodeRemote.d.ts +15 -8
- package/lib/sync/stream/NodeRemote.d.ts.map +1 -0
- package/lib/sync/stream/NodeRemote.js +26 -21
- package/lib/sync/stream/NodeRemote.js.map +1 -1
- package/lib/sync/stream/NodeStreamingSyncImplementation.d.ts +2 -1
- package/lib/sync/stream/NodeStreamingSyncImplementation.d.ts.map +1 -0
- package/lib/sync/stream/NodeStreamingSyncImplementation.js +2 -2
- package/lib/sync/stream/NodeStreamingSyncImplementation.js.map +1 -1
- package/lib/worker.d.ts +1 -0
- package/lib/worker.d.ts.map +1 -0
- package/package.json +19 -30
- package/src/db/AsyncDatabase.ts +7 -10
- package/src/db/BetterSqliteWorker.ts +22 -14
- package/src/db/NodeSqliteWorker.ts +16 -13
- package/src/db/PowerSyncDatabase.ts +46 -59
- package/src/db/RemoteConnection.ts +12 -34
- package/src/db/SqliteWorker.ts +3 -13
- package/src/db/WorkerConnectionPool.ts +16 -33
- package/src/index.ts +2 -1
- package/src/sync/stream/NodeRemote.ts +43 -44
- package/src/sync/stream/NodeStreamingSyncImplementation.ts +2 -2
- package/dist/DefaultWorker.cjs +0 -232
- package/dist/DefaultWorker.cjs.map +0 -1
- package/dist/bundle.cjs +0 -533
- package/dist/bundle.cjs.map +0 -1
- package/dist/bundle.d.cts +0 -127
- package/dist/worker.cjs +0 -233
- package/dist/worker.cjs.map +0 -1
- package/dist/worker.d.cts +0 -20
- package/lib/utils/modules.d.ts +0 -2
- package/lib/utils/modules.js +0 -6
- package/lib/utils/modules.js.map +0 -1
- package/lib/utils/modules_commonjs.d.ts +0 -2
- package/lib/utils/modules_commonjs.js +0 -7
- package/lib/utils/modules_commonjs.js.map +0 -1
- package/src/utils/modules.ts +0 -6
- package/src/utils/modules_commonjs.ts +0 -7
|
@@ -1,91 +1,59 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
AdditionalConnectionOptions,
|
|
6
|
-
BucketStorageAdapter,
|
|
2
|
+
BasePowerSyncDatabaseOptions,
|
|
3
|
+
CommonPowerSyncDatabase,
|
|
4
|
+
DatabaseSource,
|
|
7
5
|
DBAdapter,
|
|
8
6
|
PowerSyncBackendConnector,
|
|
9
|
-
|
|
10
|
-
PowerSyncDatabaseOptions,
|
|
11
|
-
PowerSyncDatabaseOptionsWithSettings,
|
|
12
|
-
RequiredAdditionalConnectionOptions,
|
|
13
|
-
SqliteBucketStorage,
|
|
14
|
-
SQLOpenFactory
|
|
7
|
+
PowerSyncDatabaseConstructor
|
|
15
8
|
} from '@powersync/common';
|
|
9
|
+
import {
|
|
10
|
+
BasePowerSyncDatabase,
|
|
11
|
+
AbstractStreamingSyncImplementation,
|
|
12
|
+
BucketStorageAdapter,
|
|
13
|
+
CreateSyncImplementationOptions,
|
|
14
|
+
SqliteBucketStorage,
|
|
15
|
+
openDatabase
|
|
16
|
+
} from '@powersync/shared-internals';
|
|
16
17
|
|
|
17
|
-
import {
|
|
18
|
+
import { NodeRemote, NodeRemoteOptions } from '../sync/stream/NodeRemote.js';
|
|
18
19
|
import { NodeStreamingSyncImplementation } from '../sync/stream/NodeStreamingSyncImplementation.js';
|
|
19
20
|
|
|
20
|
-
import {
|
|
21
|
+
import { WorkerConnectionPool } from './WorkerConnectionPool.js';
|
|
21
22
|
import { NodeSQLOpenOptions } from './options.js';
|
|
22
23
|
|
|
23
|
-
export type NodePowerSyncDatabaseOptions =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
remoteOptions?: Partial<AbstractRemoteOptions>;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export type NodeAdditionalConnectionOptions = AdditionalConnectionOptions & NodeCustomConnectionOptions;
|
|
34
|
-
|
|
35
|
-
export type NodePowerSyncConnectionOptions = PowerSyncConnectionOptions & NodeAdditionalConnectionOptions;
|
|
24
|
+
export type NodePowerSyncDatabaseOptions = BasePowerSyncDatabaseOptions &
|
|
25
|
+
DatabaseSource<NodeSQLOpenOptions> & {
|
|
26
|
+
/**
|
|
27
|
+
* Options to override how the SDK will connect to the sync service.
|
|
28
|
+
*/
|
|
29
|
+
remoteOptions?: NodeRemoteOptions;
|
|
30
|
+
};
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
* A PowerSync database which provides SQLite functionality
|
|
39
|
-
* which is automatically synced.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```typescript
|
|
43
|
-
* export const db = new PowerSyncDatabase({
|
|
44
|
-
* schema: AppSchema,
|
|
45
|
-
* database: {
|
|
46
|
-
* dbFilename: 'example.db'
|
|
47
|
-
* }
|
|
48
|
-
* });
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
32
|
+
class NodePowerSyncDatabase extends BasePowerSyncDatabase<NodePowerSyncDatabaseOptions> {
|
|
52
33
|
constructor(options: NodePowerSyncDatabaseOptions) {
|
|
53
34
|
super(options);
|
|
54
35
|
}
|
|
55
36
|
|
|
56
37
|
async _initialize(): Promise<void> {
|
|
57
38
|
if ('initialize' in this.database) {
|
|
58
|
-
await (this.database as
|
|
39
|
+
await (this.database as WorkerConnectionPool).initialize();
|
|
59
40
|
}
|
|
60
41
|
}
|
|
61
42
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*/
|
|
65
|
-
protected openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter {
|
|
66
|
-
return new WorkerPoolDatabaseAdapter(options.database);
|
|
43
|
+
protected openDBAdapter(): DBAdapter {
|
|
44
|
+
return openDatabase(this.options, (open) => new WorkerConnectionPool(open));
|
|
67
45
|
}
|
|
68
46
|
|
|
69
47
|
protected generateBucketStorageAdapter(): BucketStorageAdapter {
|
|
70
48
|
return new SqliteBucketStorage(this.database, this.logger);
|
|
71
49
|
}
|
|
72
50
|
|
|
73
|
-
connect(
|
|
74
|
-
connector: PowerSyncBackendConnector,
|
|
75
|
-
options?: PowerSyncConnectionOptions & NodeCustomConnectionOptions
|
|
76
|
-
): Promise<void> {
|
|
77
|
-
return super.connect(connector, options);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
51
|
protected generateSyncStreamImplementation(
|
|
81
52
|
connector: PowerSyncBackendConnector,
|
|
82
|
-
options:
|
|
53
|
+
options: CreateSyncImplementationOptions
|
|
83
54
|
): AbstractStreamingSyncImplementation {
|
|
84
55
|
const logger = this.logger;
|
|
85
|
-
const remote = new NodeRemote(connector, logger,
|
|
86
|
-
dispatcher: options.dispatcher,
|
|
87
|
-
...(this.options as NodePowerSyncDatabaseOptions).remoteOptions
|
|
88
|
-
});
|
|
56
|
+
const remote = new NodeRemote(connector, logger, this.options.remoteOptions);
|
|
89
57
|
|
|
90
58
|
return new NodeStreamingSyncImplementation({
|
|
91
59
|
adapter: this.bucketStorageAdapter,
|
|
@@ -100,3 +68,22 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
100
68
|
});
|
|
101
69
|
}
|
|
102
70
|
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A PowerSync database which provides SQLite functionality
|
|
74
|
+
* which is automatically synced.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* export const db = new PowerSyncDatabase({
|
|
79
|
+
* schema: AppSchema,
|
|
80
|
+
* database: {
|
|
81
|
+
* dbFilename: 'example.db'
|
|
82
|
+
* }
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
// Typed constructor to avoid leaking AbstractPowerSyncDatabase into the public interface
|
|
87
|
+
export const PowerSyncDatabase: PowerSyncDatabaseConstructor<NodePowerSyncDatabaseOptions> = NodePowerSyncDatabase;
|
|
88
|
+
|
|
89
|
+
export interface PowerSyncDatabase extends CommonPowerSyncDatabase {}
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConnectionClosedError,
|
|
3
|
-
DBGetUtilsDefaultMixin,
|
|
4
|
-
QueryResult,
|
|
5
|
-
SqlExecutor,
|
|
6
|
-
LockContext
|
|
7
|
-
} from '@powersync/common';
|
|
1
|
+
import { QueryResult, LockContext, RawQueryResult, SqliteRecord, queryResultFromMapped } from '@powersync/common';
|
|
8
2
|
import { releaseProxy, Remote } from 'comlink';
|
|
9
3
|
import { Worker } from 'node:worker_threads';
|
|
10
|
-
import { AsyncDatabase, AsyncDatabaseOpener
|
|
4
|
+
import { AsyncDatabase, AsyncDatabaseOpener } from './AsyncDatabase.js';
|
|
5
|
+
import { ConnectionClosedError } from '@powersync/shared-internals';
|
|
11
6
|
|
|
12
7
|
/**
|
|
13
8
|
* A PowerSync database connection implemented with RPC calls to a background worker.
|
|
14
9
|
*/
|
|
15
|
-
class
|
|
10
|
+
export class RemoteConnection extends LockContext {
|
|
16
11
|
private readonly worker: Worker;
|
|
17
12
|
private readonly comlink: Remote<AsyncDatabaseOpener>;
|
|
18
13
|
private readonly database: Remote<AsyncDatabase>;
|
|
@@ -20,6 +15,7 @@ class BaseRemoteConnection implements SqlExecutor {
|
|
|
20
15
|
private readonly notifyWorkerClosed = new AbortController();
|
|
21
16
|
|
|
22
17
|
constructor(worker: Worker, comlink: Remote<AsyncDatabaseOpener>, database: Remote<AsyncDatabase>) {
|
|
18
|
+
super();
|
|
23
19
|
this.worker = worker;
|
|
24
20
|
this.comlink = comlink;
|
|
25
21
|
this.database = database;
|
|
@@ -66,28 +62,27 @@ class BaseRemoteConnection implements SqlExecutor {
|
|
|
66
62
|
});
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
|
|
65
|
+
execute<T = SqliteRecord>(query: string, params?: any[] | undefined): Promise<QueryResult<T>> {
|
|
70
66
|
return this.withRemote(async () => {
|
|
71
|
-
const
|
|
72
|
-
return
|
|
67
|
+
const results = await this.database.execute(query, params ?? []);
|
|
68
|
+
return queryResultFromMapped(results, results.rows as T[] | undefined);
|
|
73
69
|
});
|
|
74
70
|
}
|
|
75
71
|
|
|
76
|
-
|
|
72
|
+
executeBatch(query: string, params: any[][] = []): Promise<QueryResult<never>> {
|
|
77
73
|
return this.withRemote(async () => {
|
|
78
|
-
|
|
79
|
-
return BaseRemoteConnection.wrapQueryResult(result);
|
|
74
|
+
return await this.database.executeBatch(query, params ?? []);
|
|
80
75
|
});
|
|
81
76
|
}
|
|
82
77
|
|
|
83
|
-
executeRaw(query: string, params?: any[] | undefined): Promise<
|
|
78
|
+
executeRaw(query: string, params?: any[] | undefined): Promise<RawQueryResult> {
|
|
84
79
|
return this.withRemote(async () => {
|
|
85
80
|
return await this.database.executeRaw(query, params ?? []);
|
|
86
81
|
});
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
async refreshSchema() {
|
|
90
|
-
await this.
|
|
85
|
+
await this.executeRaw("pragma table_info('sqlite_master')");
|
|
91
86
|
}
|
|
92
87
|
|
|
93
88
|
async close() {
|
|
@@ -96,21 +91,4 @@ class BaseRemoteConnection implements SqlExecutor {
|
|
|
96
91
|
this.comlink[releaseProxy]();
|
|
97
92
|
await this.worker.terminate();
|
|
98
93
|
}
|
|
99
|
-
|
|
100
|
-
static wrapQueryResult(result: ProxiedQueryResult): QueryResult {
|
|
101
|
-
let rows: QueryResult['rows'] | undefined = undefined;
|
|
102
|
-
if (result.rows) {
|
|
103
|
-
rows = {
|
|
104
|
-
...result.rows,
|
|
105
|
-
item: (idx) => result.rows?._array[idx]
|
|
106
|
-
} satisfies QueryResult['rows'];
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
...result,
|
|
111
|
-
rows
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
94
|
}
|
|
115
|
-
|
|
116
|
-
export class RemoteConnection extends DBGetUtilsDefaultMixin(BaseRemoteConnection) implements LockContext {}
|
package/src/db/SqliteWorker.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
2
|
import OS from 'node:os';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
3
|
import url from 'node:url';
|
|
5
4
|
import { parentPort } from 'node:worker_threads';
|
|
6
|
-
import { dynamicImport, isBundledToCommonJs } from '../utils/modules.js';
|
|
7
5
|
import { AsyncDatabase, AsyncDatabaseOpenOptions, AsyncDatabaseOpener } from './AsyncDatabase.js';
|
|
8
6
|
import { openDatabase as openBetterSqliteDatabase } from './BetterSqliteWorker.js';
|
|
9
7
|
import { openDatabase as openNodeDatabase } from './NodeSqliteWorker.js';
|
|
@@ -71,21 +69,13 @@ export function getPowerSyncExtensionFilename() {
|
|
|
71
69
|
export function startPowerSyncWorker(options?: Partial<PowerSyncWorkerOptions>) {
|
|
72
70
|
const resolvedOptions: PowerSyncWorkerOptions = {
|
|
73
71
|
extensionPath() {
|
|
74
|
-
const isCommonJsModule = isBundledToCommonJs;
|
|
75
72
|
const extensionFilename = getPowerSyncExtensionFilename();
|
|
76
|
-
|
|
77
|
-
if (isCommonJsModule) {
|
|
78
|
-
resolved = path.resolve(__dirname, '../lib/', extensionFilename);
|
|
79
|
-
} else {
|
|
80
|
-
resolved = url.fileURLToPath(new URL(`../${extensionFilename}`, import.meta.url));
|
|
81
|
-
}
|
|
82
|
-
|
|
73
|
+
const resolved = url.fileURLToPath(new URL(`../${extensionFilename}`, import.meta.url));
|
|
83
74
|
return resolved;
|
|
84
75
|
},
|
|
85
76
|
async loadBetterSqlite3() {
|
|
86
|
-
const module = await
|
|
87
|
-
|
|
88
|
-
return isBundledToCommonJs ? module : module.default;
|
|
77
|
+
const module = await import('better-sqlite3');
|
|
78
|
+
return module.default;
|
|
89
79
|
},
|
|
90
80
|
...options
|
|
91
81
|
};
|
|
@@ -4,20 +4,15 @@ import * as path from 'node:path';
|
|
|
4
4
|
import { Worker } from 'node:worker_threads';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
BaseObserver,
|
|
8
7
|
BatchedUpdateNotification,
|
|
9
|
-
|
|
10
|
-
DBAdapterDefaultMixin,
|
|
11
|
-
DBAdapterListener,
|
|
8
|
+
DBAdapter,
|
|
12
9
|
DBLockOptions,
|
|
13
10
|
LockContext,
|
|
14
11
|
QueryResult,
|
|
15
|
-
Semaphore,
|
|
16
|
-
timeoutSignal,
|
|
17
12
|
Transaction
|
|
18
13
|
} from '@powersync/common';
|
|
14
|
+
import { Semaphore, timeoutSignal } from '@powersync/shared-internals';
|
|
19
15
|
import { Remote } from 'comlink';
|
|
20
|
-
import { isBundledToCommonJs } from '../utils/modules.js';
|
|
21
16
|
import { AsyncDatabase, AsyncDatabaseOpener } from './AsyncDatabase.js';
|
|
22
17
|
import { RemoteConnection } from './RemoteConnection.js';
|
|
23
18
|
import { NodeDatabaseImplementation, NodeSQLOpenOptions } from './options.js';
|
|
@@ -37,12 +32,12 @@ const defaultDatabaseImplementation: NodeDatabaseImplementation = {
|
|
|
37
32
|
/**
|
|
38
33
|
* Adapter for better-sqlite3
|
|
39
34
|
*/
|
|
40
|
-
export class WorkerConnectionPool extends
|
|
35
|
+
export class WorkerConnectionPool extends DBAdapter {
|
|
41
36
|
private readonly options: NodeSQLOpenOptions;
|
|
42
37
|
public readonly name: string;
|
|
43
38
|
|
|
44
|
-
private writeConnection
|
|
45
|
-
private readConnections
|
|
39
|
+
private writeConnection?: Semaphore<RemoteConnection>;
|
|
40
|
+
private readConnections?: Semaphore<RemoteConnection>;
|
|
46
41
|
|
|
47
42
|
constructor(options: NodeSQLOpenOptions) {
|
|
48
43
|
super();
|
|
@@ -77,21 +72,15 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
77
72
|
}
|
|
78
73
|
|
|
79
74
|
const openWorker = async (isWriter: boolean) => {
|
|
80
|
-
const isCommonJsModule = isBundledToCommonJs;
|
|
81
|
-
let worker: Worker;
|
|
82
75
|
const workerName = isWriter ? `write ${dbFilePath}` : `read ${dbFilePath}`;
|
|
83
76
|
|
|
84
77
|
const workerFactory = this.options.openWorker ?? ((...args) => new Worker(...args));
|
|
85
|
-
|
|
86
|
-
worker = workerFactory(path.resolve(__dirname, 'DefaultWorker.cjs'), { name: workerName });
|
|
87
|
-
} else {
|
|
88
|
-
worker = workerFactory(new URL('./DefaultWorker.js', import.meta.url), { name: workerName });
|
|
89
|
-
}
|
|
78
|
+
const worker = workerFactory(new URL('./DefaultWorker.js', import.meta.url), { name: workerName });
|
|
90
79
|
|
|
91
80
|
const listeners = new WeakMap<EventListenerOrEventListenerObject, (e: any) => void>();
|
|
92
81
|
|
|
93
82
|
const comlink = Comlink.wrap<AsyncDatabaseOpener>({
|
|
94
|
-
postMessage: worker.postMessage.bind(worker),
|
|
83
|
+
postMessage: worker.postMessage.bind(worker) as any,
|
|
95
84
|
addEventListener: (type, listener) => {
|
|
96
85
|
let resolved: (event: any) => void =
|
|
97
86
|
'handleEvent' in listener ? listener.handleEvent.bind(listener) : listener;
|
|
@@ -127,16 +116,14 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
127
116
|
implementation: this.options.implementation ?? defaultDatabaseImplementation
|
|
128
117
|
})) as Remote<AsyncDatabase>;
|
|
129
118
|
if (isWriter) {
|
|
130
|
-
await database.
|
|
119
|
+
await database.executeRaw("SELECT powersync_update_hooks('install');", []);
|
|
131
120
|
}
|
|
132
121
|
|
|
133
122
|
const connection = new RemoteConnection(worker, comlink, database);
|
|
134
123
|
if (this.options.initializeConnection) {
|
|
135
124
|
await this.options.initializeConnection(connection, isWriter);
|
|
136
125
|
}
|
|
137
|
-
if (
|
|
138
|
-
await connection.execute('pragma query_only = true');
|
|
139
|
-
} else {
|
|
126
|
+
if (isWriter) {
|
|
140
127
|
// We only need to enable this on the writer connection.
|
|
141
128
|
// We can get `database is locked` errors if we enable this on concurrently opening read connections.
|
|
142
129
|
await connection.execute('pragma journal_mode = WAL');
|
|
@@ -156,8 +143,8 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
156
143
|
}
|
|
157
144
|
|
|
158
145
|
async close() {
|
|
159
|
-
const { item: writeConnection, release: returnWrite } = await this.writeConnection
|
|
160
|
-
const { items: readers, release: returnReaders } = await this.readConnections
|
|
146
|
+
const { item: writeConnection, release: returnWrite } = await this.writeConnection!.requestOne();
|
|
147
|
+
const { items: readers, release: returnReaders } = await this.readConnections!.requestAll();
|
|
161
148
|
|
|
162
149
|
try {
|
|
163
150
|
await writeConnection.close();
|
|
@@ -169,7 +156,7 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
169
156
|
}
|
|
170
157
|
|
|
171
158
|
async readLock<T>(fn: (tx: RemoteConnection) => Promise<T>, options?: DBLockOptions | undefined): Promise<T> {
|
|
172
|
-
const lease = await this.readConnections
|
|
159
|
+
const lease = await this.readConnections!.requestOne(timeoutSignal(options?.timeoutMs));
|
|
173
160
|
try {
|
|
174
161
|
return await fn(lease.item);
|
|
175
162
|
} finally {
|
|
@@ -178,20 +165,18 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
178
165
|
}
|
|
179
166
|
|
|
180
167
|
async writeLock<T>(fn: (tx: RemoteConnection) => Promise<T>, options?: DBLockOptions | undefined): Promise<T> {
|
|
181
|
-
const { item, release } = await this.writeConnection
|
|
168
|
+
const { item, release } = await this.writeConnection!.requestOne(timeoutSignal(options?.timeoutMs));
|
|
182
169
|
|
|
183
170
|
try {
|
|
184
171
|
try {
|
|
185
172
|
return await fn(item);
|
|
186
173
|
} finally {
|
|
187
|
-
const serializedUpdates = await item.executeRaw("SELECT powersync_update_hooks('get');", []);
|
|
174
|
+
const { rawRows: serializedUpdates } = await item.executeRaw("SELECT powersync_update_hooks('get');", []);
|
|
188
175
|
const updates = JSON.parse(serializedUpdates[0][0] as string) as string[];
|
|
189
176
|
|
|
190
177
|
if (updates.length > 0) {
|
|
191
178
|
const event: BatchedUpdateNotification = {
|
|
192
|
-
tables: updates
|
|
193
|
-
groupedUpdates: {},
|
|
194
|
-
rawUpdates: []
|
|
179
|
+
tables: updates
|
|
195
180
|
};
|
|
196
181
|
this.iterateListeners((cb) => cb.tablesUpdated?.(event));
|
|
197
182
|
}
|
|
@@ -204,7 +189,7 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
204
189
|
async refreshSchema() {
|
|
205
190
|
await this.writeLock((l) => l.refreshSchema());
|
|
206
191
|
|
|
207
|
-
const { items, release } = await this.readConnections
|
|
192
|
+
const { items, release } = await this.readConnections!.requestAll();
|
|
208
193
|
try {
|
|
209
194
|
await Promise.all(items.map((c) => c.refreshSchema()));
|
|
210
195
|
} finally {
|
|
@@ -212,5 +197,3 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
|
|
|
212
197
|
}
|
|
213
198
|
}
|
|
214
199
|
}
|
|
215
|
-
|
|
216
|
-
export class WorkerPoolDatabaseAdapter extends DBAdapterDefaultMixin(WorkerConnectionPool) {}
|
package/src/index.ts
CHANGED
|
@@ -1,34 +1,18 @@
|
|
|
1
1
|
import * as os from 'node:os';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
BSONImplementation,
|
|
8
|
-
DEFAULT_REMOTE_LOGGER,
|
|
9
|
-
FetchImplementation,
|
|
10
|
-
FetchImplementationProvider,
|
|
11
|
-
RemoteConnector
|
|
12
|
-
} from '@powersync/common';
|
|
13
|
-
import { BSON } from 'bson';
|
|
14
|
-
import {
|
|
15
|
-
Dispatcher,
|
|
16
|
-
EnvHttpProxyAgent,
|
|
17
|
-
ErrorEvent,
|
|
18
|
-
getGlobalDispatcher,
|
|
19
|
-
ProxyAgent,
|
|
20
|
-
WebSocket as UndiciWebSocket
|
|
21
|
-
} from 'undici';
|
|
3
|
+
import { AbstractRemote, FetchOptions, RemoteConnector } from '@powersync/shared-internals';
|
|
4
|
+
import { Dispatcher, EnvHttpProxyAgent, getGlobalDispatcher, ProxyAgent, WebSocket as UndiciWebSocket } from 'undici';
|
|
5
|
+
import { PowerSyncLogger } from '@powersync/common';
|
|
6
|
+
import type { WebSocketSyncStreamPlatform, WebSocketSupport } from '@powersync/shared-internals/websockets';
|
|
22
7
|
|
|
23
8
|
export const STREAMING_POST_TIMEOUT_MS = 30_000;
|
|
24
9
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
export interface NodeRemoteOptions {
|
|
11
|
+
/**
|
|
12
|
+
* @internal Only meant to be used for tests.
|
|
13
|
+
*/
|
|
14
|
+
customFetch?: typeof fetch;
|
|
30
15
|
|
|
31
|
-
export type NodeCustomConnectionOptions = {
|
|
32
16
|
/**
|
|
33
17
|
* Optional custom dispatcher for HTTP or WEB_SOCKET connections.
|
|
34
18
|
*
|
|
@@ -36,32 +20,49 @@ export type NodeCustomConnectionOptions = {
|
|
|
36
20
|
* or other connection options.
|
|
37
21
|
*/
|
|
38
22
|
dispatcher?: Dispatcher;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export type NodeRemoteOptions = AbstractRemoteOptions & NodeCustomConnectionOptions;
|
|
23
|
+
}
|
|
42
24
|
|
|
43
25
|
export class NodeRemote extends AbstractRemote {
|
|
44
26
|
private wsDispatcher: Dispatcher | undefined;
|
|
27
|
+
private fetchImpl: typeof fetch;
|
|
45
28
|
|
|
46
29
|
constructor(
|
|
47
30
|
protected connector: RemoteConnector,
|
|
48
|
-
|
|
49
|
-
options?:
|
|
31
|
+
logger: PowerSyncLogger,
|
|
32
|
+
options?: NodeRemoteOptions
|
|
50
33
|
) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
dispatcher
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
34
|
+
super(connector, logger);
|
|
35
|
+
|
|
36
|
+
this.fetchImpl =
|
|
37
|
+
options?.customFetch ??
|
|
38
|
+
((resource, init) => {
|
|
39
|
+
const dispatcher = options?.dispatcher ?? defaultFetchDispatcher();
|
|
40
|
+
|
|
41
|
+
return fetch(resource, {
|
|
42
|
+
// @ts-expect-error
|
|
43
|
+
dispatcher,
|
|
44
|
+
...init
|
|
45
|
+
});
|
|
46
|
+
});
|
|
60
47
|
|
|
61
48
|
this.wsDispatcher = options?.dispatcher;
|
|
62
49
|
}
|
|
63
50
|
|
|
64
|
-
protected
|
|
51
|
+
protected fetch({ resource, request }: FetchOptions): Promise<Response> {
|
|
52
|
+
return this.fetchImpl(resource, request);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
protected async loadWebSocketSupport(platform: WebSocketSyncStreamPlatform): Promise<WebSocketSupport> {
|
|
56
|
+
if (!websockets) {
|
|
57
|
+
// loadWebSocketSupport being called concurrently is safe, the import resolves to the same module in that case.
|
|
58
|
+
const module = await import('@powersync/shared-internals/websockets');
|
|
59
|
+
websockets = new module.WebSocketSupport(platform);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return websockets;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
createSocket(url: string): globalThis.WebSocket {
|
|
65
66
|
// Create dedicated dispatcher for this WebSocket
|
|
66
67
|
const baseDispatcher = this.getWebsocketDispatcher(url);
|
|
67
68
|
|
|
@@ -98,10 +99,6 @@ export class NodeRemote extends AbstractRemote {
|
|
|
98
99
|
`${os.platform()}/${os.release()}`
|
|
99
100
|
].join(' ');
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
-
async getBSON(): Promise<BSONImplementation> {
|
|
103
|
-
return BSON;
|
|
104
|
-
}
|
|
105
102
|
}
|
|
106
103
|
|
|
107
104
|
function defaultFetchDispatcher(): Dispatcher {
|
|
@@ -121,3 +118,5 @@ function getProxyForProtocol(protocol: string): string | undefined {
|
|
|
121
118
|
process.env[`ALL_PROXY`]
|
|
122
119
|
);
|
|
123
120
|
}
|
|
121
|
+
|
|
122
|
+
let websockets: WebSocketSupport | undefined;
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
LockOptions,
|
|
5
5
|
LockType,
|
|
6
6
|
Mutex
|
|
7
|
-
} from '@powersync/
|
|
7
|
+
} from '@powersync/shared-internals';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Global locks which prevent multiple instances from syncing
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
const LOCKS = new Map<string, Map<LockType, Mutex>>();
|
|
14
14
|
|
|
15
15
|
export class NodeStreamingSyncImplementation extends AbstractStreamingSyncImplementation {
|
|
16
|
-
locks
|
|
16
|
+
locks!: Map<LockType, Mutex>; // initialized by initLocks()
|
|
17
17
|
|
|
18
18
|
constructor(options: AbstractStreamingSyncImplementationOptions) {
|
|
19
19
|
super(options);
|