Skip to content

Commit

Permalink
fix(core): fix ghost alias when parsing yarn lockfile (#18646)
Browse files Browse the repository at this point in the history
  • Loading branch information
meeroslav authored Aug 17, 2023
1 parent 2180268 commit 43b802d
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 15 deletions.
144 changes: 144 additions & 0 deletions packages/nx/src/plugins/js/lock-file/yarn-parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,11 @@ describe('yarn LockFile utility', () => {
'node_modules/yargs/package.json': '{"version": "17.6.2"}',
'node_modules/yargs-parser/package.json': '{"version": "21.1.1"}',
'node_modules/yocto-queue/package.json': '{"version": "0.1.0"}',
'node_modules/@types/prop-types/package.json': '{"version": "15.7.5"}',
'node_modules/@docusaurus/core/package.json': '{"version": "2.4.1"}',
'node_modules/@docusaurus/react-loadable/package.json':
'{"version": "5.5.2"}',
'node_modules/react-loadable/package.json': '{"version": "5.5.2"}',
};
vol.fromJSON(fileSys, '/root');
});
Expand Down Expand Up @@ -620,6 +625,145 @@ describe('yarn LockFile utility', () => {
prunedLockFile.split('\n').slice(2)
);
});

describe('alias duplicate', () => {
it('should parse yarn berry', async () => {
const lockFile = `# This file is generated by running "yarn install" inside your project.
# Manual changes might be lost - proceed with caution!
__metadata:
version: 6
cacheKey: 8
"@docusaurus/core@npm:2.4.1":
version: 2.4.1
resolution: "@docusaurus/core@npm:2.4.1"
dependencies:
"@docusaurus/react-loadable": 5.5.2
react-loadable: "npm:@docusaurus/react-loadable@5.5.2"
bin:
docusaurus: bin/docusaurus.mjs
checksum: 40c887ef662f7679d803695d4193268c2c177c6d4e13b43b56cc519322522a1608b4bfc4999f6355be778ca7a0256f0d27ab18a19b352a9da1aed66e2644dc82
languageName: node
linkType: hard
"@docusaurus/react-loadable@npm:5.5.2, react-loadable@npm:@docusaurus/react-loadable@5.5.2":
version: 5.5.2
resolution: "@docusaurus/react-loadable@npm:5.5.2"
checksum: 930fb9e2936412a12461f210acdc154a433283921ca43ac3fc3b84cb6c12eb738b3a3719373022bf68004efeb1a928dbe36c467d7a1f86454ed6241576d936e7
languageName: node
linkType: hard
`;

const packageJson: PackageJson = {
name: '@my-ns/example',
version: '0.0.1',
type: 'commonjs',
dependencies: {
'@docusaurus/core': '2.4.1',
},
};

const builder = new ProjectGraphBuilder();
parseYarnLockfile(lockFile, packageJson, builder);
const graph = builder.getUpdatedProjectGraph();
expect(graph.externalNodes).toMatchInlineSnapshot(`
{
"npm:@docusaurus/core": {
"data": {
"hash": "40c887ef662f7679d803695d4193268c2c177c6d4e13b43b56cc519322522a1608b4bfc4999f6355be778ca7a0256f0d27ab18a19b352a9da1aed66e2644dc82",
"packageName": "@docusaurus/core",
"version": "2.4.1",
},
"name": "npm:@docusaurus/core",
"type": "npm",
},
"npm:@docusaurus/react-loadable": {
"data": {
"hash": "930fb9e2936412a12461f210acdc154a433283921ca43ac3fc3b84cb6c12eb738b3a3719373022bf68004efeb1a928dbe36c467d7a1f86454ed6241576d936e7",
"packageName": "@docusaurus/react-loadable",
"version": "5.5.2",
},
"name": "npm:@docusaurus/react-loadable",
"type": "npm",
},
"npm:react-loadable": {
"data": {
"hash": "930fb9e2936412a12461f210acdc154a433283921ca43ac3fc3b84cb6c12eb738b3a3719373022bf68004efeb1a928dbe36c467d7a1f86454ed6241576d936e7",
"packageName": "react-loadable",
"version": "npm:@docusaurus/react-loadable@5.5.2",
},
"name": "npm:react-loadable",
"type": "npm",
},
}
`);
});

it('should parse yarn classic', async () => {
const lockFile = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@docusaurus/core@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.4.1.tgz#4b8ff5766131ce3fbccaad0b1daf2ad4dc76f62d"
integrity sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g==
dependencies:
"@docusaurus/react-loadable" "5.5.2"
react-loadable "npm:@docusaurus/react-loadable@5.5.2"
"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2":
version "5.5.2"
resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce"
integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==
`;

const packageJson: PackageJson = {
name: '@my-ns/example',
version: '0.0.1',
type: 'commonjs',
dependencies: {
'@docusaurus/core': '2.4.1',
},
};

const builder = new ProjectGraphBuilder();
parseYarnLockfile(lockFile, packageJson, builder);
const graph = builder.getUpdatedProjectGraph();
expect(graph.externalNodes).toMatchInlineSnapshot(`
{
"npm:@docusaurus/core": {
"data": {
"hash": "sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g==",
"packageName": "@docusaurus/core",
"version": "2.4.1",
},
"name": "npm:@docusaurus/core",
"type": "npm",
},
"npm:@docusaurus/react-loadable": {
"data": {
"hash": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==",
"packageName": "@docusaurus/react-loadable",
"version": "5.5.2",
},
"name": "npm:@docusaurus/react-loadable",
"type": "npm",
},
"npm:react-loadable": {
"data": {
"hash": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==",
"packageName": "react-loadable",
"version": "npm:@docusaurus/react-loadable@5.5.2",
},
"name": "npm:react-loadable",
"type": "npm",
},
}
`);
});
});
});

describe('auxiliary tagged version ranges', () => {
Expand Down
33 changes: 18 additions & 15 deletions packages/nx/src/plugins/js/lock-file/yarn-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,17 @@ export function parseYarnLockfile(
addDependencies(groupedDependencies, builder, keyMap);
}

function getPackageNames(keys: string): string[] {
const packageNames = new Set<string>();
function getPackageNameKeyPairs(keys: string): Map<string, Set<string>> {
const result = new Map<string, Set<string>>();
keys.split(', ').forEach((key) => {
const packageName = key.slice(0, key.indexOf('@', 1));
packageNames.add(packageName);
if (result.has(packageName)) {
result.get(packageName).add(key);
} else {
result.set(packageName, new Set([key]));
}
});
return Array.from(packageNames);
return result;
}

function addNodes(
Expand All @@ -79,16 +83,14 @@ function addNodes(
if (snapshot.linkType === 'soft' || keys.includes('@patch:')) {
return;
}
const packageNames = getPackageNames(keys);
packageNames.forEach((packageName) => {
const version = findVersion(
packageName,
keys.split(', ')[0],
snapshot,
isBerry
);

keys.split(', ').forEach((key) => {
const nameKeyPairs = getPackageNameKeyPairs(keys);
nameKeyPairs.forEach((keySet, packageName) => {
const keysArray = Array.from(keySet);
// use key relevant to the package name
const version = findVersion(packageName, keysArray[0], snapshot, isBerry);

// use keys linked to the extracted package name
keysArray.forEach((key) => {
// we don't need to keep duplicates, we can just track the keys
const existingNode = nodes.get(packageName)?.get(version);
if (existingNode) {
Expand Down Expand Up @@ -182,11 +184,12 @@ function findVersion(
snapshot: YarnDependency,
isBerry: boolean
): string {
const versionRange = key.slice(packageName.length + 1);
const versionRange = key.slice(key.indexOf('@', 1) + 1);
// check for alias packages
const isAlias = isBerry
? snapshot.resolution && !snapshot.resolution.startsWith(`${packageName}@`)
: versionRange.startsWith('npm:');

if (isAlias) {
return versionRange;
}
Expand Down

1 comment on commit 43b802d

@vercel
Copy link

@vercel vercel bot commented on 43b802d Aug 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx.dev

Please sign in to comment.