127fb2a470
- check size while reading stream instead of checking after reading all stream - move MAX_TARBALL_UPLOAD_SIZE_BYTES to config variables - increase MAX_TARBALL_UPLOAD_SIZE_BYTES default from 50Mb to 100Mb
89 lines
1.9 KiB
TypeScript
89 lines
1.9 KiB
TypeScript
import { type Readable } from 'stream';
|
|
|
|
export const streamToBuffer = async (
|
|
stream: Readable,
|
|
maxSizeBytes?: number,
|
|
): Promise<Buffer> => {
|
|
const chunks: Buffer[] = [];
|
|
let totalSize = 0;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
if (stream.readableEnded) {
|
|
reject(new Error('Stream has already ended'));
|
|
|
|
return;
|
|
}
|
|
|
|
if (!stream.readable) {
|
|
reject(new Error('Stream is not readable'));
|
|
|
|
return;
|
|
}
|
|
|
|
let isResolved = false;
|
|
|
|
const cleanup = () => {
|
|
stream.removeListener('data', onData);
|
|
stream.removeListener('end', onEnd);
|
|
stream.removeListener('error', onError);
|
|
stream.removeListener('close', onClose);
|
|
};
|
|
|
|
const onData = (chunk: Buffer) => {
|
|
if (!isResolved) {
|
|
totalSize += chunk.length;
|
|
|
|
if (maxSizeBytes !== undefined && totalSize > maxSizeBytes) {
|
|
isResolved = true;
|
|
cleanup();
|
|
stream.destroy();
|
|
reject(
|
|
new Error(
|
|
`Stream exceeds maximum allowed size of ${maxSizeBytes} bytes`,
|
|
),
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
chunks.push(chunk);
|
|
}
|
|
};
|
|
|
|
const onEnd = () => {
|
|
if (!isResolved) {
|
|
isResolved = true;
|
|
cleanup();
|
|
resolve(Buffer.concat(chunks));
|
|
}
|
|
};
|
|
|
|
const onError = (error: Error) => {
|
|
if (!isResolved) {
|
|
isResolved = true;
|
|
cleanup();
|
|
reject(error);
|
|
}
|
|
};
|
|
|
|
const onClose = () => {
|
|
if (!isResolved) {
|
|
if (stream.readableEnded) {
|
|
isResolved = true;
|
|
cleanup();
|
|
resolve(Buffer.concat(chunks));
|
|
} else {
|
|
isResolved = true;
|
|
cleanup();
|
|
reject(new Error('Stream closed before end'));
|
|
}
|
|
}
|
|
};
|
|
|
|
stream.on('data', onData);
|
|
stream.on('end', onEnd);
|
|
stream.on('error', onError);
|
|
stream.on('close', onClose);
|
|
});
|
|
};
|