Skip to content
Open
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
46 changes: 24 additions & 22 deletions packages/angular/cli/src/command-builder/command-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
*/

import { schema } from '@angular-devkit/core';
import { readFileSync } from 'node:fs';
import { join, posix, relative } from 'node:path';
import type { ArgumentsCamelCase, Argv, CommandModule as YargsCommandModule } from 'yargs';
import { Parser as yargsParser } from 'yargs/helpers';
import { getAnalyticsUserId } from '../analytics/analytics';
Expand All @@ -20,6 +18,7 @@ import { AngularWorkspace } from '../utilities/config';
import { memoize } from '../utilities/memoize';
import { CommandContext, CommandScope, Options, OtherOptions } from './definitions';
import { Option, addSchemaOptionsToCommand } from './utilities/json-schema';
import '../utilities/markdown-loader';

export { CommandScope };
export type { CommandContext, Options, OtherOptions };
Expand All @@ -31,8 +30,11 @@ export interface CommandModuleImplementation<T extends {} = {}> extends Omit<
/** Scope in which the command can be executed in. */
scope: CommandScope;

/** Path used to load the long description for the command in JSON help text. */
longDescriptionPath?: string;
/** Long description for the command in JSON help text. */
longDescription?: string;

/** Relative path to the long description file for the command in JSON help text. */
longDescriptionRelativePath?: string;

/** Object declaring the options the command accepts, or a function accepting and returning a yargs instance. */
builder(argv: Argv): Promise<Argv<T>> | Argv<T>;
Expand All @@ -50,7 +52,8 @@ export interface FullDescribe {
export abstract class CommandModule<T extends {} = {}> implements CommandModuleImplementation<T> {
abstract readonly command: string;
abstract readonly describe: string | false;
abstract readonly longDescriptionPath?: string;
readonly longDescription?: string;
readonly longDescriptionRelativePath?: string;
protected readonly shouldReportAnalytics: boolean = true;
readonly scope: CommandScope = CommandScope.Both;

Expand All @@ -68,23 +71,22 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
* `false` will result in a hidden command.
*/
public get fullDescribe(): FullDescribe | false {
return this.describe === false
? false
: {
describe: this.describe,
...(this.longDescriptionPath
? {
longDescriptionRelativePath: relative(
join(__dirname, '../../../../'),
this.longDescriptionPath,
).replace(/\\/g, posix.sep),
longDescription: readFileSync(this.longDescriptionPath, 'utf8').replace(
/\r\n/g,
'\n',
),
}
: {}),
};
if (this.describe === false) {
return false;
}

const description: FullDescribe = {
describe: this.describe,
};

if (this.longDescription) {
description.longDescription = this.longDescription.replace(/\r\n/g, '\n');
description.longDescriptionRelativePath =
this.longDescriptionRelativePath ??
`@angular/cli/src/commands/${this.commandName}/long-description.md`;
}

return description;
}

protected get commandName(): string {
Expand Down
5 changes: 4 additions & 1 deletion packages/angular/cli/src/commands/add/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import { NgAddSaveDependency, PackageManifest, PackageMetadata } from '../../pac
import { assertIsError } from '../../utilities/error';
import { isTTY } from '../../utilities/tty';
import { VERSION } from '../../utilities/version';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

class CommandError extends Error {}

Expand Down Expand Up @@ -100,7 +103,7 @@ export default class AddCommandModule
{
command = 'add <collection>';
describe = 'Adds support for an external library to your project.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;
protected override allowPrivateSchematics = true;
private readonly schematicName = 'ng-add';
private rootRequire = createRequire(this.context.root + '/');
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/analytics/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { Argv } from 'yargs';
import {
CommandModule,
Expand All @@ -18,6 +17,9 @@ import {
demandCommandFailureMessage,
} from '../../command-builder/utilities/command';
import { AnalyticsInfoCommandModule } from './info/cli';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';
import {
AnalyticsDisableModule,
AnalyticsEnableModule,
Expand All @@ -30,7 +32,7 @@ export default class AnalyticsCommandModule
{
command = 'analytics';
describe = 'Configures the gathering of Angular CLI usage metrics.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;

builder(localYargs: Argv): Argv {
const subcommands = [
Expand Down
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/analytics/info/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export class AnalyticsInfoCommandModule
{
command = 'info';
describe = 'Prints analytics gathering and reporting configuration in the console.';
longDescriptionPath?: string;

builder(localYargs: Argv): Argv {
return localYargs.strict();
Expand Down
2 changes: 0 additions & 2 deletions packages/angular/cli/src/commands/analytics/settings/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ abstract class AnalyticsSettingModule
extends CommandModule<AnalyticsCommandArgs>
implements CommandModuleImplementation<AnalyticsCommandArgs>
{
longDescriptionPath?: string;

builder(localYargs: Argv): Argv<AnalyticsCommandArgs> {
return localYargs
.option('global', {
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/build/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { ArchitectCommandModule } from '../../command-builder/architect-command-module';
import { CommandModuleImplementation } from '../../command-builder/command-module';
import { RootCommands } from '../command-config';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

export default class BuildCommandModule
extends ArchitectCommandModule
Expand All @@ -20,5 +22,5 @@ export default class BuildCommandModule
aliases = RootCommands['build'].aliases;
describe =
'Compiles an Angular application or library into an output directory named dist/ at the given output path.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;
}
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/cache/clean/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { getCacheConfig } from '../utilities';
export class CacheCleanModule extends CommandModule implements CommandModuleImplementation {
command = 'clean';
describe = 'Deletes persistent disk cache from disk.';
longDescriptionPath: string | undefined;
override scope = CommandScope.In;

builder(localYargs: Argv): Argv {
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/cache/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { Argv } from 'yargs';
import {
CommandModule,
Expand All @@ -20,6 +19,9 @@ import {
} from '../../command-builder/utilities/command';
import { CacheCleanModule } from './clean/cli';
import { CacheInfoCommandModule } from './info/cli';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';
import { CacheDisableModule, CacheEnableModule } from './settings/cli';

export default class CacheCommandModule
Expand All @@ -28,7 +30,7 @@ export default class CacheCommandModule
{
command = 'cache';
describe = 'Configure persistent disk cache and retrieve cache statistics.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;
override scope = CommandScope.In;

builder(localYargs: Argv): Argv {
Expand Down
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/cache/info/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { getCacheConfig } from '../utilities';
export class CacheInfoCommandModule extends CommandModule implements CommandModuleImplementation {
command = 'info';
describe = 'Prints persistent disk cache configuration and statistics in the console.';
longDescriptionPath?: string | undefined;
override scope = CommandScope.In;

builder(localYargs: Argv): Argv {
Expand Down
2 changes: 0 additions & 2 deletions packages/angular/cli/src/commands/cache/settings/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export class CacheDisableModule extends CommandModule implements CommandModuleIm
command = 'disable';
aliases = 'off';
describe = 'Disables persistent disk cache for all projects in the workspace.';
longDescriptionPath: string | undefined;
override scope = CommandScope.In;

builder(localYargs: Argv): Argv {
Expand All @@ -34,7 +33,6 @@ export class CacheEnableModule extends CommandModule implements CommandModuleImp
command = 'enable';
aliases = 'on';
describe = 'Enables disk cache for all projects in the workspace.';
longDescriptionPath: string | undefined;
override scope = CommandScope.In;

builder(localYargs: Argv): Argv {
Expand Down
7 changes: 4 additions & 3 deletions packages/angular/cli/src/commands/completion/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation } from '../../command-builder/command-module';
import { addCommandModuleToYargs } from '../../command-builder/utilities/command';
import { colors } from '../../utilities/color';
import { hasGlobalCliInstall, initializeAutocomplete } from '../../utilities/completion';
import { assertIsError } from '../../utilities/error';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

export default class CompletionCommandModule
extends CommandModule
implements CommandModuleImplementation
{
command = 'completion';
describe = 'Set up Angular CLI autocompletion for your terminal.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;

builder(localYargs: Argv): Argv {
addCommandModuleToYargs(CompletionScriptCommandModule, this.context);
Expand Down Expand Up @@ -64,7 +66,6 @@ Appended \`source <(ng completion script)\` to \`${rcFile}\`. Restart your termi
class CompletionScriptCommandModule extends CommandModule implements CommandModuleImplementation {
command = 'script';
describe = 'Generate a bash and zsh real-time type-ahead autocompletion script.';
longDescriptionPath = undefined;

builder(localYargs: Argv): Argv {
return localYargs;
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/config/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import { JsonValue } from '@angular-devkit/core';
import { randomUUID } from 'node:crypto';
import { join } from 'node:path';
import { Argv } from 'yargs';
import {
CommandModule,
Expand All @@ -18,6 +17,9 @@ import {
} from '../../command-builder/command-module';
import { getWorkspaceRaw, validateWorkspace } from '../../utilities/config';
import { JSONFile, parseJson } from '../../utilities/json-file';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

interface ConfigCommandArgs {
'json-path'?: string;
Expand All @@ -32,7 +34,7 @@ export default class ConfigCommandModule
command = 'config [json-path] [value]';
describe =
'Retrieves or sets Angular configuration values in the angular.json file for the workspace.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;

builder(localYargs: Argv): Argv<ConfigCommandArgs> {
return localYargs
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/deploy/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { MissingTargetChoice } from '../../command-builder/architect-base-command-module';
import { ArchitectCommandModule } from '../../command-builder/architect-command-module';
import { CommandModuleImplementation } from '../../command-builder/command-module';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

export default class DeployCommandModule
extends ArchitectCommandModule
Expand Down Expand Up @@ -37,7 +39,7 @@ export default class DeployCommandModule

multiTarget = false;
command = 'deploy [project]';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;
describe =
'Invokes the deploy builder for a specified project or for the default project in the workspace.';
}
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/e2e/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@ export default class E2eCommandModule
command = 'e2e [project]';
aliases = RootCommands['e2e'].aliases;
describe = 'Builds and serves an Angular application, then runs end-to-end tests.';
longDescriptionPath?: string;
}
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/extract-i18n/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export default class ExtractI18nCommandModule
multiTarget = false;
command = 'extract-i18n [project]';
describe = 'Extracts i18n messages from source code.';
longDescriptionPath?: string | undefined;

override async findDefaultBuilderName(
project: workspaces.ProjectDefinition,
Expand Down
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/generate/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export default class GenerateCommandModule
command = 'generate';
aliases = RootCommands['generate'].aliases;
describe = 'Generates and/or modifies files based on a schematic.';
longDescriptionPath?: string | undefined;

override async builder(argv: Argv): Promise<Argv<GenerateCommandArgs>> {
let localYargs = (await super.builder(argv)).command({
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/lint/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { MissingTargetChoice } from '../../command-builder/architect-base-command-module';
import { ArchitectCommandModule } from '../../command-builder/architect-command-module';
import { CommandModuleImplementation } from '../../command-builder/command-module';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

export default class LintCommandModule
extends ArchitectCommandModule
Expand All @@ -24,6 +26,6 @@ export default class LintCommandModule

multiTarget = true;
command = 'lint [project]';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;
describe = 'Runs linting tools on Angular application code in a given project folder.';
}
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/make-this-awesome/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default class AwesomeCommandModule
command = 'make-this-awesome';
describe = false as const;
deprecated = false;
longDescriptionPath?: string | undefined;

builder(localYargs: Argv): Argv {
return localYargs;
Expand Down
1 change: 0 additions & 1 deletion packages/angular/cli/src/commands/mcp/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ For more information and documentation, visit: https://angular.dev/ai/mcp
export default class McpCommandModule extends CommandModule implements CommandModuleImplementation {
command = 'mcp';
describe = false as const;
longDescriptionPath = undefined;

builder(localYargs: Argv): Argv {
return localYargs
Expand Down
6 changes: 4 additions & 2 deletions packages/angular/cli/src/commands/new/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { join } from 'node:path';
import { Argv } from 'yargs';
import {
CommandModuleImplementation,
Expand All @@ -21,6 +20,9 @@ import {
} from '../../command-builder/schematics-command-module';
import { VERSION } from '../../utilities/version';
import { RootCommands } from '../command-config';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore strict-deps: Markdown files are asset dependencies bundled/loaded at runtime
import longDescription from './long-description.md';

interface NewCommandArgs extends SchematicsCommandArgs {
collection?: string;
Expand All @@ -37,7 +39,7 @@ export default class NewCommandModule
command = 'new [name]';
aliases = RootCommands['new'].aliases;
describe = 'Creates a new Angular workspace.';
longDescriptionPath = join(__dirname, 'long-description.md');
override longDescription = longDescription;

override async builder(argv: Argv): Promise<Argv<NewCommandArgs>> {
const localYargs = (await super.builder(argv)).option('collection', {
Expand Down
Loading