Skip to content

Commit 387472a

Browse files
committed
fix(@angular/cli): register schematic aliases when providing collection name in ng generate
Previously, schematic aliases were not registered when a collection name was provided to `ng generate`. Example: `ng generate c` where `c` is an alias for `component` would work, but `ng generate @schematics/angular:c` would fail. This commits fixes the schematic registration to handle the latter case. Closes #24518 (cherry picked from commit 3ebb195)
1 parent b000481 commit 387472a

File tree

2 files changed

+65
-16
lines changed

2 files changed

+65
-16
lines changed

packages/angular/cli/src/commands/generate/cli.ts

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ export class GenerateCommandModule
7979
// When 'describe' is set to false, it results in a hidden command.
8080
describe: hidden === true ? false : typeof description === 'string' ? description : '',
8181
deprecated: xDeprecated === true || typeof xDeprecated === 'string' ? xDeprecated : false,
82-
aliases: Array.isArray(aliases) ? (aliases as string[]) : undefined,
82+
aliases: Array.isArray(aliases)
83+
? await this.generateCommandAliasesStrings(collectionName, aliases as string[])
84+
: undefined,
8385
builder: (localYargs) => this.addSchemaOptionsToCommand(localYargs, options).strict(),
8486
handler: (options) =>
8587
this.handler({ ...options, schematic: `${collectionName}:${schematicName}` }),
@@ -120,6 +122,41 @@ export class GenerateCommandModule
120122
return collectionName ? [collectionName] : [...(await this.getSchematicCollections())];
121123
}
122124

125+
private async shouldAddCollectionNameAsPartOfCommand(): Promise<boolean> {
126+
const [collectionNameFromArgs] = this.parseSchematicInfo(
127+
// positional = [generate, component] or [generate]
128+
this.context.args.positional[1],
129+
);
130+
131+
const schematicCollectionsFromConfig = await this.getSchematicCollections();
132+
const collectionNames = await this.getCollectionNames();
133+
134+
// Only add the collection name as part of the command when it's not a known
135+
// schematics collection or when it has been provided via the CLI.
136+
// Ex:`ng generate @schematics/angular:c`
137+
return (
138+
!!collectionNameFromArgs ||
139+
!collectionNames.some((c) => schematicCollectionsFromConfig.has(c))
140+
);
141+
}
142+
143+
/**
144+
* Generate an aliases string array to be passed to the command builder.
145+
*
146+
* @example `[component]` or `[@schematics/angular:component]`.
147+
*/
148+
private async generateCommandAliasesStrings(
149+
collectionName: string,
150+
schematicAliases: string[],
151+
): Promise<string[]> {
152+
// Only add the collection name as part of the command when it's not a known
153+
// schematics collection or when it has been provided via the CLI.
154+
// Ex:`ng generate @schematics/angular:c`
155+
return (await this.shouldAddCollectionNameAsPartOfCommand())
156+
? schematicAliases.map((alias) => `${collectionName}:${alias}`)
157+
: schematicAliases;
158+
}
159+
123160
/**
124161
* Generate a command string to be passed to the command builder.
125162
*
@@ -130,23 +167,14 @@ export class GenerateCommandModule
130167
schematicName: string,
131168
options: Option[],
132169
): Promise<string> {
133-
const [collectionNameFromArgs] = this.parseSchematicInfo(
134-
// positional = [generate, component] or [generate]
135-
this.context.args.positional[1],
136-
);
137-
138170
const dasherizedSchematicName = strings.dasherize(schematicName);
139-
const schematicCollectionsFromConfig = await this.getSchematicCollections();
140-
const collectionNames = await this.getCollectionNames();
141171

142172
// Only add the collection name as part of the command when it's not a known
143173
// schematics collection or when it has been provided via the CLI.
144174
// Ex:`ng generate @schematics/angular:component`
145-
const commandName =
146-
!!collectionNameFromArgs ||
147-
!collectionNames.some((c) => schematicCollectionsFromConfig.has(c))
148-
? collectionName + ':' + dasherizedSchematicName
149-
: dasherizedSchematicName;
175+
const commandName = (await this.shouldAddCollectionNameAsPartOfCommand())
176+
? collectionName + ':' + dasherizedSchematicName
177+
: dasherizedSchematicName;
150178

151179
const positionalArgs = options
152180
.filter((o) => o.positional !== undefined)
@@ -165,6 +193,7 @@ export class GenerateCommandModule
165193
*/
166194
private async *getSchematics(): AsyncGenerator<{
167195
schematicName: string;
196+
schematicAliases?: Set<string>;
168197
collectionName: string;
169198
}> {
170199
const seenNames = new Set<string>();
@@ -176,7 +205,10 @@ export class GenerateCommandModule
176205
// If a schematic with this same name is already registered skip.
177206
if (!seenNames.has(schematicName)) {
178207
seenNames.add(schematicName);
179-
yield { schematicName, collectionName };
208+
const { aliases } = collection.description.schematics[schematicName];
209+
const schematicAliases = aliases && new Set(aliases);
210+
211+
yield { schematicName, schematicAliases, collectionName };
180212
}
181213
}
182214
}
@@ -196,8 +228,11 @@ export class GenerateCommandModule
196228
this.context.args.positional[1],
197229
);
198230

199-
for await (const { schematicName, collectionName } of this.getSchematics()) {
200-
if (schematicName === schematicNameFromArgs) {
231+
for await (const { schematicName, collectionName, schematicAliases } of this.getSchematics()) {
232+
if (
233+
schematicNameFromArgs &&
234+
(schematicName === schematicNameFromArgs || schematicAliases?.has(schematicNameFromArgs))
235+
) {
201236
return [[schematicName, collectionName]];
202237
}
203238

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ng } from '../../utils/process';
2+
3+
export default async function () {
4+
const schematicNameVariation = [
5+
'component',
6+
'c',
7+
'@schematics/angular:component',
8+
'@schematics/angular:c',
9+
];
10+
11+
for (const schematic of schematicNameVariation) {
12+
await ng('generate', schematic, 'comp-name', '--display-block', '--dry-run');
13+
}
14+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy