feat(nx): support passing args to run-commands builder

This commit is contained in:
Victor Savkin 2019-05-07 10:51:59 -04:00
parent 857ee73142
commit 7d5fdcd1d3
5 changed files with 90 additions and 9 deletions

View File

@ -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

View File

@ -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();

View File

@ -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');
});
});

View File

@ -15,6 +15,8 @@ export interface RunCommandsBuilderOptions {
commands: { command: string }[];
parallel?: boolean;
readyWhen?: string;
args?: string;
parsedArgs?: { [k: string]: string };
}
export default class RunCommandsBuilder
@ -22,6 +24,10 @@ export default class RunCommandsBuilder
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(
@ -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
}))
@ -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;
@ -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;
}, {});
}
}

View File

@ -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"]