spawn.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import crossSpawn from 'cross-spawn'
  2. import logger from './logger'
  3. const log = logger('app:spawn')
  4. const warn = logger('app:spawn', 'red')
  5. /*
  6. Returns pid, takes onClose
  7. */
  8. export const spawn = (
  9. cmd: string,
  10. params: string[],
  11. cwd: string,
  12. onClose?: (code: number) => void
  13. ): number => {
  14. log(`Running "${cmd} ${params.join(' ')}"`)
  15. log()
  16. // TODO: move to execa?
  17. const runner = crossSpawn(cmd, params, {
  18. stdio: 'inherit',
  19. cwd,
  20. env: process.env
  21. })
  22. runner.on('close', code => {
  23. log()
  24. if (code) {
  25. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
  26. log(`Command "${cmd}" failed with exit code: ${code}`)
  27. }
  28. // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
  29. onClose && onClose(code)
  30. })
  31. return runner.pid
  32. }
  33. /*
  34. Returns nothing, takes onFail
  35. */
  36. export const spawnSync = (
  37. cmd: string,
  38. params: string[],
  39. cwd: string,
  40. onFail?: () => void
  41. ): void => {
  42. log(`[sync] Running "${cmd} ${params.join(' ')}"`)
  43. log()
  44. const runner = crossSpawn.sync(cmd, params, {
  45. stdio: 'inherit',
  46. cwd
  47. })
  48. // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
  49. if (runner.status || runner.error) {
  50. warn()
  51. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
  52. warn(`⚠️ Command "${cmd}" failed with exit code: ${runner.status}`)
  53. if (runner.status === null) {
  54. warn(`⚠️ Please globally install "${cmd}"`)
  55. }
  56. // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
  57. onFail && onFail()
  58. process.exit(1)
  59. }
  60. }