Skip to content

Commit

Permalink
feat(@schematics/angular): add migration to remove solution style tsc…
Browse files Browse the repository at this point in the history
…onfig

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
  • Loading branch information
alan-agius4 authored and filipesilva committed Aug 12, 2020
1 parent 8b96e52 commit 8fb5259
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 177 deletions.
10 changes: 5 additions & 5 deletions packages/schematics/angular/migrations/migration-collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,6 @@
"factory": "./update-10/update-libraries-tslib",
"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"
},
"solution-style-tsconfig": {
"version": "10.0.0-beta.7",
"factory": "./update-10/solution-style-tsconfig",
"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"
},
"update-workspace-dependencies": {
"version": "10.0.0-rc.2",
"factory": "./update-10/update-dependencies",
Expand All @@ -104,6 +99,11 @@
"version": "10.0.1",
"factory": "./update-10/update-module-and-target-compiler-options",
"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"
},
"remove-solution-style-tsconfig": {
"version": "10.1.0-next.5",
"factory": "./update-10/remove-solution-style-tsconfig",
"description": "Removing \"Solution Style\" TypeScript configuration file support."
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Path, dirname, join, normalize, resolve } from '@angular-devkit/core';
import { DirEntry, Rule } from '@angular-devkit/schematics';
import { JSONFile } from '../../utility/json-file';

function* visitExtendedJsonFiles(directory: DirEntry): IterableIterator<Path> {
for (const path of directory.subfiles) {
if (!path.endsWith('.json')) {
continue;
}

const entry = directory.file(path);
const content = entry?.content.toString();
if (content?.includes('tsconfig.base.json')) {
yield join(directory.path, path);
}
}

for (const path of directory.subdirs) {
if (path === 'node_modules' || path.startsWith('.')) {
continue;
}

yield* visitExtendedJsonFiles(directory.dir(path));
}
}

export default function (): Rule {
return (host, context) => {
const logger = context.logger;

const tsConfig = new JSONFile(host, 'tsconfig.json');
const files = tsConfig.get(['files']);
if (!(Array.isArray(files) && files.length === 0)) {
logger.info('Migration has already been executed.');

return;
}

if (host.exists('tsconfig.base.json')) {
host.overwrite('tsconfig.json', host.read('tsconfig.base.json') || '');
host.delete('tsconfig.base.json');
}

// Iterate over all tsconfig files and change the extends from 'tsconfig.base.json' to 'tsconfig.json'.
const extendsJsonPath = ['extends'];
for (const path of visitExtendedJsonFiles(host.root)) {
const tsConfigDir = dirname(normalize(path));
let tsConfigJson;

try {
tsConfigJson = new JSONFile(host, path);
const extendsValue = tsConfigJson.get(extendsJsonPath);

if (typeof extendsValue === 'string' && '/tsconfig.base.json' === resolve(tsConfigDir, normalize(extendsValue))) {
// tsconfig extends the workspace tsconfig path.
tsConfig.modify(extendsJsonPath, extendsValue.replace('tsconfig.base.json', 'tsconfig.json'));
}
} catch (error) {
logger.warn(
`${error.message || error}\n` +
'If this is a TypeScript configuration file you will need to update the "extends" value manually.',
);

continue;
}
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { EmptyTree } from '@angular-devkit/schematics';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';

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

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

// Create tsconfigs
const compilerOptions = { target: 'es2015' };
createJsonFile(tree, 'tsconfig.json', { compilerOptions });
createJsonFile(tree, 'tsconfig.json', { files: [] });
createJsonFile(tree, 'tsconfig.base.json', { compilerOptions });
createJsonFile(tree, 'tsconfig.common.json', { compilerOptions });
createJsonFile(tree, 'src/tsconfig.json', { extends: './../tsconfig.json', compilerOptions });
createJsonFile(tree, 'src/tsconfig.tsc.json', { extends: './tsconfig.json', compilerOptions });
createJsonFile(tree, 'src/tsconfig.base.json', { extends: './../tsconfig.json', compilerOptions });
createJsonFile(tree, 'src/tsconfig.tsc.json', { extends: './tsconfig.base.json', compilerOptions });
createJsonFile(tree, 'src/tsconfig.app.json', { extends: './../tsconfig.common.json', compilerOptions });
createJsonFile(tree, 'src/tsconfig.spec.json', { extends: './../tsconfig.json', compilerOptions });
createJsonFile(tree, 'src/tsconfig.worker.json', { extends: './../tsconfig.json', compilerOptions });
});

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

it(`should update extends from 'tsconfig.json' to 'tsconfig.json'`, async () => {
it(`should update extends from 'tsconfig.base.json' to 'tsconfig.json'`, async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
expect(readJsonFile(newTree, 'src/tsconfig.json').extends).toEqual('./../tsconfig.json');
expect(readJsonFile(newTree, 'src/tsconfig.spec.json').extends).toEqual('./../tsconfig.json');
expect(readJsonFile(newTree, 'src/tsconfig.worker.json').extends).toEqual('./../tsconfig.json');
});

it('should not update extends if not extended the root tsconfig', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
expect(readJsonFile(newTree, 'src/tsconfig.tsc.json').extends).toEqual('./tsconfig.json');
});

it('should add project referenced to root level tsconfig', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();

expect(readJsonFile(newTree, 'tsconfig.json')).toEqual({
files: [],
references: [
{
path: './src/tsconfig.app.json',
},
{
path: './src/tsconfig.worker.json',
},
{
path: './src/tsconfig.spec.json',
},
],
});
expect(readJsonFile(newTree, 'src/tsconfig.tsc.json').extends).toEqual('./tsconfig.base.json');
});

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

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

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

This file was deleted.

0 comments on commit 8fb5259

Please sign in to comment.