spawn.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. 'use strict';
  2. const spawn = require('cross-spawn');
  3. const Promise = require('bluebird');
  4. const CacheStream = require('./cache_stream');
  5. function promiseSpawn(command, args = [], options = {}) {
  6. if (!command) throw new TypeError('command is required!');
  7. if (typeof args === 'string') args = [args];
  8. if (!Array.isArray(args)) {
  9. options = args;
  10. args = [];
  11. }
  12. return new Promise((resolve, reject) => {
  13. const task = spawn(command, args, options);
  14. const verbose = options.verbose;
  15. const { encoding = 'utf8' } = options;
  16. const stdoutCache = new CacheStream();
  17. const stderrCache = new CacheStream();
  18. if (task.stdout) {
  19. const stdout = task.stdout.pipe(stdoutCache);
  20. if (verbose) stdout.pipe(process.stdout);
  21. }
  22. if (task.stderr) {
  23. const stderr = task.stderr.pipe(stderrCache);
  24. if (verbose) stderr.pipe(process.stderr);
  25. }
  26. task.on('close', code => {
  27. if (code) {
  28. const e = new Error(getCache(stderrCache, encoding));
  29. e.code = code;
  30. return reject(e);
  31. }
  32. resolve(getCache(stdoutCache, encoding));
  33. });
  34. task.on('error', reject);
  35. // Listen to exit events if neither stdout and stderr exist (inherit stdio)
  36. if (!task.stdout && !task.stderr) {
  37. task.on('exit', code => {
  38. if (code) {
  39. const e = new Error('Spawn failed');
  40. e.code = code;
  41. return reject(e);
  42. }
  43. resolve();
  44. });
  45. }
  46. });
  47. }
  48. function getCache(stream, encoding) {
  49. const buf = stream.getCache();
  50. stream.destroy();
  51. if (!encoding) return buf;
  52. return buf.toString(encoding);
  53. }
  54. module.exports = promiseSpawn;