Skip to content

Commit 1af9927

Browse files
Add validation for command parameters
Add validation for the parameters that each command accepts. Add logic to check if command has mandatory parameters and all of them are provided - if any of them is missing, command is not executed. Add logic to validate all arguments passed to command - if the command does not accept arguments, but there are some passed to it, it is not executed. Add ICommandParameter interface to describe command parameter. Add allowedParameters property to ICommand interface. Add canExecute method to ICommand interface. It is not mandatory to implement it and it is used when the command will validate the parameters on its own. The common validation is implemented in CommandsService. ICommandParameter describes one parameter that the command accepts. It can be mandatory for the command or not. That's why I've added mandatory boolean parameter to the interface. Each parameter have its own logic for valid values, that's why ICommandParameter has validate method. It is called from the CommandsService when the arguments are validated. CommandsService itself tries to validate all command arguments. One special case is when the command is hierarchical. In this situation the root command is validated first, but it doesn't have own definition, so it doesn't have allowed parameters. That's why CommandsService checks if the command is valid hierarchical command. If command has canExecute method implemented, CommandsService will use it to validate the arguments. If not, it will try to validate all passed command line arguments with the allowed parameters of the command, by checking their count, calling validate method, etc. Each command has different number of allowed parameters. In most of the cases the command parameter is string and the only requirement for it is to be non-empty. That's why new StringCommandParameter class is added. It is used to define such parameters. In case the parameter has more complicated logic, new class, that implements ICommandParameter is added for it. Remove some tests as the validation logic is moved outside of some methods - in the command parameters. Add new unit tests.
1 parent 5eda9d5 commit 1af9927

20 files changed

+435
-64
lines changed

lib/bootstrap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ $injector.require("analyticsSettingsService", "./services/analytics-settings-ser
1818

1919
$injector.require("emulatorSettingsService", "./services/emulator-settings-service");
2020

21+
$injector.require("platformCommandParameter", "./platform-command-param");
2122
$injector.requireCommand("create", "./commands/create-project");
2223
$injector.requireCommand("platform|*list", "./commands/list-platforms");
2324
$injector.requireCommand("platform|add", "./commands/add-platform");

lib/commands/add-platform.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
23

34
export class AddPlatformCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
5+
constructor(private $platformService: IPlatformService,
6+
private $errors: IErrors) { }
57

68
execute(args: string[]): IFuture<void> {
79
return (() => {
810
this.$platformService.addPlatforms(args).wait();
911
}).future<void>()();
1012
}
13+
14+
allowedParameters: ICommandParameter[] = [];
15+
16+
canExecute(args: string[]): IFuture<boolean> {
17+
return (() => {
18+
if(!args || args.length === 0) {
19+
this.$errors.fail("No platform specified. Please specify a platform to add");
20+
}
21+
22+
_.each(args, arg => this.$platformService.validatePlatform(arg));
23+
24+
return true;
25+
}).future<boolean>()();
26+
}
1127
}
1228
$injector.registerCommand("platform|add", AddPlatformCommand);

lib/commands/build.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
23

34
export class BuildCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
5+
constructor(private $platformService: IPlatformService,
6+
private $platformCommandParameter: ICommandParameter) { }
57

68
execute(args: string[]): IFuture<void> {
79
return (() => {
810
this.$platformService.buildPlatform(args[0]).wait();
911
}).future<void>()();
1012
}
13+
14+
allowedParameters = [this.$platformCommandParameter];
1115
}
1216
$injector.registerCommand("build", BuildCommand);

lib/commands/create-project.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
3+
4+
export class ProjectCommandParameter implements ICommandParameter {
5+
constructor(private $errors: IErrors,
6+
private $projectNameValidator: IProjectNameValidator) { }
7+
8+
mandatory = true;
9+
validate(value: string): IFuture<boolean> {
10+
return (() => {
11+
if(!value) {
12+
this.$errors.fail("You must specify <App name> when creating a new project.");
13+
}
14+
15+
return this.$projectNameValidator.validate(value);
16+
}).future<boolean>()();
17+
}
18+
}
219

320
export class CreateProjectCommand implements ICommand {
4-
constructor(private $projectService: IProjectService) { }
21+
constructor(private $projectService: IProjectService,
22+
private $errors: IErrors,
23+
private $projectNameValidator: IProjectNameValidator) { }
524

625
public enableHooks = false;
726

@@ -10,5 +29,7 @@ export class CreateProjectCommand implements ICommand {
1029
this.$projectService.createProject(args[0]).wait();
1130
}).future<void>()();
1231
}
32+
33+
allowedParameters = [new ProjectCommandParameter(this.$errors, this.$projectNameValidator) ]
1334
}
1435
$injector.registerCommand("create", CreateProjectCommand);

lib/commands/deploy.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
23

34
export class DeployOnDeviceCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
5+
constructor(private $platformService: IPlatformService,
6+
private $platformCommandParameter: ICommandParameter) { }
57

68
execute(args: string[]): IFuture<void> {
79
return this.$platformService.deployOnDevice(args[0]);
810
}
11+
12+
allowedParameters = [this.$platformCommandParameter];
913
}
10-
$injector.registerCommand("deploy", DeployOnDeviceCommand);
14+
$injector.registerCommand("deploy", DeployOnDeviceCommand);

lib/commands/emulate.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
///<reference path="../.d.ts"/>
22

33
export class EmulateCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
4+
constructor(private $platformService: IPlatformService,
5+
private $platformCommandParameter: ICommandParameter) { }
56

6-
execute(args: string[]): IFuture<void> { return this.$platformService.deployOnEmulator(args[0]);}
7+
execute(args: string[]): IFuture<void> { return this.$platformService.deployOnEmulator(args[0]); }
8+
9+
allowedParameters = [this.$platformCommandParameter];
710
}
8-
$injector.registerCommand("emulate", EmulateCommand);
11+
$injector.registerCommand("emulate", EmulateCommand);

lib/commands/list-devices.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import util = require("util")
44

55
export class ListDevicesCommand implements ICommand {
66
constructor(private $devicesServices: Mobile.IDevicesServices,
7-
private $logger: ILogger) { }
7+
private $logger: ILogger,
8+
private $stringParameter: ICommandParameter) { }
89

910
execute(args: string[]): IFuture<void> {
1011
return (() => {
@@ -17,5 +18,7 @@ export class ListDevicesCommand implements ICommand {
1718
this.$devicesServices.execute(action, undefined, {allowNoDevices: true}).wait();
1819
}).future<void>()();
1920
}
21+
22+
allowedParameters = [this.$stringParameter];
2023
}
2124
$injector.registerCommand("list-devices", ListDevicesCommand);

lib/commands/list-platforms.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@ export class ListPlatformsCommand implements ICommand {
2424
}
2525
}).future<void>()();
2626
}
27+
28+
allowedParameters: ICommandParameter[] = [];
2729
}
2830
$injector.registerCommand("platform|*list", ListPlatformsCommand);

lib/commands/post-install.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@ export class PostInstallCommand implements ICommand {
2121
this.$autoCompletionService.enableAutoCompletion().wait();
2222
}).future<void>()();
2323
}
24+
25+
public allowedParameters: ICommandParameter[] = [];
2426
}
2527
$injector.registerCommand("dev-post-install", PostInstallCommand);

lib/commands/prepare.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
///<reference path="../.d.ts"/>
22

33
export class PrepareCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
4+
constructor(private $platformService: IPlatformService,
5+
private $platformCommandParameter: ICommandParameter) { }
56

67
execute(args: string[]): IFuture<void> {
78
return (() => {
89
this.$platformService.preparePlatform(args[0]).wait();
910
}).future<void>()();
1011
}
12+
13+
allowedParameters = [this.$platformCommandParameter];
1114
}
1215
$injector.registerCommand("prepare", PrepareCommand);

lib/commands/remove-platform.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
23

34
export class RemovePlatformCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
5+
constructor(private $platformService: IPlatformService,
6+
private $errors: IErrors) { }
57

68
execute(args: string[]): IFuture<void> {
79
return (() => {
810
this.$platformService.removePlatforms(args).wait();
911
}).future<void>()();
1012
}
13+
14+
canExecute(args: string[]): IFuture<boolean> {
15+
return (() => {
16+
if(!args || args.length === 0) {
17+
this.$errors.fail("No platform specified. Please specify a platform to remove");
18+
}
19+
20+
_.each(args, arg => this.$platformService.validatePlatformInstalled(arg));
21+
22+
return true;
23+
}).future<boolean>()();
24+
}
25+
26+
allowedParameters: ICommandParameter[] = [];
1127
}
1228
$injector.registerCommand("platform|remove", RemovePlatformCommand);

lib/commands/run.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
23

34
export class RunCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
5+
constructor(private $platformService: IPlatformService,
6+
private $platformCommandParameter: ICommandParameter) { }
57

68
execute(args: string[]): IFuture<void> {
79
return (() => {
810
this.$platformService.runPlatform(args[0]).wait();
911
}).future<void>()();
1012
}
13+
14+
allowedParameters = [this.$platformCommandParameter];
1115
}
1216
$injector.registerCommand("run", RunCommand);

lib/commands/update-platform.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
///<reference path="../.d.ts"/>
2+
"use strict";
23

34
export class UpdatePlatformCommand implements ICommand {
4-
constructor(private $platformService: IPlatformService) { }
5+
constructor(private $platformService: IPlatformService,
6+
private $errors:IErrors) { }
57

68
execute(args: string[]): IFuture<void> {
79
return (() => {
810
this.$platformService.updatePlatforms(args).wait();
911
}).future<void>()();
1012
}
13+
14+
canExecute(args: string[]): IFuture<boolean> {
15+
return (() => {
16+
if(!args || args.length === 0) {
17+
this.$errors.fail("No platform specified. Please specify platforms to update.");
18+
}
19+
20+
_.each(args, arg => this.$platformService.validatePlatformInstalled(arg));
21+
22+
return true;
23+
}).future<boolean>()();
24+
}
25+
26+
allowedParameters: ICommandParameter[] = [];
1127
}
1228
$injector.registerCommand("platform|update", UpdatePlatformCommand);

lib/definitions/platform.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ interface IPlatformService {
1010
buildPlatform(platform: string): IFuture<void>;
1111
deployOnDevice(platform: string): IFuture<void>;
1212
deployOnEmulator(platform: string): IFuture<void>;
13+
validatePlatformInstalled(platform: string): void;
14+
validatePlatform(platform: string): void;
1315
}
1416

1517
interface IPlatformData {

lib/platform-command-param.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
///<reference path=".d.ts"/>
2+
"use strict";
3+
4+
export class PlatformCommandParameter implements ICommandParameter {
5+
constructor(private $platformService: IPlatformService) { }
6+
mandatory = true;
7+
validate(value: string): IFuture<boolean> {
8+
return (() => {
9+
this.$platformService.validatePlatformInstalled(value);
10+
return true;
11+
}).future<boolean>()();
12+
}
13+
}
14+
$injector.register("platformCommandParameter", PlatformCommandParameter);

lib/services/platform-service.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ export class PlatformService implements IPlatformService {
2121

2222
public addPlatforms(platforms: string[]): IFuture<void> {
2323
return (() => {
24-
if(!platforms || platforms.length === 0) {
25-
this.$errors.fail("No platform specified. Please specify a platform to add");
26-
}
27-
2824
var platformsDir = this.$projectData.platformsDir;
2925
this.$fs.ensureDirectoryExists(platformsDir).wait();
3026

@@ -136,7 +132,6 @@ export class PlatformService implements IPlatformService {
136132

137133
public preparePlatform(platform: string): IFuture<void> {
138134
return (() => {
139-
this.validatePlatformInstalled(platform);
140135
platform = platform.toLowerCase();
141136

142137
var platformData = this.$platformsData.getPlatformData(platform);
@@ -166,7 +161,6 @@ export class PlatformService implements IPlatformService {
166161

167162
public buildPlatform(platform: string): IFuture<void> {
168163
return (() => {
169-
this.validatePlatformInstalled(platform);
170164
platform = platform.toLowerCase();
171165

172166
var platformData = this.$platformsData.getPlatformData(platform);
@@ -177,7 +171,6 @@ export class PlatformService implements IPlatformService {
177171

178172
public runPlatform(platform: string): IFuture<void> {
179173
return (() => {
180-
this.validatePlatformInstalled(platform);
181174
platform = platform.toLowerCase();
182175

183176
this.preparePlatform(platform).wait();
@@ -191,10 +184,6 @@ export class PlatformService implements IPlatformService {
191184

192185
public removePlatforms(platforms: string[]): IFuture<void> {
193186
return (() => {
194-
if(!platforms || platforms.length === 0) {
195-
this.$errors.fail("No platform specified. Please specify a platform to remove");
196-
}
197-
198187
_.each(platforms, platform => {
199188
this.validatePlatformInstalled(platform);
200189

@@ -207,10 +196,6 @@ export class PlatformService implements IPlatformService {
207196

208197
public updatePlatforms(platforms: string[]): IFuture<void> {
209198
return (() => {
210-
if(!platforms || platforms.length === 0) {
211-
this.$errors.fail("No platform specified. Please specify a platform to remove");
212-
}
213-
214199
_.each(platforms, platform => {
215200
var parts = platform.split("@");
216201
platform = parts[0].toLowerCase();
@@ -224,7 +209,6 @@ export class PlatformService implements IPlatformService {
224209

225210
public deployOnDevice(platform: string): IFuture<void> {
226211
return (() => {
227-
this.validatePlatformInstalled(platform);
228212
platform = platform.toLowerCase();
229213

230214
var platformData = this.$platformsData.getPlatformData(platform);
@@ -267,7 +251,7 @@ export class PlatformService implements IPlatformService {
267251
}).future<void>()();
268252
}
269253

270-
private validatePlatform(platform: string): void {
254+
public validatePlatform(platform: string): void {
271255
if(!platform) {
272256
this.$errors.fail("No platform specified.")
273257
}
@@ -283,7 +267,7 @@ export class PlatformService implements IPlatformService {
283267
}
284268
}
285269

286-
private validatePlatformInstalled(platform: string): void {
270+
public validatePlatformInstalled(platform: string): void {
287271
this.validatePlatform(platform);
288272

289273
if (!this.isPlatformInstalled(platform).wait()) {

0 commit comments

Comments
 (0)