From eb2163a4e1bde824d6354d9e10d48242de8c39f8 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Thu, 5 Mar 2026 22:14:37 +0530 Subject: [PATCH] fix(arborist): respect --omit flag in linked install strategy --- .../arborist/lib/arborist/isolated-reifier.js | 5 ++- workspaces/arborist/test/isolated-mode.js | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/workspaces/arborist/lib/arborist/isolated-reifier.js b/workspaces/arborist/lib/arborist/isolated-reifier.js index 4916610245907..2b70a831f0205 100644 --- a/workspaces/arborist/lib/arborist/isolated-reifier.js +++ b/workspaces/arborist/lib/arborist/isolated-reifier.js @@ -90,6 +90,7 @@ module.exports = cls => class IsolatedReifier extends cls { **/ async makeIdealGraph () { const idealTree = this.idealTree + const omit = new Set(this.options.omit) this.idealGraph = { external: [], @@ -110,7 +111,9 @@ module.exports = cls => class IsolatedReifier extends cls { processed.add(next.location) next.edgesOut.forEach(edge => { if (edge.to && !(next.package.bundleDependencies || next.package.bundledDependencies || []).includes(edge.to.name)) { - queue.push(edge.to) + if (!edge.to.shouldOmit?.(omit)) { + queue.push(edge.to) + } } }) // local `file:` deps are in fsChildren but are not workspaces. diff --git a/workspaces/arborist/test/isolated-mode.js b/workspaces/arborist/test/isolated-mode.js index 492d467a9dd17..b1b0cc7c203c4 100644 --- a/workspaces/arborist/test/isolated-mode.js +++ b/workspaces/arborist/test/isolated-mode.js @@ -2055,6 +2055,48 @@ function parseGraphRecursive (key, deps) { return { name, version, workspace, peer, dependencies } } +tap.test('omit dev dependencies with linked strategy', async t => { + const graph = { + registry: [ + { name: 'which', version: '1.0.0', dependencies: { isexe: '^1.0.0' } }, + { name: 'isexe', version: '1.0.0' }, + { name: 'eslint', version: '1.0.0' }, + ], + root: { + name: 'myapp', + version: '1.0.0', + dependencies: { which: '1.0.0' }, + devDependencies: { eslint: '1.0.0' }, + }, + workspaces: [ + { + name: 'mylib', + version: '1.0.0', + dependencies: { isexe: '1.0.0' }, + devDependencies: { eslint: '1.0.0' }, + }, + ], + } + + const { dir, registry } = await getRepo(graph) + const cache = fs.mkdtempSync(`${getTempDir()}/test-`) + const arborist = new Arborist({ + path: dir, + registry, + packumentCache: new Map(), + cache, + omit: ['dev'], + }) + await arborist.reify({ installStrategy: 'linked' }) + + const storeDir = path.join(dir, 'node_modules', '.store') + const storeEntries = fs.readdirSync(storeDir) + + t.ok(storeEntries.some(e => e.startsWith('which@')), 'prod dep which is in store') + t.ok(storeEntries.some(e => e.startsWith('isexe@')), 'prod dep isexe is in store') + t.notOk(storeEntries.some(e => e.startsWith('eslint@')), 'dev dep eslint is not in store') +}) + /* * TO TEST: * --------------------------------------