command-queue
v0.1.5
Published
A flexible API for executing groups of commands synchronously or asynchronously.
Downloads
16
Maintainers
Readme
CommandQueue
CommandQueue provides a flexible API for executing groups of commands synchronously or asynchronously. It was originally created to provide an alternative to using the scripts field in package.json for executing commands. By using CommandQueue, you can easily execute commands from a JavaScript file instead, which is better suited for managing complex build steps.
Table of Contents
Features
- Supports different combinations of synchronous and asynchronous command execution.
- Allows full customization of child_process parameters for executing a command.
Installation
To install the package:
npm install command-queue
To require the package:
var CommandQueue = require("command-queue");
Usage
Synchronous Execution
To specify the commands to run synchronously, use the .sync()
method:
// Update the PATH if necessary.
process.env.PATH += ':./node_modules/.bin';
new CommandQueue()
.sync(
'rimraf dist/',
'mkdir dist/'
)
.run();
Asynchronous Execution
To specify the commands to run asynchronously, use the .async()
method:
new CommandQueue()
.async(
'karma start',
'webpack-dev-server --hot'
)
.run();
Parallel Execution
To specify the commands to run in parallel, use the .parallel()
method:
new CommandQueue()
.parallel(
'karma start',
'webpack-dev-server --hot'
)
.run();
Parallel execution runs the commands asynchronously, but if one fails, the remaining commands are terminated using SIGTERM.
Note: This functionality is inspired by Parallel Shell.
Nested Execution
CommandQueue itself can be used as a command:
new CommandQueue()
.sync(
'command B1',
new CommandQueue().async(
'command B2a',
'command B2b',
'command B2c'
),
'command B3'
)
.run();
Batched Execution
Each call to an .async()
, .sync()
, or .parallel()
method creates a
new batch of commands. CommandQueue waits for the current batch of commands
to complete before executing the next batch of commands.
In the following example, CommandQueue waits for the A commands to complete before executing the B commands, and waits for the B commands to complete before executing the C commands.
new CommandQueue()
.async(
'command A1',
'command A2',
'command A3'
)
.parallel(
'command B1',
'command B2',
'command B3'
)
.sync(
'command C1',
'command C2',
'command C3'
)
.run();
Run
To start command execution, use the .run()
method. The .run()
method
returns a deferred promise which
is resolved when the commands have completed or a command has terminated with
an error.
new CommandQueue()
.sync('command 1')
.run()
.then(
function() {
console.log('done');
},
function() {
console.log('a command failed');
}
);
Close
To terminate currently running commands, use the .close()
method. It will send
a SIGTERM to those commands.
var queue = new CommandQueue();
queue
.async(
'command 1',
'command 2',
'command 3'
)
.run()
.then(
function() {
console.log('success');
},
function() {
console.log('failure');
// Close any remaining commands.
queue.close();
}
);
Posix or Win32
By default CommandQueue will detect the current platform and use the appropriate
shell for executing the commands. However, you can force CommandQueue to use
a specific platform's shell by using either the .posix()
method, or
the .win32()
method.
new CommandQueue()
.posix()
.sync(...)
.run();
new CommandQueue()
.win32()
.sync(...)
.run();
Run Command Customization
To customize how a command is run, replace or override the
CommandQueue.prototype.runCommand()
method.
Here is the default method:
/*
* Runs a command. This function is intended to be user replaceable
* to allow customization of the child creation process.
*
* @param {string} cmd The user provided command to run.
* @param {string} shell The shell commmand.
* @param {string} shellFlag The shell flag.
* @param {'sync'|'async'|'parallel'} runType
* @returns {object} The child process.
*/
CommandQueue.prototype.runCommand = function(cmd, shell, shellFlag, runType) {
var args = [shellFlag, cmd];
var childProcess = spawn(shell, args, {
cwd: process.cwd,
env: process.env,
stdio: ['pipe', process.stdout, process.stderr]
});
return childProcess;
};
By customizing the runCommand()
method, you can also change the types of
user arguments that can be passed into the .async()
, .sync()
,
and .parallel()
methods.
The following example shows how the runCommand()
method is changed to
accept a command that is an object rather than a string,
and how the .sync()
method can now be passed such an object.
var queue = new CommandQueue();
queue.runCommand = function(cmd, shell, shellFlag, runType) {
console.log(runType + ':' + cmd.message);
var args = [shellFlag, cmd.nodeCmd];
var childProcess = spawn(shell, args, ...);
...
};
queue.sync({
message: 'hello',
nodeCmd: 'node foobar.js'
});
queue.run();