Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ function collectDependencies(node, relevantPackageLocations) {
node = node.target;
}
for (const edge of node.edgesOut.values()) {
if (edge.dev) {
if (edge.dev || !edge.to) {
// Skip dev dependencies and optional peer dependencies that are not installed
continue;
}
collectDependencies(edge.to, relevantPackageLocations);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -19247,7 +19247,8 @@
"replacestream": "^4.0.3",
"router": "^2.2.0",
"spdy": "^4.0.2",
"yesno": "^0.4.0"
"yesno": "^0.4.0",
"ws": "^8.21.0"
},
"devDependencies": {
"@eslint/js": "^9.8.0",
Expand Down Expand Up @@ -19366,6 +19367,27 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ws": {
"version": "8.21.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
}
23 changes: 23 additions & 0 deletions internal/shrinkwrap-extractor/test/lib/convertToShrinkwrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,29 @@ test("Compare generated shrinkwrap with expected result", async (t) => {
"Generated shrinkwrap packages should match expected");
});

test("Optional peer dependencies with null edges should be excluded", async (t) => {
// Guards against: ws declares bufferutil and utf-8-validate as peerOptional, but they are not
// installed. Arborist represents these as edges with edge.to === null. The generator must skip
// them instead of throwing "Cannot read properties of null (reading 'location')".
const __dirname = import.meta.dirname;

const cwd = path.join(__dirname, "..", "fixture", "project.a");
const symlinkPath = await setupFixtureSymlink(cwd);
t.after(async () => await unlink(symlinkPath).catch(() => {}));

const shrinkwrapJson = await convertPackageLockToShrinkwrap(cwd, "@ui5/cli");

// ws itself must be present (it is a real production dep of @ui5/server)
assert.ok(shrinkwrapJson.packages["node_modules/ws"],
"ws should be included in the shrinkwrap");

// Its optional peer deps are not installed and must NOT appear
assert.equal(shrinkwrapJson.packages["node_modules/bufferutil"], undefined,
"bufferutil (optional peerDep of ws) must not be included");
assert.equal(shrinkwrapJson.packages["node_modules/utf-8-validate"], undefined,
"utf-8-validate (optional peerDep of ws) must not be included");
});

// Error handling tests
test("Error handling - invalid target package name", async (t) => {
const __dirname = import.meta.dirname;
Expand Down
Loading