MCPcopy Create free account
hub / github.com/isomorphic-git/isomorphic-git / fromNodeStream

Function fromNodeStream

src/utils/fromNodeStream.js:2–61  ·  view source on GitHub ↗
(stream)

Source from the content-addressed store, hash-verified

1// Convert a Node stream to an Async Iterator
2export function fromNodeStream(stream) {
3 // Use native async iteration if it's available.
4 const asyncIterator = Object.getOwnPropertyDescriptor(
5 stream,
6 Symbol.asyncIterator
7 )
8 if (asyncIterator && asyncIterator.enumerable) {
9 return stream
10 }
11 // Author's Note
12 // I tried many MANY ways to do this.
13 // I tried two npm modules (stream-to-async-iterator and streams-to-async-iterator) with no luck.
14 // I tried using 'readable' and .read(), and .pause() and .resume()
15 // It took me two loooong evenings to get to this point.
16 // So if you are horrified that this solution just builds up a queue with no backpressure,
17 // and turns Promises inside out, too bad. This is the first code that worked reliably.
18 let ended = false
19 const queue = []
20 let defer = {}
21 stream.on('data', chunk => {
22 queue.push(chunk)
23 if (defer.resolve) {
24 defer.resolve({ value: queue.shift(), done: false })
25 defer = {}
26 }
27 })
28 stream.on('error', err => {
29 if (defer.reject) {
30 defer.reject(err)
31 defer = {}
32 }
33 })
34 stream.on('end', () => {
35 ended = true
36 if (defer.resolve) {
37 defer.resolve({ done: true })
38 defer = {}
39 }
40 })
41 return {
42 next() {
43 return new Promise((resolve, reject) => {
44 if (queue.length === 0 && ended) {
45 return resolve({ done: true })
46 } else if (queue.length > 0) {
47 return resolve({ value: queue.shift(), done: false })
48 } else if (queue.length === 0 && !ended) {
49 defer = { resolve, reject }
50 }
51 })
52 },
53 return() {
54 stream.removeAllListeners()
55 if (stream.destroy) stream.destroy()
56 },
57 [Symbol.asyncIterator]() {
58 return this
59 },
60 }

Callers 1

requestFunction · 0.90

Calls 1

resolveMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…