Skip to content

Commit

Permalink
feat(linter): support custom build targets for buildability check (nr…
Browse files Browse the repository at this point in the history
  • Loading branch information
meeroslav committed May 4, 2023
1 parent 5f7b68c commit e328bfa
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const tsconfig = {
'@mycompany/domain1': ['libs/domain1/src/index.ts'],
'@mycompany/domain2': ['libs/domain2/src/index.ts'],
'@mycompany/buildableLib': ['libs/buildableLib/src/main.ts'],
'@mycompany/buildableLib2': ['libs/buildableLib2/src/main.ts'],
'@nonBuildableScope/nonBuildableLib': [
'libs/nonBuildableLib/src/main.ts',
],
Expand Down Expand Up @@ -91,6 +92,7 @@ const fileSys = {
'./libs/domain1/src/index.ts': '',
'./libs/domain2/src/index.ts': '',
'./libs/buildableLib/src/main.ts': '',
'./libs/buildableLib2/src/main.ts': '',
'./libs/nonBuildableLib/src/main.ts': '',
'./libs/public/src/index.ts': '',
'./libs/dependsOnPrivate/src/index.ts': '',
Expand Down Expand Up @@ -1726,10 +1728,63 @@ Circular file chain:
expect(failures[1].message).toEqual(message);
});

it('should error when buildable libraries with custom target import non-buildable libraries', () => {
const failures = runRule(
{
enforceBuildableLibDependency: true,
buildTargets: ['my-build'],
},
`${process.cwd()}/proj/libs/buildableLib2/src/main.ts`,
`
import '@nonBuildableScope/nonBuildableLib';
import('@nonBuildableScope/nonBuildableLib');
`,
{
nodes: {
buildableLib2: {
name: 'buildableLib2',
type: 'lib',
data: {
root: 'libs/buildableLib2',
tags: [],
implicitDependencies: [],
targets: {
'my-build': {
// defines a buildable lib
executor: '@angular-devkit/build-ng-packagr:build',
},
},
files: [createFile(`libs/buildableLib2/src/main.ts`)],
},
},
nonBuildableLib: {
name: 'nonBuildableLib',
type: 'lib',
data: {
root: 'libs/nonBuildableLib',
tags: [],
implicitDependencies: [],
targets: {},
files: [createFile(`libs/nonBuildableLib/src/main.ts`)],
},
},
},
dependencies: {},
}
);

const message =
'Buildable libraries cannot import or export from non-buildable libraries';
expect(failures.length).toEqual(2);
expect(failures[0].message).toEqual(message);
expect(failures[1].message).toEqual(message);
});

it('should not error when buildable libraries import another buildable libraries', () => {
const failures = runRule(
{
enforceBuildableLibDependency: true,
buildTargets: ['my-build', 'build'],
},
`${process.cwd()}/proj/libs/buildableLib/src/main.ts`,
`
Expand Down Expand Up @@ -1762,7 +1817,7 @@ Circular file chain:
tags: [],
implicitDependencies: [],
targets: {
build: {
'my-build': {
// defines a buildable lib
executor: '@angular-devkit/build-ng-packagr:build',
},
Expand Down
9 changes: 6 additions & 3 deletions packages/eslint-plugin/src/rules/enforce-module-boundaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
isComboDepConstraint,
} from '../utils/runtime-lint-utils';
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';
import { TargetProjectLocator } from '@nx/js/src/internal';
import { basename, dirname, relative } from 'path';
import {
getBarrelEntryPointByImportScope,
Expand All @@ -46,6 +45,7 @@ import { readProjectGraph } from '../utils/project-graph-utils';
type Options = [
{
allow: string[];
buildTargets: string[];
depConstraints: DepConstraint[];
enforceBuildableLibDependency: boolean;
allowCircularSelfDependency: boolean;
Expand Down Expand Up @@ -90,6 +90,7 @@ export default createESLintRule<Options, MessageIds>({
banTransitiveDependencies: { type: 'boolean' },
checkNestedExternalImports: { type: 'boolean' },
allow: [{ type: 'string' }],
buildTargets: [{ type: 'string' }],
depConstraints: [
{
type: 'object',
Expand Down Expand Up @@ -138,6 +139,7 @@ export default createESLintRule<Options, MessageIds>({
defaultOptions: [
{
allow: [],
buildTargets: ['build'],
depConstraints: [],
enforceBuildableLibDependency: false,
allowCircularSelfDependency: false,
Expand All @@ -151,6 +153,7 @@ export default createESLintRule<Options, MessageIds>({
[
{
allow,
buildTargets,
depConstraints,
enforceBuildableLibDependency,
allowCircularSelfDependency,
Expand Down Expand Up @@ -479,8 +482,8 @@ export default createESLintRule<Options, MessageIds>({
targetProject.type === 'lib'
) {
if (
hasBuildExecutor(sourceProject) &&
!hasBuildExecutor(targetProject)
hasBuildExecutor(sourceProject, buildTargets) &&
!hasBuildExecutor(targetProject, buildTargets)
) {
context.report({
node,
Expand Down
14 changes: 9 additions & 5 deletions packages/eslint-plugin/src/utils/runtime-lint-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,17 +381,21 @@ function parseImportWildcards(importDefinition: string): RegExp {
}

/**
* Verifies whether the given node has an architect builder attached
* Verifies whether the given node has a builder target
* @param projectGraph the node to verify
* @param buildTargets the list of targets to check for
*/
export function hasBuildExecutor(
projectGraph: ProjectGraphProjectNode
projectGraph: ProjectGraphProjectNode,
buildTargets = ['build']
): boolean {
return (
// can the architect not be defined? real use case?
projectGraph.data.targets &&
projectGraph.data.targets.build &&
projectGraph.data.targets.build.executor !== ''
buildTargets.some(
(target) =>
projectGraph.data.targets[target] &&
projectGraph.data.targets[target].executor !== ''
)
);
}

Expand Down

0 comments on commit e328bfa

Please sign in to comment.