Files
skills/docs/foundation/flow/streams-metadata/README.md
2026-05-29 08:20:56 +01:00

4.7 KiB

@suaveplan/streams-metadata - Universal stream transforms that detect MIME type and extract EXIF/IPTC/XMP image metadata via @suaveplan/streams BaseTransform

Universal stream transforms that detect MIME type and extract EXIF/IPTC/XMP image metadata from buffered Uint8Array payloads. Three composable transforms (MimeTransform, ExifTransform, and the wrapping MetadataTransform) each extend BaseTransform from @suaveplan/streams and expose a typed event surface through the inherited on/off API.

Documentation tree

  • errors — Stable error registry for the @suaveplan/streams-metadata package. Every failure surface produced by MimeTransform,…
    • errors — Stable error registry for the @suaveplan/streams-metadata package. Every failure surface produced by MimeTransform,…
  • events — Declares the typed StreamsMetadataEvents map consumed by every transform in this package. BaseTransform fro…
    • events — Declares the typed StreamsMetadataEvents map consumed by every transform in this package. BaseTransform fro…
  • exif — ExifTransform is a universal stream transform that extracts ImageMetadata via @suaveplan/exif::readMetadata…
    • exif — ExifTransform is a universal stream transform that extracts ImageMetadata via @suaveplan/exif::readMetadata…
  • metadata — MetadataTransform is the high-level composing wrapper around MimeTransform and ExifTransform. A single instance r…
    • metadata — MetadataTransform is the high-level composing wrapper around MimeTransform and ExifTransform. A single instance r…
  • mime — MimeTransform is a universal stream transform that decides the MIME type of a buffered binary payload and (in `e…
    • mime — MimeTransform is a universal stream transform that decides the MIME type of a buffered binary payload and (in `e…
  • payload — Public type contract shared by every @suaveplan/streams-metadata transform. Callers and library code agree on the sha…
  • process-options — Defines the ProcessOptions shape accepted by every @suaveplan/streams-metadata transform's `process(input, options?…

Install

bun add @suaveplan/streams-metadata

Quick start

import { MetadataTransform } from "@suaveplan/streams-metadata";

const transform = new MetadataTransform();
const result = await transform.process({ bytes: imageBytes, name: "photo.jpg" });

console.log(result.mime?.mimeType); // "image/jpeg"
console.log(result.exif?.width);    // 1920

Manual composition

Use MimeTransform and ExifTransform separately when you need fine-grained control over each stage or want to run only one of them:

import { ExifTransform, MimeTransform } from "@suaveplan/streams-metadata";

const mime = new MimeTransform();
const exif = new ExifTransform({ read: { skipXmp: true } });

mime.on("mime:detected", (r) => console.log("MIME:", r.mimeType, "(source:", r.source, ")"));
exif.on("exif:detected", (m) => console.log("Dimensions:", m.width, "x", m.height));

const afterMime = await mime.process({ bytes: imageBytes, name: "photo.jpg" });
const afterExif = await exif.process(afterMime);

Error handling

MetadataTransform catches errors from either child transform, emits metadata:error with the thrown value, and returns the original input reference so the pipeline continues. MimeTransform never throws for unknown bytes — the fallback is application/octet-stream. ExifTransform wraps every reader exception as ExifFailedError (STREAMS_METADATA.EXIF_FAILED) preserving the original cause.

Modules