@powersync/node 0.12.0 → 0.14.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/DefaultWorker.cjs.map +1 -1
- package/dist/bundle.cjs +45 -21
- package/dist/bundle.cjs.map +1 -1
- package/dist/worker.cjs.map +1 -1
- package/lib/db/AsyncDatabase.js +1 -0
- package/lib/db/AsyncDatabase.js.map +1 -0
- package/lib/db/BetterSqliteWorker.js +1 -0
- package/lib/db/BetterSqliteWorker.js.map +1 -0
- package/lib/db/DefaultWorker.js +1 -0
- package/lib/db/DefaultWorker.js.map +1 -0
- package/lib/db/NodeSqliteWorker.js +1 -0
- package/lib/db/NodeSqliteWorker.js.map +1 -0
- package/lib/db/PowerSyncDatabase.js +1 -0
- package/lib/db/PowerSyncDatabase.js.map +1 -0
- package/lib/db/RemoteConnection.d.ts +3 -2
- package/lib/db/RemoteConnection.js +30 -12
- package/lib/db/RemoteConnection.js.map +1 -0
- package/lib/db/SqliteWorker.js +1 -0
- package/lib/db/SqliteWorker.js.map +1 -0
- package/lib/db/WorkerConnectionPool.d.ts +1 -1
- package/lib/db/WorkerConnectionPool.js +9 -4
- package/lib/db/WorkerConnectionPool.js.map +1 -0
- package/lib/db/options.js +1 -0
- package/lib/db/options.js.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -0
- package/lib/sync/stream/NodeRemote.js +1 -0
- package/lib/sync/stream/NodeRemote.js.map +1 -0
- package/lib/sync/stream/NodeStreamingSyncImplementation.d.ts +3 -3
- package/lib/sync/stream/NodeStreamingSyncImplementation.js +8 -4
- package/lib/sync/stream/NodeStreamingSyncImplementation.js.map +1 -0
- package/lib/utils/modules.js +1 -0
- package/lib/utils/modules.js.map +1 -0
- package/lib/utils/modules_commonjs.js +1 -0
- package/lib/utils/modules_commonjs.js.map +1 -0
- package/lib/worker.js +1 -0
- package/lib/worker.js.map +1 -0
- package/package.json +10 -10
- package/src/db/AsyncDatabase.ts +26 -0
- package/src/db/BetterSqliteWorker.ts +72 -0
- package/src/db/DefaultWorker.ts +3 -0
- package/src/db/NodeSqliteWorker.ts +63 -0
- package/src/db/PowerSyncDatabase.ts +100 -0
- package/src/db/RemoteConnection.ts +129 -0
- package/src/db/SqliteWorker.ts +119 -0
- package/src/db/WorkerConnectionPool.ts +328 -0
- package/src/db/options.ts +51 -0
- package/src/index.ts +4 -0
- package/src/sync/stream/NodeRemote.ts +123 -0
- package/src/sync/stream/NodeStreamingSyncImplementation.ts +57 -0
- package/src/utils/modules.ts +6 -0
- package/src/utils/modules_commonjs.ts +7 -0
- package/src/worker.ts +1 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type ILogger,
|
|
5
|
+
AbstractRemote,
|
|
6
|
+
AbstractRemoteOptions,
|
|
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';
|
|
22
|
+
|
|
23
|
+
export const STREAMING_POST_TIMEOUT_MS = 30_000;
|
|
24
|
+
|
|
25
|
+
class NodeFetchProvider extends FetchImplementationProvider {
|
|
26
|
+
getFetch(): FetchImplementation {
|
|
27
|
+
return fetch.bind(globalThis);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type NodeCustomConnectionOptions = {
|
|
32
|
+
/**
|
|
33
|
+
* Optional custom dispatcher for HTTP or WEB_SOCKET connections.
|
|
34
|
+
*
|
|
35
|
+
* This can be used to customize proxy usage (using undici ProxyAgent),
|
|
36
|
+
* or other connection options.
|
|
37
|
+
*/
|
|
38
|
+
dispatcher?: Dispatcher;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type NodeRemoteOptions = AbstractRemoteOptions & NodeCustomConnectionOptions;
|
|
42
|
+
|
|
43
|
+
export class NodeRemote extends AbstractRemote {
|
|
44
|
+
private wsDispatcher: Dispatcher | undefined;
|
|
45
|
+
|
|
46
|
+
constructor(
|
|
47
|
+
protected connector: RemoteConnector,
|
|
48
|
+
protected logger: ILogger = DEFAULT_REMOTE_LOGGER,
|
|
49
|
+
options?: Partial<NodeRemoteOptions>
|
|
50
|
+
) {
|
|
51
|
+
const fetchDispatcher = options?.dispatcher ?? defaultFetchDispatcher();
|
|
52
|
+
|
|
53
|
+
super(connector, logger, {
|
|
54
|
+
fetchImplementation: options?.fetchImplementation ?? new NodeFetchProvider(),
|
|
55
|
+
fetchOptions: {
|
|
56
|
+
dispatcher: fetchDispatcher
|
|
57
|
+
},
|
|
58
|
+
...(options ?? {})
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.wsDispatcher = options?.dispatcher;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected createSocket(url: string): globalThis.WebSocket {
|
|
65
|
+
// Create dedicated dispatcher for this WebSocket
|
|
66
|
+
const baseDispatcher = this.getWebsocketDispatcher(url);
|
|
67
|
+
|
|
68
|
+
// Create WebSocket with dedicated dispatcher
|
|
69
|
+
const ws = new UndiciWebSocket(url, {
|
|
70
|
+
dispatcher: baseDispatcher,
|
|
71
|
+
headers: {
|
|
72
|
+
'User-Agent': this.getUserAgent()
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return ws as globalThis.WebSocket;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected getWebsocketDispatcher(url: string) {
|
|
80
|
+
if (this.wsDispatcher != null) {
|
|
81
|
+
return this.wsDispatcher;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const protocol = new URL(url).protocol.replace(':', '');
|
|
85
|
+
const proxy = getProxyForProtocol(protocol);
|
|
86
|
+
if (proxy != null) {
|
|
87
|
+
return new ProxyAgent(proxy);
|
|
88
|
+
} else {
|
|
89
|
+
return getGlobalDispatcher();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getUserAgent(): string {
|
|
94
|
+
return [
|
|
95
|
+
super.getUserAgent(),
|
|
96
|
+
`powersync-node`,
|
|
97
|
+
`node/${process.versions.node}`,
|
|
98
|
+
`${os.platform()}/${os.release()}`
|
|
99
|
+
].join(' ');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async getBSON(): Promise<BSONImplementation> {
|
|
103
|
+
return BSON;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function defaultFetchDispatcher(): Dispatcher {
|
|
108
|
+
// EnvHttpProxyAgent automatically uses HTTP_PROXY, HTTPS_PROXY and NO_PROXY env vars by default.
|
|
109
|
+
// We add ALL_PROXY support.
|
|
110
|
+
return new EnvHttpProxyAgent({
|
|
111
|
+
httpProxy: getProxyForProtocol('http'),
|
|
112
|
+
httpsProxy: getProxyForProtocol('https')
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getProxyForProtocol(protocol: string): string | undefined {
|
|
117
|
+
return (
|
|
118
|
+
process.env[`${protocol.toLowerCase()}_proxy`] ??
|
|
119
|
+
process.env[`${protocol.toUpperCase()}_PROXY`] ??
|
|
120
|
+
process.env[`all_proxy`] ??
|
|
121
|
+
process.env[`ALL_PROXY`]
|
|
122
|
+
);
|
|
123
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AbstractStreamingSyncImplementation,
|
|
3
|
+
AbstractStreamingSyncImplementationOptions,
|
|
4
|
+
LockOptions,
|
|
5
|
+
LockType
|
|
6
|
+
} from '@powersync/common';
|
|
7
|
+
import { Mutex } from 'async-mutex';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Global locks which prevent multiple instances from syncing
|
|
11
|
+
* concurrently.
|
|
12
|
+
*/
|
|
13
|
+
const LOCKS = new Map<string, Map<LockType, Mutex>>();
|
|
14
|
+
|
|
15
|
+
const lockTypes = new Set(Object.values(LockType));
|
|
16
|
+
|
|
17
|
+
export class NodeStreamingSyncImplementation extends AbstractStreamingSyncImplementation {
|
|
18
|
+
locks: Map<LockType, Mutex>;
|
|
19
|
+
|
|
20
|
+
constructor(options: AbstractStreamingSyncImplementationOptions) {
|
|
21
|
+
super(options);
|
|
22
|
+
this.initLocks();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Configures global locks on sync process
|
|
27
|
+
*/
|
|
28
|
+
initLocks() {
|
|
29
|
+
const { identifier } = this.options;
|
|
30
|
+
if (identifier && LOCKS.has(identifier)) {
|
|
31
|
+
this.locks = LOCKS.get(identifier)!;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.locks = new Map<LockType, Mutex>();
|
|
36
|
+
this.locks.set(LockType.CRUD, new Mutex());
|
|
37
|
+
this.locks.set(LockType.SYNC, new Mutex());
|
|
38
|
+
|
|
39
|
+
if (identifier) {
|
|
40
|
+
LOCKS.set(identifier, this.locks);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
obtainLock<T>(lockOptions: LockOptions<T>): Promise<T> {
|
|
45
|
+
const lock = this.locks.get(lockOptions.type);
|
|
46
|
+
if (!lock) {
|
|
47
|
+
throw new Error(`Lock type ${lockOptions.type} not found`);
|
|
48
|
+
}
|
|
49
|
+
return lock.runExclusive(async () => {
|
|
50
|
+
if (lockOptions.signal?.aborted) {
|
|
51
|
+
throw new Error('Aborted');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return lockOptions.callback();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// NOTE! Do not import this file directly! We have a rollup plugin that rewrites imports to modules.js to this file when
|
|
2
|
+
// bundling to CommonJS.
|
|
3
|
+
export const isBundledToCommonJs: boolean = true;
|
|
4
|
+
|
|
5
|
+
export async function dynamicImport(path: string) {
|
|
6
|
+
return require(path);
|
|
7
|
+
}
|
package/src/worker.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './db/SqliteWorker.js';
|