index.ts 4.2 KB

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