UNPKG

@angular/cli

Version:
389 lines (388 loc) • 20.6 kB
"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.dev/license */ 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 __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; 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.SchematicsCommandModule = exports.DEFAULT_SCHEMATICS_COLLECTION = void 0; const core_1 = require("@angular-devkit/core"); const schematics_1 = require("@angular-devkit/schematics"); const tools_1 = require("@angular-devkit/schematics/tools"); const node_path_1 = require("node:path"); const analytics_1 = require("../analytics/analytics"); const analytics_parameters_1 = require("../analytics/analytics-parameters"); const config_1 = require("../utilities/config"); const error_1 = require("../utilities/error"); const memoize_1 = require("../utilities/memoize"); const tty_1 = require("../utilities/tty"); const command_module_1 = require("./command-module"); const json_schema_1 = require("./utilities/json-schema"); const schematic_engine_host_1 = require("./utilities/schematic-engine-host"); const schematic_workflow_1 = require("./utilities/schematic-workflow"); exports.DEFAULT_SCHEMATICS_COLLECTION = '@schematics/angular'; let SchematicsCommandModule = (() => { let _classSuper = command_module_1.CommandModule; let _instanceExtraInitializers = []; let _getOrCreateWorkflowForBuilder_decorators; let _getOrCreateWorkflowForExecution_decorators; let _getSchematicCollections_decorators; return class SchematicsCommandModule extends _classSuper { static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _getOrCreateWorkflowForBuilder_decorators = [memoize_1.memoize]; _getOrCreateWorkflowForExecution_decorators = [memoize_1.memoize]; _getSchematicCollections_decorators = [memoize_1.memoize]; __esDecorate(this, null, _getOrCreateWorkflowForBuilder_decorators, { kind: "method", name: "getOrCreateWorkflowForBuilder", static: false, private: false, access: { has: obj => "getOrCreateWorkflowForBuilder" in obj, get: obj => obj.getOrCreateWorkflowForBuilder }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _getOrCreateWorkflowForExecution_decorators, { kind: "method", name: "getOrCreateWorkflowForExecution", static: false, private: false, access: { has: obj => "getOrCreateWorkflowForExecution" in obj, get: obj => obj.getOrCreateWorkflowForExecution }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _getSchematicCollections_decorators, { kind: "method", name: "getSchematicCollections", static: false, private: false, access: { has: obj => "getSchematicCollections" in obj, get: obj => obj.getSchematicCollections }, metadata: _metadata }, null, _instanceExtraInitializers); if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } scope = (__runInitializers(this, _instanceExtraInitializers), command_module_1.CommandScope.In); allowPrivateSchematics = false; async builder(argv) { return argv .option('interactive', { describe: 'Enable interactive input prompts.', type: 'boolean', default: true, }) .option('dry-run', { describe: 'Run through and reports activity without writing out results.', type: 'boolean', alias: ['d'], default: false, }) .option('defaults', { describe: 'Disable interactive input prompts for options with a default.', type: 'boolean', default: false, }) .option('force', { describe: 'Force overwriting of existing files.', type: 'boolean', default: false, }) .strict(); } /** Get schematic schema options.*/ async getSchematicOptions(collection, schematicName, workflow) { const schematic = collection.createSchematic(schematicName, true); const { schemaJson } = schematic.description; if (!schemaJson) { return []; } return (0, json_schema_1.parseJsonSchemaToOptions)(workflow.registry, schemaJson); } getOrCreateWorkflowForBuilder(collectionName) { return new tools_1.NodeWorkflow(this.context.root, { resolvePaths: this.getResolvePaths(collectionName), engineHostCreator: (options) => new schematic_engine_host_1.SchematicEngineHost(options.resolvePaths), }); } async getOrCreateWorkflowForExecution(collectionName, options) { const { logger, root, packageManager } = this.context; const { force, dryRun, packageRegistry } = options; const workflow = new tools_1.NodeWorkflow(root, { force, dryRun, packageManager: packageManager.name, // A schema registry is required to allow customizing addUndefinedDefaults registry: new core_1.schema.CoreSchemaRegistry(schematics_1.formats.standardFormats), packageRegistry, resolvePaths: this.getResolvePaths(collectionName), schemaValidation: true, optionTransforms: [ // Add configuration file defaults async (schematic, current) => { const projectName = typeof current?.project === 'string' ? current.project : this.getProjectName(); return { ...(await (0, config_1.getSchematicDefaults)(schematic.collection.name, schematic.name, projectName)), ...current, }; }, ], engineHostCreator: (options) => new schematic_engine_host_1.SchematicEngineHost(options.resolvePaths), }); workflow.registry.addPostTransform(core_1.schema.transforms.addUndefinedDefaults); workflow.registry.useXDeprecatedProvider((msg) => logger.warn(msg)); workflow.registry.addSmartDefaultProvider('projectName', () => this.getProjectName()); const workingDir = (0, core_1.normalize)((0, node_path_1.relative)(this.context.root, process.cwd())); workflow.registry.addSmartDefaultProvider('workingDirectory', () => workingDir === '' ? undefined : workingDir); workflow.engineHost.registerOptionsTransform(async (schematic, options) => { const { collection: { name: collectionName }, name: schematicName, } = schematic; const analytics = (0, analytics_1.isPackageNameSafeForAnalytics)(collectionName) ? await this.getAnalytics() : undefined; analytics?.reportSchematicRunEvent({ [analytics_parameters_1.EventCustomDimension.SchematicCollectionName]: collectionName, [analytics_parameters_1.EventCustomDimension.SchematicName]: schematicName, ...this.getAnalyticsParameters(options), }); return options; }); if (options.interactive !== false && (0, tty_1.isTTY)()) { workflow.registry.usePromptProvider(async (definitions) => { let prompts; const answers = {}; for (const definition of definitions) { if (options.defaults && definition.default !== undefined) { continue; } // Only load prompt package if needed prompts ??= await Promise.resolve().then(() => __importStar(require('@inquirer/prompts'))); switch (definition.type) { case 'confirmation': answers[definition.id] = await prompts.confirm({ message: definition.message, default: definition.default, }); break; case 'list': if (!definition.items?.length) { continue; } answers[definition.id] = await (definition.multiselect ? prompts.checkbox : prompts.select)({ message: definition.message, validate: (values) => { if (!definition.validator) { return true; } return definition.validator(Object.values(values).map(({ value }) => value)); }, default: definition.multiselect ? undefined : definition.default, choices: definition.items?.map((item) => typeof item == 'string' ? { name: item, value: item, } : { ...item, name: item.label, value: item.value, }), }); break; case 'input': { let finalValue; answers[definition.id] = await prompts.input({ message: definition.message, default: definition.default, async validate(value) { if (definition.validator === undefined) { return true; } let lastValidation = false; for (const type of definition.propertyTypes) { let potential; switch (type) { case 'string': potential = String(value); break; case 'integer': case 'number': potential = Number(value); break; default: potential = value; break; } lastValidation = await definition.validator(potential); // Can be a string if validation fails if (lastValidation === true) { finalValue = potential; return true; } } return lastValidation; }, }); // Use validated value if present. // This ensures the correct type is inserted into the final schema options. if (finalValue !== undefined) { answers[definition.id] = finalValue; } break; } } } return answers; }); } return workflow; } async getSchematicCollections() { const getSchematicCollections = (configSection) => { if (!configSection) { return undefined; } const { schematicCollections } = configSection; if (Array.isArray(schematicCollections)) { return new Set(schematicCollections); } return undefined; }; const { workspace, globalConfiguration } = this.context; if (workspace) { const project = (0, config_1.getProjectByCwd)(workspace); if (project) { const value = getSchematicCollections(workspace.getProjectCli(project)); if (value) { return value; } } } const value = getSchematicCollections(workspace?.getCli()) ?? getSchematicCollections(globalConfiguration.getCli()); if (value) { return value; } return new Set([exports.DEFAULT_SCHEMATICS_COLLECTION]); } parseSchematicInfo(schematic) { if (schematic?.includes(':')) { const [collectionName, schematicName] = schematic.split(':', 2); return [collectionName, schematicName]; } return [undefined, schematic]; } async runSchematic(options) { const { logger } = this.context; const { schematicOptions, executionOptions, collectionName, schematicName } = options; const workflow = await this.getOrCreateWorkflowForExecution(collectionName, executionOptions); if (!schematicName) { throw new Error('schematicName cannot be undefined.'); } const { unsubscribe, files } = (0, schematic_workflow_1.subscribeToWorkflow)(workflow, logger); try { await workflow .execute({ collection: collectionName, schematic: schematicName, options: schematicOptions, logger, allowPrivate: this.allowPrivateSchematics, }) .toPromise(); if (!files.size) { logger.info('Nothing to be done.'); } if (executionOptions.dryRun) { logger.warn(`\nNOTE: The "--dry-run" option means no changes were made.`); } } catch (err) { // In case the workflow was not successful, show an appropriate error message. if (err instanceof schematics_1.UnsuccessfulWorkflowExecution) { // "See above" because we already printed the error. logger.fatal('The Schematic workflow failed. See above.'); } else { (0, error_1.assertIsError)(err); logger.fatal(err.message); } return 1; } finally { unsubscribe(); } return 0; } getProjectName() { const { workspace } = this.context; if (!workspace) { return undefined; } const projectName = (0, config_1.getProjectByCwd)(workspace); if (projectName) { return projectName; } return undefined; } getResolvePaths(collectionName) { const { workspace, root } = this.context; if (collectionName[0] === '.') { // Resolve relative collections from the location of `angular.json` return [root]; } return workspace ? // Workspace collectionName === exports.DEFAULT_SCHEMATICS_COLLECTION ? // Favor __dirname for @schematics/angular to use the build-in version [__dirname, process.cwd(), root] : [process.cwd(), root, __dirname] : // Global [__dirname, process.cwd()]; } }; })(); exports.SchematicsCommandModule = SchematicsCommandModule;