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:
@@ -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.
|
||||
Reference in New Issue
Block a user