@nylorun/runtime 0.10.0-beta → 0.12.0-beta
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/CHANGELOG.md +86 -0
- package/README.md +53 -51
- package/dist/adapters/execution/restate.d.ts +130 -0
- package/dist/adapters/execution/restate.js +442 -0
- package/dist/adapters/sandbox/virtual.js +1 -1
- package/dist/adapters/streams/s2.d.ts +18 -0
- package/dist/adapters/streams/s2.js +361 -0
- package/dist/core/executors.d.ts +4 -1
- package/dist/core/executors.js +20 -1
- package/dist/core/flow-host.d.ts +93 -132
- package/dist/core/flow-host.js +282 -547
- package/dist/core/sandbox-routes.d.ts +13 -4
- package/dist/core/sandbox-routes.js +14 -12
- package/dist/execution/memory.d.ts +54 -0
- package/dist/execution/memory.js +217 -0
- package/dist/execution/types.d.ts +125 -0
- package/dist/execution/types.js +52 -0
- package/dist/host/config-for.d.ts +2 -1
- package/dist/host/config-for.js +3 -21
- package/dist/host/config.d.ts +0 -8
- package/dist/host/create-host.d.ts +36 -1
- package/dist/host/create-host.js +51 -24
- package/dist/host/execution.d.ts +61 -0
- package/dist/host/execution.js +69 -0
- package/dist/host/http.d.ts +4 -0
- package/dist/host/http.js +6 -0
- package/dist/host/index.d.ts +3 -1
- package/dist/host/index.js +2 -0
- package/dist/host/main.js +106 -47
- package/dist/host/stack-config.d.ts +72 -0
- package/dist/host/stack-config.js +193 -0
- package/dist/index.d.ts +1 -1
- package/dist/infra/database.d.ts +16 -0
- package/dist/infra/database.js +31 -0
- package/dist/infra/execution.d.ts +39 -0
- package/dist/infra/execution.js +68 -0
- package/dist/infra/index.d.ts +42 -0
- package/dist/infra/index.js +56 -0
- package/dist/infra/readiness.d.ts +33 -0
- package/dist/infra/readiness.js +53 -0
- package/dist/infra/streams.d.ts +17 -0
- package/dist/infra/streams.js +33 -0
- package/dist/infra/workers.d.ts +39 -0
- package/dist/infra/workers.js +31 -0
- package/dist/model/pi-model.d.ts +2 -2
- package/dist/model/pi-model.js +5 -5
- package/dist/sandbox/manager.d.ts +26 -8
- package/dist/sandbox/manager.js +95 -47
- package/dist/sandbox/select.d.ts +1 -1
- package/dist/sandbox/select.js +4 -5
- package/dist/sandbox/types.d.ts +2 -2
- package/dist/store/canonical.d.ts +5 -0
- package/dist/store/canonical.js +17 -0
- package/dist/store/cursor.d.ts +9 -0
- package/dist/store/cursor.js +18 -0
- package/dist/store/memory.d.ts +57 -0
- package/dist/store/memory.js +645 -0
- package/dist/store/ownership.d.ts +19 -0
- package/dist/store/ownership.js +33 -0
- package/dist/store/postgres/connect.d.ts +25 -0
- package/dist/store/postgres/connect.js +25 -0
- package/dist/store/postgres/locking.d.ts +16 -0
- package/dist/store/postgres/locking.js +22 -0
- package/dist/store/postgres/migrations/001_initial.d.ts +27 -0
- package/dist/store/postgres/migrations/001_initial.js +196 -0
- package/dist/store/postgres/migrations/002_session_owner.d.ts +6 -0
- package/dist/store/postgres/migrations/002_session_owner.js +13 -0
- package/dist/store/postgres/migrations/index.d.ts +49 -0
- package/dist/store/postgres/migrations/index.js +76 -0
- package/dist/store/postgres/names.d.ts +11 -0
- package/dist/store/postgres/names.js +42 -0
- package/dist/store/postgres/store.d.ts +11 -0
- package/dist/store/postgres/store.js +797 -0
- package/dist/store/postgres/tenants.d.ts +90 -0
- package/dist/store/postgres/tenants.js +214 -0
- package/dist/store/types.d.ts +442 -0
- package/dist/store/types.js +10 -0
- package/dist/streams/basin.d.ts +23 -0
- package/dist/streams/basin.js +51 -0
- package/dist/streams/memory.d.ts +25 -0
- package/dist/streams/memory.js +124 -0
- package/dist/streams/relay.d.ts +37 -0
- package/dist/streams/relay.js +254 -0
- package/dist/streams/types.d.ts +115 -0
- package/dist/streams/types.js +86 -0
- package/dist/tenant/actions.d.ts +153 -0
- package/dist/tenant/actions.js +191 -0
- package/dist/tenant/advance.d.ts +15 -0
- package/dist/tenant/advance.js +439 -0
- package/dist/tenant/auth.d.ts +32 -0
- package/dist/tenant/auth.js +169 -0
- package/dist/tenant/commands.d.ts +3 -0
- package/dist/tenant/commands.js +393 -0
- package/dist/tenant/context.d.ts +147 -0
- package/dist/tenant/context.js +48 -0
- package/dist/tenant/effects.d.ts +20 -0
- package/dist/tenant/effects.js +564 -0
- package/dist/tenant/envelope.d.ts +0 -3
- package/dist/tenant/envelope.js +2 -34
- package/dist/tenant/ephemeral.d.ts +15 -4
- package/dist/tenant/ephemeral.js +106 -38
- package/dist/tenant/http.d.ts +38 -0
- package/dist/tenant/http.js +53 -0
- package/dist/tenant/live.d.ts +92 -0
- package/dist/tenant/live.js +290 -0
- package/dist/tenant/model-setting.d.ts +16 -0
- package/dist/tenant/model-setting.js +12 -0
- package/dist/tenant/module.d.ts +29 -8
- package/dist/tenant/module.js +165 -158
- package/dist/tenant/paths.d.ts +12 -8
- package/dist/tenant/paths.js +38 -12
- package/dist/tenant/principals.d.ts +12 -13
- package/dist/tenant/principals.js +50 -38
- package/dist/tenant/quarantine-error.d.ts +1 -1
- package/dist/tenant/quarantine-error.js +2 -8
- package/dist/tenant/quarantine.d.ts +0 -8
- package/dist/tenant/quarantine.js +8 -30
- package/dist/tenant/reset.d.ts +7 -6
- package/dist/tenant/reset.js +7 -51
- package/dist/tenant/routes-tenant.d.ts +12 -0
- package/dist/tenant/routes-tenant.js +137 -0
- package/dist/tenant/routes.d.ts +9 -0
- package/dist/tenant/routes.js +151 -0
- package/dist/tenant/runtime.d.ts +59 -58
- package/dist/tenant/runtime.js +243 -2201
- package/dist/tenant/scheduler.d.ts +25 -0
- package/dist/tenant/scheduler.js +84 -0
- package/dist/tenant/session.d.ts +60 -0
- package/dist/tenant/session.js +94 -0
- package/dist/tenant/sessions.d.ts +40 -0
- package/dist/tenant/sessions.js +163 -0
- package/dist/tenant/status.d.ts +13 -4
- package/dist/tenant/status.js +76 -41
- package/dist/tenant/store-memory.d.ts +9 -12
- package/dist/tenant/store-memory.js +79 -68
- package/dist/tenant/store-pg.d.ts +15 -0
- package/dist/tenant/store-pg.js +140 -0
- package/dist/tenant/streams.d.ts +126 -0
- package/dist/tenant/streams.js +419 -0
- package/dist/tenant/sweep.d.ts +15 -0
- package/dist/tenant/sweep.js +122 -0
- package/dist/tenant/transcript.d.ts +104 -0
- package/dist/tenant/transcript.js +58 -0
- package/dist/tenant/types.d.ts +101 -15
- package/dist/tenant/types.js +23 -1
- package/dist/tenant/worker.d.ts +84 -0
- package/dist/tenant/worker.js +189 -0
- package/dist/vault/service.d.ts +44 -31
- package/dist/vault/service.js +454 -360
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +15 -14
- package/dist/adapters/sandbox/microsandbox.d.ts +0 -2
- package/dist/adapters/sandbox/microsandbox.js +0 -238
- package/dist/core/store.d.ts +0 -32
- package/dist/core/store.js +0 -143
- package/dist/launcher/commands.d.ts +0 -24
- package/dist/launcher/commands.js +0 -260
- package/dist/launcher/ensure-config.d.ts +0 -16
- package/dist/launcher/ensure-config.js +0 -79
- package/dist/launcher/errors.d.ts +0 -12
- package/dist/launcher/errors.js +0 -22
- package/dist/launcher/host-config.d.ts +0 -17
- package/dist/launcher/host-config.js +0 -64
- package/dist/launcher/host-state.d.ts +0 -17
- package/dist/launcher/host-state.js +0 -61
- package/dist/launcher/lifecycle.d.ts +0 -66
- package/dist/launcher/lifecycle.js +0 -407
- package/dist/launcher/locks.d.ts +0 -26
- package/dist/launcher/locks.js +0 -117
- package/dist/launcher/logs.d.ts +0 -18
- package/dist/launcher/logs.js +0 -117
- package/dist/launcher/main.d.ts +0 -2
- package/dist/launcher/main.js +0 -66
- package/dist/launcher/output.d.ts +0 -11
- package/dist/launcher/output.js +0 -68
- package/dist/launcher/paths.d.ts +0 -20
- package/dist/launcher/paths.js +0 -36
- package/dist/launcher/probe.d.ts +0 -23
- package/dist/launcher/probe.js +0 -72
- package/dist/launcher/protocol.d.ts +0 -62
- package/dist/launcher/protocol.js +0 -1
- package/dist/launcher/schema-guard.d.ts +0 -6
- package/dist/launcher/schema-guard.js +0 -36
- package/dist/launcher/spawn.d.ts +0 -22
- package/dist/launcher/spawn.js +0 -85
- package/dist/launcher/status.d.ts +0 -6
- package/dist/launcher/status.js +0 -65
- package/dist/tenant/migration.d.ts +0 -16
- package/dist/tenant/migration.js +0 -116
- package/dist/tenant/schema.d.ts +0 -23
- package/dist/tenant/schema.js +0 -151
- package/dist/tenant/store-fs.d.ts +0 -16
- package/dist/tenant/store-fs.js +0 -205
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { HOST_PROTOCOL, LAUNCHER_PROTOCOL, } from "@nylorun/core/compatibility";
|
|
4
|
-
import { TENANT_SCHEMA_VERSION } from "../tenant/schema.js";
|
|
5
|
-
import { RUNTIME_VERSION } from "../version.js";
|
|
6
|
-
import { LauncherError, UsageError } from "./errors.js";
|
|
7
|
-
import { down, restart, run, up } from "./lifecycle.js";
|
|
8
|
-
import { logs } from "./logs.js";
|
|
9
|
-
import { emitError, emitEvent, emitResult, exitCodeFor, } from "./output.js";
|
|
10
|
-
import { ensureHostLayout, hostPaths } from "./paths.js";
|
|
11
|
-
import { status } from "./status.js";
|
|
12
|
-
export const launcherUsage = `Usage: nylorun-runtime [--home <dir>] [--json] <command>
|
|
13
|
-
|
|
14
|
-
Commands:
|
|
15
|
-
version also --version
|
|
16
|
-
up [--port <n>] [--allow-downgrade]
|
|
17
|
-
down [--wait [--timeout <s>]] [--force]
|
|
18
|
-
restart [--port <n>] [--allow-downgrade] [--wait | --force]
|
|
19
|
-
run [--port <n>] [--allow-downgrade]
|
|
20
|
-
status
|
|
21
|
-
logs [--lines <n>] [--follow] [--tenant <id> | --all]`;
|
|
22
|
-
/** The Runtime needs node:sqlite and Node 24 APIs. */
|
|
23
|
-
const MIN_NODE_MAJOR = 24;
|
|
24
|
-
function usage(message) {
|
|
25
|
-
throw new UsageError(`${message}\n\n${launcherUsage}`);
|
|
26
|
-
}
|
|
27
|
-
function parseGlobal(args) {
|
|
28
|
-
const rest = [];
|
|
29
|
-
let json = false;
|
|
30
|
-
let home;
|
|
31
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
32
|
-
const arg = args[index];
|
|
33
|
-
if (arg === "--json") {
|
|
34
|
-
json = true;
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
if (arg === "--home") {
|
|
38
|
-
const value = args[++index];
|
|
39
|
-
if (!value || value.startsWith("-"))
|
|
40
|
-
usage("--home requires a directory.");
|
|
41
|
-
home = value;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
if (arg === "--help" || arg === "-h") {
|
|
45
|
-
throw new UsageError(launcherUsage, "");
|
|
46
|
-
}
|
|
47
|
-
rest.push(arg === "--version" && rest.length === 0 ? "version" : arg);
|
|
48
|
-
}
|
|
49
|
-
return { rest, booleans: new Set(), values: new Map(), json, home };
|
|
50
|
-
}
|
|
51
|
-
function parseCommandFlags(args, allowed = {}) {
|
|
52
|
-
const booleans = new Set();
|
|
53
|
-
const values = new Map();
|
|
54
|
-
const rest = [];
|
|
55
|
-
const booleanNames = new Set(allowed.booleans ?? []);
|
|
56
|
-
const valueNames = new Set(allowed.values ?? []);
|
|
57
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
58
|
-
const arg = args[index];
|
|
59
|
-
if (!arg.startsWith("-")) {
|
|
60
|
-
rest.push(arg);
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
if (booleanNames.has(arg)) {
|
|
64
|
-
if (booleans.has(arg))
|
|
65
|
-
usage(`${arg} may only be supplied once.`);
|
|
66
|
-
booleans.add(arg);
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (valueNames.has(arg)) {
|
|
70
|
-
if (values.has(arg))
|
|
71
|
-
usage(`${arg} may only be supplied once.`);
|
|
72
|
-
const value = args[++index];
|
|
73
|
-
if (!value || value.startsWith("-"))
|
|
74
|
-
usage(`${arg} requires a value.`);
|
|
75
|
-
values.set(arg, value);
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
usage(`Unknown flag ${arg}.`);
|
|
79
|
-
}
|
|
80
|
-
return { rest, booleans, values, json: false };
|
|
81
|
-
}
|
|
82
|
-
function parsePort(value) {
|
|
83
|
-
if (value === undefined)
|
|
84
|
-
return undefined;
|
|
85
|
-
const port = Number(value);
|
|
86
|
-
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
87
|
-
usage("--port must be an integer between 0 and 65535.");
|
|
88
|
-
}
|
|
89
|
-
return port;
|
|
90
|
-
}
|
|
91
|
-
function lifecycleContext(paths, options, sink) {
|
|
92
|
-
return {
|
|
93
|
-
paths,
|
|
94
|
-
platform: options.platform,
|
|
95
|
-
nodeBinary: options.nodeBinary,
|
|
96
|
-
hostEntry: fileURLToPath(new URL("../host/main.js", import.meta.url)),
|
|
97
|
-
runtimeVersion: RUNTIME_VERSION,
|
|
98
|
-
tenantSchemaMax: TENANT_SCHEMA_VERSION,
|
|
99
|
-
baselineEnv: options.baselineEnv,
|
|
100
|
-
emit: (event) => emitEvent(sink, event),
|
|
101
|
-
...(options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}),
|
|
102
|
-
...(options.lifecycle ?? {}),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Run launcher commands. Returns a process exit code (0, 1, or 2).
|
|
107
|
-
* Ambient values must already be resolved into `options`.
|
|
108
|
-
*/
|
|
109
|
-
export async function runLauncher(argv, options) {
|
|
110
|
-
const sink = options.sink;
|
|
111
|
-
try {
|
|
112
|
-
const global = parseGlobal(argv);
|
|
113
|
-
sink.json = global.json || sink.json;
|
|
114
|
-
const home = resolve(global.home ?? options.home);
|
|
115
|
-
const paths = hostPaths(home);
|
|
116
|
-
const [verb, ...rest] = global.rest;
|
|
117
|
-
if (!verb)
|
|
118
|
-
usage("Missing command.");
|
|
119
|
-
if (verb === "version") {
|
|
120
|
-
const flags = parseCommandFlags(rest);
|
|
121
|
-
if (flags.rest.length)
|
|
122
|
-
usage("version takes no arguments.");
|
|
123
|
-
emitResult(sink, {
|
|
124
|
-
runtimeVersion: options.lifecycle?.runtimeVersion ?? RUNTIME_VERSION,
|
|
125
|
-
launcherProtocol: LAUNCHER_PROTOCOL,
|
|
126
|
-
protocol: HOST_PROTOCOL,
|
|
127
|
-
node: options.nodeVersion,
|
|
128
|
-
});
|
|
129
|
-
return 0;
|
|
130
|
-
}
|
|
131
|
-
const nodeMajor = Number(options.nodeVersion.split(".")[0]);
|
|
132
|
-
if (!(nodeMajor >= MIN_NODE_MAJOR)) {
|
|
133
|
-
throw new LauncherError("platform_unsupported", `Node ${MIN_NODE_MAJOR} or newer is required to run the Nylorun Runtime (found ${options.nodeVersion}).`, `Install Node ${MIN_NODE_MAJOR}, then reinstall: npm install --global @nylorun/runtime`);
|
|
134
|
-
}
|
|
135
|
-
if (verb === "status") {
|
|
136
|
-
const flags = parseCommandFlags(rest);
|
|
137
|
-
if (flags.rest.length)
|
|
138
|
-
usage("status takes no arguments.");
|
|
139
|
-
const result = await status(paths, options.lifecycle?.runtimeVersion ?? RUNTIME_VERSION);
|
|
140
|
-
emitResult(sink, { ...result });
|
|
141
|
-
return 0;
|
|
142
|
-
}
|
|
143
|
-
if (verb === "logs") {
|
|
144
|
-
const flags = parseCommandFlags(rest, {
|
|
145
|
-
booleans: ["--follow", "-f", "--all"],
|
|
146
|
-
values: ["--lines", "-n", "--tenant"],
|
|
147
|
-
});
|
|
148
|
-
if (flags.rest.length)
|
|
149
|
-
usage("logs takes no positional arguments.");
|
|
150
|
-
if (flags.booleans.has("--all") && flags.values.has("--tenant")) {
|
|
151
|
-
usage("Use either --tenant or --all, not both.");
|
|
152
|
-
}
|
|
153
|
-
const linesRaw = flags.values.get("--lines") ?? flags.values.get("-n");
|
|
154
|
-
let lines;
|
|
155
|
-
if (linesRaw !== undefined) {
|
|
156
|
-
lines = Number(linesRaw);
|
|
157
|
-
if (!Number.isInteger(lines) || lines < 0) {
|
|
158
|
-
usage("--lines must be a non-negative integer.");
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
await logs(paths, {
|
|
162
|
-
...(lines !== undefined ? { lines } : {}),
|
|
163
|
-
follow: flags.booleans.has("--follow") || flags.booleans.has("-f"),
|
|
164
|
-
all: flags.booleans.has("--all"),
|
|
165
|
-
...(flags.values.has("--tenant")
|
|
166
|
-
? { tenant: flags.values.get("--tenant") }
|
|
167
|
-
: {}),
|
|
168
|
-
...(options.signal ? { signal: options.signal } : {}),
|
|
169
|
-
emit: (event) => emitEvent(sink, event),
|
|
170
|
-
});
|
|
171
|
-
return 0;
|
|
172
|
-
}
|
|
173
|
-
if (verb === "up") {
|
|
174
|
-
const flags = parseCommandFlags(rest, {
|
|
175
|
-
booleans: ["--allow-downgrade"],
|
|
176
|
-
values: ["--port"],
|
|
177
|
-
});
|
|
178
|
-
if (flags.rest.length)
|
|
179
|
-
usage("up takes no positional arguments.");
|
|
180
|
-
const port = parsePort(flags.values.get("--port"));
|
|
181
|
-
const result = await up(lifecycleContext(paths, options, sink), {
|
|
182
|
-
...(port !== undefined ? { port } : {}),
|
|
183
|
-
allowDowngrade: flags.booleans.has("--allow-downgrade"),
|
|
184
|
-
});
|
|
185
|
-
emitResult(sink, { ...result });
|
|
186
|
-
return 0;
|
|
187
|
-
}
|
|
188
|
-
if (verb === "down") {
|
|
189
|
-
const flags = parseCommandFlags(rest, {
|
|
190
|
-
booleans: ["--wait", "--force"],
|
|
191
|
-
values: ["--timeout"],
|
|
192
|
-
});
|
|
193
|
-
if (flags.rest.length)
|
|
194
|
-
usage("down takes no positional arguments.");
|
|
195
|
-
let timeoutMs;
|
|
196
|
-
if (flags.values.has("--timeout")) {
|
|
197
|
-
const seconds = Number(flags.values.get("--timeout"));
|
|
198
|
-
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
199
|
-
usage("--timeout must be a positive number of seconds.");
|
|
200
|
-
}
|
|
201
|
-
timeoutMs = seconds * 1000;
|
|
202
|
-
}
|
|
203
|
-
const result = await down(lifecycleContext(paths, options, sink), {
|
|
204
|
-
wait: flags.booleans.has("--wait"),
|
|
205
|
-
force: flags.booleans.has("--force"),
|
|
206
|
-
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
207
|
-
});
|
|
208
|
-
emitResult(sink, { ...result });
|
|
209
|
-
return 0;
|
|
210
|
-
}
|
|
211
|
-
if (verb === "restart") {
|
|
212
|
-
const flags = parseCommandFlags(rest, {
|
|
213
|
-
booleans: ["--allow-downgrade", "--wait", "--force"],
|
|
214
|
-
values: ["--timeout", "--port"],
|
|
215
|
-
});
|
|
216
|
-
if (flags.rest.length)
|
|
217
|
-
usage("restart takes no positional arguments.");
|
|
218
|
-
let timeoutMs;
|
|
219
|
-
if (flags.values.has("--timeout")) {
|
|
220
|
-
const seconds = Number(flags.values.get("--timeout"));
|
|
221
|
-
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
222
|
-
usage("--timeout must be a positive number of seconds.");
|
|
223
|
-
}
|
|
224
|
-
timeoutMs = seconds * 1000;
|
|
225
|
-
}
|
|
226
|
-
const port = parsePort(flags.values.get("--port"));
|
|
227
|
-
const result = await restart(lifecycleContext(paths, options, sink), {
|
|
228
|
-
allowDowngrade: flags.booleans.has("--allow-downgrade"),
|
|
229
|
-
wait: flags.booleans.has("--wait"),
|
|
230
|
-
force: flags.booleans.has("--force"),
|
|
231
|
-
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
232
|
-
...(port !== undefined ? { port } : {}),
|
|
233
|
-
});
|
|
234
|
-
emitResult(sink, { ...result });
|
|
235
|
-
return 0;
|
|
236
|
-
}
|
|
237
|
-
if (verb === "run") {
|
|
238
|
-
const flags = parseCommandFlags(rest, {
|
|
239
|
-
booleans: ["--allow-downgrade"],
|
|
240
|
-
values: ["--port"],
|
|
241
|
-
});
|
|
242
|
-
if (flags.rest.length)
|
|
243
|
-
usage("run takes no positional arguments.");
|
|
244
|
-
const port = parsePort(flags.values.get("--port"));
|
|
245
|
-
const ctx = lifecycleContext(paths, options, sink);
|
|
246
|
-
const result = await run(ctx, {
|
|
247
|
-
...(port !== undefined ? { port } : {}),
|
|
248
|
-
allowDowngrade: flags.booleans.has("--allow-downgrade"),
|
|
249
|
-
onReady: (ready) => emitResult(sink, { ...ready }),
|
|
250
|
-
});
|
|
251
|
-
void result;
|
|
252
|
-
return 0;
|
|
253
|
-
}
|
|
254
|
-
usage(`Unknown command ${verb}.`);
|
|
255
|
-
}
|
|
256
|
-
catch (error) {
|
|
257
|
-
emitError(sink, error instanceof Error ? error : new Error(String(error)));
|
|
258
|
-
return exitCodeFor(error);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type HostConfigFile } from "./host-config.js";
|
|
2
|
-
import { type HostPaths } from "./paths.js";
|
|
3
|
-
export interface EnsureHostConfigOptions {
|
|
4
|
-
/** Explicit `--port`; collision fails (strict). `0` means pick a free port. */
|
|
5
|
-
port?: number;
|
|
6
|
-
host?: string;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Load or create host.json. On first setup prefer 8787; when taken, pick a free
|
|
10
|
-
* loopback port. Explicit `--port` is strict (except `0` = free port).
|
|
11
|
-
*/
|
|
12
|
-
export declare function ensureHostConfig(paths: HostPaths, options?: EnsureHostConfigOptions): Promise<{
|
|
13
|
-
config: HostConfigFile;
|
|
14
|
-
created: boolean;
|
|
15
|
-
portSelected: boolean;
|
|
16
|
-
}>;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { createServer } from "node:net";
|
|
2
|
-
import { LauncherError } from "./errors.js";
|
|
3
|
-
import { newHostId, readHostConfig, writeHostConfig, } from "./host-config.js";
|
|
4
|
-
import { hostUrl } from "./paths.js";
|
|
5
|
-
import { portBindable, probeHostHealth } from "./probe.js";
|
|
6
|
-
import { ensureHostLayout } from "./paths.js";
|
|
7
|
-
const DEFAULT_HOST = "127.0.0.1";
|
|
8
|
-
const DEFAULT_PORT = 8787;
|
|
9
|
-
async function findFreeLoopbackPort(host) {
|
|
10
|
-
const server = createServer();
|
|
11
|
-
return await new Promise((resolvePromise, reject) => {
|
|
12
|
-
server.once("error", reject);
|
|
13
|
-
server.listen(0, host, () => {
|
|
14
|
-
const address = server.address();
|
|
15
|
-
if (!address || typeof address === "string") {
|
|
16
|
-
server.close();
|
|
17
|
-
reject(new Error("Could not allocate a free loopback port."));
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const { port } = address;
|
|
21
|
-
server.close(() => resolvePromise(port));
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Load or create host.json. On first setup prefer 8787; when taken, pick a free
|
|
27
|
-
* loopback port. Explicit `--port` is strict (except `0` = free port).
|
|
28
|
-
*/
|
|
29
|
-
export async function ensureHostConfig(paths, options = {}) {
|
|
30
|
-
await ensureHostLayout(paths);
|
|
31
|
-
const existing = await readHostConfig(paths);
|
|
32
|
-
if (existing) {
|
|
33
|
-
if (options.port !== undefined && options.port !== 0 && options.port !== existing.port) {
|
|
34
|
-
const updated = {
|
|
35
|
-
...existing,
|
|
36
|
-
format: 1,
|
|
37
|
-
port: options.port,
|
|
38
|
-
};
|
|
39
|
-
if (!(await portBindable(updated.host, updated.port))) {
|
|
40
|
-
const probe = await probeHostHealth(hostUrl(updated));
|
|
41
|
-
if (!probe.health || probe.health.hostId !== updated.hostId) {
|
|
42
|
-
throw new LauncherError("foreign_port", `Port ${updated.port} on ${updated.host} is in use by another process.`, 'Choose a free port with "nylorun-runtime up --port <n>".');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
await writeHostConfig(paths, updated);
|
|
46
|
-
return { config: updated, created: false, portSelected: false };
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
config: { ...existing, format: 1 },
|
|
50
|
-
created: false,
|
|
51
|
-
portSelected: false,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
const host = options.host ?? DEFAULT_HOST;
|
|
55
|
-
let port = options.port === 0 ? await findFreeLoopbackPort(host) : (options.port ?? DEFAULT_PORT);
|
|
56
|
-
let portSelected = options.port === 0;
|
|
57
|
-
if (options.port !== undefined && options.port !== 0) {
|
|
58
|
-
if (!(await portBindable(host, port))) {
|
|
59
|
-
throw new LauncherError("foreign_port", `Port ${port} on ${host} is in use by another process.`, 'Choose a free port with "nylorun-runtime up --port <n>".');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else if (options.port === undefined) {
|
|
63
|
-
if (!(await portBindable(host, port))) {
|
|
64
|
-
const probe = await probeHostHealth(hostUrl({ host, port }));
|
|
65
|
-
if (probe.foreign || probe.health || !(await portBindable(host, port))) {
|
|
66
|
-
port = await findFreeLoopbackPort(host);
|
|
67
|
-
portSelected = true;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
const config = {
|
|
72
|
-
format: 1,
|
|
73
|
-
hostId: newHostId(),
|
|
74
|
-
host,
|
|
75
|
-
port,
|
|
76
|
-
};
|
|
77
|
-
await writeHostConfig(paths, config);
|
|
78
|
-
return { config, created: true, portSelected };
|
|
79
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { ErrorCode } from "@nylorun/core/compatibility";
|
|
2
|
-
/** Operational launcher failure (exit 1). Usage errors are separate (exit 2). */
|
|
3
|
-
export declare class LauncherError extends Error {
|
|
4
|
-
readonly code: ErrorCode;
|
|
5
|
-
readonly remedy: string;
|
|
6
|
-
readonly details?: unknown;
|
|
7
|
-
constructor(code: ErrorCode, message: string, remedy: string, details?: unknown);
|
|
8
|
-
}
|
|
9
|
-
export declare class UsageError extends Error {
|
|
10
|
-
readonly remedy: string;
|
|
11
|
-
constructor(message: string, remedy?: string);
|
|
12
|
-
}
|
package/dist/launcher/errors.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/** Operational launcher failure (exit 1). Usage errors are separate (exit 2). */
|
|
2
|
-
export class LauncherError extends Error {
|
|
3
|
-
code;
|
|
4
|
-
remedy;
|
|
5
|
-
details;
|
|
6
|
-
constructor(code, message, remedy, details) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.name = "LauncherError";
|
|
9
|
-
this.code = code;
|
|
10
|
-
this.remedy = remedy;
|
|
11
|
-
if (details !== undefined)
|
|
12
|
-
this.details = details;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export class UsageError extends Error {
|
|
16
|
-
remedy;
|
|
17
|
-
constructor(message, remedy = "See nylorun-runtime --help.") {
|
|
18
|
-
super(message);
|
|
19
|
-
this.name = "UsageError";
|
|
20
|
-
this.remedy = remedy;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { HostPaths } from "./paths.js";
|
|
2
|
-
import type { HostConfigFileV1 } from "./protocol.js";
|
|
3
|
-
export type HostConfigFile = HostConfigFileV1 & Record<string, unknown>;
|
|
4
|
-
export declare const HOST_ID_PATTERN: RegExp;
|
|
5
|
-
export declare function newHostId(): string;
|
|
6
|
-
export declare function isHostId(value: unknown): value is string;
|
|
7
|
-
/**
|
|
8
|
-
* Read host.json. Missing `format` means Tenants-era format 0.
|
|
9
|
-
* Returns undefined when absent or structurally invalid.
|
|
10
|
-
*/
|
|
11
|
-
export declare function readHostConfig(paths: HostPaths): Promise<HostConfigFile | undefined>;
|
|
12
|
-
/**
|
|
13
|
-
* Write host.json at format 1. Upgrades format 0, keeps unknown fields, and
|
|
14
|
-
* refuses files with a newer format (`host_format_newer`).
|
|
15
|
-
*/
|
|
16
|
-
export declare function writeHostConfig(paths: HostPaths, config: HostConfigFile): Promise<void>;
|
|
17
|
-
export declare function hostConfigFormat(config: HostConfigFile): number;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
-
import { newTenantId } from "@nylorun/core/compatibility";
|
|
4
|
-
import { LauncherError } from "./errors.js";
|
|
5
|
-
const KNOWN_FORMAT = 1;
|
|
6
|
-
export const HOST_ID_PATTERN = /^host_[0-9a-hjkmnp-tv-z]{26}$/;
|
|
7
|
-
export function newHostId() {
|
|
8
|
-
return `host_${newTenantId().slice(3)}`;
|
|
9
|
-
}
|
|
10
|
-
export function isHostId(value) {
|
|
11
|
-
return typeof value === "string" && HOST_ID_PATTERN.test(value);
|
|
12
|
-
}
|
|
13
|
-
function formatOf(value) {
|
|
14
|
-
if (value.format === undefined)
|
|
15
|
-
return 0;
|
|
16
|
-
if (typeof value.format === "number" && Number.isInteger(value.format)) {
|
|
17
|
-
return value.format;
|
|
18
|
-
}
|
|
19
|
-
return Number.POSITIVE_INFINITY;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Read host.json. Missing `format` means Tenants-era format 0.
|
|
23
|
-
* Returns undefined when absent or structurally invalid.
|
|
24
|
-
*/
|
|
25
|
-
export async function readHostConfig(paths) {
|
|
26
|
-
try {
|
|
27
|
-
const value = JSON.parse(await readFile(paths.config, "utf8"));
|
|
28
|
-
if (typeof value.hostId !== "string" ||
|
|
29
|
-
typeof value.host !== "string" ||
|
|
30
|
-
typeof value.port !== "number") {
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Write host.json at format 1. Upgrades format 0, keeps unknown fields, and
|
|
41
|
-
* refuses files with a newer format (`host_format_newer`).
|
|
42
|
-
*/
|
|
43
|
-
export async function writeHostConfig(paths, config) {
|
|
44
|
-
const existing = await readHostConfig(paths);
|
|
45
|
-
if (existing) {
|
|
46
|
-
const existingFormat = formatOf(existing);
|
|
47
|
-
if (existingFormat > KNOWN_FORMAT) {
|
|
48
|
-
throw new LauncherError("host_format_newer", `host.json format ${existingFormat} is newer than this launcher supports (${KNOWN_FORMAT}).`, "Upgrade the Runtime (npm install --global @nylorun/runtime@latest), then retry.", { format: existingFormat, known: KNOWN_FORMAT });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const merged = {
|
|
52
|
-
...(existing ?? {}),
|
|
53
|
-
...config,
|
|
54
|
-
format: 1,
|
|
55
|
-
};
|
|
56
|
-
const temporary = `${paths.config}.${randomBytes(8).toString("hex")}.tmp`;
|
|
57
|
-
await writeFile(temporary, `${JSON.stringify(merged, null, 2)}\n`, {
|
|
58
|
-
mode: 0o600,
|
|
59
|
-
});
|
|
60
|
-
await rename(temporary, paths.config);
|
|
61
|
-
}
|
|
62
|
-
export function hostConfigFormat(config) {
|
|
63
|
-
return formatOf(config);
|
|
64
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { HostPaths } from "./paths.js";
|
|
2
|
-
export interface HostStateFile {
|
|
3
|
-
pid: number;
|
|
4
|
-
startedAt: string;
|
|
5
|
-
version: string;
|
|
6
|
-
entry: string;
|
|
7
|
-
url: string;
|
|
8
|
-
}
|
|
9
|
-
export interface HostCredentialsFile {
|
|
10
|
-
adminKey: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function readHostState(paths: HostPaths): Promise<HostStateFile | undefined>;
|
|
13
|
-
export declare function writeHostState(paths: HostPaths, state: HostStateFile): Promise<void>;
|
|
14
|
-
export declare function clearHostState(paths: HostPaths): Promise<void>;
|
|
15
|
-
export declare function readHostCredentials(paths: HostPaths): Promise<HostCredentialsFile | undefined>;
|
|
16
|
-
/** Create host-credentials.json mode 0600 if missing (Tenants D15). */
|
|
17
|
-
export declare function ensureHostCredentials(paths: HostPaths): Promise<HostCredentialsFile>;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { unlink } from "node:fs/promises";
|
|
3
|
-
import { readFile, rename, writeFile, chmod } from "node:fs/promises";
|
|
4
|
-
export async function readHostState(paths) {
|
|
5
|
-
try {
|
|
6
|
-
const value = JSON.parse(await readFile(paths.state, "utf8"));
|
|
7
|
-
return typeof value?.pid === "number" ? value : undefined;
|
|
8
|
-
}
|
|
9
|
-
catch {
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export async function writeHostState(paths, state) {
|
|
14
|
-
const temporary = `${paths.state}.${randomBytes(8).toString("hex")}.tmp`;
|
|
15
|
-
await writeFile(temporary, `${JSON.stringify(state, null, 2)}\n`, {
|
|
16
|
-
mode: 0o600,
|
|
17
|
-
});
|
|
18
|
-
await rename(temporary, paths.state);
|
|
19
|
-
}
|
|
20
|
-
export async function clearHostState(paths) {
|
|
21
|
-
try {
|
|
22
|
-
await unlink(paths.state);
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
/* absent */
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export async function readHostCredentials(paths) {
|
|
29
|
-
try {
|
|
30
|
-
const value = JSON.parse(await readFile(paths.credentials, "utf8"));
|
|
31
|
-
if (typeof value?.adminKey === "string" &&
|
|
32
|
-
/^[0-9a-f]{64}$/.test(value.adminKey)) {
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return undefined;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/** Create host-credentials.json mode 0600 if missing (Tenants D15). */
|
|
42
|
-
export async function ensureHostCredentials(paths) {
|
|
43
|
-
const existing = await readHostCredentials(paths);
|
|
44
|
-
if (existing)
|
|
45
|
-
return existing;
|
|
46
|
-
const credentials = {
|
|
47
|
-
adminKey: randomBytes(32).toString("hex"),
|
|
48
|
-
};
|
|
49
|
-
const temporary = `${paths.credentials}.${randomBytes(8).toString("hex")}.tmp`;
|
|
50
|
-
await writeFile(temporary, `${JSON.stringify(credentials)}\n`, {
|
|
51
|
-
mode: 0o600,
|
|
52
|
-
});
|
|
53
|
-
await rename(temporary, paths.credentials);
|
|
54
|
-
try {
|
|
55
|
-
await chmod(paths.credentials, 0o600);
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
/* best-effort */
|
|
59
|
-
}
|
|
60
|
-
return credentials;
|
|
61
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { type LockOptions } from "./locks.js";
|
|
2
|
-
import { type HostPaths } from "./paths.js";
|
|
3
|
-
import type { DownResult, LauncherEvent, UpResult } from "./protocol.js";
|
|
4
|
-
import { spawnHostProcess } from "./spawn.js";
|
|
5
|
-
export type LifecycleEmit = (event: LauncherEvent) => void;
|
|
6
|
-
export interface LifecycleContext {
|
|
7
|
-
paths: HostPaths;
|
|
8
|
-
platform: NodeJS.Platform;
|
|
9
|
-
/** Node that runs the Host: the launcher's own `process.execPath`. */
|
|
10
|
-
nodeBinary: string;
|
|
11
|
-
/** Host entry of this package (`dist/host/main.js`). */
|
|
12
|
-
hostEntry: string;
|
|
13
|
-
/** Version of this `@nylorun/runtime` package. */
|
|
14
|
-
runtimeVersion: string;
|
|
15
|
-
/** Highest Tenant schema this package can open. */
|
|
16
|
-
tenantSchemaMax: number;
|
|
17
|
-
/** Allowlisted ambient baseline (from main.ts). */
|
|
18
|
-
baselineEnv: Readonly<Record<string, string | undefined>>;
|
|
19
|
-
emit?: LifecycleEmit;
|
|
20
|
-
fetchImpl?: typeof fetch;
|
|
21
|
-
lock?: LockOptions;
|
|
22
|
-
/** Injectable spawn for tests. */
|
|
23
|
-
spawnHost?: typeof spawnHostProcess;
|
|
24
|
-
/** Injectable signals for `run` tests. */
|
|
25
|
-
onSignal?: (handler: (signal: NodeJS.Signals) => void) => () => void;
|
|
26
|
-
}
|
|
27
|
-
export interface UpOptions {
|
|
28
|
-
port?: number;
|
|
29
|
-
/** Foreground mode used by `run`. */
|
|
30
|
-
foreground?: boolean;
|
|
31
|
-
/** Start even when this Runtime is older than the one that last ran. */
|
|
32
|
-
allowDowngrade?: boolean;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Start the local Host (D§9.6). Never restarts a running Host.
|
|
36
|
-
*/
|
|
37
|
-
export declare function up(ctx: LifecycleContext, options?: UpOptions): Promise<UpResult>;
|
|
38
|
-
export interface DownOptions {
|
|
39
|
-
wait?: boolean;
|
|
40
|
-
force?: boolean;
|
|
41
|
-
timeoutMs?: number;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Stop the local Host (D§9.7).
|
|
45
|
-
*/
|
|
46
|
-
export declare function down(ctx: LifecycleContext, options?: DownOptions): Promise<DownResult>;
|
|
47
|
-
export interface RestartOptions {
|
|
48
|
-
allowDowngrade?: boolean;
|
|
49
|
-
wait?: boolean;
|
|
50
|
-
force?: boolean;
|
|
51
|
-
timeoutMs?: number;
|
|
52
|
-
port?: number;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Check the installed Runtime can take over, stop, start (D§9.8).
|
|
56
|
-
* runtimeVersion updates only after ready.
|
|
57
|
-
*/
|
|
58
|
-
export declare function restart(ctx: LifecycleContext, options?: RestartOptions): Promise<UpResult>;
|
|
59
|
-
/**
|
|
60
|
-
* Foreground Host: print up result once ready; stop on SIGINT/SIGTERM (D§9.3).
|
|
61
|
-
*/
|
|
62
|
-
export declare function run(ctx: LifecycleContext, options?: {
|
|
63
|
-
port?: number;
|
|
64
|
-
allowDowngrade?: boolean;
|
|
65
|
-
onReady?: (result: UpResult) => void;
|
|
66
|
-
}): Promise<UpResult>;
|