Skip to content

Commit 66239b9

Browse files
petebacondarwinmatsko
authored andcommitted
refactor(ivy): expose ngcc programmatically (angular#29092)
The `mainNgcc()` function has been refactored to make it easier to call ngcc from JavaScript, rather than via the command line. For example, the `yargs` argument parsing and the exception handling/logging have moved to the `main-ngcc.ts` file so that it is only used for the command line version. FW-1118 PR Close angular#29092
1 parent a770aa2 commit 66239b9

3 files changed

Lines changed: 84 additions & 68 deletions

File tree

packages/compiler-cli/ngcc/main-ngcc.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,44 @@
66
* Use of this source code is governed by an MIT-style license that can be
77
* found in the LICENSE file at https://angular.io/license
88
*/
9+
import * as path from 'canonical-path';
10+
import * as yargs from 'yargs';
911

1012
import {mainNgcc} from './src/main';
13+
import {EntryPointFormat} from './src/packages/entry_point';
1114

1215
// CLI entry point
1316
if (require.main === module) {
1417
const args = process.argv.slice(2);
15-
process.exitCode = mainNgcc(args);
18+
const options =
19+
yargs
20+
.option('s', {
21+
alias: 'source',
22+
describe: 'A path to the root folder to compile.',
23+
default: './node_modules'
24+
})
25+
.option('f', {
26+
alias: 'formats',
27+
array: true,
28+
describe: 'An array of formats to compile.',
29+
default: ['fesm2015', 'esm2015', 'fesm5', 'esm5']
30+
})
31+
.option('t', {
32+
alias: 'target',
33+
describe: 'A path to a root folder where the compiled files will be written.',
34+
defaultDescription: 'The `source` folder.'
35+
})
36+
.help()
37+
.parse(args);
38+
39+
const baseSourcePath: string = path.resolve(options['s']);
40+
const formats: EntryPointFormat[] = options['f'];
41+
const baseTargetPath: string = options['t'];
42+
try {
43+
mainNgcc({baseSourcePath, formats, baseTargetPath});
44+
process.exitCode = 0;
45+
} catch (e) {
46+
console.error(e.stack || e.message);
47+
process.exitCode = 1;
48+
}
1649
}

packages/compiler-cli/ngcc/src/main.ts

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import * as path from 'canonical-path';
9-
import * as yargs from 'yargs';
108

119
import {checkMarkerFile, writeMarkerFile} from './packages/build_marker';
1210
import {DependencyHost} from './packages/dependency_host';
@@ -16,72 +14,61 @@ import {makeEntryPointBundle} from './packages/entry_point_bundle';
1614
import {EntryPointFinder} from './packages/entry_point_finder';
1715
import {Transformer} from './packages/transformer';
1816

19-
export function mainNgcc(args: string[]): number {
20-
const options =
21-
yargs
22-
.option('s', {
23-
alias: 'source',
24-
describe: 'A path to the root folder to compile.',
25-
default: './node_modules'
26-
})
27-
.option('f', {
28-
alias: 'formats',
29-
array: true,
30-
describe: 'An array of formats to compile.',
31-
default: ['fesm2015', 'esm2015', 'fesm5', 'esm5']
32-
})
33-
.option('t', {
34-
alias: 'target',
35-
describe: 'A path to a root folder where the compiled files will be written.',
36-
defaultDescription: 'The `source` folder.'
37-
})
38-
.help()
39-
.parse(args);
40-
41-
const sourcePath: string = path.resolve(options['s']);
42-
const formats: EntryPointFormat[] = options['f'];
43-
const targetPath: string = options['t'] || sourcePath;
17+
/**
18+
* The options to configure the ngcc compiler.
19+
*/
20+
export interface NgccOptions {
21+
/** The path to the node_modules folder that contains the packages to compile. */
22+
baseSourcePath: string;
23+
/** A list of JavaScript bundle formats that should be compiled. */
24+
formats: EntryPointFormat[];
25+
/** The path to the node_modules folder where modified files should be written. */
26+
baseTargetPath?: string;
27+
}
4428

45-
const transformer = new Transformer(sourcePath, targetPath);
29+
/**
30+
* This is the main entry-point into ngcc (aNGular Compatibility Compiler).
31+
*
32+
* You can call this function to process one or more npm packages, to ensure
33+
* that they are compatible with the ivy compiler (ngtsc).
34+
*
35+
* @param options The options telling ngcc what to compile and how.
36+
*/
37+
export function mainNgcc({baseSourcePath, formats, baseTargetPath = baseSourcePath}: NgccOptions):
38+
void {
39+
const transformer = new Transformer(baseSourcePath, baseTargetPath);
4640
const host = new DependencyHost();
4741
const resolver = new DependencyResolver(host);
4842
const finder = new EntryPointFinder(resolver);
4943

50-
try {
51-
const {entryPoints} = finder.findEntryPoints(sourcePath);
52-
entryPoints.forEach(entryPoint => {
44+
const {entryPoints} = finder.findEntryPoints(baseSourcePath);
45+
entryPoints.forEach(entryPoint => {
5346

54-
// Are we compiling the Angular core?
55-
const isCore = entryPoint.name === '@angular/core';
47+
// Are we compiling the Angular core?
48+
const isCore = entryPoint.name === '@angular/core';
5649

57-
// We transform the d.ts typings files while transforming one of the formats.
58-
// This variable decides with which of the available formats to do this transform.
59-
// It is marginally faster to process via the flat file if available.
60-
const dtsTransformFormat: EntryPointFormat = entryPoint.fesm2015 ? 'fesm2015' : 'esm2015';
50+
// We transform the d.ts typings files while transforming one of the formats.
51+
// This variable decides with which of the available formats to do this transform.
52+
// It is marginally faster to process via the flat file if available.
53+
const dtsTransformFormat: EntryPointFormat = entryPoint.fesm2015 ? 'fesm2015' : 'esm2015';
6154

62-
formats.forEach(format => {
63-
if (checkMarkerFile(entryPoint, format)) {
64-
console.warn(`Skipping ${entryPoint.name} : ${format} (already built).`);
65-
return;
66-
}
55+
formats.forEach(format => {
56+
if (checkMarkerFile(entryPoint, format)) {
57+
console.warn(`Skipping ${entryPoint.name} : ${format} (already built).`);
58+
return;
59+
}
6760

68-
const bundle =
69-
makeEntryPointBundle(entryPoint, isCore, format, format === dtsTransformFormat);
70-
if (bundle === null) {
71-
console.warn(
72-
`Skipping ${entryPoint.name} : ${format} (no entry point file for this format).`);
73-
} else {
74-
transformer.transform(entryPoint, isCore, bundle);
75-
}
61+
const bundle =
62+
makeEntryPointBundle(entryPoint, isCore, format, format === dtsTransformFormat);
63+
if (bundle === null) {
64+
console.warn(
65+
`Skipping ${entryPoint.name} : ${format} (no entry point file for this format).`);
66+
} else {
67+
transformer.transform(entryPoint, isCore, bundle);
68+
}
7669

77-
// Write the built-with-ngcc marker
78-
writeMarkerFile(entryPoint, format);
79-
});
70+
// Write the built-with-ngcc marker
71+
writeMarkerFile(entryPoint, format);
8072
});
81-
} catch (e) {
82-
console.error(e.stack || e.message);
83-
return 1;
84-
}
85-
86-
return 0;
73+
});
8774
}

packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,19 @@ describe('ngcc main()', () => {
1919
afterEach(restoreRealFileSystem);
2020

2121
it('should run ngcc without errors for fesm2015', () => {
22-
const format = 'fesm2015';
23-
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
22+
expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['fesm2015']})).not.toThrow();
2423
});
2524

2625
it('should run ngcc without errors for fesm5', () => {
27-
const format = 'fesm5';
28-
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
26+
expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['fesm5']})).not.toThrow();
2927
});
3028

3129
it('should run ngcc without errors for esm2015', () => {
32-
const format = 'esm2015';
33-
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
30+
expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['esm2015']})).not.toThrow();
3431
});
3532

3633
it('should run ngcc without errors for esm5', () => {
37-
const format = 'esm5';
38-
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
34+
expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['esm5']})).not.toThrow();
3935
});
4036
});
4137

0 commit comments

Comments
 (0)