@evolu/nodejs 3.1.0 → 4.0.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 +10 -1
- package/dist/src/Fs.d.ts +63 -0
- package/dist/src/Fs.d.ts.map +1 -0
- package/dist/src/Fs.js +217 -0
- package/dist/src/Task.d.ts +51 -38
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +2 -2
- package/dist/src/TestBundle.d.ts.map +1 -1
- package/dist/src/TestBundle.js +9 -12
- package/dist/src/TestJSDoc.d.ts +4 -1
- package/dist/src/TestJSDoc.d.ts.map +1 -1
- package/dist/src/TestJSDoc.js +1 -0
- package/dist/src/TestOverviewReporter.d.ts +23 -0
- package/dist/src/TestOverviewReporter.d.ts.map +1 -0
- package/dist/src/TestOverviewReporter.js +66 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/local-first/Relay.d.ts +15 -27
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +10 -25
- package/package.json +17 -8
- package/src/Cli.test.ts +90 -0
- package/src/Fs.test.ts +1019 -0
- package/src/Fs.ts +300 -0
- package/src/Platform.test.ts +32 -0
- package/src/Task.ts +62 -45
- package/src/TestBundle.ts +11 -15
- package/src/TestJSDoc.ts +7 -1
- package/src/TestOverviewReporter.test.ts +219 -0
- package/src/TestOverviewReporter.ts +86 -0
- package/src/Time.test.ts +67 -0
- package/src/index.ts +1 -0
- package/src/local-first/Relay.ts +15 -26
package/dist/src/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { type CreateSqliteDriverDep, type RandomDep, type Task, type TimingSafeEqualDep } from "@evolu/common";
|
|
1
|
+
import { type CreateSqliteDriverDep, Port, type RandomDep, type Task, type TimingSafeEqualDep } from "@evolu/common";
|
|
2
2
|
import { type Relay, type RelayConfig } from "@evolu/common/local-first";
|
|
3
3
|
export interface NodeJsRelayConfig extends RelayConfig {
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The HTTP server's {@link Port}. Zero requests an automatically assigned
|
|
6
|
+
* port.
|
|
7
|
+
*/
|
|
8
|
+
readonly port?: Port;
|
|
6
9
|
}
|
|
7
10
|
export type RelayDeps = CreateSqliteDriverDep & RandomDep & TimingSafeEqualDep;
|
|
8
11
|
/** Dependencies for {@link createRelay} using better-sqlite3. */
|
|
@@ -16,32 +19,17 @@ export declare const createRelayDeps: () => RelayDeps;
|
|
|
16
19
|
* ### Example
|
|
17
20
|
*
|
|
18
21
|
* ```ts
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* const
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* }),
|
|
22
|
+
* import { assertType, Port, type Task } from "@evolu/common";
|
|
23
|
+
* import type { Relay } from "@evolu/common/local-first";
|
|
24
|
+
* import { createRelay, type RelayDeps } from "@evolu/nodejs";
|
|
25
|
+
*
|
|
26
|
+
* const main = createRelay({
|
|
27
|
+
* port: Port.orThrow(4000),
|
|
28
|
+
* isOwnerWithinQuota: (_ownerId, requiredBytes) =>
|
|
29
|
+
* requiredBytes <= 1024 * 1024,
|
|
28
30
|
* });
|
|
29
31
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* await runMain(deps)(
|
|
33
|
-
* createRelay({
|
|
34
|
-
* port: 4000,
|
|
35
|
-
*
|
|
36
|
-
* // Note: Relay requires URL in format ws://host:port?ownerId=<ownerId>
|
|
37
|
-
* // isOwnerAllowed: (_ownerId, { signal: _signal }) => true,
|
|
38
|
-
*
|
|
39
|
-
* isOwnerWithinQuota: (_ownerId, requiredBytes) => {
|
|
40
|
-
* const maxBytes = 1024 * 1024; // 1MB
|
|
41
|
-
* return requiredBytes <= maxBytes;
|
|
42
|
-
* },
|
|
43
|
-
* }),
|
|
44
|
-
* );
|
|
32
|
+
* assertType<typeof main, Task<Relay, never, RelayDeps>>();
|
|
45
33
|
* ```
|
|
46
34
|
*/
|
|
47
35
|
export declare const createRelay: ({ port, name, isOwnerAllowed, isOwnerWithinQuota, }: NodeJsRelayConfig) => Task<Relay, never, RelayDeps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/local-first/Relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,qBAAqB,EAK1B,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,kBAAkB,EAGxB,MAAM,eAAe,CAAC;AACvB,OAAO,EAQL,KAAK,KAAK,EACV,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAC;AAQnC,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD
|
|
1
|
+
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/local-first/Relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,qBAAqB,EAK1B,IAAI,EACJ,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,kBAAkB,EAGxB,MAAM,eAAe,CAAC;AACvB,OAAO,EAQL,KAAK,KAAK,EACV,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAC;AAQnC,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,qBAAqB,GAAG,SAAS,GAAG,kBAAkB,CAAC;AAE/E,iEAAiE;AACjE,eAAO,MAAM,eAAe,QAAO,SAIjC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,WAAW,wDAMnB,iBAAiB,KAAG,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAkNlD,CAAC"}
|
|
@@ -50,7 +50,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
50
50
|
var e = new Error(message);
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
|
-
import { assert, createRandom, createRelation, createSqlite, daemon, Name, ok, OwnerId, tryAsync, Uint8Array, } from "@evolu/common";
|
|
53
|
+
import { assert, createRandom, createRelation, createSqlite, daemon, Name, ok, OwnerId, Port, tryAsync, Uint8Array, } from "@evolu/common";
|
|
54
54
|
import { applyProtocolMessageAsRelay, createBaseSqliteStorageTables, createRelaySqliteStorage, createRelayStorageTables, defaultProtocolMessageMaxSize, parseOwnerIdFromOwnerWebSocketTransportUrl, } from "@evolu/common/local-first";
|
|
55
55
|
import { once } from "events";
|
|
56
56
|
import { existsSync } from "fs";
|
|
@@ -73,35 +73,20 @@ export const createRelayDeps = () => ({
|
|
|
73
73
|
* ### Example
|
|
74
74
|
*
|
|
75
75
|
* ```ts
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
76
|
+
* import { assertType, Port, type Task } from "@evolu/common";
|
|
77
|
+
* import type { Relay } from "@evolu/common/local-first";
|
|
78
|
+
* import { createRelay, type RelayDeps } from "@evolu/nodejs";
|
|
79
79
|
*
|
|
80
|
-
* const
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* }),
|
|
80
|
+
* const main = createRelay({
|
|
81
|
+
* port: Port.orThrow(4000),
|
|
82
|
+
* isOwnerWithinQuota: (_ownerId, requiredBytes) =>
|
|
83
|
+
* requiredBytes <= 1024 * 1024,
|
|
85
84
|
* });
|
|
86
85
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* await runMain(deps)(
|
|
90
|
-
* createRelay({
|
|
91
|
-
* port: 4000,
|
|
92
|
-
*
|
|
93
|
-
* // Note: Relay requires URL in format ws://host:port?ownerId=<ownerId>
|
|
94
|
-
* // isOwnerAllowed: (_ownerId, { signal: _signal }) => true,
|
|
95
|
-
*
|
|
96
|
-
* isOwnerWithinQuota: (_ownerId, requiredBytes) => {
|
|
97
|
-
* const maxBytes = 1024 * 1024; // 1MB
|
|
98
|
-
* return requiredBytes <= maxBytes;
|
|
99
|
-
* },
|
|
100
|
-
* }),
|
|
101
|
-
* );
|
|
86
|
+
* assertType<typeof main, Task<Relay, never, RelayDeps>>();
|
|
102
87
|
* ```
|
|
103
88
|
*/
|
|
104
|
-
export const createRelay = ({ port = 443, name = Name.orThrow("evolu-relay"), isOwnerAllowed, isOwnerWithinQuota, }) => async (run) => {
|
|
89
|
+
export const createRelay = ({ port = Port.orThrow(443), name = Name.orThrow("evolu-relay"), isOwnerAllowed, isOwnerWithinQuota, }) => async (run) => {
|
|
105
90
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
106
91
|
try {
|
|
107
92
|
const disposer = __addDisposableResource(env_1, new AsyncDisposableStack(), true);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evolu/nodejs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Evolu for Node.js",
|
|
5
5
|
"author": "Daniel Steigerwald <daniel@steigerwald.cz>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"types": "./dist/src/TestJSDoc.d.ts",
|
|
30
30
|
"import": "./dist/src/TestJSDoc.js",
|
|
31
31
|
"default": "./dist/src/TestJSDoc.js"
|
|
32
|
+
},
|
|
33
|
+
"./TestOverviewReporter": {
|
|
34
|
+
"types": "./dist/src/TestOverviewReporter.d.ts",
|
|
35
|
+
"import": "./dist/src/TestOverviewReporter.js",
|
|
36
|
+
"default": "./dist/src/TestOverviewReporter.js"
|
|
32
37
|
}
|
|
33
38
|
},
|
|
34
39
|
"typesVersions": {
|
|
@@ -38,11 +43,15 @@
|
|
|
38
43
|
],
|
|
39
44
|
"TestJSDoc": [
|
|
40
45
|
"./dist/src/TestJSDoc.d.ts"
|
|
46
|
+
],
|
|
47
|
+
"TestOverviewReporter": [
|
|
48
|
+
"./dist/src/TestOverviewReporter.d.ts"
|
|
41
49
|
]
|
|
42
50
|
}
|
|
43
51
|
},
|
|
44
52
|
"files": [
|
|
45
53
|
"dist/src/**",
|
|
54
|
+
"!dist/**/*.test.*",
|
|
46
55
|
"src/**",
|
|
47
56
|
"README.md"
|
|
48
57
|
],
|
|
@@ -51,9 +60,9 @@
|
|
|
51
60
|
"ws": "^8.21.3"
|
|
52
61
|
},
|
|
53
62
|
"devDependencies": {
|
|
54
|
-
"@evolu/common": "8.
|
|
55
|
-
"@evolu/oxlint-config": "0.
|
|
56
|
-
"@evolu/typescript-config": "0.1.
|
|
63
|
+
"@evolu/common": "8.10.0",
|
|
64
|
+
"@evolu/oxlint-config": "0.2.0",
|
|
65
|
+
"@evolu/typescript-config": "0.1.1",
|
|
57
66
|
"@types/better-sqlite3": "^9.6.0",
|
|
58
67
|
"@types/node": "^24.10.9",
|
|
59
68
|
"@types/ws": "^8.18.1",
|
|
@@ -64,9 +73,9 @@
|
|
|
64
73
|
"webpack": "^5.109.2"
|
|
65
74
|
},
|
|
66
75
|
"peerDependencies": {
|
|
67
|
-
"@evolu/common": "^8.
|
|
68
|
-
"@evolu/oxlint-config": "^0.
|
|
69
|
-
"@evolu/typescript-config": "^0.1.
|
|
76
|
+
"@evolu/common": "^8.10.0",
|
|
77
|
+
"@evolu/oxlint-config": "^0.2.0",
|
|
78
|
+
"@evolu/typescript-config": "^0.1.1",
|
|
70
79
|
"oxlint": "^1.79.0",
|
|
71
80
|
"oxlint-tsgolint": "7.0.2001",
|
|
72
81
|
"typescript": ">=7.0.0",
|
|
@@ -97,7 +106,7 @@
|
|
|
97
106
|
}
|
|
98
107
|
},
|
|
99
108
|
"engines": {
|
|
100
|
-
"node": ">=24.
|
|
109
|
+
"node": ">=24.20.0"
|
|
101
110
|
},
|
|
102
111
|
"publishConfig": {
|
|
103
112
|
"access": "public"
|
package/src/Cli.test.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertEqual,
|
|
3
|
+
assertErr,
|
|
4
|
+
assertOk,
|
|
5
|
+
assertTrue,
|
|
6
|
+
testAbortError,
|
|
7
|
+
testAbortReason,
|
|
8
|
+
testCreateRun,
|
|
9
|
+
} from "@evolu/common";
|
|
10
|
+
import { test } from "node:test";
|
|
11
|
+
import { spawn } from "./Cli.ts";
|
|
12
|
+
|
|
13
|
+
test("spawn succeeds with inherited stdio and a configured cwd", async () => {
|
|
14
|
+
await using run = testCreateRun();
|
|
15
|
+
const scriptsDirectory = new URL("../../../scripts/", import.meta.url);
|
|
16
|
+
const result = await run(
|
|
17
|
+
spawn(
|
|
18
|
+
process.execPath,
|
|
19
|
+
["-e", 'process.exit(process.cwd().endsWith("scripts") ? 0 : 1)'],
|
|
20
|
+
{ cwd: scriptsDirectory },
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
assertOk(result);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("spawn returns a start error", async () => {
|
|
28
|
+
await using run = testCreateRun();
|
|
29
|
+
const result = await run(spawn("evolu-command-that-does-not-exist", []));
|
|
30
|
+
|
|
31
|
+
assertErr(result);
|
|
32
|
+
const { message } = result.error;
|
|
33
|
+
assertTrue(
|
|
34
|
+
message.startsWith("Failed to start evolu-command-that-does-not-exist:"),
|
|
35
|
+
);
|
|
36
|
+
assertEqual(result, {
|
|
37
|
+
ok: false,
|
|
38
|
+
error: {
|
|
39
|
+
type: "SpawnError",
|
|
40
|
+
command: "evolu-command-that-does-not-exist",
|
|
41
|
+
exitCode: null,
|
|
42
|
+
signal: null,
|
|
43
|
+
message,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("spawn returns a non-zero exit error", async () => {
|
|
49
|
+
await using run = testCreateRun();
|
|
50
|
+
const result = await run(spawn(process.execPath, ["-e", "process.exit(7)"]));
|
|
51
|
+
const command = `${process.execPath} -e process.exit(7)`;
|
|
52
|
+
|
|
53
|
+
assertErr(result, {
|
|
54
|
+
type: "SpawnError",
|
|
55
|
+
command,
|
|
56
|
+
exitCode: 7,
|
|
57
|
+
signal: null,
|
|
58
|
+
message: `${command} exited with code 7.`,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("spawn returns a signal exit error", async () => {
|
|
63
|
+
await using run = testCreateRun();
|
|
64
|
+
const result = await run(
|
|
65
|
+
spawn(process.execPath, ["-e", 'process.kill(process.pid, "SIGTERM")']),
|
|
66
|
+
);
|
|
67
|
+
const command = `${process.execPath} -e process.kill(process.pid, "SIGTERM")`;
|
|
68
|
+
|
|
69
|
+
assertErr(result, {
|
|
70
|
+
type: "SpawnError",
|
|
71
|
+
command,
|
|
72
|
+
exitCode: null,
|
|
73
|
+
signal: "SIGTERM",
|
|
74
|
+
message: `${command} exited from SIGTERM.`,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("spawn aborts its child process with the Run", async () => {
|
|
79
|
+
await using run = testCreateRun();
|
|
80
|
+
const fiber = run.abortable(
|
|
81
|
+
spawn(process.execPath, ["-e", "setInterval(() => {}, 1000)"]),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
await new Promise<void>((resolve) => {
|
|
85
|
+
setImmediate(resolve);
|
|
86
|
+
});
|
|
87
|
+
fiber.abort(testAbortReason);
|
|
88
|
+
|
|
89
|
+
assertErr(await fiber, testAbortError);
|
|
90
|
+
});
|