@williamthorsen/nmr 0.48.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.meta/changelog.json +218 -0
- package/.readyup/kits/default.js +1527 -1460
- package/.readyup/manifest.json +96 -11
- package/CHANGELOG.md +65 -0
- package/README.md +19 -8
- package/agents/guidance/rulebooks/nmr.md +2 -2
- package/dist/esm/check-cache-build-output.d.ts +24 -0
- package/dist/esm/check-cache-build-output.js +49 -0
- package/dist/esm/check-cache-delegation.d.ts +27 -0
- package/dist/esm/check-cache-delegation.js +92 -0
- package/dist/esm/check-cache-entries.d.ts +109 -0
- package/dist/esm/check-cache-entries.js +87 -0
- package/dist/esm/check-cache-gate.d.ts +64 -0
- package/dist/esm/check-cache-gate.js +226 -0
- package/dist/esm/check-cache-key.d.ts +47 -0
- package/dist/esm/check-cache-key.js +77 -0
- package/dist/esm/check-cache-record.d.ts +69 -0
- package/dist/esm/check-cache-record.js +167 -0
- package/dist/esm/check-cache.d.ts +8 -176
- package/dist/esm/check-cache.js +9 -214
- package/dist/esm/child-env.d.ts +57 -0
- package/dist/esm/child-env.js +59 -0
- package/dist/esm/child-process.d.ts +55 -0
- package/dist/esm/child-process.js +112 -0
- package/dist/esm/commands/build.d.ts +0 -16
- package/dist/esm/commands/build.js +9 -214
- package/dist/esm/commands/clean.js +3 -2
- package/dist/esm/commands/compiler.d.ts +18 -0
- package/dist/esm/commands/compiler.js +49 -0
- package/dist/esm/commands/fmt.d.ts +0 -39
- package/dist/esm/commands/fmt.js +4 -81
- package/dist/esm/commands/format-targets.d.ts +39 -0
- package/dist/esm/commands/format-targets.js +83 -0
- package/dist/esm/commands/rewrite-specifiers.d.ts +17 -0
- package/dist/esm/commands/rewrite-specifiers.js +122 -0
- package/dist/esm/commands/tsconfig-chain.d.ts +8 -0
- package/dist/esm/commands/tsconfig-chain.js +63 -0
- package/dist/esm/config-check-cache.d.ts +17 -0
- package/dist/esm/config-check-cache.js +63 -0
- package/dist/esm/config-validation.d.ts +20 -0
- package/dist/esm/config-validation.js +236 -0
- package/dist/esm/config.js +4 -286
- package/dist/esm/crossing-diagnostics.d.ts +39 -0
- package/dist/esm/crossing-diagnostics.js +132 -0
- package/dist/esm/default-scripts.js +1 -1
- package/dist/esm/delegate-host.d.ts +43 -0
- package/dist/esm/delegate-host.js +191 -0
- package/dist/esm/delegation-target.d.ts +52 -0
- package/dist/esm/delegation-target.js +71 -0
- package/dist/esm/fan-out.d.ts +57 -0
- package/dist/esm/fan-out.js +146 -0
- package/dist/esm/glyphs.d.ts +1 -1
- package/dist/esm/help.js +10 -3
- package/dist/esm/helpers/deriveExcerpt.d.ts +9 -0
- package/dist/esm/helpers/deriveExcerpt.js +1 -1
- package/dist/esm/helpers/renderQuotedList.d.ts +2 -0
- package/dist/esm/helpers/renderQuotedList.js +9 -0
- package/dist/esm/hooks.d.ts +17 -0
- package/dist/esm/hooks.js +23 -0
- package/dist/esm/invocation-args.d.ts +40 -0
- package/dist/esm/invocation-args.js +178 -0
- package/dist/esm/invocation.d.ts +67 -0
- package/dist/esm/invocation.js +3 -0
- package/dist/esm/machine-lock.d.ts +2 -0
- package/dist/esm/machine-lock.js +1 -1
- package/dist/esm/output-channel.d.ts +23 -0
- package/dist/esm/output-channel.js +14 -0
- package/dist/esm/pass-manifest.d.ts +53 -0
- package/dist/esm/pass-manifest.js +89 -0
- package/dist/esm/presentation.d.ts +47 -0
- package/dist/esm/presentation.js +32 -0
- package/dist/esm/recording.d.ts +1 -1
- package/dist/esm/recording.js +2 -2
- package/dist/esm/remote-host-session.d.ts +62 -0
- package/dist/esm/remote-host-session.js +277 -0
- package/dist/esm/remote-probe-host.d.ts +22 -0
- package/dist/esm/remote-probe-host.js +50 -0
- package/dist/esm/remote-probe.d.ts +63 -0
- package/dist/esm/remote-probe.js +88 -0
- package/dist/esm/remote-run.d.ts +45 -65
- package/dist/esm/remote-run.js +128 -162
- package/dist/esm/remote-session.d.ts +40 -0
- package/dist/esm/remote-session.js +151 -0
- package/dist/esm/remote-snapshot.d.ts +21 -0
- package/dist/esm/remote-snapshot.js +80 -0
- package/dist/esm/replay-assembly.d.ts +2 -2
- package/dist/esm/replay-assembly.js +1 -1
- package/dist/esm/run-chain.d.ts +21 -0
- package/dist/esm/run-chain.js +108 -0
- package/dist/esm/runCli.d.ts +1 -9
- package/dist/esm/runCli.js +39 -1002
- package/dist/esm/runner.d.ts +1 -54
- package/dist/esm/runner.js +2 -125
- package/dist/esm/shell-syntax.d.ts +30 -0
- package/dist/esm/shell-syntax.js +120 -0
- package/dist/esm/steps.d.ts +0 -2
- package/dist/esm/steps.js +3 -119
- package/dist/esm/types.d.ts +5 -0
- package/dist/esm/user-config.d.ts +34 -0
- package/dist/esm/user-config.js +93 -0
- package/dist/esm/verbosity.d.ts +6 -0
- package/dist/esm/verbosity.js +7 -7
- package/dist/esm/verdict.d.ts +1 -1
- package/dist/esm/verdict.js +1 -1
- package/docs/check-cache.md +28 -12
- package/docs/delegate.md +103 -17
- package/docs/reporting.md +6 -1
- package/docs/scripts.md +2 -1
- package/package.json +4 -4
- /package/dist/esm/{prettier-default-config.d.ts → prettier-default.config.d.ts} +0 -0
- /package/dist/esm/{prettier-default-config.js → prettier-default.config.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ReplayLine } from './check-cache.js';
|
|
1
|
+
import { type ReplayLine } from './check-cache-entries.js';
|
|
2
2
|
import { type Step } from './steps.js';
|
|
3
3
|
/**
|
|
4
4
|
* Assembles what a composite's skip replays: the excerpts recorded by its constituents, in the order in which
|
|
@@ -14,7 +14,7 @@ import { type Step } from './steps.js';
|
|
|
14
14
|
*
|
|
15
15
|
* An entry is admissible when the run that certified it is this one and the tree that it describes is this one.
|
|
16
16
|
* The witness is what a run stamps on an excerpt that it records and on one that it recalls and replays; the
|
|
17
|
-
* tree
|
|
17
|
+
* tree id bounds an identity carried by a process out of the run that issued it.
|
|
18
18
|
*/
|
|
19
19
|
export declare function assembleReplay(options: {
|
|
20
20
|
anchorDir: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readCheckCacheEntry } from "./check-cache.js";
|
|
1
|
+
import { readCheckCacheEntry } from "./check-cache-entries.js";
|
|
2
2
|
import { readNmrStep } from "./steps.js";
|
|
3
3
|
import { getWorkspacePackageDirs } from "./workspace.js";
|
|
4
4
|
export async function assembleReplay(options) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type OutputStyle } from '@williamthorsen/nmr-core';
|
|
2
|
+
import type { TreeSnapshot } from './check-cache.js';
|
|
3
|
+
import type { Invocation, PhaseResult, RunPlan } from './invocation.js';
|
|
4
|
+
import type { ScriptRegistry } from './resolve-scripts.js';
|
|
5
|
+
import { type ResolvedScript } from './resolver.js';
|
|
6
|
+
/**
|
|
7
|
+
* Assembles the chain that a resolved script runs at this scope, the hooks wrapped around it included, and the key
|
|
8
|
+
* under which a pass by that chain is recorded. Settles a no-op override and an argument that no step can take.
|
|
9
|
+
*/
|
|
10
|
+
export declare function assembleChain(options: {
|
|
11
|
+
invocation: Invocation;
|
|
12
|
+
registry: ScriptRegistry;
|
|
13
|
+
resolvedScript: ResolvedScript;
|
|
14
|
+
snapshot: TreeSnapshot | undefined;
|
|
15
|
+
}): PhaseResult<Pick<RunPlan, 'commandString' | 'key' | 'ownSteps' | 'steps'>>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the line announcing that a `package.json` script is standing in for a built-in, or `undefined` under
|
|
18
|
+
* `quiet` or when none is due. Only a script replacing a name that the registry already defines is worth
|
|
19
|
+
* announcing; an ordinary tier-3 entry that happens to resolve is not standing in for anything.
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatOverrideNotice(resolvedScript: ResolvedScript, registry: ScriptRegistry, command: string, anchorDir: string, quiet: boolean, style: OutputStyle): string | undefined;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { formatGlyphLine, reportError } from '@williamthorsen/nmr-core';
|
|
3
|
+
import { resolveCacheKey } from "./check-cache-gate.js";
|
|
4
|
+
import { reportNmrCrossing } from "./crossing-diagnostics.js";
|
|
5
|
+
import { NMR_GLYPHS } from "./glyphs.js";
|
|
6
|
+
import { isHookName } from "./helpers/hook-name.js";
|
|
7
|
+
import { quoteForShell } from "./helpers/quoteForShell.js";
|
|
8
|
+
import { wrapWithHooks } from "./hooks.js";
|
|
9
|
+
import { reportVerdict } from "./presentation.js";
|
|
10
|
+
import { applyDevBinToSteps } from "./resolver.js";
|
|
11
|
+
import { dropRecursiveSteps, renderChain } from "./steps.js";
|
|
12
|
+
export function assembleChain(options) {
|
|
13
|
+
const { invocation, registry, resolvedScript, snapshot } = options;
|
|
14
|
+
const { anchorDir, command, context, env, parsedArgs, stderr, stdout, styles } = invocation;
|
|
15
|
+
const { isEmptiedByWorkspace, steps: runnableSteps } = readRunnableSteps(resolvedScript, context.workspacePackageDirs);
|
|
16
|
+
const resolvedCommand = renderChain(runnableSteps);
|
|
17
|
+
const noOpReason = findNoOpReason(resolvedCommand, isEmptiedByWorkspace);
|
|
18
|
+
if (noOpReason !== undefined && !parsedArgs.shouldPrintLog) {
|
|
19
|
+
reportVerdict({ command, scope: invocation.scope, outcome: 'no-op', reason: noOpReason }, stdout, invocation.format, styles.stdout);
|
|
20
|
+
return { settled: true, result: { exitCode: 0 } };
|
|
21
|
+
}
|
|
22
|
+
const substitutedSteps = applyDevBinToSteps(runnableSteps, context.config.devBin, context.monorepoRoot);
|
|
23
|
+
const substitutedCommand = renderChain(substitutedSteps);
|
|
24
|
+
const bindResult = bindPassthrough(substitutedSteps, parsedArgs.passthrough, command);
|
|
25
|
+
if (!bindResult.ok) {
|
|
26
|
+
reportError(bindResult.error, stderr);
|
|
27
|
+
return { settled: true, result: { exitCode: 1 } };
|
|
28
|
+
}
|
|
29
|
+
const mainSteps = bindResult.steps;
|
|
30
|
+
const isHookInvocation = isHookName(command);
|
|
31
|
+
const fullSteps = isHookInvocation
|
|
32
|
+
? mainSteps
|
|
33
|
+
: wrapWithHooks(command, mainSteps, registry, anchorDir, parsedArgs.isWorkspaceRoot);
|
|
34
|
+
const fullCommand = renderChain(fullSteps);
|
|
35
|
+
reportNmrCrossing({
|
|
36
|
+
config: context.config,
|
|
37
|
+
isReading: parsedArgs.shouldPrintLog,
|
|
38
|
+
isWorkspaceRoot: parsedArgs.isWorkspaceRoot,
|
|
39
|
+
monorepoRoot: context.monorepoRoot,
|
|
40
|
+
registry,
|
|
41
|
+
resolvedScript,
|
|
42
|
+
shouldUseRoot: invocation.shouldUseRoot,
|
|
43
|
+
stderr,
|
|
44
|
+
style: styles.stderr,
|
|
45
|
+
});
|
|
46
|
+
const key = resolveCacheKey({
|
|
47
|
+
anchorDir,
|
|
48
|
+
command,
|
|
49
|
+
commandString: fullCommand,
|
|
50
|
+
env,
|
|
51
|
+
monorepoRoot: context.monorepoRoot,
|
|
52
|
+
snapshot,
|
|
53
|
+
stderr,
|
|
54
|
+
substitution: substitutedCommand === resolvedCommand ? undefined : substitutedCommand,
|
|
55
|
+
});
|
|
56
|
+
return { settled: false, value: { commandString: fullCommand, key, ownSteps: mainSteps, steps: fullSteps } };
|
|
57
|
+
}
|
|
58
|
+
export function formatOverrideNotice(resolvedScript, registry, command, anchorDir, quiet, style) {
|
|
59
|
+
const registryEntry = Object.hasOwn(registry, command) ? registry[command] : undefined;
|
|
60
|
+
if (quiet || resolvedScript.origin.tier !== 'package' || registryEntry === undefined) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const notice = `${path.basename(anchorDir)}: Using override script: ${renderChain(resolvedScript.steps)}`;
|
|
64
|
+
return `${formatGlyphLine(NMR_GLYPHS, style, 'package', notice)}\n`;
|
|
65
|
+
}
|
|
66
|
+
function acceptsArguments(step) {
|
|
67
|
+
return step.kind === 'opaque' || step.shouldDeclineArguments !== true;
|
|
68
|
+
}
|
|
69
|
+
function bindPassthrough(steps, passthrough, command) {
|
|
70
|
+
if (passthrough.length === 0) {
|
|
71
|
+
return { ok: true, steps };
|
|
72
|
+
}
|
|
73
|
+
if (!steps.some(acceptsArguments)) {
|
|
74
|
+
return { ok: false, error: formatUnroutableArgumentsError(command) };
|
|
75
|
+
}
|
|
76
|
+
const boundSteps = steps.map((step) => {
|
|
77
|
+
if (!acceptsArguments(step)) {
|
|
78
|
+
return step;
|
|
79
|
+
}
|
|
80
|
+
return step.kind === 'structural'
|
|
81
|
+
? { ...step, argv: [...step.argv, ...passthrough] }
|
|
82
|
+
: { kind: 'opaque', command: `${step.command} ${passthrough.map(quoteForShell).join(' ')}` };
|
|
83
|
+
});
|
|
84
|
+
return { ok: true, steps: boundSteps };
|
|
85
|
+
}
|
|
86
|
+
function findNoOpReason(resolvedCommand, isEmptiedByWorkspace) {
|
|
87
|
+
if (isEmptiedByWorkspace) {
|
|
88
|
+
return 'empty-workspace';
|
|
89
|
+
}
|
|
90
|
+
if (resolvedCommand === '') {
|
|
91
|
+
return 'empty-override';
|
|
92
|
+
}
|
|
93
|
+
if (resolvedCommand === ':') {
|
|
94
|
+
return 'noop-override';
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
function formatUnroutableArgumentsError(command) {
|
|
99
|
+
return (`\`${command}\` does not take trailing arguments: every step of its chain declines them. ` +
|
|
100
|
+
'Running it unnarrowed is not what the arguments asked for, so nothing ran.');
|
|
101
|
+
}
|
|
102
|
+
function readRunnableSteps(resolvedScript, workspacePackageDirs) {
|
|
103
|
+
if (workspacePackageDirs.length > 0) {
|
|
104
|
+
return { isEmptiedByWorkspace: false, steps: resolvedScript.steps };
|
|
105
|
+
}
|
|
106
|
+
const steps = dropRecursiveSteps(resolvedScript.steps);
|
|
107
|
+
return { isEmptiedByWorkspace: steps.length === 0 && resolvedScript.steps.length > 0, steps };
|
|
108
|
+
}
|
package/dist/esm/runCli.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
|
-
|
|
3
|
-
* Marks a run made on a delegating caller's behalf, in which a command that the registry does not define, and a
|
|
4
|
-
* `--log` with nothing to show, exit 0 rather than failing.
|
|
5
|
-
*/
|
|
6
|
-
export declare const RUN_IF_PRESENT_ENV_VAR = "NMR_RUN_IF_PRESENT";
|
|
2
|
+
import { type RunCliResult } from './invocation.js';
|
|
7
3
|
/** @internal */
|
|
8
4
|
export interface RunCliOptions {
|
|
9
5
|
/** Post-slice CLI arguments (equivalent to `process.argv.slice(2)`). */
|
|
@@ -17,10 +13,6 @@ export interface RunCliOptions {
|
|
|
17
13
|
/** Stream for errors, warnings, and debug notes. */
|
|
18
14
|
stderr: Writable;
|
|
19
15
|
}
|
|
20
|
-
/** @internal */
|
|
21
|
-
export interface RunCliResult {
|
|
22
|
-
exitCode: number;
|
|
23
|
-
}
|
|
24
16
|
/**
|
|
25
17
|
* Executes the nmr CLI flow in-process and returns the resulting exit code.
|
|
26
18
|
* Does not hold global state, does not read `process.*` globals, and never calls `process.exit`.
|