Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# Add @suaveplan/api-openapi — OpenAPI registry + route factory (3 of 5)
**Package**: `@suaveplan/api-openapi` (NEW, server-tier)
**Status**: PROPOSED
**Type**: new-package (split from upstream `@suaveplan/api`)
- **Spec delta**: ./specs/api-openapi/spec.md
- **Companions**: `add-api-plugin`, `add-api-tenant`, `add-api-migrations`, `enterprise-api`
- **Position in chain**: depends on `add-api-plugin` (consumers register routes via plugin `onInit`)
## Why
Upstream `@suaveplan/api`'s `openapi/` (1,066 LOC) ships an `OpenAPIRegistry`, a doc merger, a typed `RouteBuilder`, and a global `SchemaRegistry`. Splitting it lets `@suaveplan/api-schemas` (the Zod boundary) and downstream `api-plugin-*` packages compose a focused OpenAPI surface without dragging the Hono app orchestrator along.
The upstream layer has two notable issues genesis fixes: (1) the `OpenAPIRegistry` and Hono's `OpenAPIHono.doc()` are **not connected** — registry tracks routes for introspection but the actual doc is generated by Hono, so drift between the two is silent; (2) `getSchemaRegistry()` is a global singleton, untestable in parallel and conflicting with multi-app deployments.
## What changes
Net-new package at `0.1.0`. ADDED:
- `OpenAPIRegistry` class — single source of truth. Tracks `info`, `servers`, `securitySchemes`, `tags`, `routes`. Methods: `registerSecurityScheme`, `registerTag`, `registerRoute`, `getRoutes`, `getRoutesByPlugin`, `getRoutesByTag`, `buildDocument(): OpenAPIDocument` (returns the full 3.1.0 doc, not just info+servers).
- **Hono integration**: `OpenAPIRegistry.applyTo(app: OpenAPIHono)` — registers a single `app.doc(specPath, ...)` handler that serves the registry-built document. Eliminates the drift between registry state and Hono doc output.
- `RouteBuilder` fluent API — type-preserving via `RouteBuilder<TParams, TQuery, TBody, TResponse>` generics; `.params(z)/.query(z)/.body(z)/.response(z)` thread types through; `.build()` returns `TypedRouteConfig` compatible with `@hono/zod-openapi`.
- `route(method, path)` factory + shorthands `GET/POST/PUT/PATCH/DELETE(path)`.
- `StandardResponses` — `400/401/403/404/422/500/503` (widened from upstream's 400/401/403/404/500 to cover the full SuaveplanError statusCode range).
- `ErrorResponseSchema` — Zod schema matching `@suaveplan/error` wire shape (`{ success: false, error: { code, message, details?, requestId?, timestamp, cause? } }`).
- `successResponse(T)`, `paginatedResponse(T)`, `errorResponse(desc)` — response wrapper schemas.
- `SchemaRegistry` class — local instance (no global singleton). Methods: `register`, `get`, `has`, `getNames`, `getAll`, `remove`, `clear`, `extend(baseName, name, ext)`, `partial(baseName, name)`, `pick(baseName, name, keys)`, `omit(baseName, name, keys)`. `defineSchema(schema, meta, registry)` requires an explicit registry instance.
- `CommonSchemas` — `uuid`, `email`, `url`, `datetime`, `positiveInt`, `nonNegativeInt`, `page`, `limit`, `sortOrder` (Zod schemas with `.openapi()` metadata).
- `OpenAPIDocument` + `PathItem` + `Operation` types — structural shape for cross-tool merging.
- `mergeOpenAPIDocuments(base, ...docs)` — same path-merge / components-spread / tag-dedup semantics as upstream.
- `prefixPaths(doc, prefix)`, `filterPathsByTag(doc, tags)`, `removeInternalRoutes(doc)` — doc transforms.
- `BearerAuthScheme`, `ApiKeyScheme` security-scheme presets.
- `OpenAPIError extends SuaveplanError<OpenAPIErrorCode>` — codes `OPENAPI_INVALID_INPUT`, `OPENAPI_SCHEMA_NOT_FOUND`, `OPENAPI_INVALID_BASE_SCHEMA` (e.g. `extend` on a non-ZodObject).
- Plugin integration: `definePluginRoutes(routes: TypedRouteConfig[], registry: OpenAPIRegistry)` helper that plugins call from `onInit` to register routes against both Hono (`app.openapi`) and the registry.
## Out of scope
- **OpenAPI 3.0 support.** Genesis ships 3.1.0 only (matches Hono `OpenAPIHono.getOpenAPI31Document`). A back-compat 3.0 transform is a follow-up.
- **YAML / TOML emit.** Doc is emitted as JSON. YAML adapter belongs in a separate package.
- **Spec validation against the 3.1 schema.** We trust `@hono/zod-openapi`'s output structure; we don't reparse our own emitted spec. A validator package is out of scope.
- **OpenAPI UI rendering** (Swagger / Redoc / Scalar / Altair). These ship as separate plugins (`api-openapi-ui-swagger`, etc — all in the in-flight change set).
## Source mapping
| Capability | Upstream source | Notes |
|---|---|---|
| `OpenAPIRegistry` | `../suaveplan/packages/server/api/src/openapi/openapi-registry.ts` L1-L238 | port + add `buildDocument()` that emits the full doc + `applyTo(app)` Hono integration |
| Doc merging + transforms | `../suaveplan/packages/server/api/src/openapi/openapi-merger.ts` L1-L271 | verbatim port |
| `RouteBuilder` + factories + `StandardResponses` + helpers | `../suaveplan/packages/server/api/src/openapi/route-factory.ts` L1-L298 | port + widen `StandardResponses` to include 422 and 503 |
| `SchemaRegistry` + `CommonSchemas` | `../suaveplan/packages/server/api/src/openapi/schema-registry.ts` L1-L255 | port + drop global singleton; require explicit registry instance |
## Impact
### Affected dependents
Depends on `add-api-plugin` (for the `PluginDescriptor`/`PluginContext` types) and indirectly on `@suaveplan/api-schemas` (existing on genesis). Will be consumed by `@suaveplan/api` (orchestrator) and every `@suaveplan/api-plugin-*` package that ships routes.