Skip to content

Commit 8fb5259

Browse files
alan-agius4filipesilva
authored andcommitted
feat(@schematics/angular): add migration to remove solution style tsconfig
Following the issues highlighted in https://docs.google.com/document/d/1eB6cGCG_2ircfS5GzpDC9dBgikeYYcMxghVH5sDESHw/edit?usp=sharing and discussions held with the TypeScript team. Together with the TypeScript team it was decided that the best course of action is to rollback this feature. In future, it is not excluded that solution style tsconfigs are re-introduced. Closes #18040, closes #18130 and closes #18170
1 parent 8b96e52 commit 8fb5259

File tree

4 files changed

+94
-177
lines changed

4 files changed

+94
-177
lines changed

packages/schematics/angular/migrations/migration-collection.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,6 @@
9090
"factory": "./update-10/update-libraries-tslib",
9191
"description": "Update library projects to use tslib version 2 as a direct dependency. Read more about this here: https://v10.angular.io/guide/migration-update-libraries-tslib"
9292
},
93-
"solution-style-tsconfig": {
94-
"version": "10.0.0-beta.7",
95-
"factory": "./update-10/solution-style-tsconfig",
96-
"description": "Add \"Solution Style\" TypeScript configuration file support. This improves developer experience using editors powered by TypeScript’s language server. Read more about this here: https://v10.angular.io/guide/migration-solution-style-tsconfig"
97-
},
9893
"update-workspace-dependencies": {
9994
"version": "10.0.0-rc.2",
10095
"factory": "./update-10/update-dependencies",
@@ -104,6 +99,11 @@
10499
"version": "10.0.1",
105100
"factory": "./update-10/update-module-and-target-compiler-options",
106101
"description": "Update 'module' and 'target' TypeScript compiler options. Read more about this here: https://v10.angular.io/guide/migration-update-module-and-target-compiler-options"
102+
},
103+
"remove-solution-style-tsconfig": {
104+
"version": "10.1.0-next.5",
105+
"factory": "./update-10/remove-solution-style-tsconfig",
106+
"description": "Removing \"Solution Style\" TypeScript configuration file support."
107107
}
108108
}
109109
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { Path, dirname, join, normalize, resolve } from '@angular-devkit/core';
9+
import { DirEntry, Rule } from '@angular-devkit/schematics';
10+
import { JSONFile } from '../../utility/json-file';
11+
12+
function* visitExtendedJsonFiles(directory: DirEntry): IterableIterator<Path> {
13+
for (const path of directory.subfiles) {
14+
if (!path.endsWith('.json')) {
15+
continue;
16+
}
17+
18+
const entry = directory.file(path);
19+
const content = entry?.content.toString();
20+
if (content?.includes('tsconfig.base.json')) {
21+
yield join(directory.path, path);
22+
}
23+
}
24+
25+
for (const path of directory.subdirs) {
26+
if (path === 'node_modules' || path.startsWith('.')) {
27+
continue;
28+
}
29+
30+
yield* visitExtendedJsonFiles(directory.dir(path));
31+
}
32+
}
33+
34+
export default function (): Rule {
35+
return (host, context) => {
36+
const logger = context.logger;
37+
38+
const tsConfig = new JSONFile(host, 'tsconfig.json');
39+
const files = tsConfig.get(['files']);
40+
if (!(Array.isArray(files) && files.length === 0)) {
41+
logger.info('Migration has already been executed.');
42+
43+
return;
44+
}
45+
46+
if (host.exists('tsconfig.base.json')) {
47+
host.overwrite('tsconfig.json', host.read('tsconfig.base.json') || '');
48+
host.delete('tsconfig.base.json');
49+
}
50+
51+
// Iterate over all tsconfig files and change the extends from 'tsconfig.base.json' to 'tsconfig.json'.
52+
const extendsJsonPath = ['extends'];
53+
for (const path of visitExtendedJsonFiles(host.root)) {
54+
const tsConfigDir = dirname(normalize(path));
55+
let tsConfigJson;
56+
57+
try {
58+
tsConfigJson = new JSONFile(host, path);
59+
const extendsValue = tsConfigJson.get(extendsJsonPath);
60+
61+
if (typeof extendsValue === 'string' && '/tsconfig.base.json' === resolve(tsConfigDir, normalize(extendsValue))) {
62+
// tsconfig extends the workspace tsconfig path.
63+
tsConfig.modify(extendsJsonPath, extendsValue.replace('tsconfig.base.json', 'tsconfig.json'));
64+
}
65+
} catch (error) {
66+
logger.warn(
67+
`${error.message || error}\n` +
68+
'If this is a TypeScript configuration file you will need to update the "extends" value manually.',
69+
);
70+
71+
continue;
72+
}
73+
}
74+
};
75+
}

packages/schematics/angular/migrations/update-10/solution-style-tsconfig_spec.ts renamed to packages/schematics/angular/migrations/update-10/remove-solution-style-tsconfig_spec.ts

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import { EmptyTree } from '@angular-devkit/schematics';
1010
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
1111
import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
1212

13-
describe('Migration to create "Solution Style" tsconfig', () => {
14-
const schematicName = 'solution-style-tsconfig';
13+
describe('Migration to remove "Solution Style" tsconfig', () => {
14+
const schematicName = 'remove-solution-style-tsconfig';
1515

1616
const schematicRunner = new SchematicTestRunner(
1717
'migrations',
@@ -70,49 +70,32 @@ describe('Migration to create "Solution Style" tsconfig', () => {
7070

7171
// Create tsconfigs
7272
const compilerOptions = { target: 'es2015' };
73-
createJsonFile(tree, 'tsconfig.json', { compilerOptions });
73+
createJsonFile(tree, 'tsconfig.json', { files: [] });
74+
createJsonFile(tree, 'tsconfig.base.json', { compilerOptions });
7475
createJsonFile(tree, 'tsconfig.common.json', { compilerOptions });
7576
createJsonFile(tree, 'src/tsconfig.json', { extends: './../tsconfig.json', compilerOptions });
76-
createJsonFile(tree, 'src/tsconfig.tsc.json', { extends: './tsconfig.json', compilerOptions });
77+
createJsonFile(tree, 'src/tsconfig.base.json', { extends: './../tsconfig.json', compilerOptions });
78+
createJsonFile(tree, 'src/tsconfig.tsc.json', { extends: './tsconfig.base.json', compilerOptions });
7779
createJsonFile(tree, 'src/tsconfig.app.json', { extends: './../tsconfig.common.json', compilerOptions });
7880
createJsonFile(tree, 'src/tsconfig.spec.json', { extends: './../tsconfig.json', compilerOptions });
7981
createJsonFile(tree, 'src/tsconfig.worker.json', { extends: './../tsconfig.json', compilerOptions });
8082
});
8183

82-
it(`should rename 'tsconfig.json' to 'tsconfig.json'`, async () => {
84+
it(`should rename 'tsconfig.base.json' to 'tsconfig.json'`, async () => {
8385
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
84-
expect(newTree.exists('tsconfig.json')).toBeTrue();
86+
expect(readJsonFile(newTree, 'tsconfig.json')['compilerOptions']).toBeTruthy();
87+
expect(newTree.exists('tsconfig.base.json')).toBeFalse();
8588
});
8689

87-
it(`should update extends from 'tsconfig.json' to 'tsconfig.json'`, async () => {
90+
it(`should update extends from 'tsconfig.base.json' to 'tsconfig.json'`, async () => {
8891
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
89-
expect(readJsonFile(newTree, 'src/tsconfig.json').extends).toEqual('./../tsconfig.json');
9092
expect(readJsonFile(newTree, 'src/tsconfig.spec.json').extends).toEqual('./../tsconfig.json');
9193
expect(readJsonFile(newTree, 'src/tsconfig.worker.json').extends).toEqual('./../tsconfig.json');
9294
});
9395

9496
it('should not update extends if not extended the root tsconfig', async () => {
9597
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
96-
expect(readJsonFile(newTree, 'src/tsconfig.tsc.json').extends).toEqual('./tsconfig.json');
97-
});
98-
99-
it('should add project referenced to root level tsconfig', async () => {
100-
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
101-
102-
expect(readJsonFile(newTree, 'tsconfig.json')).toEqual({
103-
files: [],
104-
references: [
105-
{
106-
path: './src/tsconfig.app.json',
107-
},
108-
{
109-
path: './src/tsconfig.worker.json',
110-
},
111-
{
112-
path: './src/tsconfig.spec.json',
113-
},
114-
],
115-
});
98+
expect(readJsonFile(newTree, 'src/tsconfig.tsc.json').extends).toEqual('./tsconfig.base.json');
11699
});
117100

118101
it('should not error out when a JSON file is a blank', async () => {
@@ -125,10 +108,10 @@ describe('Migration to create "Solution Style" tsconfig', () => {
125108
const logs: string[] = [];
126109
schematicRunner.logger.subscribe(m => logs.push(m.message));
127110

128-
tree.create('src/invalid/error.json', '{ invalid }');
111+
tree.create('src/invalid/error.json', `{ "extends": "./../../tsconfig.base.json", invalid }`);
129112
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
130113

131-
expect(readJsonFile(newTree, 'src/tsconfig.tsc.json').extends).toEqual('./tsconfig.json');
132-
expect(logs.join('\n')).toContain('Failed to parse "src/invalid/error.json" as JSON AST Object. Invalid JSON character');
114+
expect(readJsonFile(newTree, 'src/tsconfig.spec.json').extends).toEqual('./../tsconfig.json');
115+
expect(logs.join('\n')).toContain('Failed to parse "/src/invalid/error.json" as JSON AST Object. InvalidSymbol at location: 43.');
133116
});
134117
});

packages/schematics/angular/migrations/update-10/solution-style-tsconfig.ts

Lines changed: 0 additions & 141 deletions
This file was deleted.

0 commit comments

Comments
 (0)