Files
twenty/packages/twenty-server/src/utils/stream-to-buffer.ts
T
martmull 127fb2a470 Increase size of tarball upload (#20767)
- 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
2026-05-20 12:39:11 +00:00

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);
});
};