Skip to content

Commit 4f91816

Browse files
alan-agius4filipesilva
authored andcommitted
feat(@schematics/angular): migrate libraries to be published from ViewEngine to Ivy Partial compilation
This migration updates libraries to be published in partial mode instead of view engine. Also, it removed deprecated options from ng-packagr configuration.
1 parent 961218a commit 4f91816

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
"version": "13.0.0",
140140
"factory": "./update-13/update-angular-config",
141141
"description": "Remove deprecated options from 'angular.json' that are no longer present in v13."
142+
},
143+
"update-libraries-v13": {
144+
"version": "13.0.0",
145+
"factory": "./update-13/update-libraries",
146+
"description": "Update library projects to be published in partial mode and removed deprecated options from ng-packagr configuration."
142147
}
143148
}
144149
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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.io/license
7+
*/
8+
9+
import { join } from '@angular-devkit/core';
10+
import { DirEntry, Rule } from '@angular-devkit/schematics';
11+
import { JSONFile } from '../../utility/json-file';
12+
import { allTargetOptions, getWorkspace } from '../../utility/workspace';
13+
14+
function* visit(directory: DirEntry): IterableIterator<string> {
15+
for (const path of directory.subfiles) {
16+
if (path === 'ng-package.json') {
17+
yield join(directory.path, path);
18+
}
19+
}
20+
21+
for (const path of directory.subdirs) {
22+
if (path === 'node_modules' || path.startsWith('.')) {
23+
continue;
24+
}
25+
26+
yield* visit(directory.dir(path));
27+
}
28+
}
29+
30+
export default function (): Rule {
31+
const ENABLE_IVY_JSON_PATH = ['angularCompilerOptions', 'enableIvy'];
32+
const COMPILATION_MODE_JSON_PATH = ['angularCompilerOptions', 'compilationMode'];
33+
const NG_PACKAGR_DEPRECATED_OPTIONS_PATHS = [
34+
['lib', 'umdModuleIds'],
35+
['lib', 'amdId'],
36+
['lib', 'umdId'],
37+
];
38+
39+
return async (tree) => {
40+
const workspace = await getWorkspace(tree);
41+
const librariesTsConfig = new Set<string>();
42+
const ngPackagrConfig = new Set<string>();
43+
44+
for (const [, project] of workspace.projects) {
45+
for (const [_, target] of project.targets) {
46+
if (target.builder !== '@angular-devkit/build-angular:ng-packagr') {
47+
continue;
48+
}
49+
50+
for (const [, options] of allTargetOptions(target)) {
51+
if (typeof options.tsConfig === 'string') {
52+
librariesTsConfig.add(options.tsConfig);
53+
}
54+
55+
if (typeof options.project === 'string') {
56+
ngPackagrConfig.add(options.project);
57+
}
58+
}
59+
}
60+
}
61+
62+
// Gather configurations which are not referecned in angular.json
63+
// (This happens when users have secondary entry-points)
64+
for (const p of visit(tree.root)) {
65+
ngPackagrConfig.add(p);
66+
}
67+
68+
// Update ng-packagr configuration
69+
for (const config of ngPackagrConfig) {
70+
const json = new JSONFile(tree, config);
71+
for (const optionPath of NG_PACKAGR_DEPRECATED_OPTIONS_PATHS) {
72+
json.remove(optionPath);
73+
}
74+
}
75+
76+
// Update tsconfig files
77+
for (const tsConfig of librariesTsConfig) {
78+
const json = new JSONFile(tree, tsConfig);
79+
if (json.get(ENABLE_IVY_JSON_PATH) === false) {
80+
json.remove(ENABLE_IVY_JSON_PATH);
81+
json.modify(COMPILATION_MODE_JSON_PATH, 'partial');
82+
}
83+
}
84+
};
85+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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.io/license
7+
*/
8+
9+
import { EmptyTree } from '@angular-devkit/schematics';
10+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
11+
import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
12+
13+
function readJsonFile(tree: UnitTestTree, path: string): Record<string, Record<string, unknown>> {
14+
return JSON.parse(tree.readContent(path));
15+
}
16+
17+
function createWorkSpaceConfig(tree: UnitTestTree) {
18+
const angularConfig: WorkspaceSchema = {
19+
version: 1,
20+
projects: {
21+
app: {
22+
root: '',
23+
sourceRoot: 'src',
24+
projectType: ProjectType.Library,
25+
prefix: 'app',
26+
architect: {
27+
build: {
28+
builder: Builders.NgPackagr,
29+
options: {
30+
project: 'ngpackage.json',
31+
tsConfig: 'tsconfig.lib.json',
32+
},
33+
configurations: {
34+
production: {
35+
tsConfig: 'tsconfig.lib.prod.json',
36+
},
37+
},
38+
},
39+
},
40+
},
41+
},
42+
};
43+
44+
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
45+
tree.create(
46+
'/tsconfig.lib.json',
47+
JSON.stringify(
48+
{ angularCompilerOptions: { enableIvy: true, fullTemplateTypeCheck: true } },
49+
undefined,
50+
2,
51+
),
52+
);
53+
tree.create(
54+
'/tsconfig.lib.prod.json',
55+
JSON.stringify(
56+
{ angularCompilerOptions: { enableIvy: false, fullTemplateTypeCheck: true } },
57+
undefined,
58+
2,
59+
),
60+
);
61+
62+
tree.create(
63+
'/ngpackage.json',
64+
JSON.stringify(
65+
{
66+
lib: { entryFile: 'src/public-api.ts', amdId: 'foo', umdId: 'foo', umdModuleIds: ['foo'] },
67+
},
68+
undefined,
69+
2,
70+
),
71+
);
72+
}
73+
74+
const schematicName = 'update-libraries-v13';
75+
76+
describe(`Migration to update library projects. ${schematicName}`, () => {
77+
const schematicRunner = new SchematicTestRunner(
78+
'migrations',
79+
require.resolve('../migration-collection.json'),
80+
);
81+
82+
let tree: UnitTestTree;
83+
beforeEach(() => {
84+
tree = new UnitTestTree(new EmptyTree());
85+
createWorkSpaceConfig(tree);
86+
});
87+
88+
describe('TypeScript Config', () => {
89+
it(`should replace "enableIvy: false" with "compilationMode: "partial" `, async () => {
90+
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
91+
const { angularCompilerOptions } = readJsonFile(newTree, 'tsconfig.lib.prod.json');
92+
expect(angularCompilerOptions.compilationMode).toBe('partial');
93+
expect(angularCompilerOptions.enableIvy).toBeUndefined();
94+
});
95+
96+
it(`should not replace "enableIvy: true"`, async () => {
97+
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
98+
const { angularCompilerOptions } = readJsonFile(newTree, 'tsconfig.lib.json');
99+
expect(angularCompilerOptions.enableIvy).toBeTrue();
100+
});
101+
});
102+
103+
describe('Ng-packagr Config', () => {
104+
it(`should remove UMD related options from ng-packagr configuration referenced from angular.json`, async () => {
105+
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
106+
const { lib } = readJsonFile(newTree, 'ngpackage.json');
107+
expect(lib.entryFile).toBeDefined();
108+
expect(lib.amdId).toBeUndefined();
109+
expect(lib.umdId).toBeUndefined();
110+
expect(lib.umdModuleIds).toBeUndefined();
111+
});
112+
113+
it(`should remove UMD related options from un-referenced ng-packagr configuration (secondary entry-points)`, async () => {
114+
tree.create(
115+
'/testing/ng-package.json',
116+
JSON.stringify(
117+
{
118+
lib: {
119+
entryFile: 'src/public-api.ts',
120+
amdId: 'foo',
121+
umdId: 'foo',
122+
umdModuleIds: ['foo'],
123+
},
124+
},
125+
undefined,
126+
2,
127+
),
128+
);
129+
130+
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
131+
const { lib } = readJsonFile(newTree, 'testing/ng-package.json');
132+
expect(lib.entryFile).toBeDefined();
133+
expect(lib.amdId).toBeUndefined();
134+
expect(lib.umdId).toBeUndefined();
135+
expect(lib.umdModuleIds).toBeUndefined();
136+
});
137+
});
138+
});

0 commit comments

Comments
 (0)