UNPKG

@angular/cli

Version:
309 lines • 12.8 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@angular-devkit/core"); const node_1 = require("@angular-devkit/core/node"); const command_1 = require("./command"); const tools_1 = require("@angular-devkit/schematics/tools"); const schematics_1 = require("@angular-devkit/schematics"); const config_1 = require("../utilities/config"); const schematics_2 = require("../utilities/schematics"); const config_2 = require("../utilities/config"); const operators_1 = require("rxjs/operators"); const workspace_loader_1 = require("../models/workspace-loader"); class SchematicCommand extends command_1.Command { constructor() { super(...arguments); this.options = []; this.allowPrivateSchematics = false; this._host = new node_1.NodeJsSyncHost(); this.argStrategy = command_1.ArgumentStrategy.Nothing; this.coreOptions = [ { name: 'dry-run', type: Boolean, default: false, aliases: ['d'], description: 'Run through without making any changes.' }, { name: 'force', type: Boolean, default: false, aliases: ['f'], description: 'Forces overwriting of files.' } ]; this.arguments = ['project']; } initialize(_options) { return __awaiter(this, void 0, void 0, function* () { this._loadWorkspace(); }); } setPathOptions(options, workingDir) { if (workingDir === '') { return {}; } return this.options .filter(o => o.format === 'path') .map(o => o.name) .filter(name => options[name] === undefined) .reduce((acc, curr) => { acc[curr] = workingDir; return acc; }, {}); } runSchematic(options) { const { collectionName, schematicName, debug, force, dryRun } = options; let schematicOptions = this.removeCoreOptions(options.schematicOptions); let nothingDone = true; let loggingQueue = []; let error = false; const fsHost = new core_1.virtualFs.ScopedHost(new node_1.NodeJsSyncHost(), core_1.normalize(this.project.root)); const workflow = new tools_1.NodeWorkflow(fsHost, { force, dryRun, packageManager: config_1.getPackageManager(), root: this.project.root, }); const workingDir = process.cwd().replace(this.project.root, '').replace(/\\/g, '/'); const pathOptions = this.setPathOptions(schematicOptions, workingDir); schematicOptions = Object.assign({}, schematicOptions, pathOptions); const defaultOptions = this.readDefaults(collectionName, schematicName, schematicOptions); schematicOptions = Object.assign({}, schematicOptions, defaultOptions); // Pass the rest of the arguments as the smart default "argv". Then delete it. // Removing the first item which is the schematic name. const rawArgs = schematicOptions._; workflow.registry.addSmartDefaultProvider('argv', (schema) => { if ('index' in schema) { return rawArgs[Number(schema['index'])]; } else { return rawArgs; } }); delete schematicOptions._; workflow.registry.addSmartDefaultProvider('projectName', (_schema) => { if (this._workspace) { return this._workspace.getProjectByPath(core_1.normalize(process.cwd())) || this._workspace.getDefaultProjectName(); } return undefined; }); workflow.reporter.subscribe((event) => { nothingDone = false; // Strip leading slash to prevent confusion. const eventPath = event.path.startsWith('/') ? event.path.substr(1) : event.path; switch (event.kind) { case 'error': error = true; const desc = event.description == 'alreadyExist' ? 'already exists' : 'does not exist.'; this.logger.warn(`ERROR! ${eventPath} ${desc}.`); break; case 'update': loggingQueue.push(core_1.tags.oneLine ` ${core_1.terminal.white('UPDATE')} ${eventPath} (${event.content.length} bytes) `); break; case 'create': loggingQueue.push(core_1.tags.oneLine ` ${core_1.terminal.green('CREATE')} ${eventPath} (${event.content.length} bytes) `); break; case 'delete': loggingQueue.push(`${core_1.terminal.yellow('DELETE')} ${eventPath}`); break; case 'rename': loggingQueue.push(`${core_1.terminal.blue('RENAME')} ${eventPath} => ${event.to}`); break; } }); workflow.lifeCycle.subscribe(event => { if (event.kind == 'end' || event.kind == 'post-tasks-start') { if (!error) { // Output the logging queue, no error happened. loggingQueue.forEach(log => this.logger.info(log)); } loggingQueue = []; error = false; } }); return new Promise((resolve) => { workflow.execute({ collection: collectionName, schematic: schematicName, options: schematicOptions, debug: debug, logger: this.logger, allowPrivate: this.allowPrivateSchematics, }) .subscribe({ error: (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. this.logger.fatal('The Schematic workflow failed. See above.'); } else if (debug) { this.logger.fatal(`An error occured:\n${err.message}\n${err.stack}`); } else { this.logger.fatal(err.message); } resolve(1); }, complete: () => { const showNothingDone = !(options.showNothingDone === false); if (nothingDone && showNothingDone) { this.logger.info('Nothing to be done.'); } if (dryRun) { this.logger.warn(`\nNOTE: Run with "dry run" no changes were made.`); } resolve(); }, }); }); } removeCoreOptions(options) { const opts = Object.assign({}, options); if (this._originalOptions.find(option => option.name == 'dryRun')) { delete opts.dryRun; } if (this._originalOptions.find(option => option.name == 'force')) { delete opts.force; } if (this._originalOptions.find(option => option.name == 'debug')) { delete opts.debug; } return opts; } getOptions(options) { // Make a copy. this._originalOptions = [...this.options]; const collectionName = options.collectionName || config_1.getDefaultSchematicCollection(); const collection = schematics_2.getCollection(collectionName); const schematic = schematics_2.getSchematic(collection, options.schematicName, this.allowPrivateSchematics); this._deAliasedName = schematic.description.name; if (!schematic.description.schemaJson) { return Promise.resolve({ options: [], arguments: [] }); } const properties = schematic.description.schemaJson.properties; const keys = Object.keys(properties); const availableOptions = keys .map(key => (Object.assign({}, properties[key], { name: core_1.strings.dasherize(key) }))) .map(opt => { let type; const schematicType = opt.type; switch (opt.type) { case 'string': type = String; break; case 'boolean': type = Boolean; break; case 'integer': case 'number': type = Number; break; // Ignore arrays / objects. default: return null; } let aliases = []; if (opt.alias) { aliases = [...aliases, opt.alias]; } if (opt.aliases) { aliases = [...aliases, ...opt.aliases]; } const schematicDefault = opt.default; return Object.assign({}, opt, { aliases, type, schematicType, default: undefined, // do not carry over schematics defaults schematicDefault, hidden: opt.visible === false }); }) .filter(x => x); const schematicOptions = availableOptions .filter(opt => opt.$default === undefined || opt.$default.$source !== 'argv'); const schematicArguments = availableOptions .filter(opt => opt.$default !== undefined && opt.$default.$source === 'argv') .sort((a, b) => { if (a.$default.index === undefined) { return 1; } if (b.$default.index === undefined) { return -1; } if (a.$default.index == b.$default.index) { return 0; } else if (a.$default.index > b.$default.index) { return 1; } else { return -1; } }); return Promise.resolve({ options: schematicOptions, arguments: schematicArguments }); } _loadWorkspace() { if (this._workspace) { return; } const workspaceLoader = new workspace_loader_1.WorkspaceLoader(this._host); try { workspaceLoader.loadWorkspace(this.project.root).pipe(operators_1.take(1)) .subscribe((workspace) => this._workspace = workspace, (err) => { if (!this.allowMissingWorkspace) { // Ignore missing workspace throw err; } }); } catch (err) { if (!this.allowMissingWorkspace) { // Ignore missing workspace throw err; } } } _cleanDefaults(defaults, undefinedOptions) { Object.keys(defaults) .filter(key => !undefinedOptions.map(core_1.strings.camelize).includes(key)) .forEach(key => { delete defaults[key]; }); return defaults; } readDefaults(collectionName, schematicName, options) { if (this._deAliasedName) { schematicName = this._deAliasedName; } const projectName = options.project; const defaults = config_2.getSchematicDefaults(collectionName, schematicName, projectName); // Get list of all undefined options. const undefinedOptions = this.options .filter(o => options[o.name] === undefined) .map(o => o.name); // Delete any default that is not undefined. this._cleanDefaults(defaults, undefinedOptions); return defaults; } } exports.SchematicCommand = SchematicCommand; //# sourceMappingURL=/Users/hansl/Sources/hansl/angular-cli/models/schematic-command.js.map