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,65 @@
|
||||
# `middleware-adapter` — Middleware ⇄ Hono MiddlewareHandler bridge
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
This module bidirectionally bridges the onion-model `Middleware` type from `@suaveplan/api-router` and Hono's native `MiddlewareHandler`. The bridge is what lets a `Router` adapter installed on top of a Hono app participate in the same per-request pipeline — inbound headers become `RouterRequest`, outbound builder results become Web `Response` objects, and downstream Hono middlewares observe the `next()` boundary as their own.
|
||||
|
||||
The conversion is intentionally one-directional in effect: `toHonoMiddleware` runs the suaveplan middleware ahead of Hono's downstream chain, while `fromHonoMiddleware` defers strictly to the `next()` because Hono context cannot be safely synthesised outside a real dispatch. Real Hono middlewares get installed via `getHonoApp().use(...)` directly.
|
||||
|
||||
## Features
|
||||
|
||||
- `toHonoMiddleware(mw)` — adapts a `Middleware` to a `MiddlewareHandler` Hono can install.
|
||||
- `fromHonoMiddleware(handler)` — produces a `Middleware` that defers to the chain; throws `ROUTER_HONO.INVALID_HONO_PEER` for non-functions.
|
||||
- Header/query reflection from `c.req.raw` to `MapHeaders` so handlers run against the canonical suaveplan
|
||||
- Wraps Hono-internal throws in `RouterHonoError` with code `HONO_INTERNAL_ERROR` and a cause-chain.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { toHonoMiddleware } from "@suaveplan/api-router-hono/middleware-adapter";
|
||||
import type { Middleware } from "@suaveplan/api-router";
|
||||
import { Hono } from "hono";
|
||||
|
||||
const trace: Middleware = async (req, next) => {
|
||||
console.log(req.requestId);
|
||||
return next();
|
||||
};
|
||||
|
||||
const app = new Hono();
|
||||
app.use("*", toHonoMiddleware(trace));
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
fromHonoMiddleware,
|
||||
toHonoMiddleware,
|
||||
} from "@suaveplan/api-router-hono/middleware-adapter";
|
||||
import { createHonoRouter } from "@suaveplan/api-router-hono/adapter";
|
||||
|
||||
const router = createHonoRouter();
|
||||
|
||||
router.use(async (req, next) => {
|
||||
const res = await next();
|
||||
return { ...res, headers: { ...res.headers, "x-trace": req.requestId } };
|
||||
});
|
||||
|
||||
const app = router.getHonoApp();
|
||||
app.use("*", toHonoMiddleware(async (_req, next) => next()));
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `toHonoMiddleware(mw: Middleware): MiddlewareHandler` — wraps a suaveplan middleware.
|
||||
- `fromHonoMiddleware(handler: MiddlewareHandler): Middleware` — wraps a Hono middleware.
|
||||
|
||||
Both helpers preserve the `RouterError` / `RouterHonoError` cause chains so observability stays end-to-end.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`contextToRouterRequest` reads `x-tenant-id` and `x-request-id` headers (case-insensitive) to populate the corresponding fields. Both default to safe stand-ins (`"default"` tenant, time-derived request id) so unit tests bypass middleware setup. `routerResponseToWebResponse` JSON-stringifies non-string bodies and sets `content-type: application/json` when no body content-type is already present.
|
||||
Reference in New Issue
Block a user