@akala/core
Version:
75 lines • 3.22 kB
JavaScript
import ErrorWithStatus, { HttpStatusCode } from "../errorWithStatus.js";
import { IsomorphicBuffer } from "../helpers.js";
/**
* Error thrown when a message is incomplete and cannot be processed.
* Used by protocol adapters to indicate that more data is needed to complete the message.
*/
export class IncompleteMessageError extends Error {
transformedMessages;
remainingPart;
constructor(transformedMessages, remainingPart) {
super();
this.transformedMessages = transformedMessages;
this.remainingPart = remainingPart;
}
}
/**
* Protocol adapter that buffers incomplete messages until they are complete.
* Extends SocketProtocolAdapter to handle fragmented messages by accumulating
* data until a complete message can be processed.
* @template T The type of messages after transformation
*/
export function LongMessageProtocolTransformer(transform) {
const buffer = [];
return {
receive: (data, self) => {
try {
buffer.push(data);
const result = transform.receive(buffer, self);
buffer.length = 0;
return result;
}
catch (e) {
if (e instanceof IncompleteMessageError) {
buffer.splice(0, buffer.length, ...e.remainingPart);
return e.transformedMessages;
}
else if (e.statusCode == HttpStatusCode.PartialContent) {
buffer.push(data);
return [];
}
}
},
send(data, self) {
const chunks = transform.send(data, self);
if (!chunks.length)
return undefined;
if (chunks.length == 1)
return chunks[0];
if (chunks.length > 1) {
let stringCount = 0;
let bufferCount = 0;
for (const chunk of chunks) {
if (typeof chunk == 'string')
stringCount++;
else if (chunk instanceof IsomorphicBuffer)
bufferCount++;
else
throw new ErrorWithStatus(HttpStatusCode.BadRequest, 'Expected a string or IsomorphicBuffer, but got ' + typeof chunk);
}
if (bufferCount == chunks.length)
return IsomorphicBuffer.concat(chunks);
if (stringCount == chunks.length)
return chunks.reduce((previous, current) => previous + current, '');
if (stringCount > bufferCount)
return chunks.reduce((previous, current) => previous + (typeof current == 'string' ? current : current.toString('utf8')), '');
else if (bufferCount == chunks.length)
return IsomorphicBuffer.concat(chunks).toString('utf-8');
else
return IsomorphicBuffer.concat(chunks.map(chunk => typeof chunk == 'string' ? IsomorphicBuffer.from(chunk) : chunk));
}
},
close: transform.close?.bind(transform)
};
}
//# sourceMappingURL=shared.long-message-protocol-transformer.js.map