3.1 KiB
bunny-cdn-adapter.streams
Purpose
Builds the ReadableStream and WritableStream instances BunnyCdnAdapter returns from createReadStream / createWriteStream. Splits the stream plumbing out of the main class body so each piece can be unit-tested without instantiating the full adapter.
buildReadStream lazily resolves the StorageClientCtx promise on the first pull (the adapter passes a promise that resolves once headers are computed) then pumps the Response.body chunks 1:1 to the consumer. buildWriteStream buffers chunks until close and dispatches via the caller-supplied commit callback — the adapter passes (body, signal) => this.set(safe, body, undefined, signal) so the write goes through the OTel-wrapped set path.
Features
- Native streaming:
buildReadStreamreturnsResponse.bodychunks without buffering. - Error propagation: mid-stream errors surface via
controller.error; aborts propagate through the underlying fetch's signal. buildWriteStreamaccepts an injectablecommitcallback so the adapter (or test fixtures) controls how the buffered body is shipped.abort()handler drops buffered chunks promptly so memory does not linger after cancellation.
Usage: Basic
import { buildReadStream, buildWriteStream } from "@suaveplan/storage-cdn-bunnycdn";
const stream = buildReadStream(ctxPromise, "k", signal);
for await (const chunk of stream) processChunk(chunk);
Usage: Advanced
import { buildWriteStream } from "@suaveplan/storage-cdn-bunnycdn";
const ws = buildWriteStream({
key: "k",
signal,
commit: async (body, s) => storage.set("k", body, undefined, s),
});
const writer = ws.getWriter();
await writer.write(chunk);
await writer.close(); // triggers commit
API Reference
buildReadStream(ctxPromise, key, signal?): ReadableStream<Uint8Array>
Starts the GET on first read; pumps the response body until done. Response.body === null closes the stream cleanly without enqueueing.
interface WriteStreamArgs
{ key, signal, commit } — commit(body, signal) is invoked once at close time with the concatenated buffer.
buildWriteStream(args): WritableStream<Uint8Array>
Buffers chunks, concatenates on close, dispatches via commit. abort() clears the buffer without committing.
Implementation Notes
- Buffered-then-flush is the right tradeoff for BunnyCDN Storage PUT: their API expects a known
Content-Length, which means chunked transfers without orchestration aren't supported. Provider-specific streaming uploads (the documented multi-part upload pattern) belong in a separate helper. abort()clearschunksrather than reusing the array — clearing length forces garbage collection of every enqueued buffer once the writer releases its reference.releaseLock()on the response body reader runs infinallyso a mid-stream error doesn't leak the lock.ctxPromiseis awaited insidestart; if header resolution fails (e.g. a caller-supplied asyncheaderscallback rejects), the rejection surfaces viacontroller.error, which is what consumers expect for stream initialisation failures.