262 lines
37 KiB
JavaScript
262 lines
37 KiB
JavaScript
|
"use strict";
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright Google LLC 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
|
||
|
*/
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.FileSystemEngineHostBase = exports.SchematicNameCollisionException = exports.SchematicMissingDescriptionException = exports.SchematicMissingFieldsException = exports.CollectionMissingFieldsException = exports.CollectionMissingSchematicsMapException = exports.FactoryCannotBeResolvedException = exports.SchematicMissingFactoryException = exports.InvalidCollectionJsonException = exports.CollectionCannotBeResolvedException = void 0;
|
||
|
const core_1 = require("@angular-devkit/core");
|
||
|
const node_1 = require("@angular-devkit/core/node");
|
||
|
const fs_1 = require("fs");
|
||
|
const path_1 = require("path");
|
||
|
const rxjs_1 = require("rxjs");
|
||
|
const src_1 = require("../src");
|
||
|
const file_system_utility_1 = require("./file-system-utility");
|
||
|
class CollectionCannotBeResolvedException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Collection ${JSON.stringify(name)} cannot be resolved.`);
|
||
|
}
|
||
|
}
|
||
|
exports.CollectionCannotBeResolvedException = CollectionCannotBeResolvedException;
|
||
|
class InvalidCollectionJsonException extends core_1.BaseException {
|
||
|
constructor(_name, path, jsonException) {
|
||
|
let msg = `Collection JSON at path ${JSON.stringify(path)} is invalid.`;
|
||
|
if (jsonException) {
|
||
|
msg = `${msg} ${jsonException.message}`;
|
||
|
}
|
||
|
super(msg);
|
||
|
}
|
||
|
}
|
||
|
exports.InvalidCollectionJsonException = InvalidCollectionJsonException;
|
||
|
class SchematicMissingFactoryException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Schematic ${JSON.stringify(name)} is missing a factory.`);
|
||
|
}
|
||
|
}
|
||
|
exports.SchematicMissingFactoryException = SchematicMissingFactoryException;
|
||
|
class FactoryCannotBeResolvedException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Schematic ${JSON.stringify(name)} cannot resolve the factory.`);
|
||
|
}
|
||
|
}
|
||
|
exports.FactoryCannotBeResolvedException = FactoryCannotBeResolvedException;
|
||
|
class CollectionMissingSchematicsMapException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Collection "${name}" does not have a schematics map.`);
|
||
|
}
|
||
|
}
|
||
|
exports.CollectionMissingSchematicsMapException = CollectionMissingSchematicsMapException;
|
||
|
class CollectionMissingFieldsException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Collection "${name}" is missing fields.`);
|
||
|
}
|
||
|
}
|
||
|
exports.CollectionMissingFieldsException = CollectionMissingFieldsException;
|
||
|
class SchematicMissingFieldsException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Schematic "${name}" is missing fields.`);
|
||
|
}
|
||
|
}
|
||
|
exports.SchematicMissingFieldsException = SchematicMissingFieldsException;
|
||
|
class SchematicMissingDescriptionException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Schematics "${name}" does not have a description.`);
|
||
|
}
|
||
|
}
|
||
|
exports.SchematicMissingDescriptionException = SchematicMissingDescriptionException;
|
||
|
class SchematicNameCollisionException extends core_1.BaseException {
|
||
|
constructor(name) {
|
||
|
super(`Schematics/alias ${JSON.stringify(name)} collides with another alias or schematic` +
|
||
|
' name.');
|
||
|
}
|
||
|
}
|
||
|
exports.SchematicNameCollisionException = SchematicNameCollisionException;
|
||
|
/**
|
||
|
* A EngineHost base class that uses the file system to resolve collections. This is the base of
|
||
|
* all other EngineHost provided by the tooling part of the Schematics library.
|
||
|
*/
|
||
|
class FileSystemEngineHostBase {
|
||
|
constructor() {
|
||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
this._transforms = [];
|
||
|
this._contextTransforms = [];
|
||
|
this._taskFactories = new Map();
|
||
|
}
|
||
|
listSchematicNames(collection, includeHidden) {
|
||
|
const schematics = [];
|
||
|
for (const key of Object.keys(collection.schematics)) {
|
||
|
const schematic = collection.schematics[key];
|
||
|
if ((schematic.hidden && !includeHidden) || schematic.private) {
|
||
|
continue;
|
||
|
}
|
||
|
// If extends is present without a factory it is an alias, do not return it
|
||
|
// unless it is from another collection.
|
||
|
if (!schematic.extends || schematic.factory) {
|
||
|
schematics.push(key);
|
||
|
}
|
||
|
else if (schematic.extends && schematic.extends.indexOf(':') !== -1) {
|
||
|
schematics.push(key);
|
||
|
}
|
||
|
}
|
||
|
return schematics;
|
||
|
}
|
||
|
registerOptionsTransform(t) {
|
||
|
this._transforms.push(t);
|
||
|
}
|
||
|
registerContextTransform(t) {
|
||
|
this._contextTransforms.push(t);
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
* @param name
|
||
|
* @return {{path: string}}
|
||
|
*/
|
||
|
createCollectionDescription(name, requester) {
|
||
|
const path = this._resolveCollectionPath(name, requester?.path);
|
||
|
const jsonValue = (0, file_system_utility_1.readJsonFile)(path);
|
||
|
if (!jsonValue || typeof jsonValue != 'object' || Array.isArray(jsonValue)) {
|
||
|
throw new InvalidCollectionJsonException(name, path);
|
||
|
}
|
||
|
// normalize extends property to an array
|
||
|
if (typeof jsonValue['extends'] === 'string') {
|
||
|
jsonValue['extends'] = [jsonValue['extends']];
|
||
|
}
|
||
|
const description = this._transformCollectionDescription(name, {
|
||
|
...jsonValue,
|
||
|
path,
|
||
|
});
|
||
|
if (!description || !description.name) {
|
||
|
throw new InvalidCollectionJsonException(name, path);
|
||
|
}
|
||
|
// Validate aliases.
|
||
|
const allNames = Object.keys(description.schematics);
|
||
|
for (const schematicName of Object.keys(description.schematics)) {
|
||
|
const aliases = description.schematics[schematicName].aliases || [];
|
||
|
for (const alias of aliases) {
|
||
|
if (allNames.indexOf(alias) != -1) {
|
||
|
throw new SchematicNameCollisionException(alias);
|
||
|
}
|
||
|
}
|
||
|
allNames.push(...aliases);
|
||
|
}
|
||
|
return description;
|
||
|
}
|
||
|
createSchematicDescription(name, collection) {
|
||
|
// Resolve aliases first.
|
||
|
for (const schematicName of Object.keys(collection.schematics)) {
|
||
|
const schematicDescription = collection.schematics[schematicName];
|
||
|
if (schematicDescription.aliases && schematicDescription.aliases.indexOf(name) != -1) {
|
||
|
name = schematicName;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!(name in collection.schematics)) {
|
||
|
return null;
|
||
|
}
|
||
|
const collectionPath = (0, path_1.dirname)(collection.path);
|
||
|
const partialDesc = collection.schematics[name];
|
||
|
if (!partialDesc) {
|
||
|
return null;
|
||
|
}
|
||
|
if (partialDesc.extends) {
|
||
|
const index = partialDesc.extends.indexOf(':');
|
||
|
const collectionName = index !== -1 ? partialDesc.extends.slice(0, index) : null;
|
||
|
const schematicName = index === -1 ? partialDesc.extends : partialDesc.extends.slice(index + 1);
|
||
|
if (collectionName !== null) {
|
||
|
const extendCollection = this.createCollectionDescription(collectionName);
|
||
|
return this.createSchematicDescription(schematicName, extendCollection);
|
||
|
}
|
||
|
else {
|
||
|
return this.createSchematicDescription(schematicName, collection);
|
||
|
}
|
||
|
}
|
||
|
// Use any on this ref as we don't have the OptionT here, but we don't need it (we only need
|
||
|
// the path).
|
||
|
if (!partialDesc.factory) {
|
||
|
throw new SchematicMissingFactoryException(name);
|
||
|
}
|
||
|
const resolvedRef = this._resolveReferenceString(partialDesc.factory, collectionPath, collection);
|
||
|
if (!resolvedRef) {
|
||
|
throw new FactoryCannotBeResolvedException(name);
|
||
|
}
|
||
|
let schema = partialDesc.schema;
|
||
|
let schemaJson = undefined;
|
||
|
if (schema) {
|
||
|
if (!(0, path_1.isAbsolute)(schema)) {
|
||
|
schema = (0, path_1.join)(collectionPath, schema);
|
||
|
}
|
||
|
schemaJson = (0, file_system_utility_1.readJsonFile)(schema);
|
||
|
}
|
||
|
// The schematic path is used to resolve URLs.
|
||
|
// We should be able to just do `dirname(resolvedRef.path)` but for compatibility with
|
||
|
// Bazel under Windows this directory needs to be resolved from the collection instead.
|
||
|
// This is needed because on Bazel under Windows the data files (such as the collection or
|
||
|
// url files) are not in the same place as the compiled JS.
|
||
|
const maybePath = (0, path_1.join)(collectionPath, partialDesc.factory);
|
||
|
const path = (0, fs_1.existsSync)(maybePath) && (0, fs_1.statSync)(maybePath).isDirectory() ? maybePath : (0, path_1.dirname)(maybePath);
|
||
|
return this._transformSchematicDescription(name, collection, {
|
||
|
...partialDesc,
|
||
|
schema,
|
||
|
schemaJson,
|
||
|
name,
|
||
|
path,
|
||
|
factoryFn: resolvedRef.ref,
|
||
|
collection,
|
||
|
});
|
||
|
}
|
||
|
createSourceFromUrl(url) {
|
||
|
switch (url.protocol) {
|
||
|
case null:
|
||
|
case 'file:':
|
||
|
return (context) => {
|
||
|
// Check if context has necessary FileSystemSchematicContext path property
|
||
|
const fileDescription = context.schematic.description;
|
||
|
if (fileDescription.path === undefined) {
|
||
|
throw new Error('Unsupported schematic context. Expected a FileSystemSchematicContext.');
|
||
|
}
|
||
|
// Resolve all file:///a/b/c/d from the schematic's own path, and not the current
|
||
|
// path.
|
||
|
const root = (0, core_1.normalize)((0, path_1.resolve)(fileDescription.path, url.path || ''));
|
||
|
return new src_1.HostCreateTree(new core_1.virtualFs.ScopedHost(new node_1.NodeJsSyncHost(), root));
|
||
|
};
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
transformOptions(schematic, options, context) {
|
||
|
const transform = async () => {
|
||
|
let transformedOptions = options;
|
||
|
for (const transformer of this._transforms) {
|
||
|
const transformerResult = transformer(schematic, transformedOptions, context);
|
||
|
transformedOptions = await ((0, rxjs_1.isObservable)(transformerResult)
|
||
|
? (0, rxjs_1.lastValueFrom)(transformerResult)
|
||
|
: transformerResult);
|
||
|
}
|
||
|
return transformedOptions;
|
||
|
};
|
||
|
return (0, rxjs_1.from)(transform());
|
||
|
}
|
||
|
transformContext(context) {
|
||
|
return this._contextTransforms.reduce((acc, curr) => curr(acc), context);
|
||
|
}
|
||
|
getSchematicRuleFactory(schematic, _collection) {
|
||
|
return schematic.factoryFn;
|
||
|
}
|
||
|
registerTaskExecutor(factory, options) {
|
||
|
this._taskFactories.set(factory.name, () => (0, rxjs_1.from)(factory.create(options)));
|
||
|
}
|
||
|
createTaskExecutor(name) {
|
||
|
const factory = this._taskFactories.get(name);
|
||
|
if (factory) {
|
||
|
return factory();
|
||
|
}
|
||
|
return (0, rxjs_1.throwError)(new src_1.UnregisteredTaskException(name));
|
||
|
}
|
||
|
hasTaskExecutor(name) {
|
||
|
return this._taskFactories.has(name);
|
||
|
}
|
||
|
}
|
||
|
exports.FileSystemEngineHostBase = FileSystemEngineHostBase;
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS1zeXN0ZW0tZW5naW5lLWhvc3QtYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2FuZ3VsYXJfZGV2a2l0L3NjaGVtYXRpY3MvdG9vbHMvZmlsZS1zeXN0ZW0tZW5naW5lLWhvc3QtYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7QUFFSCwrQ0FBdUY7QUFDdkYsb0RBQTJEO0FBQzNELDJCQUEwQztBQUMxQywrQkFBMEQ7QUFDMUQsK0JBQW1HO0FBRW5HLGdDQU9nQjtBQVFoQiwrREFBcUQ7QUFXckQsTUFBYSxtQ0FBb0MsU0FBUSxvQkFBYTtJQUNwRSxZQUFZLElBQVk7UUFDdEIsS0FBSyxDQUFDLGNBQWMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztJQUNsRSxDQUFDO0NBQ0Y7QUFKRCxrRkFJQztBQUNELE1BQWEsOEJBQStCLFNBQVEsb0JBQWE7SUFDL0QsWUFBWSxLQUFhLEVBQUUsSUFBWSxFQUFFLGFBQXFCO1FBQzVELElBQUksR0FBRyxHQUFHLDJCQUEyQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7UUFFeEUsSUFBSSxhQUFhLEVBQUU7WUFDakIsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUN6QztRQUVELEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNiLENBQUM7Q0FDRjtBQVZELHdFQVVDO0FBQ0QsTUFBYSxnQ0FBaUMsU0FBUSxvQkFBYTtJQUNqRSxZQUFZLElBQVk7UUFDdEIsS0FBSyxDQUFDLGFBQWEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUNuRSxDQUFDO0NBQ0Y7QUFKRCw0RUFJQztBQUNELE1BQWEsZ0NBQWlDLFNBQVEsb0JBQWE7SUFDakUsWUFBWSxJ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
|