Skip to content

Commit

Permalink
feat(nx): support passing args to run-commands builder
Browse files Browse the repository at this point in the history
  • Loading branch information
vsavkin committed May 7, 2019
1 parent 857ee73 commit 7d5fdcd
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 9 deletions.
8 changes: 2 additions & 6 deletions docs/api-builders/run-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ Run commands

## Properties

### commands

Type: `array` of `object`

#### command
### args

Type: `string`

Command to run in child process
Extra arguments. You can pass them as follows: ng run project:target --args='--wait=100'. You can them use {args.wait} syntax to interpolate them in angular.json

### parallel

Expand Down
1 change: 0 additions & 1 deletion packages/nest/src/schematics/ng-add/ng-add.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ describe('ng-add', () => {
.toPromise();
const packageJson = readJsonInTree(result, 'package.json');

console.log(packageJson);
expect(packageJson.dependencies['@nrwl/nest']).toBeUndefined();
expect(packageJson.devDependencies['@nrwl/nest']).toBeDefined();
expect(packageJson.dependencies['@nestjs/core']).toBeDefined();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,52 @@ describe('Command Runner Builder', () => {
expect(result).toEqual({ success: false });
expect(readFile(f)).toEqual('1');
});

it('should throw when invalid args', async () => {
const root = normalize('/root');
const f = fileSync().name;

try {
await builder
.run({
root,
builder: '@nrwl/run-commands',
projectType: 'application',
options: {
commands: [
{
command: `echo {args.key} >> ${f}`
}
],
args: 'key=value'
}
})
.toPromise();
} catch (e) {
expect(e.message).toEqual('Invalid args: key=value');
}
});

it('should enable parameter substitution', async () => {
const root = normalize('/root');
const f = fileSync().name;
const result = await builder
.run({
root,
builder: '@nrwl/run-commands',
projectType: 'application',
options: {
commands: [
{
command: `echo {args.key} >> ${f}`
}
],
args: '--key=value'
}
})
.toPromise();

expect(result).toEqual({ success: true });
expect(readFile(f)).toEqual('value');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ export interface RunCommandsBuilderOptions {
commands: { command: string }[];
parallel?: boolean;
readyWhen?: string;
args?: string;
parsedArgs?: { [k: string]: string };
}

export default class RunCommandsBuilder
implements Builder<RunCommandsBuilderOptions> {
run(
config: BuilderConfiguration<RunCommandsBuilderOptions>
): Observable<BuildEvent> {
config.options.parsedArgs = {
...(config.options as any),
...this.parseArgs(config.options.args)
};
return Observable.create(async observer => {
if (!config || !config.options || !config.options.commands) {
observer.error(
Expand Down Expand Up @@ -62,7 +68,10 @@ export default class RunCommandsBuilder
config: BuilderConfiguration<RunCommandsBuilderOptions>
) {
const procs = config.options.commands.map(c =>
this.createProcess(c.command, config.options.readyWhen).then(result => ({
this.createProcess(
this.transformCommand(c.command, config.options.parsedArgs),
config.options.readyWhen
).then(result => ({
result,
command: c.command
}))
Expand Down Expand Up @@ -106,7 +115,7 @@ export default class RunCommandsBuilder
>(async (m, c) => {
if ((await m) === null) {
const success = await this.createProcess(
c.command,
this.transformCommand(c.command, config.options.parsedArgs),
config.options.readyWhen
);
return !success ? c.command : null;
Expand Down Expand Up @@ -151,4 +160,29 @@ export default class RunCommandsBuilder
});
});
}

private transformCommand(command: string, args: any) {
const regex = /{args\.([^}]+)}/g;
return command.replace(regex, (_, group: string) => args[group]);
}

private parseArgs(args: string) {
if (!args) {
return {};
}
return args
.split(' ')
.map(t => t.trim())
.reduce((m, c) => {
if (!c.startsWith('--')) {
throw new Error(`Invalid args: ${args}`);
}
const [key, value] = c.substring(2).split('=');
if (!key || !value) {
throw new Error(`Invalid args: ${args}`);
}
m[key] = value;
return m;
}, {});
}
}
4 changes: 4 additions & 0 deletions packages/workspace/src/builders/run-commands/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
"readyWhen": {
"type": "string",
"description": "String to appear in stdout or stderr that indicates that the task is done. This option can only be used when parallel is set to true. If not specified, the task is done when all the child processes complete."
},
"args": {
"type": "string",
"description": "Extra arguments. You can pass them as follows: ng run project:target --args='--wait=100'. You can them use {args.wait} syntax to interpolate them in angular.json"
}
},
"required": ["commands"]
Expand Down

0 comments on commit 7d5fdcd

Please sign in to comment.