mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(migrations): skip tsconfig files of non-Angular projects
Only touch tsconfig files for targets that use an Angular builder, including community ones like Nx, so non-Angular projects in mixed workspaces are left alone.
Fixes #69837
(cherry picked from commit f72600eadd)
This commit is contained in:
@@ -12,7 +12,9 @@ import {JSONFile} from '@schematics/angular/utility/json-file';
|
||||
|
||||
export function migrate(): Rule {
|
||||
return async (tree: Tree) => {
|
||||
const {buildPaths, testPaths} = await getProjectTsConfigPaths(tree);
|
||||
const {buildPaths, testPaths} = await getProjectTsConfigPaths(tree, {
|
||||
angularBuildersOnly: true,
|
||||
});
|
||||
const allPaths = [...new Set([...buildPaths, ...testPaths])];
|
||||
|
||||
for (const tsconfigPath of allPaths) {
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('strict-safe-navigation-narrow migration', () => {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@angular/build:application',
|
||||
options: {
|
||||
tsConfig: './tsconfig.json',
|
||||
},
|
||||
@@ -138,4 +139,44 @@ describe('strict-safe-navigation-narrow migration', () => {
|
||||
tsconfig.angularCompilerOptions.extendedDiagnostics.checks.nullishCoalescingNotNullable,
|
||||
).toBe('suppress');
|
||||
});
|
||||
|
||||
it('should not migrate tsconfig files of projects that do not use an Angular builder', async () => {
|
||||
tree.overwrite(
|
||||
'/angular.json',
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
projects: {
|
||||
'angular-app': {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@angular/build:application',
|
||||
options: {tsConfig: './tsconfig.app.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
'node-lib': {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@nx/js:tsc',
|
||||
options: {tsConfig: './tsconfig.lib.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
tree.create('/tsconfig.app.json', JSON.stringify({compilerOptions: {target: 'es2020'}}));
|
||||
tree.create('/tsconfig.lib.json', JSON.stringify({compilerOptions: {target: 'es2020'}}));
|
||||
|
||||
const runMigration = migrate();
|
||||
await runMigration(tree, {} as any);
|
||||
|
||||
const appTsconfig = parseConfig(tree, '/tsconfig.app.json');
|
||||
expect(
|
||||
appTsconfig.angularCompilerOptions.extendedDiagnostics.checks.nullishCoalescingNotNullable,
|
||||
).toBe('suppress');
|
||||
expect(parseConfig(tree, '/tsconfig.lib.json').angularCompilerOptions).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,7 +44,9 @@ function getResolvedAngularCompilerOptions(tree: any, tsconfigPath: string): Rec
|
||||
*/
|
||||
export function migrate(): Rule {
|
||||
return async (tree) => {
|
||||
const {buildPaths, testPaths} = await getProjectTsConfigPaths(tree);
|
||||
const {buildPaths, testPaths} = await getProjectTsConfigPaths(tree, {
|
||||
angularBuildersOnly: true,
|
||||
});
|
||||
const allPaths = [...new Set([...buildPaths, ...testPaths])];
|
||||
|
||||
for (const tsconfigPath of allPaths) {
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('strict-templates-default migration', () => {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@angular/build:application',
|
||||
options: {
|
||||
tsConfig: './tsconfig.json',
|
||||
},
|
||||
@@ -197,4 +198,41 @@ describe('strict-templates-default migration', () => {
|
||||
expect(baseTsconfig.angularCompilerOptions).toBeDefined();
|
||||
expect(appTsconfig.angularCompilerOptions).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not migrate tsconfig files of projects that do not use an Angular builder', async () => {
|
||||
tree.overwrite(
|
||||
'/angular.json',
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
projects: {
|
||||
'angular-app': {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@angular/build:application',
|
||||
options: {tsConfig: './tsconfig.app.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
'node-lib': {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@nx/js:tsc',
|
||||
options: {tsConfig: './tsconfig.lib.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
tree.create('/tsconfig.app.json', JSON.stringify({compilerOptions: {target: 'es2020'}}));
|
||||
tree.create('/tsconfig.lib.json', JSON.stringify({compilerOptions: {target: 'es2020'}}));
|
||||
|
||||
await migrate()(tree, {} as any);
|
||||
|
||||
const appTsconfig = parseConfig(tree, '/tsconfig.app.json');
|
||||
expect(appTsconfig.angularCompilerOptions.strictTemplates).toBe(false);
|
||||
expect(parseConfig(tree, '/tsconfig.lib.json').angularCompilerOptions).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,4 +100,59 @@ describe('project tsconfig paths', () => {
|
||||
|
||||
expect((await getProjectTsConfigPaths(testTree)).buildPaths).toEqual(['tsconfig.json']);
|
||||
});
|
||||
|
||||
it('should only return tsconfig paths of Angular builders when `angularBuildersOnly` is set', async () => {
|
||||
testTree.create('/tsconfig.app.json', '');
|
||||
testTree.create('/tsconfig.nx.json', '');
|
||||
testTree.create('/tsconfig.lib.json', '');
|
||||
testTree.create('/tsconfig.ngx-build-plus.json', '');
|
||||
testTree.create(
|
||||
'/angular.json',
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
projects: {
|
||||
angular_app: {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@angular/build:application',
|
||||
options: {tsConfig: './tsconfig.app.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
nx_angular_app: {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: '@nx/angular:webpack-browser',
|
||||
options: {tsConfig: './tsconfig.nx.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
node_lib: {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {builder: '@nx/js:tsc', options: {tsConfig: './tsconfig.lib.json'}},
|
||||
},
|
||||
},
|
||||
ngx_build_plus_app: {
|
||||
root: '',
|
||||
architect: {
|
||||
build: {
|
||||
builder: 'ngx-build-plus:browser',
|
||||
options: {tsConfig: './tsconfig.ngx-build-plus.json'},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const {buildPaths} = await getProjectTsConfigPaths(testTree, {angularBuildersOnly: true});
|
||||
expect(buildPaths).toEqual([
|
||||
'tsconfig.app.json',
|
||||
'tsconfig.nx.json',
|
||||
'tsconfig.ngx-build-plus.json',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,9 +12,14 @@ import {Tree} from '@angular-devkit/schematics';
|
||||
/**
|
||||
* Gets all tsconfig paths from a CLI project by reading the workspace configuration
|
||||
* and looking for common tsconfig locations.
|
||||
*
|
||||
* When `angularBuildersOnly` is set, only targets that use an Angular builder are considered.
|
||||
* This avoids picking up tsconfig files of non-Angular projects in a mixed workspace (e.g. an Nx
|
||||
* monorepo), which should not be touched by Angular migrations.
|
||||
*/
|
||||
export async function getProjectTsConfigPaths(
|
||||
tree: Tree,
|
||||
{angularBuildersOnly = false}: {angularBuildersOnly?: boolean} = {},
|
||||
): Promise<{buildPaths: string[]; testPaths: string[]}> {
|
||||
// Start with some tsconfig paths that are generally used within CLI projects. Note
|
||||
// that we are not interested in IDE-specific tsconfig files (e.g. /tsconfig.json)
|
||||
@@ -24,6 +29,10 @@ export async function getProjectTsConfigPaths(
|
||||
const workspace = await getWorkspace(tree);
|
||||
for (const [, project] of workspace.projects) {
|
||||
for (const [name, target] of project.targets) {
|
||||
if (angularBuildersOnly && !isAngularBuilder(target.builder)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [, options] of allTargetOptions(target)) {
|
||||
const tsConfig = options['tsConfig'];
|
||||
// Filter out tsconfig files that don't exist in the CLI project.
|
||||
@@ -46,6 +55,22 @@ export async function getProjectTsConfigPaths(
|
||||
};
|
||||
}
|
||||
|
||||
/** Prefixes of Angular builders, including common community builders (e.g. Nx). */
|
||||
const angularBuilderPrefixes = [
|
||||
'@angular-devkit/build-angular:',
|
||||
'@angular/build:',
|
||||
'@nx/angular:',
|
||||
'@angular-builders/',
|
||||
'ngx-build-plus:',
|
||||
];
|
||||
|
||||
/** Whether the given builder is a recognized Angular builder. */
|
||||
function isAngularBuilder(builder: string | undefined): boolean {
|
||||
return (
|
||||
builder !== undefined && angularBuilderPrefixes.some((prefix) => builder.startsWith(prefix))
|
||||
);
|
||||
}
|
||||
|
||||
/** Get options for all configurations for the passed builder target. */
|
||||
function* allTargetOptions(
|
||||
target: workspaces.TargetDefinition,
|
||||
|
||||
Reference in New Issue
Block a user