@williamthorsen/nmr 2.0.1 → 2.0.3
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/.meta/changelog.json +107 -0
- package/.readyup/kits/default.js +41 -5
- package/.readyup/manifest.json +14 -9
- package/CHANGELOG.md +30 -0
- package/README.md +2 -8
- package/dist/esm/{check-cache-build-output.d.ts → check-cache/check-cache-build-output.d.ts} +1 -1
- package/dist/esm/{check-cache-build-output.js → check-cache/check-cache-build-output.js} +6 -6
- package/dist/esm/{check-cache-delegation.d.ts → check-cache/check-cache-delegation.d.ts} +3 -3
- package/dist/esm/{check-cache-delegation.js → check-cache/check-cache-delegation.js} +2 -2
- package/dist/esm/{check-cache-entries.js → check-cache/check-cache-entries.js} +1 -1
- package/dist/esm/{check-cache-gate.d.ts → check-cache/check-cache-gate.d.ts} +5 -4
- package/dist/esm/{check-cache-gate.js → check-cache/check-cache-gate.js} +10 -10
- package/dist/esm/{check-cache-key.d.ts → check-cache/check-cache-key.d.ts} +1 -1
- package/dist/esm/{check-cache-record.d.ts → check-cache/check-cache-record.d.ts} +6 -5
- package/dist/esm/{check-cache-record.js → check-cache/check-cache-record.js} +7 -6
- package/dist/esm/{check-cache.d.ts → check-cache/check-cache.d.ts} +10 -2
- package/dist/esm/{check-cache.js → check-cache/check-cache.js} +7 -4
- package/dist/esm/{config-check-cache.d.ts → check-cache/config-check-cache.d.ts} +1 -1
- package/dist/esm/{config-check-cache.js → check-cache/config-check-cache.js} +4 -4
- package/dist/esm/{pass-manifest.d.ts → check-cache/pass-manifest.d.ts} +1 -1
- package/dist/esm/{pass-manifest.js → check-cache/pass-manifest.js} +1 -1
- package/dist/esm/{recording.js → check-cache/recording.js} +2 -2
- package/dist/esm/{replay-assembly.d.ts → check-cache/replay-assembly.d.ts} +1 -1
- package/dist/esm/{replay-assembly.js → check-cache/replay-assembly.js} +2 -2
- package/dist/esm/child-env.d.ts +1 -1
- package/dist/esm/child-env.js +2 -2
- package/dist/esm/commands/actionlint.d.ts +2 -7
- package/dist/esm/commands/actionlint.js +5 -11
- package/dist/esm/commands/build-output.d.ts +2 -1
- package/dist/esm/commands/clean.js +1 -1
- package/dist/esm/commands/fmt-cache.js +3 -2
- package/dist/esm/commands/fmt.d.ts +6 -13
- package/dist/esm/commands/fmt.js +47 -30
- package/dist/esm/commands/node-pin.d.ts +15 -5
- package/dist/esm/commands/node-pin.js +43 -10
- package/dist/esm/commands/package-manifest.d.ts +28 -0
- package/dist/esm/commands/package-manifest.js +32 -0
- package/dist/esm/commands/run-vitest.js +21 -20
- package/dist/esm/commands/shellcheck.d.ts +2 -7
- package/dist/esm/commands/shellcheck.js +3 -11
- package/dist/esm/commands/spawn-inherited.d.ts +21 -0
- package/dist/esm/commands/spawn-inherited.js +11 -0
- package/dist/esm/commands/taze.d.ts +6 -6
- package/dist/esm/commands/taze.js +3 -7
- package/dist/esm/config-validation.js +1 -1
- package/dist/esm/config.js +3 -12
- package/dist/esm/{delegate-host.d.ts → delegation/delegate-host.d.ts} +3 -3
- package/dist/esm/{delegate-host.js → delegation/delegate-host.js} +9 -8
- package/dist/esm/{delegation-target.js → delegation/delegation-target.js} +1 -1
- package/dist/esm/{remote-probe.js → delegation/remote-probe.js} +2 -2
- package/dist/esm/{remote-run.js → delegation/remote-run.js} +5 -5
- package/dist/esm/{remote-session.js → delegation/remote-session.js} +1 -1
- package/dist/esm/{user-config.js → delegation/user-config.js} +4 -13
- package/dist/esm/env-switch.d.ts +25 -0
- package/dist/esm/env-switch.js +26 -0
- package/dist/esm/fan-out.d.ts +4 -1
- package/dist/esm/fan-out.js +1 -3
- package/dist/esm/help.js +1 -1
- package/dist/esm/helpers/filter-selection.d.ts +2 -0
- package/dist/esm/helpers/importConfigDefault.d.ts +7 -0
- package/dist/esm/helpers/importConfigDefault.js +45 -0
- package/dist/esm/invocation.d.ts +7 -3
- package/dist/esm/machine-lock.js +2 -1
- package/dist/esm/route.d.ts +6 -0
- package/dist/esm/route.js +15 -2
- package/dist/esm/run-chain.d.ts +1 -1
- package/dist/esm/run-chain.js +1 -1
- package/dist/esm/runCli.d.ts +9 -0
- package/dist/esm/runCli.js +24 -9
- package/dist/esm/runner.d.ts +2 -0
- package/dist/esm/runner.js +1 -1
- package/dist/esm/verdict.d.ts +1 -1
- package/docs/check-cache.md +7 -7
- package/docs/delegate.md +2 -2
- package/docs/machine-lock.md +4 -4
- package/docs/scripts.md +4 -0
- package/docs/upgrades.md +9 -1
- package/docs/utilities.md +4 -2
- package/package.json +2 -2
- /package/dist/esm/{check-cache-entries.d.ts → check-cache/check-cache-entries.d.ts} +0 -0
- /package/dist/esm/{check-cache-key.js → check-cache/check-cache-key.js} +0 -0
- /package/dist/esm/{recording.d.ts → check-cache/recording.d.ts} +0 -0
- /package/dist/esm/{delegation-target.d.ts → delegation/delegation-target.d.ts} +0 -0
- /package/dist/esm/{remote-host-session.d.ts → delegation/remote-host-session.d.ts} +0 -0
- /package/dist/esm/{remote-host-session.js → delegation/remote-host-session.js} +0 -0
- /package/dist/esm/{remote-probe-host.d.ts → delegation/remote-probe-host.d.ts} +0 -0
- /package/dist/esm/{remote-probe-host.js → delegation/remote-probe-host.js} +0 -0
- /package/dist/esm/{remote-probe.d.ts → delegation/remote-probe.d.ts} +0 -0
- /package/dist/esm/{remote-run.d.ts → delegation/remote-run.d.ts} +0 -0
- /package/dist/esm/{remote-session.d.ts → delegation/remote-session.d.ts} +0 -0
- /package/dist/esm/{remote-snapshot.d.ts → delegation/remote-snapshot.d.ts} +0 -0
- /package/dist/esm/{remote-snapshot.js → delegation/remote-snapshot.js} +0 -0
- /package/dist/esm/{user-config.d.ts → delegation/user-config.d.ts} +0 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
1
|
import fs from 'node:fs';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import { runGit, UserError } from '@williamthorsen/nmr-core';
|
|
5
|
-
import {
|
|
4
|
+
import { resolveInheritedExitCode, spawnInherited } from "./spawn-inherited.js";
|
|
6
5
|
import { ensureTool, resolveToolCacheRoots } from "./workflow-tools.js";
|
|
7
6
|
export async function runShellcheck(monorepoRoot, args, options = {}) {
|
|
8
7
|
const shellcheckArgs = args.length > 0 ? [...args] : listPresentScripts(monorepoRoot, options.listFiles);
|
|
@@ -13,14 +12,11 @@ export async function runShellcheck(monorepoRoot, args, options = {}) {
|
|
|
13
12
|
const cacheRoots = options.cacheRoots ?? resolveToolCacheRoots(monorepoRoot);
|
|
14
13
|
const ensure = options.ensure ?? ((tool, roots) => ensureTool(tool, { cacheRoots: roots }));
|
|
15
14
|
const shellcheckPath = await ensure('shellcheck', cacheRoots);
|
|
16
|
-
const outcome = (options.spawn ?? spawnInherited)(shellcheckPath, shellcheckArgs, monorepoRoot);
|
|
15
|
+
const outcome = (options.spawn ?? spawnInherited)(shellcheckPath, shellcheckArgs, { cwd: monorepoRoot });
|
|
17
16
|
if (outcome.error !== undefined) {
|
|
18
17
|
throw new UserError(`Cannot run shellcheck: ${outcome.error.message}`, { cause: outcome.error });
|
|
19
18
|
}
|
|
20
|
-
|
|
21
|
-
return describeSignalExitCode(outcome.signal);
|
|
22
|
-
}
|
|
23
|
-
return outcome.status ?? 1;
|
|
19
|
+
return resolveInheritedExitCode(outcome);
|
|
24
20
|
}
|
|
25
21
|
export function listTrackedScripts(monorepoRoot) {
|
|
26
22
|
const result = runGit(['ls-files', '-z', '--', '*.sh'], monorepoRoot);
|
|
@@ -32,7 +28,3 @@ export function listTrackedScripts(monorepoRoot) {
|
|
|
32
28
|
function listPresentScripts(monorepoRoot, listFiles = listTrackedScripts) {
|
|
33
29
|
return listFiles(monorepoRoot).filter((file) => fs.existsSync(path.join(monorepoRoot, file)));
|
|
34
30
|
}
|
|
35
|
-
function spawnInherited(file, args, cwd) {
|
|
36
|
-
const result = spawnSync(file, args, { cwd, stdio: 'inherit' });
|
|
37
|
-
return { error: result.error, signal: result.signal, status: result.status };
|
|
38
|
-
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** How a program spawned on the caller's stdio ended. */
|
|
2
|
+
export interface InheritedOutcome {
|
|
3
|
+
error?: Error | undefined;
|
|
4
|
+
signal: NodeJS.Signals | null;
|
|
5
|
+
status: number | null;
|
|
6
|
+
}
|
|
7
|
+
export interface SpawnInheritedOptions {
|
|
8
|
+
/** Directory in which the program runs. Defaults to the current one. */
|
|
9
|
+
cwd?: string;
|
|
10
|
+
/** Environment for the program. Defaults to `process.env`. */
|
|
11
|
+
env?: NodeJS.ProcessEnv;
|
|
12
|
+
}
|
|
13
|
+
/** A function that runs a program on the caller's stdio, the shape of each command's injectable spawn. */
|
|
14
|
+
export type SpawnInherited = typeof spawnInherited;
|
|
15
|
+
/** Returns the exit code that reports how the program ended: the shell's code for a death by signal, else its status. */
|
|
16
|
+
export declare function resolveInheritedExitCode({ signal, status }: Pick<InheritedOutcome, 'signal' | 'status'>): number;
|
|
17
|
+
/**
|
|
18
|
+
* Runs a program on the caller's stdio, so that it sees the caller's terminal: It colors its output, renders
|
|
19
|
+
* progress, and reads input as it would when run directly.
|
|
20
|
+
*/
|
|
21
|
+
export declare function spawnInherited(file: string, args: readonly string[], options?: SpawnInheritedOptions): InheritedOutcome;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { describeSignalExitCode } from "../child-process.js";
|
|
3
|
+
export function resolveInheritedExitCode({ signal, status }) {
|
|
4
|
+
if (signal !== null)
|
|
5
|
+
return describeSignalExitCode(signal);
|
|
6
|
+
return status ?? 1;
|
|
7
|
+
}
|
|
8
|
+
export function spawnInherited(file, args, options = {}) {
|
|
9
|
+
const result = spawnSync(file, args, { cwd: options.cwd, env: options.env, stdio: 'inherit' });
|
|
10
|
+
return { error: result.error, signal: result.signal, status: result.status };
|
|
11
|
+
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
2
|
import { type OutputStyle } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { type CheckNodePinOptions } from './node-pin.js';
|
|
4
|
-
|
|
5
|
-
status: number | null;
|
|
6
|
-
error?: Error | undefined;
|
|
7
|
-
}
|
|
4
|
+
import { type SpawnInherited } from './spawn-inherited.js';
|
|
8
5
|
export interface RunTazeOptions {
|
|
9
6
|
/** Checks the `.tool-versions` Node pin in a directory. Injected by tests. */
|
|
10
7
|
checkNodePin?: (dir: string, options: CheckNodePinOptions) => Promise<void>;
|
|
@@ -12,8 +9,11 @@ export interface RunTazeOptions {
|
|
|
12
9
|
loadConfig?: (cwd: string) => Promise<unknown>;
|
|
13
10
|
/** Resolves the absolute path of taze's CLI entry. Injected by tests. */
|
|
14
11
|
resolveCliPath?: () => string;
|
|
15
|
-
/**
|
|
16
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Runs the CLI on the caller's stdio, so that taze's progress rendering, cursor restore, and `--interactive` mode
|
|
14
|
+
* see the caller's TTY. Injected by tests.
|
|
15
|
+
*/
|
|
16
|
+
spawn?: SpawnInherited;
|
|
17
17
|
/** Stream that error output and pass headings are written to. Defaults to `process.stderr`. */
|
|
18
18
|
stderr?: Writable;
|
|
19
19
|
/** Style of `stderr`, in which the Node pin check reports. Defaults to `'plain'`. */
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import process from 'node:process';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
@@ -7,6 +6,7 @@ import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
|
7
6
|
import { NMR_TAZE_BIN } from "../bins.js";
|
|
8
7
|
import { loadPackageMaturityPeriod } from "./load-package-maturity-period.js";
|
|
9
8
|
import { checkNodePin as checkNodePinDefault } from "./node-pin.js";
|
|
9
|
+
import { resolveInheritedExitCode, spawnInherited } from "./spawn-inherited.js";
|
|
10
10
|
import { isSilent, readFlag } from "./taze-args.js";
|
|
11
11
|
import { planTazePasses } from "./taze-passes.js";
|
|
12
12
|
const TAZE_CLI_SPECIFIER = 'taze/cli';
|
|
@@ -17,7 +17,7 @@ const NODE_PIN_SKIP_FLAGS = ['--no-node-version', '--help', '-h', '--version', '
|
|
|
17
17
|
export async function runTaze(args, options = {}) {
|
|
18
18
|
const stderr = options.stderr ?? process.stderr;
|
|
19
19
|
const resolveCliPath = options.resolveCliPath ?? resolveTazeCliPath;
|
|
20
|
-
const spawn = options.spawn ??
|
|
20
|
+
const spawn = options.spawn ?? spawnInherited;
|
|
21
21
|
const loadConfig = options.loadConfig ?? loadPackageMaturityPeriod;
|
|
22
22
|
let cliPath;
|
|
23
23
|
try {
|
|
@@ -59,7 +59,7 @@ export async function runTaze(args, options = {}) {
|
|
|
59
59
|
reportError(NMR_TAZE_BIN, `Failed to run taze: ${outcome.error.message}`, stderr);
|
|
60
60
|
return 1;
|
|
61
61
|
}
|
|
62
|
-
const status = outcome
|
|
62
|
+
const status = resolveInheritedExitCode(outcome);
|
|
63
63
|
if (exitCode === 0)
|
|
64
64
|
exitCode = status;
|
|
65
65
|
}
|
|
@@ -74,7 +74,3 @@ function composeRequestTimeoutArgs(args) {
|
|
|
74
74
|
function resolveConfigDir(args) {
|
|
75
75
|
return path.resolve(readFlag(args, ['--cwd', '-C'])?.value ?? '.');
|
|
76
76
|
}
|
|
77
|
-
function spawnNode(nodePath, argv) {
|
|
78
|
-
const result = spawnSync(nodePath, argv, { stdio: 'inherit' });
|
|
79
|
-
return { status: result.status, error: result.error };
|
|
80
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isRecord, UserError } from '@williamthorsen/nmr-core';
|
|
2
|
-
import { assertResolvableCheckCacheCommands } from "./config-check-cache.js";
|
|
2
|
+
import { assertResolvableCheckCacheCommands } from "./check-cache/config-check-cache.js";
|
|
3
3
|
import { findUnexpressibleToken } from "./steps.js";
|
|
4
4
|
import { formatVerbosityRejection, isCommandVerbosity } from "./verbosity.js";
|
|
5
5
|
export const CONFIG_TIERS = {
|
package/dist/esm/config.js
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
1
|
import { existsSync } from 'node:fs';
|
|
10
|
-
import {
|
|
11
|
-
import { isRecord, UserError } from '@williamthorsen/nmr-core';
|
|
2
|
+
import { UserError } from '@williamthorsen/nmr-core';
|
|
12
3
|
import { CONFIG_TIERS, validateConfig } from "./config-validation.js";
|
|
13
4
|
import { resolveConfigPath } from "./helpers/config-path.js";
|
|
14
5
|
import { escapeControlCharacters } from "./helpers/escapeControlCharacters.js";
|
|
15
6
|
import { isHookName } from "./helpers/hook-name.js";
|
|
7
|
+
import { importConfigDefault } from "./helpers/importConfigDefault.js";
|
|
16
8
|
import { getDefaultRootScripts, getDefaultWorkspaceScripts } from "./resolve-scripts.js";
|
|
17
9
|
import { describeScript } from "./resolver.js";
|
|
18
10
|
import { readSelfReference, readStepListSelfReference } from "./steps.js";
|
|
@@ -25,8 +17,7 @@ export async function loadConfig(baseDir) {
|
|
|
25
17
|
if (!existsSync(configPath)) {
|
|
26
18
|
return {};
|
|
27
19
|
}
|
|
28
|
-
const
|
|
29
|
-
const loadedConfig = isRecord(importedModule) ? importedModule['default'] : undefined;
|
|
20
|
+
const loadedConfig = await importConfigDefault(configPath);
|
|
30
21
|
return validateConfig(loadedConfig, configPath, baseDir);
|
|
31
22
|
}
|
|
32
23
|
export async function loadRootConfig(monorepoRoot) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type ExecutionTarget, type Invocation, type PhaseResult, type RunCliResult, type RunPlan } from '
|
|
2
|
-
import type { RetainedOutput } from '
|
|
3
|
-
import type { VerdictOutcome } from '
|
|
1
|
+
import { type ExecutionTarget, type Invocation, type PhaseResult, type RunCliResult, type RunPlan } from '../invocation.js';
|
|
2
|
+
import type { RetainedOutput } from '../runner.js';
|
|
3
|
+
import type { VerdictOutcome } from '../verdict.js';
|
|
4
4
|
/** How a run on the host ended, or that the invocation runs here after all. */
|
|
5
5
|
export type HostRunResult = {
|
|
6
6
|
kind: 'here';
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import { Writable } from 'node:stream';
|
|
3
3
|
import { reportError, startTimer } from '@williamthorsen/nmr-core';
|
|
4
|
-
import { NMR_BIN } from "
|
|
5
|
-
import { NO_CACHE_ENV_VAR, resolveRunId, writeDebugNote } from "
|
|
6
|
-
import { buildChildEnv, buildRemoteEnv } from "
|
|
4
|
+
import { NMR_BIN } from "../bins.js";
|
|
5
|
+
import { NO_CACHE_ENV_VAR, resolveRunId, writeDebugNote } from "../check-cache/check-cache.js";
|
|
6
|
+
import { buildChildEnv, buildRemoteEnv } from "../child-env.js";
|
|
7
|
+
import { isEnvSwitchOn } from "../env-switch.js";
|
|
8
|
+
import { createBoundedBuffer } from "../helpers/createBoundedBuffer.js";
|
|
9
|
+
import { USAGE_EXIT_CODE, } from "../invocation.js";
|
|
10
|
+
import { isDelegationFlag } from "../invocation-args.js";
|
|
11
|
+
import { reportVerdict } from "../presentation.js";
|
|
7
12
|
import { resolveDelegationTarget } from "./delegation-target.js";
|
|
8
|
-
import { createBoundedBuffer } from "./helpers/createBoundedBuffer.js";
|
|
9
|
-
import { USAGE_EXIT_CODE, } from "./invocation.js";
|
|
10
|
-
import { isDelegationFlag } from "./invocation-args.js";
|
|
11
|
-
import { reportVerdict } from "./presentation.js";
|
|
12
13
|
import { chooseHost, probeHost } from "./remote-probe.js";
|
|
13
14
|
import { DELEGATE_ENV_VAR, DELEGATE_FLAG, DELEGATE_TO_FLAG, DELEGATION_FAILURE_EXIT_CODE, deriveCheckoutPath, formatMisplacedDelegationWarning, readLastLine, runRemotely, } from "./remote-run.js";
|
|
14
15
|
import { createSnapshot } from "./remote-snapshot.js";
|
|
@@ -46,7 +47,7 @@ export async function runInvocationOnHost(invocation, target) {
|
|
|
46
47
|
format,
|
|
47
48
|
passthrough: parsedArgs.passthrough,
|
|
48
49
|
runId: resolveRunId(env),
|
|
49
|
-
shouldBypassCache: parsedArgs.shouldBypassCache || env
|
|
50
|
+
shouldBypassCache: parsedArgs.shouldBypassCache || isEnvSwitchOn(env, NO_CACHE_ENV_VAR),
|
|
50
51
|
shouldBypassLock: parsedArgs.shouldBypassLock,
|
|
51
52
|
snapshot: undefined,
|
|
52
53
|
styles,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { hasAgentMarker } from "../verbosity.js";
|
|
1
2
|
import { DELEGATE_ENV_VAR, DELEGATE_FLAG, DELEGATE_TO_FLAG } from "./remote-run.js";
|
|
2
3
|
import { formatDisplayPath, resolveUserConfigPath } from "./user-config.js";
|
|
3
|
-
import { hasAgentMarker } from "./verbosity.js";
|
|
4
4
|
export async function resolveDelegationTarget(options) {
|
|
5
5
|
const { command, env, extraAgentEnvVars, flagValue, isFanOut, isOptedOut, isReading } = options;
|
|
6
6
|
const { isRepoOptedOut, readUserConfig, shouldDelegate } = options;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { isRecord } from '@williamthorsen/nmr-core';
|
|
3
|
-
import { quoteForShell } from "
|
|
4
|
-
import { LOCK_DIR_ENV_VAR, LOCK_FILE, STALE_AFTER_MS } from "
|
|
3
|
+
import { quoteForShell } from "../helpers/quoteForShell.js";
|
|
4
|
+
import { LOCK_DIR_ENV_VAR, LOCK_FILE, STALE_AFTER_MS } from "../machine-lock.js";
|
|
5
5
|
import { CHECKOUT_LOCK_PATH } from "./remote-host-session.js";
|
|
6
6
|
import { probeHostLocks } from "./remote-probe-host.js";
|
|
7
7
|
import { DELEGATION_FAILURE_EXIT_CODE, readLastLine, runSsh } from "./remote-run.js";
|
|
@@ -4,11 +4,11 @@ import os from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { GIT_OUTPUT_LIMIT_BYTES, startTimer, STATUS_GLYPHS } from '@williamthorsen/nmr-core';
|
|
7
|
-
import { PASS_MANIFEST_DIR_ENV_VAR, writeDebugNote } from "
|
|
8
|
-
import { createBoundedBuffer } from "
|
|
9
|
-
import { quoteForShell } from "
|
|
10
|
-
import { STALE_AFTER_MS } from "
|
|
11
|
-
import { formatFlagSpelling } from "
|
|
7
|
+
import { PASS_MANIFEST_DIR_ENV_VAR, writeDebugNote } from "../check-cache/check-cache.js";
|
|
8
|
+
import { createBoundedBuffer } from "../helpers/createBoundedBuffer.js";
|
|
9
|
+
import { quoteForShell } from "../helpers/quoteForShell.js";
|
|
10
|
+
import { STALE_AFTER_MS } from "../machine-lock.js";
|
|
11
|
+
import { formatFlagSpelling } from "../nmr-flags.js";
|
|
12
12
|
import { CHECKOUT_LOCK_PATH } from "./remote-host-session.js";
|
|
13
13
|
import { composeSessionScript, createSessionDemultiplexer, formatDelegationWaitingLine } from "./remote-session.js";
|
|
14
14
|
export const DELEGATE_ENV_VAR = 'NMR_DELEGATE';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Writable } from 'node:stream';
|
|
2
2
|
import { isRecord } from '@williamthorsen/nmr-core';
|
|
3
|
-
import { quoteForShell } from "
|
|
3
|
+
import { quoteForShell } from "../helpers/quoteForShell.js";
|
|
4
4
|
import { runHostSession, } from "./remote-host-session.js";
|
|
5
5
|
export function composeSessionScript(options) {
|
|
6
6
|
const { checkoutDir, params } = options;
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
1
|
import { existsSync } from 'node:fs';
|
|
10
2
|
import path from 'node:path';
|
|
11
|
-
import { pathToFileURL } from 'node:url';
|
|
12
3
|
import { isRecord, UserError } from '@williamthorsen/nmr-core';
|
|
13
|
-
import { assertRecognizedKeys } from "
|
|
14
|
-
import {
|
|
4
|
+
import { assertRecognizedKeys } from "../config-validation.js";
|
|
5
|
+
import { importConfigDefault } from "../helpers/importConfigDefault.js";
|
|
6
|
+
import { resolveXdgBaseDir } from "../helpers/resolveXdgBaseDir.js";
|
|
15
7
|
export const DELEGATE_WHEN_VALUES = ['agent', 'always'];
|
|
16
8
|
export function formatDisplayPath(filePath, env) {
|
|
17
9
|
const home = env['HOME'];
|
|
@@ -29,8 +21,7 @@ export async function loadUserConfig(env) {
|
|
|
29
21
|
if (configPath === undefined || !existsSync(configPath)) {
|
|
30
22
|
return undefined;
|
|
31
23
|
}
|
|
32
|
-
const
|
|
33
|
-
const loadedConfig = isRecord(importedModule) ? importedModule['default'] : undefined;
|
|
24
|
+
const loadedConfig = await importConfigDefault(configPath);
|
|
34
25
|
return { config: validateUserConfig(loadedConfig, configPath), path: configPath };
|
|
35
26
|
}
|
|
36
27
|
export function resolveUserConfigPath(env) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The values that an on/off environment switch accepts. An unset or empty variable is off as well, so that a shell
|
|
3
|
+
* that clears a switch keeps working.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ENV_SWITCH_VALUES: readonly ["0", "1"];
|
|
6
|
+
/**
|
|
7
|
+
* Reports whether a switch is on. A value that the switch does not accept reads as off: nmr and `nmr-fmt` reject
|
|
8
|
+
* one at entry, through `readEnvSwitch`, before any command runs.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isEnvSwitchOn(env: NodeJS.ProcessEnv, name: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Reads an on/off switch from the environment. An unrecognized value is returned as an error, since a fallback to
|
|
13
|
+
* off would hide a misspelling, such as `true`, for the life of the shell.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readEnvSwitch(env: NodeJS.ProcessEnv, name: string): EnvSwitchRead;
|
|
16
|
+
/** Reads each named switch, and returns the message naming the first one whose value it does not accept. */
|
|
17
|
+
export declare function readEnvSwitches(env: NodeJS.ProcessEnv, names: readonly string[]): string | undefined;
|
|
18
|
+
/** Whether a switch is on, or the message naming why its value could not be read. */
|
|
19
|
+
export type EnvSwitchRead = {
|
|
20
|
+
ok: true;
|
|
21
|
+
isOn: boolean;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
error: string;
|
|
25
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const ENV_SWITCH_VALUES = ['0', '1'];
|
|
2
|
+
export function isEnvSwitchOn(env, name) {
|
|
3
|
+
return env[name] === '1';
|
|
4
|
+
}
|
|
5
|
+
export function readEnvSwitch(env, name) {
|
|
6
|
+
const rawValue = env[name];
|
|
7
|
+
if (rawValue === undefined || rawValue === '' || rawValue === '0') {
|
|
8
|
+
return { ok: true, isOn: false };
|
|
9
|
+
}
|
|
10
|
+
if (rawValue === '1') {
|
|
11
|
+
return { ok: true, isOn: true };
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
ok: false,
|
|
15
|
+
error: `${name} is \`${rawValue}\`, which is not one of: ${ENV_SWITCH_VALUES.join(', ')} (unset or empty is off)`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function readEnvSwitches(env, names) {
|
|
19
|
+
for (const name of names) {
|
|
20
|
+
const read = readEnvSwitch(env, name);
|
|
21
|
+
if (!read.ok) {
|
|
22
|
+
return read.error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
package/dist/esm/fan-out.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
2
|
import type { ResolvedContext } from './context.js';
|
|
3
|
+
import type { ReadFilterSelection } from './helpers/filter-selection.js';
|
|
3
4
|
import { type RunCliResult } from './invocation.js';
|
|
4
5
|
import type { ParsedArgs } from './nmr-flags.js';
|
|
5
|
-
import {
|
|
6
|
+
import type { RunSteps, RunStepsOptions } from './runner.js';
|
|
6
7
|
import type { Step } from './steps.js';
|
|
7
8
|
/**
|
|
8
9
|
* Composes the delegation that an `-F` or `-R` calls for, or `undefined` when the invocation runs here.
|
|
@@ -52,6 +53,8 @@ export declare function runDelegation(options: {
|
|
|
52
53
|
}>;
|
|
53
54
|
};
|
|
54
55
|
parsedArgs: ParsedArgs;
|
|
56
|
+
readFilterSelection: ReadFilterSelection;
|
|
55
57
|
runOptions: RunStepsOptions;
|
|
58
|
+
runSteps: RunSteps;
|
|
56
59
|
stderr: Writable;
|
|
57
60
|
}): Promise<RunCliResult>;
|
package/dist/esm/fan-out.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { reportError } from '@williamthorsen/nmr-core';
|
|
2
2
|
import { NMR_BIN } from "./bins.js";
|
|
3
|
-
import { readFilterSelection } from "./helpers/filter-selection.js";
|
|
4
3
|
import { findClosestName } from "./helpers/findClosestName.js";
|
|
5
4
|
import { renderQuotedList } from "./helpers/renderQuotedList.js";
|
|
6
5
|
import { RUN_IF_PRESENT_ENV_VAR } from "./invocation.js";
|
|
7
6
|
import { buildRootRegistry, buildWorkspaceRegistry, readPackageJsonScripts } from "./resolver.js";
|
|
8
|
-
import { runSteps } from "./runner.js";
|
|
9
7
|
import { readWorkspacePackageNames, resolveWorkspace } from "./workspace.js";
|
|
10
8
|
const RECURSIVE_REJECTION = '-R/--recursive did not match any workspace:';
|
|
11
9
|
export function composeDelegation(options) {
|
|
@@ -46,7 +44,7 @@ export function listDefinedCommands(context) {
|
|
|
46
44
|
return names;
|
|
47
45
|
}
|
|
48
46
|
export async function runDelegation(options) {
|
|
49
|
-
const { context, delegation, parsedArgs, runOptions, stderr } = options;
|
|
47
|
+
const { context, delegation, parsedArgs, readFilterSelection, runOptions, runSteps, stderr } = options;
|
|
50
48
|
const selection = parsedArgs.filter === undefined ? undefined : readFilterSelection(parsedArgs.filter, context.monorepoRoot);
|
|
51
49
|
const refusal = findEmptySelectionRefusal({ context, parsedArgs, selection });
|
|
52
50
|
if (refusal !== undefined) {
|
package/dist/esm/help.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { DELEGATE_ENV_VAR } from "./delegation/remote-run.js";
|
|
1
2
|
import { isHookName } from "./helpers/hook-name.js";
|
|
2
3
|
import { OUTPUT_STYLE_ENV_VAR } from "./output-style.js";
|
|
3
|
-
import { DELEGATE_ENV_VAR } from "./remote-run.js";
|
|
4
4
|
import { buildRootRegistry, buildWorkspaceRegistry, describeScript, isSelfReferential, readPackageJsonScripts, } from "./resolver.js";
|
|
5
5
|
const LIFECYCLE_SCRIPT_NAMES = new Set([
|
|
6
6
|
'dependencies',
|
|
@@ -32,6 +32,8 @@ export declare function interpretSelectionProbe(probe: SelectionProbe, monorepoR
|
|
|
32
32
|
export declare function interpretDelegateProbe(probe: SelectionProbe): FilterSelection;
|
|
33
33
|
/** What a `-F` pattern selected, as far as pnpm could be asked. `multiple` is two or more packages beside the root. */
|
|
34
34
|
export type FilterSelection = 'empty' | 'multiple' | 'single' | 'unresolved';
|
|
35
|
+
/** Reads what a `-F` pattern selects, as `readFilterSelection` does: the form in which a caller receives it. */
|
|
36
|
+
export type ReadFilterSelection = typeof readFilterSelection;
|
|
35
37
|
/** What a listing proves, `root-only` being the reading that only the delegate can settle. */
|
|
36
38
|
export type ProbeReading = FilterSelection | 'root-only';
|
|
37
39
|
/** The part of a probe's completion from which a selection is read. */
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imports the nmr config file at `configPath` and returns its default export, or `undefined` when the module does not
|
|
3
|
+
* have one. Throws a `UserError` that names the file when it fails to parse or throws while loading, keeping the
|
|
4
|
+
* original error as its `cause`. A parse error's location, when Node reports one, follows the config's path, or
|
|
5
|
+
* precedes the cause's message when it lies in a module that the config imports.
|
|
6
|
+
*/
|
|
7
|
+
export declare function importConfigDefault(configPath: string): Promise<unknown>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { realpathSync } from 'node:fs';
|
|
10
|
+
import { pathToFileURL } from 'node:url';
|
|
11
|
+
import { isRecord, UserError } from '@williamthorsen/nmr-core';
|
|
12
|
+
import { describeError, isError } from '@williamthorsen/toolbelt.errors';
|
|
13
|
+
export async function importConfigDefault(configPath) {
|
|
14
|
+
let importedModule;
|
|
15
|
+
try {
|
|
16
|
+
importedModule = await import(__rewriteRelativeImportExtension(pathToFileURL(configPath).href));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
const location = readSyntaxErrorLocation(error);
|
|
20
|
+
const isInConfig = location !== undefined && isConfigFile(location.file, configPath);
|
|
21
|
+
const configLocation = isInConfig ? `${configPath}:${location.line}` : configPath;
|
|
22
|
+
const foreignLocation = location === undefined || isInConfig ? '' : `${location.file}:${location.line}: `;
|
|
23
|
+
throw new UserError(`Cannot load nmr config at ${configLocation}: ${foreignLocation}${describeError(error)}. Fix the file and rerun.`, { cause: error });
|
|
24
|
+
}
|
|
25
|
+
return isRecord(importedModule) ? importedModule['default'] : undefined;
|
|
26
|
+
}
|
|
27
|
+
function isConfigFile(file, configPath) {
|
|
28
|
+
return file === configPath || file === resolveRealPath(configPath);
|
|
29
|
+
}
|
|
30
|
+
function readSyntaxErrorLocation(error) {
|
|
31
|
+
if (!isError(error) || error.stack === undefined) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const match = /^(?<file>.+):(?<line>\d+)$/u.exec(error.stack.split('\n', 1)[0] ?? '');
|
|
35
|
+
const { file, line } = match?.groups ?? {};
|
|
36
|
+
return file === undefined || line === undefined ? undefined : { file, line };
|
|
37
|
+
}
|
|
38
|
+
function resolveRealPath(filePath) {
|
|
39
|
+
try {
|
|
40
|
+
return realpathSync(filePath);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/esm/invocation.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
2
|
import { type StreamStyles } from '@williamthorsen/nmr-core';
|
|
3
|
-
import type { TreeSnapshot } from './check-cache.js';
|
|
3
|
+
import type { TreeReader, TreeSnapshot } from './check-cache/check-cache.js';
|
|
4
4
|
import type { ResolvedContext } from './context.js';
|
|
5
|
-
import type { DelegationTarget } from './delegation-target.js';
|
|
5
|
+
import type { DelegationTarget } from './delegation/delegation-target.js';
|
|
6
|
+
import type { ReadFilterSelection } from './helpers/filter-selection.js';
|
|
6
7
|
import type { ParsedArgs } from './nmr-flags.js';
|
|
7
8
|
import type { ReportFormat } from './report-format.js';
|
|
8
|
-
import type { RunStepsOptions } from './runner.js';
|
|
9
|
+
import type { RunSteps, RunStepsOptions } from './runner.js';
|
|
9
10
|
import type { Step } from './steps.js';
|
|
10
11
|
import type { CommandVerbosity } from './verbosity.js';
|
|
11
12
|
/** An invocation that reached a command: what it asks for, how it presents itself, and where it runs. */
|
|
@@ -17,6 +18,9 @@ export interface Invocation {
|
|
|
17
18
|
env: NodeJS.ProcessEnv;
|
|
18
19
|
format: ReportFormat;
|
|
19
20
|
parsedArgs: ParsedArgs;
|
|
21
|
+
readFilterSelection: ReadFilterSelection;
|
|
22
|
+
readTree: TreeReader;
|
|
23
|
+
runSteps: RunSteps;
|
|
20
24
|
scope: string;
|
|
21
25
|
shouldUseRoot: boolean;
|
|
22
26
|
stderr: Writable;
|
package/dist/esm/machine-lock.js
CHANGED
|
@@ -5,6 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
7
7
|
import { isRecord, STATUS_GLYPHS } from '@williamthorsen/nmr-core';
|
|
8
|
+
import { isEnvSwitchOn } from "./env-switch.js";
|
|
8
9
|
const RECLAIM_GUARD = 'heavy.lock.reclaim';
|
|
9
10
|
const RECLAIM_GUARD_STALE_AFTER_MS = 10_000;
|
|
10
11
|
export const HEARTBEAT_INTERVAL_MS = 10_000;
|
|
@@ -31,7 +32,7 @@ export const POLL_INTERVAL_MS = 1000;
|
|
|
31
32
|
export const STALE_AFTER_MS = 60_000;
|
|
32
33
|
export async function acquireMachineLock(options) {
|
|
33
34
|
const { command, dir, env, stderr } = options;
|
|
34
|
-
if (env
|
|
35
|
+
if (isEnvSwitchOn(env, NO_LOCK_ENV_VAR)) {
|
|
35
36
|
return createHoldFreeLock({ isChainUnlocked: true, waited: false });
|
|
36
37
|
}
|
|
37
38
|
const lockDir = options.lockDir ?? resolveLockDir({ env, platform: process.platform, uid: process.getuid?.() });
|
package/dist/esm/route.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
2
|
import { type CommandNode } from '@williamthorsen/nmr-core/cli';
|
|
3
|
+
import { type TreeReader } from './check-cache/check-cache.js';
|
|
3
4
|
import type { ResolvedContext } from './context.js';
|
|
5
|
+
import type { ReadFilterSelection } from './helpers/filter-selection.js';
|
|
4
6
|
import { type Invocation } from './invocation.js';
|
|
5
7
|
import { type ParsedArgs } from './nmr-flags.js';
|
|
8
|
+
import type { RunSteps } from './runner.js';
|
|
6
9
|
/** What the command tree of one invocation is built from. */
|
|
7
10
|
export interface RouteInput {
|
|
8
11
|
context: ResolvedContext;
|
|
@@ -10,8 +13,11 @@ export interface RouteInput {
|
|
|
10
13
|
env: NodeJS.ProcessEnv;
|
|
11
14
|
/** The invocation's flags as the first pass read them, or `undefined` when they do not parse. */
|
|
12
15
|
firstPass: ParsedArgs | undefined;
|
|
16
|
+
readFilterSelection: ReadFilterSelection;
|
|
17
|
+
readTree: TreeReader;
|
|
13
18
|
/** Runs an invocation that reached a command and resolves to its exit code. */
|
|
14
19
|
runInvocation: (invocation: Invocation) => Promise<number>;
|
|
20
|
+
runSteps: RunSteps;
|
|
15
21
|
stderr: Writable;
|
|
16
22
|
stdout: Writable;
|
|
17
23
|
}
|
package/dist/esm/route.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { createCli, UsageError } from '@williamthorsen/nmr-core/cli';
|
|
3
|
+
import { DEBUG_ENV_VAR, NO_CACHE_ENV_VAR } from "./check-cache/check-cache.js";
|
|
4
|
+
import { readEnvSwitch, readEnvSwitches } from "./env-switch.js";
|
|
3
5
|
import { listDefinedCommands } from "./fan-out.js";
|
|
4
6
|
import { describeHelp } from "./help.js";
|
|
5
7
|
import { RUN_IF_PRESENT_ENV_VAR } from "./invocation.js";
|
|
8
|
+
import { NO_LOCK_ENV_VAR } from "./machine-lock.js";
|
|
6
9
|
import { NMR_FLAGS, toParsedArgs } from "./nmr-flags.js";
|
|
7
10
|
import { isTerminalStream } from "./output-style.js";
|
|
8
11
|
import { readPresentation, resolveReportingVerbosity } from "./presentation.js";
|
|
9
12
|
import { resolveReportFormat } from "./report-format.js";
|
|
13
|
+
const ENV_SWITCH_NAMES = [DEBUG_ENV_VAR, NO_CACHE_ENV_VAR, NO_LOCK_ENV_VAR, RUN_IF_PRESENT_ENV_VAR];
|
|
10
14
|
const { defineGroup } = createCli();
|
|
11
15
|
const { defineCommand } = createCli();
|
|
12
16
|
export function buildRoot(input) {
|
|
@@ -20,7 +24,9 @@ export function buildRoot(input) {
|
|
|
20
24
|
}
|
|
21
25
|
const command = firstPass?.command;
|
|
22
26
|
if (command !== undefined && !firstPass?.shouldShowHelp && !Object.hasOwn(commands, command)) {
|
|
23
|
-
const
|
|
27
|
+
const runIfPresent = readEnvSwitch(env, RUN_IF_PRESENT_ENV_VAR);
|
|
28
|
+
const isAnsweredByNmr = !runIfPresent.ok ||
|
|
29
|
+
runIfPresent.isOn ||
|
|
24
30
|
(firstPass?.shouldDelegate === true && firstPass.delegateHosts === undefined) ||
|
|
25
31
|
listDefinedCommands(context).has(command);
|
|
26
32
|
if (isAnsweredByNmr) {
|
|
@@ -50,7 +56,7 @@ function defineScriptCommand(name, summary, input) {
|
|
|
50
56
|
});
|
|
51
57
|
}
|
|
52
58
|
function deriveInvocation(flags, input) {
|
|
53
|
-
const { context, cwd, env, firstPass, stderr, stdout } = input;
|
|
59
|
+
const { context, cwd, env, firstPass, readFilterSelection, readTree, runSteps, stderr, stdout } = input;
|
|
54
60
|
const parsedArgs = toParsedArgs(flags, []);
|
|
55
61
|
const presentationRead = readPresentation({
|
|
56
62
|
env,
|
|
@@ -61,6 +67,10 @@ function deriveInvocation(flags, input) {
|
|
|
61
67
|
if (!presentationRead.ok) {
|
|
62
68
|
throw new UsageError(presentationRead.error);
|
|
63
69
|
}
|
|
70
|
+
const switchError = readEnvSwitches(env, ENV_SWITCH_NAMES);
|
|
71
|
+
if (switchError !== undefined) {
|
|
72
|
+
throw new UsageError(switchError);
|
|
73
|
+
}
|
|
64
74
|
if (parsedArgs.shouldPrintLog && firstPass?.command === undefined) {
|
|
65
75
|
throw new UsageError('--log requires a command name: `nmr --log <command>`');
|
|
66
76
|
}
|
|
@@ -81,6 +91,9 @@ function deriveInvocation(flags, input) {
|
|
|
81
91
|
env,
|
|
82
92
|
format,
|
|
83
93
|
parsedArgs,
|
|
94
|
+
readFilterSelection,
|
|
95
|
+
readTree,
|
|
96
|
+
runSteps,
|
|
84
97
|
scope: path.basename(anchorDir),
|
|
85
98
|
shouldUseRoot,
|
|
86
99
|
stderr,
|
package/dist/esm/run-chain.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type OutputStyle } from '@williamthorsen/nmr-core';
|
|
2
|
-
import type { TreeSnapshot } from './check-cache.js';
|
|
2
|
+
import type { TreeSnapshot } from './check-cache/check-cache.js';
|
|
3
3
|
import { type Invocation, type PhaseResult, type RunPlan } from './invocation.js';
|
|
4
4
|
import type { ScriptRegistry } from './resolve-scripts.js';
|
|
5
5
|
import type { ResolvedScript } from './resolver.js';
|
package/dist/esm/run-chain.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { formatGlyphLine, reportError } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { NMR_BIN } from "./bins.js";
|
|
4
|
-
import { resolveCacheKey } from "./check-cache-gate.js";
|
|
4
|
+
import { resolveCacheKey } from "./check-cache/check-cache-gate.js";
|
|
5
5
|
import { reportNmrCrossing } from "./crossing-diagnostics.js";
|
|
6
6
|
import { NMR_GLYPHS } from "./glyphs.js";
|
|
7
7
|
import { isHookName } from "./helpers/hook-name.js";
|
package/dist/esm/runCli.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
|
+
import { type TreeReader } from './check-cache/check-cache.js';
|
|
3
|
+
import { type ReadFilterSelection } from './helpers/filter-selection.js';
|
|
2
4
|
import { type RunCliResult } from './invocation.js';
|
|
5
|
+
import { type RunSteps } from './runner.js';
|
|
3
6
|
/** @internal */
|
|
4
7
|
export interface RunCliOptions {
|
|
5
8
|
/** Post-slice CLI arguments (equivalent to `process.argv.slice(2)`). */
|
|
@@ -8,6 +11,12 @@ export interface RunCliOptions {
|
|
|
8
11
|
cwd: string;
|
|
9
12
|
/** Environment from which `runCli` reads its settings, and the base of the one that its children inherit. */
|
|
10
13
|
env: NodeJS.ProcessEnv;
|
|
14
|
+
/** Reads what a `-F` pattern selects; defaults to `readFilterSelection`, which asks pnpm. */
|
|
15
|
+
readFilterSelection?: ReadFilterSelection;
|
|
16
|
+
/** Reads the working tree that the check-result cache gates on; defaults to `GIT_TREE_READER`, which asks git. */
|
|
17
|
+
readTree?: TreeReader;
|
|
18
|
+
/** Runs a step list; defaults to `runSteps`. */
|
|
19
|
+
runSteps?: RunSteps;
|
|
11
20
|
/** Stream for normal output: help, version, verdicts, recordings, and override notices. */
|
|
12
21
|
stdout: Writable;
|
|
13
22
|
/** Stream for errors, warnings, and debug notes. */
|