From 2a2f20af34f9cee4cb9da4f690e9bae91835a6a6 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 24 May 2022 11:59:19 +0000 Subject: [PATCH] fix(@angular/cli): handle format `path` in invoked schematics With this change we change the how we handle `"format": "path"` schematic property option. Previously, in version 14 this format was only being applied on parent schematics that were registered as commands. With this change we apply the formatter on all options, even those who are called programmatically using APIs like `externalSchematic`. --- .../cli/src/command-builder/command-module.ts | 10 +------ .../schematics-command-module.ts | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/packages/angular/cli/src/command-builder/command-module.ts b/packages/angular/cli/src/command-builder/command-module.ts index 5de4e4e43741..0ca5b12a742b 100644 --- a/packages/angular/cli/src/command-builder/command-module.ts +++ b/packages/angular/cli/src/command-builder/command-module.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import { analytics, logging, normalize, schema, strings } from '@angular-devkit/core'; +import { analytics, logging, schema, strings } from '@angular-devkit/core'; import { readFileSync } from 'fs'; import * as path from 'path'; import { @@ -197,8 +197,6 @@ export abstract class CommandModule implements CommandModuleI * **Note:** This method should be called from the command bundler method. */ protected addSchemaOptionsToCommand(localYargs: Argv, options: Option[]): Argv { - const workingDir = normalize(path.relative(this.context.root, process.cwd())); - for (const option of options) { const { default: defaultVal, @@ -211,7 +209,6 @@ export abstract class CommandModule implements CommandModuleI hidden, name, choices, - format, } = option; const sharedOptions: YargsOptions & PositionalOptions = { @@ -224,11 +221,6 @@ export abstract class CommandModule implements CommandModuleI ...(this.context.args.options.help ? { default: defaultVal } : {}), }; - // Special case for schematics - if (workingDir && format === 'path' && name === 'path' && hidden) { - sharedOptions.default = workingDir; - } - if (positional === undefined) { localYargs = localYargs.option(strings.dasherize(name), { type, diff --git a/packages/angular/cli/src/command-builder/schematics-command-module.ts b/packages/angular/cli/src/command-builder/schematics-command-module.ts index ec371fe228ee..3c8aaa7fe585 100644 --- a/packages/angular/cli/src/command-builder/schematics-command-module.ts +++ b/packages/angular/cli/src/command-builder/schematics-command-module.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import { schema, tags } from '@angular-devkit/core'; +import { normalize as devkitNormalize, isJsonObject, schema, tags } from '@angular-devkit/core'; import { Collection, UnsuccessfulWorkflowExecution, formats } from '@angular-devkit/schematics'; import { FileSystemCollectionDescription, @@ -14,7 +14,7 @@ import { NodeWorkflow, } from '@angular-devkit/schematics/tools'; import type { CheckboxQuestion, Question } from 'inquirer'; -import { resolve } from 'path'; +import { relative, resolve } from 'path'; import { Argv } from 'yargs'; import { getProjectByCwd, getSchematicDefaults } from '../utilities/config'; import { memoize } from '../utilities/memoize'; @@ -137,6 +137,8 @@ export abstract class SchematicsCommandModule workflow.registry.useXDeprecatedProvider((msg) => logger.warn(msg)); let shouldReportAnalytics = true; + const workingDir = devkitNormalize(relative(this.context.root, process.cwd())); + workflow.engineHost.registerOptionsTransform(async (schematic, options) => { if (shouldReportAnalytics) { shouldReportAnalytics = false; @@ -150,6 +152,30 @@ export abstract class SchematicsCommandModule ]); } + // Handle `"format": "path"` options. + const schema = schematic?.schemaJson; + if (!options || workingDir === '' || !schema || !isJsonObject(schema)) { + return options; + } + + if (!('path' in options && (options as Record)['path'] === undefined)) { + return options; + } + + const properties = schema?.['properties']; + if (!properties || !isJsonObject(properties)) { + return options; + } + + const property = properties['path']; + if (!property || !isJsonObject(property)) { + return options; + } + + if (property['format'] === 'path') { + (options as Record)['path'] = workingDir; + } + return options; });