Skip to content

Commit

Permalink
feat(schematics): enhance nxEnforceModuleBoundaries check to support …
Browse files Browse the repository at this point in the history
…projects tagged with multiple tags
  • Loading branch information
vsavkin committed Mar 25, 2018
1 parent 7b63de6 commit d416c58
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 28 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"package": "./scripts/package.sh",
"release": "./scripts/release.sh",
"copy": "./scripts/copy.sh",
"test:schematics": "yarn linknpm && ./scripts/test_schematics.sh",
"test:nx": "yarn linknpm && ./scripts/test_nx.sh",
"test:schematics": "yarn linknpm fast && ./scripts/test_schematics.sh",
"test:nx": "yarn linknpm fast && ./scripts/test_nx.sh",
"test":
"yarn linknpm && ./scripts/test_nx.sh && ./scripts/test_schematics.sh",
"checkformat": "echo 1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,37 @@ describe('Enforce Module Boundaries', () => {
name: 'api',
root: 'libs/api/src',
type: ProjectType.lib,
tags: ['api'],
tags: ['api', 'domain1'],
files: [`libs/api/index.ts`]
},
{
name: 'impl',
root: 'libs/impl/src',
type: ProjectType.lib,
tags: ['impl'],
tags: ['impl', 'domain1'],
files: [`libs/impl/index.ts`]
},
{
name: 'impl2',
root: 'libs/impl2/src',
type: ProjectType.lib,
tags: ['impl'],
tags: ['impl', 'domain1'],
files: [`libs/impl2/index.ts`]
},
{
name: 'impl-domain2',
root: 'libs/impl-domain2/src',
type: ProjectType.lib,
tags: ['impl', 'domain2'],
files: [`libs/impl-domain2/index.ts`]
},
{
name: 'impl-both-domains',
root: 'libs/impl-both-domains/src',
type: ProjectType.lib,
tags: ['impl', 'domain1', 'domain2'],
files: [`libs/impl-both-domains/index.ts`]
},
{
name: 'untagged',
root: 'libs/untagged/src',
Expand All @@ -110,7 +124,9 @@ describe('Enforce Module Boundaries', () => {
const depConstraints = {
depConstraints: [
{ sourceTag: 'api', onlyDependOnLibsWithTags: ['api'] },
{ sourceTag: 'impl', onlyDependOnLibsWithTags: ['api', 'impl'] }
{ sourceTag: 'impl', onlyDependOnLibsWithTags: ['api', 'impl'] },
{ sourceTag: 'domain1', onlyDependOnLibsWithTags: ['domain1'] },
{ sourceTag: 'domain2', onlyDependOnLibsWithTags: ['domain2'] }
]
};

Expand Down Expand Up @@ -159,6 +175,47 @@ describe('Enforce Module Boundaries', () => {
);
});

it('should check all tags', () => {
const failures = runRule(
depConstraints,
`${process.cwd()}/proj/libs/impl/index.ts`,
`
import '@mycompany/impl-domain2';
`,
projectNodes
);

expect(failures[0].getFailure()).toEqual(
'A project tagged with "domain1" can only depend on libs tagged with "domain1"'
);
});

it('should allow a domain1 project to depend on a project that is tagged with domain1 and domain2', () => {
const failures = runRule(
depConstraints,
`${process.cwd()}/proj/libs/impl/index.ts`,
`
import '@mycompany/impl-both-domains';
`,
projectNodes
);

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

it('should allow a domain1/domain2 project depend on domain1', () => {
const failures = runRule(
depConstraints,
`${process.cwd()}/proj/libs/impl-both-domain/index.ts`,
`
import '@mycompany/impl';
`,
projectNodes
);

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

it('should not error when the constraints are satisfied', () => {
const failures = runRule(
depConstraints,
Expand Down
41 changes: 20 additions & 21 deletions packages/schematics/src/tslint/nxEnforceModuleBoundariesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,9 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {

// check that dependency constraints are satisfied
if (this.depConstraints.length > 0) {
const constraint = this.findConstraintFor(sourceProject);

const constraints = this.findConstraintsFor(sourceProject);
// when no constrains found => error. Force the user to provision them.
if (!constraint) {
if (constraints.length === 0) {
this.addFailureAt(
node.getStart(),
node.getWidth(),
Expand All @@ -187,20 +186,22 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
return;
}

if (
hasNoneOfTheseTags(
targetProject,
constraint.onlyDependOnLibsWithTags || []
)
) {
const allowedTags = constraint.onlyDependOnLibsWithTags
.map(s => `"${s}"`)
.join(', ');
const error = `A project tagged with "${
constraint.sourceTag
}" can only depend on libs tagged with ${allowedTags}`;
this.addFailureAt(node.getStart(), node.getWidth(), error);
return;
for (let constraint of constraints) {
if (
hasNoneOfTheseTags(
targetProject,
constraint.onlyDependOnLibsWithTags || []
)
) {
const allowedTags = constraint.onlyDependOnLibsWithTags
.map(s => `"${s}"`)
.join(', ');
const error = `A project tagged with "${
constraint.sourceTag
}" can only depend on libs tagged with ${allowedTags}`;
this.addFailureAt(node.getStart(), node.getWidth(), error);
return;
}
}
}
}
Expand Down Expand Up @@ -294,10 +295,8 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
return s.startsWith('.');
}

private findConstraintFor(sourceProject: ProjectNode) {
return this.depConstraints.filter(f =>
hasTag(sourceProject, f.sourceTag)
)[0];
private findConstraintsFor(sourceProject: ProjectNode) {
return this.depConstraints.filter(f => hasTag(sourceProject, f.sourceTag));
}
}

Expand Down
5 changes: 5 additions & 0 deletions scripts/build_for_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

rm -rf build
./node_modules/.bin/ngc
rsync -a --exclude=*.ts packages/ build/packages
7 changes: 6 additions & 1 deletion scripts/link.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#!/usr/bin/env bash

./scripts/build.sh
if [ "$1" = "fast" ]; then
./scripts/build_for_test.sh
fi
if [ "$1" != "fast" ]; then
./scripts/build.sh
fi

rm -rf node_modules/@nrwl
cp -r build/packages node_modules/@nrwl
Expand Down

0 comments on commit d416c58

Please sign in to comment.