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,95 @@
|
||||
# `build-routes.ts` — OpenAPI route surface for the event-bus plugin
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Builds the three `PluginRouteEntry` objects the plugin mounts on the
|
||||
host Hono app + `OpenAPIRegistry` via `definePluginRoutes`. The
|
||||
surface (`POST /publish`, `GET /subscriptions`,
|
||||
`DELETE /subscriptions/:id`) gives operators an HTTP-only path to
|
||||
exercise the event bus — useful for cross-language producers, smoke
|
||||
tests, and admin tooling. Per-tenant scoping flows through the same
|
||||
`extractTenantId` helper used by the request middleware so the HTTP
|
||||
and in-process surfaces stay consistent.
|
||||
|
||||
## Features
|
||||
|
||||
- 3 routes: publish, list, delete.
|
||||
- All routes typed via `RouteBuilder` with Zod request/response
|
||||
schemas — the OpenAPI doc the host serves at `/openapi.json`
|
||||
advertises every shape with full inference.
|
||||
- Auth gating is installed by the plugin's `onInit` at the
|
||||
sub-path level (`app.use(routePrefix + "/*", requireAuth())`),
|
||||
because `RouteBuilder` does not own a `.middleware(...)` slot.
|
||||
- DELETE returns HTTP 404 for both unknown ids AND cross-tenant
|
||||
attempts (the `TENANT_MISMATCH` swallow is deliberate — exposing
|
||||
the distinction would leak id ownership across tenants).
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { definePluginRoutes } from "@suaveplan/api-openapi";
|
||||
import { buildRoutes } from "@suaveplan/api-plugin-event-bus/routes/build-routes";
|
||||
|
||||
const entries = buildRoutes({
|
||||
service: eventBusService,
|
||||
tenantIsolation: true,
|
||||
});
|
||||
definePluginRoutes(entries, {
|
||||
app,
|
||||
registry: openAPIRegistry,
|
||||
pluginName: "event-bus",
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { buildRoutes } from "@suaveplan/api-plugin-event-bus/routes/build-routes";
|
||||
|
||||
// Mount under a custom prefix by remapping each entry's path before
|
||||
// handing the array to definePluginRoutes.
|
||||
const prefix = "/internal/bus";
|
||||
const entries = buildRoutes({
|
||||
service,
|
||||
tenantIsolation: true,
|
||||
}).map((e) => ({
|
||||
...e,
|
||||
route: { ...e.route, path: `${prefix}${e.route.path}` },
|
||||
}));
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `buildRoutes(options: BuildRoutesOptions): PluginRouteEntry[]`
|
||||
|
||||
Returns 3 entries:
|
||||
|
||||
1. `POST /publish` — body: `PublishBodySchema`; response:
|
||||
`successResponse(PublishResultSchema)`.
|
||||
2. `GET /subscriptions` — response: `successResponse(SubscriptionListSchema)`.
|
||||
3. `DELETE /subscriptions/{id}` — params: `UnsubscribeParamsSchema`;
|
||||
response: `successResponse(UnsubscribeResultSchema)`. Returns 404
|
||||
for both unknown ids AND foreign tenants.
|
||||
|
||||
### `interface BuildRoutesOptions`
|
||||
|
||||
`{ service: EventBusService; tenantIsolation: boolean }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The handlers parse the request body via `PublishBodySchema.parse`
|
||||
directly rather than relying on Hono's `c.req.valid()` so the
|
||||
validation flow is identical when the host is using a stripped-down
|
||||
test harness without the full OpenAPI middleware chain.
|
||||
- The publish handler clones `c.req.raw` before reading the body so
|
||||
any downstream middleware that re-reads the request keeps working.
|
||||
- The auth gate is installed by the plugin's `onInit`, NOT here. This
|
||||
keeps `buildRoutes` pure — it has no opinion on auth, allowing test
|
||||
harnesses to mount the routes without standing up `api-plugin-auth`.
|
||||
- The 404 mapping for `TENANT_MISMATCH` is deliberate — exposing the
|
||||
difference between "not found" and "found but not yours" would
|
||||
leak subscription-id ownership across tenants.
|
||||
Reference in New Issue
Block a user