@nylorun/cli 0.3.0-beta → 0.4.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 +50 -1
- package/README.md +55 -78
- package/dist/{runtime/baseline.js → baseline.js} +0 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +34 -115
- package/dist/doctor.d.ts +1 -12
- package/dist/doctor.js +6 -96
- package/dist/home.d.ts +6 -0
- package/dist/home.js +15 -0
- package/dist/model/host-model.js +1 -1
- package/dist/project/create-tenant.d.ts +3 -1
- package/dist/project/create-tenant.js +3 -2
- package/dist/project/credentials.js +1 -1
- package/dist/project/env.d.ts +3 -0
- package/dist/project/env.js +21 -0
- package/dist/project/link.js +1 -1
- package/dist/project/root.js +2 -1
- package/dist/project/seed.d.ts +6 -0
- package/dist/project/seed.js +9 -7
- package/dist/tenant/commands.js +73 -14
- package/package.json +6 -9
- package/dist/dev-entry.d.ts +0 -5
- package/dist/dev-entry.js +0 -7
- package/dist/dev.d.ts +0 -47
- package/dist/dev.js +0 -278
- package/dist/launcher.d.ts +0 -5
- package/dist/launcher.js +0 -7
- package/dist/project/attach.d.ts +0 -32
- package/dist/project/attach.js +0 -241
- package/dist/runtime/commands.d.ts +0 -16
- package/dist/runtime/commands.js +0 -292
- package/dist/runtime/ephemeral.d.ts +0 -37
- package/dist/runtime/ephemeral.js +0 -84
- package/dist/runtime/exit-codes.d.ts +0 -9
- package/dist/runtime/exit-codes.js +0 -43
- package/dist/runtime/index.d.ts +0 -8
- package/dist/runtime/index.js +0 -6
- package/dist/runtime/launcher.d.ts +0 -81
- package/dist/runtime/launcher.js +0 -243
- package/dist/runtime/progress.d.ts +0 -10
- package/dist/runtime/progress.js +0 -8
- package/dist/runtime/version.d.ts +0 -6
- package/dist/runtime/version.js +0 -27
- /package/dist/{runtime/baseline.d.ts → baseline.d.ts} +0 -0
package/dist/runtime/launcher.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { delimiter, dirname, join, resolve } from "node:path";
|
|
5
|
-
import { PROTOCOL_VERSION } from "@nylorun/agents";
|
|
6
|
-
import { CliError } from "../errors.js";
|
|
7
|
-
import { exitCodeForLauncherError, } from "./exit-codes.js";
|
|
8
|
-
import { renderProgress } from "./progress.js";
|
|
9
|
-
import { runtimeVersion } from "./version.js";
|
|
10
|
-
/** The launcher command `@nylorun/runtime` installs (npm bin). */
|
|
11
|
-
export const LAUNCHER_BIN = "nylorun-runtime";
|
|
12
|
-
/** The `nylorun-runtime --json` contract this CLI speaks (core LAUNCHER_PROTOCOL). */
|
|
13
|
-
const LAUNCHER_PROTOCOL = 1;
|
|
14
|
-
/** Resolve NYLORUN_HOME, an explicit home, or `~/.nylorun`. */
|
|
15
|
-
export function resolveHome(home) {
|
|
16
|
-
if (home !== undefined && home.trim() !== "")
|
|
17
|
-
return resolve(home);
|
|
18
|
-
const fromEnv = process.env.NYLORUN_HOME?.trim();
|
|
19
|
-
if (fromEnv)
|
|
20
|
-
return resolve(fromEnv);
|
|
21
|
-
return resolve(join(homedir(), ".nylorun"));
|
|
22
|
-
}
|
|
23
|
-
/** Install command shown whenever the Runtime is missing or incompatible. */
|
|
24
|
-
export function runtimeInstallCommand() {
|
|
25
|
-
return `npm install --global @nylorun/runtime@${runtimeVersion()}`;
|
|
26
|
-
}
|
|
27
|
-
/** Find `name` on PATH (with PATHEXT on Windows). */
|
|
28
|
-
export function findOnPath(name, env) {
|
|
29
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(delimiter).filter(Boolean);
|
|
30
|
-
const extensions = process.platform === "win32"
|
|
31
|
-
? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean)
|
|
32
|
-
: [""];
|
|
33
|
-
for (const dir of dirs) {
|
|
34
|
-
for (const extension of extensions) {
|
|
35
|
-
const candidate = join(dir, `${name}${extension.toLowerCase()}`);
|
|
36
|
-
try {
|
|
37
|
-
if (statSync(candidate).isFile())
|
|
38
|
-
return candidate;
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
/* not here */
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return undefined;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* npm links a bin to the package's JS file: a symlink on POSIX, a `.cmd` shim
|
|
49
|
-
* next to the package on Windows. Running that file on this Node avoids
|
|
50
|
-
* spawning `.cmd` shims, which Node refuses without a shell.
|
|
51
|
-
*/
|
|
52
|
-
function launcherScript(bin) {
|
|
53
|
-
if (process.platform !== "win32") {
|
|
54
|
-
const real = realpathSync(bin);
|
|
55
|
-
return real.endsWith(".js") ? real : undefined;
|
|
56
|
-
}
|
|
57
|
-
const dir = dirname(bin);
|
|
58
|
-
const main = join("@nylorun", "runtime", "dist", "launcher", "main.js");
|
|
59
|
-
// Global prefix (`<prefix>/nylorun-runtime.cmd`) or project `.bin`.
|
|
60
|
-
for (const candidate of [
|
|
61
|
-
join(dir, "node_modules", main),
|
|
62
|
-
join(dir, "..", main),
|
|
63
|
-
]) {
|
|
64
|
-
if (existsSync(candidate))
|
|
65
|
-
return candidate;
|
|
66
|
-
}
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Find the installed Runtime's launcher on PATH and check it speaks this CLI's
|
|
71
|
-
* launcher and Host protocols. Never downloads or installs anything: a missing
|
|
72
|
-
* Runtime is a prerequisite error that names the install command.
|
|
73
|
-
*/
|
|
74
|
-
export async function launcher(home, options = {}) {
|
|
75
|
-
const resolvedHome = resolve(home);
|
|
76
|
-
const env = options.env ?? process.env;
|
|
77
|
-
const bin = findOnPath(LAUNCHER_BIN, env);
|
|
78
|
-
if (!bin) {
|
|
79
|
-
throw new CliError(`The Nylorun Runtime is not installed (no "${LAUNCHER_BIN}" on PATH).\nInstall it, then retry:\n ${runtimeInstallCommand()}`, 1);
|
|
80
|
-
}
|
|
81
|
-
const probe = await invokeLauncher(bin, resolvedHome, ["version"], { env, renderProgress: false }, false);
|
|
82
|
-
throwOnLauncherFailure(probe);
|
|
83
|
-
const info = probe.result ?? {};
|
|
84
|
-
const version = typeof info.runtimeVersion === "string" ? info.runtimeVersion : "unknown";
|
|
85
|
-
const protocol = info.protocol;
|
|
86
|
-
const hostCompatible = typeof protocol?.min === "number" &&
|
|
87
|
-
typeof protocol.max === "number" &&
|
|
88
|
-
protocol.min <= PROTOCOL_VERSION &&
|
|
89
|
-
PROTOCOL_VERSION <= protocol.max;
|
|
90
|
-
if (info.launcherProtocol !== LAUNCHER_PROTOCOL || !hostCompatible) {
|
|
91
|
-
throw new CliError(`The installed Nylorun Runtime ${version} (${bin}) is not compatible with this CLI.\nInstall a compatible Runtime, then retry:\n ${runtimeInstallCommand()}`, 1);
|
|
92
|
-
}
|
|
93
|
-
return createHandle(resolvedHome, {
|
|
94
|
-
bin,
|
|
95
|
-
version,
|
|
96
|
-
node: typeof info.node === "string" ? info.node : "unknown",
|
|
97
|
-
}, env);
|
|
98
|
-
}
|
|
99
|
-
function createHandle(home, runtime, defaultEnv) {
|
|
100
|
-
const run = (args, options = {}, streaming) => invokeLauncher(runtime.bin, home, args, {
|
|
101
|
-
...options,
|
|
102
|
-
env: options.env ?? defaultEnv,
|
|
103
|
-
}, streaming);
|
|
104
|
-
return {
|
|
105
|
-
home,
|
|
106
|
-
runtime,
|
|
107
|
-
invoke: (args, options) => run(args, options, false),
|
|
108
|
-
invokeStreaming: (args, options) => run(args, options, true),
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
/** Quote one argument for cmd.exe (only used for non-npm `.cmd` shims). */
|
|
112
|
-
function quoteForCmd(value) {
|
|
113
|
-
return `"${value.replace(/"/g, '""')}"`;
|
|
114
|
-
}
|
|
115
|
-
function spawnLauncher(bin, args, env) {
|
|
116
|
-
const options = {
|
|
117
|
-
env: { ...env },
|
|
118
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
119
|
-
};
|
|
120
|
-
const script = launcherScript(bin);
|
|
121
|
-
if (script)
|
|
122
|
-
return spawn(process.execPath, [script, ...args], options);
|
|
123
|
-
if (process.platform === "win32" && /\.(cmd|bat)$/i.test(bin)) {
|
|
124
|
-
// Windows runs .cmd files only through cmd.exe, which needs quoting.
|
|
125
|
-
return spawn(quoteForCmd(bin), args.map(quoteForCmd), {
|
|
126
|
-
...options,
|
|
127
|
-
shell: true,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
return spawn(bin, args, options);
|
|
131
|
-
}
|
|
132
|
-
async function invokeLauncher(bin, home, args, options, _streaming) {
|
|
133
|
-
const childArgs = ["--json", "--home", home, ...args];
|
|
134
|
-
const child = spawnLauncher(bin, childArgs, options.env);
|
|
135
|
-
const events = [];
|
|
136
|
-
let result;
|
|
137
|
-
let error;
|
|
138
|
-
let stdout = "";
|
|
139
|
-
let stderr = "";
|
|
140
|
-
let lineBuffer = "";
|
|
141
|
-
const handleLine = (line) => {
|
|
142
|
-
const trimmed = line.trim();
|
|
143
|
-
if (!trimmed)
|
|
144
|
-
return;
|
|
145
|
-
let event;
|
|
146
|
-
try {
|
|
147
|
-
event = JSON.parse(trimmed);
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
events.push(event);
|
|
153
|
-
options.onEvent?.(event);
|
|
154
|
-
if (event.type === "progress" && options.renderProgress !== false) {
|
|
155
|
-
renderProgress(event);
|
|
156
|
-
}
|
|
157
|
-
if (event.type === "result") {
|
|
158
|
-
const { type: _t, ...fields } = event;
|
|
159
|
-
result = fields;
|
|
160
|
-
}
|
|
161
|
-
if (event.type === "error") {
|
|
162
|
-
error = {
|
|
163
|
-
code: event.code,
|
|
164
|
-
message: event.message,
|
|
165
|
-
remedy: event.remedy,
|
|
166
|
-
...(event.details !== undefined ? { details: event.details } : {}),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
if (event.type === "log") {
|
|
170
|
-
const prefix = event.source === "tenant" && event.tenantId
|
|
171
|
-
? `[${event.tenantId}] `
|
|
172
|
-
: "";
|
|
173
|
-
process.stdout.write(`${prefix}${event.line}\n`);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
child.stdout?.on("data", (chunk) => {
|
|
177
|
-
const text = chunk.toString("utf8");
|
|
178
|
-
stdout += text;
|
|
179
|
-
lineBuffer += text;
|
|
180
|
-
const parts = lineBuffer.split("\n");
|
|
181
|
-
lineBuffer = parts.pop() ?? "";
|
|
182
|
-
for (const part of parts)
|
|
183
|
-
handleLine(part);
|
|
184
|
-
});
|
|
185
|
-
child.stderr?.on("data", (chunk) => {
|
|
186
|
-
stderr += chunk.toString("utf8");
|
|
187
|
-
});
|
|
188
|
-
const abort = () => {
|
|
189
|
-
try {
|
|
190
|
-
child.kill("SIGTERM");
|
|
191
|
-
}
|
|
192
|
-
catch {
|
|
193
|
-
/* ignore */
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
if (options.signal) {
|
|
197
|
-
if (options.signal.aborted)
|
|
198
|
-
abort();
|
|
199
|
-
else
|
|
200
|
-
options.signal.addEventListener("abort", abort, { once: true });
|
|
201
|
-
}
|
|
202
|
-
const exitCode = await waitForExit(child);
|
|
203
|
-
if (lineBuffer.trim())
|
|
204
|
-
handleLine(lineBuffer);
|
|
205
|
-
if (options.signal) {
|
|
206
|
-
options.signal.removeEventListener("abort", abort);
|
|
207
|
-
}
|
|
208
|
-
return {
|
|
209
|
-
events,
|
|
210
|
-
...(result ? { result } : {}),
|
|
211
|
-
...(error ? { error } : {}),
|
|
212
|
-
exitCode,
|
|
213
|
-
stdout,
|
|
214
|
-
stderr,
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
function waitForExit(child) {
|
|
218
|
-
return new Promise((resolvePromise, reject) => {
|
|
219
|
-
child.once("error", reject);
|
|
220
|
-
child.once("exit", (code, signal) => {
|
|
221
|
-
if (code !== null)
|
|
222
|
-
resolvePromise(code);
|
|
223
|
-
else
|
|
224
|
-
resolvePromise(signal === "SIGINT" ? 130 : signal === "SIGTERM" ? 143 : 1);
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Throw CliError with the Tenants-era exit code for a failed launcher invoke.
|
|
230
|
-
*/
|
|
231
|
-
export function throwOnLauncherFailure(outcome) {
|
|
232
|
-
if (outcome.exitCode === 0)
|
|
233
|
-
return;
|
|
234
|
-
if (outcome.exitCode === 2) {
|
|
235
|
-
throw new CliError(outcome.error?.message ??
|
|
236
|
-
(outcome.stderr.trim() || "Invalid runtime arguments."), 2);
|
|
237
|
-
}
|
|
238
|
-
const code = outcome.error?.code;
|
|
239
|
-
const message = outcome.error
|
|
240
|
-
? `${outcome.error.message}${outcome.error.remedy ? `\n${outcome.error.remedy}` : ""}`
|
|
241
|
-
: outcome.stderr.trim() || `Runtime launcher failed (exit ${outcome.exitCode}).`;
|
|
242
|
-
throw new CliError(message, exitCodeForLauncherError(code));
|
|
243
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Render launcher progress the way the Tenants-era CLI did: phase name on
|
|
3
|
-
* stderr.
|
|
4
|
-
*/
|
|
5
|
-
export type ProgressEvent = {
|
|
6
|
-
type: "progress";
|
|
7
|
-
phase: "start" | "stop" | "wait";
|
|
8
|
-
message?: string;
|
|
9
|
-
};
|
|
10
|
-
export declare function renderProgress(event: ProgressEvent, write?: (line: string) => void): void;
|
package/dist/runtime/progress.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Recommended Runtime version from `cli/package.json` `nylorun.runtime` (D7):
|
|
3
|
-
* the version named in install instructions. Compatibility itself is checked
|
|
4
|
-
* by launcher and Host protocol, not by an exact match.
|
|
5
|
-
*/
|
|
6
|
-
export declare function runtimeVersion(): string;
|
package/dist/runtime/version.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { CliError } from "../errors.js";
|
|
5
|
-
function cliPackageJsonPath() {
|
|
6
|
-
// src/runtime/*.ts and dist/runtime/*.js both sit two levels below cli/.
|
|
7
|
-
return join(dirname(fileURLToPath(import.meta.url)), "..", "..", "package.json");
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Recommended Runtime version from `cli/package.json` `nylorun.runtime` (D7):
|
|
11
|
-
* the version named in install instructions. Compatibility itself is checked
|
|
12
|
-
* by launcher and Host protocol, not by an exact match.
|
|
13
|
-
*/
|
|
14
|
-
export function runtimeVersion() {
|
|
15
|
-
let raw;
|
|
16
|
-
try {
|
|
17
|
-
raw = JSON.parse(readFileSync(cliPackageJsonPath(), "utf8"));
|
|
18
|
-
}
|
|
19
|
-
catch (error) {
|
|
20
|
-
throw new CliError(`Cannot read CLI package.json: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
21
|
-
}
|
|
22
|
-
const version = raw?.nylorun?.runtime;
|
|
23
|
-
if (typeof version !== "string" || version.trim() === "") {
|
|
24
|
-
throw new CliError('cli/package.json is missing "nylorun.runtime" (the recommended Runtime version).', 1);
|
|
25
|
-
}
|
|
26
|
-
return version;
|
|
27
|
-
}
|
|
File without changes
|