46 lines
1.1 KiB
TypeScript
46 lines
1.1 KiB
TypeScript
/**
|
|
* Parse an NDJSON (newline-delimited JSON) stream into an async generator.
|
|
*
|
|
* Works with both Node.js `ReadableStream` and browser `ReadableStream<Uint8Array>`.
|
|
* Handles partial lines across chunk boundaries gracefully.
|
|
*/
|
|
export async function* parseNdjsonStream<T = unknown>(
|
|
body: ReadableStream<Uint8Array>
|
|
): AsyncGenerator<T> {
|
|
const reader = body.getReader();
|
|
const decoder = new TextDecoder();
|
|
let buffer = '';
|
|
|
|
try {
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
|
|
buffer += decoder.decode(value, { stream: true });
|
|
const lines = buffer.split('\n');
|
|
buffer = lines.pop() ?? '';
|
|
|
|
for (const line of lines) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed) continue;
|
|
try {
|
|
yield JSON.parse(trimmed) as T;
|
|
} catch {
|
|
// skip malformed lines
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process remaining buffer after stream ends
|
|
if (buffer.trim()) {
|
|
try {
|
|
yield JSON.parse(buffer.trim()) as T;
|
|
} catch {
|
|
// skip
|
|
}
|
|
}
|
|
} finally {
|
|
reader.releaseLock();
|
|
}
|
|
}
|