FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

refactor(executor): split out locate/execute · ionic-team/ionic-cli@d4d5286 · GitHub

Repository navigation

Commit d4d5286

Browse files
committed
refactor(executor): split out locate/execute
1 parent 5648344 commit d4d5286

2 files changed

Lines changed: 48 additions & 20 deletions

File tree

‎packages/@ionic/cli-framework/src/definitions.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ export interface HydratedNamespaceMetadata<C extends ICommand<C, N, M, I, O>, N
135135
export interface IExecutor<C extends ICommand<C, N, M, I, O>, N extends INamespace<C, N, M, I, O>, M extends CommandMetadata<I, O>, I extends CommandMetadataInput, O extends CommandMetadataOption> {
136136
readonly namespace: N;
137137

138+
locate(argv: readonly string[], options?: NamespaceLocateOptions): Promise<NamespaceLocateResult<C, N, M, I, O>>;
139+
execute(location: NamespaceLocateResult<C, N, M, I, O>): Promise<void>;
138140
execute(argv: readonly string[], env: NodeJS.ProcessEnv): Promise<void>;
139141
run(command: C, cmdargs: readonly string[], runinfo?: Partial<CommandInstanceInfo<C, N, M, I, O>>): Promise<void>;
140142
}

‎packages/@ionic/cli-framework/src/lib/executor.ts‎

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { EventEmitter } from 'events';
22
import * as lodash from 'lodash';
33

4-
import { CommandInstanceInfo, CommandMetadata, CommandMetadataInput, CommandMetadataOption, ICommand, IExecutor, INamespace, NamespaceLocateResult } from '../definitions';
4+
import { CommandInstanceInfo, CommandMetadata, CommandMetadataInput, CommandMetadataOption, ICommand, IExecutor, INamespace, NamespaceLocateOptions, NamespaceLocateResult } from '../definitions';
55
import { BaseError, InputValidationError } from '../errors';
66
import { isCommand, isNamespace } from '../guards';
77

@@ -20,11 +20,23 @@ export const EXECUTOR_OPS: ExecutorOperations = Object.freeze({
2020
RPC: '📡',
2121
});
2222

23+
export const HELP_FLAGS = ['--help', '-?'];
24+
2325
export abstract class AbstractExecutor<C extends ICommand<C, N, M, I, O>, N extends INamespace<C, N, M, I, O>, M extends CommandMetadata<I, O>, I extends CommandMetadataInput, O extends CommandMetadataOption> extends EventEmitter implements IExecutor<C, N, M, I, O> {
2426
abstract readonly namespace: N;
2527

28+
abstract locate(argv: readonly string[], options?: NamespaceLocateOptions): Promise<NamespaceLocateResult<C, N, M, I, O>>;
29+
abstract execute(location: NamespaceLocateResult<C, N, M, I, O>): Promise<void>;
2630
abstract execute(argv: readonly string[], env: NodeJS.ProcessEnv): Promise<void>;
2731
abstract run(command: C, cmdargs: readonly string[], runinfo?: Partial<CommandInstanceInfo<C, N, M, I, O>>): Promise<void>;
32+
33+
async resolveExecuteInput(argvOrLocation: readonly string[] | NamespaceLocateResult<C, N, M, I, O>): Promise<[NamespaceLocateResult<C, N, M, I, O>, string[]]> {
34+
if ('obj' in argvOrLocation) {
35+
return [argvOrLocation, [...argvOrLocation.args]];
36+
} else {
37+
return [await this.locate(argvOrLocation), [...argvOrLocation]];
38+
}
39+
}
2840
}
2941

3042
export interface BaseExecutorFormatHelpOptions {
@@ -57,6 +69,20 @@ export class BaseExecutor<C extends ICommand<C, N, M, I, O>, N extends INamespac
5769
this.stderr = stderr ? stderr : process.stderr;
5870
}
5971

72+
/**
73+
* Locate a command or namespace given an array of positional arguments
74+
* (argv).
75+
*
76+
* @param argv Command arguments sliced to the root for the namespace of this
77+
* executor. Usually, this means `process.argv.slice(2)`.
78+
*/
79+
async locate(argv: readonly string[]): Promise<NamespaceLocateResult<C, N, M, I, O>> {
80+
const parsedArgs = stripOptions(argv, {});
81+
const location = await this.namespace.locate(parsedArgs);
82+
83+
return location;
84+
}
85+
6086
/**
6187
* Locate and execute a command given an array of positional command
6288
* arguments (argv) and a set of environment variables.
@@ -68,32 +94,21 @@ export class BaseExecutor<C extends ICommand<C, N, M, I, O>, N extends INamespac
6894
* executor. Usually, this means `process.argv.slice(2)`.
6995
* @param env Environment variables for this execution.
7096
*/
71-
async execute(argv: readonly string[], env: NodeJS.ProcessEnv): Promise<void> {
72-
if (argv[0] === EXECUTOR_OPS.RPC) {
97+
async execute(argvOrLocation: readonly string[] | NamespaceLocateResult<C, N, M, I, O>, env?: NodeJS.ProcessEnv): Promise<void> {
98+
if (Array.isArray(argvOrLocation) && argvOrLocation[0] === EXECUTOR_OPS.RPC) {
7399
return this.rpc();
74100
}
75101

76-
const parsedArgs = stripOptions(argv, { includeSeparated: false });
77-
const location = await this.namespace.locate(parsedArgs);
102+
const [ location, argv ] = await this.resolveExecuteInput(argvOrLocation);
78103

79-
if (argv.find(arg => arg === '--help' || arg === '-?') || isNamespace(location.obj)) {
80-
const cmdoptions = parseArgs([...argv]);
104+
if (lodash.intersection(HELP_FLAGS, argv).length > 0 || isNamespace(location.obj)) {
105+
const cmdoptions = parseArgs(argv);
81106
this.stdout.write(await this.formatHelp(location, { format: cmdoptions['json'] ? 'json' : 'terminal' }));
82107
} else {
83108
const cmd = location.obj;
84-
const cmdargs = lodash.drop(argv, location.path.length - 1);
85-
86-
try {
87-
await this.run(cmd, cmdargs, { location, env, executor: this });
88-
} catch (e) {
89-
if (e instanceof BaseError) {
90-
this.stderr.write(`Error: ${e.message}`);
91-
process.exitCode = typeof e.exitCode === 'undefined' ? 1 : e.exitCode;
92-
return;
93-
}
109+
const cmdargs = location.args;
94110

95-
throw e;
96-
}
111+
await this.run(cmd, cmdargs, { location, env, executor: this });
97112
}
98113
}
99114

@@ -166,5 +181,16 @@ export class Executor extends BaseExecutor<Command, Namespace, CommandMetadata,
166181

167182
export async function execute<C extends ICommand<C, N, M, I, O>, N extends INamespace<C, N, M, I, O>, M extends CommandMetadata<I, O>, I extends CommandMetadataInput, O extends CommandMetadataOption>({ namespace, argv, env, ...rest }: { namespace: N; argv: string[]; env: NodeJS.ProcessEnv } & Partial<BaseExecutorDeps<C, N, M, I, O>>) {
168183
const executor = new BaseExecutor<C, N, M, I, O>({ namespace, ...rest });
169-
await executor.execute(argv, env);
184+
185+
try {
186+
await executor.execute(argv, env);
187+
} catch (e) {
188+
if (e instanceof BaseError) {
189+
executor.stderr.write(`Error: ${e.message}`);
190+
process.exitCode = typeof e.exitCode === 'undefined' ? 1 : e.exitCode;
191+
return;
192+
}
193+
194+
throw e;
195+
}
170196
}

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL