index.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { exec as shell_exec, spawn as shell_spawn } from 'child_process';
  2. const MAX_BUFFER = 10 * Math.pow(2, 20);
  3. export function exec(
  4. command: string,
  5. stdout?: ((...args) => void) | NodeJS.WriteStream,
  6. stderr?: ((...args) => void) | NodeJS.WriteStream,
  7. stdin?: NodeJS.ReadableStream | string
  8. ) {
  9. return new Promise<string>((resolve, reject) => {
  10. try {
  11. let stdoutbuf = '';
  12. let stderrbuf = '';
  13. // EXEC CHILD PROCESS
  14. const p = shell_exec(command, { maxBuffer: MAX_BUFFER }, (err, out) => {
  15. if (err) return reject(err);
  16. if (stdoutbuf.length > 0 && typeof stdout === 'function') stdout(stdoutbuf);
  17. if (stderrbuf.length > 0 && typeof stderr === 'function') stderr(stderrbuf);
  18. resolve(out);
  19. });
  20. // PIPE STDIN (?)
  21. if (typeof stdin === 'string') {
  22. p.stdin.setDefaultEncoding('utf-8');
  23. if (!stdin.endsWith('\n')) stdin += '\n';
  24. p.stdin.write(stdin);
  25. p.stdin.end();
  26. } else if (typeof stdin !== 'undefined') {
  27. stdin.pipe(p.stdin);
  28. }
  29. // PIPE STDOUT
  30. if (typeof stdout === 'function') {
  31. p.stdout.on('data', (chunk) => {
  32. stdoutbuf += chunk;
  33. let i = -1;
  34. while ((i = stdoutbuf.indexOf('\n')) >= 0) {
  35. const line = stdoutbuf.substring(0, i);
  36. stdoutbuf = stdoutbuf.substring(i + 1);
  37. if (typeof stdout === 'function') {
  38. stdout(line);
  39. }
  40. }
  41. });
  42. } else if (typeof stdout !== 'undefined') {
  43. p.stdout.pipe(stdout);
  44. }
  45. // PIPE STDERR
  46. if (typeof stderr === 'function') {
  47. p.stderr.on('data', (chunk) => {
  48. stderrbuf += chunk;
  49. let i = -1;
  50. while ((i = stderrbuf.indexOf('\n')) >= 0) {
  51. const line = stderrbuf.substring(0, i);
  52. stderrbuf = stderrbuf.substring(i + 1);
  53. if (typeof stderr === 'function') {
  54. stderr(line);
  55. }
  56. }
  57. });
  58. } else if (typeof stderr !== 'undefined') {
  59. p.stderr.pipe(stderr);
  60. }
  61. } catch (err) {
  62. reject(err);
  63. }
  64. });
  65. }
  66. export function spawn(
  67. command: string,
  68. args: string[],
  69. stdout?: ((...args) => void) | NodeJS.WriteStream,
  70. stderr?: ((...args) => void) | NodeJS.WriteStream,
  71. stdin?: NodeJS.ReadableStream | string
  72. ) {
  73. return new Promise<void>((resolve, reject) => {
  74. try {
  75. let stdoutbuf = '';
  76. let stderrbuf = '';
  77. const p = shell_spawn(command, args);
  78. // PIPE STDIN (?)
  79. if (typeof stdin === 'string') {
  80. p.stdin.setDefaultEncoding('utf-8');
  81. if (!stdin.endsWith('\n')) stdin += '\n';
  82. p.stdin.write(stdin);
  83. p.stdin.end();
  84. } else if (typeof stdin !== 'undefined') {
  85. stdin.pipe(p.stdin);
  86. }
  87. // PIPE STDOUT
  88. if (typeof stdout === 'function') {
  89. p.stdout.on('data', (chunk) => {
  90. stdoutbuf += chunk;
  91. let i = -1;
  92. while ((i = stdoutbuf.indexOf('\n')) >= 0) {
  93. const line = stdoutbuf.substring(0, i);
  94. stdoutbuf = stdoutbuf.substring(i + 1);
  95. if (typeof stdout === 'function') {
  96. stdout(line);
  97. }
  98. }
  99. });
  100. } else if (typeof stdout !== 'undefined') {
  101. p.stdout.pipe(stdout);
  102. }
  103. // PIPE STDERR
  104. if (typeof stderr === 'function') {
  105. p.stderr.on('data', (chunk) => {
  106. stderrbuf += chunk;
  107. let i = -1;
  108. while ((i = stderrbuf.indexOf('\n')) >= 0) {
  109. const line = stderrbuf.substring(0, i);
  110. stderrbuf = stderrbuf.substring(i + 1);
  111. if (typeof stderr === 'function') {
  112. stderr(line);
  113. }
  114. }
  115. });
  116. } else if (typeof stderr !== 'undefined') {
  117. p.stderr.pipe(stderr);
  118. }
  119. p.on('close', (code, sig) => {
  120. if (!code) resolve();
  121. else reject();
  122. });
  123. p.on('error', reject);
  124. p.on('exit', (code, sig) => {
  125. if (!code) resolve();
  126. else reject();
  127. });
  128. } catch (err) {
  129. reject(err);
  130. }
  131. });
  132. }