@williamthorsen/nmr 1.0.0 โ 2.0.1
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 +104 -0
- package/.readyup/kits/default.js +12 -28
- package/.readyup/manifest.json +19 -24
- package/CHANGELOG.md +33 -0
- package/README.md +9 -3
- package/dist/esm/check-cache-gate.d.ts +0 -3
- package/dist/esm/check-cache-gate.js +1 -5
- package/dist/esm/cli-build.js +3 -10
- package/dist/esm/cli-clean.js +1 -2
- package/dist/esm/cli-report-catalog.js +2 -3
- package/dist/esm/cli-report-overrides.js +3 -5
- package/dist/esm/commands/build-output.d.ts +7 -32
- package/dist/esm/commands/build-output.js +8 -13
- package/dist/esm/commands/build-report.d.ts +6 -0
- package/dist/esm/commands/build-report.js +21 -0
- package/dist/esm/commands/build.d.ts +27 -4
- package/dist/esm/commands/build.js +24 -86
- package/dist/esm/commands/clean-report.d.ts +6 -0
- package/dist/esm/commands/clean-report.js +20 -0
- package/dist/esm/commands/clean.d.ts +39 -7
- package/dist/esm/commands/clean.js +57 -34
- package/dist/esm/commands/compile.d.ts +5 -0
- package/dist/esm/commands/compile.js +32 -0
- package/dist/esm/commands/fmt.d.ts +11 -0
- package/dist/esm/commands/fmt.js +6 -2
- package/dist/esm/commands/publish-output.d.ts +40 -0
- package/dist/esm/commands/publish-output.js +66 -0
- package/dist/esm/commands/report-catalog.d.ts +5 -0
- package/dist/esm/commands/report-catalog.js +19 -0
- package/dist/esm/commands/report-overrides.d.ts +5 -0
- package/dist/esm/commands/report-overrides.js +20 -1
- package/dist/esm/config-validation.js +1 -14
- package/dist/esm/config.d.ts +1 -1
- package/dist/esm/crossing-diagnostics.d.ts +1 -1
- package/dist/esm/resolver.d.ts +0 -12
- package/dist/esm/resolver.js +0 -35
- package/dist/esm/run-chain.d.ts +1 -1
- package/dist/esm/run-chain.js +1 -5
- package/dist/esm/types.d.ts +0 -1
- package/docs/check-cache.md +0 -1
- package/docs/scripts.md +17 -12
- package/docs/upgrades.md +1 -1
- package/docs/utilities.md +2 -2
- package/package.json +8 -8
package/.meta/changelog.json
CHANGED
|
@@ -1,4 +1,108 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"date": "2026-11-11",
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "๐ Bug fixes",
|
|
8
|
+
"audience": "all",
|
|
9
|
+
"items": [
|
|
10
|
+
{
|
|
11
|
+
"description": "Fixes the issue that `nmr-clean`, `nmr-compile`, `nmr-report-catalog`, and `nmr-report-overrides` ignored their arguments, so `--help` or a mistyped option ran the command, and `nmr-clean --help` removed build output instead of printing usage. (#1273)",
|
|
12
|
+
"hash": "a4bfd2bc9c298a919c15070bae4437188c0edb37",
|
|
13
|
+
"entry": 1
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"title": "โป๏ธ Refactoring",
|
|
19
|
+
"audience": "dev",
|
|
20
|
+
"items": [
|
|
21
|
+
{
|
|
22
|
+
"description": "Adds an optional `spawn` adapter to `runPrettier` in `packages/nmr/src/commands/fmt.ts`, which defaults to `spawnSync` with inherited stdio, so that a test can replace the Prettier process without mocking `node:child_process`. (#1271)",
|
|
23
|
+
"hash": "18227bf9c7d8fb0fb11bf3382602be131603419a",
|
|
24
|
+
"entry": 1
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"description": "Extracts the unchanged-build skip report from `detectBuildChanges` into the exported `reportUnchangedBuild`, which takes the environment as a parameter rather than reading `process.env`. (#1272)",
|
|
28
|
+
"hash": "7708c82fe5b528709dd3c822c1449b6a843292c4",
|
|
29
|
+
"entry": 1
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"description": "Replaces the copies of the entry-point `glob` call in `buildPackage` and `hasBuildOutput` with one function, `resolveEntryPoints` in `build-output.ts`, so the build and the check cache's probe for build output cannot select different files. (#1274)",
|
|
33
|
+
"hash": "aadd160714f8a4b00aa9965897b97fb15ee8500b",
|
|
34
|
+
"entry": 1
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"description": "Moves the printing of the build's progress and outcome lines from `buildPackage` to `nmr-compile`, which renders the `BuildOutcome` returned by `buildPackage` and the events from its new `onProgress` callback through `build-report.ts`. (#1277)",
|
|
38
|
+
"hash": "7204e9ebbb7ef2d60f0ddf74a1ea4de4b62e50c0",
|
|
39
|
+
"entry": 1
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"description": "Moves the emit's staging, swap by rename, and scratch-directory handling from `build.ts` and `build-output.ts` into `publish-output.ts`, which `build.ts` now calls with the emit directory. (#1278)",
|
|
43
|
+
"hash": "27bc6915156ae739206679b977baf91267f73fa9",
|
|
44
|
+
"entry": 1
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"description": "Makes `cleanFrom` in `clean.ts` return a `CleanOutcome` and report each completed step through an `onProgress` callback rather than print, leaving `runClean` as the only function that prints, through the renderers in the new `clean-report.ts`. (#1279)",
|
|
48
|
+
"hash": "5188dd2411cd737d337ae8bf232fc68d5bc911c6",
|
|
49
|
+
"entry": 1
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"title": "๐งช Tests",
|
|
55
|
+
"audience": "dev",
|
|
56
|
+
"items": [
|
|
57
|
+
{
|
|
58
|
+
"description": "Moves the `runPrettier` cases from `fmt.tool.test.ts` to a new `fmt.unit.test.ts` that asserts on the invocations recorded by a spawn fake, and adds cases for a spawn error and for a Prettier process killed by a signal. (#1271)",
|
|
59
|
+
"hash": "18227bf9c7d8fb0fb11bf3382602be131603419a",
|
|
60
|
+
"entry": 2
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"description": "Replaces six skip-report cases in `build.publication.tool.test.ts`, each of which compiled a package to seed the cache, with unit tests of `reportUnchangedBuild` in `build.unit.test.ts` that write the recorded emit duration directly. (#1272)",
|
|
64
|
+
"hash": "7708c82fe5b528709dd3c822c1449b6a843292c4",
|
|
65
|
+
"entry": 2
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"description": "Tests `resolveEntryPoints` directly in `build-output.unit.test.ts` and removes the tool-tier tests in `build.tool.test.ts` that checked the same default exclusions, `ignorePatterns` override, and `extraIgnorePatterns` composition through a full build. (#1274)",
|
|
69
|
+
"hash": "aadd160714f8a4b00aa9965897b97fb15ee8500b",
|
|
70
|
+
"entry": 2
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"version": "2.0.0",
|
|
78
|
+
"date": "2026-11-10",
|
|
79
|
+
"sections": [
|
|
80
|
+
{
|
|
81
|
+
"title": "๐ชฆ Removed",
|
|
82
|
+
"audience": "all",
|
|
83
|
+
"items": [
|
|
84
|
+
{
|
|
85
|
+
"description": "Removes the `devBin` root-config field of `@williamthorsen/nmr`, which replaced the first token of a resolved command with a command that ran a bin from source. (#1269)",
|
|
86
|
+
"breaking": true,
|
|
87
|
+
"migration": "Replace each `devBin` entry by overriding the script that runs the bin in `rootScripts` or `workspaceScripts` with `node <path to the bin's source>`, and build an absolute path for a workspace script, because nmr no longer resolves relative paths from the monorepo root and a workspace script runs in each package's directory; a `package.json` script that runs the bin outranks the config, so change it in that `package.json`.",
|
|
88
|
+
"hash": "5a95865afe2560a4bb9e3f66448bd68f6a32c312",
|
|
89
|
+
"entry": 1
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"title": "โป๏ธ Refactoring",
|
|
95
|
+
"audience": "dev",
|
|
96
|
+
"items": [
|
|
97
|
+
{
|
|
98
|
+
"description": "Move the duplicated output-style resolver into nmr-core's cli entry (#1248)",
|
|
99
|
+
"body": "Replaces the duplicate `resolveStyles` modules in `release-kit` and `v11y-check` with one `resolveCliStyles` function, exported from `@williamthorsen/nmr-core/cli`. Each package still reads its own `RELEASE_KIT_OUTPUT_STYLE` or `V11Y_CHECK_OUTPUT_STYLE` variable and still reports a usage error for a value other than `auto`, `plain`, or `rich`.",
|
|
100
|
+
"hash": "c5f4ac68360ce550a7e53006a2a633b79f179f5f"
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
},
|
|
2
106
|
{
|
|
3
107
|
"version": "1.0.0",
|
|
4
108
|
"date": "2026-11-08",
|
package/.readyup/kits/default.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @noformat -- @generated. Do not edit. Compiled by rdy. */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
-
export const __readyupVersion = "0.45.
|
|
3
|
+
export const __readyupVersion = "0.45.1";
|
|
4
4
|
import { createRequire as __rdyCreateRequire } from 'node:module';
|
|
5
5
|
const require = __rdyCreateRequire(import.meta.url);
|
|
6
6
|
|
|
@@ -7382,12 +7382,12 @@ import { isRecord, listTrackedFiles } from "readyup/check-utils";
|
|
|
7382
7382
|
import { globSync } from "node:fs";
|
|
7383
7383
|
import { basename, join, sep } from "node:path";
|
|
7384
7384
|
|
|
7385
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.
|
|
7385
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.1/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/isError.js
|
|
7386
7386
|
function isError(error) {
|
|
7387
7387
|
return error instanceof Error || Object.prototype.toString.call(error) === "[object Error]";
|
|
7388
7388
|
}
|
|
7389
7389
|
|
|
7390
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.
|
|
7390
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.1/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/describeError.js
|
|
7391
7391
|
function describeError(error) {
|
|
7392
7392
|
try {
|
|
7393
7393
|
if (isError(error) && typeof error.message === "string" && error.message !== "") {
|
|
@@ -8162,11 +8162,11 @@ function formatMalformedScript(dir, key, value) {
|
|
|
8162
8162
|
return `${rejection} A step list belongs in \`${CONFIG_RELATIVE_PATH}\` under \`${field}\`.`;
|
|
8163
8163
|
}
|
|
8164
8164
|
|
|
8165
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8165
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/parseArgs.js
|
|
8166
8166
|
import path6 from "node:path";
|
|
8167
8167
|
import process2 from "node:process";
|
|
8168
8168
|
|
|
8169
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8169
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/UsageError.js
|
|
8170
8170
|
var UsageError = class extends Error {
|
|
8171
8171
|
constructor(message, options) {
|
|
8172
8172
|
super(message, options);
|
|
@@ -8174,7 +8174,7 @@ var UsageError = class extends Error {
|
|
|
8174
8174
|
}
|
|
8175
8175
|
};
|
|
8176
8176
|
|
|
8177
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8177
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/ParseError.js
|
|
8178
8178
|
var ParseError = class extends UsageError {
|
|
8179
8179
|
kind;
|
|
8180
8180
|
token;
|
|
@@ -8186,12 +8186,12 @@ var ParseError = class extends UsageError {
|
|
|
8186
8186
|
}
|
|
8187
8187
|
};
|
|
8188
8188
|
|
|
8189
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8189
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/resolveLongName.js
|
|
8190
8190
|
function resolveLongName(key, definition) {
|
|
8191
8191
|
return definition.long ?? key.replaceAll(/[A-Z]/g, (capital) => `-${capital.toLowerCase()}`);
|
|
8192
8192
|
}
|
|
8193
8193
|
|
|
8194
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8194
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/tokenizeArgs.js
|
|
8195
8195
|
import { parseArgs as nodeParseArgs } from "node:util";
|
|
8196
8196
|
function tokenizeArgs(argv, schema, extraBooleans = []) {
|
|
8197
8197
|
const nodeOptions = {};
|
|
@@ -8221,7 +8221,7 @@ function findFlagEntry(flagsByName, token) {
|
|
|
8221
8221
|
return entry.definition.short === token.rawName.slice(1) ? entry : void 0;
|
|
8222
8222
|
}
|
|
8223
8223
|
|
|
8224
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8224
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/validateSpec.js
|
|
8225
8225
|
var CAMEL_CASE_KEY = /^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]+)*$/;
|
|
8226
8226
|
function validateSpec(spec) {
|
|
8227
8227
|
validateFlags(spec.flags ?? {});
|
|
@@ -8302,7 +8302,7 @@ function validateOperands(operands) {
|
|
|
8302
8302
|
}
|
|
8303
8303
|
}
|
|
8304
8304
|
|
|
8305
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.
|
|
8305
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/parseArgs.js
|
|
8306
8306
|
function parseArgs(argv, spec, options = {}) {
|
|
8307
8307
|
validateSpec(spec);
|
|
8308
8308
|
return parseValidatedArgs(argv, spec, options);
|
|
@@ -8733,11 +8733,6 @@ function readPackageScripts(packageDir) {
|
|
|
8733
8733
|
}
|
|
8734
8734
|
}
|
|
8735
8735
|
|
|
8736
|
-
// src/helpers/type-guards.ts
|
|
8737
|
-
function isStringRecord(value) {
|
|
8738
|
-
return isRecord2(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
8739
|
-
}
|
|
8740
|
-
|
|
8741
8736
|
// src/verbosity.ts
|
|
8742
8737
|
var COMMAND_VERBOSITIES = ["full", "quiet"];
|
|
8743
8738
|
function formatVerbosityRejection(source, value) {
|
|
@@ -8752,7 +8747,7 @@ function isCommandVerbosity(value) {
|
|
|
8752
8747
|
var CONFIG_TIERS = {
|
|
8753
8748
|
root: {
|
|
8754
8749
|
label: "a monorepo-root config",
|
|
8755
|
-
honoredKeys: ["checkCache", "delegate", "
|
|
8750
|
+
honoredKeys: ["checkCache", "delegate", "output", "rootScripts", "selfHostedRunner", "workspaceScripts"],
|
|
8756
8751
|
elsewhere: "the package's own config"
|
|
8757
8752
|
},
|
|
8758
8753
|
workspace: {
|
|
@@ -8788,8 +8783,6 @@ function validateConfig(value, configPath, baseDir) {
|
|
|
8788
8783
|
const checkCache = validateCheckCacheField(value, configPath);
|
|
8789
8784
|
if (checkCache) config.checkCache = checkCache;
|
|
8790
8785
|
if (value["delegate"] !== void 0) config.delegate = validateDelegateField(value["delegate"], configPath);
|
|
8791
|
-
const devBin = validateStringRecordField(value, "devBin", configPath);
|
|
8792
|
-
if (devBin) config.devBin = devBin;
|
|
8793
8786
|
const output = validateOutputField(value, configPath);
|
|
8794
8787
|
if (output) config.output = output;
|
|
8795
8788
|
const workspaceScripts2 = validateScriptField(value, "workspaceScripts", configPath);
|
|
@@ -8960,15 +8953,6 @@ function validateScriptField(value, fieldName, configPath) {
|
|
|
8960
8953
|
assertValidElements(scripts, fieldName, configPath);
|
|
8961
8954
|
return scripts;
|
|
8962
8955
|
}
|
|
8963
|
-
function validateStringRecordField(value, fieldName, configPath) {
|
|
8964
|
-
if (!Object.hasOwn(value, fieldName) || value[fieldName] === void 0) {
|
|
8965
|
-
return void 0;
|
|
8966
|
-
}
|
|
8967
|
-
if (!isStringRecord(value[fieldName])) {
|
|
8968
|
-
throw new UserError(`Invalid nmr config at ${configPath}: \`${fieldName}\` must be a Record<string, string>`);
|
|
8969
|
-
}
|
|
8970
|
-
return value[fieldName];
|
|
8971
|
-
}
|
|
8972
8956
|
|
|
8973
8957
|
// src/helpers/escapeControlCharacters.ts
|
|
8974
8958
|
var NAMED_ESCAPES = /* @__PURE__ */ new Map([
|
|
@@ -9611,7 +9595,7 @@ function hasSupportedStrictLintVersion() {
|
|
|
9611
9595
|
});
|
|
9612
9596
|
}
|
|
9613
9597
|
function getMinVersion() {
|
|
9614
|
-
const pickedFields = { "version": "
|
|
9598
|
+
const pickedFields = { "version": "2.0.1" };
|
|
9615
9599
|
if (typeof pickedFields["version"] !== "string") {
|
|
9616
9600
|
throw new TypeError("nmr/package.json: 'version' must be a string");
|
|
9617
9601
|
}
|
package/.readyup/manifest.json
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
"kits": [
|
|
4
4
|
{
|
|
5
5
|
"bundledDependencies": {
|
|
6
|
-
"@williamthorsen/toolbelt.arrays": "6.4.
|
|
7
|
-
"@williamthorsen/toolbelt.cli": "0.8.
|
|
8
|
-
"@williamthorsen/toolbelt.datetime": "4.1.
|
|
9
|
-
"@williamthorsen/toolbelt.errors": "0.9.
|
|
10
|
-
"@williamthorsen/toolbelt.filesystem": "0.10.
|
|
11
|
-
"@williamthorsen/toolbelt.guards": "4.2.
|
|
12
|
-
"@williamthorsen/toolbelt.numbers": "7.3.
|
|
13
|
-
"@williamthorsen/toolbelt.objects": "4.4.
|
|
14
|
-
"@williamthorsen/toolbelt.packaging": "0.7.
|
|
6
|
+
"@williamthorsen/toolbelt.arrays": "6.4.2",
|
|
7
|
+
"@williamthorsen/toolbelt.cli": "0.8.1",
|
|
8
|
+
"@williamthorsen/toolbelt.datetime": "4.1.2",
|
|
9
|
+
"@williamthorsen/toolbelt.errors": "0.9.1",
|
|
10
|
+
"@williamthorsen/toolbelt.filesystem": "0.10.1",
|
|
11
|
+
"@williamthorsen/toolbelt.guards": "4.2.1",
|
|
12
|
+
"@williamthorsen/toolbelt.numbers": "7.3.2",
|
|
13
|
+
"@williamthorsen/toolbelt.objects": "4.4.1",
|
|
14
|
+
"@williamthorsen/toolbelt.packaging": "0.7.1",
|
|
15
15
|
"@williamthorsen/toolbelt.sets": "3.1.0",
|
|
16
|
-
"@williamthorsen/toolbelt.strings": "8.2.
|
|
16
|
+
"@williamthorsen/toolbelt.strings": "8.2.2",
|
|
17
17
|
"@williamthorsen/toolbelt.terminal": "0.3.0",
|
|
18
|
-
"ansi-regex": "6.
|
|
18
|
+
"ansi-regex": "6.6.0",
|
|
19
19
|
"ansi-styles": "6.2.3",
|
|
20
20
|
"cli-truncate": "6.1.1",
|
|
21
21
|
"diff": "9.0.0",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"checklist": "nmr",
|
|
33
33
|
"checks": [
|
|
34
34
|
"@williamthorsen/nmr in devDependencies",
|
|
35
|
-
"@williamthorsen/nmr >=
|
|
35
|
+
"@williamthorsen/nmr >= 2.0.1",
|
|
36
36
|
"pnpm-workspace.yaml exists",
|
|
37
37
|
"catalogued dependencies use catalog:",
|
|
38
38
|
"package.json has packageManager field",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"path": "../../nmr-core/dist/esm/cache/cache-store.js"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"hash": "
|
|
89
|
+
"hash": "6ea2c3c0",
|
|
90
90
|
"kind": "module",
|
|
91
91
|
"path": "../../nmr-core/dist/esm/cli.js"
|
|
92
92
|
},
|
|
@@ -236,7 +236,7 @@
|
|
|
236
236
|
"path": "lib/workspace-build.ts"
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
|
-
"hash": "
|
|
239
|
+
"hash": "c0b5a504",
|
|
240
240
|
"kind": "inline",
|
|
241
241
|
"path": "../package.json",
|
|
242
242
|
"paths": [
|
|
@@ -254,12 +254,12 @@
|
|
|
254
254
|
"path": "../src/config-check-cache.ts"
|
|
255
255
|
},
|
|
256
256
|
{
|
|
257
|
-
"hash": "
|
|
257
|
+
"hash": "d25aef4f",
|
|
258
258
|
"kind": "module",
|
|
259
259
|
"path": "../src/config-validation.ts"
|
|
260
260
|
},
|
|
261
261
|
{
|
|
262
|
-
"hash": "
|
|
262
|
+
"hash": "d345a285",
|
|
263
263
|
"kind": "module",
|
|
264
264
|
"path": "../src/config.ts"
|
|
265
265
|
},
|
|
@@ -308,11 +308,6 @@
|
|
|
308
308
|
"kind": "module",
|
|
309
309
|
"path": "../src/helpers/reportClosing.ts"
|
|
310
310
|
},
|
|
311
|
-
{
|
|
312
|
-
"hash": "3f8448c9",
|
|
313
|
-
"kind": "module",
|
|
314
|
-
"path": "../src/helpers/type-guards.ts"
|
|
315
|
-
},
|
|
316
311
|
{
|
|
317
312
|
"hash": "77f6bb50",
|
|
318
313
|
"kind": "module",
|
|
@@ -324,7 +319,7 @@
|
|
|
324
319
|
"path": "../src/resolve-scripts.ts"
|
|
325
320
|
},
|
|
326
321
|
{
|
|
327
|
-
"hash": "
|
|
322
|
+
"hash": "0112952e",
|
|
328
323
|
"kind": "module",
|
|
329
324
|
"path": "../src/resolver.ts"
|
|
330
325
|
},
|
|
@@ -361,10 +356,10 @@
|
|
|
361
356
|
],
|
|
362
357
|
"name": "default",
|
|
363
358
|
"path": "kits/default.js",
|
|
364
|
-
"readyupVersion": "0.45.
|
|
359
|
+
"readyupVersion": "0.45.1",
|
|
365
360
|
"source": "kits/default.ts",
|
|
366
361
|
"sourceHash": "9fd61bf4",
|
|
367
|
-
"targetHash": "
|
|
362
|
+
"targetHash": "8eca943d"
|
|
368
363
|
}
|
|
369
364
|
]
|
|
370
365
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 2.0.1 โ 2026-11-11
|
|
6
|
+
|
|
7
|
+
### ๐ Bug fixes
|
|
8
|
+
|
|
9
|
+
- Fixes the issue that `nmr-clean`, `nmr-compile`, `nmr-report-catalog`, and `nmr-report-overrides` ignored their arguments, so `--help` or a mistyped option ran the command, and `nmr-clean --help` removed build output instead of printing usage. (#1273)
|
|
10
|
+
|
|
11
|
+
### โป๏ธ Refactoring
|
|
12
|
+
|
|
13
|
+
- Adds an optional `spawn` adapter to `runPrettier` in `packages/nmr/src/commands/fmt.ts`, which defaults to `spawnSync` with inherited stdio, so that a test can replace the Prettier process without mocking `node:child_process`. (#1271)
|
|
14
|
+
- Extracts the unchanged-build skip report from `detectBuildChanges` into the exported `reportUnchangedBuild`, which takes the environment as a parameter rather than reading `process.env`. (#1272)
|
|
15
|
+
- Replaces the copies of the entry-point `glob` call in `buildPackage` and `hasBuildOutput` with one function, `resolveEntryPoints` in `build-output.ts`, so the build and the check cache's probe for build output cannot select different files. (#1274)
|
|
16
|
+
- Moves the printing of the build's progress and outcome lines from `buildPackage` to `nmr-compile`, which renders the `BuildOutcome` returned by `buildPackage` and the events from its new `onProgress` callback through `build-report.ts`. (#1277)
|
|
17
|
+
- Moves the emit's staging, swap by rename, and scratch-directory handling from `build.ts` and `build-output.ts` into `publish-output.ts`, which `build.ts` now calls with the emit directory. (#1278)
|
|
18
|
+
- Makes `cleanFrom` in `clean.ts` return a `CleanOutcome` and report each completed step through an `onProgress` callback rather than print, leaving `runClean` as the only function that prints, through the renderers in the new `clean-report.ts`. (#1279)
|
|
19
|
+
|
|
20
|
+
### ๐งช Tests
|
|
21
|
+
|
|
22
|
+
- Moves the `runPrettier` cases from `fmt.tool.test.ts` to a new `fmt.unit.test.ts` that asserts on the invocations recorded by a spawn fake, and adds cases for a spawn error and for a Prettier process killed by a signal. (#1271)
|
|
23
|
+
- Replaces six skip-report cases in `build.publication.tool.test.ts`, each of which compiled a package to seed the cache, with unit tests of `reportUnchangedBuild` in `build.unit.test.ts` that write the recorded emit duration directly. (#1272)
|
|
24
|
+
- Tests `resolveEntryPoints` directly in `build-output.unit.test.ts` and removes the tool-tier tests in `build.tool.test.ts` that checked the same default exclusions, `ignorePatterns` override, and `extraIgnorePatterns` composition through a full build. (#1274)
|
|
25
|
+
|
|
26
|
+
## 2.0.0 โ 2026-11-10
|
|
27
|
+
|
|
28
|
+
### ๐ชฆ Removed
|
|
29
|
+
|
|
30
|
+
- ๐จ **Breaking:** Removes the `devBin` root-config field of `@williamthorsen/nmr`, which replaced the first token of a resolved command with a command that ran a bin from source. (#1269)
|
|
31
|
+
|
|
32
|
+
### โป๏ธ Refactoring
|
|
33
|
+
|
|
34
|
+
- Move the duplicated output-style resolver into nmr-core's cli entry (#1248)
|
|
35
|
+
|
|
36
|
+
Replaces the duplicate `resolveStyles` modules in `release-kit` and `v11y-check` with one `resolveCliStyles` function, exported from `@williamthorsen/nmr-core/cli`. Each package still reads its own `RELEASE_KIT_OUTPUT_STYLE` or `V11Y_CHECK_OUTPUT_STYLE` variable and still reports a usage error for a value other than `auto`, `plain`, or `rich`.
|
|
37
|
+
|
|
5
38
|
## 1.0.0 โ 2026-11-08
|
|
6
39
|
|
|
7
40
|
### ๐งช Tests
|
package/README.md
CHANGED
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
Context-aware script runner for pnpm monorepos. Includes an `nmr` (node-monorepo run) binary that provides centralized, consistent script execution across workspace packages and the monorepo root.
|
|
6
6
|
|
|
7
|
-
<!-- section:release-notes
|
|
7
|
+
<!-- section:release-notes -->
|
|
8
|
+
## Release notes โ v2.0.1 (2026-11-11)
|
|
9
|
+
|
|
10
|
+
### ๐ Bug fixes
|
|
11
|
+
|
|
12
|
+
- Fixes the issue that `nmr-clean`, `nmr-compile`, `nmr-report-catalog`, and `nmr-report-overrides` ignored their arguments, so `--help` or a mistyped option ran the command, and `nmr-clean --help` removed build output instead of printing usage. (#1273)
|
|
13
|
+
<!-- /section:release-notes -->
|
|
8
14
|
|
|
9
15
|
## Installation
|
|
10
16
|
|
|
@@ -141,7 +147,7 @@ export default defineConfig({
|
|
|
141
147
|
});
|
|
142
148
|
```
|
|
143
149
|
|
|
144
|
-
[Scripts and configuration](docs/scripts.md#configuration) lists every `defineConfig` field
|
|
150
|
+
[Scripts and configuration](docs/scripts.md#configuration) lists every `defineConfig` field, covers package-level configuration, and shows how to run a workspace bin from source.
|
|
145
151
|
|
|
146
152
|
## What nmr reports
|
|
147
153
|
|
|
@@ -304,7 +310,7 @@ rdy list --from npm:@williamthorsen/nmr # what nmr publishes
|
|
|
304
310
|
|
|
305
311
|
## Documentation
|
|
306
312
|
|
|
307
|
-
- [Scripts and configuration](docs/scripts.md): Override tiers, script values, hooks, `defineConfig` fields,
|
|
313
|
+
- [Scripts and configuration](docs/scripts.md): Override tiers, script values, hooks, `defineConfig` fields, running a workspace bin from source, and the default commands
|
|
308
314
|
- [What nmr reports](docs/reporting.md): Verdicts, `--json`, output style, and verbosity
|
|
309
315
|
- [Check-result cache](docs/check-cache.md): What is skipped, what a hit requires, and replaying, reading, and bypassing recorded runs
|
|
310
316
|
- [Machine lock](docs/machine-lock.md): Which commands wait for one another, where the lock lives, and bypassing it
|
|
@@ -25,8 +25,6 @@ export declare function openGate(options: {
|
|
|
25
25
|
}): TreeSnapshot | undefined;
|
|
26
26
|
/**
|
|
27
27
|
* Computes the key under which this invocation would be recorded, or `undefined` when the cache does not apply.
|
|
28
|
-
* The cache does not apply to a `devBin` substitution: the substitute is built from a location that the tree id
|
|
29
|
-
* does not describe, so a pass by it is not a pass by the command that the key names.
|
|
30
28
|
*/
|
|
31
29
|
export declare function resolveCacheKey(options: {
|
|
32
30
|
anchorDir: string;
|
|
@@ -36,7 +34,6 @@ export declare function resolveCacheKey(options: {
|
|
|
36
34
|
monorepoRoot: string;
|
|
37
35
|
snapshot: TreeSnapshot | undefined;
|
|
38
36
|
stderr: Writable;
|
|
39
|
-
substitution: string | undefined;
|
|
40
37
|
}): string | undefined;
|
|
41
38
|
/**
|
|
42
39
|
* Runs the resolved steps behind the check-result cache: skips them when a recorded pass covers this
|
|
@@ -33,14 +33,10 @@ export function openGate(options) {
|
|
|
33
33
|
return snapshot.snapshot;
|
|
34
34
|
}
|
|
35
35
|
export function resolveCacheKey(options) {
|
|
36
|
-
const { env, snapshot, stderr
|
|
36
|
+
const { env, snapshot, stderr } = options;
|
|
37
37
|
if (snapshot === undefined) {
|
|
38
38
|
return undefined;
|
|
39
39
|
}
|
|
40
|
-
if (substitution !== undefined) {
|
|
41
|
-
writeDebugNote(`gate disabled: devBin substituted \`${substitution}\``, env, stderr);
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
40
|
const result = computeCacheKey({
|
|
45
41
|
anchorDir: options.anchorDir,
|
|
46
42
|
command: options.command,
|
package/dist/esm/cli-build.js
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
1
2
|
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
2
3
|
import { NMR_COMPILE_BIN } from "./bins.js";
|
|
3
|
-
import {
|
|
4
|
-
import { loadWorkspaceConfig } from "./config.js";
|
|
5
|
-
import { resolveBinStyles } from "./resolveBinStyles.js";
|
|
4
|
+
import { runCompile } from "./commands/compile.js";
|
|
6
5
|
try {
|
|
7
|
-
|
|
8
|
-
const packageDir = process.cwd();
|
|
9
|
-
const { build } = await loadWorkspaceConfig(packageDir);
|
|
10
|
-
await buildPackage(packageDir, {
|
|
11
|
-
style: stdout,
|
|
12
|
-
...(build?.extraIgnorePatterns !== undefined && { extraIgnorePatterns: build.extraIgnorePatterns }),
|
|
13
|
-
});
|
|
6
|
+
process.exitCode = await runCompile(process.argv.slice(2), process.cwd());
|
|
14
7
|
}
|
|
15
8
|
catch (error) {
|
|
16
9
|
reportFailure(NMR_COMPILE_BIN, error);
|
package/dist/esm/cli-clean.js
CHANGED
|
@@ -2,9 +2,8 @@ import process from 'node:process';
|
|
|
2
2
|
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { NMR_CLEAN_BIN } from "./bins.js";
|
|
4
4
|
import { runClean } from "./commands/clean.js";
|
|
5
|
-
import { resolveBinStyles } from "./resolveBinStyles.js";
|
|
6
5
|
try {
|
|
7
|
-
await runClean(process.
|
|
6
|
+
process.exitCode = await runClean(process.argv.slice(2), process.cwd());
|
|
8
7
|
}
|
|
9
8
|
catch (error) {
|
|
10
9
|
reportFailure(NMR_CLEAN_BIN, error);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { NMR_REPORT_CATALOG_BIN } from "./bins.js";
|
|
4
|
-
import {
|
|
5
|
-
import { resolveBinStyles } from "./resolveBinStyles.js";
|
|
4
|
+
import { runReportCatalog } from "./commands/report-catalog.js";
|
|
6
5
|
try {
|
|
7
|
-
|
|
6
|
+
process.exitCode = await runReportCatalog(process.argv.slice(2), process.cwd());
|
|
8
7
|
}
|
|
9
8
|
catch (error) {
|
|
10
9
|
reportFailure(NMR_REPORT_CATALOG_BIN, error);
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
1
2
|
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
2
3
|
import { NMR_REPORT_OVERRIDES_BIN } from "./bins.js";
|
|
3
|
-
import {
|
|
4
|
-
import { resolveBinStyles } from "./resolveBinStyles.js";
|
|
5
|
-
import { findMonorepoRoot } from "./workspace.js";
|
|
4
|
+
import { runReportOverrides } from "./commands/report-overrides.js";
|
|
6
5
|
try {
|
|
7
|
-
|
|
8
|
-
reportOverrides(monorepoRoot, resolveBinStyles().stderr);
|
|
6
|
+
process.exitCode = await runReportOverrides(process.argv.slice(2), process.cwd());
|
|
9
7
|
}
|
|
10
8
|
catch (error) {
|
|
11
9
|
reportFailure(NMR_REPORT_OVERRIDES_BIN, error);
|
|
@@ -6,28 +6,13 @@ export interface BuildOptions {
|
|
|
6
6
|
ignorePatterns?: string[];
|
|
7
7
|
outdir?: string;
|
|
8
8
|
}
|
|
9
|
-
/** The pair of directories through which a build publishes, both siblings of the emit directory. */
|
|
10
|
-
export interface ScratchDirs {
|
|
11
|
-
previousDir: string;
|
|
12
|
-
stagingDir: string;
|
|
13
|
-
}
|
|
14
|
-
export declare const DEFAULT_ENTRY_GLOBS: string[];
|
|
15
|
-
/**
|
|
16
|
-
* Directories holding test scaffolding rather than published code, excluded from entry-point selection so that a
|
|
17
|
-
* package does not publish its own helpers. The list differs from the vitest factory's `COVERAGE_EXCLUDE`, which
|
|
18
|
-
* leaves `test-utils/` inside the coverage include set, and neither list can be derived from the other.
|
|
19
|
-
*
|
|
20
|
-
* Ignoring a file removes it as an entry point, not from the emit. The compiler still emits whatever the
|
|
21
|
-
* surviving entry points import, which keeps a production module that uses a helper from emitting a dangling
|
|
22
|
-
* specifier. Widening this list can therefore only drop files that production code does not import.
|
|
23
|
-
*/
|
|
24
|
-
export declare const DEFAULT_IGNORE_PATTERNS: string[];
|
|
25
9
|
export declare const DEFAULT_OUTDIR = "dist/esm/";
|
|
26
10
|
/**
|
|
27
|
-
* Reports whether the output that a build of `packageDir` would produce is currently on disk.
|
|
28
|
-
*
|
|
29
|
-
* whether to rebuild cannot disagree: A package whose entry points emit
|
|
30
|
-
* reports present. Passing options that the build was not given would make
|
|
11
|
+
* Reports whether the output that a build of `packageDir` would produce is currently on disk. Selects entry points
|
|
12
|
+
* through `resolveEntryPoints` and tests them through `hasExpectedBuildOutput`, as the build does, so a caller
|
|
13
|
+
* probing for output and the build deciding whether to rebuild cannot disagree: A package whose entry points emit
|
|
14
|
+
* nothing does not expect any output, and reports present. Passing options that the build was not given would make
|
|
15
|
+
* the two disagree.
|
|
31
16
|
*/
|
|
32
17
|
export declare function hasBuildOutput(packageDir: string, options?: BuildOptions): Promise<boolean>;
|
|
33
18
|
/**
|
|
@@ -65,18 +50,8 @@ export declare function resolveBuildCachePath(packageDir: string): string;
|
|
|
65
50
|
* `readBuildDigest` returns.
|
|
66
51
|
*/
|
|
67
52
|
export declare function resolveEmitDurationPath(packageDir: string): string;
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
* and `previous`, which the outgoing output is renamed aside to. Both are siblings of the emit directory, so a
|
|
71
|
-
* rename between them never crosses a filesystem, and both are dot-prefixed so that a leftover stays out of the
|
|
72
|
-
* globs that select sources.
|
|
73
|
-
*
|
|
74
|
-
* The names are fixed rather than unique because the build removes both before use. A unique name would need a
|
|
75
|
-
* sweep to accomplish that removal, and a sweep cannot tell a directory orphaned by a killed run from one that a
|
|
76
|
-
* concurrent build is still writing. Because a directory left behind by a failed build is cleared the same way,
|
|
77
|
-
* the failure path does not need any cleanup of its own.
|
|
78
|
-
*/
|
|
79
|
-
export declare function resolveScratchDirs(emitDir: string): ScratchDirs;
|
|
53
|
+
/** Selects the entry points that a build of `packageDir` compiles, as paths relative to `packageDir`. */
|
|
54
|
+
export declare function resolveEntryPoints(packageDir: string, options?: BuildOptions): Promise<string[]>;
|
|
80
55
|
/**
|
|
81
56
|
* Resolves the fingerprint of the nmr compiling `packageDir`, the `BuildToolchain` member that identifies nmr. It
|
|
82
57
|
* is nmr's own build digest when one is on disk, which changes on a dev-loop edit that the version does not
|
|
@@ -3,17 +3,14 @@ import path from 'node:path';
|
|
|
3
3
|
import { findPackageRoot, readCacheEntry, readGuardedCacheEntry, resolveCacheEntryPath, writeGuardedCacheEntry, } from '@williamthorsen/nmr-core';
|
|
4
4
|
import { glob } from 'glob';
|
|
5
5
|
import { readPackageJson } from "../helpers/package-json.js";
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const DEFAULT_ENTRY_GLOBS = ['src/**/*.{ts,tsx}'];
|
|
7
|
+
const DEFAULT_IGNORE_PATTERNS = ['**/__fixtures__/**', '**/__mocks__/**', '**/__tests__/**', '**/test-utils/**'];
|
|
8
8
|
export const DEFAULT_OUTDIR = 'dist/esm/';
|
|
9
9
|
const BUILD_CACHE_TOOL = 'nmr-compile';
|
|
10
10
|
const SELF_DIR = findPackageRoot(import.meta.url);
|
|
11
11
|
export async function hasBuildOutput(packageDir, options = {}) {
|
|
12
12
|
const outdir = options.outdir ?? DEFAULT_OUTDIR;
|
|
13
|
-
const entryPoints = await
|
|
14
|
-
cwd: packageDir,
|
|
15
|
-
ignore: [...(options.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS), ...(options.extraIgnorePatterns ?? [])],
|
|
16
|
-
});
|
|
13
|
+
const entryPoints = await resolveEntryPoints(packageDir, options);
|
|
17
14
|
return hasExpectedBuildOutput(packageDir, outdir, entryPoints);
|
|
18
15
|
}
|
|
19
16
|
export function hasExpectedBuildOutput(packageDir, outdir, entryPoints) {
|
|
@@ -49,13 +46,11 @@ export function resolveEmitDurationPath(packageDir) {
|
|
|
49
46
|
extension: '.duration.json',
|
|
50
47
|
});
|
|
51
48
|
}
|
|
52
|
-
export function
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
stagingDir: path.join(parent, `.${name}.staging`),
|
|
58
|
-
};
|
|
49
|
+
export async function resolveEntryPoints(packageDir, options = {}) {
|
|
50
|
+
return glob(options.entryGlobs ?? DEFAULT_ENTRY_GLOBS, {
|
|
51
|
+
cwd: packageDir,
|
|
52
|
+
ignore: [...(options.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS), ...(options.extraIgnorePatterns ?? [])],
|
|
53
|
+
});
|
|
59
54
|
}
|
|
60
55
|
export async function resolveToolchainFingerprint(packageDir, selfDir = SELF_DIR) {
|
|
61
56
|
if (!isSameDir(packageDir, selfDir)) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type OutputStyle } from '@williamthorsen/nmr-core';
|
|
2
|
+
import type { BuildOutcome, BuildProgress } from './build.js';
|
|
3
|
+
/** Renders the line that closes a build: the skip, naming the saving when it is worth naming, or the emit. */
|
|
4
|
+
export declare function renderBuildOutcome(outcome: BuildOutcome, packageName: string, style: OutputStyle): string;
|
|
5
|
+
/** Renders the line that announces an emit, naming why the build is about to run. */
|
|
6
|
+
export declare function renderBuildProgress(progress: BuildProgress, packageName: string, style: OutputStyle): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { formatGlyphLine, STATUS_GLYPHS } from '@williamthorsen/nmr-core';
|
|
2
|
+
import { NMR_GLYPHS } from "../glyphs.js";
|
|
3
|
+
import { formatSaving } from "../helpers/duration.js";
|
|
4
|
+
export function renderBuildOutcome(outcome, packageName, style) {
|
|
5
|
+
if (outcome.kind === 'unchanged') {
|
|
6
|
+
const saving = formatSaving(outcome.savedMs ?? 0);
|
|
7
|
+
const savingClause = saving === undefined ? '' : `, ${saving}`;
|
|
8
|
+
return `${STATUS_GLYPHS[style].skipped.text} ${packageName}: No changes detected. Skipping build${savingClause}.`;
|
|
9
|
+
}
|
|
10
|
+
return formatGlyphLine(NMR_GLYPHS, style, 'package', `${packageName}: ${describeEmit(outcome.fileCount, outcome.outdir)}`);
|
|
11
|
+
}
|
|
12
|
+
export function renderBuildProgress(progress, packageName, style) {
|
|
13
|
+
const message = progress.kind === 'output-missing' ? 'Build output is missing. Rebuilding.' : 'Changes detected.';
|
|
14
|
+
return formatGlyphLine(NMR_GLYPHS, style, 'package', `${packageName}: ${message}`);
|
|
15
|
+
}
|
|
16
|
+
function describeEmit(fileCount, outdir) {
|
|
17
|
+
if (fileCount === 0) {
|
|
18
|
+
return 'Did not emit any output.';
|
|
19
|
+
}
|
|
20
|
+
return `Compiled ${fileCount} files to ${outdir.replace(/\/+$/u, '')}.`;
|
|
21
|
+
}
|