UNPKG

@akala/core

Version:
75 lines 3.22 kB
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