Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
# `events`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Declares the typed `StreamsMetadataEvents` map consumed by every transform
in this package. `BaseTransform` from `@suaveplan/streams` already
carries a generic event API parameterised by an event-map type, so this
package does not need (and does not expose) a separate `EventEmitter`
property: every transform subclasses
`BaseTransform<{}, StreamsMetadataEvents>` and inherits typed
`on(name, fn)` / `off(name, fn)` methods.
The event map is the public observability contract — listeners attach to
the transform directly and receive strongly typed payloads, with
TypeScript rejecting accesses to fields that do not exist on the declared
payload.
## Features
- Single-source map of event name to payload type, consumed by all three
transforms and re-exported from the package root.
- Compatible with the `EventMap` constraint declared by
`@suaveplan/streams::BaseTransform`.
- Four events covering both child stages (`mime:detected`, `exif:detected`)
and the wrapper's lifecycle (`metadata:complete`, `metadata:error`).
## Usage: Basic Example
```ts
import { MetadataTransform } from "@suaveplan/streams-metadata";
const transform = new MetadataTransform();
transform.on("mime:detected", (r) => {
console.log("MIME:", r.mimeType, "source:", r.source);
});
transform.on("metadata:complete", (p) => {
console.log("Done:", p.mime?.mimeType, p.exif?.format);
});
```
## Usage: Advanced Example
```ts
import {
MetadataTransform,
type StreamsMetadataEvents,
} from "@suaveplan/streams-metadata";
const transform = new MetadataTransform();
const handlers: {
[K in keyof StreamsMetadataEvents]: (payload: StreamsMetadataEvents[K]) => void;
} = {
"mime:detected": (r) => console.log("MIME", r.priority, r.mimeType),
"exif:detected": (m) => console.log("EXIF", m.format),
"metadata:complete": (p) => console.log("OK", p.bytes.byteLength, "bytes"),
"metadata:error": (e) => console.error("FAIL", e),
};
for (const name of Object.keys(handlers) as (keyof StreamsMetadataEvents)[]) {
transform.on(name, handlers[name] as never);
}
```
## API Reference
- `type StreamsMetadataEvents`:
- `"mime:detected": MimeDetectionResult` — fired by `MimeTransform` (and
forwarded by `MetadataTransform`) after detection completes.
- `"exif:detected": ImageMetadata` — fired by `ExifTransform` (and
forwarded by `MetadataTransform`) after the underlying
`@suaveplan/exif::readMetadata` returns.
- `"metadata:complete": EnrichedPayload` — fired only by
`MetadataTransform`, once both children succeed.
- `"metadata:error": unknown` — fired only by `MetadataTransform` when
either child throws. The payload is the original thrown value.
## Implementation Notes
- The map is declared as a `type` alias (not an `interface`) so it
satisfies the structural `Readonly<Record<string, unknown>>` constraint
imposed by `@suaveplan/streams::EventMap` without interface widening.
- Field order is fixed for stable JSDoc generation: child events first,
wrapper events last.
- Adding a new event is a breaking change to the public API — bump the
package version and document it in the next archived spec change.