Skip to content

Commit 2ce1155

Browse files
committed
fix(@angular/cli): allow commandMap as an argument
With a fallback to looking for it from current file.
1 parent a7b9ee5 commit 2ce1155

File tree

1 file changed

+34
-35
lines changed

1 file changed

+34
-35
lines changed

packages/angular/cli/models/command-runner.ts

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import { convertSchemaToOptions, parseSchema } from './json-schema';
3838

3939

4040
export interface CommandMap {
41-
[key: string]: string;
41+
[key: string]: Path;
4242
}
4343

4444
interface CommandMetadata {
@@ -84,9 +84,12 @@ function levenshtein(a: string, b: string): number {
8484
* @param logger The logger to use.
8585
* @param context Execution context.
8686
*/
87-
export async function runCommand(args: string[],
88-
logger: logging.Logger,
89-
context: CommandContext): Promise<number | void> {
87+
export async function runCommand(
88+
args: string[],
89+
logger: logging.Logger,
90+
context: CommandContext,
91+
commandMap?: CommandMap,
92+
): Promise<number | void> {
9093

9194
// if not args supplied, just run the help command.
9295
if (!args || args.length === 0) {
@@ -101,24 +104,31 @@ export async function runCommand(args: string[],
101104
? CommandScope.inProject
102105
: CommandScope.outsideProject;
103106

104-
const commandMapPath = findUp('commands.json', __dirname);
105-
if (commandMapPath === null) {
106-
logger.fatal('Unable to find command map.');
107+
if (commandMap === undefined) {
108+
const commandMapPath = findUp('commands.json', __dirname);
109+
if (commandMapPath === null) {
110+
logger.fatal('Unable to find command map.');
107111

108-
return 1;
112+
return 1;
113+
}
114+
const cliDir = dirname(normalize(commandMapPath));
115+
const commandsText = readFileSync(commandMapPath).toString('utf-8');
116+
const commandJson = JSON.parse(commandsText) as { [name: string]: string };
117+
118+
commandMap = {};
119+
for (const commandName of Object.keys(commandJson)) {
120+
commandMap[commandName] = join(cliDir, commandJson[commandName]);
121+
}
109122
}
110-
const cliDir = dirname(normalize(commandMapPath));
111-
const commandsText = readFileSync(commandMapPath).toString('utf-8');
112-
const commandMap = JSON.parse(commandsText) as CommandMap;
113123

114-
let commandMetadata = commandName ? findCommand(cliDir, commandMap, commandName) : null;
124+
let commandMetadata = commandName ? findCommand(commandMap, commandName) : null;
115125

116126
if (!commandMetadata && (rawOptions.v || rawOptions.version)) {
117127
commandName = 'version';
118-
commandMetadata = findCommand(cliDir, commandMap, commandName);
128+
commandMetadata = findCommand(commandMap, commandName);
119129
} else if (!commandMetadata && rawOptions.help) {
120130
commandName = 'help';
121-
commandMetadata = findCommand(cliDir, commandMap, commandName);
131+
commandMetadata = findCommand(commandMap, commandName);
122132
}
123133

124134
if (!commandMetadata) {
@@ -132,7 +142,7 @@ export async function runCommand(args: string[],
132142
return 1;
133143
} else {
134144
const commandsDistance = {} as { [name: string]: number };
135-
const allCommands = listAllCommandNames(cliDir, commandMap).sort((a, b) => {
145+
const allCommands = Object.keys(commandMap).sort((a, b) => {
136146
if (!(a in commandsDistance)) {
137147
commandsDistance[a] = levenshtein(a, commandName);
138148
}
@@ -153,7 +163,7 @@ export async function runCommand(args: string[],
153163
}
154164
}
155165

156-
const command = await createCommand(cliDir, commandMetadata, context, logger);
166+
const command = await createCommand(commandMetadata, context, logger);
157167
const metadataOptions = await convertSchemaToOptions(commandMetadata.text);
158168
if (command === null) {
159169
logger.error(tags.stripIndent`Command (${commandName}) failed to instantiate.`);
@@ -173,7 +183,7 @@ export async function runCommand(args: string[],
173183
options = parseOptions(args, command.options);
174184

175185
if (commandName === 'help') {
176-
options.commandInfo = getAllCommandInfo(cliDir, commandMap);
186+
options.commandInfo = getAllCommandInfo(commandMap);
177187
}
178188

179189
if (options.help) {
@@ -350,7 +360,7 @@ export function parseOptions(args: string[], optionsAndArguments: Option[]) {
350360
}
351361

352362
// Find a command.
353-
function findCommand(rootDir: Path, map: CommandMap, name: string): CommandLocation | null {
363+
function findCommand(map: CommandMap, name: string): CommandLocation | null {
354364
// let Cmd: CommandConstructor = map[name];
355365
let commandName = name;
356366

@@ -359,8 +369,7 @@ function findCommand(rootDir: Path, map: CommandMap, name: string): CommandLocat
359369
commandName = Object.keys(map)
360370
.filter(key => {
361371
// get aliases for the key
362-
const metadataPath = map[key];
363-
const metadataText = readFileSync(join(rootDir, metadataPath)).toString('utf-8');
372+
const metadataText = readFileSync(map[key]).toString('utf-8');
364373
const metadata = JSON.parse(metadataText);
365374
const aliases = metadata['$aliases'];
366375
if (!aliases) {
@@ -372,12 +381,11 @@ function findCommand(rootDir: Path, map: CommandMap, name: string): CommandLocat
372381
})[0];
373382
}
374383

375-
const relativeMetadataPath = map[commandName];
384+
const metadataPath = map[commandName];
376385

377-
if (!relativeMetadataPath) {
386+
if (!metadataPath) {
378387
return null;
379388
}
380-
const metadataPath = join(rootDir, relativeMetadataPath);
381389
const metadataText = readFileSync(metadataPath).toString('utf-8');
382390

383391
const metadata = parseJson(metadataText) as any;
@@ -390,8 +398,7 @@ function findCommand(rootDir: Path, map: CommandMap, name: string): CommandLocat
390398
}
391399

392400
// Create an instance of a command.
393-
async function createCommand(rootDir: Path,
394-
metadata: CommandLocation,
401+
async function createCommand(metadata: CommandLocation,
395402
context: CommandContext,
396403
logger: logging.Logger): Promise<Command | null> {
397404
const schema = parseSchema(metadata.text);
@@ -424,26 +431,18 @@ function mapCommandScope(scope: 'in' | 'out' | undefined): CommandScope {
424431
return commandScope;
425432
}
426433

427-
// TODO: filter out commands that should not be listed based upon the command's metadata
428-
function listAllCommandNames(rootDir: Path, map: CommandMap): string[] {
429-
return getAllCommandInfo(rootDir, map)
430-
.reduce((acc, cmd) => {
431-
return [...acc, cmd.name, ...cmd.aliases];
432-
}, [] as string[]);
433-
}
434-
435434
interface CommandInfo {
436435
name: string;
437436
description: string;
438437
aliases: string[];
439438
hidden: boolean;
440439
}
441-
function getAllCommandInfo(rootDir: Path, map: CommandMap): CommandInfo[] {
440+
function getAllCommandInfo(map: CommandMap): CommandInfo[] {
442441
return Object.keys(map)
443442
.map(name => {
444443
return {
445444
name: name,
446-
metadata: findCommand(rootDir, map, name),
445+
metadata: findCommand(map, name),
447446
};
448447
})
449448
.map(info => {

0 commit comments

Comments
 (0)