7e68690c70
- Fix single-line anchor-echo stripping to trigger empty-insert validation - Fix trailing boundary-echo stripping for boundary-only payloads - Extract shared chunking logic to hashline-chunk-formatter - Align empty stream/iterable handling with formatHashLines - Add regression tests for all fixes
53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
export interface HashlineChunkFormatter {
|
|
push(formattedLine: string): string[]
|
|
flush(): string | undefined
|
|
}
|
|
|
|
interface HashlineChunkFormatterOptions {
|
|
maxChunkLines: number
|
|
maxChunkBytes: number
|
|
}
|
|
|
|
export function createHashlineChunkFormatter(options: HashlineChunkFormatterOptions): HashlineChunkFormatter {
|
|
const { maxChunkLines, maxChunkBytes } = options
|
|
let outputLines: string[] = []
|
|
let outputBytes = 0
|
|
|
|
const flush = (): string | undefined => {
|
|
if (outputLines.length === 0) return undefined
|
|
const chunk = outputLines.join("\n")
|
|
outputLines = []
|
|
outputBytes = 0
|
|
return chunk
|
|
}
|
|
|
|
const push = (formattedLine: string): string[] => {
|
|
const chunksToYield: string[] = []
|
|
const separatorBytes = outputLines.length === 0 ? 0 : 1
|
|
const lineBytes = Buffer.byteLength(formattedLine, "utf-8")
|
|
|
|
if (
|
|
outputLines.length > 0 &&
|
|
(outputLines.length >= maxChunkLines || outputBytes + separatorBytes + lineBytes > maxChunkBytes)
|
|
) {
|
|
const flushed = flush()
|
|
if (flushed) chunksToYield.push(flushed)
|
|
}
|
|
|
|
outputLines.push(formattedLine)
|
|
outputBytes += (outputLines.length === 1 ? 0 : 1) + lineBytes
|
|
|
|
if (outputLines.length >= maxChunkLines || outputBytes >= maxChunkBytes) {
|
|
const flushed = flush()
|
|
if (flushed) chunksToYield.push(flushed)
|
|
}
|
|
|
|
return chunksToYield
|
|
}
|
|
|
|
return {
|
|
push,
|
|
flush,
|
|
}
|
|
}
|