Initial setup of project dependencies including axios, express, dotenv, and other supporting packages. Added configuration files and documentation for project setup and usage.
88 lines
1.6 KiB
JavaScript
88 lines
1.6 KiB
JavaScript
|
|
export const streamChunk = function* (chunk, chunkSize) {
|
|
let len = chunk.byteLength;
|
|
|
|
if (!chunkSize || len < chunkSize) {
|
|
yield chunk;
|
|
return;
|
|
}
|
|
|
|
let pos = 0;
|
|
let end;
|
|
|
|
while (pos < len) {
|
|
end = pos + chunkSize;
|
|
yield chunk.slice(pos, end);
|
|
pos = end;
|
|
}
|
|
}
|
|
|
|
export const readBytes = async function* (iterable, chunkSize) {
|
|
for await (const chunk of readStream(iterable)) {
|
|
yield* streamChunk(chunk, chunkSize);
|
|
}
|
|
}
|
|
|
|
const readStream = async function* (stream) {
|
|
if (stream[Symbol.asyncIterator]) {
|
|
yield* stream;
|
|
return;
|
|
}
|
|
|
|
const reader = stream.getReader();
|
|
try {
|
|
for (;;) {
|
|
const {done, value} = await reader.read();
|
|
if (done) {
|
|
break;
|
|
}
|
|
yield value;
|
|
}
|
|
} finally {
|
|
await reader.cancel();
|
|
}
|
|
}
|
|
|
|
export const trackStream = (stream, chunkSize, onProgress, onFinish) => {
|
|
const iterator = readBytes(stream, chunkSize);
|
|
|
|
let bytes = 0;
|
|
let done;
|
|
let _onFinish = (e) => {
|
|
if (!done) {
|
|
done = true;
|
|
onFinish && onFinish(e);
|
|
}
|
|
}
|
|
|
|
return new ReadableStream({
|
|
async pull(controller) {
|
|
try {
|
|
const {done, value} = await iterator.next();
|
|
|
|
if (done) {
|
|
_onFinish();
|
|
controller.close();
|
|
return;
|
|
}
|
|
|
|
let len = value.byteLength;
|
|
if (onProgress) {
|
|
let loadedBytes = bytes += len;
|
|
onProgress(loadedBytes);
|
|
}
|
|
controller.enqueue(new Uint8Array(value));
|
|
} catch (err) {
|
|
_onFinish(err);
|
|
throw err;
|
|
}
|
|
},
|
|
cancel(reason) {
|
|
_onFinish(reason);
|
|
return iterator.return();
|
|
}
|
|
}, {
|
|
highWaterMark: 2
|
|
})
|
|
}
|