2
0

shell.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. const { spawn, spawnSync, exec, execFile } = require('child_process')
  2. const { promisify } = require('util')
  3. function betterExec(cmd, options = {}, callback) {
  4. let childProcess
  5. let cmdStr, cmdPath, cmdArgs
  6. if (Array.isArray(cmd)) {
  7. cmdPath = cmd[0]
  8. cmdArgs = cmd.slice(1)
  9. } else {
  10. cmdStr = cmd
  11. }
  12. function callbackWrap(error, res) {
  13. if (callback) {
  14. callback(error, res)
  15. }
  16. if (error && options.exitOnError) {
  17. process.exit(1) // TODO: somehow get exit code
  18. }
  19. }
  20. if (options.live) {
  21. childProcess = spawn(cmdPath || cmdStr, cmdArgs, {
  22. shell: !cmdArgs,
  23. stdio: 'inherit',
  24. ...options
  25. })
  26. childProcess.on('close', function(code) {
  27. callbackWrap(
  28. code === 0 ? null : new Error('shell command failed'),
  29. { success: code === 0 }
  30. )
  31. })
  32. } else if (cmdArgs) { // array of tokens
  33. childProcess = execFile(cmdPath, cmdArgs, {
  34. encoding: 'utf8',
  35. ...options
  36. }, function(error, stdout, stderr) {
  37. callbackWrap(error, { stdout, stderr, success: !error })
  38. })
  39. } else { // exec in a shell
  40. childProcess = exec(cmdStr, {
  41. encoding: 'utf8',
  42. ...options
  43. }, function(error, stdout, stderr) {
  44. callbackWrap(error, { stdout, stderr, success: !error })
  45. })
  46. }
  47. return childProcess
  48. }
  49. function betterExecSync(cmd, options = {}) {
  50. let cmdStr, cmdPath, cmdArgs
  51. if (Array.isArray(cmd)) {
  52. cmdPath = cmd[0]
  53. cmdArgs = cmd.slice(1)
  54. } else {
  55. cmdStr = cmd
  56. }
  57. let res = spawnSync(cmdPath || cmdStr, cmdArgs, {
  58. encoding: 'utf8',
  59. shell: !cmdArgs,
  60. stdio: options.live ? 'inherit' : 'pipe',
  61. ...options
  62. })
  63. if (res.status !== 0 && options.exitOnError) {
  64. process.exit(res.status)
  65. }
  66. return { ...res, success: res.status === 0 }
  67. }
  68. function withOptions(baseOptions = {}) {
  69. let origFunc = this
  70. return (cmd, options) => {
  71. return origFunc(cmd, { ...baseOptions, ...options })
  72. }
  73. }
  74. betterExec.withOptions = withOptions
  75. betterExec.sync = betterExecSync
  76. betterExec.sync.withOptions = withOptions
  77. betterExec.promise = promisify(betterExec)
  78. betterExec.promise.withOptions = withOptions
  79. module.exports = betterExec
  80. /* parsing workspaces
  81. const PROJECT_ROOT = path.resolve(__dirname, '..')
  82. let res = exec('yarn', [ 'workspaces', '--json', 'info' ], { // order of args matters
  83. cwd: PROJECT_ROOT
  84. })
  85. if (!res.success) {
  86. console.error(res.stderr)
  87. process.exit(1)
  88. } else {
  89. let workspaces
  90. try {
  91. let wrapper = JSON.parse(res.stdout)
  92. workspaces = JSON.parse(wrapper.data)
  93. } catch(err) {
  94. console.error('Couldn\'t parse JSON')
  95. process.exit(1)
  96. }
  97. console.log(workspaces)
  98. }
  99. */