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

106 lines
4.0 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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
*/
import {AbsoluteFsPath} from '../../src/ngtsc/path';
import {checkMarker, writeMarker} from './packages/build_marker';
import {DependencyHost} from './packages/dependency_host';
import {DependencyResolver} from './packages/dependency_resolver';
import {EntryPointFormat, EntryPointJsonProperty, getEntryPointFormat} from './packages/entry_point';
import {makeEntryPointBundle} from './packages/entry_point_bundle';
import {EntryPointFinder} from './packages/entry_point_finder';
import {Transformer} from './packages/transformer';
/**
* The options to configure the ngcc compiler.
*/
export interface NgccOptions {
/** The path to the node_modules folder that contains the packages to compile. */
baseSourcePath: AbsoluteFsPath;
/**
* The path, relative to `baseSourcePath` of the primary package to be compiled.
* All its dependencies will need to be compiled too.
*/
targetEntryPointPath?: AbsoluteFsPath;
/**
* Which entry-point properties in the package.json to consider when compiling.
* Each of properties contain a path to particular bundle format for a given entry-point.
*/
propertiesToConsider?: EntryPointJsonProperty[];
}
const SUPPORTED_FORMATS: EntryPointFormat[] = ['esm5', 'esm2015'];
/**
* This is the main entry-point into ngcc (aNGular Compatibility Compiler).
*
* You can call this function to process one or more npm packages, to ensure
* that they are compatible with the ivy compiler (ngtsc).
*
* @param options The options telling ngcc what to compile and how.
*/
export function mainNgcc({baseSourcePath, targetEntryPointPath, propertiesToConsider}: NgccOptions):
void {
const transformer = new Transformer(baseSourcePath, baseSourcePath);
const host = new DependencyHost();
const resolver = new DependencyResolver(host);
const finder = new EntryPointFinder(resolver);
const {entryPoints} = finder.findEntryPoints(baseSourcePath, targetEntryPointPath);
entryPoints.forEach(entryPoint => {
// Are we compiling the Angular core?
const isCore = entryPoint.name === '@angular/core';
const propertiesToCompile =
propertiesToConsider || Object.keys(entryPoint.packageJson) as EntryPointJsonProperty[];
const compiledFormats = new Set<string>();
for (let i = 0; i < propertiesToCompile.length; i++) {
const property = propertiesToCompile[i];
const formatPath = entryPoint.packageJson[property];
const format = getEntryPointFormat(property);
// No format then this property is not supposed to be compiled.
if (!formatPath || !format || SUPPORTED_FORMATS.indexOf(format) === -1) continue;
if (checkMarker(entryPoint, property)) {
compiledFormats.add(formatPath);
console.warn(`Skipping ${entryPoint.name} : ${property} (already compiled).`);
continue;
}
if (!compiledFormats.has(formatPath)) {
const bundle = makeEntryPointBundle(
entryPoint.path, formatPath, entryPoint.typings, isCore, format,
compiledFormats.size === 0);
if (bundle) {
console.warn(`Compiling ${entryPoint.name} : ${property} as ${format}`);
transformer.transform(entryPoint, isCore, bundle);
compiledFormats.add(formatPath);
} else {
console.warn(
`Skipping ${entryPoint.name} : ${format} (no valid entry point file for this format).`);
}
} else {
console.warn(`Skipping ${entryPoint.name} : ${property} (already compiled).`);
}
// Either this format was just compiled or its underlying format was compiled because of a
// previous property.
if (compiledFormats.has(formatPath)) {
writeMarker(entryPoint, property);
}
}
if (compiledFormats.size === 0) {
throw new Error(
`Failed to compile any formats for entry-point at (${entryPoint.path}). Tried ${propertiesToCompile}.`);
}
});
}