Skip to content

Commit

Permalink
fix(@schematics/angular): update or add module and target to non exte…
Browse files Browse the repository at this point in the history
…nded tsconfig

Fixes #14436
  • Loading branch information
Alan Agius authored and mgechev committed May 21, 2019
1 parent 1573e2d commit 10c7b21
Showing 2 changed files with 81 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {
JsonAstObject,
JsonParseMode,
isJsonObject,
join,
@@ -36,40 +35,10 @@ not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.`;

export function updateES5Projects(): Rule {
return (host: Tree) => {
const tsConfigPath = '/tsconfig.json';
const compilerOptions = getCompilerOptionsAstObject(host, tsConfigPath);
if (!compilerOptions) {
return host;
}

const recorder = host.beginUpdate(tsConfigPath);
const scriptTarget = findPropertyInAstObject(compilerOptions, 'target');
if (!scriptTarget) {
insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'target', 'es2015', 4);
} else if (scriptTarget.value !== 'es2015') {
const { start, end } = scriptTarget;
recorder.remove(start.offset, end.offset - start.offset);
recorder.insertLeft(start.offset, '"es2015"');
}

const scriptModule = findPropertyInAstObject(compilerOptions, 'module');
if (!scriptModule) {
insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'module', 'esnext', 4);
} else if (scriptModule.value !== 'esnext') {
const { start, end } = scriptModule;
recorder.remove(start.offset, end.offset - start.offset);
recorder.insertLeft(start.offset, '"esnext"');
}

host.commitUpdate(recorder);

return updateProjects;
};
}
return (tree: Tree) => {
// update workspace tsconfig
updateTsConfig(tree, '/tsconfig.json');

function updateProjects(): Rule {
return (tree) => {
const angularConfigContent = tree.read('angular.json') || tree.read('.angular.json');

if (!angularConfigContent) {
@@ -106,28 +75,16 @@ function updateProjects(): Rule {
continue;
}

const tsConfigs = [];
const buildOptionsConfig = architect.build.options;
if (isJsonObject(buildOptionsConfig) && typeof buildOptionsConfig.tsConfig === 'string') {
tsConfigs.push(buildOptionsConfig.tsConfig);
updateTsConfig(tree, buildOptionsConfig.tsConfig);
}

const testConfig = architect.test;
if (isJsonObject(testConfig)
&& isJsonObject(testConfig.options)
&& typeof testConfig.options.tsConfig === 'string') {
tsConfigs.push(testConfig.options.tsConfig);
}

for (const tsConfig of tsConfigs) {
const compilerOptions = getCompilerOptionsAstObject(tree, tsConfig);
if (!compilerOptions) {
continue;
}
const recorder = tree.beginUpdate(tsConfig);
removePropertyInAstObject(recorder, compilerOptions, 'target');
removePropertyInAstObject(recorder, compilerOptions, 'module');
tree.commitUpdate(recorder);
updateTsConfig(tree, testConfig.options.tsConfig);
}

const browserslistPath = join(normalize(project.root), 'browserslist');
@@ -159,8 +116,8 @@ function updateProjects(): Rule {
};
}

function getCompilerOptionsAstObject(host: Tree, tsConfigPath: string): JsonAstObject | undefined {
const buffer = host.read(tsConfigPath);
function updateTsConfig(tree: Tree, tsConfigPath: string): void {
const buffer = tree.read(tsConfigPath);
if (!buffer) {
return;
}
@@ -171,10 +128,37 @@ function getCompilerOptionsAstObject(host: Tree, tsConfigPath: string): JsonAstO
return;
}

const configExtends = findPropertyInAstObject(tsCfgAst, 'extends');
const isExtendedConfig = configExtends && configExtends.kind === 'string';

const compilerOptions = findPropertyInAstObject(tsCfgAst, 'compilerOptions');
if (!compilerOptions || compilerOptions.kind !== 'object') {
return;
}

return compilerOptions;
const recorder = tree.beginUpdate(tsConfigPath);

if (isExtendedConfig) {
removePropertyInAstObject(recorder, compilerOptions, 'target');
removePropertyInAstObject(recorder, compilerOptions, 'module');
} else {
const scriptTarget = findPropertyInAstObject(compilerOptions, 'target');
if (!scriptTarget) {
insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'target', 'es2015', 4);
} else if (scriptTarget.value !== 'es2015') {
const { start, end } = scriptTarget;
recorder.remove(start.offset, end.offset - start.offset);
recorder.insertLeft(start.offset, '"es2015"');
}
const scriptModule = findPropertyInAstObject(compilerOptions, 'module');
if (!scriptModule) {
insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'module', 'esnext', 4);
} else if (scriptModule.value !== 'esnext') {
const { start, end } = scriptModule;
recorder.remove(start.offset, end.offset - start.offset);
recorder.insertLeft(start.offset, '"esnext"');
}
}

tree.commitUpdate(recorder);
}
Original file line number Diff line number Diff line change
@@ -93,16 +93,21 @@ describe('Migration to version 8', () => {
expect(tree2.exists('/browserslist')).toBe(true);
});

it(`should remove 'target' and 'module' from non workspace tsconfig.json`, () => {
it(`should remove 'target' and 'module' from non workspace extended tsconfig.json`, () => {
const appTsConfig = '/tsconfig.app.json';
const specsTsConfig = '/tsconfig.spec.json';
const compilerOptions = {
...oldTsConfig.compilerOptions,
target: 'es2015',
module: 'es2015',
};
const tsConfig = JSON.stringify({
extends: '../../tsconfig.json',
compilerOptions: {
moduleResolution: 'node',
target: 'es2015',
module: 'es2015',
},
}, null, 2);

tree.overwrite(appTsConfig, tsConfig);
tree.overwrite(specsTsConfig, tsConfig);

tree.overwrite(appTsConfig, JSON.stringify({ compilerOptions }, null, 2));
const tree2 = schematicRunner.runSchematic('migration-07', {}, tree.branch());
const { compilerOptions: appCompilerOptions } = JSON.parse(tree2.readContent(appTsConfig));
expect(appCompilerOptions.target).toBeUndefined();
@@ -114,6 +119,40 @@ describe('Migration to version 8', () => {
expect(specsCompilerOptions.module).toBeUndefined();
});

it(`should update 'target' and 'module' to non workspace non-extended tsconfig.json`, () => {
const appTsConfig = '/tsconfig.app.json';
const tsConfig = JSON.stringify({
compilerOptions: {
moduleResolution: 'node',
target: 'es5',
module: 'es5',
},
}, null, 2);

tree.overwrite(appTsConfig, tsConfig);

const tree2 = schematicRunner.runSchematic('migration-07', {}, tree.branch());
const { compilerOptions: appCompilerOptions } = JSON.parse(tree2.readContent(appTsConfig));
expect(appCompilerOptions.target).toBe('es2015');
expect(appCompilerOptions.module).toBe('esnext');
});

it(`should add 'target' and 'module' to non workspace non-extended tsconfig.json`, () => {
const appTsConfig = '/tsconfig.app.json';
const tsConfig = JSON.stringify({
compilerOptions: {
moduleResolution: 'node',
},
}, null, 2);

tree.overwrite(appTsConfig, tsConfig);

const tree2 = schematicRunner.runSchematic('migration-07', {}, tree.branch());
const { compilerOptions: appCompilerOptions } = JSON.parse(tree2.readContent(appTsConfig));
expect(appCompilerOptions.target).toBe('es2015');
expect(appCompilerOptions.module).toBe('esnext');
});

it(`should not update projects which browser builder is not 'build-angular:browser'`, () => {
tree.delete('/browserslist');
const config = JSON.parse(tree.readContent('angular.json'));

0 comments on commit 10c7b21

Please sign in to comment.