版博士V2.0程序
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

stream.js 2.9 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import {createReadStream, readFileSync} from 'node:fs';
  2. import {isStream} from 'is-stream';
  3. import getStream from 'get-stream';
  4. import mergeStream from 'merge-stream';
  5. const validateInputOptions = input => {
  6. if (input !== undefined) {
  7. throw new TypeError('The `input` and `inputFile` options cannot be both set.');
  8. }
  9. };
  10. const getInputSync = ({input, inputFile}) => {
  11. if (typeof inputFile !== 'string') {
  12. return input;
  13. }
  14. validateInputOptions(input);
  15. return readFileSync(inputFile);
  16. };
  17. // `input` and `inputFile` option in sync mode
  18. export const handleInputSync = options => {
  19. const input = getInputSync(options);
  20. if (isStream(input)) {
  21. throw new TypeError('The `input` option cannot be a stream in sync mode');
  22. }
  23. return input;
  24. };
  25. const getInput = ({input, inputFile}) => {
  26. if (typeof inputFile !== 'string') {
  27. return input;
  28. }
  29. validateInputOptions(input);
  30. return createReadStream(inputFile);
  31. };
  32. // `input` and `inputFile` option in async mode
  33. export const handleInput = (spawned, options) => {
  34. const input = getInput(options);
  35. if (input === undefined) {
  36. return;
  37. }
  38. if (isStream(input)) {
  39. input.pipe(spawned.stdin);
  40. } else {
  41. spawned.stdin.end(input);
  42. }
  43. };
  44. // `all` interleaves `stdout` and `stderr`
  45. export const makeAllStream = (spawned, {all}) => {
  46. if (!all || (!spawned.stdout && !spawned.stderr)) {
  47. return;
  48. }
  49. const mixed = mergeStream();
  50. if (spawned.stdout) {
  51. mixed.add(spawned.stdout);
  52. }
  53. if (spawned.stderr) {
  54. mixed.add(spawned.stderr);
  55. }
  56. return mixed;
  57. };
  58. // On failure, `result.stdout|stderr|all` should contain the currently buffered stream
  59. const getBufferedData = async (stream, streamPromise) => {
  60. // When `buffer` is `false`, `streamPromise` is `undefined` and there is no buffered data to retrieve
  61. if (!stream || streamPromise === undefined) {
  62. return;
  63. }
  64. stream.destroy();
  65. try {
  66. return await streamPromise;
  67. } catch (error) {
  68. return error.bufferedData;
  69. }
  70. };
  71. const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => {
  72. if (!stream || !buffer) {
  73. return;
  74. }
  75. if (encoding) {
  76. return getStream(stream, {encoding, maxBuffer});
  77. }
  78. return getStream.buffer(stream, {maxBuffer});
  79. };
  80. // Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all)
  81. export const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => {
  82. const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer});
  83. const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer});
  84. const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2});
  85. try {
  86. return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]);
  87. } catch (error) {
  88. return Promise.all([
  89. {error, signal: error.signal, timedOut: error.timedOut},
  90. getBufferedData(stdout, stdoutPromise),
  91. getBufferedData(stderr, stderrPromise),
  92. getBufferedData(all, allPromise),
  93. ]);
  94. }
  95. };