whatwg-stream-to-async-iter
Version:
73 lines • 2.37 kB
JavaScript
const isIterable = (x) => x != null && typeof x === 'object' && Symbol.iterator in x;
const isAsyncIterable = (x) => x != null && typeof x === 'object' && Symbol.asyncIterator in x;
const forAwaitableIterator = (x) => isAsyncIterable(x)
? x[Symbol.asyncIterator]()
: isIterable(x)
? x[Symbol.iterator]()
: (() => { throw Error('Not for-awaitable. Neither Symbol.asyncIterator nor Symbol.iterator found.'); })();
export async function* streamToAsyncIterable(stream) {
const reader = stream.getReader();
try {
let { done, value } = await reader.read();
while (!done) {
yield value;
({ done, value } = await reader.read());
}
reader.releaseLock(); // FIXME: is this necessary?
}
catch (err) {
throw err;
}
}
// Older version of Cloudflare Workers do not support the `ReadableStream` constructor,
// so we use a TransformStream instead:
function asyncIterableToStreamTS(iterable) {
const { readable, writable } = new TransformStream();
(async () => {
const writer = writable.getWriter();
try {
for await (const x of iterable)
writer.write(x);
writer.close();
}
catch (err) {
writer.abort(err);
}
})();
return readable;
}
function asyncIterableToStreamRS(iterable) {
let iterator;
return new ReadableStream({
start() {
iterator = forAwaitableIterator(iterable);
},
async pull(controller) {
const { value, done } = await iterator.next();
if (!done)
controller.enqueue(value);
else
controller.close();
},
async cancel(reason) {
var _a;
try {
await ((_a = iterator.throw) === null || _a === void 0 ? void 0 : _a.call(iterator, reason));
}
catch (_b) { }
},
});
}
const tryReadableStream = () => {
try {
return !!new ReadableStream({});
}
catch (_a) {
return false;
}
};
export const asyncIterableToStream = tryReadableStream()
? asyncIterableToStreamRS
: asyncIterableToStreamTS;
export { streamToAsyncIterable as streamToAsyncIter, asyncIterableToStream as asyncIterToStream, };
//# sourceMappingURL=index.js.map