diff --git a/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.spec.ts b/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.spec.ts index fc15bf32b8490..99b4a01cb8972 100644 --- a/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.spec.ts +++ b/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.spec.ts @@ -479,7 +479,7 @@ describe('TargetProjectLocator', () => { expect(proj5).toEqual('proj5'); }); - it('should be able to resolve packages alises', () => { + it('should be able to resolve packages aliases', () => { const lodash = targetProjectLocator.findProjectFromImport( 'lodash', 'libs/proj/index.ts' @@ -899,6 +899,85 @@ describe('TargetProjectLocator', () => { expect(result).toEqual('npm:@json2csv/plainjs'); }); }); + + describe('findNpmProjectFromImport', () => { + it('should resolve external node when the version does not match its own package.json (i.e. git remote) ', () => { + const projects = { + proj: { + name: 'proj', + type: 'lib' as const, + data: { + root: 'proj', + }, + }, + }; + const npmProjects = { + 'npm:foo': { + name: 'npm:foo' as const, + type: 'npm' as const, + data: { + version: + 'git+ssh://git@github.com/example/foo.git#6f4b450fc642abba540535f0755c990b42a16026', + packageName: 'foo', + }, + }, + }; + + const targetProjectLocator = new TargetProjectLocator( + projects, + npmProjects, + new Map() + ); + targetProjectLocator['readPackageJson'] = () => ({ + name: 'foo', + version: '0.0.1', + }); + const result = targetProjectLocator.findNpmProjectFromImport( + 'lodash', + 'proj/index.ts' + ); + + expect(result).toEqual('npm:foo'); + }); + + it('should resolve a specific version of external node', () => { + const projects = { + proj: { + name: 'proj', + type: 'lib' as const, + data: { + root: 'proj', + }, + }, + }; + const npmProjects = { + 'npm:foo@0.0.1': { + name: 'npm:foo@0.0.1' as const, + type: 'npm' as const, + data: { + version: '0.0.1', + packageName: 'foo', + }, + }, + }; + + const targetProjectLocator = new TargetProjectLocator( + projects, + npmProjects, + new Map() + ); + targetProjectLocator['readPackageJson'] = () => ({ + name: 'foo', + version: '0.0.1', + }); + const result = targetProjectLocator.findNpmProjectFromImport( + 'lodash', + 'proj/index.ts' + ); + + expect(result).toEqual('npm:foo@0.0.1'); + }); + }); }); describe('isBuiltinModuleImport()', () => { diff --git a/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts b/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts index 86b21bd19875b..af2890d22cdd8 100644 --- a/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts +++ b/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts @@ -18,6 +18,7 @@ import { resolveModuleByImport, } from '../../utils/typescript'; import { getPackageNameFromImportPath } from '../../../../utils/get-package-name-from-import-path'; + /** * The key is a combination of the package name and the workspace relative directory * containing the file importing it e.g. `lodash__packages/my-lib`, the value is the @@ -187,15 +188,24 @@ export class TargetProjectLocator { } const version = clean(externalPackageJson.version); - const npmProjectKey = `npm:${externalPackageJson.name}@${version}`; - let matchingExternalNode = this.npmProjects[npmProjectKey]; + let matchingExternalNode = + this.npmProjects[`npm:${externalPackageJson.name}@${version}`]; + if (!matchingExternalNode) { // check if it's a package alias, where the resolved package key is used as the version - const aliasNpmProjectKey = `npm:${packageName}@${npmProjectKey}`; + const aliasNpmProjectKey = `npm:${packageName}@npm:${externalPackageJson.name}@${version}`; matchingExternalNode = this.npmProjects[aliasNpmProjectKey]; - if (!matchingExternalNode) { - return null; - } + } + + if (!matchingExternalNode) { + // Fallback to package name as key. This can happen if the version in project graph is not the same as in the resolved package.json. + // e.g. Version in project graph is a git remote, but the resolved version is semver. + matchingExternalNode = + this.npmProjects[`npm:${externalPackageJson.name}`]; + } + + if (!matchingExternalNode) { + return null; } this.npmResolutionCache.set(