fix(core): handle npm scope when matching project substring (#31160)
This PR fixes an issue if a JS project uses the same name as the npm scope. For example, if you have `@acme/acme` and `@acme/acme-e2e` projects, then running `nx lint acme` will fail with an error: ``` NX Multiple projects matched: @acme/acme-e2e @acme/acme ``` ## Current Behavior Nx fails to run the task ## Expected Behavior Nx should find the project to run the task for (ignoring scope) ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
b620ea7dc1
commit
5aa0c4050f
@ -88,6 +88,22 @@ describe('findMatchingProjects', () => {
|
|||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'@test/test': {
|
||||||
|
name: '@test/test',
|
||||||
|
type: 'app',
|
||||||
|
data: {
|
||||||
|
root: 'apps/test',
|
||||||
|
tags: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'@test/test-e2e': {
|
||||||
|
name: '@test/test-e2e',
|
||||||
|
type: 'app',
|
||||||
|
data: {
|
||||||
|
root: 'apps/test-e2e',
|
||||||
|
tags: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should return no projects when passed no patterns', () => {
|
it('should return no projects when passed no patterns', () => {
|
||||||
@ -114,6 +130,8 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
'@acme/nested/foo',
|
'@acme/nested/foo',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -128,6 +146,8 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
'@acme/nested/foo',
|
'@acme/nested/foo',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
]);
|
]);
|
||||||
expect(findMatchingProjects(['a', '!*'], projectGraph)).toEqual([]);
|
expect(findMatchingProjects(['a', '!*'], projectGraph)).toEqual([]);
|
||||||
});
|
});
|
||||||
@ -176,6 +196,8 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
'@acme/nested/foo',
|
'@acme/nested/foo',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -187,7 +209,7 @@ describe('findMatchingProjects', () => {
|
|||||||
projectGraph
|
projectGraph
|
||||||
);
|
);
|
||||||
expect(matches).toEqual(expect.arrayContaining(['a', 'b', 'nested']));
|
expect(matches).toEqual(expect.arrayContaining(['a', 'b', 'nested']));
|
||||||
expect(matches.length).toEqual(8);
|
expect(matches.length).toEqual(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should expand generic glob patterns for tags', () => {
|
it('should expand generic glob patterns for tags', () => {
|
||||||
@ -217,7 +239,11 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
]);
|
]);
|
||||||
expect(findMatchingProjects(['apps/*'], projectGraph)).toEqual(['c']);
|
expect(findMatchingProjects(['apps/*'], projectGraph)).toEqual([
|
||||||
|
'c',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
|
]);
|
||||||
expect(findMatchingProjects(['**/nested'], projectGraph)).toEqual([
|
expect(findMatchingProjects(['**/nested'], projectGraph)).toEqual([
|
||||||
'nested',
|
'nested',
|
||||||
]);
|
]);
|
||||||
@ -234,6 +260,8 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
'@acme/nested/foo',
|
'@acme/nested/foo',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
]);
|
]);
|
||||||
expect(findMatchingProjects(['!tag:api'], projectGraph)).toEqual([
|
expect(findMatchingProjects(['!tag:api'], projectGraph)).toEqual([
|
||||||
'b',
|
'b',
|
||||||
@ -243,6 +271,8 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
'@acme/nested/foo',
|
'@acme/nested/foo',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
]);
|
]);
|
||||||
expect(
|
expect(
|
||||||
findMatchingProjects(['!tag:api', 'test-project'], projectGraph)
|
findMatchingProjects(['!tag:api', 'test-project'], projectGraph)
|
||||||
@ -254,6 +284,8 @@ describe('findMatchingProjects', () => {
|
|||||||
'@acme/bar',
|
'@acme/bar',
|
||||||
'foo_bar1',
|
'foo_bar1',
|
||||||
'@acme/nested/foo',
|
'@acme/nested/foo',
|
||||||
|
'@test/test',
|
||||||
|
'@test/test-e2e',
|
||||||
'test-project',
|
'test-project',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
@ -280,6 +312,15 @@ describe('findMatchingProjects', () => {
|
|||||||
expect(findMatchingProjects(['fo'], projectGraph)).toEqual([]);
|
expect(findMatchingProjects(['fo'], projectGraph)).toEqual([]);
|
||||||
expect(findMatchingProjects(['nested/fo'], projectGraph)).toEqual([]);
|
expect(findMatchingProjects(['nested/fo'], projectGraph)).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle case where scope and names are the same', () => {
|
||||||
|
expect(findMatchingProjects(['test'], projectGraph)).toEqual([
|
||||||
|
'@test/test',
|
||||||
|
]);
|
||||||
|
expect(findMatchingProjects(['test-e2e'], projectGraph)).toEqual([
|
||||||
|
'@test/test-e2e',
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const projects = [
|
const projects = [
|
||||||
|
|||||||
@ -169,7 +169,7 @@ function addMatchingProjectsByName(
|
|||||||
if (!isGlobPattern(pattern.value)) {
|
if (!isGlobPattern(pattern.value)) {
|
||||||
// Custom regex that is basically \b but includes hyphens (-) and excludes underscores (_), so "foo" pattern matches "foo_bar" but not "foo-e2e".
|
// Custom regex that is basically \b but includes hyphens (-) and excludes underscores (_), so "foo" pattern matches "foo_bar" but not "foo-e2e".
|
||||||
const regex = new RegExp(
|
const regex = new RegExp(
|
||||||
`(?<![a-zA-Z0-9-])${pattern.value}(?![a-zA-Z0-9-])`,
|
`(?<![@a-zA-Z0-9-])${pattern.value}(?![@a-zA-Z0-9-])`,
|
||||||
'i'
|
'i'
|
||||||
);
|
);
|
||||||
const matchingProjects = Object.keys(projects).filter((name) =>
|
const matchingProjects = Object.keys(projects).filter((name) =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user