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,106 @@
# `options.ts` — Zod schema for `EventBusPluginOptions`
## Purpose
Boundary Zod schema validated by `createEventBusPlugin(options)` at
the factory entry point. Invalid input produces an
`EventBusError(EVENT_BUS.INVALID_INPUT)` carrying the underlying
`ZodError` as `cause` — callers always see a typed failure, never an
`unknown` parse error from upstream code paths. Schema is `.strict()`
so unknown keys fail loudly (typos in option names surface immediately
rather than producing silent no-ops).
## Features
- Single schema (`EventBusPluginOptionsSchema`) covering the full
option surface with sane defaults applied.
- Sub-schemas exported for downstream reuse:
`BackpressureOptionsSchema`, `IdempotencyOptionsSchema`.
- Schema produces a fully-resolved
`EventBusPluginOptionsResolved` type (defaults applied) suitable for
passing as `PluginDescriptor.defaults`.
- Strict mode prevents typo classes like `applySchema: true` (the
wrong package's option) from silently being ignored.
## Usage: Basic
```ts
import { EventBusPluginOptionsSchema } from "@suaveplan/api-plugin-event-bus/schemas/options";
const resolved = EventBusPluginOptionsSchema.parse({});
console.log(resolved.routePrefix); // "/event-bus"
console.log(resolved.backpressure.policy); // "drop-oldest"
```
## Usage: Advanced
```ts
import {
EventBusPluginOptionsSchema,
type EventBusPluginOptionsInput,
} from "@suaveplan/api-plugin-event-bus/schemas/options";
const input: EventBusPluginOptionsInput = {
backpressure: { capacity: 32, policy: "throw" },
idempotency: { enabled: true, cacheCapacity: 8192 },
routePrefix: "/bus",
mountRoutes: false,
requireAuthForRoutes: false,
tenantIsolation: false,
interceptors: [
async (env, next) => {
console.log("emit", env.type);
return next();
},
],
};
const resolved = EventBusPluginOptionsSchema.parse(input);
```
## API Reference
### `EventBusPluginOptionsSchema`
Strict object schema producing `EventBusPluginOptionsResolved`. Fields:
- `interceptors: Interceptor[]` (default `[]`).
- `backpressure: { capacity: number; policy: QueuePolicy }`.
- `idempotency: { enabled: boolean; cacheCapacity: number }`.
- `routePrefix: string` (default `"/event-bus"`).
- `mountRoutes: boolean` (default `true`).
- `requireAuthForRoutes: boolean` (default `true`).
- `tenantIsolation: boolean` (default `true`).
- `maxTopicLength: number` (default `256`).
- `logger?: LoggerLike` (optional override).
### `BackpressureOptionsSchema`
Stand-alone sub-schema. Exported so consumers building custom plugin
factories can reuse the same shape.
### `IdempotencyOptionsSchema`
Stand-alone sub-schema.
### `type EventBusPluginOptionsInput`
`z.input` of the top-level schema — what callers pass in.
### `type EventBusPluginOptionsResolved`
`z.output` of the top-level schema — what the descriptor stores as
`defaults` after parsing.
## Implementation Notes
- The `interceptors` array uses `z.custom` (`typeof val === "function"`)
rather than `z.function(...)` because Zod 4's `z.function` is
builder-style and does not return a `ZodType` directly compatible
with `z.array`.
- The `routePrefix` regex matches `/auth`'s rule verbatim — start with
`/`, no trailing `/` (the literal root `/` is allowed). Sharing the
rule across the plugin family means routes mount predictably.
- The schema is `.strict()` because the cost of catching typos at the
factory boundary far outweighs the convenience of forward-compatible
passthrough.

View File

@@ -0,0 +1,99 @@
# `routes.ts` — Zod schemas for the HTTP route surface
## Purpose
Boundary Zod schemas validated by the three OpenAPI routes the plugin
optionally mounts: `POST /event-bus/publish`, `GET /event-bus/subscriptions`,
and `DELETE /event-bus/subscriptions/:id`. The schemas double as the
canonical wire contract — the OpenAPI doc served by the host is
generated from them, and downstream client codegen consumes them via
the `./schemas/routes` subpath export.
## Features
- Request body schemas (`PublishBodySchema`) constrain topic syntax
AND length.
- Response schemas (`PublishResultSchema`, `SubscriptionListSchema`,
`UnsubscribeResultSchema`) describe every field the routes return.
- All schemas are exported alongside their inferred TypeScript types
(`PublishBody`, `PublishResult`, …) so handlers receive narrow,
static types.
- Error-report sub-schema (`ErrorReportSchema`) preserves the listener
failure surface across the wire.
## Usage: Basic
```ts
import { PublishBodySchema } from "@suaveplan/api-plugin-event-bus/schemas/routes";
const parsed = PublishBodySchema.parse({
topic: "order.created",
payload: { id: "o1" },
});
```
## Usage: Advanced
```ts
import {
PublishBodySchema,
PublishResultSchema,
type PublishResult,
} from "@suaveplan/api-plugin-event-bus/schemas/routes";
async function publishViaHttp(req: Request): Promise<PublishResult> {
const body = PublishBodySchema.parse(await req.json());
const res = await fetch("/event-bus/publish", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(body),
});
return PublishResultSchema.parse(await res.json());
}
```
## API Reference
### `PublishBodySchema`
Strict shape: `{ topic, payload?, idempotencyKey?, timeoutMs?, traceId? }`.
### `PublishResultSchema`
`{ delivered: number; dropped: boolean; errors: ErrorReport[] }`.
### `ErrorReportSchema`
`{ code: string; message: string }`. Surfaces listener exceptions —
the upstream `EventsError.code` and `.message` are passed through.
### `SubscriptionRecordSchema`
`{ id, topic, tenantId?, createdAt, once, idempotent }`.
### `SubscriptionListSchema`
`{ subscriptions: SubscriptionRecord[] }`.
### `UnsubscribeParamsSchema`
`{ id }` — used as the OpenAPI `params` schema for the DELETE route.
### `UnsubscribeResultSchema`
`{ unsubscribed: boolean }`.
## Implementation Notes
- `payload` is `z.unknown()` because the bus is intentionally
payload-agnostic. Publishers / subscribers Zod-validate at their own
layers (or fail loudly on the deserialise) when a typed contract is
required.
- `idempotencyKey` is capped at 256 chars to avoid pathological keys
starving the in-memory cache.
- `timeoutMs` is capped at 60_000 — beyond that, callers should set up
durable retries through their own scheduler rather than parking an
HTTP connection.
- The route schemas project the topic returned to the client back
through `unscopeTopic` at the service layer so HTTP responses never
leak the `tenant:<id>:` prefix.