@williamthorsen/nmr 0.35.0 → 0.36.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 +1416 -0
- package/.readyup/kits/default.js +86 -4
- package/.readyup/manifest.json +5 -5
- package/CHANGELOG.md +894 -0
- package/README.md +22 -15
- package/dist/esm/commands/build.js +1 -1
- package/dist/esm/config.d.ts +0 -8
- package/dist/esm/config.js +66 -9
- package/dist/esm/helpers/config-path.d.ts +8 -0
- package/dist/esm/helpers/config-path.js +7 -0
- package/dist/esm/helpers/findClosestName.d.ts +7 -0
- package/dist/esm/helpers/findClosestName.js +38 -0
- package/dist/esm/helpers/package-json.js +1 -1
- package/dist/esm/runCli.js +1 -1
- package/dist/esm/types.d.ts +3 -2
- package/dist/esm/vitest-git-isolation.js +6 -0
- package/package.json +8 -6
package/.readyup/kits/default.js
CHANGED
|
@@ -5,14 +5,14 @@ export const __readyupVersion = "0.35.0";
|
|
|
5
5
|
|
|
6
6
|
// .readyup/kits/default.ts
|
|
7
7
|
import { existsSync, globSync, readdirSync as readdirSync2 } from "node:fs";
|
|
8
|
-
import { basename, dirname, join, sep } from "node:path";
|
|
8
|
+
import { basename, dirname, join, posix, sep } from "node:path";
|
|
9
9
|
|
|
10
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.
|
|
10
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.7.0/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/isError.js
|
|
11
11
|
function isError(error) {
|
|
12
12
|
return error instanceof Error || Object.prototype.toString.call(error) === "[object Error]";
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.
|
|
15
|
+
// ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.7.0/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/describeError.js
|
|
16
16
|
function describeError(error) {
|
|
17
17
|
try {
|
|
18
18
|
if (isError(error) && typeof error.message === "string" && error.message !== "") {
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
hasMinDevDependencyVersion,
|
|
35
35
|
hasPackageJsonField,
|
|
36
36
|
isRecord,
|
|
37
|
+
listTrackedFiles,
|
|
37
38
|
readFile,
|
|
38
39
|
readPackageJson
|
|
39
40
|
} from "readyup/check-utils";
|
|
@@ -258,6 +259,19 @@ var default_default = defineRdyKit({
|
|
|
258
259
|
check: allWorkspacePackagesCanBuild,
|
|
259
260
|
fix: `Add "build": ":" to packages that don't need a build, or ensure packages that use the default nmr build have a tsconfig.json and a src/ directory`
|
|
260
261
|
},
|
|
262
|
+
// -- Bin targets ---------------------------------------------------------
|
|
263
|
+
{
|
|
264
|
+
name: "every bin target is a committed wrapper",
|
|
265
|
+
severity: "error",
|
|
266
|
+
check: () => everyBinTargetIsACommittedWrapper(),
|
|
267
|
+
fix: `Point each listed entry at a committed wrapper under bin/ that loads the build output at runtime. pnpm links a workspace package's bins during the install's link phase, which runs before anything is built, so a target that is not committed does not exist when pnpm reaches for it \u2014 and pnpm never retries, leaving the link missing for the life of the node_modules tree`
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: "every bin wrapper's build-output target is covered by files",
|
|
271
|
+
severity: "warn",
|
|
272
|
+
check: () => everyBinWrapperTargetIsCoveredByFiles(),
|
|
273
|
+
fix: "Add the build output directory to `files` in each listed package. npm and pnpm publish the bin target itself whatever `files` says, so the wrapper ships pointing at build output missing from the tarball"
|
|
274
|
+
},
|
|
261
275
|
// -- Vitest projects -----------------------------------------------------
|
|
262
276
|
{
|
|
263
277
|
name: "no retired Vitest config variants",
|
|
@@ -345,6 +359,8 @@ var default_default = defineRdyKit({
|
|
|
345
359
|
]
|
|
346
360
|
});
|
|
347
361
|
var SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([".git", "coverage", "dist", "node_modules"]);
|
|
362
|
+
var BUILD_OUTPUT_DIR = "dist";
|
|
363
|
+
var WRAPPER_TARGET_PATTERN = /['"](\.\.?\/[^'"]+)['"]/;
|
|
348
364
|
var CONFIG_EXTENSIONS = "{ts,mts,cts,js,mjs,cjs}";
|
|
349
365
|
var VITE_CONFIG_PATTERN = `vite.config.${CONFIG_EXTENSIONS}`;
|
|
350
366
|
var VITEST_CONFIG_PATTERN = `vitest.config.${CONFIG_EXTENSIONS}`;
|
|
@@ -445,6 +461,70 @@ function discoverMemberWorkspaces() {
|
|
|
445
461
|
return { ok: false, detail: `cannot enumerate workspaces: ${describeError(error)}` };
|
|
446
462
|
}
|
|
447
463
|
}
|
|
464
|
+
async function everyBinTargetIsACommittedWrapper() {
|
|
465
|
+
const discovery = discoverMemberWorkspaces();
|
|
466
|
+
if (!discovery.ok) return discovery;
|
|
467
|
+
const tracked = await listTrackedFiles();
|
|
468
|
+
const trackedPaths = tracked === void 0 ? void 0 : new Set(tracked);
|
|
469
|
+
const offenders = discovery.workspaces.flatMap(
|
|
470
|
+
(workspace) => readBinEntries(workspace).flatMap((entry) => {
|
|
471
|
+
const defect = describeBinTargetDefect(workspace, entry, trackedPaths);
|
|
472
|
+
return defect === void 0 ? [] : [`${describeBinEntry(workspace, entry)} (${defect})`];
|
|
473
|
+
})
|
|
474
|
+
);
|
|
475
|
+
if (offenders.length === 0) return true;
|
|
476
|
+
return { ok: false, detail: formatPaths(offenders) };
|
|
477
|
+
}
|
|
478
|
+
function everyBinWrapperTargetIsCoveredByFiles() {
|
|
479
|
+
const discovery = discoverMemberWorkspaces();
|
|
480
|
+
if (!discovery.ok) return discovery;
|
|
481
|
+
const cwd = process.cwd();
|
|
482
|
+
const offenders = discovery.workspaces.flatMap((workspace) => {
|
|
483
|
+
const files = workspace.packageJson["files"];
|
|
484
|
+
if (!Array.isArray(files)) return [];
|
|
485
|
+
const published = new Set(files.flatMap((entry) => typeof entry === "string" ? [readFirstSegment(entry)] : []));
|
|
486
|
+
return readBinEntries(workspace).flatMap((entry) => {
|
|
487
|
+
const target = readWrapperTarget(cwd, workspace, entry);
|
|
488
|
+
if (target === void 0 || published.has(readFirstSegment(target))) return [];
|
|
489
|
+
return [`${describeBinEntry(workspace, entry)} -> ${target}`];
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
if (offenders.length === 0) return true;
|
|
493
|
+
return { ok: false, detail: formatPaths(offenders) };
|
|
494
|
+
}
|
|
495
|
+
function describeBinEntry(workspace, entry) {
|
|
496
|
+
return `${workspace.name ?? workspace.dir}:${entry.command} -> ${entry.target}`;
|
|
497
|
+
}
|
|
498
|
+
function describeBinTargetDefect(workspace, entry, trackedPaths) {
|
|
499
|
+
if (readFirstSegment(entry.target) === BUILD_OUTPUT_DIR) return `names a path under ${BUILD_OUTPUT_DIR}/`;
|
|
500
|
+
if (trackedPaths === void 0) return void 0;
|
|
501
|
+
return trackedPaths.has(`${workspace.dir}/${entry.target}`) ? void 0 : "untracked";
|
|
502
|
+
}
|
|
503
|
+
function normalizeBinTarget(target) {
|
|
504
|
+
return target.replace(/^\.\//, "");
|
|
505
|
+
}
|
|
506
|
+
function readBinEntries(workspace) {
|
|
507
|
+
const bin = workspace.packageJson["bin"];
|
|
508
|
+
if (typeof bin === "string") {
|
|
509
|
+
const command = workspace.name?.split("/").at(-1) ?? basename(workspace.dir);
|
|
510
|
+
return [{ command, target: normalizeBinTarget(bin) }];
|
|
511
|
+
}
|
|
512
|
+
if (!isRecord(bin)) return [];
|
|
513
|
+
return Object.entries(bin).flatMap(
|
|
514
|
+
([command, target]) => typeof target === "string" ? [{ command, target: normalizeBinTarget(target) }] : []
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
function readFirstSegment(entry) {
|
|
518
|
+
return normalizeBinTarget(entry).split("/", 1).at(0) ?? "";
|
|
519
|
+
}
|
|
520
|
+
function readWrapperTarget(cwd, workspace, entry) {
|
|
521
|
+
if (readFirstSegment(entry.target) === BUILD_OUTPUT_DIR) return void 0;
|
|
522
|
+
const content = readFileIn(cwd, `${workspace.dir}/${entry.target}`);
|
|
523
|
+
if (content === void 0) return void 0;
|
|
524
|
+
const specifier = WRAPPER_TARGET_PATTERN.exec(content)?.[1];
|
|
525
|
+
if (specifier === void 0) return void 0;
|
|
526
|
+
return posix.normalize(posix.join(posix.dirname(entry.target), specifier));
|
|
527
|
+
}
|
|
448
528
|
function everyTestFileNamesItsTier(cwd = process.cwd()) {
|
|
449
529
|
const untiered = findTestFiles(cwd).filter((path2) => !hasTierInfix(path2));
|
|
450
530
|
if (untiered.length === 0) return true;
|
|
@@ -472,7 +552,7 @@ function formatPaths(paths) {
|
|
|
472
552
|
${paths.map((path2) => ` ${path2}`).join("\n")}`;
|
|
473
553
|
}
|
|
474
554
|
function getMinVersion() {
|
|
475
|
-
const picked = { "version": "0.
|
|
555
|
+
const picked = { "version": "0.36.0" };
|
|
476
556
|
if (typeof picked["version"] !== "string") {
|
|
477
557
|
throw new TypeError("nmr/package.json: 'version' must be a string");
|
|
478
558
|
}
|
|
@@ -626,6 +706,8 @@ function vitestRootConfigBuildsOnSharedConfig(cwd = process.cwd()) {
|
|
|
626
706
|
}
|
|
627
707
|
export {
|
|
628
708
|
default_default as default,
|
|
709
|
+
everyBinTargetIsACommittedWrapper,
|
|
710
|
+
everyBinWrapperTargetIsCoveredByFiles,
|
|
629
711
|
everyTestFileNamesItsTier,
|
|
630
712
|
everyViteConfigHasVitestConfig,
|
|
631
713
|
hasSupportedEslintVersion,
|
package/.readyup/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"kits": [
|
|
4
4
|
{
|
|
5
5
|
"bundledDependencies": {
|
|
6
|
-
"@williamthorsen/toolbelt.errors": "0.
|
|
6
|
+
"@williamthorsen/toolbelt.errors": "0.7.0"
|
|
7
7
|
},
|
|
8
8
|
"checklists": [
|
|
9
9
|
"nmr"
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"esbuildVersion": "0.28.2",
|
|
12
12
|
"inputs": [
|
|
13
13
|
{
|
|
14
|
-
"hash": "
|
|
14
|
+
"hash": "5c3cbdb9",
|
|
15
15
|
"kind": "module",
|
|
16
16
|
"path": "kits/default.ts"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"hash": "
|
|
19
|
+
"hash": "6f709fcd",
|
|
20
20
|
"kind": "inline",
|
|
21
21
|
"path": "../package.json",
|
|
22
22
|
"paths": [
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"path": "kits/default.js",
|
|
44
44
|
"readyupVersion": "0.35.0",
|
|
45
45
|
"source": "kits/default.ts",
|
|
46
|
-
"sourceHash": "
|
|
47
|
-
"targetHash": "
|
|
46
|
+
"sourceHash": "5c3cbdb9",
|
|
47
|
+
"targetHash": "c24a46ec"
|
|
48
48
|
}
|
|
49
49
|
]
|
|
50
50
|
}
|