Skip to content

Commit

Permalink
feat(@angular/cli): allow commands to reparse options if needed
Browse files Browse the repository at this point in the history
  • Loading branch information
hansl authored and Brocco committed Mar 9, 2018
1 parent 71772fd commit 88fc93f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 28 deletions.
42 changes: 20 additions & 22 deletions packages/@angular/cli/models/command-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
CommandScope
} from '../models/command';
import { oneLine } from 'common-tags';
import { Logger } from '@angular-devkit/core/src/logger';
import { logging } from '@angular-devkit/core';
import { camelize } from '@angular-devkit/core/src/utils/strings';

const yargsParser = require('yargs-parser');
Expand All @@ -19,12 +19,13 @@ export interface CommandMap {
* Run a command.
* @param commandMap Map of available commands.
* @param args Raw unparsed arguments.
* @param logger The logger to use.
* @param context Execution context.
*/
export async function runCommand(commandMap: CommandMap,
args: string[],
logger: Logger,
context: CommandContext): Promise<any> {
args: string[],
logger: logging.Logger,
context: CommandContext): Promise<any> {

const rawOptions = yargsParser(args, { alias: { help: ['h'] }, boolean: [ 'help' ] });
let commandName = rawOptions._[0];
Expand Down Expand Up @@ -55,11 +56,10 @@ export async function runCommand(commandMap: CommandMap,

const command = new Cmd(context, logger);

let options = parseOptions(yargsParser, args, command.options);
options = mapArguments(options, command.arguments);
args = await command.initializeRaw(args);
let options = parseOptions(args, command.options, command.arguments);
await command.initialize(options);
options = parseOptions(yargsParser, args, command.options);
options = mapArguments(options, command.arguments);
options = parseOptions(args, command.options, command.arguments);
if (commandName === 'help') {
options.commandMap = commandMap;
}
Expand All @@ -74,9 +74,13 @@ export async function runCommand(commandMap: CommandMap,
}
}

function parseOptions(parser: Function,
args: string[],
cmdOpts: Option[]): any {
export function parseOptions<T = any>(
args: string[],
cmdOpts: Option[],
commandArguments: string[],
): T {
const parser = yargsParser;

const aliases = cmdOpts.concat()
.filter(o => o.aliases && o.aliases.length > 0)
.reduce((aliases: any, opt: Option) => {
Expand Down Expand Up @@ -131,23 +135,17 @@ function parseOptions(parser: Function,
.filter(key => key.indexOf('-') !== -1)
.forEach(key => delete parsedOptions[key]);

return parsedOptions;
}

// Map arguments to options.
function mapArguments(options: any, args: string[]): any {
const optsWithMappedArgs = {...options};
optsWithMappedArgs._.forEach((value: string, index: number) => {
parsedOptions._.forEach((value: string, index: number) => {
// Remove the starting "<" and trailing ">".
const arg = args[index];
const arg = commandArguments[index];
if (arg) {
optsWithMappedArgs[arg] = value;
parsedOptions[arg] = value;
}
});

delete optsWithMappedArgs._;
delete parsedOptions._;

return optsWithMappedArgs;
return parsedOptions;
}

// Find a command.
Expand Down
15 changes: 9 additions & 6 deletions packages/@angular/cli/models/command.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Logger } from '@angular-devkit/core/src/logger';
import { logging } from '@angular-devkit/core';
const { cyan } = require('chalk');

export interface CommandConstructor {
new(context: CommandContext, logger: Logger): Command;
new(context: CommandContext, logger: logging.Logger): Command;
aliases: string[];
scope: CommandScope.everywhere;
}
Expand All @@ -14,16 +14,19 @@ export enum CommandScope {
}

export abstract class Command {
constructor(context: CommandContext, logger: Logger) {
constructor(context: CommandContext, logger: logging.Logger) {
this.logger = logger;
if (context) {
this.project = context.project;
this.ui = context.ui;
}
}

initialize(_options: any): Promise<void> {
return Promise.resolve();
async initializeRaw(args: any): Promise<any> {
return args;
}
async initialize(_options: any): Promise<void> {
return;
}

validate(_options: any): boolean | Promise<boolean> {
Expand Down Expand Up @@ -68,7 +71,7 @@ export abstract class Command {
public hidden = false;
public unknown = false;
public scope = CommandScope.everywhere;
protected readonly logger: Logger;
protected readonly logger: logging.Logger;
protected readonly project: any;
protected readonly ui: Ui;
}
Expand Down

0 comments on commit 88fc93f

Please sign in to comment.