Skip to content

Commit 38ea7dc

Browse files
clydinfilipesilva
authored andcommitted
refactor(@schematics/angular): use new JSON helpers in update-app-tsconfigs migration
1 parent 752c57f commit 38ea7dc

File tree

1 file changed

+45
-80
lines changed

1 file changed

+45
-80
lines changed

packages/schematics/angular/migrations/update-9/update-app-tsconfigs.ts

Lines changed: 45 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,16 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import { JsonAstObject, join, logging, normalize } from '@angular-devkit/core';
9-
import { Rule, Tree, UpdateRecorder } from '@angular-devkit/schematics';
9+
import { Rule, Tree } from '@angular-devkit/schematics';
1010
import { dirname, relative } from 'path';
11-
import {
12-
findPropertyInAstObject,
13-
insertPropertyInAstObjectInOrder,
14-
removePropertyInAstObject,
15-
} from '../../utility/json-utils';
11+
import { JSONFile } from '../../utility/json-file';
12+
import { findPropertyInAstObject } from '../../utility/json-utils';
1613
import { Builders } from '../../utility/workspace-models';
1714
import {
1815
forwardSlashPath,
1916
getAllOptions,
2017
getTargets,
2118
getWorkspace,
22-
readJsonFileAsAstObject,
2319
} from './utils';
2420

2521
/**
@@ -29,9 +25,8 @@ import {
2925
* - Sets module compiler option to esnext or commonjs
3026
*/
3127
export function updateApplicationTsConfigs(): Rule {
32-
return (tree, context) => {
28+
return (tree, { logger }) => {
3329
const workspace = getWorkspace(tree);
34-
const logger = context.logger;
3530

3631
// Add `module` option in the workspace tsconfig
3732
updateModuleCompilerOption(tree, '/tsconfig.json');
@@ -47,8 +42,6 @@ export function updateApplicationTsConfigs(): Rule {
4742
for (const { target, project } of getTargets(workspace, 'test', Builders.Karma)) {
4843
updateTsConfig(tree, target, project, Builders.Karma, logger);
4944
}
50-
51-
return tree;
5245
};
5346
}
5447

@@ -61,58 +54,48 @@ function updateTsConfig(
6154
) {
6255
const options = getAllOptions(builderConfig);
6356
for (const option of options) {
64-
let recorder: UpdateRecorder;
6557
const tsConfigOption = findPropertyInAstObject(option, 'tsConfig');
6658

6759
if (!tsConfigOption || tsConfigOption.kind !== 'string') {
6860
continue;
6961
}
7062

7163
const tsConfigPath = tsConfigOption.value;
72-
let tsConfigAst = readJsonFileAsAstObject(tree, tsConfigPath);
73-
if (!tsConfigAst) {
64+
65+
// Update 'module' compilerOption
66+
updateModuleCompilerOption(tree, tsConfigPath, builderName);
67+
68+
let tsConfigJson;
69+
try {
70+
tsConfigJson = new JSONFile(tree, tsConfigPath);
71+
} catch {
7472
logger.warn(`Cannot find file: ${tsConfigPath}`);
7573
continue;
7674
}
7775

7876
// Remove 'enableIvy: true' since this is the default in version 9.
79-
const angularCompilerOptions = findPropertyInAstObject(tsConfigAst, 'angularCompilerOptions');
80-
if (angularCompilerOptions && angularCompilerOptions.kind === 'object') {
81-
const enableIvy = findPropertyInAstObject(angularCompilerOptions, 'enableIvy');
82-
if (enableIvy && enableIvy.kind === 'true') {
83-
recorder = tree.beginUpdate(tsConfigPath);
84-
if (angularCompilerOptions.properties.length === 1) {
85-
// remove entire 'angularCompilerOptions'
86-
removePropertyInAstObject(recorder, tsConfigAst, 'angularCompilerOptions');
87-
} else {
88-
removePropertyInAstObject(recorder, angularCompilerOptions, 'enableIvy');
89-
}
90-
tree.commitUpdate(recorder);
77+
if (tsConfigJson.get(['angularCompilerOptions', 'enableIvy']) === true) {
78+
const angularCompilerOptions = tsConfigJson.get(['angularCompilerOptions']);
79+
const keys = Object.keys(angularCompilerOptions as object);
80+
81+
if (keys.length === 1) {
82+
// remove entire 'angularCompilerOptions'
83+
tsConfigJson.remove(['angularCompilerOptions']);
84+
} else {
85+
// leave other options
86+
tsConfigJson.remove(['angularCompilerOptions', 'enableIvy']);
9187
}
9288
}
9389

94-
// Update 'module' compilerOption
95-
updateModuleCompilerOption(tree, tsConfigPath, builderName);
96-
9790
// Add stricter file inclusions to avoid unused file warning during compilation
9891
if (builderName !== Builders.Karma) {
99-
// Note: we need to re-read the tsconfig after very commit because
100-
// otherwise the updates will be out of sync since we are ammending the same node.
101-
102-
// we are already checking that tsconfig exists above!
103-
// tslint:disable-next-line: no-non-null-assertion
104-
tsConfigAst = readJsonFileAsAstObject(tree, tsConfigPath)!;
105-
const include = findPropertyInAstObject(tsConfigAst, 'include');
106-
107-
if (include && include.kind === 'array') {
108-
const tsInclude = include.elements.find(({ value }) => typeof value === 'string' && value.endsWith('**/*.ts'));
109-
if (tsInclude) {
110-
const { start, end } = tsInclude;
111-
recorder = tree.beginUpdate(tsConfigPath);
112-
recorder.remove(start.offset, end.offset - start.offset);
92+
93+
const include = tsConfigJson.get(['include']);
94+
if (include && Array.isArray(include)) {
95+
const tsInclude = include.findIndex((value) => typeof value === 'string' && value.endsWith('**/*.ts'));
96+
if (tsInclude !== -1) {
11397
// Replace ts includes with d.ts
114-
recorder.insertLeft(start.offset, tsInclude.text.replace('.ts', '.d.ts'));
115-
tree.commitUpdate(recorder);
98+
tsConfigJson.modify(['include', tsInclude], include[tsInclude].replace('.ts', '.d.ts'));
11699
}
117100
} else {
118101
// Includes are not present, add includes to dts files
@@ -123,13 +106,11 @@ function updateTsConfig(
123106
? join(normalize(srcRootAst.value), '**/*.d.ts')
124107
: '**/*.d.ts';
125108

126-
recorder = tree.beginUpdate(tsConfigPath);
127-
insertPropertyInAstObjectInOrder(recorder, tsConfigAst, 'include', [include], 2);
128-
tree.commitUpdate(recorder);
109+
tsConfigJson.modify(['include'], [include]);
129110
}
130111

131-
const files = findPropertyInAstObject(tsConfigAst, 'files');
132-
if (!files) {
112+
const files = tsConfigJson.get(['files']);
113+
if (files === undefined) {
133114
const newFiles: string[] = [];
134115
const tsConfigDir = dirname(forwardSlashPath(tsConfigPath));
135116

@@ -146,53 +127,37 @@ function updateTsConfig(
146127
}
147128

148129
if (newFiles.length) {
149-
recorder = tree.beginUpdate(tsConfigPath);
150-
// tslint:disable-next-line: no-non-null-assertion
151-
tsConfigAst = readJsonFileAsAstObject(tree, tsConfigPath)!;
152-
insertPropertyInAstObjectInOrder(recorder, tsConfigAst, 'files', newFiles, 2);
153-
tree.commitUpdate(recorder);
130+
tsConfigJson.modify(['files'], newFiles);
154131
}
155132

156-
recorder = tree.beginUpdate(tsConfigPath);
157-
// tslint:disable-next-line: no-non-null-assertion
158-
tsConfigAst = readJsonFileAsAstObject(tree, tsConfigPath)!;
159-
removePropertyInAstObject(recorder, tsConfigAst, 'exclude');
160-
tree.commitUpdate(recorder);
133+
tsConfigJson.remove(['exclude']);
161134
}
162135
}
163136
}
164137
}
165138

166139
function updateModuleCompilerOption(tree: Tree, tsConfigPath: string, builderName?: Builders) {
167-
const tsConfigAst = readJsonFileAsAstObject(tree, tsConfigPath);
168-
169-
if (!tsConfigAst) {
140+
let tsConfigJson;
141+
try {
142+
tsConfigJson = new JSONFile(tree, tsConfigPath);
143+
} catch {
170144
return;
171145
}
172146

173-
const compilerOptions = findPropertyInAstObject(tsConfigAst, 'compilerOptions');
174-
if (!compilerOptions || compilerOptions.kind !== 'object') {
147+
const compilerOptions = tsConfigJson.get(['compilerOptions']);
148+
if (!compilerOptions || typeof compilerOptions !== 'object') {
175149
return;
176150
}
177151

178-
const configExtends = findPropertyInAstObject(tsConfigAst, 'extends');
179-
const isExtendedConfig = configExtends && configExtends.kind === 'string';
180-
const recorder = tree.beginUpdate(tsConfigPath);
152+
const configExtends = tsConfigJson.get(['extends']);
153+
const isExtended = configExtends && typeof configExtends === 'string';
181154

182155
// Server tsconfig should have a module of commonjs
183156
const moduleType = builderName === Builders.Server ? 'commonjs' : 'esnext';
184-
if (isExtendedConfig && builderName !== Builders.Server) {
185-
removePropertyInAstObject(recorder, compilerOptions, 'module');
157+
158+
if (isExtended && builderName !== Builders.Server) {
159+
tsConfigJson.remove(['compilerOptions', 'module']);
186160
} else {
187-
const scriptModule = findPropertyInAstObject(compilerOptions, 'module');
188-
if (!scriptModule) {
189-
insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'module', moduleType, 4);
190-
} else if (scriptModule.value !== moduleType) {
191-
const { start, end } = scriptModule;
192-
recorder.remove(start.offset, end.offset - start.offset);
193-
recorder.insertLeft(start.offset, `"${moduleType}"`);
194-
}
161+
tsConfigJson.modify(['compilerOptions', 'module'], moduleType);
195162
}
196-
197-
tree.commitUpdate(recorder);
198163
}

0 commit comments

Comments
 (0)