Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(linter): project with empty onlyDependsOn can only depend on tagless project #12878

Merged
merged 1 commit into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const tsconfig = {
paths: {
'@mycompany/impl': ['libs/impl/src/index.ts'],
'@mycompany/untagged': ['libs/untagged/src/index.ts'],
'@mycompany/tagged': ['libs/tagged/src/index.ts'],
'@mycompany/api': ['libs/api/src/index.ts'],
'@mycompany/impl-domain2': ['libs/impl-domain2/src/index.ts'],
'@mycompany/impl-both-domains': ['libs/impl-both-domains/src/index.ts'],
Expand Down Expand Up @@ -69,6 +70,7 @@ const packageJson = {
const fileSys = {
'./libs/impl/src/index.ts': '',
'./libs/untagged/src/index.ts': '',
'./libs/tagged/src/index.ts': '',
'./libs/api/src/index.ts': '',
'./libs/impl-domain2/src/index.ts': '',
'./libs/impl-both-domains/src/index.ts': '',
Expand Down Expand Up @@ -310,9 +312,10 @@ describe('Enforce Module Boundaries (eslint)', () => {
implicitDependencies: [],
architect: {},
files: [
createFile(
`libs/private/src/index.tslibs/private/src/index.tslibs/private/src/index.ts`
),
createFile(`libs/private/src/index.ts`, [
'untaggedName',
'taggedName',
]),
],
},
},
Expand All @@ -327,6 +330,17 @@ describe('Enforce Module Boundaries (eslint)', () => {
files: [createFile(`libs/untagged/src/index.ts`)],
},
},
taggedName: {
name: 'taggedName',
type: 'lib',
data: {
root: 'libs/tagged',
tags: ['some-tag'],
implicitDependencies: [],
architect: {},
files: [createFile(`libs/tagged/src/index.ts`)],
},
},
},
externalNodes: {
'npm:npm-package': {
Expand Down Expand Up @@ -387,6 +401,7 @@ describe('Enforce Module Boundaries (eslint)', () => {
{ sourceTag: 'domain1', onlyDependOnLibsWithTags: ['domain1'] },
{ sourceTag: 'domain2', onlyDependOnLibsWithTags: ['domain2'] },
{ sourceTag: 'public', notDependOnLibsWithTags: ['private'] },
{ sourceTag: 'private', onlyDependOnLibsWithTags: [] },
],
};

Expand Down Expand Up @@ -530,6 +545,38 @@ describe('Enforce Module Boundaries (eslint)', () => {
expect(failures[1].message).toEqual(message);
});

it('should not error when the target library is untagged, if source expects it', () => {
const failures = runRule(
depConstraints,
`${process.cwd()}/proj/libs/private/src/index.ts`,
`
import '@mycompany/untagged';
import('@mycompany/untagged');
`,
graph
);

expect(failures.length).toEqual(0);
});

it('should error when the target library is tagged, if source does not expect it', () => {
const failures = runRule(
depConstraints,
`${process.cwd()}/proj/libs/private/src/index.ts`,
`
import '@mycompany/tagged';
import('@mycompany/tagged');
`,
graph
);

const message =
'A project tagged with "private" cannot depend on any libs with tags';
expect(failures.length).toEqual(2);
expect(failures[0].message).toEqual(message);
expect(failures[1].message).toEqual(message);
});

it('should error when the target library has a disallowed tag', () => {
const failures = runRule(
depConstraints,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export type MessageIds =
| 'nestedBannedExternalImportsViolation'
| 'noTransitiveDependencies'
| 'onlyTagsConstraintViolation'
| 'emptyOnlyTagsConstraintViolation'
| 'notTagsConstraintViolation';
export const RULE_NAME = 'enforce-module-boundaries';

Expand Down Expand Up @@ -117,6 +118,8 @@ export default createESLintRule<Options, MessageIds>({
nestedBannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package. Nested import found at {{childProjectName}}`,
noTransitiveDependencies: `Transitive dependencies are not allowed. Only packages defined in the "package.json" can be imported`,
onlyTagsConstraintViolation: `A project tagged with "{{sourceTag}}" can only depend on libs tagged with {{tags}}`,
emptyOnlyTagsConstraintViolation:
'A project tagged with "{{sourceTag}}" cannot depend on any libs with tags',
notTagsConstraintViolation: `A project tagged with "{{sourceTag}}" can not depend on libs tagged with {{tags}}\n\nViolation detected in:\n{{projects}}`,
},
},
Expand Down Expand Up @@ -516,6 +519,20 @@ export default createESLintRule<Options, MessageIds>({
});
return;
}
if (
constraint.onlyDependOnLibsWithTags &&
constraint.onlyDependOnLibsWithTags.length === 0 &&
targetProject.data.tags.length !== 0
) {
context.report({
node,
messageId: 'emptyOnlyTagsConstraintViolation',
data: {
sourceTag: constraint.sourceTag,
},
});
return;
}
if (
constraint.notDependOnLibsWithTags &&
constraint.notDependOnLibsWithTags.length
Expand Down