From ecb02a88a7ca0940d25957d941dc7c66736af4f7 Mon Sep 17 00:00:00 2001 From: Tea Reggi Date: Fri, 10 Jul 2026 11:44:15 -0400 Subject: [PATCH 1/4] fix(view): avoid wrapping array results (#9745) npm 12.0.0 breaks downstream updaters by returning nested arrays for `npm view versions --json`. ## The bug On npm 12.0.0, a single array-valued field is wrapped in the outer results array: ``` $ npm view abbrev versions --json [["1.0.3","1.0.4", ...]] # should be ["1.0.3","1.0.4", ...] ``` This happens in `lib/commands/view.js` `#packageOutput`: for a single-field query it maps to `res.map(m => m[first[0]])`, and when that field's value is itself an array (e.g. `versions`), it gets double-wrapped. ## The fix Return a sole array-valued JSON result directly instead of adding a second result wrapper. Existing output shapes are preserved: - scalar and object results still return in an array (`["1.0.0"]`, `[{...}]`) - multiple matching versions keep the result boundary (`[[...],[...]]`) - a single array-valued result is returned directly (`["1.0.0","1.0.1"]`) Docs and tests updated to cover flat array, nested array, object-wrapper, workspace, and multi-match cases. Co-authored-by: Martin Ruiz Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/lib/content/commands/npm-view.md | 4 +- lib/commands/view.js | 5 +- test/lib/commands/view.js | 151 +++++++++++++++++++++++++- 3 files changed, 156 insertions(+), 4 deletions(-) diff --git a/docs/lib/content/commands/npm-view.md b/docs/lib/content/commands/npm-view.md index 36b8b93c0ddc1..bba36b73e911a 100644 --- a/docs/lib/content/commands/npm-view.md +++ b/docs/lib/content/commands/npm-view.md @@ -174,7 +174,9 @@ If only a single string field for a single version is output, then it will not b If the field is an object, it will be output as a JavaScript object literal. If the `--json` flag is given, the outputted fields will be JSON. -The output is always an array, even if only a single version matches. +Scalar and object results are returned in an array, even if only a single version matches. +When the output contains one array-valued result, that array is returned directly without an additional result wrapper. +Multiple array-valued results remain separate items in the outer results array. If the version range matches multiple versions then each printed value will be prefixed with the version it applies to. diff --git a/lib/commands/view.js b/lib/commands/view.js index 9a3d8f29233c4..747f1d4ffafd8 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -240,12 +240,15 @@ class View extends BaseCommand { }) if (json) { - // Users can expect an array . const first = Object.keys(res[0] || {}) const jsonRes = first.length === 1 ? res.map(m => m[first[0]]) : res if (jsonRes.length === 0) { return } + // Avoid wrapping a single array-valued result in another array. + if (jsonRes.length === 1 && Array.isArray(jsonRes[0])) { + return jsonRes[0] + } return jsonRes } diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index dbf4560bf46ab..3b5a581f3a6b1 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -189,14 +189,37 @@ const packument = (nv, opts) => { }, purple: { name: 'purple', + 'dist-tags': { + latest: '1.0.0', + }, versions: { '1.0.0': { + version: '1.0.0', foo: 1, + metadata: { + channels: ['latest', 'next'], + empty: [], + release: { + stable: true, + }, + }, + items: [ + { tags: ['one', 'two'] }, + ], maintainers: [ { name: 'claudia' }, ], }, - '1.0.1': {}, + '1.0.1': { + version: '1.0.1', + metadata: { + channels: ['next'], + empty: [], + release: { + stable: false, + }, + }, + }, }, }, green: { @@ -508,6 +531,118 @@ t.test('package with --json and single string arg', async t => { t.strictSame(JSON.parse(joinedOutput()), ['1.0.0'], 'returns single string value as array') }) +t.test('package with --json and array-valued field', async t => { + const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) + await view.exec(['blue', 'versions']) + t.strictSame( + JSON.parse(joinedOutput()), + ['1.0.0', '1.0.1'], + 'returns the field value without an additional result wrapper' + ) +}) + +t.test('package with --json and array-valued field from multiple matches', async t => { + const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) + await view.exec(['blue@^1', 'versions']) + t.strictSame( + JSON.parse(joinedOutput()), + [ + ['1.0.0', '1.0.1'], + ['1.0.0', '1.0.1'], + ], + 'preserves the result boundary for each matching version' + ) +}) + +t.test('package field access with --json preserves value shapes', async t => { + const cases = [ + { + name: 'nested scalar field', + args: ['purple@1.0.0', 'metadata.release.stable'], + expected: [true], + }, + { + name: 'nested object field', + args: ['purple@1.0.0', 'metadata.release'], + expected: [{ stable: true }], + }, + { + name: 'nested empty array field', + args: ['purple@1.0.0', 'metadata.empty'], + expected: [], + }, + { + name: 'nested single-item array field', + args: ['purple@1.0.1', 'metadata.channels'], + expected: ['next'], + }, + { + name: 'nested multi-item array field', + args: ['purple@1.0.0', 'metadata.channels'], + expected: ['latest', 'next'], + }, + { + name: 'array field with bracket notation', + args: ['purple@1.0.0', 'metadata[channels]'], + expected: ['latest', 'next'], + }, + { + name: 'indexed array element', + args: ['purple@1.0.0', 'metadata.channels[0]'], + expected: ['latest'], + }, + { + name: 'expanded array subfield', + args: ['pink@1.0.0', 'maintainers.url'], + expected: [{ + 'maintainers[0].url': 'http://c.pink.com', + 'maintainers[1].url': 'http://i.pink.com', + }], + }, + { + name: 'expanded array-valued subfield', + args: ['purple@1.0.0', 'items.tags'], + expected: ['one', 'two'], + }, + { + name: 'multiple requested fields', + args: ['purple@1.0.0', 'metadata.channels', 'metadata.release'], + expected: [{ + 'metadata.channels': ['latest', 'next'], + 'metadata.release': { stable: true }, + }], + }, + { + name: 'multiple requested fields with one missing', + args: ['purple@1.0.0', 'metadata.channels', 'missing'], + expected: ['latest', 'next'], + }, + { + name: 'array field from multiple matching versions', + args: ['purple@^1', 'metadata.channels'], + expected: [ + ['latest', 'next'], + ['next'], + ], + }, + { + name: 'array field present in one of multiple matching versions', + args: ['purple@^1', 'items'], + expected: [ + { tags: ['one', 'two'] }, + ], + }, + ] + + for (const { name, args, expected } of cases) { + await t.test(name, async t => { + const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) + await view.exec(args) + t.strictSame(JSON.parse(joinedOutput()), expected) + }) + } +}) + t.test('package with single version', async t => { t.test('full json', async t => { const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) @@ -519,7 +654,7 @@ t.test('package with single version', async t => { const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) await view.exec(['single-version', 'versions']) const parsed = JSON.parse(joinedOutput()) - t.strictSame(parsed, [['1.0.0']], 'does not unwrap single item arrays in json') + t.strictSame(parsed, ['1.0.0'], 'preserves the array-valued field') }) t.test('no json and versions arg', async t => { @@ -766,6 +901,18 @@ t.test('workspaces', async t => { t.matchSnapshot(joinedOutput()) }) + t.test('all workspaces array field --json', async t => { + const { view, joinedOutput } = await loadMockNpm(t, { + prefixDir, + config: { unicode: false, workspaces: true, json: true }, + }) + await view.exec(['.', 'versions']) + t.strictSame(JSON.parse(joinedOutput()), { + green: ['1.0.0', '1.0.1'], + orange: ['1.0.0', '1.0.1'], + }) + }) + t.test('single workspace --json', async t => { const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, From 72a6088fcdd8099d5f07bf7e06f54a24a835fc5f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:45:05 +0000 Subject: [PATCH 2/4] chore: release 12.0.1 --- .release-please-manifest.json | 12 +++++------ AUTHORS | 1 + CHANGELOG.md | 14 +++++++++++++ package-lock.json | 32 +++++++++++++++--------------- package.json | 12 +++++------ workspaces/arborist/CHANGELOG.md | 4 ++++ workspaces/arborist/package.json | 2 +- workspaces/libnpmdiff/CHANGELOG.md | 4 ++++ workspaces/libnpmdiff/package.json | 4 ++-- workspaces/libnpmexec/CHANGELOG.md | 4 ++++ workspaces/libnpmexec/package.json | 4 ++-- workspaces/libnpmfund/CHANGELOG.md | 4 ++++ workspaces/libnpmfund/package.json | 4 ++-- workspaces/libnpmpack/CHANGELOG.md | 4 ++++ workspaces/libnpmpack/package.json | 4 ++-- 15 files changed, 72 insertions(+), 37 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9a97beff03910..aa435ac5b59d5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,12 +1,12 @@ { - ".": "12.0.0", - "workspaces/arborist": "10.0.0", + ".": "12.0.1", + "workspaces/arborist": "10.0.1", "workspaces/libnpmaccess": "11.0.0", - "workspaces/libnpmdiff": "9.0.0", - "workspaces/libnpmexec": "11.0.0", - "workspaces/libnpmfund": "8.0.0", + "workspaces/libnpmdiff": "9.0.1", + "workspaces/libnpmexec": "11.0.1", + "workspaces/libnpmfund": "8.0.1", "workspaces/libnpmorg": "9.0.0", - "workspaces/libnpmpack": "10.0.0", + "workspaces/libnpmpack": "10.0.1", "workspaces/libnpmpublish": "12.0.0", "workspaces/libnpmsearch": "10.0.0", "workspaces/libnpmteam": "9.0.0", diff --git a/AUTHORS b/AUTHORS index 0c452f5a1a4e3..3c14bfd1bf19f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1035,3 +1035,4 @@ Dale Lakes <6843636+dale-lakes@users.noreply.github.com> rijildaniel <40638987+rijildaniel@users.noreply.github.com> UB Justin Clark +James Prevett diff --git a/CHANGELOG.md b/CHANGELOG.md index ac09f9903c845..da431409546d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [12.0.1](https://github.com/npm/cli/compare/v12.0.0...v12.0.1) (2026-07-10) +### Bug Fixes +* [`ecb02a8`](https://github.com/npm/cli/commit/ecb02a88a7ca0940d25957d941dc7c66736af4f7) [#9745](https://github.com/npm/cli/pull/9745) view: avoid wrapping array results (#9745) (@reggi, @martinrrm, @Copilot) +* [`47fc8b1`](https://github.com/npm/cli/commit/47fc8b191a841ec177f2d7d486dde1b66dc0045c) [#9740](https://github.com/npm/cli/pull/9740) correct bundled sigstore from dev dependency conflict (#9740) (@james-pre) + + +### Dependencies + +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.1): `@npmcli/arborist@10.0.1` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmdiff-v9.0.1): `libnpmdiff@9.0.1` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmexec-v11.0.1): `libnpmexec@11.0.1` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmfund-v8.0.1): `libnpmfund@8.0.1` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmpack-v10.0.1): `libnpmpack@10.0.1` + ## [12.0.0](https://github.com/npm/cli/compare/v12.0.0-pre.3...v12.0.0) (2026-07-08) ### ⚠️ BREAKING CHANGES * npm view --json now always returns an array. diff --git a/package-lock.json b/package-lock.json index 0c1d90c11fb54..0bcc1c791d892 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm", - "version": "12.0.0", + "version": "12.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm", - "version": "12.0.0", + "version": "12.0.1", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -87,7 +87,7 @@ ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/config": "^11.0.0", "@npmcli/fs": "^6.0.0", "@npmcli/git": "^8.0.0", @@ -115,11 +115,11 @@ "is-cidr": "^7.0.0", "json-parse-even-better-errors": "^6.0.0", "libnpmaccess": "^11.0.0", - "libnpmdiff": "^9.0.0", - "libnpmexec": "^11.0.0", - "libnpmfund": "^8.0.0", + "libnpmdiff": "^9.0.1", + "libnpmexec": "^11.0.1", + "libnpmfund": "^8.0.1", "libnpmorg": "^9.0.0", - "libnpmpack": "^10.0.0", + "libnpmpack": "^10.0.1", "libnpmpublish": "^12.0.0", "libnpmsearch": "^10.0.0", "libnpmteam": "^9.0.0", @@ -14947,7 +14947,7 @@ }, "workspaces/arborist": { "name": "@npmcli/arborist", - "version": "10.0.0", + "version": "10.0.1", "license": "ISC", "dependencies": { "@gar/promise-retry": "^1.0.0", @@ -15047,10 +15047,10 @@ } }, "workspaces/libnpmdiff": { - "version": "9.0.0", + "version": "9.0.1", "license": "ISC", "dependencies": { - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/installed-package-contents": "^5.0.0", "binary-extensions": "^3.0.0", "diff": "^8.0.2", @@ -15069,11 +15069,11 @@ } }, "workspaces/libnpmexec": { - "version": "11.0.0", + "version": "11.0.1", "license": "ISC", "dependencies": { "@gar/promise-retry": "^1.0.0", - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/package-json": "^8.0.0", "@npmcli/run-script": "^11.0.0", "ci-info": "^4.0.0", @@ -15100,10 +15100,10 @@ } }, "workspaces/libnpmfund": { - "version": "8.0.0", + "version": "8.0.1", "license": "ISC", "dependencies": { - "@npmcli/arborist": "^10.0.0" + "@npmcli/arborist": "^10.0.1" }, "devDependencies": { "@npmcli/eslint-config": "^5.0.1", @@ -15133,10 +15133,10 @@ } }, "workspaces/libnpmpack": { - "version": "10.0.0", + "version": "10.0.1", "license": "ISC", "dependencies": { - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/run-script": "^11.0.0", "npm-package-arg": "^14.0.0", "pacote": "^22.0.0" diff --git a/package.json b/package.json index 560655107ff4f..6779e6ca60a96 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "12.0.0", + "version": "12.0.1", "name": "npm", "description": "a package manager for JavaScript", "workspaces": [ @@ -48,7 +48,7 @@ }, "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/config": "^11.0.0", "@npmcli/fs": "^6.0.0", "@npmcli/git": "^8.0.0", @@ -76,11 +76,11 @@ "is-cidr": "^7.0.0", "json-parse-even-better-errors": "^6.0.0", "libnpmaccess": "^11.0.0", - "libnpmdiff": "^9.0.0", - "libnpmexec": "^11.0.0", - "libnpmfund": "^8.0.0", + "libnpmdiff": "^9.0.1", + "libnpmexec": "^11.0.1", + "libnpmfund": "^8.0.1", "libnpmorg": "^9.0.0", - "libnpmpack": "^10.0.0", + "libnpmpack": "^10.0.1", "libnpmpublish": "^12.0.0", "libnpmsearch": "^10.0.0", "libnpmteam": "^9.0.0", diff --git a/workspaces/arborist/CHANGELOG.md b/workspaces/arborist/CHANGELOG.md index 4b2af7e2aeae8..8c267ab1d4400 100644 --- a/workspaces/arborist/CHANGELOG.md +++ b/workspaces/arborist/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [10.0.1](https://github.com/npm/cli/compare/arborist-v10.0.0...arborist-v10.0.1) (2026-07-10) +### Bug Fixes +* [`47fc8b1`](https://github.com/npm/cli/commit/47fc8b191a841ec177f2d7d486dde1b66dc0045c) [#9740](https://github.com/npm/cli/pull/9740) correct bundled sigstore from dev dependency conflict (#9740) (@james-pre) + ## [10.0.0](https://github.com/npm/cli/compare/arborist-v10.0.0-pre.2...arborist-v10.0.0) (2026-07-08) ### ⚠️ BREAKING CHANGES * `npm shrinkwrap` is removed, the `shrinkwrap` config alias is removed, and `npm-shrinkwrap.json` is no longer loaded or honored at the project root or from inside dependency tarballs. Rename project-root `npm-shrinkwrap.json` to `package-lock.json`; use `bundleDependencies` if you need to ship a locked dependency tree. diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index f1416200bf3aa..ed472a2e3415c 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "10.0.0", + "version": "10.0.1", "description": "Manage node_modules trees", "dependencies": { "@gar/promise-retry": "^1.0.0", diff --git a/workspaces/libnpmdiff/CHANGELOG.md b/workspaces/libnpmdiff/CHANGELOG.md index 152235f243015..fdcffff706ba8 100644 --- a/workspaces/libnpmdiff/CHANGELOG.md +++ b/workspaces/libnpmdiff/CHANGELOG.md @@ -72,6 +72,10 @@ * [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.0-pre.2): `@npmcli/arborist@10.0.0-pre.2` +### Dependencies + +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.1): `@npmcli/arborist@10.0.1` + ## [9.0.0](https://github.com/npm/cli/compare/libnpmdiff-v9.0.0-pre.1...libnpmdiff-v9.0.0) (2026-07-08) ### ⚠️ BREAKING CHANGES * `npm` now supports node `^22.22.2 || ^24.15.0 || >=26.0.0` diff --git a/workspaces/libnpmdiff/package.json b/workspaces/libnpmdiff/package.json index d09922040693b..1d29743fd9c6c 100644 --- a/workspaces/libnpmdiff/package.json +++ b/workspaces/libnpmdiff/package.json @@ -1,6 +1,6 @@ { "name": "libnpmdiff", - "version": "9.0.0", + "version": "9.0.1", "description": "The registry diff", "repository": { "type": "git", @@ -47,7 +47,7 @@ "tap": "^16.3.8" }, "dependencies": { - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/installed-package-contents": "^5.0.0", "binary-extensions": "^3.0.0", "diff": "^8.0.2", diff --git a/workspaces/libnpmexec/CHANGELOG.md b/workspaces/libnpmexec/CHANGELOG.md index 4cf32af0baf61..a5117042a0591 100644 --- a/workspaces/libnpmexec/CHANGELOG.md +++ b/workspaces/libnpmexec/CHANGELOG.md @@ -40,6 +40,10 @@ * [workspace](https://github.com/npm/cli/releases/tag/arborist-v9.4.2): `@npmcli/arborist@9.4.2` +### Dependencies + +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.1): `@npmcli/arborist@10.0.1` + ## [11.0.0](https://github.com/npm/cli/compare/libnpmexec-v11.0.0-pre.1...libnpmexec-v11.0.0) (2026-07-08) ### ⚠️ BREAKING CHANGES * `npm` now supports node `^22.22.2 || ^24.15.0 || >=26.0.0` diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index 7bc164c813ebb..4ed8d6a04214b 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -1,6 +1,6 @@ { "name": "libnpmexec", - "version": "11.0.0", + "version": "11.0.1", "files": [ "bin/", "lib/" @@ -65,7 +65,7 @@ }, "dependencies": { "@gar/promise-retry": "^1.0.0", - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/package-json": "^8.0.0", "@npmcli/run-script": "^11.0.0", "ci-info": "^4.0.0", diff --git a/workspaces/libnpmfund/CHANGELOG.md b/workspaces/libnpmfund/CHANGELOG.md index fea2a1111d5e8..e47fd4d581d87 100644 --- a/workspaces/libnpmfund/CHANGELOG.md +++ b/workspaces/libnpmfund/CHANGELOG.md @@ -96,6 +96,10 @@ * [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.0-pre.2): `@npmcli/arborist@10.0.0-pre.2` +### Dependencies + +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.1): `@npmcli/arborist@10.0.1` + ## [8.0.0](https://github.com/npm/cli/compare/libnpmfund-v8.0.0-pre.1...libnpmfund-v8.0.0) (2026-07-08) ### ⚠️ BREAKING CHANGES * `npm` now supports node `^22.22.2 || ^24.15.0 || >=26.0.0` diff --git a/workspaces/libnpmfund/package.json b/workspaces/libnpmfund/package.json index 762562f53ba0d..3cc201c8a095e 100644 --- a/workspaces/libnpmfund/package.json +++ b/workspaces/libnpmfund/package.json @@ -1,6 +1,6 @@ { "name": "libnpmfund", - "version": "8.0.0", + "version": "8.0.1", "main": "lib/index.js", "files": [ "bin/", @@ -46,7 +46,7 @@ "tap": "^16.3.8" }, "dependencies": { - "@npmcli/arborist": "^10.0.0" + "@npmcli/arborist": "^10.0.1" }, "engines": { "node": "^22.22.2 || ^24.15.0 || >=26.0.0" diff --git a/workspaces/libnpmpack/CHANGELOG.md b/workspaces/libnpmpack/CHANGELOG.md index 1754984452e91..1d582c40dfc17 100644 --- a/workspaces/libnpmpack/CHANGELOG.md +++ b/workspaces/libnpmpack/CHANGELOG.md @@ -76,6 +76,10 @@ * [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.0-pre.2): `@npmcli/arborist@10.0.0-pre.2` +### Dependencies + +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v10.0.1): `@npmcli/arborist@10.0.1` + ## [10.0.0](https://github.com/npm/cli/compare/libnpmpack-v10.0.0-pre.2...libnpmpack-v10.0.0) (2026-07-08) ### ⚠️ BREAKING CHANGES * npm pack and npm publish now error when a package's overrides apply to one or more of its bundled packages (bundledDependencies / bundleDependencies). Defining both fields is still allowed as long as no override actually targets a bundled package. To resolve the error, remove the affected entries from either overrides or the bundle. diff --git a/workspaces/libnpmpack/package.json b/workspaces/libnpmpack/package.json index 458cc9a0a9440..16272086b441c 100644 --- a/workspaces/libnpmpack/package.json +++ b/workspaces/libnpmpack/package.json @@ -1,6 +1,6 @@ { "name": "libnpmpack", - "version": "10.0.0", + "version": "10.0.1", "description": "Programmatic API for the bits behind npm pack", "author": "GitHub Inc.", "main": "lib/index.js", @@ -37,7 +37,7 @@ "bugs": "https://github.com/npm/libnpmpack/issues", "homepage": "https://npmjs.com/package/libnpmpack", "dependencies": { - "@npmcli/arborist": "^10.0.0", + "@npmcli/arborist": "^10.0.1", "@npmcli/run-script": "^11.0.0", "npm-package-arg": "^14.0.0", "pacote": "^22.0.0" From ddd50e92370073a1ea0e0e4483de4088e8e34210 Mon Sep 17 00:00:00 2001 From: Tea Reggi Date: Fri, 10 Jul 2026 14:49:43 -0400 Subject: [PATCH 3/4] chore(arborist): add missing registry mock in bin links reify test (#9746) The `bin links adding and removing` test in `workspaces/arborist/test/arborist/reify.js` reifies `rimraf@2.7.1` without setting up a mock registry. This adds `createRegistry(t, true)` so the test uses the mock registry instead of depending on the real one. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- workspaces/arborist/test/arborist/reify.js | 1 + 1 file changed, 1 insertion(+) diff --git a/workspaces/arborist/test/arborist/reify.js b/workspaces/arborist/test/arborist/reify.js index d453c79baa325..943e340b22c1f 100644 --- a/workspaces/arborist/test/arborist/reify.js +++ b/workspaces/arborist/test/arborist/reify.js @@ -1255,6 +1255,7 @@ t.test('bin links adding and removing', t => { const path = t.testdir({ 'package.json': JSON.stringify({}), }) + createRegistry(t, true) const rbin = resolve(path, 'node_modules/.bin/rimraf') return reify(path, { add: ['rimraf@2.7.1'] }) .then(() => fs.statSync(rbin)) // should be there From 7b1f6c173d17b3bf30e45426f6df39473c6a1163 Mon Sep 17 00:00:00 2001 From: Tea Reggi Date: Fri, 10 Jul 2026 14:50:00 -0400 Subject: [PATCH 4/4] chore: parse pack --json object output in node integration (#9747) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The `build nodejs` jobs in `Release Integration / publish` fail at `.github/workflows/node-integration.yml`: ``` node . pack --loglevel=silent --json | jq -r .[0].filename → jq: error (at :9859): Cannot index object with number → Process completed with exit code 5 ``` As of #9247 (sync json output of pack and publish), `npm pack --json` no longer outputs an array. `logTar` now buffers `{ [tar.name]: tarball }`, so the output is an object keyed by package name: ```json { "npm": { "filename": "npm-12.0.1.tgz", ... } } ``` The workflow still parsed it with `.[0].filename`, which errors on an object. npm 12.0.x is the first release carrying this change, so the release integration only started breaking now. ## Fix Parse the filename from the object instead of an array index: ```diff -npmtarball="$(node . pack --loglevel=silent --json | jq -r .[0].filename)" +npmtarball="$(node . pack --loglevel=silent --json | jq -r 'to_entries[0].value.filename')" ``` Verified locally: returns `npm-12.0.1.tgz`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/node-integration.yml | 2 +- scripts/template-oss/node-integration-yml.hbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node-integration.yml b/.github/workflows/node-integration.yml index 054b7f1b657a7..929d73b513141 100644 --- a/.github/workflows/node-integration.yml +++ b/.github/workflows/node-integration.yml @@ -107,7 +107,7 @@ jobs: echo "::group::packing npm release $npmVersion" pushd "$npmDir" >/dev/null node scripts/resetdeps.js - npmtarball="$(node . pack --loglevel=silent --json | jq -r .[0].filename)" + npmtarball="$(node . pack --loglevel=silent --json | jq -r 'to_entries[0].value.filename')" tar czf "$npmFile" -C "$npmDir" . popd >/dev/null echo "npm=$npmFile" >> $GITHUB_OUTPUT diff --git a/scripts/template-oss/node-integration-yml.hbs b/scripts/template-oss/node-integration-yml.hbs index 9b4391d3991f2..5fef5f10c2b1f 100644 --- a/scripts/template-oss/node-integration-yml.hbs +++ b/scripts/template-oss/node-integration-yml.hbs @@ -105,7 +105,7 @@ jobs: echo "::group::packing npm release $npmVersion" pushd "$npmDir" >/dev/null node scripts/resetdeps.js - npmtarball="$(node . pack --loglevel=silent --json | jq -r .[0].filename)" + npmtarball="$(node . pack --loglevel=silent --json | jq -r 'to_entries[0].value.filename')" tar czf "$npmFile" -C "$npmDir" . popd >/dev/null echo "npm=$npmFile" >> $GITHUB_OUTPUT