Files
2026-05-27 23:47:53 +01:00

2.4 KiB

resolver.writes

Purpose

Implements the write(uri, body, signal?) semantics. Accepts either Uint8Array or ReadableStream<Uint8Array> for the body, forwards a native createWriteStream when the adapter exposes one and the body is a stream, and otherwise drains the stream (via new Response(stream).arrayBuffer()) into a single adapter.set call. The drain path increments storage_uri.buffered_write_total{scheme} so operators can alert on mis-composed adapters that quietly buffer large payloads.

SuaveplanError subclasses thrown by adapter.set (any package's namespaced error — DriveUriError, StorageHttpError, etc.) pass through unchanged so consumers can route on the original code. Non-namespaced throwables (plain Error, foreign objects) are wrapped as STORAGE_URI.WRITE_UNSUPPORTED with the original preserved as cause, giving a normalised failure mode for read-only adapters that lack their own error class.

Features

  • Branch on body shape via getReader duck-test.
  • Forward createWriteStream only when present AND body is a stream.
  • Drain-and-set fallback for both buffered bodies and missing createWriteStream.
  • SuaveplanError pass-through on adapter.set throw; WRITE_UNSUPPORTED wrap with cause preserved for non-namespaced throwables only.

Usage: Basic

import { writeViaPlugin } from "@suaveplan/storage-uri/resolver";

await writeViaPlugin(plugin, "file:///a.bin", "a.bin", new Uint8Array([1, 2, 3]), undefined);

Usage: Advanced

async function writeStream(resolver: StorageUriResolver, uri: string, src: AsyncIterable<Uint8Array>): Promise<void> {
    const stream = new ReadableStream<Uint8Array>({
        async start(ctrl) {
            for await (const chunk of src) ctrl.enqueue(chunk);
            ctrl.close();
        },
    });
    await resolver.write(uri, stream);
}

API Reference

  • function writeViaPlugin(plugin, uri, key, body, signal): Promise<void>

Implementation Notes

new Response(stream).arrayBuffer() is the cheapest cross-runtime way to drain a Web Stream into a contiguous buffer; it works in Node 18+, Bun, and every browser without any polyfill. The WRITE_UNSUPPORTED re-wrap is distinct from the ADAPTER_ERROR wrap in resolver.ts because callers typically branch on these two conditions differently — WRITE_UNSUPPORTED is a capability miss while ADAPTER_ERROR is a transient upstream fault.