Skip to content

Instantly share code, notes, and snippets.

@cowboyd
Last active September 23, 2019 22:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cowboyd/caeb3d8412de827379d7c71e5af41ea6 to your computer and use it in GitHub Desktop.
Save cowboyd/caeb3d8412de827379d7c71e5af41ea6 to your computer and use it in GitHub Desktop.
@effection/node
import child_process from 'child_process';
/**
* Continue a process once an event is received:
* ```ts
* yield untilEvent(mocha, 'onTestStarted');
*
*/
function untilEvent(emitter, eventName) {
return execution => {
let handle = (...args) => execution.resume(args);
emitter.on(eventName, handle);
return () => emitter.off(eventName, handle);
};
}
/**
* Spawn a process using command and arguments. It will raise if the child
* process has a non-zero exit status or is interrupted.
* e.g.
* ```js
* // spawn child process, and continue once it exits successfully.
* yield spawn("/usr/bin/chrome", ['--no-data-dir', '--disable-popups']);
*
* // spawn child process, but continue immediately.
* this.fork(spawn("/usr/bin/chrome", ['--no-data-dir', '--disable-popups']));
* ```
*/
function spawn(cmd, args) {
return function*() {
let process = child_process.spawn(cmd, args);
// listen for errors
let errors = this.fork(function*() {
let [ error ] = yield untilEvent(process, 'error');
throw error;
});
try {
let [ code, signal ] = yield untilEvent(process, 'exit');
if (code != null & code !== 0) {
let error = new Error(`'${cmd} ${args.join('')}' exited with non zero exit status`);
error.name = 'NonZeroExitError';
throw error;
} else if (signal != null) {
let error = new Error(`interrupted with ${signal}`);
error.name = 'SignalError';
throw error;
}
} finally {
errors.halt();
process.kill();
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment