Skip to content

Commit 8819b16

Browse files
committed
fix: unify the way of showing help by removing the supressCommandHelp in favor of the failWithHelp method
1 parent 38778ac commit 8819b16

24 files changed

+112
-133
lines changed

lib/commands/add-platform.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export class AddPlatformCommand extends ValidatePlatformCommandBase implements I
1717
await this.$platformCommandHelper.addPlatforms(args, this.$projectData, this.$options.frameworkPath);
1818
}
1919

20-
public async canExecute(args: string[]): Promise<ICanExecuteCommandOutput> {
20+
public async canExecute(args: string[]): Promise<boolean> {
2121
if (!args || args.length === 0) {
2222
this.$errors.failWithHelp("No platform specified. Please specify a platform to add.");
2323
}
@@ -30,14 +30,10 @@ export class AddPlatformCommand extends ValidatePlatformCommandBase implements I
3030
this.$errors.fail(`Applications for platform ${arg} can not be built on this OS`);
3131
}
3232

33-
const output = await super.canExecuteCommandBase(arg);
34-
canExecute = canExecute && output.canExecute;
33+
canExecute = await super.canExecuteCommandBase(arg);
3534
}
3635

37-
return {
38-
canExecute,
39-
suppressCommandHelp: !canExecute
40-
};
36+
return canExecute;
4137
}
4238
}
4339

lib/commands/build.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,17 @@ export abstract class BuildCommandBase extends ValidatePlatformCommandBase {
3434
}
3535
}
3636

37-
protected async validateArgs(args: string[], platform: string): Promise<ICanExecuteCommandOutput> {
38-
const canExecute = await this.validateArgsCore(args, platform);
39-
return {
40-
canExecute,
41-
suppressCommandHelp: false
42-
};
37+
protected async validateArgs(args: string[], platform: string): Promise<boolean> {
38+
return await this.validateArgsCore(args, platform);
4339
}
4440

4541
private async validateArgsCore(args: string[], platform: string): Promise<boolean> {
4642
if (args.length !== 0) {
47-
return false;
43+
this.$errors.failWithHelp(`The arguments '${args.join(" ")}' are not valid for the current command.`);
4844
}
4945

5046
const result = await this.$platformValidationService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, platform);
47+
5148
return result;
5249
}
5350
}
@@ -72,20 +69,20 @@ export class BuildIosCommand extends BuildCommandBase implements ICommand {
7269
await this.executeCore([this.$devicePlatformsConstants.iOS.toLowerCase()]);
7370
}
7471

75-
public async canExecute(args: string[]): Promise<boolean | ICanExecuteCommandOutput> {
72+
public async canExecute(args: string[]): Promise<boolean> {
7673
const platform = this.$devicePlatformsConstants.iOS;
7774
if (!this.$options.force) {
7875
await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [platform] });
7976
}
8077

8178
super.validatePlatform(platform);
8279

83-
let result = await super.canExecuteCommandBase(platform, { notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } });
84-
if (result.canExecute) {
85-
result = await super.validateArgs(args, platform);
80+
let canExecute = await super.canExecuteCommandBase(platform, { notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } });
81+
if (canExecute) {
82+
canExecute = await super.validateArgs(args, platform);
8683
}
8784

88-
return result;
85+
return canExecute;
8986
}
9087
}
9188

@@ -120,22 +117,22 @@ export class BuildAndroidCommand extends BuildCommandBase implements ICommand {
120117
}
121118
}
122119

123-
public async canExecute(args: string[]): Promise<boolean | ICanExecuteCommandOutput> {
120+
public async canExecute(args: string[]): Promise<boolean> {
124121
const platform = this.$devicePlatformsConstants.Android;
125122
if (!this.$options.force) {
126123
await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [platform] });
127124
}
128125
this.$androidBundleValidatorHelper.validateRuntimeVersion(this.$projectData);
129-
let result = await super.canExecuteCommandBase(platform, { notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } });
130-
if (result.canExecute) {
126+
let canExecute = await super.canExecuteCommandBase(platform, { notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } });
127+
if (canExecute) {
131128
if (this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) {
132129
this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE);
133130
}
134131

135-
result = await super.validateArgs(args, platform);
132+
canExecute = await super.validateArgs(args, platform);
136133
}
137134

138-
return result;
135+
return canExecute;
139136
}
140137
}
141138

lib/commands/command-base.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ export abstract class ValidatePlatformCommandBase {
77
abstract allowedParameters: ICommandParameter[];
88
abstract execute(args: string[]): Promise<void>;
99

10-
public async canExecuteCommandBase(platform: string, options?: ICanExecuteCommandOptions): Promise<ICanExecuteCommandOutput> {
10+
public async canExecuteCommandBase(platform: string, options?: ICanExecuteCommandOptions): Promise<boolean> {
1111
options = options || {};
1212
const validatePlatformOutput = await this.validatePlatformBase(platform, options.notConfiguredEnvOptions);
1313
const canExecute = this.canExecuteCommand(validatePlatformOutput);
14-
let result = { canExecute, suppressCommandHelp: !canExecute };
14+
let result = canExecute;
1515

1616
if (canExecute && options.validateOptions) {
17-
const validateOptionsOutput = await this.$platformValidationService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, platform);
18-
result = { canExecute: validateOptionsOutput, suppressCommandHelp: false };
17+
result = await this.$platformValidationService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, platform);
1918
}
2019

2120
return result;

lib/commands/debug.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements
5252
});
5353
}
5454

55-
public async canExecute(args: string[]): Promise<ICanExecuteCommandOutput> {
55+
public async canExecute(args: string[]): Promise<boolean> {
5656
if (!this.$options.force) {
5757
await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [this.platform] });
5858
}
@@ -103,7 +103,7 @@ export class DebugIOSCommand implements ICommand {
103103
return this.debugPlatformCommand.execute(args);
104104
}
105105

106-
public async canExecute(args: string[]): Promise<ICanExecuteCommandOutput> {
106+
public async canExecute(args: string[]): Promise<boolean> {
107107
if (!this.$platformValidationService.isPlatformSupportedForOS(this.$devicePlatformsConstants.iOS, this.$projectData)) {
108108
this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.iOS} can not be built on this OS`);
109109
}
@@ -164,7 +164,7 @@ export class DebugAndroidCommand implements ICommand {
164164
public execute(args: string[]): Promise<void> {
165165
return this.debugPlatformCommand.execute(args);
166166
}
167-
public async canExecute(args: string[]): Promise<ICanExecuteCommandOutput> {
167+
public async canExecute(args: string[]): Promise<boolean> {
168168
const result = await this.debugPlatformCommand.canExecute(args);
169169
return result;
170170
}

lib/commands/deploy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class DeployOnDeviceCommand extends ValidatePlatformCommandBase implement
2828
await this.$deployCommandHelper.deploy(platform);
2929
}
3030

31-
public async canExecute(args: string[]): Promise<boolean | ICanExecuteCommandOutput> {
31+
public async canExecute(args: string[]): Promise<boolean> {
3232
this.$androidBundleValidatorHelper.validateNoAab();
3333
if (!args || !args.length || args.length > 1) {
3434
return false;

lib/commands/prepare.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class PrepareCommand extends ValidatePlatformCommandBase implements IComm
2929
await this.$prepareController.prepare(prepareData);
3030
}
3131

32-
public async canExecute(args: string[]): Promise<boolean | ICanExecuteCommandOutput> {
32+
public async canExecute(args: string[]): Promise<boolean> {
3333
const platform = args[0];
3434
const result = await this.$platformCommandParameter.validate(platform) &&
3535
await this.$platformValidationService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, platform);

lib/commands/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ abstract class TestCommandBase {
4848
await this.$testExecutionService.startKarmaServer(this.platform, liveSyncInfo, deviceDescriptors);
4949
}
5050

51-
async canExecute(args: string[]): Promise<boolean | ICanExecuteCommandOutput> {
51+
async canExecute(args: string[]): Promise<boolean> {
5252
if (!this.$options.force) {
5353
await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [this.platform] });
5454
}

lib/common/declarations.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ interface IFailOptions {
579579
name?: string;
580580
formatStr?: string;
581581
errorCode?: number;
582-
suppressCommandHelp?: boolean;
583582
proxyAuthenticationRequired?: boolean;
584583
printOnStdout?: boolean;
585584
}

lib/common/definitions/commands.d.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface ICommand extends ICommandOptions {
1010
// One possible case where you can use this method is when you have two commandParameters, neither of them is mandatory,
1111
// but at least one of them is required. Used in prop|add, prop|set, etc. commands as their logic is complicated and
1212
// default validation in CommandsService is not applicable.
13-
canExecute?(args: string[]): Promise<boolean | ICanExecuteCommandOutput>;
13+
canExecute?(args: string[]): Promise<boolean>;
1414
completionData?: string[];
1515
dashedOptions?: IDictionary<IDashedOption>;
1616
isHierarchicalCommand?: boolean;
@@ -23,15 +23,6 @@ interface ICommand extends ICommandOptions {
2323
postCommandAction?(args: string[]): Promise<void>;
2424
}
2525

26-
interface ICanExecuteCommandOutput {
27-
canExecute: boolean;
28-
/**
29-
* In case when canExecute method returns false, the help of the command is printed.
30-
* In case when canExecute method returns false and suppressCommandHelp is true, the command's help will not be printed.
31-
*/
32-
suppressCommandHelp?: boolean;
33-
}
34-
3526
interface ICanExecuteCommandOptions {
3627
validateOptions?: boolean;
3728
notConfiguredEnvOptions?: INotConfiguredEnvOptions;

lib/common/errors.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,20 +125,18 @@ export class Errors implements IErrors {
125125

126126
public fail(optsOrFormatStr: string | IFailOptions, ...args: any[]): never {
127127
const opts = this.getFailOptions(optsOrFormatStr);
128-
opts.suppressCommandHelp = true;
129-
return this.failWithOptions(opts, args);
128+
return this.failWithOptions(opts, false, args);
130129
}
131130

132131
// DEPRECATED: use .fail instead
133132
public failWithoutHelp(optsOrFormatStr: string | IFailOptions, ...args: any[]): never {
134-
return this.failWithoutHelp(optsOrFormatStr, args);
133+
return this.fail(optsOrFormatStr, args);
135134
}
136135

137136
public failWithHelp(optsOrFormatStr: string | IFailOptions, ...args: any[]): never {
138137
const opts = this.getFailOptions(optsOrFormatStr);
139-
opts.suppressCommandHelp = false;
140138

141-
return this.failWithOptions(opts, args);
139+
return this.failWithOptions(opts, true, args);
142140
}
143141

144142
private getFailOptions(optsOrFormatStr: string | IFailOptions): IFailOptions {
@@ -150,7 +148,7 @@ export class Errors implements IErrors {
150148
return opts;
151149
}
152150

153-
private failWithOptions(opts: IFailOptions, ...args: any[]): never {
151+
private failWithOptions(opts: IFailOptions, suggestCommandHelp: boolean, ...args: any[]): never {
154152
const argsArray = args || [];
155153
const exception: any = new (<any>Exception)();
156154
exception.name = opts.name || "Exception";
@@ -164,15 +162,15 @@ export class Errors implements IErrors {
164162

165163
exception.stack = (new Error(exception.message)).stack;
166164
exception.errorCode = opts.errorCode || ErrorCodes.UNKNOWN;
167-
exception.suppressCommandHelp = opts.suppressCommandHelp;
165+
exception.suggestCommandHelp = suggestCommandHelp;
168166
exception.proxyAuthenticationRequired = !!opts.proxyAuthenticationRequired;
169167
exception.printOnStdout = opts.printOnStdout;
170168
this.$injector.resolve("logger").trace(opts.formatStr);
171169

172170
throw exception;
173171
}
174172

175-
public async beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<void>): Promise<boolean> {
173+
public async beginCommand(action: () => Promise<boolean>, printCommandHelpSuggestion: () => Promise<void>): Promise<boolean> {
176174
try {
177175
return await action();
178176
} catch (ex) {
@@ -186,8 +184,8 @@ export class Errors implements IErrors {
186184
console.error(message);
187185
}
188186

189-
if (!ex.suppressCommandHelp) {
190-
await printCommandHelp();
187+
if (ex.suggestCommandHelp) {
188+
await printCommandHelpSuggestion();
191189
}
192190

193191
await tryTrackException(ex, this.$injector);

lib/common/mobile/mobile-core/devices-service.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,7 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
456456
}
457457

458458
const errorMessage = `${preErrorMsg}${errors.map(e => e.message || e).join(EOL)}`;
459-
const suppressCommandHelp = _.some(errors, (e: any) => e.suppressCommandHelp);
460-
this.$errors.fail({ formatStr: errorMessage, suppressCommandHelp });
459+
this.$errors.fail(errorMessage);
461460
}
462461

463462
return result;
@@ -678,7 +677,7 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
678677
if (platforms.length === 1) {
679678
this._platform = platforms[0];
680679
} else if (platforms.length === 0) {
681-
this.$errors.fail({ formatStr: constants.ERROR_NO_DEVICES, suppressCommandHelp: true });
680+
this.$errors.fail(constants.ERROR_NO_DEVICES);
682681
} else {
683682
this.$errors.failWithHelp("Multiple device platforms detected (%s). Specify platform or device on command line.",
684683
helpers.formatListOfNames(platforms, "and"));

lib/common/services/commands-service.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export class CommandsService implements ICommandsService {
2525
private $logger: ILogger,
2626
private $options: IOptions,
2727
private $staticConfig: Config.IStaticConfig,
28-
private $helpService: IHelpService,
2928
private $extensibilityService: IExtensibilityService,
3029
private $optionsTracker: IOptionsTracker) {
3130
}
@@ -92,21 +91,19 @@ export class CommandsService implements ICommandsService {
9291
return false;
9392
}
9493

95-
private printHelp(commandName: string, commandArguments: string[]): Promise<void> {
96-
try {
97-
return this.$helpService.showCommandLineHelp({ commandName: this.beautifyCommandName(commandName), commandArguments });
98-
} catch (printHelpException) {
99-
console.error("Failed to display command help", printHelpException);
100-
}
94+
private printHelpSuggestion(commandName: string, commandArguments: string[]): Promise<void> {
95+
const commandHelp = `tns ${helpers.stringReplaceAll(this.beautifyCommandName(commandName), "|", " ")} --help`;
96+
this.$logger.printMarkdown(`Run \`${commandHelp}\` for more information.`);
97+
return;
10198
}
10299

103-
private async executeCommandAction(commandName: string, commandArguments: string[], action: (_commandName: string, _commandArguments: string[]) => Promise<boolean | ICanExecuteCommandOutput>): Promise<boolean> {
100+
private async executeCommandAction(commandName: string, commandArguments: string[], action: (_commandName: string, _commandArguments: string[]) => Promise<boolean>): Promise<boolean> {
104101
return this.$errors.beginCommand(
105102
() => action.apply(this, [commandName, commandArguments]),
106-
() => this.printHelp(commandName, commandArguments));
103+
() => this.printHelpSuggestion(commandName, commandArguments));
107104
}
108105

109-
private async tryExecuteCommandAction(commandName: string, commandArguments: string[]): Promise<boolean | ICanExecuteCommandOutput> {
106+
private async tryExecuteCommandAction(commandName: string, commandArguments: string[]): Promise<boolean> {
110107
const command = this.$injector.resolveCommand(commandName);
111108
if (!command || !command.isHierarchicalCommand) {
112109
const dashedOptions = command ? command.dashedOptions : null;
@@ -119,23 +116,20 @@ export class CommandsService implements ICommandsService {
119116
public async tryExecuteCommand(commandName: string, commandArguments: string[]): Promise<void> {
120117
const canExecuteResult: any = await this.executeCommandAction(commandName, commandArguments, this.tryExecuteCommandAction);
121118
const canExecute = typeof canExecuteResult === "object" ? canExecuteResult.canExecute : canExecuteResult;
122-
const suppressCommandHelp = typeof canExecuteResult === "object" ? canExecuteResult.suppressCommandHelp : false;
123119

124120
if (canExecute) {
125121
await this.executeCommandAction(commandName, commandArguments, this.executeCommandUnchecked);
126122
} else {
127123
// If canExecuteCommand returns false, the command cannot be executed or there's no such command at all.
128124
const command = this.$injector.resolveCommand(commandName);
129125
if (command) {
130-
if (!suppressCommandHelp) {
131-
// If command cannot be executed we should print its help.
132-
await this.printHelp(commandName, commandArguments);
133-
}
126+
this.$logger.error(`Command '${commandName} ${commandArguments}' cannot be executed.`);
127+
await this.printHelpSuggestion(commandName, commandArguments);
134128
}
135129
}
136130
}
137131

138-
private async canExecuteCommand(commandName: string, commandArguments: string[], isDynamicCommand?: boolean): Promise<boolean | ICanExecuteCommandOutput> {
132+
private async canExecuteCommand(commandName: string, commandArguments: string[], isDynamicCommand?: boolean): Promise<boolean> {
139133
const command = this.$injector.resolveCommand(commandName);
140134
const beautifiedName = helpers.stringReplaceAll(commandName, "|", " ");
141135
if (command) {

lib/common/test/unit-tests/stubs.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class ErrorsStub implements IErrors {
5858
printCallStack: boolean = false;
5959

6060
fail(formatStr: string, ...args: any[]): never;
61-
fail(opts: { formatStr?: string; errorCode?: number; suppressCommandHelp?: boolean }, ...args: any[]): never;
61+
fail(opts: IFailOptions, ...args: any[]): never;
6262

6363
fail(...args: any[]): never {
6464
if (_.isObject(args) && (<any>args).formatStr) {
@@ -69,11 +69,11 @@ export class ErrorsStub implements IErrors {
6969
}
7070

7171
failWithoutHelp(opts: string | IFailOptions, ...args: any[]): never {
72-
return this.fail(<any>opts);
72+
return this.fail(<any>opts, args);
7373
}
7474

7575
failWithHelp(opts: string | IFailOptions, ...args: any[]): never {
76-
return this.fail(<any>opts);
76+
return this.fail(<any>opts, args);
7777
}
7878

7979
async beginCommand(action: () => Promise<boolean>, printHelpCommand: () => Promise<void>): Promise<boolean> {

lib/common/test/unit-tests/xcode-select-service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ function createTestInjector(config: { xcodeSelectStdout: string, isDarwin: boole
2323
}
2424
});
2525
testInjector.register("errors", {
26-
failWithoutHelp: (message: string, ...args: any[]): void => { executionStopped = true; }
26+
failWithHelp: (): void => { executionStopped = true; },
27+
failWithoutHelp: (): void => { executionStopped = true; },
28+
fail: (): void => { executionStopped = true; }
2729
});
2830

2931
testInjector.register("hostInfo", {

0 commit comments

Comments
 (0)