node-command 2.0.2 → 2.0.4
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/bin/nc.mjs +1289 -266
- package/lib/diagnostics-bundle.mjs +38 -10
- package/lib/setup.mjs +863 -46
- package/package.json +11 -16
|
@@ -17,7 +17,7 @@ import os from 'node:os';
|
|
|
17
17
|
import path from 'node:path';
|
|
18
18
|
import zlib from 'node:zlib';
|
|
19
19
|
import child_process from 'node:child_process';
|
|
20
|
-
import { candidateInstallRoots, decideInstallMode, getNcRootForMode, probeInstallRoot } from './setup.mjs';
|
|
20
|
+
import { candidateInstallRoots, decideInstallMode, getNcRootForMode, probeInstallRoot, resolveExecutable } from './setup.mjs';
|
|
21
21
|
|
|
22
22
|
export const CLI_DIAGNOSTICS_VERSION = '1.0.0';
|
|
23
23
|
export const CLI_DIAGNOSTICS_MAX_LOG_BYTES = 65536;
|
|
@@ -121,13 +121,22 @@ export function parseCliDiagnosticsArgs(argv = []) {
|
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* Best-effort service status for the platform agent units. Never throws.
|
|
124
|
+
* Executables resolve from the same absolute allowlist used by privileged
|
|
125
|
+
* paths, so the caller's PATH cannot redirect a diagnostic probe.
|
|
124
126
|
* @param {string} [platform]
|
|
127
|
+
* @param {{ run?: (cmd: string, args: string[], options: object) => any, resolve?: typeof resolveExecutable }} [options]
|
|
125
128
|
*/
|
|
126
|
-
export function probeCliServiceStatus(platform = os.platform()) {
|
|
129
|
+
export function probeCliServiceStatus(platform = os.platform(), { run = child_process.execFileSync, resolve = resolveExecutable } = {}) {
|
|
127
130
|
const checks = [];
|
|
128
|
-
const tryRun = (
|
|
131
|
+
const tryRun = (name, args) => {
|
|
132
|
+
let cmd;
|
|
129
133
|
try {
|
|
130
|
-
|
|
134
|
+
cmd = resolve(name, { platform });
|
|
135
|
+
} catch {
|
|
136
|
+
return { ok: false, stdout: '' };
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const out = run(cmd, args, {
|
|
131
140
|
timeout: 8000,
|
|
132
141
|
stdio: ['ignore', 'pipe', 'pipe']
|
|
133
142
|
});
|
|
@@ -549,17 +558,36 @@ export function runCliDiagnostics(argv = [], { ncRoot = null, env = process.env,
|
|
|
549
558
|
writeFile ||
|
|
550
559
|
((f, d) => {
|
|
551
560
|
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
552
|
-
|
|
561
|
+
// Never follow an existing file or symlink at the predictable output
|
|
562
|
+
// name: O_EXCL makes a pre-created path fail closed instead of
|
|
563
|
+
// truncating its target.
|
|
564
|
+
const fd = fs.openSync(
|
|
565
|
+
f,
|
|
566
|
+
fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | (fs.constants.O_NOFOLLOW || 0),
|
|
567
|
+
0o600
|
|
568
|
+
);
|
|
569
|
+
try {
|
|
570
|
+
fs.writeFileSync(fd, d);
|
|
571
|
+
} catch (err) {
|
|
572
|
+
try {
|
|
573
|
+
fs.unlinkSync(f);
|
|
574
|
+
} catch {}
|
|
575
|
+
throw err;
|
|
576
|
+
} finally {
|
|
577
|
+
fs.closeSync(fd);
|
|
578
|
+
}
|
|
553
579
|
});
|
|
554
580
|
try {
|
|
555
581
|
writer(outPath, archive);
|
|
556
582
|
} catch (err) {
|
|
557
583
|
const hint =
|
|
558
|
-
err?.code === '
|
|
559
|
-
? 'Suggested action: choose a
|
|
560
|
-
: err?.code === '
|
|
561
|
-
? 'Suggested action:
|
|
562
|
-
:
|
|
584
|
+
err?.code === 'EEXIST'
|
|
585
|
+
? 'Suggested action: the output file already exists and is never overwritten; choose a different --output path and re-run.'
|
|
586
|
+
: err?.code === 'EACCES'
|
|
587
|
+
? 'Suggested action: choose a writable --output path or re-run with permission to write there.'
|
|
588
|
+
: err?.code === 'ENOSPC'
|
|
589
|
+
? 'Suggested action: free disk space and re-run.'
|
|
590
|
+
: 'Suggested action: choose a different --output path and re-run.';
|
|
563
591
|
return {
|
|
564
592
|
handled: true,
|
|
565
593
|
ok: false,
|