@williamthorsen/nmr 0.38.0 → 0.39.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.
Files changed (64) hide show
  1. package/.meta/changelog.json +84 -0
  2. package/.readyup/kits/default.js +84 -79
  3. package/.readyup/manifest.json +5 -5
  4. package/CHANGELOG.md +70 -0
  5. package/README.md +37 -11
  6. package/dist/esm/check-cache.d.ts +2 -2
  7. package/dist/esm/check-cache.js +24 -24
  8. package/dist/esm/cli-ensure-prepublish-hooks.js +4 -4
  9. package/dist/esm/commands/build-output.d.ts +2 -2
  10. package/dist/esm/commands/build-output.js +9 -9
  11. package/dist/esm/commands/build.js +65 -63
  12. package/dist/esm/commands/clean.js +11 -11
  13. package/dist/esm/commands/ensure-prepublish-hooks.d.ts +2 -2
  14. package/dist/esm/commands/ensure-prepublish-hooks.js +41 -41
  15. package/dist/esm/commands/fmt.js +33 -33
  16. package/dist/esm/commands/report-catalog.js +9 -7
  17. package/dist/esm/commands/report-overrides.js +7 -7
  18. package/dist/esm/config.js +25 -25
  19. package/dist/esm/context.js +8 -8
  20. package/dist/esm/help.d.ts +2 -2
  21. package/dist/esm/help.js +21 -21
  22. package/dist/esm/helpers/clampToBytes.js +3 -3
  23. package/dist/esm/helpers/createBoundedBuffer.d.ts +1 -1
  24. package/dist/esm/helpers/createBoundedBuffer.js +2 -2
  25. package/dist/esm/helpers/duration.d.ts +2 -2
  26. package/dist/esm/helpers/duration.js +7 -7
  27. package/dist/esm/helpers/filter-selection.js +12 -12
  28. package/dist/esm/helpers/findClosestName.js +15 -15
  29. package/dist/esm/helpers/package-json.d.ts +2 -2
  30. package/dist/esm/helpers/package-json.js +26 -25
  31. package/dist/esm/helpers/transcript.d.ts +2 -2
  32. package/dist/esm/helpers/transcript.js +14 -14
  33. package/dist/esm/prettier.js +5 -5
  34. package/dist/esm/recording.d.ts +5 -5
  35. package/dist/esm/recording.js +21 -14
  36. package/dist/esm/report-format.d.ts +1 -1
  37. package/dist/esm/report-format.js +7 -7
  38. package/dist/esm/resolveBinStyles.js +3 -3
  39. package/dist/esm/resolver.d.ts +2 -2
  40. package/dist/esm/resolver.js +15 -15
  41. package/dist/esm/runCli.js +252 -186
  42. package/dist/esm/runner.d.ts +1 -1
  43. package/dist/esm/runner.js +18 -18
  44. package/dist/esm/steps.d.ts +13 -1
  45. package/dist/esm/steps.js +32 -27
  46. package/dist/esm/tests.d.ts +7 -7
  47. package/dist/esm/tests.js +20 -8
  48. package/dist/esm/tiers.d.ts +1 -1
  49. package/dist/esm/tiers.js +8 -8
  50. package/dist/esm/verbosity.d.ts +1 -1
  51. package/dist/esm/verbosity.js +7 -7
  52. package/dist/esm/verdict.d.ts +9 -2
  53. package/dist/esm/verdict.js +63 -50
  54. package/dist/esm/vitest-source-resolution.js +48 -46
  55. package/dist/esm/vitest.d.ts +2 -2
  56. package/dist/esm/vitest.js +74 -25
  57. package/dist/esm/workspace.d.ts +2 -18
  58. package/dist/esm/workspace.js +9 -67
  59. package/docs/reporting.md +6 -2
  60. package/docs/vitest.md +6 -6
  61. package/docs/workspace.md +24 -1
  62. package/package.json +3 -4
  63. package/dist/esm/helpers/workspace-patterns.d.ts +0 -8
  64. package/dist/esm/helpers/workspace-patterns.js +0 -29
@@ -1,5 +1,5 @@
1
- export function formatDuration(milliseconds) {
2
- const total = Math.max(0, milliseconds);
1
+ export function formatDuration(durationMs) {
2
+ const total = Math.max(0, durationMs);
3
3
  if (total < MILLISECONDS_PER_MINUTE) {
4
4
  return `${truncateToTenth(total)}s`;
5
5
  }
@@ -10,11 +10,11 @@ export function formatDuration(milliseconds) {
10
10
  }
11
11
  return joinUnits(`${Math.floor(totalMinutes / MINUTES_PER_HOUR)}h`, totalMinutes % MINUTES_PER_HOUR, 'm');
12
12
  }
13
- export function formatSaving(milliseconds) {
14
- if (!Number.isFinite(milliseconds) || milliseconds < MILLISECONDS_PER_SECOND) {
13
+ export function formatSaving(durationMs) {
14
+ if (!Number.isFinite(durationMs) || durationMs < MILLISECONDS_PER_SECOND) {
15
15
  return undefined;
16
16
  }
17
- return `saved ~${formatDuration(milliseconds)}`;
17
+ return `saved ~${formatDuration(durationMs)}`;
18
18
  }
19
19
  const MILLISECONDS_PER_MINUTE = 60_000;
20
20
  const MILLISECONDS_PER_SECOND = 1_000;
@@ -23,6 +23,6 @@ const SECONDS_PER_MINUTE = 60;
23
23
  function joinUnits(major, minor, minorUnit) {
24
24
  return minor === 0 ? major : `${major} ${minor}${minorUnit}`;
25
25
  }
26
- function truncateToTenth(milliseconds) {
27
- return Math.floor(milliseconds / 100) / 10;
26
+ function truncateToTenth(durationMs) {
27
+ return Math.floor(durationMs / 100) / 10;
28
28
  }
@@ -5,31 +5,31 @@ import process from 'node:process';
5
5
  import { isObject } from "./type-guards.js";
6
6
  const SELECTION_MARKER = 'nmr-selected-scope';
7
7
  export function readFilterSelection(pattern, monorepoRoot) {
8
- const listing = spawnSync('pnpm', ['ls', '--filter', pattern, '--depth', '-1', '--json'], {
8
+ const listingRun = spawnSync('pnpm', ['ls', '--filter', pattern, '--depth', '-1', '--json'], {
9
9
  cwd: monorepoRoot,
10
10
  encoding: 'utf8',
11
11
  });
12
- const reading = interpretSelectionProbe({ error: listing.error, status: listing.status, stdout: listing.stdout }, monorepoRoot);
13
- return reading === 'root-only' ? readDelegateSelection(pattern, monorepoRoot) : reading;
12
+ const probeReading = interpretSelectionProbe({ error: listingRun.error, status: listingRun.status, stdout: listingRun.stdout }, monorepoRoot);
13
+ return probeReading === 'root-only' ? readDelegateSelection(pattern, monorepoRoot) : probeReading;
14
14
  }
15
15
  export function interpretSelectionProbe(probe, monorepoRoot) {
16
16
  if (probe.error !== undefined || probe.status !== 0) {
17
17
  return 'unresolved';
18
18
  }
19
- let parsed;
19
+ let parsedListing;
20
20
  try {
21
- parsed = JSON.parse(probe.stdout);
21
+ parsedListing = JSON.parse(probe.stdout);
22
22
  }
23
23
  catch {
24
24
  return 'unresolved';
25
25
  }
26
- if (!Array.isArray(parsed)) {
26
+ if (!Array.isArray(parsedListing)) {
27
27
  return 'unresolved';
28
28
  }
29
- if (parsed.length === 0) {
29
+ if (parsedListing.length === 0) {
30
30
  return 'empty';
31
31
  }
32
- const packageCount = parsed.filter((entry) => !isRootEntry(entry, monorepoRoot)).length;
32
+ const packageCount = parsedListing.filter((entry) => !isRootEntry(entry, monorepoRoot)).length;
33
33
  if (packageCount === 0) {
34
34
  return 'root-only';
35
35
  }
@@ -45,9 +45,9 @@ function isRootEntry(entry, monorepoRoot) {
45
45
  if (!isObject(entry) || typeof entry['path'] !== 'string') {
46
46
  return false;
47
47
  }
48
- return readRealPath(entry['path']) === readRealPath(monorepoRoot);
48
+ return resolveRealPath(entry['path']) === resolveRealPath(monorepoRoot);
49
49
  }
50
- function readRealPath(target) {
50
+ function resolveRealPath(target) {
51
51
  try {
52
52
  return realpathSync(target);
53
53
  }
@@ -56,6 +56,6 @@ function readRealPath(target) {
56
56
  }
57
57
  }
58
58
  function readDelegateSelection(pattern, monorepoRoot) {
59
- const probe = spawnSync('pnpm', ['--filter', pattern, 'exec', process.execPath, '--eval', `process.stdout.write('${SELECTION_MARKER}')`], { cwd: monorepoRoot, encoding: 'utf8' });
60
- return interpretDelegateProbe({ error: probe.error, status: probe.status, stdout: probe.stdout });
59
+ const probeRun = spawnSync('pnpm', ['--filter', pattern, 'exec', process.execPath, '--eval', `process.stdout.write('${SELECTION_MARKER}')`], { cwd: monorepoRoot, encoding: 'utf8' });
60
+ return interpretDelegateProbe({ error: probeRun.error, status: probeRun.status, stdout: probeRun.stdout });
61
61
  }
@@ -1,33 +1,33 @@
1
1
  export function findClosestName(name, candidates) {
2
2
  const ceiling = Math.max(1, Math.floor(name.length / 4));
3
- let closest;
4
- let shortest = Infinity;
3
+ let closestName;
4
+ let shortestDistance = Infinity;
5
5
  for (const candidate of candidates) {
6
6
  const distance = measureDistance(name, candidate);
7
- if (distance < shortest) {
8
- shortest = distance;
9
- closest = candidate;
7
+ if (distance < shortestDistance) {
8
+ shortestDistance = distance;
9
+ closestName = candidate;
10
10
  }
11
11
  }
12
- return shortest <= ceiling ? closest : undefined;
12
+ return shortestDistance <= ceiling ? closestName : undefined;
13
13
  }
14
14
  function measureDistance(first, second) {
15
15
  if (first.length === 0 || second.length === 0) {
16
16
  return Math.max(first.length, second.length);
17
17
  }
18
- let previous = Array.from({ length: second.length + 1 }, (_unused, column) => column);
19
- let current = Array.from({ length: second.length + 1 }, () => 0);
18
+ let previousRow = Array.from({ length: second.length + 1 }, (_unused, column) => column);
19
+ let currentRow = Array.from({ length: second.length + 1 }, () => 0);
20
20
  for (let row = 1; row <= first.length; row += 1) {
21
- current[0] = row;
21
+ currentRow[0] = row;
22
22
  for (let column = 1; column <= second.length; column += 1) {
23
- const substitution = readCell(previous, column - 1) + (first[row - 1] === second[column - 1] ? 0 : 1);
24
- current[column] = Math.min(readCell(current, column - 1) + 1, readCell(previous, column) + 1, substitution);
23
+ const substitution = readCell(previousRow, column - 1) + (first[row - 1] === second[column - 1] ? 0 : 1);
24
+ currentRow[column] = Math.min(readCell(currentRow, column - 1) + 1, readCell(previousRow, column) + 1, substitution);
25
25
  }
26
- const completed = current;
27
- current = previous;
28
- previous = completed;
26
+ const completedRow = currentRow;
27
+ currentRow = previousRow;
28
+ previousRow = completedRow;
29
29
  }
30
- return readCell(previous, second.length);
30
+ return readCell(previousRow, second.length);
31
31
  }
32
32
  function readCell(row, index) {
33
33
  const value = row[index];
@@ -25,14 +25,14 @@ export declare function readPackageJson(dir: string): PackageJson;
25
25
  /**
26
26
  * Returns the `pnpm.overrides` block a package.json declares, every key it holds and each value as written.
27
27
  */
28
- export declare function getPnpmOverrides(pkg: PackageJson): Record<string, unknown> | undefined;
28
+ export declare function getPnpmOverrides(packageJson: PackageJson): Record<string, unknown> | undefined;
29
29
  /**
30
30
  * Parses a `package.json`'s text, rejecting what does not parse.
31
31
  *
32
32
  * A file the user wrote by hand is theirs to fix, so the failure names it rather than reporting the parser's
33
33
  * own stack.
34
34
  */
35
- export declare function parsePackageJson(raw: string, file: string): unknown;
35
+ export declare function parsePackageJson(rawText: string, file: string): unknown;
36
36
  /**
37
37
  * Narrows a `scripts` record to strings, rejecting any value that is not one.
38
38
  *
@@ -14,45 +14,46 @@ export const DEPENDENCY_FIELDS = [
14
14
  ];
15
15
  export function readPackageJson(dir) {
16
16
  const file = resolvePackageJsonPath(dir);
17
- const parsed = parsePackageJson(readFileSync(file, 'utf8'), file);
18
- if (!isObject(parsed)) {
17
+ const parsedManifest = parsePackageJson(readFileSync(file, 'utf8'), file);
18
+ if (!isObject(parsedManifest)) {
19
19
  throw new UserError(`Invalid package.json in ${dir}: expected an object`);
20
20
  }
21
- const pkg = {};
22
- if (typeof parsed['name'] === 'string')
23
- pkg.name = parsed['name'];
24
- if (parsed['private'] === true)
25
- pkg.private = true;
26
- if (typeof parsed['version'] === 'string')
27
- pkg.version = parsed['version'];
28
- if (typeof parsed['packageManager'] === 'string')
29
- pkg.packageManager = parsed['packageManager'];
30
- if (isObject(parsed['scripts'])) {
31
- pkg.scripts = readScriptRecord(dir, parsed['scripts']);
21
+ const packageJson = {};
22
+ if (typeof parsedManifest['name'] === 'string')
23
+ packageJson.name = parsedManifest['name'];
24
+ if (parsedManifest['private'] === true)
25
+ packageJson.private = true;
26
+ if (typeof parsedManifest['version'] === 'string')
27
+ packageJson.version = parsedManifest['version'];
28
+ if (typeof parsedManifest['packageManager'] === 'string') {
29
+ packageJson.packageManager = parsedManifest['packageManager'];
32
30
  }
33
- if (isObject(parsed['pnpm'])) {
34
- const pnpm = parsed['pnpm'];
31
+ if (isObject(parsedManifest['scripts'])) {
32
+ packageJson.scripts = readScriptRecord(dir, parsedManifest['scripts']);
33
+ }
34
+ if (isObject(parsedManifest['pnpm'])) {
35
+ const pnpm = parsedManifest['pnpm'];
35
36
  if (isObject(pnpm['overrides'])) {
36
- pkg.pnpm = { overrides: pnpm['overrides'] };
37
+ packageJson.pnpm = { overrides: pnpm['overrides'] };
37
38
  }
38
39
  }
39
40
  for (const field of DEPENDENCY_FIELDS) {
40
- const declared = parsed[field];
41
- if (isObject(declared)) {
42
- pkg[field] = readStringValues(declared);
41
+ const declaredDependencies = parsedManifest[field];
42
+ if (isObject(declaredDependencies)) {
43
+ packageJson[field] = readStringValues(declaredDependencies);
43
44
  }
44
45
  }
45
- return pkg;
46
+ return packageJson;
46
47
  }
47
- export function getPnpmOverrides(pkg) {
48
- if (!isObject(pkg.pnpm))
48
+ export function getPnpmOverrides(packageJson) {
49
+ if (!isObject(packageJson.pnpm))
49
50
  return undefined;
50
- const overrides = pkg.pnpm.overrides;
51
+ const overrides = packageJson.pnpm.overrides;
51
52
  return isObject(overrides) ? overrides : undefined;
52
53
  }
53
- export function parsePackageJson(raw, file) {
54
+ export function parsePackageJson(rawText, file) {
54
55
  try {
55
- return JSON.parse(raw);
56
+ return JSON.parse(rawText);
56
57
  }
57
58
  catch (error) {
58
59
  throw new UserError(`Invalid package.json at ${file}: ${describeError(error)}`);
@@ -16,7 +16,7 @@ export declare const TRANSCRIPT_LIMIT_BYTES = 262144;
16
16
  * stderr on failure is the command's own output going to a stream that may be a terminal, and stripping its
17
17
  * color there would be a loss.
18
18
  */
19
- export declare function cleanTranscript(raw: string): string;
19
+ export declare function cleanTranscript(rawText: string): string;
20
20
  /**
21
21
  * Composes what a pass persists from what its command wrote, or `undefined` where it wrote nothing worth
22
22
  * keeping.
@@ -25,6 +25,6 @@ export declare function cleanTranscript(raw: string): string;
25
25
  * failure: nmr reads each through a pipe of its own, so their true interleaving is not among the facts it
26
26
  * holds. A stream carrying nothing contributes neither content nor marker.
27
27
  */
28
- export declare function composeTranscript(retained: RetainedOutput): string | undefined;
28
+ export declare function composeTranscript(retainedOutput: RetainedOutput): string | undefined;
29
29
  /** Renders the line that stands in for dropped bytes, in nmr's voice so it is not mistaken for the tool's. */
30
30
  export declare function formatElisionMarker(byteCount: number): string;
@@ -2,15 +2,15 @@ export const TRANSCRIPT_LIMIT_BYTES = 262_144;
2
2
  const ANSI_PATTERN = /\u{1B}(?:\[[\u{30}-\u{3F}]*[\u{20}-\u{2F}]*[\u{40}-\u{7E}]|\][^\u{7}\u{1B}]*(?:\u{7}|\u{1B}\\))/gu;
3
3
  const END_LIMIT_BYTES = TRANSCRIPT_LIMIT_BYTES / 2;
4
4
  const STREAM_MARKER = '\n… nmr: stderr …\n';
5
- export function cleanTranscript(raw) {
6
- return raw
5
+ export function cleanTranscript(rawText) {
6
+ return rawText
7
7
  .replaceAll(ANSI_PATTERN, '')
8
8
  .split('\n')
9
9
  .map((line) => renderCarriageReturns(line))
10
10
  .join('\n');
11
11
  }
12
- export function composeTranscript(retained) {
13
- const streams = [retained.stdout, retained.stderr]
12
+ export function composeTranscript(retainedOutput) {
13
+ const streams = [retainedOutput.stdout, retainedOutput.stderr]
14
14
  .map((stream) => cleanTranscript(stream.toString('utf8')))
15
15
  .filter((stream) => stream.trim() !== '');
16
16
  if (streams.length === 0) {
@@ -22,19 +22,19 @@ export function formatElisionMarker(byteCount) {
22
22
  const unit = byteCount === 1 ? 'byte' : 'bytes';
23
23
  return `\n… nmr elided ${byteCount.toLocaleString('en-US')} ${unit} …\n`;
24
24
  }
25
- function alignEnd(buffer, end) {
26
- let aligned = Math.min(buffer.length, end);
27
- while (aligned > 0 && isContinuationByte(buffer[aligned])) {
28
- aligned--;
25
+ function alignEnd(buffer, endOffset) {
26
+ let alignedOffset = Math.min(buffer.length, endOffset);
27
+ while (alignedOffset > 0 && isContinuationByte(buffer[alignedOffset])) {
28
+ alignedOffset--;
29
29
  }
30
- return aligned;
30
+ return alignedOffset;
31
31
  }
32
- function alignStart(buffer, start) {
33
- let aligned = Math.max(0, start);
34
- while (aligned < buffer.length && isContinuationByte(buffer[aligned])) {
35
- aligned++;
32
+ function alignStart(buffer, startOffset) {
33
+ let alignedOffset = Math.max(0, startOffset);
34
+ while (alignedOffset < buffer.length && isContinuationByte(buffer[alignedOffset])) {
35
+ alignedOffset++;
36
36
  }
37
- return aligned;
37
+ return alignedOffset;
38
38
  }
39
39
  function clampTranscript(transcript) {
40
40
  const buffer = Buffer.from(transcript, 'utf8');
@@ -57,23 +57,23 @@ export function definePrettierConfig(options = {}) {
57
57
  function buildShellPlugin() {
58
58
  return {
59
59
  ...shPlugin,
60
- languages: shPlugin.languages.filter(isInferredLanguage).map(withoutExcludedFilenames),
60
+ languages: shPlugin.languages.filter(isInferredLanguage).map(dropExcludedFilenames),
61
61
  };
62
62
  }
63
63
  function isInferredLanguage(language) {
64
64
  return INFERRED_LANGUAGES.has(language.name);
65
65
  }
66
- function withoutExcludedFilenames(language) {
66
+ function dropExcludedFilenames(language) {
67
67
  if (language.filenames === undefined)
68
68
  return language;
69
69
  return { ...language, filenames: language.filenames.filter((name) => !EXCLUDED_FILENAMES.has(name)) };
70
70
  }
71
71
  function assertNoReplacement(options) {
72
72
  if ('overrides' in options)
73
- throw ownedKeyError('overrides', 'additionalOverrides');
73
+ throw buildOwnedKeyError('overrides', 'additionalOverrides');
74
74
  if ('plugins' in options)
75
- throw ownedKeyError('plugins', 'additionalPlugins');
75
+ throw buildOwnedKeyError('plugins', 'additionalPlugins');
76
76
  }
77
- function ownedKeyError(key, seam) {
77
+ function buildOwnedKeyError(key, seam) {
78
78
  return new TypeError(`definePrettierConfig: \`${key}\` is owned by this config. Use \`${seam}\` to append to it.`);
79
79
  }
@@ -28,12 +28,12 @@ export type KeyDifference = {
28
28
  ingredient: 'command-string';
29
29
  } | {
30
30
  ingredient: 'nmr-version';
31
- current: string;
32
- recorded: string;
31
+ currentVersion: string;
32
+ recordedVersion: string;
33
33
  } | {
34
34
  ingredient: 'node-version';
35
- current: string;
36
- recorded: string;
35
+ currentVersion: string;
36
+ recordedVersion: string;
37
37
  } | {
38
38
  ingredient: 'other';
39
39
  };
@@ -99,7 +99,7 @@ export declare function renderRefusal(options: {
99
99
  export declare function resolveRecording(options: {
100
100
  anchorDir: string;
101
101
  command: string;
102
- current: RunIdentity;
102
+ currentIdentity: RunIdentity;
103
103
  isCacheable: boolean;
104
104
  key: string | undefined;
105
105
  monorepoRoot: string;
@@ -27,7 +27,10 @@ export async function resolveRecording(options) {
27
27
  }
28
28
  const ageMs = Math.max(0, Date.now() - Date.parse(entry.recordedAt));
29
29
  if (entry.key !== options.key) {
30
- return { ok: false, refusal: { kind: 'mismatched', ageMs, difference: findKeyDifference(entry, options.current) } };
30
+ return {
31
+ ok: false,
32
+ refusal: { kind: 'mismatched', ageMs, difference: findKeyDifference(entry, options.currentIdentity) },
33
+ };
31
34
  }
32
35
  const transcript = await readTranscript({ anchorDir, command, monorepoRoot });
33
36
  if (transcript === undefined && (entry.retention?.replay.length ?? 0) === 0) {
@@ -45,14 +48,14 @@ function describeDifference(difference) {
45
48
  case 'command-string':
46
49
  return 'over a command chain this is not';
47
50
  case 'nmr-version':
48
- return `under nmr ${difference.recorded}, not ${difference.current}`;
51
+ return `under nmr ${difference.recordedVersion}, not ${difference.currentVersion}`;
49
52
  case 'node-version':
50
- return `under Node ${difference.recorded}, not ${difference.current}`;
53
+ return `under Node ${difference.recordedVersion}, not ${difference.currentVersion}`;
51
54
  case 'other':
52
55
  return 'under an install or environment this run does not share';
53
56
  default: {
54
- const unhandled = difference;
55
- throw new Error(`Unhandled key difference: ${JSON.stringify(unhandled)}`);
57
+ const unhandledDifference = difference;
58
+ throw new Error(`Unhandled key difference: ${JSON.stringify(unhandledDifference)}`);
56
59
  }
57
60
  }
58
61
  }
@@ -69,23 +72,27 @@ function describeRefusal(command, refusal) {
69
72
  case 'no-output':
70
73
  return `the pass ${formatDuration(refusal.ageMs)} ago retained none, as a run printing nothing or writing to a terminal does`;
71
74
  default: {
72
- const unhandled = refusal;
73
- throw new Error(`Unhandled refusal: ${JSON.stringify(unhandled)}`);
75
+ const unhandledRefusal = refusal;
76
+ throw new Error(`Unhandled refusal: ${JSON.stringify(unhandledRefusal)}`);
74
77
  }
75
78
  }
76
79
  }
77
- function findKeyDifference(entry, current) {
78
- if (current.treeHash !== undefined && entry.treeHash !== current.treeHash) {
80
+ function findKeyDifference(entry, currentIdentity) {
81
+ if (currentIdentity.treeHash !== undefined && entry.treeHash !== currentIdentity.treeHash) {
79
82
  return { ingredient: 'tree' };
80
83
  }
81
- if (entry.commandString !== current.commandString) {
84
+ if (entry.commandString !== currentIdentity.commandString) {
82
85
  return { ingredient: 'command-string' };
83
86
  }
84
- if (entry.nmrVersion !== current.nmrVersion) {
85
- return { ingredient: 'nmr-version', current: current.nmrVersion, recorded: entry.nmrVersion };
87
+ if (entry.nmrVersion !== currentIdentity.nmrVersion) {
88
+ return { ingredient: 'nmr-version', currentVersion: currentIdentity.nmrVersion, recordedVersion: entry.nmrVersion };
86
89
  }
87
- if (entry.nodeVersion !== current.nodeVersion) {
88
- return { ingredient: 'node-version', current: current.nodeVersion, recorded: entry.nodeVersion };
90
+ if (entry.nodeVersion !== currentIdentity.nodeVersion) {
91
+ return {
92
+ ingredient: 'node-version',
93
+ currentVersion: currentIdentity.nodeVersion,
94
+ recordedVersion: entry.nodeVersion,
95
+ };
89
96
  }
90
97
  return { ingredient: 'other' };
91
98
  }
@@ -47,5 +47,5 @@ export type ReportFormatRead = {
47
47
  export declare function resolveReportFormat(options: ResolveReportFormatOptions): ReportFormat;
48
48
  export interface ResolveReportFormatOptions {
49
49
  envFormat: ReportFormat | undefined;
50
- jsonFlag: boolean;
50
+ hasJsonFlag: boolean;
51
51
  }
@@ -6,20 +6,20 @@ export function isReportFormat(value) {
6
6
  return names.includes(value);
7
7
  }
8
8
  export function readReportFormatEnv(env) {
9
- const raw = env[REPORT_FORMAT_ENV_VAR];
10
- if (raw === undefined || raw === '') {
9
+ const rawValue = env[REPORT_FORMAT_ENV_VAR];
10
+ if (rawValue === undefined || rawValue === '') {
11
11
  return { ok: true };
12
12
  }
13
- if (!isReportFormat(raw)) {
14
- return { ok: false, error: formatReportFormatRejection(REPORT_FORMAT_ENV_VAR, raw) };
13
+ if (!isReportFormat(rawValue)) {
14
+ return { ok: false, error: formatReportFormatRejection(REPORT_FORMAT_ENV_VAR, rawValue) };
15
15
  }
16
- return { ok: true, format: raw };
16
+ return { ok: true, format: rawValue };
17
17
  }
18
18
  export const REPORT_FORMAT_ENV_VAR = 'NMR_REPORT_FORMAT';
19
19
  export const REPORT_FORMATS = ['text', 'json'];
20
20
  export function resolveReportFormat(options) {
21
- const { envFormat, jsonFlag } = options;
22
- if (jsonFlag)
21
+ const { envFormat, hasJsonFlag } = options;
22
+ if (hasJsonFlag)
23
23
  return 'json';
24
24
  return envFormat ?? 'text';
25
25
  }
@@ -3,14 +3,14 @@ import { describeInvalidOutputStyle } from '@williamthorsen/nmr-core';
3
3
  import { resolveOutputStyles } from "./output-style.js";
4
4
  import { UserError } from "./UserError.js";
5
5
  export function resolveBinStyles() {
6
- const { invalid, styles } = resolveOutputStyles({
6
+ const { invalid: invalidStyle, styles } = resolveOutputStyles({
7
7
  env: process.env,
8
8
  flagValue: undefined,
9
9
  stderrIsTty: process.stderr.isTTY,
10
10
  stdoutIsTty: process.stdout.isTTY,
11
11
  });
12
- if (invalid !== undefined) {
13
- throw new UserError(describeInvalidOutputStyle(invalid));
12
+ if (invalidStyle !== undefined) {
13
+ throw new UserError(describeInvalidOutputStyle(invalidStyle));
14
14
  }
15
15
  return styles;
16
16
  }
@@ -38,7 +38,7 @@ export interface ResolvedScript {
38
38
  * A bare string element and the `{ run }` spec compose the same step. The spec's only addition is the
39
39
  * declaration of what the step does with the invocation's trailing arguments, which position cannot carry.
40
40
  */
41
- export declare function expandScript(script: ScriptValue, workspaceRoot: boolean): readonly Step[];
41
+ export declare function expandScript(script: ScriptValue, isWorkspaceRoot: boolean): readonly Step[];
42
42
  /**
43
43
  * Returns a description of a script for help output.
44
44
  */
@@ -87,4 +87,4 @@ export declare function isSelfReferential(script: string, commandName: string, p
87
87
  * Returns undefined if the command is not found in the registry. A package.json override of `""` (indicating
88
88
  * skip) resolves to a single opaque step carrying it, which renders back to the empty string.
89
89
  */
90
- export declare function resolveScript(commandName: string, registry: ScriptRegistry, packageDir: string | undefined, workspaceRoot: boolean): ResolvedScript | undefined;
90
+ export declare function resolveScript(commandName: string, registry: ScriptRegistry, packageDir: string | undefined, isWorkspaceRoot: boolean): ResolvedScript | undefined;
@@ -12,13 +12,13 @@ export function applyDevBin(command, devBin, monorepoRoot) {
12
12
  }
13
13
  const spaceIndex = command.indexOf(' ');
14
14
  const firstToken = spaceIndex === -1 ? command : command.slice(0, spaceIndex);
15
- const rest = spaceIndex === -1 ? '' : command.slice(spaceIndex);
15
+ const restOfCommand = spaceIndex === -1 ? '' : command.slice(spaceIndex);
16
16
  const replacement = devBin[firstToken];
17
17
  if (replacement === undefined) {
18
18
  return command;
19
19
  }
20
20
  const resolvedReplacement = resolveReplacementPaths(replacement, monorepoRoot);
21
- return resolvedReplacement + rest;
21
+ return resolvedReplacement + restOfCommand;
22
22
  }
23
23
  export function applyDevBinToSteps(steps, devBin, monorepoRoot) {
24
24
  if (!devBin) {
@@ -40,13 +40,13 @@ function resolveReplacementPaths(replacement, monorepoRoot) {
40
40
  })
41
41
  .join(' ');
42
42
  }
43
- export function expandScript(script, workspaceRoot) {
43
+ export function expandScript(script, isWorkspaceRoot) {
44
44
  if (typeof script === 'string') {
45
45
  return [{ kind: 'opaque', command: script }];
46
46
  }
47
47
  return script.map((element) => typeof element === 'string'
48
- ? composeNmrStep(element, workspaceRoot)
49
- : composeNmrStep(element.run, workspaceRoot, element.shouldDeclineArguments));
48
+ ? composeNmrStep(element, isWorkspaceRoot)
49
+ : composeNmrStep(element.run, isWorkspaceRoot, element.shouldDeclineArguments));
50
50
  }
51
51
  export function describeScript(script) {
52
52
  return typeof script === 'string' ? script : `[${script.map(describeElement).join(', ')}]`;
@@ -59,9 +59,9 @@ function describeElement(element) {
59
59
  }
60
60
  export function readPackageJsonScripts(packageDir) {
61
61
  const file = resolvePackageJsonPath(packageDir);
62
- let raw;
62
+ let rawText;
63
63
  try {
64
- raw = readFileSync(file, 'utf8');
64
+ rawText = readFileSync(file, 'utf8');
65
65
  }
66
66
  catch (error) {
67
67
  if (hasErrnoCode(error, 'ENOENT')) {
@@ -69,10 +69,10 @@ export function readPackageJsonScripts(packageDir) {
69
69
  }
70
70
  throw error;
71
71
  }
72
- const parsed = parsePackageJson(raw, file);
73
- if (!isObject(parsed))
72
+ const parsedManifest = parsePackageJson(rawText, file);
73
+ if (!isObject(parsedManifest))
74
74
  return undefined;
75
- const scripts = parsed['scripts'];
75
+ const scripts = parsedManifest['scripts'];
76
76
  if (!isObject(scripts))
77
77
  return undefined;
78
78
  return readScriptRecord(packageDir, scripts);
@@ -108,15 +108,15 @@ export function findChainedSelfReference(packageDir, commandName) {
108
108
  export function isSelfReferential(script, commandName, packageDir) {
109
109
  return readSelfReference({ anchoredAtRoot: isMonorepoRoot(packageDir), commandName, script }) !== undefined;
110
110
  }
111
- export function resolveScript(commandName, registry, packageDir, workspaceRoot) {
111
+ export function resolveScript(commandName, registry, packageDir, isWorkspaceRoot) {
112
112
  if (packageDir) {
113
113
  const pkgScripts = readPackageJsonScripts(packageDir);
114
114
  if (pkgScripts && Object.hasOwn(pkgScripts, commandName)) {
115
- const override = pkgScripts[commandName];
116
- if (override !== undefined && !isSelfReferential(override, commandName, packageDir)) {
115
+ const overrideCommand = pkgScripts[commandName];
116
+ if (overrideCommand !== undefined && !isSelfReferential(overrideCommand, commandName, packageDir)) {
117
117
  return {
118
118
  origin: { tier: 'package', file: resolvePackageJsonPath(packageDir), key: commandName },
119
- steps: [{ kind: 'opaque', command: override }],
119
+ steps: [{ kind: 'opaque', command: overrideCommand }],
120
120
  };
121
121
  }
122
122
  }
@@ -128,5 +128,5 @@ export function resolveScript(commandName, registry, packageDir, workspaceRoot)
128
128
  if (registryEntry === undefined) {
129
129
  return undefined;
130
130
  }
131
- return { origin: { tier: 'registry', key: commandName }, steps: expandScript(registryEntry, workspaceRoot) };
131
+ return { origin: { tier: 'registry', key: commandName }, steps: expandScript(registryEntry, isWorkspaceRoot) };
132
132
  }