refactor(ivy): expose ngcc programmatically (#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 #29092
This commit is contained in:
Pete Bacon Darwin 2019-03-20 13:47:58 +00:00 committed by Matias Niemelä
parent a770aa231d
commit 66239b9d09
3 changed files with 84 additions and 68 deletions

View File

@ -6,11 +6,44 @@
* Use of this source code is governed by an MIT-style license that can be * Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import * as path from 'canonical-path';
import * as yargs from 'yargs';
import {mainNgcc} from './src/main'; import {mainNgcc} from './src/main';
import {EntryPointFormat} from './src/packages/entry_point';
// CLI entry point // CLI entry point
if (require.main === module) { if (require.main === module) {
const args = process.argv.slice(2); const args = process.argv.slice(2);
process.exitCode = mainNgcc(args); const options =
yargs
.option('s', {
alias: 'source',
describe: 'A path to the root folder to compile.',
default: './node_modules'
})
.option('f', {
alias: 'formats',
array: true,
describe: 'An array of formats to compile.',
default: ['fesm2015', 'esm2015', 'fesm5', 'esm5']
})
.option('t', {
alias: 'target',
describe: 'A path to a root folder where the compiled files will be written.',
defaultDescription: 'The `source` folder.'
})
.help()
.parse(args);
const baseSourcePath: string = path.resolve(options['s']);
const formats: EntryPointFormat[] = options['f'];
const baseTargetPath: string = options['t'];
try {
mainNgcc({baseSourcePath, formats, baseTargetPath});
process.exitCode = 0;
} catch (e) {
console.error(e.stack || e.message);
process.exitCode = 1;
}
} }

View File

@ -5,8 +5,6 @@
* Use of this source code is governed by an MIT-style license that can be * Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import * as path from 'canonical-path';
import * as yargs from 'yargs';
import {checkMarkerFile, writeMarkerFile} from './packages/build_marker'; import {checkMarkerFile, writeMarkerFile} from './packages/build_marker';
import {DependencyHost} from './packages/dependency_host'; import {DependencyHost} from './packages/dependency_host';
@ -16,39 +14,34 @@ import {makeEntryPointBundle} from './packages/entry_point_bundle';
import {EntryPointFinder} from './packages/entry_point_finder'; import {EntryPointFinder} from './packages/entry_point_finder';
import {Transformer} from './packages/transformer'; import {Transformer} from './packages/transformer';
export function mainNgcc(args: string[]): number { /**
const options = * The options to configure the ngcc compiler.
yargs */
.option('s', { export interface NgccOptions {
alias: 'source', /** The path to the node_modules folder that contains the packages to compile. */
describe: 'A path to the root folder to compile.', baseSourcePath: string;
default: './node_modules' /** A list of JavaScript bundle formats that should be compiled. */
}) formats: EntryPointFormat[];
.option('f', { /** The path to the node_modules folder where modified files should be written. */
alias: 'formats', baseTargetPath?: string;
array: true, }
describe: 'An array of formats to compile.',
default: ['fesm2015', 'esm2015', 'fesm5', 'esm5']
})
.option('t', {
alias: 'target',
describe: 'A path to a root folder where the compiled files will be written.',
defaultDescription: 'The `source` folder.'
})
.help()
.parse(args);
const sourcePath: string = path.resolve(options['s']); /**
const formats: EntryPointFormat[] = options['f']; * This is the main entry-point into ngcc (aNGular Compatibility Compiler).
const targetPath: string = options['t'] || sourcePath; *
* You can call this function to process one or more npm packages, to ensure
const transformer = new Transformer(sourcePath, targetPath); * that they are compatible with the ivy compiler (ngtsc).
*
* @param options The options telling ngcc what to compile and how.
*/
export function mainNgcc({baseSourcePath, formats, baseTargetPath = baseSourcePath}: NgccOptions):
void {
const transformer = new Transformer(baseSourcePath, baseTargetPath);
const host = new DependencyHost(); const host = new DependencyHost();
const resolver = new DependencyResolver(host); const resolver = new DependencyResolver(host);
const finder = new EntryPointFinder(resolver); const finder = new EntryPointFinder(resolver);
try { const {entryPoints} = finder.findEntryPoints(baseSourcePath);
const {entryPoints} = finder.findEntryPoints(sourcePath);
entryPoints.forEach(entryPoint => { entryPoints.forEach(entryPoint => {
// Are we compiling the Angular core? // Are we compiling the Angular core?
@ -78,10 +71,4 @@ export function mainNgcc(args: string[]): number {
writeMarkerFile(entryPoint, format); writeMarkerFile(entryPoint, format);
}); });
}); });
} catch (e) {
console.error(e.stack || e.message);
return 1;
}
return 0;
} }

View File

@ -19,23 +19,19 @@ describe('ngcc main()', () => {
afterEach(restoreRealFileSystem); afterEach(restoreRealFileSystem);
it('should run ngcc without errors for fesm2015', () => { it('should run ngcc without errors for fesm2015', () => {
const format = 'fesm2015'; expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['fesm2015']})).not.toThrow();
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
}); });
it('should run ngcc without errors for fesm5', () => { it('should run ngcc without errors for fesm5', () => {
const format = 'fesm5'; expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['fesm5']})).not.toThrow();
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
}); });
it('should run ngcc without errors for esm2015', () => { it('should run ngcc without errors for esm2015', () => {
const format = 'esm2015'; expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['esm2015']})).not.toThrow();
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
}); });
it('should run ngcc without errors for esm5', () => { it('should run ngcc without errors for esm5', () => {
const format = 'esm5'; expect(() => mainNgcc({baseSourcePath: '/node_modules', formats: ['esm5']})).not.toThrow();
expect(mainNgcc(['-f', format, '-s', '/node_modules'])).toBe(0);
}); });
}); });