diff --git a/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.spec.ts b/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.spec.ts index fd85354e2a876..45cb6c7d9e8b7 100644 --- a/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.spec.ts +++ b/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.spec.ts @@ -7,6 +7,7 @@ import { } from '@nrwl/devkit'; import { DepConstraint, + findConstraintsFor, findTransitiveExternalDependencies, hasBannedDependencies, hasBannedImport, @@ -19,6 +20,68 @@ jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); +describe('findConstraintsFor', () => { + it('should find constraints matching tag', () => { + const constriants: DepConstraint[] = [ + { sourceTag: 'a', onlyDependOnLibsWithTags: ['b'] }, + { sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] }, + { sourceTag: 'c', onlyDependOnLibsWithTags: ['a'] }, + ]; + + expect( + findConstraintsFor(constriants, { + type: 'lib', + name: 'someLib', + data: { root: '.', files: [], tags: ['b'] }, + }) + ).toEqual([{ sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] }]); + }); + + it('should find constraints matching *', () => { + const constriants: DepConstraint[] = [ + { sourceTag: 'a', onlyDependOnLibsWithTags: ['b'] }, + { sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] }, + { sourceTag: '*', onlyDependOnLibsWithTags: ['a'] }, + ]; + + expect( + findConstraintsFor(constriants, { + type: 'lib', + name: 'someLib', + data: { root: '.', files: [], tags: ['b'] }, + }) + ).toEqual([ + { sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] }, + { sourceTag: '*', onlyDependOnLibsWithTags: ['a'] }, + ]); + }); + + it('should find constraints matching regex', () => { + const constriants: DepConstraint[] = [ + { sourceTag: 'a', onlyDependOnLibsWithTags: ['a'] }, + { sourceTag: '/^b$/', onlyDependOnLibsWithTags: ['c'] }, + { sourceTag: '/a|b/', onlyDependOnLibsWithTags: ['c'] }, + ]; + expect( + findConstraintsFor(constriants, { + type: 'lib', + name: 'someLib', + data: { root: '.', files: [], tags: ['b'] }, + }) + ).toEqual([ + { sourceTag: '/^b$/', onlyDependOnLibsWithTags: ['c'] }, + { sourceTag: '/a|b/', onlyDependOnLibsWithTags: ['c'] }, + ]); + expect( + findConstraintsFor(constriants, { + type: 'lib', + name: 'someLib', + data: { root: '.', files: [], tags: ['baz'] }, + }) + ).toEqual([{ sourceTag: '/a|b/', onlyDependOnLibsWithTags: ['c'] }]); + }); +}); + describe('hasBannedImport', () => { const source: ProjectGraphProjectNode = { type: 'lib', diff --git a/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.ts b/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.ts index ab816546c5b42..8a9ad35b12a5d 100644 --- a/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.ts +++ b/packages/eslint-plugin-nx/src/utils/runtime-lint-utils.ts @@ -86,8 +86,23 @@ export function findDependenciesWithTags( ); } -function hasTag(proj: ProjectGraphProjectNode, tag: string) { - return tag === '*' || (proj.data.tags || []).indexOf(tag) > -1; +const regexMap = new Map(); +function hasTag(proj: ProjectGraphProjectNode, tag: string): boolean { + if (tag === '*') return true; + + // if the tag is a regex, check if the project matches the regex + if (tag.startsWith('/') && tag.endsWith('/')) { + let regex; + if (regexMap.has(tag)) { + regex = regexMap.get(tag); + } else { + regex = new RegExp(tag.substring(1, tag.length - 1)); + regexMap.set(tag, regex); + } + return (proj.data.tags || []).some((t) => regex.test(t)); + } + + return (proj.data.tags || []).indexOf(tag) > -1; } export function matchImportWithWildcard(