Thanks to visit codestin.com
Credit goes to github.com

Skip to content

chore: switch to using angular-devkit directly for schematics and builder #1985

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

Merged
merged 1 commit into from
Aug 13, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions packages/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
"LICENSE",
"builders.json"
],
"dependencies": {
"@nx/devkit": ">= 19.5.4 < 20.0.0",
"nx": ">= 19.5.4 < 20.0.0"
},
"devDependencies": {
"@angular-devkit/architect": ">= 0.1800.0 < 0.1900.0",
"@angular-devkit/core": ">= 18.0.0 < 19.0.0"
Expand Down
24 changes: 9 additions & 15 deletions packages/builder/src/lint.impl.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
import type { BuilderOutput } from '@angular-devkit/architect';
import {
convertNxExecutor,
joinPathFragments,
workspaceRoot,
} from '@nx/devkit';
import { createBuilder, type BuilderOutput } from '@angular-devkit/architect';
import type { ESLint } from 'eslint';
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { dirname, join, resolve } from 'path';
import type { Schema } from './schema';
import { resolveAndInstantiateESLint } from './utils/eslint-utils';

export default convertNxExecutor(
export default createBuilder(
async (options: Schema, context): Promise<BuilderOutput> => {
const systemRoot = context.root;
const systemRoot = context.workspaceRoot;

// eslint resolves files relative to the current working directory.
// We want these paths to always be resolved relative to the workspace
// root to be able to run the lint executor from any subfolder.
process.chdir(systemRoot);

const projectName = context.projectName || '<???>';
const projectName = context.target?.project ?? '<???>';
const printInfo = options.format && !options.silent;

if (printInfo) {
Expand All @@ -43,9 +38,7 @@
* we only want to support it if the user has explicitly opted into it by converting
* their root ESLint config to use eslint.config.js
*/
const useFlatConfig = existsSync(
joinPathFragments(workspaceRoot, 'eslint.config.js'),
);
const useFlatConfig = existsSync(join(systemRoot, 'eslint.config.js'));
const { eslint, ESLint } = await resolveAndInstantiateESLint(
eslintConfigPath,
options,
Expand Down Expand Up @@ -74,8 +67,9 @@
)
) {
let eslintConfigPathForError = `for ${projectName}`;
if (context.projectsConfigurations?.projects?.[projectName]?.root) {
const { root } = context.projectsConfigurations.projects[projectName];
const projectMetadata = await context.getProjectMetadata(projectName);

Check warning on line 70 in packages/builder/src/lint.impl.ts

View check run for this annotation

Codecov / codecov/patch

packages/builder/src/lint.impl.ts#L70

Added line #L70 was not covered by tests
if (projectMetadata?.root) {
const { root } = projectMetadata;

Check warning on line 72 in packages/builder/src/lint.impl.ts

View check run for this annotation

Codecov / codecov/patch

packages/builder/src/lint.impl.ts#L72

Added line #L72 was not covered by tests
eslintConfigPathForError = `\`${root}/.eslintrc.json\``;
}

Expand Down Expand Up @@ -168,7 +162,7 @@
const formattedResults = await formatter.format(finalLintResults);

if (options.outputFile) {
const pathToOutputFile = join(context.root, options.outputFile);
const pathToOutputFile = join(systemRoot, options.outputFile);
mkdirSync(dirname(pathToOutputFile), { recursive: true });
writeFileSync(pathToOutputFile, formattedResults);
} else {
Expand Down
2 changes: 0 additions & 2 deletions packages/schematics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@
"dependencies": {
"@angular-eslint/eslint-plugin": "18.2.0",
"@angular-eslint/eslint-plugin-template": "18.2.0",
"@nx/devkit": ">= 19.5.4 < 20.0.0",
"ignore": "5.3.2",
"nx": "^19.0.6",
"semver": "7.6.3",
"strip-json-comments": "3.1.1"
},
Expand Down
45 changes: 23 additions & 22 deletions packages/schematics/src/add-eslint-to-project/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Tree } from '../devkit-imports';
import { convertNxGenerator } from '../devkit-imports';
import type { Rule, Tree } from '@angular-devkit/schematics';
import { chain } from '@angular-devkit/schematics';
import {
addESLintTargetToProject,
createESLintConfigForProject,
Expand All @@ -11,26 +11,27 @@ interface Schema {
setParserOptionsProject?: boolean;
}

export default convertNxGenerator(async (tree: Tree, options: Schema) => {
const projectName = determineTargetProjectName(tree, options.project);
if (!projectName) {
throw new Error(
'\n' +
`
export default function addESLintToProject(schema: Schema): Rule {
return (tree: Tree) => {
const projectName = determineTargetProjectName(tree, schema.project);
if (!projectName) {
throw new Error(
'\n' +
`
Error: You must specify a project to add ESLint to because you have multiple projects in your angular.json

E.g. npx ng g @angular-eslint/schematics:add-eslint-to-project {{YOUR_PROJECT_NAME_GOES_HERE}}
`.trim(),
);
}

// Create the config file first so that we can check for its existence when setting the target
createESLintConfigForProject(
tree,
projectName,
options.setParserOptionsProject ?? false,
);

// Update the lint builder and config in angular.json
addESLintTargetToProject(tree, projectName, 'lint');
});
`.trim(),
);
}
return chain([
// Create the ESLint config file for the project
createESLintConfigForProject(
projectName,
schema.setParserOptionsProject ?? false,
),
// Set the lint builder and config in angular.json
addESLintTargetToProject(projectName, 'lint'),
]);
};
}
49 changes: 24 additions & 25 deletions packages/schematics/src/application/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import type { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { chain, externalSchematic } from '@angular-devkit/schematics';
/**
* We are able to use the full, unaltered Schema directly from @schematics/angular
* The applicable json file is copied from node_modules as a prebuiid step to ensure
* they stay in sync.
*/
import type { Schema as AngularSchema } from '@schematics/angular/application/schema';
import type { Tree } from '../devkit-imports';
import {
convertNxGenerator,
wrapAngularDevkitSchematic,
} from '../devkit-imports';
import {
addESLintTargetToProject,
createESLintConfigForProject,
Expand All @@ -18,25 +15,27 @@ interface Schema extends AngularSchema {
setParserOptionsProject?: boolean;
}

export default convertNxGenerator(async (tree: Tree, options: Schema) => {
// Remove angular-eslint specific options before passing to the Angular schematic
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { setParserOptionsProject, ...angularOptions } = options;

const applicationGenerator = wrapAngularDevkitSchematic(
'@schematics/angular',
'application',
);

await applicationGenerator(tree, angularOptions);
function eslintRelatedChanges(options: Schema) {
return chain([
// Create the ESLint config file for the project
createESLintConfigForProject(
options.name,
options.setParserOptionsProject ?? false,
),
// Update the lint builder and config in angular.json
addESLintTargetToProject(options.name, 'lint'),
]);
}

// Create the config file first so that we can check for its existence when setting the target
createESLintConfigForProject(
tree,
options.name,
options.setParserOptionsProject ?? false,
);
export default function (options: Schema): Rule {
return (host: Tree, context: SchematicContext) => {
// Remove angular-eslint specific options before passing to the Angular schematic
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { setParserOptionsProject, ...angularOptions } = options;

// Update the lint builder and config in angular.json
addESLintTargetToProject(tree, options.name, 'lint');
});
return chain([
externalSchematic('@schematics/angular', 'application', angularOptions),
eslintRelatedChanges(options),
])(host, context);
};
}
49 changes: 24 additions & 25 deletions packages/schematics/src/library/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import type { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { chain, externalSchematic } from '@angular-devkit/schematics';
/**
* We are able to use the full, unaltered Schema directly from @schematics/angular
* The applicable json file is copied from node_modules as a prebuiid step to ensure
* they stay in sync.
*/
import type { Schema as AngularSchema } from '@schematics/angular/library/schema';
import type { Tree } from '../devkit-imports';
import {
convertNxGenerator,
wrapAngularDevkitSchematic,
} from '../devkit-imports';
import {
addESLintTargetToProject,
createESLintConfigForProject,
Expand All @@ -18,25 +15,27 @@ interface Schema extends AngularSchema {
setParserOptionsProject?: boolean;
}

export default convertNxGenerator(async (tree: Tree, options: Schema) => {
// Remove angular-eslint specific options before passing to the Angular schematic
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { setParserOptionsProject, ...angularOptions } = options;

const libraryGenerator = wrapAngularDevkitSchematic(
'@schematics/angular',
'library',
);

await libraryGenerator(tree, angularOptions);
function eslintRelatedChanges(options: Schema) {
return chain([
// Create the ESLint config file for the project
createESLintConfigForProject(
options.name,
options.setParserOptionsProject ?? false,
),
// Update the lint builder and config in angular.json
addESLintTargetToProject(options.name, 'lint'),
]);
}

// Create the config file first so that we can check for its existence when setting the target
createESLintConfigForProject(
tree,
options.name,
options.setParserOptionsProject ?? false,
);
export default function (options: Schema): Rule {
return (host: Tree, context: SchematicContext) => {
// Remove angular-eslint specific options before passing to the Angular schematic
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { setParserOptionsProject, ...angularOptions } = options;

// Update the lint builder and config in angular.json
addESLintTargetToProject(tree, options.name, 'lint');
});
return chain([
externalSchematic('@schematics/angular', 'library', angularOptions),
eslintRelatedChanges(options),
])(host, context);
};
}
Loading