From 5536f807d597349152764fc0116119b60b23bd6b Mon Sep 17 00:00:00 2001 From: Damilola Olufemi Date: Wed, 5 Feb 2025 10:56:41 +0000 Subject: [PATCH] fix(OSM-2190): check package version when fetching node key --- lib/dep-graph-builders/npm-lock-v2/index.ts | 7 +++++ .../simple-out-of-sync/package-lock.json | 28 +++++++++++++++++++ .../simple-out-of-sync/package.json | 15 ++++++++++ .../dep-graph-builders/npm-lock-v2.test.ts | 23 +++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package-lock.json create mode 100644 test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package.json diff --git a/lib/dep-graph-builders/npm-lock-v2/index.ts b/lib/dep-graph-builders/npm-lock-v2/index.ts index 33c2f30b..c61a0fb4 100644 --- a/lib/dep-graph-builders/npm-lock-v2/index.ts +++ b/lib/dep-graph-builders/npm-lock-v2/index.ts @@ -303,6 +303,13 @@ export const getChildNodeKey = ( // If we only have one candidate then we just take it if (candidateKeys.length === 1) { + if ( + semver.validRange(version) && + pkgs[candidateKeys[0]].version && + !semver.satisfies(pkgs[candidateKeys[0]].version, version) + ) { + return undefined; + } return candidateKeys[0]; } // If we are bundled we assume we are scoped by the bundle root at least diff --git a/test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package-lock.json b/test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package-lock.json new file mode 100644 index 00000000..dec31f98 --- /dev/null +++ b/test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "simple-out-of-sync", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "simple-out-of-sync", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "lodash": "4.17.17" + } + }, + "node_modules/lodash": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-/B2DjOphAoqi5BX4Gg2oh4UR0Gy/A7xYAMh3aSECEKzwS3eCDEpS0Cals1Ktvxwlal3bBJNc+5W9kNIcADdw5Q==" + } + }, + "dependencies": { + "lodash": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-/B2DjOphAoqi5BX4Gg2oh4UR0Gy/A7xYAMh3aSECEKzwS3eCDEpS0Cals1Ktvxwlal3bBJNc+5W9kNIcADdw5Q==" + } + } +} diff --git a/test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package.json b/test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package.json new file mode 100644 index 00000000..6256437b --- /dev/null +++ b/test/jest/dep-graph-builders/fixtures/npm-lock-v2/simple-out-of-sync/package.json @@ -0,0 +1,15 @@ +{ + "name": "simple-out-of-sync", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "lodash": "4.17.21" + } +} diff --git a/test/jest/dep-graph-builders/npm-lock-v2.test.ts b/test/jest/dep-graph-builders/npm-lock-v2.test.ts index a07dee5b..ad600ffa 100644 --- a/test/jest/dep-graph-builders/npm-lock-v2.test.ts +++ b/test/jest/dep-graph-builders/npm-lock-v2.test.ts @@ -439,6 +439,29 @@ describe('dep-graph-builder npm-lock-v2', () => { ).rejects.toThrow(new OutOfSyncError('ms@0.6.2', LockfileType.npm)); }); + it('project: simple-out-of-sync -> throws OutOfSyncError', async () => { + const fixtureName = 'simple-out-of-sync'; + const pkgJsonContent = readFileSync( + join(__dirname, `./fixtures/npm-lock-v2/${fixtureName}/package.json`), + 'utf8', + ); + const npmLockContent = readFileSync( + join( + __dirname, + `./fixtures/npm-lock-v2/${fixtureName}/package-lock.json`, + ), + 'utf8', + ); + await expect( + parseNpmLockV2Project(pkgJsonContent, npmLockContent, { + includeDevDeps: false, + includeOptionalDeps: true, + pruneCycles: true, + strictOutOfSync: true, + }), + ).rejects.toThrow(new OutOfSyncError('lodash@4.17.21', LockfileType.npm)); + }); + it('project: simple-top-level-out-of-sync -> throws OutOfSyncError', async () => { const fixtureName = 'missing-top-level-deps'; const pkgJsonContent = readFileSync(