[6a3a178] | 1 | "use strict";
|
---|
| 2 | /**
|
---|
| 3 | * @license
|
---|
| 4 | * Copyright Google LLC All Rights Reserved.
|
---|
| 5 | *
|
---|
| 6 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 7 | * found in the LICENSE file at https://angular.io/license
|
---|
| 8 | */
|
---|
| 9 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
---|
| 10 | if (k2 === undefined) k2 = k;
|
---|
| 11 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
---|
| 12 | }) : (function(o, m, k, k2) {
|
---|
| 13 | if (k2 === undefined) k2 = k;
|
---|
| 14 | o[k2] = m[k];
|
---|
| 15 | }));
|
---|
| 16 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
---|
| 17 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
---|
| 18 | }) : function(o, v) {
|
---|
| 19 | o["default"] = v;
|
---|
| 20 | });
|
---|
| 21 | var __importStar = (this && this.__importStar) || function (mod) {
|
---|
| 22 | if (mod && mod.__esModule) return mod;
|
---|
| 23 | var result = {};
|
---|
| 24 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
---|
| 25 | __setModuleDefault(result, mod);
|
---|
| 26 | return result;
|
---|
| 27 | };
|
---|
| 28 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
| 29 | exports.SchematicCommand = exports.UnknownCollectionError = void 0;
|
---|
| 30 | const core_1 = require("@angular-devkit/core");
|
---|
| 31 | const schematics_1 = require("@angular-devkit/schematics");
|
---|
| 32 | const tools_1 = require("@angular-devkit/schematics/tools");
|
---|
| 33 | const inquirer = __importStar(require("inquirer"));
|
---|
| 34 | const systemPath = __importStar(require("path"));
|
---|
| 35 | const color_1 = require("../utilities/color");
|
---|
| 36 | const config_1 = require("../utilities/config");
|
---|
| 37 | const json_schema_1 = require("../utilities/json-schema");
|
---|
| 38 | const package_manager_1 = require("../utilities/package-manager");
|
---|
| 39 | const tty_1 = require("../utilities/tty");
|
---|
| 40 | const analytics_1 = require("./analytics");
|
---|
| 41 | const command_1 = require("./command");
|
---|
| 42 | const parser_1 = require("./parser");
|
---|
| 43 | const schematic_engine_host_1 = require("./schematic-engine-host");
|
---|
| 44 | class UnknownCollectionError extends Error {
|
---|
| 45 | constructor(collectionName) {
|
---|
| 46 | super(`Invalid collection (${collectionName}).`);
|
---|
| 47 | }
|
---|
| 48 | }
|
---|
| 49 | exports.UnknownCollectionError = UnknownCollectionError;
|
---|
| 50 | class SchematicCommand extends command_1.Command {
|
---|
| 51 | constructor(context, description, logger) {
|
---|
| 52 | super(context, description, logger);
|
---|
| 53 | this.allowPrivateSchematics = false;
|
---|
| 54 | this.useReportAnalytics = false;
|
---|
| 55 | this.defaultCollectionName = '@schematics/angular';
|
---|
| 56 | this.collectionName = this.defaultCollectionName;
|
---|
| 57 | }
|
---|
| 58 | async initialize(options) {
|
---|
| 59 | await this.createWorkflow(options);
|
---|
| 60 | if (this.schematicName) {
|
---|
| 61 | // Set the options.
|
---|
| 62 | const collection = this.getCollection(this.collectionName);
|
---|
| 63 | const schematic = this.getSchematic(collection, this.schematicName, true);
|
---|
| 64 | const options = await json_schema_1.parseJsonSchemaToOptions(this._workflow.registry, schematic.description.schemaJson || {});
|
---|
| 65 | this.description.description = schematic.description.description;
|
---|
| 66 | this.description.options.push(...options.filter((x) => !x.hidden));
|
---|
| 67 | // Remove any user analytics from schematics that are NOT part of our safelist.
|
---|
| 68 | for (const o of this.description.options) {
|
---|
| 69 | if (o.userAnalytics && !analytics_1.isPackageNameSafeForAnalytics(this.collectionName)) {
|
---|
| 70 | o.userAnalytics = undefined;
|
---|
| 71 | }
|
---|
| 72 | }
|
---|
| 73 | }
|
---|
| 74 | }
|
---|
| 75 | async printHelp() {
|
---|
| 76 | await super.printHelp();
|
---|
| 77 | this.logger.info('');
|
---|
| 78 | const subCommandOption = this.description.options.filter((x) => x.subcommands)[0];
|
---|
| 79 | if (!subCommandOption || !subCommandOption.subcommands) {
|
---|
| 80 | return 0;
|
---|
| 81 | }
|
---|
| 82 | const schematicNames = Object.keys(subCommandOption.subcommands);
|
---|
| 83 | if (schematicNames.length > 1) {
|
---|
| 84 | this.logger.info('Available Schematics:');
|
---|
| 85 | const namesPerCollection = {};
|
---|
| 86 | schematicNames.forEach((name) => {
|
---|
| 87 | let [collectionName, schematicName] = name.split(/:/, 2);
|
---|
| 88 | if (!schematicName) {
|
---|
| 89 | schematicName = collectionName;
|
---|
| 90 | collectionName = this.collectionName;
|
---|
| 91 | }
|
---|
| 92 | if (!namesPerCollection[collectionName]) {
|
---|
| 93 | namesPerCollection[collectionName] = [];
|
---|
| 94 | }
|
---|
| 95 | namesPerCollection[collectionName].push(schematicName);
|
---|
| 96 | });
|
---|
| 97 | const defaultCollection = await this.getDefaultSchematicCollection();
|
---|
| 98 | Object.keys(namesPerCollection).forEach((collectionName) => {
|
---|
| 99 | const isDefault = defaultCollection == collectionName;
|
---|
| 100 | this.logger.info(` Collection "${collectionName}"${isDefault ? ' (default)' : ''}:`);
|
---|
| 101 | namesPerCollection[collectionName].forEach((schematicName) => {
|
---|
| 102 | this.logger.info(` ${schematicName}`);
|
---|
| 103 | });
|
---|
| 104 | });
|
---|
| 105 | }
|
---|
| 106 | return 0;
|
---|
| 107 | }
|
---|
| 108 | async printHelpUsage() {
|
---|
| 109 | const subCommandOption = this.description.options.filter((x) => x.subcommands)[0];
|
---|
| 110 | if (!subCommandOption || !subCommandOption.subcommands) {
|
---|
| 111 | return;
|
---|
| 112 | }
|
---|
| 113 | const schematicNames = Object.keys(subCommandOption.subcommands);
|
---|
| 114 | if (schematicNames.length == 1) {
|
---|
| 115 | this.logger.info(this.description.description);
|
---|
| 116 | const opts = this.description.options.filter((x) => x.positional === undefined);
|
---|
| 117 | const [collectionName, schematicName] = schematicNames[0].split(/:/)[0];
|
---|
| 118 | // Display <collectionName:schematicName> if this is not the default collectionName,
|
---|
| 119 | // otherwise just show the schematicName.
|
---|
| 120 | const displayName = collectionName == (await this.getDefaultSchematicCollection())
|
---|
| 121 | ? schematicName
|
---|
| 122 | : schematicNames[0];
|
---|
| 123 | const schematicOptions = subCommandOption.subcommands[schematicNames[0]].options;
|
---|
| 124 | const schematicArgs = schematicOptions.filter((x) => x.positional !== undefined);
|
---|
| 125 | const argDisplay = schematicArgs.length > 0
|
---|
| 126 | ? ' ' + schematicArgs.map((a) => `<${core_1.strings.dasherize(a.name)}>`).join(' ')
|
---|
| 127 | : '';
|
---|
| 128 | this.logger.info(core_1.tags.oneLine `
|
---|
| 129 | usage: ng ${this.description.name} ${displayName}${argDisplay}
|
---|
| 130 | ${opts.length > 0 ? `[options]` : ``}
|
---|
| 131 | `);
|
---|
| 132 | this.logger.info('');
|
---|
| 133 | }
|
---|
| 134 | else {
|
---|
| 135 | await super.printHelpUsage();
|
---|
| 136 | }
|
---|
| 137 | }
|
---|
| 138 | getEngine() {
|
---|
| 139 | return this._workflow.engine;
|
---|
| 140 | }
|
---|
| 141 | getCollection(collectionName) {
|
---|
| 142 | const engine = this.getEngine();
|
---|
| 143 | const collection = engine.createCollection(collectionName);
|
---|
| 144 | if (collection === null) {
|
---|
| 145 | throw new UnknownCollectionError(collectionName);
|
---|
| 146 | }
|
---|
| 147 | return collection;
|
---|
| 148 | }
|
---|
| 149 | getSchematic(collection, schematicName, allowPrivate) {
|
---|
| 150 | return collection.createSchematic(schematicName, allowPrivate);
|
---|
| 151 | }
|
---|
| 152 | setPathOptions(options, workingDir) {
|
---|
| 153 | if (workingDir === '') {
|
---|
| 154 | return {};
|
---|
| 155 | }
|
---|
| 156 | return options
|
---|
| 157 | .filter((o) => o.format === 'path')
|
---|
| 158 | .map((o) => o.name)
|
---|
| 159 | .reduce((acc, curr) => {
|
---|
| 160 | acc[curr] = workingDir;
|
---|
| 161 | return acc;
|
---|
| 162 | }, {});
|
---|
| 163 | }
|
---|
| 164 | /*
|
---|
| 165 | * Runtime hook to allow specifying customized workflow
|
---|
| 166 | */
|
---|
| 167 | async createWorkflow(options) {
|
---|
| 168 | if (this._workflow) {
|
---|
| 169 | return this._workflow;
|
---|
| 170 | }
|
---|
| 171 | const { force, dryRun } = options;
|
---|
| 172 | const root = this.context.root;
|
---|
| 173 | const workflow = new tools_1.NodeWorkflow(root, {
|
---|
| 174 | force,
|
---|
| 175 | dryRun,
|
---|
| 176 | packageManager: await package_manager_1.getPackageManager(root),
|
---|
| 177 | packageRegistry: options.packageRegistry,
|
---|
| 178 | // A schema registry is required to allow customizing addUndefinedDefaults
|
---|
| 179 | registry: new core_1.schema.CoreSchemaRegistry(schematics_1.formats.standardFormats),
|
---|
| 180 | resolvePaths: this.workspace
|
---|
| 181 | ? // Workspace
|
---|
| 182 | this.collectionName === this.defaultCollectionName
|
---|
| 183 | ? // Favor __dirname for @schematics/angular to use the build-in version
|
---|
| 184 | [__dirname, process.cwd(), root]
|
---|
| 185 | : [process.cwd(), root, __dirname]
|
---|
| 186 | : // Global
|
---|
| 187 | [__dirname, process.cwd()],
|
---|
| 188 | schemaValidation: true,
|
---|
| 189 | optionTransforms: [
|
---|
| 190 | // Add configuration file defaults
|
---|
| 191 | async (schematic, current) => {
|
---|
| 192 | const projectName = typeof current.project === 'string'
|
---|
| 193 | ? current.project
|
---|
| 194 | : getProjectName();
|
---|
| 195 | return {
|
---|
| 196 | ...(await config_1.getSchematicDefaults(schematic.collection.name, schematic.name, projectName)),
|
---|
| 197 | ...current,
|
---|
| 198 | };
|
---|
| 199 | },
|
---|
| 200 | ],
|
---|
| 201 | engineHostCreator: (options) => new schematic_engine_host_1.SchematicEngineHost(options.resolvePaths),
|
---|
| 202 | });
|
---|
| 203 | const getProjectName = () => {
|
---|
| 204 | if (this.workspace) {
|
---|
| 205 | const projectNames = getProjectsByPath(this.workspace, process.cwd(), this.workspace.basePath);
|
---|
| 206 | if (projectNames.length === 1) {
|
---|
| 207 | return projectNames[0];
|
---|
| 208 | }
|
---|
| 209 | else {
|
---|
| 210 | if (projectNames.length > 1) {
|
---|
| 211 | this.logger.warn(core_1.tags.oneLine `
|
---|
| 212 | Two or more projects are using identical roots.
|
---|
| 213 | Unable to determine project using current working directory.
|
---|
| 214 | Using default workspace project instead.
|
---|
| 215 | `);
|
---|
| 216 | }
|
---|
| 217 | const defaultProjectName = this.workspace.extensions['defaultProject'];
|
---|
| 218 | if (typeof defaultProjectName === 'string' && defaultProjectName) {
|
---|
| 219 | return defaultProjectName;
|
---|
| 220 | }
|
---|
| 221 | }
|
---|
| 222 | }
|
---|
| 223 | return undefined;
|
---|
| 224 | };
|
---|
| 225 | workflow.registry.addPostTransform(core_1.schema.transforms.addUndefinedDefaults);
|
---|
| 226 | workflow.registry.addSmartDefaultProvider('projectName', getProjectName);
|
---|
| 227 | workflow.registry.useXDeprecatedProvider((msg) => this.logger.warn(msg));
|
---|
| 228 | let shouldReportAnalytics = true;
|
---|
| 229 | workflow.engineHost.registerOptionsTransform(async (_, options) => {
|
---|
| 230 | if (shouldReportAnalytics) {
|
---|
| 231 | shouldReportAnalytics = false;
|
---|
| 232 | await this.reportAnalytics([this.description.name], options);
|
---|
| 233 | }
|
---|
| 234 | return options;
|
---|
| 235 | });
|
---|
| 236 | if (options.interactive !== false && tty_1.isTTY()) {
|
---|
| 237 | workflow.registry.usePromptProvider((definitions) => {
|
---|
| 238 | const questions = definitions
|
---|
| 239 | .filter((definition) => !options.defaults || definition.default === undefined)
|
---|
| 240 | .map((definition) => {
|
---|
| 241 | var _a;
|
---|
| 242 | const question = {
|
---|
| 243 | name: definition.id,
|
---|
| 244 | message: definition.message,
|
---|
| 245 | default: definition.default,
|
---|
| 246 | };
|
---|
| 247 | const validator = definition.validator;
|
---|
| 248 | if (validator) {
|
---|
| 249 | question.validate = (input) => validator(input);
|
---|
| 250 | // Filter allows transformation of the value prior to validation
|
---|
| 251 | question.filter = async (input) => {
|
---|
| 252 | for (const type of definition.propertyTypes) {
|
---|
| 253 | let value;
|
---|
| 254 | switch (type) {
|
---|
| 255 | case 'string':
|
---|
| 256 | value = String(input);
|
---|
| 257 | break;
|
---|
| 258 | case 'integer':
|
---|
| 259 | case 'number':
|
---|
| 260 | value = Number(input);
|
---|
| 261 | break;
|
---|
| 262 | default:
|
---|
| 263 | value = input;
|
---|
| 264 | break;
|
---|
| 265 | }
|
---|
| 266 | // Can be a string if validation fails
|
---|
| 267 | const isValid = (await validator(value)) === true;
|
---|
| 268 | if (isValid) {
|
---|
| 269 | return value;
|
---|
| 270 | }
|
---|
| 271 | }
|
---|
| 272 | return input;
|
---|
| 273 | };
|
---|
| 274 | }
|
---|
| 275 | switch (definition.type) {
|
---|
| 276 | case 'confirmation':
|
---|
| 277 | question.type = 'confirm';
|
---|
| 278 | break;
|
---|
| 279 | case 'list':
|
---|
| 280 | question.type = definition.multiselect ? 'checkbox' : 'list';
|
---|
| 281 | question.choices = (_a = definition.items) === null || _a === void 0 ? void 0 : _a.map((item) => {
|
---|
| 282 | return typeof item == 'string'
|
---|
| 283 | ? item
|
---|
| 284 | : {
|
---|
| 285 | name: item.label,
|
---|
| 286 | value: item.value,
|
---|
| 287 | };
|
---|
| 288 | });
|
---|
| 289 | break;
|
---|
| 290 | default:
|
---|
| 291 | question.type = definition.type;
|
---|
| 292 | break;
|
---|
| 293 | }
|
---|
| 294 | return question;
|
---|
| 295 | });
|
---|
| 296 | return inquirer.prompt(questions);
|
---|
| 297 | });
|
---|
| 298 | }
|
---|
| 299 | return (this._workflow = workflow);
|
---|
| 300 | }
|
---|
| 301 | async getDefaultSchematicCollection() {
|
---|
| 302 | let workspace = await config_1.getWorkspace('local');
|
---|
| 303 | if (workspace) {
|
---|
| 304 | const project = config_1.getProjectByCwd(workspace);
|
---|
| 305 | if (project && workspace.getProjectCli(project)) {
|
---|
| 306 | const value = workspace.getProjectCli(project)['defaultCollection'];
|
---|
| 307 | if (typeof value == 'string') {
|
---|
| 308 | return value;
|
---|
| 309 | }
|
---|
| 310 | }
|
---|
| 311 | if (workspace.getCli()) {
|
---|
| 312 | const value = workspace.getCli()['defaultCollection'];
|
---|
| 313 | if (typeof value == 'string') {
|
---|
| 314 | return value;
|
---|
| 315 | }
|
---|
| 316 | }
|
---|
| 317 | }
|
---|
| 318 | workspace = await config_1.getWorkspace('global');
|
---|
| 319 | if (workspace && workspace.getCli()) {
|
---|
| 320 | const value = workspace.getCli()['defaultCollection'];
|
---|
| 321 | if (typeof value == 'string') {
|
---|
| 322 | return value;
|
---|
| 323 | }
|
---|
| 324 | }
|
---|
| 325 | return this.defaultCollectionName;
|
---|
| 326 | }
|
---|
| 327 | async runSchematic(options) {
|
---|
| 328 | const { schematicOptions, debug, dryRun } = options;
|
---|
| 329 | let { collectionName, schematicName } = options;
|
---|
| 330 | let nothingDone = true;
|
---|
| 331 | let loggingQueue = [];
|
---|
| 332 | let error = false;
|
---|
| 333 | const workflow = this._workflow;
|
---|
| 334 | const workingDir = core_1.normalize(systemPath.relative(this.context.root, process.cwd()));
|
---|
| 335 | // Get the option object from the schematic schema.
|
---|
| 336 | const schematic = this.getSchematic(this.getCollection(collectionName), schematicName, this.allowPrivateSchematics);
|
---|
| 337 | // Update the schematic and collection name in case they're not the same as the ones we
|
---|
| 338 | // received in our options, e.g. after alias resolution or extension.
|
---|
| 339 | collectionName = schematic.collection.description.name;
|
---|
| 340 | schematicName = schematic.description.name;
|
---|
| 341 | // Set the options of format "path".
|
---|
| 342 | let o = null;
|
---|
| 343 | let args;
|
---|
| 344 | if (!schematic.description.schemaJson) {
|
---|
| 345 | args = await this.parseFreeFormArguments(schematicOptions || []);
|
---|
| 346 | }
|
---|
| 347 | else {
|
---|
| 348 | o = await json_schema_1.parseJsonSchemaToOptions(workflow.registry, schematic.description.schemaJson);
|
---|
| 349 | args = await this.parseArguments(schematicOptions || [], o);
|
---|
| 350 | }
|
---|
| 351 | const allowAdditionalProperties = typeof schematic.description.schemaJson === 'object' &&
|
---|
| 352 | schematic.description.schemaJson.additionalProperties;
|
---|
| 353 | if (args['--'] && !allowAdditionalProperties) {
|
---|
| 354 | args['--'].forEach((additional) => {
|
---|
| 355 | this.logger.fatal(`Unknown option: '${additional.split(/=/)[0]}'`);
|
---|
| 356 | });
|
---|
| 357 | return 1;
|
---|
| 358 | }
|
---|
| 359 | const pathOptions = o ? this.setPathOptions(o, workingDir) : {};
|
---|
| 360 | const input = {
|
---|
| 361 | ...pathOptions,
|
---|
| 362 | ...args,
|
---|
| 363 | ...options.additionalOptions,
|
---|
| 364 | };
|
---|
| 365 | workflow.reporter.subscribe((event) => {
|
---|
| 366 | nothingDone = false;
|
---|
| 367 | // Strip leading slash to prevent confusion.
|
---|
| 368 | const eventPath = event.path.startsWith('/') ? event.path.substr(1) : event.path;
|
---|
| 369 | switch (event.kind) {
|
---|
| 370 | case 'error':
|
---|
| 371 | error = true;
|
---|
| 372 | const desc = event.description == 'alreadyExist' ? 'already exists' : 'does not exist.';
|
---|
| 373 | this.logger.warn(`ERROR! ${eventPath} ${desc}.`);
|
---|
| 374 | break;
|
---|
| 375 | case 'update':
|
---|
| 376 | loggingQueue.push(core_1.tags.oneLine `
|
---|
| 377 | ${color_1.colors.cyan('UPDATE')} ${eventPath} (${event.content.length} bytes)
|
---|
| 378 | `);
|
---|
| 379 | break;
|
---|
| 380 | case 'create':
|
---|
| 381 | loggingQueue.push(core_1.tags.oneLine `
|
---|
| 382 | ${color_1.colors.green('CREATE')} ${eventPath} (${event.content.length} bytes)
|
---|
| 383 | `);
|
---|
| 384 | break;
|
---|
| 385 | case 'delete':
|
---|
| 386 | loggingQueue.push(`${color_1.colors.yellow('DELETE')} ${eventPath}`);
|
---|
| 387 | break;
|
---|
| 388 | case 'rename':
|
---|
| 389 | const eventToPath = event.to.startsWith('/') ? event.to.substr(1) : event.to;
|
---|
| 390 | loggingQueue.push(`${color_1.colors.blue('RENAME')} ${eventPath} => ${eventToPath}`);
|
---|
| 391 | break;
|
---|
| 392 | }
|
---|
| 393 | });
|
---|
| 394 | workflow.lifeCycle.subscribe((event) => {
|
---|
| 395 | if (event.kind == 'end' || event.kind == 'post-tasks-start') {
|
---|
| 396 | if (!error) {
|
---|
| 397 | // Output the logging queue, no error happened.
|
---|
| 398 | loggingQueue.forEach((log) => this.logger.info(log));
|
---|
| 399 | }
|
---|
| 400 | loggingQueue = [];
|
---|
| 401 | error = false;
|
---|
| 402 | }
|
---|
| 403 | });
|
---|
| 404 | // Temporary compatibility check for NPM 7
|
---|
| 405 | if (collectionName === '@schematics/angular' && schematicName === 'ng-new') {
|
---|
| 406 | if (!input.skipInstall &&
|
---|
| 407 | (input.packageManager === undefined || input.packageManager === 'npm')) {
|
---|
| 408 | await package_manager_1.ensureCompatibleNpm(this.context.root);
|
---|
| 409 | }
|
---|
| 410 | }
|
---|
| 411 | return new Promise((resolve) => {
|
---|
| 412 | workflow
|
---|
| 413 | .execute({
|
---|
| 414 | collection: collectionName,
|
---|
| 415 | schematic: schematicName,
|
---|
| 416 | options: input,
|
---|
| 417 | debug: debug,
|
---|
| 418 | logger: this.logger,
|
---|
| 419 | allowPrivate: this.allowPrivateSchematics,
|
---|
| 420 | })
|
---|
| 421 | .subscribe({
|
---|
| 422 | error: (err) => {
|
---|
| 423 | // In case the workflow was not successful, show an appropriate error message.
|
---|
| 424 | if (err instanceof schematics_1.UnsuccessfulWorkflowExecution) {
|
---|
| 425 | // "See above" because we already printed the error.
|
---|
| 426 | this.logger.fatal('The Schematic workflow failed. See above.');
|
---|
| 427 | }
|
---|
| 428 | else if (debug) {
|
---|
| 429 | this.logger.fatal(`An error occurred:\n${err.message}\n${err.stack}`);
|
---|
| 430 | }
|
---|
| 431 | else {
|
---|
| 432 | this.logger.fatal(err.message);
|
---|
| 433 | }
|
---|
| 434 | resolve(1);
|
---|
| 435 | },
|
---|
| 436 | complete: () => {
|
---|
| 437 | const showNothingDone = !(options.showNothingDone === false);
|
---|
| 438 | if (nothingDone && showNothingDone) {
|
---|
| 439 | this.logger.info('Nothing to be done.');
|
---|
| 440 | }
|
---|
| 441 | if (dryRun) {
|
---|
| 442 | this.logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
|
---|
| 443 | }
|
---|
| 444 | resolve();
|
---|
| 445 | },
|
---|
| 446 | });
|
---|
| 447 | });
|
---|
| 448 | }
|
---|
| 449 | async parseFreeFormArguments(schematicOptions) {
|
---|
| 450 | return parser_1.parseFreeFormArguments(schematicOptions);
|
---|
| 451 | }
|
---|
| 452 | async parseArguments(schematicOptions, options) {
|
---|
| 453 | return parser_1.parseArguments(schematicOptions, options, this.logger);
|
---|
| 454 | }
|
---|
| 455 | }
|
---|
| 456 | exports.SchematicCommand = SchematicCommand;
|
---|
| 457 | function getProjectsByPath(workspace, path, root) {
|
---|
| 458 | if (workspace.projects.size === 1) {
|
---|
| 459 | return Array.from(workspace.projects.keys());
|
---|
| 460 | }
|
---|
| 461 | const isInside = (base, potential) => {
|
---|
| 462 | const absoluteBase = systemPath.resolve(root, base);
|
---|
| 463 | const absolutePotential = systemPath.resolve(root, potential);
|
---|
| 464 | const relativePotential = systemPath.relative(absoluteBase, absolutePotential);
|
---|
| 465 | if (!relativePotential.startsWith('..') && !systemPath.isAbsolute(relativePotential)) {
|
---|
| 466 | return true;
|
---|
| 467 | }
|
---|
| 468 | return false;
|
---|
| 469 | };
|
---|
| 470 | const projects = Array.from(workspace.projects.entries())
|
---|
| 471 | .map(([name, project]) => [systemPath.resolve(root, project.root), name])
|
---|
| 472 | .filter((tuple) => isInside(tuple[0], path))
|
---|
| 473 | // Sort tuples by depth, with the deeper ones first. Since the first member is a path and
|
---|
| 474 | // we filtered all invalid paths, the longest will be the deepest (and in case of equality
|
---|
| 475 | // the sort is stable and the first declared project will win).
|
---|
| 476 | .sort((a, b) => b[0].length - a[0].length);
|
---|
| 477 | if (projects.length === 1) {
|
---|
| 478 | return [projects[0][1]];
|
---|
| 479 | }
|
---|
| 480 | else if (projects.length > 1) {
|
---|
| 481 | const firstPath = projects[0][0];
|
---|
| 482 | return projects.filter((v) => v[0] === firstPath).map((v) => v[1]);
|
---|
| 483 | }
|
---|
| 484 | return [];
|
---|
| 485 | }
|
---|