ng-packagr
Version:
Compile and package Angular libraries in Angular Package Format (APF)
180 lines • 9.38 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.packageTransformFactory = void 0;
const dependency_graph_1 = require("dependency-graph");
const rxjs_1 = require("rxjs");
const file_watcher_1 = require("../file-system/file-watcher");
const node_1 = require("../graph/node");
const color_1 = require("../utils/color");
const fs_1 = require("../utils/fs");
const log = __importStar(require("../utils/log"));
const discover_packages_1 = require("./discover-packages");
const nodes_1 = require("./nodes");
/**
* A transformation for building an npm package:
*
* - discoverPackages
* - options
* - initTsConfig
* - analyzeTsSources (thereby extracting template and stylesheet files)
* - for each entry point
* - run the entryPontTransform
*
* @param project Project token, reference to `ng-package.json`
* @param options ng-packagr options
* @param initTsConfigTransform Transformation initializing the tsconfig of each entry point.
* @param analyseSourcesTransform Transformation analyzing the typescript source files of each entry point.
* @param entryPointTransform Transformation for asset rendering and compilation of a single entry point.
*/
const packageTransformFactory = (project, options, initTsConfigTransform, analyseSourcesTransform, entryPointTransform) => (source$) => {
log.info(`Building Angular Package`);
const buildTransform = options.watch
? watchTransformFactory(project, options, analyseSourcesTransform, entryPointTransform)
: buildTransformFactory(project, analyseSourcesTransform, entryPointTransform);
const pkgUri = (0, nodes_1.ngUrl)(project);
const ngPkg = new nodes_1.PackageNode(pkgUri);
return source$.pipe(
// Discover packages and entry points
// Clean the primary dest folder (should clean all secondary sub-directory, as well)
(0, rxjs_1.switchMap)(async (graph) => {
ngPkg.data = await (0, discover_packages_1.discoverPackages)({ project });
graph.put(ngPkg);
const { dest, deleteDestPath } = ngPkg.data;
if (deleteDestPath) {
try {
await (0, fs_1.rmdir)(dest, { recursive: true });
}
catch { }
}
const entryPoints = [ngPkg.data.primary, ...ngPkg.data.secondaries].map(entryPoint => {
const { destinationFiles, moduleId } = entryPoint;
const node = new nodes_1.EntryPointNode((0, nodes_1.ngUrl)(moduleId), ngPkg.cache.sourcesFileCache, ngPkg.cache.moduleResolutionCache);
node.data = { entryPoint, destinationFiles };
node.state = node_1.STATE_PENDING;
ngPkg.dependsOn(node);
return node;
});
// Add entry points to graph
return graph.put(entryPoints);
}),
// Initialize the tsconfig for each entry point
initTsConfigTransform,
// perform build
buildTransform, (0, rxjs_1.finalize)(() => {
var _a;
for (const node of ngPkg.dependents) {
if (node instanceof nodes_1.EntryPointNode) {
(_a = node.cache.stylesheetProcessor) === null || _a === void 0 ? void 0 : _a.destroy();
}
}
}));
};
exports.packageTransformFactory = packageTransformFactory;
const watchTransformFactory = (project, options, analyseSourcesTransform, entryPointTransform) => (source$) => {
const CompleteWaitingForFileChange = '\nCompilation complete. Watching for file changes...';
const FileChangeDetected = '\nFile change detected. Starting incremental compilation...';
const FailedWaitingForFileChange = '\nCompilation failed. Watching for file changes...';
return source$.pipe((0, rxjs_1.switchMap)(graph => {
const { data, cache: { sourcesFileCache }, } = graph.find(nodes_1.isPackage);
const { onFileChange, watcher } = (0, file_watcher_1.createFileWatch)([], [data.dest + '/'], options.poll);
graph.watcher = watcher;
return onFileChange.pipe((0, rxjs_1.map)(fileChange => (0, file_watcher_1.invalidateEntryPointsAndCacheOnFileChange)(graph, [fileChange.filePath], sourcesFileCache)), (0, rxjs_1.filter)(isChanged => isChanged), (0, rxjs_1.debounceTime)(100), (0, rxjs_1.tap)(() => log.msg(FileChangeDetected)), (0, rxjs_1.startWith)(undefined), (0, rxjs_1.map)(() => graph));
}), (0, rxjs_1.switchMap)(graph => {
const startTime = Date.now();
const pkgUri = (0, nodes_1.ngUrl)(project);
const ngPkg = graph.get(pkgUri);
return (0, rxjs_1.of)(graph).pipe(analyseSourcesTransform,
// Next, run through the entry point transformation (assets rendering, code compilation)
scheduleEntryPoints(entryPointTransform), (0, rxjs_1.repeat)({ delay: () => (graph.some((0, nodes_1.isEntryPointPending)()) ? (0, rxjs_1.of)(1) : rxjs_1.EMPTY) }), (0, rxjs_1.last)(), (0, rxjs_1.tap)(() => printBuiltAngularPackage(ngPkg, startTime)), (0, rxjs_1.catchError)(error => {
log.error(error);
log.msg(FailedWaitingForFileChange);
return rxjs_1.NEVER;
}), (0, rxjs_1.tap)(() => log.msg(CompleteWaitingForFileChange)));
}));
};
const buildTransformFactory = (project, analyseSourcesTransform, entryPointTransform) => (source$) => {
return source$.pipe((0, rxjs_1.switchMap)(graph => {
const startTime = Date.now();
const pkgUri = (0, nodes_1.ngUrl)(project);
const ngPkg = graph.get(pkgUri);
return (0, rxjs_1.of)(graph).pipe(
// Analyse dependencies and external resources for each entry point
analyseSourcesTransform,
// Next, run through the entry point transformation (assets rendering, code compilation)
scheduleEntryPoints(entryPointTransform), (0, rxjs_1.tap)(() => printBuiltAngularPackage(ngPkg, startTime)));
}));
};
const scheduleEntryPoints = (epTransform) => (0, rxjs_1.pipe)((0, rxjs_1.concatMap)(graph => {
// Calculate node/dependency depth and determine build order
const depGraph = new dependency_graph_1.DepGraph({ circular: false });
for (const node of graph.values()) {
if (!(0, nodes_1.isEntryPoint)(node)) {
continue;
}
// Remove `ng://` prefix for better error messages
const from = node.url.substring(5);
depGraph.addNode(from);
for (const dep of node.dependents) {
if (!(0, nodes_1.isEntryPoint)(dep)) {
continue;
}
const to = dep.url.substring(5);
depGraph.addNode(to);
depGraph.addDependency(from, to);
}
}
// The array index is the depth.
const groups = depGraph.overallOrder().map(nodes_1.ngUrl);
// Build entry points with lower depth values first.
return (0, rxjs_1.from)(groups).pipe((0, rxjs_1.map)((epUrl) => graph.find((0, nodes_1.byEntryPoint)().and(ep => ep.url === epUrl))), (0, rxjs_1.filter)((entryPoint) => entryPoint.state !== node_1.STATE_DONE), (0, rxjs_1.concatMap)(ep => (0, rxjs_1.of)(ep).pipe(
// Mark the entry point as 'in-progress'
(0, rxjs_1.tap)(entryPoint => (entryPoint.state = node_1.STATE_IN_PROGRESS)), (0, rxjs_1.map)(() => graph), epTransform, (0, rxjs_1.catchError)(err => {
ep.state = node_1.STATE_ERROR;
throw err;
}))), (0, rxjs_1.takeLast)(1), // don't use last as sometimes it this will cause 'no elements in sequence',
(0, rxjs_1.defaultIfEmpty)(graph));
}));
function printBuiltAngularPackage(ngPackage, startTime) {
log.success('\n------------------------------------------------------------------------------');
log.success(`Built Angular Package
- from: ${ngPackage.data.src}
- to: ${ngPackage.data.dest}`);
log.success('------------------------------------------------------------------------------');
const b = color_1.colors.bold;
const w = color_1.colors.white;
log.msg(w(`\nBuild at: ${b(new Date().toISOString())} - Time: ${b('' + (Date.now() - startTime))}ms\n`));
}
//# sourceMappingURL=package.transform.js.map
;