From 42e5a6f8b270dd6ad90774282a47db02a76fe44e Mon Sep 17 00:00:00 2001 From: Shinrai Date: Sat, 8 Aug 2026 20:48:51 -0700 Subject: [PATCH 1/3] fix(devcheck): advance scanner past consumed --conditions value; drop invalid -C= form The devcheck scanner (merged via #10) had two nits: the space-form branch (`--conditions x` / `-C x`) consumed tokens[i+1] as the value but did not advance the loop index, so a value that itself looks like a flag could be double-processed; and it handled `-C=value`, which Node rejects outright ("bad option") so it can never appear. Advance i past the consumed value token, drop the dead `-C=` branch (valid forms: `--conditions=x`, `--conditions x`, `-C x`), and add -C short-flag test coverage. Redo of the change that was mistakenly pushed onto the already-merged fix/devcheck-condition-detection branch (which opened a diverged PR #12); this branch is cut fresh from next so the diff is only the scanner delta. --- devcheck.mjs | 13 ++++++++++--- tests/DevCheck.test.vitest.mjs | 8 ++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/devcheck.mjs b/devcheck.mjs index 9dd35cf..7f79d1c 100644 --- a/devcheck.mjs +++ b/devcheck.mjs @@ -61,12 +61,19 @@ if (existsSync(srcPath) && !isCI && !isInstalledPackage) { const scan = (tokens) => { for (let i = 0; i < tokens.length; i++) { if (tokens[i] === "--conditions" || tokens[i] === "-C") { - if (tokens[i + 1] !== undefined) conditions.push(tokens[i + 1]); + // Space form (`--conditions x` / `-C x`): consume the following token as this + // flag's value and SKIP it, so a value that itself looks like a flag (e.g. the + // literal `--conditions=x`) isn't re-interpreted on the next iteration. + if (tokens[i + 1] !== undefined) { + conditions.push(tokens[i + 1]); + i++; + } } else if (tokens[i].startsWith("--conditions=")) { conditions.push(tokens[i].slice("--conditions=".length)); - } else if (tokens[i].startsWith("-C=")) { - conditions.push(tokens[i].slice("-C=".length)); } + // Note: `-C=x` is intentionally not handled - Node rejects it ("bad option"), + // so it can never appear in execArgv/NODE_OPTIONS. Valid forms are + // `--conditions=x`, `--conditions x`, and `-C x`. } }; scan(process.execArgv); diff --git a/tests/DevCheck.test.vitest.mjs b/tests/DevCheck.test.vitest.mjs index de4dfea..0164f31 100644 --- a/tests/DevCheck.test.vitest.mjs +++ b/tests/DevCheck.test.vitest.mjs @@ -92,6 +92,14 @@ describe("devcheck", () => { expect(status).toBe(0); }); + test("stays silent via the -C short flag (Node's alias for --conditions)", () => { + // Node accepts `-C ` (space form) but rejects `-C=`, so only the + // space form is a real input to detect. + const { status, stderr } = runDevcheck({ src: true }, { nodeArgs: ["-C", "uuid-dev"] }); + expect(status).toBe(0); + expect(stderr).toBe(""); + }); + test("NODE_ENV=development alone does NOT silence it (only the condition selects src/)", () => { // Keying off NODE_ENV would be a false negative: dev env set but no condition means // the package is still resolving to dist/, which is exactly what should be flagged. From b9e0f50137a62fb71f730ce9815ab6af6433a765 Mon Sep 17 00:00:00 2001 From: "cldmv-bot[bot]" <230771808+cldmv-bot[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2026 04:17:40 +0000 Subject: [PATCH 2/3] chore: bump version to 1.1.6 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e783720..b4766a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cldmv/uuid", - "version": "1.1.5", + "version": "1.1.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cldmv/uuid", - "version": "1.1.5", + "version": "1.1.6", "license": "Apache-2.0", "devDependencies": { "@cldmv/fix-headers": "^1.2.2", diff --git a/package.json b/package.json index fdaf5b7..1ac1c4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cldmv/uuid", - "version": "1.1.5", + "version": "1.1.6", "description": "Extended RFC 4122 and RFC 9562 UUID implementation with custom variant structures, issuer-based identification, and timestamp variants", "main": "./index.cjs", "module": "./index.mjs", From 257b31f82ff400b9404391cfb59676139e73f7fc Mon Sep 17 00:00:00 2001 From: Shinrai Date: Sat, 8 Aug 2026 21:41:43 -0700 Subject: [PATCH 3/3] fix(exports): expose ./package.json in the exports map Node's exports map is a strict allowlist: with only "." and "./main" declared, `require.resolve("@cldmv/uuid/package.json")` (and any tool that locates a package by resolving its package.json) throws ERR_PACKAGE_PATH_NOT_EXPORTED. This broke @cldmv/rummage's web build. Add the conventional `"./package.json": "./package.json"` entry so the manifest is resolvable by name, and a regression test that asserts both the exports entry and real Node self-resolution. Fixes #6 --- package.json | 3 +- tests/package-exports.test.vitest.mjs | 40 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/package-exports.test.vitest.mjs diff --git a/package.json b/package.json index 1ac1c4a..3d3afc6 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "import": "./src/uuid.mjs" }, "import": "./dist/uuid.mjs" - } + }, + "./package.json": "./package.json" }, "type": "module", "engines": { diff --git a/tests/package-exports.test.vitest.mjs b/tests/package-exports.test.vitest.mjs new file mode 100644 index 0000000..4a4a0f7 --- /dev/null +++ b/tests/package-exports.test.vitest.mjs @@ -0,0 +1,40 @@ +/** + * @Project: @cldmv/uuid + * @Filename: /tests/package-exports.test.vitest.mjs + * @Date: 2026-08-09T00:00:00-08:00 (1786233600) + * @Author: Nate Corcoran + * @Email: + * ----- + * @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) + * @Last modified time: 2026-08-09T00:00:00-08:00 (1786233600) + * ----- + * @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. + */ + +import { test, expect, describe } from "vitest"; +import { readFileSync } from "node:fs"; +import { spawnSync } from "node:child_process"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); + +describe("package exports", () => { + test("the exports map exposes ./package.json", () => { + // Tooling resolves `/package.json` to locate a package's directory on disk; + // omitting it from `exports` makes that throw ERR_PACKAGE_PATH_NOT_EXPORTED. (#6) + const pkg = JSON.parse(readFileSync(path.join(repoRoot, "package.json"), "utf8")); + expect(pkg.exports["./package.json"]).toBe("./package.json"); + }); + + test("Node can resolve @cldmv/uuid/package.json through the exports map", () => { + // Real Node resolution (self-referencing the package by name from the repo root), + // not Vitest's resolver — before the fix this exits non-zero with + // ERR_PACKAGE_PATH_NOT_EXPORTED. + const res = spawnSync(process.execPath, ["--input-type=module", "-e", "import.meta.resolve('@cldmv/uuid/package.json');"], { + cwd: repoRoot, + encoding: "utf8" + }); + expect(res.status).toBe(0); + }); +});