Skip to content

Commit 682aaf9

Browse files
aparzipkozlowski-opensource
authored andcommitted
feat(migrations): add strictTemplates to tsconfig during ng update
Add the strictTemplates option to tsconfig.json with a default value of false
1 parent 43ef717 commit 682aaf9

5 files changed

Lines changed: 214 additions & 0 deletions

File tree

packages/core/schematics/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ bundle_entrypoints = [
125125
"http-xhr-backend",
126126
"packages/core/schematics/migrations/http-xhr-backend/index.js",
127127
],
128+
[
129+
"strict-templates",
130+
"packages/core/schematics/migrations/strict-template/index.js",
131+
],
128132
]
129133

130134
rollup.rollup(
@@ -138,6 +142,7 @@ rollup.rollup(
138142
"//packages/core/schematics:tsconfig_build",
139143
"//packages/core/schematics/migrations/change-detection-eager",
140144
"//packages/core/schematics/migrations/http-xhr-backend",
145+
"//packages/core/schematics/migrations/strict-template",
141146
"//packages/core/schematics/ng-generate/cleanup-unused-imports",
142147
"//packages/core/schematics/ng-generate/common-to-standalone-migration",
143148
"//packages/core/schematics/ng-generate/control-flow-migration",

packages/core/schematics/migrations.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
"version": "22.0.0",
1010
"description": "Adds 'withXhr' to 'provideHttpClient' function calls when the 'HttpXhrBackend' is used. For more information see: https://angular.dev/api/common/http/withXhr",
1111
"factory": "./bundles/http-xhr-backend.cjs#migrate"
12+
},
13+
"strict-template": {
14+
"version": "22.0.0",
15+
"description": "Adds 'strictTemplates: true' in tsconfig.json.",
16+
"factory": "./bundles/strict-templates.cjs#migrate"
1217
}
1318
}
1419
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
load("//tools:defaults.bzl", "jasmine_test", "ts_project")
2+
3+
package(
4+
default_visibility = [
5+
"//packages/core/schematics:__pkg__",
6+
"//packages/core/schematics/test:__pkg__",
7+
],
8+
)
9+
10+
ts_project(
11+
name = "strict-template",
12+
srcs = glob(
13+
["**/*.ts"],
14+
exclude = ["*.spec.ts"],
15+
),
16+
deps = [
17+
"//:node_modules/@angular-devkit/schematics",
18+
"//packages/core/schematics/utils",
19+
],
20+
)
21+
22+
ts_project(
23+
name = "test_lib",
24+
testonly = True,
25+
srcs = glob(["*.spec.ts"]),
26+
deps = [
27+
":strict-template",
28+
"//:node_modules/@angular-devkit/core",
29+
"//:node_modules/@angular-devkit/schematics",
30+
"//packages/core/schematics/utils",
31+
],
32+
)
33+
34+
jasmine_test(
35+
name = "test",
36+
data = [":test_lib"],
37+
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC 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.dev/license
7+
*/
8+
9+
import {Rule} from '@angular-devkit/schematics';
10+
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
11+
12+
/**
13+
* Migration that adds `strictTemplates: false` to `tsconfig.json` files.
14+
*/
15+
export function migrate(): Rule {
16+
return async (tree) => {
17+
const {buildPaths, testPaths} = await getProjectTsConfigPaths(tree);
18+
const allPaths = [...new Set([...buildPaths, ...testPaths])];
19+
20+
for (const path of allPaths) {
21+
const content = tree.read(path);
22+
if (!content) continue;
23+
24+
const contentStr = content.toString('utf-8');
25+
26+
// Check if it's already there to avoid parsing if not needed.
27+
if (contentStr.includes('strictTemplates')) {
28+
continue;
29+
}
30+
31+
try {
32+
// Use a simple JSON.parse for now. In a real world scenario we might want to use
33+
// a parser that supports comments (JSONC), but for this migration it's likely
34+
// that tsconfig files are standard enough or that overwriting them is acceptable
35+
// in the context of an ng update.
36+
const json = JSON.parse(contentStr);
37+
38+
if (!json.compilerOptions || Object.keys(json.compilerOptions).length === 0) {
39+
continue;
40+
}
41+
42+
if (!json.angularCompilerOptions) {
43+
json.angularCompilerOptions = {strictTemplates: false};
44+
tree.overwrite(path, JSON.stringify(json, null, 2));
45+
continue;
46+
}
47+
48+
if (json.angularCompilerOptions.strictTemplates === undefined) {
49+
json.angularCompilerOptions.strictTemplates = false;
50+
tree.overwrite(path, JSON.stringify(json, null, 2));
51+
}
52+
} catch (e) {
53+
// If parsing fails, skip the file to avoid corrupting it.
54+
continue;
55+
}
56+
}
57+
};
58+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC 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.dev/license
7+
*/
8+
9+
import {HostTree} from '@angular-devkit/schematics';
10+
import {UnitTestTree} from '@angular-devkit/schematics/testing/index.js';
11+
import {migrate} from './index';
12+
13+
describe('strict-template migration', () => {
14+
let tree: UnitTestTree;
15+
16+
beforeEach(() => {
17+
tree = new UnitTestTree(new HostTree());
18+
tree.create(
19+
'/angular.json',
20+
JSON.stringify({
21+
version: 1,
22+
projects: {
23+
t: {
24+
root: '',
25+
architect: {
26+
build: {
27+
options: {
28+
tsConfig: './tsconfig.json',
29+
},
30+
},
31+
},
32+
},
33+
},
34+
}),
35+
);
36+
});
37+
38+
it('should not add options if compilerOptions is empty', async () => {
39+
tree.create(
40+
'/tsconfig.json',
41+
JSON.stringify({
42+
compilerOptions: {},
43+
}),
44+
);
45+
46+
await migrate()(tree, {} as any);
47+
48+
const tsconfig = JSON.parse(tree.readContent('/tsconfig.json'));
49+
expect(tsconfig.angularCompilerOptions).toBeUndefined();
50+
});
51+
52+
it('should not add options if compilerOptions is missing', async () => {
53+
tree.create('/tsconfig.json', JSON.stringify({}));
54+
55+
await migrate()(tree, {} as any);
56+
57+
const tsconfig = JSON.parse(tree.readContent('/tsconfig.json'));
58+
expect(tsconfig.angularCompilerOptions).toBeUndefined();
59+
});
60+
61+
it('should add strictTemplates to false if compilerOptions is not empty', async () => {
62+
tree.create(
63+
'/tsconfig.json',
64+
JSON.stringify({
65+
compilerOptions: {
66+
target: 'es2020',
67+
},
68+
}),
69+
);
70+
71+
await migrate()(tree, {} as any);
72+
73+
const tsconfig = JSON.parse(tree.readContent('/tsconfig.json'));
74+
expect(tsconfig.angularCompilerOptions.strictTemplates).toBe(false);
75+
});
76+
77+
it('should add strictTemplates to false if angularCompilerOptions is empty but compilerOptions is not', async () => {
78+
tree.create(
79+
'/tsconfig.json',
80+
JSON.stringify({
81+
compilerOptions: {
82+
target: 'es2020',
83+
},
84+
angularCompilerOptions: {},
85+
}),
86+
);
87+
88+
await migrate()(tree, {} as any);
89+
90+
const tsconfig = JSON.parse(tree.readContent('/tsconfig.json'));
91+
expect(tsconfig.angularCompilerOptions.strictTemplates).toBe(false);
92+
});
93+
94+
it('should not change strictTemplates if already present', async () => {
95+
tree.create(
96+
'/tsconfig.json',
97+
JSON.stringify({
98+
angularCompilerOptions: {
99+
strictTemplates: true,
100+
},
101+
}),
102+
);
103+
104+
await migrate()(tree, {} as any);
105+
106+
const tsconfig = JSON.parse(tree.readContent('/tsconfig.json'));
107+
expect(tsconfig.angularCompilerOptions.strictTemplates).toBe(true);
108+
});
109+
});

0 commit comments

Comments
 (0)