Skip to content

Commit

Permalink
api: allow different env vars for each command (#184)
Browse files Browse the repository at this point in the history
  • Loading branch information
Coridyn committed Feb 23, 2020
1 parent a0cc081 commit af501f3
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 13 deletions.
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -225,7 +225,7 @@ concurrently can be used programmatically by using the API documented below:

### `concurrently(commands[, options])`
- `commands`: an array of either strings (containing the commands to run) or objects
with the shape `{ command, name, prefixColor }`.
with the shape `{ command, name, prefixColor, env }`.
- `options` (optional): an object containing any of the below:
- `defaultInputTarget`: the default input target when reading from `inputStream`.
Default: `0`.
Expand Down Expand Up @@ -259,7 +259,8 @@ Example:
const concurrently = require('concurrently');
concurrently([
'npm:watch-*',
{ command: 'nodemon', name: 'server' }
{ command: 'nodemon', name: 'server' },
{ command: 'deploy', name: 'deploy', env: { PUBLIC_KEY: '...' } }
], {
prefix: 'name',
killOthers: ['failure', 'success'],
Expand Down
17 changes: 9 additions & 8 deletions src/concurrently.js
Expand Up @@ -31,17 +31,17 @@ module.exports = (commands, options) => {
new ExpandNpmWildcard()
];

const spawnOpts = getSpawnOpts({ raw: options.raw });

commands = _(commands)
.map(mapToCommandInfo)
.flatMap(command => parseCommand(command, commandParsers))
.map((command, index) => new Command(Object.assign({
index,
spawnOpts,
killProcess: options.kill,
spawn: options.spawn,
}, command)))
.map((command, index) => new Command(
Object.assign({
index,
spawnOpts: getSpawnOpts({ raw: options.raw, env: command.env }),
killProcess: options.kill,
spawn: options.spawn,
}, command)
))
.value();

commands = options.controllers.reduce(
Expand All @@ -63,6 +63,7 @@ function mapToCommandInfo(command) {
command: command.command || command,
name: command.name || '',
prefixColor: command.prefixColor || '',
env: command.env || {},
};
}

Expand Down
19 changes: 19 additions & 0 deletions src/concurrently.spec.js
Expand Up @@ -97,3 +97,22 @@ it('passes commands wrapped from a controller to the next one', () => {

expect(fakeCommand.start).toHaveBeenCalledTimes(1);
});

it('merges extra env vars into each command', () => {
create([
{ command: 'echo', env: { foo: 'bar' } },
{ command: 'echo', env: { foo: 'baz' } },
'kill'
]);

expect(spawn).toHaveBeenCalledTimes(3);
expect(spawn).toHaveBeenCalledWith('echo', expect.objectContaining({
env: expect.objectContaining({ foo: 'bar' })
}));
expect(spawn).toHaveBeenCalledWith('echo', expect.objectContaining({
env: expect.objectContaining({ foo: 'baz' })
}));
expect(spawn).toHaveBeenCalledWith('kill', expect.objectContaining({
env: expect.not.objectContaining({ foo: expect.anything() })
}));
});
5 changes: 3 additions & 2 deletions src/get-spawn-opts.js
Expand Up @@ -3,10 +3,11 @@ const supportsColor = require('supports-color');
module.exports = ({
colorSupport = supportsColor.stdout,
process = global.process,
raw = false
raw = false,
env = {}
}) => Object.assign(
{},
raw && { stdio: 'inherit' },
/^win/.test(process.platform) && { detached: false },
colorSupport && { env: Object.assign({ FORCE_COLOR: colorSupport.level }, process.env) }
{ env: Object.assign(colorSupport ? { FORCE_COLOR: colorSupport.level } : {}, process.env, env) }
);
2 changes: 1 addition & 1 deletion src/get-spawn-opts.spec.js
Expand Up @@ -10,7 +10,7 @@ it('sets stdio to inherit when raw', () => {

it('merges FORCE_COLOR into env vars if color supported', () => {
const process = { env: { foo: 'bar' } };
expect(getSpawnOpts({ process, colorSupport: false }).env).toBeUndefined();
expect(getSpawnOpts({ process, colorSupport: false }).env).toEqual(process.env);
expect(getSpawnOpts({ process, colorSupport: { level: 1 } }).env).toEqual({
FORCE_COLOR: 1,
foo: 'bar'
Expand Down

0 comments on commit af501f3

Please sign in to comment.