Skip to content

Commit

Permalink
feat(schematics): add allow option to whitelist deep imports
Browse files Browse the repository at this point in the history
Adds an `allow` option to the `nx-enforce-module-boundaries` rule.

This option allows users to provide a specific set of library deep imports that should be whitelisted. Values need to be to be absolute library import paths, e.g., `@npmScope/library/subdirectory`. This option does not affect relative imports.
  • Loading branch information
emilio-martinez authored and vsavkin committed Dec 3, 2017
1 parent 7e479be commit b3f6735
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 9 deletions.
17 changes: 17 additions & 0 deletions packages/schematics/migrations/20171202-change-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { updateJsonFile } from '../src/collection/utility/fileutils';

export default {
description: 'Update the schema file to reflect the `allow` option for `nx-enforce-module-boundaries`.',
run: () => {
updateJsonFile('tslint.json', json => {
const ruleName = 'nx-enforce-module-boundaries';
const ruleOptionName = 'allow';
const rule = ruleName in json.rules ? json.rules[ruleName] : null;

// Only modify when the rule is configured with optional arguments
if (Array.isArray(rule) && typeof rule[2] === 'object' && rule[2] !== null) {
rule[2][ruleOptionName] = [];
}
});
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ describe('application', () => {
expect(tsconfigJson.compilerOptions.paths).toEqual({ '@myApp/*': ['libs/*'] });

const tslintJson = JSON.parse(getFileContent(tree, '/my-app/tslint.json'));
expect(tslintJson.rules['nx-enforce-module-boundaries']).toEqual([true, { lazyLoad: [], npmScope: 'myApp' }]);
expect(tslintJson.rules['nx-enforce-module-boundaries']).toEqual([
true,
{ allow: [], lazyLoad: [], npmScope: 'myApp' }
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@
true,
{
"npmScope": "<%= npmScope %>",
"lazyLoad": []
"lazyLoad": [],
"allow": []
}
]
}
Expand Down
9 changes: 5 additions & 4 deletions packages/schematics/src/collection/testing-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export function createEmptyWorkspace(tree: Tree): Tree {
true,
{
npmScope: '<%= npmScope %>',
lazyLoad: []
lazyLoad: [],
allow: []
}
]
}
Expand Down Expand Up @@ -41,14 +42,14 @@ export function createApp(tree: Tree, appName: string): Tree {
`
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.log(err));
Expand Down
2 changes: 1 addition & 1 deletion packages/schematics/src/collection/workspace/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function updateTsLintJson(options: Schema) {
['no-trailing-whitespace', 'one-line', 'quotemark', 'typedef-whitespace', 'whitespace'].forEach(key => {
json[key] = undefined;
});
json['nx-enforce-module-boundaries'] = [true, { npmScope: npmScope(options), lazyLoad: [] }];
json['nx-enforce-module-boundaries'] = [true, { npmScope: npmScope(options), lazyLoad: [], allow: [] }];
});
return host;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { Rule } from './nxEnforceModuleBoundariesRule';
describe('Enforce Module Boundaries', () => {
it('should not error when everything is in order', () => {
const failures = runRule(
{ npmScope: 'mycompany' },
{ npmScope: 'mycompany', allow: ['@mycompany/mylib/deep'] },
`
import '@mycompany/mylib';
import '@mycompany/mylib/deep';
import '../blah';
`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
public visitImportDeclaration(node: ts.ImportDeclaration) {
const npmScope = `@${this.getOptions()[0].npmScope}`;
const lazyLoad = this.getOptions()[0].lazyLoad;
const allow: string[] = Array.isArray(this.getOptions()[0].allow)
? this.getOptions()[0].allow.map(a => `${a}`)
: [];
const imp = node.moduleSpecifier.getText().substring(1, node.moduleSpecifier.getText().length - 1);
const impParts = imp.split(path.sep);

if (impParts[0] === npmScope && impParts.length > 2) {
if (impParts[0] === npmScope && allow.indexOf(imp) === -1 && impParts.length > 2) {
this.addFailureAt(node.getStart(), node.getWidth(), 'deep imports into libraries are forbidden');
} else if (impParts[0] === npmScope && impParts.length === 2 && lazyLoad && lazyLoad.indexOf(impParts[1]) > -1) {
this.addFailureAt(node.getStart(), node.getWidth(), 'import of lazy-loaded libraries are forbidden');
Expand Down

0 comments on commit b3f6735

Please sign in to comment.