@powersync/node 0.2.2 → 0.4.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/README.md +16 -0
- package/download_core.js +1 -1
- package/lib/db/PowerSyncDatabase.d.ts +20 -2
- package/lib/db/PowerSyncDatabase.js +8 -2
- package/lib/db/RemoteConnection.d.ts +5 -0
- package/lib/db/RemoteConnection.js +31 -8
- package/lib/libpowersync.so +0 -0
- package/lib/sync/stream/NodeRemote.d.ts +7 -3
- package/lib/sync/stream/NodeRemote.js +19 -2
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -56,6 +56,22 @@ contains everything you need to know to get started implementing PowerSync in yo
|
|
|
56
56
|
|
|
57
57
|
A simple example using `@powersync/node` is available in the [`demos/example-node/`](../demos/example-node) directory.
|
|
58
58
|
|
|
59
|
+
# Proxy Support
|
|
60
|
+
|
|
61
|
+
This SDK supports HTTP, HTTPS, and WebSocket proxies via environment variables.
|
|
62
|
+
|
|
63
|
+
## HTTP Connection Method
|
|
64
|
+
|
|
65
|
+
Internally we probe the http environment variables and apply it to fetch requests ([undici](https://www.npmjs.com/package/undici/v/5.6.0))
|
|
66
|
+
|
|
67
|
+
- Set the `HTTPS_PROXY` or `HTTP_PROXY` environment variable to automatically route HTTP requests through a proxy.
|
|
68
|
+
|
|
69
|
+
## WEB Socket Connection Method
|
|
70
|
+
|
|
71
|
+
Internally the [proxy-agent](https://www.npmjs.com/package/proxy-agent) dependency for WebSocket proxies, which has its own internal code for automatically picking up the appropriate environment variables:
|
|
72
|
+
|
|
73
|
+
- Set the `WS_PROXY` or `WSS_PROXY` environment variable to route the webocket connections through a proxy.
|
|
74
|
+
|
|
59
75
|
# Found a bug or need help?
|
|
60
76
|
|
|
61
77
|
- Join our [Discord server](https://discord.gg/powersync) where you can browse topics from our community, ask questions, share feedback, or just say hello :)
|
package/download_core.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import { AbstractPowerSyncDatabase, AbstractStreamingSyncImplementation, BucketStorageAdapter, DBAdapter, PowerSyncBackendConnector, PowerSyncDatabaseOptions, PowerSyncDatabaseOptionsWithSettings, SQLOpenFactory } from '@powersync/common';
|
|
1
|
+
import { AbstractPowerSyncDatabase, AbstractRemoteOptions, AbstractStreamingSyncImplementation, AdditionalConnectionOptions, BucketStorageAdapter, DBAdapter, PowerSyncBackendConnector, PowerSyncConnectionOptions, PowerSyncDatabaseOptions, PowerSyncDatabaseOptionsWithSettings, SQLOpenFactory } from '@powersync/common';
|
|
2
2
|
import { NodeSQLOpenOptions } from './options.js';
|
|
3
|
+
import { Dispatcher } from 'undici';
|
|
3
4
|
export type NodePowerSyncDatabaseOptions = PowerSyncDatabaseOptions & {
|
|
4
5
|
database: DBAdapter | SQLOpenFactory | NodeSQLOpenOptions;
|
|
6
|
+
/**
|
|
7
|
+
* Options to override how the SDK will connect to the sync service.
|
|
8
|
+
*
|
|
9
|
+
* This option is intended to be used for internal tests.
|
|
10
|
+
*/
|
|
11
|
+
remoteOptions?: Partial<AbstractRemoteOptions>;
|
|
12
|
+
};
|
|
13
|
+
export type NodeAdditionalConnectionOptions = AdditionalConnectionOptions & {
|
|
14
|
+
/**
|
|
15
|
+
* Optional custom dispatcher for HTTP connections (e.g. using undici).
|
|
16
|
+
* Only used when the connection method is SyncStreamConnectionMethod.HTTP
|
|
17
|
+
*/
|
|
18
|
+
dispatcher?: Dispatcher;
|
|
5
19
|
};
|
|
20
|
+
export type NodePowerSyncConnectionOptions = PowerSyncConnectionOptions & NodeAdditionalConnectionOptions;
|
|
6
21
|
/**
|
|
7
22
|
* A PowerSync database which provides SQLite functionality
|
|
8
23
|
* which is automatically synced.
|
|
@@ -25,5 +40,8 @@ export declare class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
25
40
|
*/
|
|
26
41
|
protected openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;
|
|
27
42
|
protected generateBucketStorageAdapter(): BucketStorageAdapter;
|
|
28
|
-
|
|
43
|
+
connect(connector: PowerSyncBackendConnector, options?: PowerSyncConnectionOptions & {
|
|
44
|
+
dispatcher?: Dispatcher;
|
|
45
|
+
}): Promise<void>;
|
|
46
|
+
protected generateSyncStreamImplementation(connector: PowerSyncBackendConnector, options: NodeAdditionalConnectionOptions): AbstractStreamingSyncImplementation;
|
|
29
47
|
}
|
|
@@ -32,8 +32,14 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
|
32
32
|
generateBucketStorageAdapter() {
|
|
33
33
|
return new SqliteBucketStorage(this.database, AbstractPowerSyncDatabase.transactionMutex);
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
connect(connector, options) {
|
|
36
|
+
return super.connect(connector, options);
|
|
37
|
+
}
|
|
38
|
+
generateSyncStreamImplementation(connector, options) {
|
|
39
|
+
const remote = new NodeRemote(connector, this.options.logger, {
|
|
40
|
+
dispatcher: options.dispatcher,
|
|
41
|
+
...this.options.remoteOptions
|
|
42
|
+
});
|
|
37
43
|
return new NodeStreamingSyncImplementation({
|
|
38
44
|
adapter: this.bucketStorageAdapter,
|
|
39
45
|
remote,
|
|
@@ -11,6 +11,11 @@ export declare class RemoteConnection implements LockContext {
|
|
|
11
11
|
private readonly comlink;
|
|
12
12
|
readonly database: Remote<AsyncDatabase>;
|
|
13
13
|
constructor(worker: Worker, comlink: Remote<AsyncDatabaseOpener>, database: Remote<AsyncDatabase>);
|
|
14
|
+
/**
|
|
15
|
+
* Runs the inner function, but appends the stack trace where this function was called. This is useful for workers
|
|
16
|
+
* because stack traces from worker errors are otherwise unrelated to the application issue that has caused them.
|
|
17
|
+
*/
|
|
18
|
+
private recoverTrace;
|
|
14
19
|
executeBatch(query: string, params?: any[][]): Promise<QueryResult>;
|
|
15
20
|
execute(query: string, params?: any[] | undefined): Promise<QueryResult>;
|
|
16
21
|
executeRaw(query: string, params?: any[] | undefined): Promise<any[][]>;
|
|
@@ -12,16 +12,39 @@ export class RemoteConnection {
|
|
|
12
12
|
this.comlink = comlink;
|
|
13
13
|
this.database = database;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Runs the inner function, but appends the stack trace where this function was called. This is useful for workers
|
|
17
|
+
* because stack traces from worker errors are otherwise unrelated to the application issue that has caused them.
|
|
18
|
+
*/
|
|
19
|
+
async recoverTrace(inner) {
|
|
20
|
+
const trace = {};
|
|
21
|
+
Error.captureStackTrace(trace);
|
|
22
|
+
try {
|
|
23
|
+
return await inner();
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
if (e instanceof Error && e.stack) {
|
|
27
|
+
e.stack += trace.stack;
|
|
28
|
+
}
|
|
29
|
+
throw e;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
executeBatch(query, params = []) {
|
|
33
|
+
return this.recoverTrace(async () => {
|
|
34
|
+
const result = await this.database.executeBatch(query, params ?? []);
|
|
35
|
+
return RemoteConnection.wrapQueryResult(result);
|
|
36
|
+
});
|
|
18
37
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
38
|
+
execute(query, params) {
|
|
39
|
+
return this.recoverTrace(async () => {
|
|
40
|
+
const result = await this.database.execute(query, params ?? []);
|
|
41
|
+
return RemoteConnection.wrapQueryResult(result);
|
|
42
|
+
});
|
|
22
43
|
}
|
|
23
|
-
|
|
24
|
-
return
|
|
44
|
+
executeRaw(query, params) {
|
|
45
|
+
return this.recoverTrace(async () => {
|
|
46
|
+
return await this.database.executeRaw(query, params ?? []);
|
|
47
|
+
});
|
|
25
48
|
}
|
|
26
49
|
async getAll(sql, parameters) {
|
|
27
50
|
const res = await this.execute(sql, parameters);
|
package/lib/libpowersync.so
CHANGED
|
Binary file
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { ILogger } from '
|
|
2
|
-
import {
|
|
1
|
+
import { type ILogger, AbstractRemote, AbstractRemoteOptions, BSONImplementation, RemoteConnector } from '@powersync/common';
|
|
2
|
+
import { Dispatcher } from 'undici';
|
|
3
3
|
export declare const STREAMING_POST_TIMEOUT_MS = 30000;
|
|
4
|
+
export type NodeRemoteOptions = AbstractRemoteOptions & {
|
|
5
|
+
dispatcher?: Dispatcher;
|
|
6
|
+
};
|
|
4
7
|
export declare class NodeRemote extends AbstractRemote {
|
|
5
8
|
protected connector: RemoteConnector;
|
|
6
9
|
protected logger: ILogger;
|
|
7
|
-
constructor(connector: RemoteConnector, logger?: ILogger, options?: Partial<
|
|
10
|
+
constructor(connector: RemoteConnector, logger?: ILogger, options?: Partial<NodeRemoteOptions>);
|
|
11
|
+
protected createSocket(url: string): globalThis.WebSocket;
|
|
8
12
|
getUserAgent(): string;
|
|
9
13
|
getBSON(): Promise<BSONImplementation>;
|
|
10
14
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as os from 'node:os';
|
|
2
2
|
import { AbstractRemote, DEFAULT_REMOTE_LOGGER, FetchImplementationProvider } from '@powersync/common';
|
|
3
3
|
import { BSON } from 'bson';
|
|
4
|
+
import Agent from 'proxy-agent';
|
|
5
|
+
import { EnvHttpProxyAgent } from 'undici';
|
|
6
|
+
import { WebSocket } from 'ws';
|
|
4
7
|
export const STREAMING_POST_TIMEOUT_MS = 30_000;
|
|
5
8
|
class NodeFetchProvider extends FetchImplementationProvider {
|
|
6
9
|
getFetch() {
|
|
@@ -11,13 +14,27 @@ export class NodeRemote extends AbstractRemote {
|
|
|
11
14
|
connector;
|
|
12
15
|
logger;
|
|
13
16
|
constructor(connector, logger = DEFAULT_REMOTE_LOGGER, options) {
|
|
17
|
+
// EnvHttpProxyAgent automatically uses relevant env vars for HTTP
|
|
18
|
+
const dispatcher = options?.dispatcher ?? new EnvHttpProxyAgent();
|
|
14
19
|
super(connector, logger, {
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
fetchImplementation: options?.fetchImplementation ?? new NodeFetchProvider(),
|
|
21
|
+
fetchOptions: {
|
|
22
|
+
dispatcher
|
|
23
|
+
},
|
|
24
|
+
...(options ?? {})
|
|
17
25
|
});
|
|
18
26
|
this.connector = connector;
|
|
19
27
|
this.logger = logger;
|
|
20
28
|
}
|
|
29
|
+
createSocket(url) {
|
|
30
|
+
return new WebSocket(url, {
|
|
31
|
+
// Automatically uses relevant env vars for web sockets
|
|
32
|
+
agent: new Agent.ProxyAgent(),
|
|
33
|
+
headers: {
|
|
34
|
+
'User-Agent': this.getUserAgent()
|
|
35
|
+
}
|
|
36
|
+
}); // This is compatible in Node environments
|
|
37
|
+
}
|
|
21
38
|
getUserAgent() {
|
|
22
39
|
return [
|
|
23
40
|
super.getUserAgent(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powersync/node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -36,14 +36,17 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://docs.powersync.com/",
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@powersync/common": "^1.
|
|
39
|
+
"@powersync/common": "^1.29.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@powersync/better-sqlite3": "^0.1.1",
|
|
43
43
|
"async-lock": "^1.4.0",
|
|
44
44
|
"bson": "^6.6.0",
|
|
45
45
|
"comlink": "^4.4.2",
|
|
46
|
-
"
|
|
46
|
+
"proxy-agent": "^6.5.0",
|
|
47
|
+
"undici": "^7.8.0",
|
|
48
|
+
"ws": "^8.18.1",
|
|
49
|
+
"@powersync/common": "1.29.0"
|
|
47
50
|
},
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"@types/async-lock": "^1.4.0",
|