Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/angular/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"pacote": "21.0.0",
"resolve": "1.22.10",
"semver": "7.7.2",
"yargs": "17.7.2"
"yargs": "18.0.0"
},
"ng-update": {
"migrations": "@schematics/angular/migrations/migration-collection.json",
Expand Down
4 changes: 2 additions & 2 deletions packages/angular/cli/src/command-builder/command-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import { logging, schema } from '@angular-devkit/core';
import { readFileSync } from 'node:fs';
import * as path from 'node:path';
import yargs from 'yargs';
import type {
ArgumentsCamelCase,
Argv,
Expand Down Expand Up @@ -47,6 +46,7 @@ export interface CommandContext {
globalConfiguration: AngularWorkspace;
logger: logging.Logger;
packageManager: PackageManagerUtils;
yargsInstance: Argv<{}>;

/** Arguments parsed in free-from without parser configuration. */
args: {
Expand Down Expand Up @@ -250,7 +250,7 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI

private reportCommandRunAnalytics(analytics: AnalyticsCollector): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const internalMethods = (yargs as any).getInternalMethods();
const internalMethods = (this.context.yargsInstance as any).getInternalMethods();
// $0 generate component [name] -> generate_component
// $0 add <collection> -> add
const fullCommand = (internalMethods.getUsageInstance().getUsage()[0][0] as string)
Expand Down
12 changes: 7 additions & 5 deletions packages/angular/cli/src/command-builder/command-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
demandCommandFailureMessage,
} from './utilities/command';
import { jsonHelpUsage } from './utilities/json-help';
import { normalizeOptionsMiddleware } from './utilities/normalize-options-middleware';
import { createNormalizeOptionsMiddleware } from './utilities/normalize-options-middleware';

const yargsParser = Parser as unknown as typeof Parser.default;

Expand Down Expand Up @@ -62,11 +62,14 @@ export async function runCommand(args: string[], logger: logging.Logger): Promis
}

const root = workspace?.basePath ?? process.cwd();
const localYargs = yargs(args);

const context: CommandContext = {
globalConfiguration,
workspace,
logger,
currentDirectory: process.cwd(),
yargsInstance: localYargs,
root,
packageManager: new PackageManagerUtils({ globalConfiguration, workspace, root }),
args: {
Expand All @@ -80,15 +83,14 @@ export async function runCommand(args: string[], logger: logging.Logger): Promis
},
};

let localYargs = yargs(args);
for (const CommandModule of await getCommandsToRegister(positional[0])) {
localYargs = addCommandModuleToYargs(localYargs, CommandModule, context);
addCommandModuleToYargs(CommandModule, context);
}

if (jsonHelp) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const usageInstance = (localYargs as any).getInternalMethods().getUsageInstance();
usageInstance.help = () => jsonHelpUsage();
usageInstance.help = () => jsonHelpUsage(localYargs);
}

// Add default command to support version option when no subcommand is specified
Expand Down Expand Up @@ -127,7 +129,7 @@ export async function runCommand(args: string[], logger: logging.Logger): Promis
.epilogue('For more information, see https://angular.dev/cli/.\n')
.demandCommand(1, demandCommandFailureMessage)
.recommendCommands()
.middleware(normalizeOptionsMiddleware)
.middleware(createNormalizeOptionsMiddleware(localYargs))
.version(false)
.showHelpOnFail(false)
.strict()
Expand Down
9 changes: 4 additions & 5 deletions packages/angular/cli/src/command-builder/utilities/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ export type CommandModuleConstructor = Partial<CommandModuleImplementation> & {
new (context: CommandContext): Partial<CommandModuleImplementation> & CommandModule;
};

export function addCommandModuleToYargs<T extends object, U extends CommandModuleConstructor>(
localYargs: Argv<T>,
export function addCommandModuleToYargs<U extends CommandModuleConstructor>(
commandModule: U,
context: CommandContext,
): Argv<T> {
): void {
const cmd = new commandModule(context);
const {
args: {
Expand All @@ -35,7 +34,7 @@ export function addCommandModuleToYargs<T extends object, U extends CommandModul

const describe = jsonHelp ? cmd.fullDescribe : cmd.describe;

return localYargs.command({
context.yargsInstance.command({
command: cmd.command,
aliases: cmd.aliases,
describe:
Expand All @@ -58,7 +57,7 @@ export function addCommandModuleToYargs<T extends object, U extends CommandModul
);
}

return cmd.builder(argv) as Argv<T>;
return cmd.builder(argv) as Argv;
},
handler: (args) => cmd.handler(args),
});
Expand Down
14 changes: 7 additions & 7 deletions packages/angular/cli/src/command-builder/utilities/json-help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import yargs from 'yargs';
import { Argv } from 'yargs';
import { FullDescribe } from '../command-module';

interface JsonHelpOption {
Expand Down Expand Up @@ -42,9 +42,9 @@ export interface JsonHelp extends JsonHelpDescription {

const yargsDefaultCommandRegExp = /^\$0|\*/;

export function jsonHelpUsage(): string {
export function jsonHelpUsage(localYargs: Argv): string {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const localYargs = yargs as any;
const localYargsInstance = localYargs as any;
const {
deprecatedOptions,
alias: aliases,
Expand All @@ -56,13 +56,13 @@ export function jsonHelpUsage(): string {
demandedOptions,
default: defaultVal,
hiddenOptions = [],
} = localYargs.getOptions();
} = localYargsInstance.getOptions();

const internalMethods = localYargs.getInternalMethods();
const internalMethods = localYargsInstance.getInternalMethods();
const usageInstance = internalMethods.getUsageInstance();
const context = internalMethods.getContext();
const descriptions = usageInstance.getDescriptions();
const groups = localYargs.getGroups();
const groups = localYargsInstance.getGroups();
const positional = groups[usageInstance.getPositionalGroupName()] as string[] | undefined;

const hidden = new Set(hiddenOptions);
Expand Down Expand Up @@ -124,7 +124,7 @@ export function jsonHelpUsage(): string {

const output: JsonHelp = {
name: [...context.commands].pop(),
command: `${command?.replace(yargsDefaultCommandRegExp, localYargs['$0'])}${defaultSubCommand}`,
command: `${command?.replace(yargsDefaultCommandRegExp, localYargsInstance['$0'])}${defaultSubCommand}`,
...parseDescription(rawDescription),
options: normalizeOptions.sort((a, b) => a.name.localeCompare(b.name)),
subcommands: otherSubcommands.length ? otherSubcommands : undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import * as yargs from 'yargs';
import type { Arguments, Argv } from 'yargs';

/**
* A Yargs middleware that normalizes non Array options when the argument has been provided multiple times.
Expand All @@ -17,21 +17,23 @@ import * as yargs from 'yargs';
*
* See: https://github.com/yargs/yargs-parser/pull/163#issuecomment-516566614
*/
export function normalizeOptionsMiddleware(args: yargs.Arguments): void {
// `getOptions` is not included in the types even though it's public API.
// https://github.com/yargs/yargs/issues/2098
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { array } = (yargs as any).getOptions();
const arrayOptions = new Set(array);
export function createNormalizeOptionsMiddleware(localeYargs: Argv): (args: Arguments) => void {
return (args: Arguments) => {
// `getOptions` is not included in the types even though it's public API.
// https://github.com/yargs/yargs/issues/2098
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { array } = (localeYargs as any).getOptions();
const arrayOptions = new Set(array);

for (const [key, value] of Object.entries(args)) {
if (key !== '_' && Array.isArray(value) && !arrayOptions.has(key)) {
const newValue = value.pop();
// eslint-disable-next-line no-console
console.warn(
`Option '${key}' has been specified multiple times. The value '${newValue}' will be used.`,
);
args[key] = newValue;
for (const [key, value] of Object.entries(args)) {
if (key !== '_' && Array.isArray(value) && !arrayOptions.has(key)) {
const newValue = value.pop();
// eslint-disable-next-line no-console
console.warn(
`Option '${key}' has been specified multiple times. The value '${newValue}' will be used.`,
);
args[key] = newValue;
}
}
}
};
}
2 changes: 1 addition & 1 deletion packages/angular/cli/src/commands/analytics/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class AnalyticsCommandModule
].sort(); // sort by class name.

for (const module of subcommands) {
localYargs = addCommandModuleToYargs(localYargs, module, this.context);
addCommandModuleToYargs(module, this.context);
}

return localYargs.demandCommand(1, demandCommandFailureMessage).strict();
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/cli/src/commands/cache/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default class CacheCommandModule
].sort();

for (const module of subcommands) {
localYargs = addCommandModuleToYargs(localYargs, module, this.context);
addCommandModuleToYargs(module, this.context);
}

return localYargs.demandCommand(1, demandCommandFailureMessage).strict();
Expand Down
8 changes: 5 additions & 3 deletions packages/angular/cli/src/commands/completion/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { join } from 'node:path';
import yargs, { Argv } from 'yargs';
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation } from '../../command-builder/command-module';
import { addCommandModuleToYargs } from '../../command-builder/utilities/command';
import { colors } from '../../utilities/color';
Expand All @@ -23,7 +23,9 @@ export default class CompletionCommandModule
longDescriptionPath = join(__dirname, 'long-description.md');

builder(localYargs: Argv): Argv {
return addCommandModuleToYargs(localYargs, CompletionScriptCommandModule, this.context);
addCommandModuleToYargs(CompletionScriptCommandModule, this.context);

return localYargs;
}

async run(): Promise<number> {
Expand Down Expand Up @@ -69,6 +71,6 @@ class CompletionScriptCommandModule extends CommandModule implements CommandModu
}

run(): void {
yargs.showCompletionScript();
this.context.yargsInstance.showCompletionScript();
}
}
27 changes: 25 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.