@williamthorsen/nmr 0.54.0 → 0.55.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 +65 -0
- package/.readyup/kits/default.js +25 -10
- package/.readyup/manifest.json +26 -20
- package/CHANGELOG.md +22 -0
- package/README.md +10 -3
- package/bin/ensure-prepublish-hooks.js +6 -2
- package/bin/nmr-actionlint.js +6 -2
- package/bin/nmr-clean.js +6 -2
- package/bin/nmr-compile.js +6 -2
- package/bin/nmr-fmt.js +6 -2
- package/bin/nmr-report-catalog.js +6 -2
- package/bin/nmr-report-overrides.js +6 -2
- package/bin/nmr-shellcheck.js +15 -0
- package/bin/nmr-taze.js +6 -2
- package/bin/nmr-vitest.js +6 -2
- package/bin/nmr.js +6 -2
- package/dist/esm/check-cache.js +1 -0
- package/dist/esm/child-process.js +1 -1
- package/dist/esm/cli-actionlint.js +2 -3
- package/dist/esm/cli-build.js +2 -3
- package/dist/esm/cli-clean.js +2 -3
- package/dist/esm/cli-ensure-prepublish-hooks.js +2 -3
- package/dist/esm/cli-fmt.js +8 -1
- package/dist/esm/cli-report-catalog.js +2 -3
- package/dist/esm/cli-report-overrides.js +2 -3
- package/dist/esm/cli-shellcheck.d.ts +1 -0
- package/dist/esm/cli-shellcheck.js +11 -0
- package/dist/esm/cli-taze.js +2 -3
- package/dist/esm/cli-vitest.js +8 -1
- package/dist/esm/cli.js +2 -2
- package/dist/esm/commands/actionlint.js +2 -1
- package/dist/esm/commands/build.js +9 -6
- package/dist/esm/commands/clean.js +2 -2
- package/dist/esm/commands/compiler.js +3 -3
- package/dist/esm/commands/ensure-prepublish-hooks.js +10 -3
- package/dist/esm/commands/node-pin.js +1 -1
- package/dist/esm/commands/report-overrides.js +1 -2
- package/dist/esm/commands/rewrite-specifiers.js +3 -2
- package/dist/esm/commands/shellcheck.d.ts +25 -0
- package/dist/esm/commands/shellcheck.js +41 -0
- package/dist/esm/commands/tsconfig-chain.js +4 -3
- package/dist/esm/commands/workflow-tools.js +10 -8
- package/dist/esm/config-check-cache.js +1 -1
- package/dist/esm/config-validation.js +1 -1
- package/dist/esm/config.js +1 -1
- package/dist/esm/crossing-diagnostics.js +1 -2
- package/dist/esm/default-scripts.js +1 -0
- package/dist/esm/delegation-target.d.ts +5 -4
- package/dist/esm/delegation-target.js +15 -0
- package/dist/esm/entry-chain.js +1 -1
- package/dist/esm/helpers/deriveExcerpt.js +1 -1
- package/dist/esm/helpers/duration.js +1 -1
- package/dist/esm/helpers/package-json.js +1 -1
- package/dist/esm/machine-lock.js +1 -1
- package/dist/esm/pass-manifest.js +2 -3
- package/dist/esm/remote-host-session.js +2 -2
- package/dist/esm/resolveBinStyles.js +1 -2
- package/dist/esm/user-config.js +1 -1
- package/dist/esm/vitest-source-resolution.js +1 -1
- package/dist/esm/workspace.js +1 -1
- package/docs/check-cache.md +1 -1
- package/docs/delegate.md +7 -5
- package/docs/scripts.md +4 -0
- package/docs/utilities.md +9 -1
- package/package.json +6 -5
- package/dist/esm/UserError.d.ts +0 -8
- package/dist/esm/UserError.js +0 -6
- package/dist/esm/reportCliFailure.d.ts +0 -9
- package/dist/esm/reportCliFailure.js +0 -11
package/.meta/changelog.json
CHANGED
|
@@ -1,4 +1,69 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.55.0",
|
|
4
|
+
"date": "2026-11-06",
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "🎉 Features",
|
|
8
|
+
"audience": "all",
|
|
9
|
+
"items": [
|
|
10
|
+
{
|
|
11
|
+
"description": "Adds the built-in root command `lint:shell`, which runs the new `nmr-shellcheck` bin to lint every tracked `*.sh` file with nmr's pinned shellcheck and passes without downloading shellcheck when the repo does not track any. (#1161)",
|
|
12
|
+
"hash": "d5cb485398fbc00f81b5533bd8c71033d81e6026",
|
|
13
|
+
"entry": 1
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"description": "Adds a warning to nmr's readyup kit that reports a `lint:shell` entry in `.config/nmr.config.ts`, which overrides the built-in command, and directs the repo to delete the entry. (#1161)",
|
|
17
|
+
"hash": "d5cb485398fbc00f81b5533bd8c71033d81e6026",
|
|
18
|
+
"entry": 2
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"title": "🐛 Bug fixes",
|
|
24
|
+
"audience": "all",
|
|
25
|
+
"items": [
|
|
26
|
+
{
|
|
27
|
+
"description": "Adopt the crash convention in release-kit (#1158)",
|
|
28
|
+
"body": "Makes `release-kit` report a bug in its own code as `release-kit: internal error: <message>` followed by the stack, rather than as the `Error: <message>` line that it keeps for a failure in the user's input, config, or environment. The same change makes `nmr` and `v11y-check` print a Node system error, such as `EACCES` or `ENOENT`, as `Error: <message>` rather than as an internal error.",
|
|
29
|
+
"hash": "3a62cc768b23f37156c846f32fd4acaa70f7f931"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"version": "0.54.1",
|
|
37
|
+
"date": "2026-11-05",
|
|
38
|
+
"sections": [
|
|
39
|
+
{
|
|
40
|
+
"title": "🐛 Bug fixes",
|
|
41
|
+
"audience": "all",
|
|
42
|
+
"items": [
|
|
43
|
+
{
|
|
44
|
+
"description": "Fixes the issue that `pnpm add` failed when an install hook such as `postinstall` ran an nmr command delegated by `NMR_DELEGATE` or the user config, because the host's frozen install rejected a manifest that was ahead of its lockfile, by making nmr run such a command on this machine unless `--delegate` or `--delegate-to` is passed. (#1151)",
|
|
45
|
+
"hash": "0037919912a86b9bf927e1afccf079956d6c2968",
|
|
46
|
+
"entry": 1
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"description": "Fixes the issue that `nmr` printed an unexpected crash as its raw stack, whose first line, `Error: <message>`, read the same as a handled error; it now prints `nmr: internal error: <message>` followed by the stack frames, and still prints an error caused by the user's own config as `Error: <message>`. (#1153)",
|
|
50
|
+
"hash": "0289c032b00438984efcf7466f2b3055b4dbc546",
|
|
51
|
+
"entry": 1
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"description": "Fixes the issue that the `nmr` sub-bins, such as `nmr-compile` and `nmr-fmt`, and the `v11y` subcommands reported an unexpected crash as a handled `Error: <message>` line, rather than as `<bin>: internal error: <message>` with its stack frames. (#1157)",
|
|
55
|
+
"hash": "ef1ed5f50bf0b01f19b6d6fe82a40322a8286002",
|
|
56
|
+
"entry": 1
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"description": "Fixes the issue that the bin scripts of `nmr`, `release-kit`, and `v11y-check` reported every error other than missing build output as `<bin>: failed to load: <message>` without a stack, which hid where the fault occurred. (#1157)",
|
|
60
|
+
"hash": "ef1ed5f50bf0b01f19b6d6fe82a40322a8286002",
|
|
61
|
+
"entry": 2
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
2
67
|
{
|
|
3
68
|
"version": "0.54.0",
|
|
4
69
|
"date": "2026-10-31",
|
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.
|
|
3
|
+
export const __readyupVersion = "0.45.0";
|
|
4
4
|
import { createRequire as __rdyCreateRequire } from 'node:module';
|
|
5
5
|
const require = __rdyCreateRequire(import.meta.url);
|
|
6
6
|
|
|
@@ -7691,6 +7691,7 @@ function buildRootScripts(workspaceGlobs) {
|
|
|
7691
7691
|
"fmt:check": "nmr-fmt --check",
|
|
7692
7692
|
lint: "eslint --fix .",
|
|
7693
7693
|
"lint:check": "eslint .",
|
|
7694
|
+
"lint:shell": "nmr-shellcheck",
|
|
7694
7695
|
"lint:strict": "strict-lint",
|
|
7695
7696
|
"lint:workflows": "nmr-actionlint",
|
|
7696
7697
|
// The audit takes seconds and `ci` takes minutes, so the cheap gate fails first. The audit reads the
|
|
@@ -7829,10 +7830,15 @@ function readWorkspaceManifest(monorepoRoot) {
|
|
|
7829
7830
|
}
|
|
7830
7831
|
}
|
|
7831
7832
|
|
|
7832
|
-
//
|
|
7833
|
+
// ../nmr-core/dist/esm/hasErrnoCode.js
|
|
7834
|
+
function hasErrnoCode(error, code) {
|
|
7835
|
+
return isError(error) && "code" in error && error.code === code;
|
|
7836
|
+
}
|
|
7837
|
+
|
|
7838
|
+
// ../nmr-core/dist/esm/UserError.js
|
|
7833
7839
|
var UserError = class extends Error {
|
|
7834
|
-
constructor(message) {
|
|
7835
|
-
super(message);
|
|
7840
|
+
constructor(message, options) {
|
|
7841
|
+
super(message, options);
|
|
7836
7842
|
this.name = "UserError";
|
|
7837
7843
|
}
|
|
7838
7844
|
};
|
|
@@ -7875,6 +7881,8 @@ var INSTALL_LIFECYCLE_SCRIPTS = [
|
|
|
7875
7881
|
];
|
|
7876
7882
|
var LEFTHOOK_CHECK_INSTALL_PATTERN = /\blefthook\s+check-install\b/;
|
|
7877
7883
|
var LEFTHOOK_INSTALL_PATTERN = /\blefthook\s+install\b/;
|
|
7884
|
+
var LINT_SHELL_KEY_PATTERN = /['"]lint:shell['"]\s*:/;
|
|
7885
|
+
var NMR_CONFIG_PATH = ".config/nmr.config.ts";
|
|
7878
7886
|
var rootScriptChecks = [
|
|
7879
7887
|
{
|
|
7880
7888
|
name: "root package.json has no nmr-provided scripts",
|
|
@@ -7882,6 +7890,13 @@ var rootScriptChecks = [
|
|
|
7882
7890
|
quiet: true,
|
|
7883
7891
|
check: noRedundantRootScripts,
|
|
7884
7892
|
fix: "Remove scripts from root package.json that nmr provides as built-in root scripts, and invoke them through nmr directly"
|
|
7893
|
+
},
|
|
7894
|
+
{
|
|
7895
|
+
name: ".config/nmr.config.ts does not override lint:shell",
|
|
7896
|
+
severity: "warn",
|
|
7897
|
+
quiet: true,
|
|
7898
|
+
check: () => noLintShellOverride(),
|
|
7899
|
+
fix: "Delete the `lint:shell` entry from `rootScripts` in .config/nmr.config.ts, because nmr provides `lint:shell` as a built-in root command that passes when the repo does not track any shell script"
|
|
7885
7900
|
}
|
|
7886
7901
|
];
|
|
7887
7902
|
var gitHookChecks = [
|
|
@@ -7909,6 +7924,11 @@ var legacyRunnerChecks = [
|
|
|
7909
7924
|
fix: 'Remove "ws" script entries and replace any "pnpm run ws" invocations with nmr in each packages/*/package.json'
|
|
7910
7925
|
}
|
|
7911
7926
|
];
|
|
7927
|
+
function noLintShellOverride(cwd = process.cwd()) {
|
|
7928
|
+
const content = readFileIn(cwd, NMR_CONFIG_PATH);
|
|
7929
|
+
if (content === void 0 || !LINT_SHELL_KEY_PATTERN.test(content)) return true;
|
|
7930
|
+
return { ok: false, detail: `${NMR_CONFIG_PATH}: rootScripts.lint:shell` };
|
|
7931
|
+
}
|
|
7912
7932
|
function noUnguardedLefthookInstall(cwd = process.cwd()) {
|
|
7913
7933
|
const scripts = readRootScripts(cwd);
|
|
7914
7934
|
const unguardedScripts = INSTALL_LIFECYCLE_SCRIPTS.flatMap((name) => {
|
|
@@ -8026,11 +8046,6 @@ function isHookName(key) {
|
|
|
8026
8046
|
// src/resolver.ts
|
|
8027
8047
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
8028
8048
|
|
|
8029
|
-
// ../nmr-core/dist/esm/hasErrnoCode.js
|
|
8030
|
-
function hasErrnoCode(error, code) {
|
|
8031
|
-
return isError(error) && "code" in error && error.code === code;
|
|
8032
|
-
}
|
|
8033
|
-
|
|
8034
8049
|
// src/helpers/package-json.ts
|
|
8035
8050
|
import path5 from "node:path";
|
|
8036
8051
|
|
|
@@ -9190,7 +9205,7 @@ function hasSupportedStrictLintVersion() {
|
|
|
9190
9205
|
});
|
|
9191
9206
|
}
|
|
9192
9207
|
function getMinVersion() {
|
|
9193
|
-
const pickedFields = { "version": "0.
|
|
9208
|
+
const pickedFields = { "version": "0.55.0" };
|
|
9194
9209
|
if (typeof pickedFields["version"] !== "string") {
|
|
9195
9210
|
throw new TypeError("nmr/package.json: 'version' must be a string");
|
|
9196
9211
|
}
|
package/.readyup/manifest.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"checklist": "nmr",
|
|
28
28
|
"checks": [
|
|
29
29
|
"@williamthorsen/nmr in devDependencies",
|
|
30
|
-
"@williamthorsen/nmr >= 0.
|
|
30
|
+
"@williamthorsen/nmr >= 0.55.0",
|
|
31
31
|
"pnpm-workspace.yaml exists",
|
|
32
32
|
"catalogued dependencies use catalog:",
|
|
33
33
|
"package.json has packageManager field",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"eslint >= 10.0.0",
|
|
39
39
|
"@williamthorsen/strict-lint >= 9.3.0",
|
|
40
40
|
"root package.json has no nmr-provided scripts",
|
|
41
|
+
".config/nmr.config.ts does not override lint:shell",
|
|
41
42
|
"no root install script runs lefthook install unguarded",
|
|
42
43
|
"all workspace packages can build",
|
|
43
44
|
"every bin target is a committed wrapper",
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
"path": "../../nmr-core/dist/esm/gitObjects.js"
|
|
90
91
|
},
|
|
91
92
|
{
|
|
92
|
-
"hash": "
|
|
93
|
+
"hash": "d5a89448",
|
|
93
94
|
"kind": "module",
|
|
94
95
|
"path": "../../nmr-core/dist/esm/gitOutputLimit.js"
|
|
95
96
|
},
|
|
@@ -109,12 +110,17 @@
|
|
|
109
110
|
"path": "../../nmr-core/dist/esm/helpers/workspace-patterns.js"
|
|
110
111
|
},
|
|
111
112
|
{
|
|
112
|
-
"hash": "
|
|
113
|
+
"hash": "76923c93",
|
|
113
114
|
"kind": "module",
|
|
114
115
|
"path": "../../nmr-core/dist/esm/index.js"
|
|
115
116
|
},
|
|
116
117
|
{
|
|
117
|
-
"hash": "
|
|
118
|
+
"hash": "85d76864",
|
|
119
|
+
"kind": "module",
|
|
120
|
+
"path": "../../nmr-core/dist/esm/isAnticipatedFailure.js"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"hash": "de51ceb3",
|
|
118
124
|
"kind": "module",
|
|
119
125
|
"path": "../../nmr-core/dist/esm/parseArgs.js"
|
|
120
126
|
},
|
|
@@ -124,7 +130,7 @@
|
|
|
124
130
|
"path": "../../nmr-core/dist/esm/runGit.js"
|
|
125
131
|
},
|
|
126
132
|
{
|
|
127
|
-
"hash": "
|
|
133
|
+
"hash": "01ad20df",
|
|
128
134
|
"kind": "module",
|
|
129
135
|
"path": "../../nmr-core/dist/esm/terminal.js"
|
|
130
136
|
},
|
|
@@ -138,6 +144,11 @@
|
|
|
138
144
|
"kind": "module",
|
|
139
145
|
"path": "../../nmr-core/dist/esm/updateManagedFile.js"
|
|
140
146
|
},
|
|
147
|
+
{
|
|
148
|
+
"hash": "e02e0a74",
|
|
149
|
+
"kind": "module",
|
|
150
|
+
"path": "../../nmr-core/dist/esm/UserError.js"
|
|
151
|
+
},
|
|
141
152
|
{
|
|
142
153
|
"hash": "00d00fae",
|
|
143
154
|
"kind": "module",
|
|
@@ -179,7 +190,7 @@
|
|
|
179
190
|
"path": "lib/repo-files.ts"
|
|
180
191
|
},
|
|
181
192
|
{
|
|
182
|
-
"hash": "
|
|
193
|
+
"hash": "a62f92eb",
|
|
183
194
|
"kind": "module",
|
|
184
195
|
"path": "lib/root-scripts.ts"
|
|
185
196
|
},
|
|
@@ -209,7 +220,7 @@
|
|
|
209
220
|
"path": "lib/workspace-build.ts"
|
|
210
221
|
},
|
|
211
222
|
{
|
|
212
|
-
"hash": "
|
|
223
|
+
"hash": "f22b8da5",
|
|
213
224
|
"kind": "inline",
|
|
214
225
|
"path": "../package.json",
|
|
215
226
|
"paths": [
|
|
@@ -217,22 +228,22 @@
|
|
|
217
228
|
]
|
|
218
229
|
},
|
|
219
230
|
{
|
|
220
|
-
"hash": "
|
|
231
|
+
"hash": "578af9fd",
|
|
221
232
|
"kind": "module",
|
|
222
233
|
"path": "../src/config-check-cache.ts"
|
|
223
234
|
},
|
|
224
235
|
{
|
|
225
|
-
"hash": "
|
|
236
|
+
"hash": "fa9330c5",
|
|
226
237
|
"kind": "module",
|
|
227
238
|
"path": "../src/config-validation.ts"
|
|
228
239
|
},
|
|
229
240
|
{
|
|
230
|
-
"hash": "
|
|
241
|
+
"hash": "4240e226",
|
|
231
242
|
"kind": "module",
|
|
232
243
|
"path": "../src/config.ts"
|
|
233
244
|
},
|
|
234
245
|
{
|
|
235
|
-
"hash": "
|
|
246
|
+
"hash": "463c7bbd",
|
|
236
247
|
"kind": "module",
|
|
237
248
|
"path": "../src/default-scripts.ts"
|
|
238
249
|
},
|
|
@@ -262,7 +273,7 @@
|
|
|
262
273
|
"path": "../src/helpers/hook-name.ts"
|
|
263
274
|
},
|
|
264
275
|
{
|
|
265
|
-
"hash": "
|
|
276
|
+
"hash": "7fb6c09d",
|
|
266
277
|
"kind": "module",
|
|
267
278
|
"path": "../src/helpers/package-json.ts"
|
|
268
279
|
},
|
|
@@ -301,11 +312,6 @@
|
|
|
301
312
|
"kind": "module",
|
|
302
313
|
"path": "../src/tiers.ts"
|
|
303
314
|
},
|
|
304
|
-
{
|
|
305
|
-
"hash": "faad986a",
|
|
306
|
-
"kind": "module",
|
|
307
|
-
"path": "../src/UserError.ts"
|
|
308
|
-
},
|
|
309
315
|
{
|
|
310
316
|
"hash": "ecf8a873",
|
|
311
317
|
"kind": "module",
|
|
@@ -317,17 +323,17 @@
|
|
|
317
323
|
"path": "../src/workspace-globs.ts"
|
|
318
324
|
},
|
|
319
325
|
{
|
|
320
|
-
"hash": "
|
|
326
|
+
"hash": "770e4f3a",
|
|
321
327
|
"kind": "module",
|
|
322
328
|
"path": "../src/workspace.ts"
|
|
323
329
|
}
|
|
324
330
|
],
|
|
325
331
|
"name": "default",
|
|
326
332
|
"path": "kits/default.js",
|
|
327
|
-
"readyupVersion": "0.
|
|
333
|
+
"readyupVersion": "0.45.0",
|
|
328
334
|
"source": "kits/default.ts",
|
|
329
335
|
"sourceHash": "9fd61bf4",
|
|
330
|
-
"targetHash": "
|
|
336
|
+
"targetHash": "6eb9c2b5"
|
|
331
337
|
}
|
|
332
338
|
]
|
|
333
339
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.55.0 — 2026-11-06
|
|
6
|
+
|
|
7
|
+
### 🎉 Features
|
|
8
|
+
|
|
9
|
+
- Adds the built-in root command `lint:shell`, which runs the new `nmr-shellcheck` bin to lint every tracked `*.sh` file with nmr's pinned shellcheck and passes without downloading shellcheck when the repo does not track any. (#1161)
|
|
10
|
+
- Adds a warning to nmr's readyup kit that reports a `lint:shell` entry in `.config/nmr.config.ts`, which overrides the built-in command, and directs the repo to delete the entry. (#1161)
|
|
11
|
+
|
|
12
|
+
### 🐛 Bug fixes
|
|
13
|
+
|
|
14
|
+
- Adopt the crash convention in release-kit (#1158)
|
|
15
|
+
|
|
16
|
+
Makes `release-kit` report a bug in its own code as `release-kit: internal error: <message>` followed by the stack, rather than as the `Error: <message>` line that it keeps for a failure in the user's input, config, or environment. The same change makes `nmr` and `v11y-check` print a Node system error, such as `EACCES` or `ENOENT`, as `Error: <message>` rather than as an internal error.
|
|
17
|
+
|
|
18
|
+
## 0.54.1 — 2026-11-05
|
|
19
|
+
|
|
20
|
+
### 🐛 Bug fixes
|
|
21
|
+
|
|
22
|
+
- Fixes the issue that `pnpm add` failed when an install hook such as `postinstall` ran an nmr command delegated by `NMR_DELEGATE` or the user config, because the host's frozen install rejected a manifest that was ahead of its lockfile, by making nmr run such a command on this machine unless `--delegate` or `--delegate-to` is passed. (#1151)
|
|
23
|
+
- Fixes the issue that `nmr` printed an unexpected crash as its raw stack, whose first line, `Error: <message>`, read the same as a handled error; it now prints `nmr: internal error: <message>` followed by the stack frames, and still prints an error caused by the user's own config as `Error: <message>`. (#1153)
|
|
24
|
+
- Fixes the issue that the `nmr` sub-bins, such as `nmr-compile` and `nmr-fmt`, and the `v11y` subcommands reported an unexpected crash as a handled `Error: <message>` line, rather than as `<bin>: internal error: <message>` with its stack frames. (#1157)
|
|
25
|
+
- Fixes the issue that the bin scripts of `nmr`, `release-kit`, and `v11y-check` reported every error other than missing build output as `<bin>: failed to load: <message>` without a stack, which hid where the fault occurred. (#1157)
|
|
26
|
+
|
|
5
27
|
## 0.54.0 — 2026-10-31
|
|
6
28
|
|
|
7
29
|
### 🎉 Features
|
package/README.md
CHANGED
|
@@ -5,11 +5,18 @@
|
|
|
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
7
|
<!-- section:release-notes -->
|
|
8
|
-
## Release notes — v0.
|
|
8
|
+
## Release notes — v0.55.0 (2026-11-06)
|
|
9
9
|
|
|
10
10
|
### 🎉 Features
|
|
11
11
|
|
|
12
|
-
- Adds
|
|
12
|
+
- Adds the built-in root command `lint:shell`, which runs the new `nmr-shellcheck` bin to lint every tracked `*.sh` file with nmr's pinned shellcheck and passes without downloading shellcheck when the repo does not track any. (#1161)
|
|
13
|
+
- Adds a warning to nmr's readyup kit that reports a `lint:shell` entry in `.config/nmr.config.ts`, which overrides the built-in command, and directs the repo to delete the entry. (#1161)
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Adopt the crash convention in release-kit (#1158)
|
|
18
|
+
|
|
19
|
+
Makes `release-kit` report a bug in its own code as `release-kit: internal error: <message>` followed by the stack, rather than as the `Error: <message>` line that it keeps for a failure in the user's input, config, or environment. The same change makes `nmr` and `v11y-check` print a Node system error, such as `EACCES` or `ENOENT`, as `Error: <message>` rather than as an internal error.
|
|
13
20
|
<!-- /section:release-notes -->
|
|
14
21
|
|
|
15
22
|
## Installation
|
|
@@ -316,7 +323,7 @@ rdy list --from npm:@williamthorsen/nmr # what nmr publishes
|
|
|
316
323
|
- [Machine lock](docs/machine-lock.md): Which commands wait for one another, where the lock lives, and bypassing it
|
|
317
324
|
- [Delegating to another machine](docs/delegate.md): The user config, `--delegate`, `--delegate-to`, `NMR_DELEGATE`, where a command runs, choosing among several hosts, what the host runs, and setting it up
|
|
318
325
|
- [Dependency upgrades](docs/upgrades.md): `nmr upgrade`, the upgrade policy, the Node version pin, `report-catalog`, `report-overrides`, and `nmr-taze`
|
|
319
|
-
- [Standalone utilities](docs/utilities.md): `nmr-actionlint`, `nmr-clean`, `nmr-compile`, `nmr-fmt`, `nmr-vitest`, and `ensure-prepublish-hooks`
|
|
326
|
+
- [Standalone utilities](docs/utilities.md): `nmr-actionlint`, `nmr-clean`, `nmr-compile`, `nmr-fmt`, `nmr-shellcheck`, `nmr-vitest`, and `ensure-prepublish-hooks`
|
|
320
327
|
- [Shared Vitest config](docs/vitest.md): Test tiers, test selections, the conventions check, and customization
|
|
321
328
|
- [Shared Prettier config](docs/prettier.md): What it formats and how to customize it
|
|
322
329
|
- [Workspace introspection](docs/workspace.md): The two workspace lookups
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-ensure-prepublish-hooks.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('ensure-prepublish-hooks: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`ensure-prepublish-hooks: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/bin/nmr-actionlint.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-actionlint.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-actionlint: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-actionlint: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/bin/nmr-clean.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-clean.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-clean: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-clean: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/bin/nmr-compile.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-build.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-compile: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-compile: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/bin/nmr-fmt.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-fmt.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-fmt: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-fmt: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-report-catalog.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-report-catalog: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-report-catalog: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-report-overrides.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-report-overrides: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-report-overrides: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
try {
|
|
3
|
+
await import('../dist/esm/cli-shellcheck.js');
|
|
4
|
+
} catch (error) {
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
|
+
process.stderr.write('nmr-shellcheck: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
|
+
} else {
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-shellcheck: internal error: ${message}\n${frames}`);
|
|
13
|
+
}
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
package/bin/nmr-taze.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-taze.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-taze: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-taze: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/bin/nmr-vitest.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli-vitest.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr-vitest: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr-vitest: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/bin/nmr.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
try {
|
|
3
3
|
await import('../dist/esm/cli.js');
|
|
4
4
|
} catch (error) {
|
|
5
|
-
if (error
|
|
5
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
6
6
|
process.stderr.write('nmr: build output not found; run `pnpm run bootstrap` first\n');
|
|
7
7
|
} else {
|
|
8
|
-
|
|
8
|
+
const message = typeof error?.message === 'string' && error.message !== '' ? error.message : String(error);
|
|
9
|
+
const lines = typeof error?.stack === 'string' ? error.stack.split('\n') : [];
|
|
10
|
+
const firstFrame = lines.findIndex((line) => /^\s+at /.test(line));
|
|
11
|
+
const frames = firstFrame === -1 ? '' : `${lines.slice(firstFrame).join('\n')}\n`;
|
|
12
|
+
process.stderr.write(`nmr: internal error: ${message}\n${frames}`);
|
|
9
13
|
}
|
|
10
14
|
process.exit(1);
|
|
11
15
|
}
|
package/dist/esm/check-cache.js
CHANGED
|
@@ -4,7 +4,7 @@ import process from 'node:process';
|
|
|
4
4
|
import { reportError } from '@williamthorsen/nmr-core';
|
|
5
5
|
import { createBoundedBuffer } from "./helpers/createBoundedBuffer.js";
|
|
6
6
|
const SIGNAL_EXIT_BASE = 128;
|
|
7
|
-
const PIPE_DRAIN_GRACE_MS =
|
|
7
|
+
const PIPE_DRAIN_GRACE_MS = 2000;
|
|
8
8
|
export function describeSignalExitCode(signal) {
|
|
9
9
|
return SIGNAL_EXIT_BASE + os.constants.signals[signal];
|
|
10
10
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
|
-
import {
|
|
3
|
-
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
2
|
+
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
4
3
|
import { runActionlint } from "./commands/actionlint.js";
|
|
5
4
|
import { findMonorepoRoot } from "./workspace.js";
|
|
6
5
|
try {
|
|
7
6
|
process.exitCode = await runActionlint(findMonorepoRoot(), process.argv.slice(2));
|
|
8
7
|
}
|
|
9
8
|
catch (error) {
|
|
10
|
-
|
|
9
|
+
reportFailure('nmr-actionlint', error);
|
|
11
10
|
process.exitCode = 1;
|
|
12
11
|
}
|
package/dist/esm/cli-build.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
1
|
+
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
3
2
|
import { buildPackage } from "./commands/build.js";
|
|
4
3
|
import { loadWorkspaceConfig } from "./config.js";
|
|
5
4
|
import { resolveBinStyles } from "./resolveBinStyles.js";
|
|
@@ -13,6 +12,6 @@ try {
|
|
|
13
12
|
});
|
|
14
13
|
}
|
|
15
14
|
catch (error) {
|
|
16
|
-
|
|
15
|
+
reportFailure('nmr-compile', error);
|
|
17
16
|
process.exitCode = 1;
|
|
18
17
|
}
|
package/dist/esm/cli-clean.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
|
-
import {
|
|
3
|
-
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
2
|
+
import { reportFailure } from '@williamthorsen/nmr-core';
|
|
4
3
|
import { runClean } from "./commands/clean.js";
|
|
5
4
|
import { resolveBinStyles } from "./resolveBinStyles.js";
|
|
6
5
|
try {
|
|
7
6
|
await runClean(process.cwd(), resolveBinStyles().stdout);
|
|
8
7
|
}
|
|
9
8
|
catch (error) {
|
|
10
|
-
|
|
9
|
+
reportFailure('nmr-clean', error);
|
|
11
10
|
process.exitCode = 1;
|
|
12
11
|
}
|