Files
skills/docs/persistence/storage/storage-uri-plugin-bundle
2026-05-29 08:20:56 +01:00
..
2026-05-29 08:20:56 +01:00
2026-05-29 08:20:56 +01:00

@suaveplan/storage-uri-plugin-bundle - Per-package bundle:// URI scheme plugin for @suaveplan/storage-uri. Universal; resolves bundle:/// against an injectable rootUrl via fetch on every read. Read-only StorageLike shim, HTTP Range support with 200/206/416 disambiguation, AbortSignal propagation, optional in-memory LRU, full OpenTelemetry surface.

Per-package bundle:// URI scheme for @suaveplan/storage-uri.

bundle://<package-slug>/<rel-path> lets a consuming package ship binary assets — impulse responses, sample fonts, reference images, fixture bundles — alongside its npm tarball and resolve them through the existing storage-uri ecosystem. The plugin is universal: zero node:fs, zero browser-only branches, every read goes through an injectable FetchLike against new URL(encodedRelPath, rootUrl). file:, https:, http:, data:, blob:, and bundler-virtual schemes all flow through the same fetch surface.

Documentation tree

  • abort — abort.ts declares the two helpers every read path consumes to honour an AbortSignal: ensureNotAborted short-circu…
    • abort — abort.ts declares the two helpers every read path consumes to honour an AbortSignal: ensureNotAborted short-circu…
  • cache — cache.ts declares the optional in-memory LRU used by the storage shim when a caller passes `options.cache = { maxByte…
    • cache — cache.ts declares the optional in-memory LRU used by the storage shim when a caller passes `options.cache = { maxByte…
  • error-codes — error-codes.ts declares the canonical registry of every error code raised by @suaveplan/storage-uri-plugin-bundle a…
    • error-codes — error-codes.ts declares the canonical registry of every error code raised by @suaveplan/storage-uri-plugin-bundle a…
  • factory — factory.ts is the public entry point for @suaveplan/storage-uri-plugin-bundle. bundleUriPlugin(options) validates…
    • factory — factory.ts is the public entry point for @suaveplan/storage-uri-plugin-bundle. bundleUriPlugin(options) validates…
  • node-fetch — nodeFileFetch is a server-tier FetchLike that closes a real gap in Node's global fetch: undici (the engine backin…
    • node-fetch — nodeFileFetch is a server-tier FetchLike that closes a real gap in Node's global fetch: undici (the engine backin…
  • otel — otel.ts exposes the tracer, meter, and instrument bag that every read path in @suaveplan/storage-uri-plugin-bundle…
    • otel — otel.ts exposes the tracer, meter, and instrument bag that every read path in @suaveplan/storage-uri-plugin-bundle…
  • parse — parse.ts enforces the bundle://<package-slug>/<rel-path> grammar declared in design.md §1 and rejects every malfo…
    • parse — parse.ts enforces the bundle://<package-slug>/<rel-path> grammar declared in design.md §1 and rejects every malfo…
  • range — range.ts implements the building blocks the storage shim uses to issue HTTP Range requests and disambiguate the thr…
    • range — range.ts implements the building blocks the storage shim uses to issue HTTP Range requests and disambiguate the thr…
  • storage-shim — storage-shim.ts declares BundleStorageShim, the StorageLike adapter the bundle:// URI plugin exposes. The class…
    • storage-shim.fetch — storage-shim.fetch.ts carries the two cross-cutting helpers every storage-shim method uses: safeFetch dispatches an…
    • storage-shim.head — storage-shim.head.ts implements the two HEAD-routed methods of the bundle storage shim. performExists returns a boo…
    • storage-shim — storage-shim.ts declares BundleStorageShim, the StorageLike adapter the bundle:// URI plugin exposes. The class…
    • storage-shim.range — storage-shim.range.ts carries the full getPartial pipeline: pre-fetch offset/length validation, the `Range: bytes=……
  • streaming — streaming.ts exposes the single helper the storage shim consumes from its createReadStream implementation: given a…
    • streaming — streaming.ts exposes the single helper the storage shim consumes from its createReadStream implementation: given a…
  • types — plugin-options.schemas.ts declares the Zod schema that validates BundleUriPluginOptions at construction time. The s…
    • plugin-options.schemas — plugin-options.schemas.ts declares the Zod schema that validates BundleUriPluginOptions at construction time. The s…

Modules

  • ./error-codes/error-codes — BUNDLE_URI_CODES (9 codes) + BundleUriError.
  • ./factory/factory — bundleUriPlugin(options) entry point.
  • ./parse/parse — parse + build with three-pass traversal prevention.
  • ./storage-shim/storage-shim — BundleStorageShim (StorageLike).
  • ./storage-shim/storage-shim.fetch — safeFetch + assertSuccess.
  • ./storage-shim/storage-shim.head — HEAD-backed exists / getMetadata.
  • ./storage-shim/storage-shim.range — Range pipeline with 206/200/416 disambiguation.
  • ./range/range — validateRange, buildRangeHeader, sliceForRange.
  • ./streaming/streaming — toReadableStream.
  • ./abort/abort — ensureNotAborted + wrapAbortError.
  • ./cache/cache — UriLruCache.
  • ./otel/otel — meter + tracer wiring, recordOp, fallback counters.
  • ./node-fetch — server-tier opt-in FetchLike for Node consumers whose rootUrl is a file:// URL (see Node users + file:// roots).

Quick start — register one plugin per consuming package

import { createStorageUriResolver } from "@suaveplan/storage-uri";
import { bundleUriPlugin } from "@suaveplan/storage-uri-plugin-bundle";

const resolver = createStorageUriResolver({});

// In each consuming package's `register()`:
resolver.register(
    bundleUriPlugin({
        packageSlug: "audio-ir-room-plugin-club",
        rootUrl: new URL("./", import.meta.url),
    })
);

const bytes = await resolver.read(
    "bundle://audio-ir-room-plugin-club/assets/club.wav"
);

Bundler composition — flatten assets to a CDN URL

Vite, esbuild, and webpack all rewrite new URL("./assets/x.wav", import.meta.url) at build time. Register the plugin with a rootUrl pointing at the flattened asset directory and the runtime fetch transparently lands on the bundler-produced URL:

// Vite / esbuild / webpack
import assetsRoot from "./assets/?url"; // → flattened bundle URL

bundleUriPlugin({
    packageSlug: "audio-ir-room-plugin-club",
    rootUrl: assetsRoot, // bundler-rewritten string is fine
});

In production this becomes a real HTTPS URL — bundle:// still resolves the relative path inside that root through fetch, and the OTel surface classifies the root as root_kind="http".

Node users + file:// roots

Node's global fetch (undici, all releases through Node 24) does NOT support file: URLs. If your rootUrl is a file:// URL and you are running on Node, the default globalThis.fetch wiring will reject on the first get. The package ships a dedicated server-tier adapter at the ./node-fetch subpath that closes the gap:

import { bundleUriPlugin } from "@suaveplan/storage-uri-plugin-bundle";
import { nodeFileFetch } from "@suaveplan/storage-uri-plugin-bundle/node-fetch";

const plugin = bundleUriPlugin({
    packageSlug: "audio-ir-room-plugin-club",
    rootUrl: new URL("./assets/", import.meta.url),
    fetch: nodeFileFetch, // ← required on Node when rootUrl is file://
});

nodeFileFetch reads file: URLs via node:fs/promises, returns a real Response with content-length + last-modified, honours HEAD and Range: bytes=<start>-<end> (including open-ended bytes=10-), and threads init.signal into the underlying read. Any non-file: URL falls through to globalThis.fetch, so a single adapter handles both local-disk and CDN roots without branching at the call site.

Bun's native fetch already supports file: URLs — Bun consumers can keep using the default globalThis.fetch wiring. The subpath import exists so the package's default export stays universal-pure (no node:* imports leak into browser, Cloudflare Workers, Deno, or React Native builds).

Composition — front the plugin with storage-plugin-cache

import { cachedStorage } from "@suaveplan/storage-plugin-cache";
import { MemoryCache } from "@suaveplan/cache";

const cache = new MemoryCache<Uint8Array>();
const cached = cachedStorage(plugin.adapter, { cache, namespace: "bundle" });

Error codes

BUNDLE_URI.PACKAGE_MISMATCH, PATH_TRAVERSAL, READ_ONLY, NOT_FOUND, INVALID_URI, FETCH_FAILED, RANGE_INVALID, RANGE_UNSUPPORTED, ABORTED — all reachable from a real call site exercised by the test suite.

OpenTelemetry

  • bundle_uri.op_duration_ms{op, root_kind, outcome} histogram.
  • bundle_uri.reads_total{root_kind, outcome} counter.
  • bundle_uri.errors_total{root_kind, code} counter.
  • bundle_uri.range_fallback_total{root_kind} counter.
  • bundle_uri.cache_hits_total{root_kind} / bundle_uri.cache_misses_total{root_kind} counters.
  • Per-op span on the @suaveplan/storage-uri-plugin-bundle tracer with bundle.package, bundle.rel_path (query-stripped + 256-char clip), bundle.root_kind (file | http | data | blob | other), bundle.outcome attributes.

Inject a MeterProvider with setBundleUriMeterProvider(provider) then resetInstruments() to rebind.