OpenAPI Integration
OPRA's type system is intentionally richer than OpenAPI's schema model. Several concepts that OPRA supports natively have no direct equivalent in OpenAPI 3.x:
- Type inheritance and extension — OPRA types can extend a base
ComplexType; OpenAPI has no native inheritance construct. MixinType— merges multiple types into one at the field level, with no OpenAPI parallel.MappedTypetransforms —PickType,OmitType,PartialType,RequiredTypeproduce derived types at the schema level; OpenAPI has no equivalent transform primitives.UnionTypewith discriminator — maps tooneOf, but OPRA's discriminator is enforced at runtime with validation logic that OpenAPI cannot express.- SEARCH and QUERY methods — OPRA supports these emerging HTTP methods; OpenAPI 3.x's path item spec does not.
- Scope-filtered fields — individual fields and parameters can be hidden per audience (public / internal / admin) at the type-system level; OpenAPI has no built-in equivalent.
ArrayTypewithminOccurs/maxOccurs— OPRA's typed array wrapper carries occurrence constraints that go beyond what OpenAPI'sitemsschema conveys.
Despite these gaps, OpenAPI is a widely adopted industry standard. Tooling ecosystems — Swagger UI, Postman, Scalar, API gateways, client generators — all speak OpenAPI. To make OPRA services compatible with this ecosystem, @opra/openapi provides a best-effort conversion: OPRA constructs that map cleanly are converted faithfully; those that have no OpenAPI equivalent are approximated or skipped, with a warning recorded for each.
@opra/openapi generates standard OpenAPI 3.0 / 3.1 documents from an OPRA ApiDocument. Once you have an ApiDocument — the runtime representation of your OPRA HTTP service — this package converts it to a spec-compliant JSON object you can serve with Swagger UI, import into Postman, feed to API gateways, or use with any OpenAPI-aware tooling.
Installation
npm install @opra/openapi
@opra/common is a peer dependency; install it too if you haven't already.
How it works
OPRA's ApiDocument already contains everything needed: controllers, operations, typed request/response shapes, parameters, and the data type registry. @opra/openapi walks this structure and maps each piece to its OpenAPI equivalent:
| OPRA construct | OpenAPI equivalent |
|---|---|
HttpController | Path items (grouped by URL) |
HttpOperation | Operation object (get, post, … under each path) |
.QueryParam(), .PathParam(), .Header(), .Cookie() | parameters[] |
.RequestContent() | requestBody |
.Response() | responses |
ComplexType / MappedType / MixinType | components.schemas object |
EnumType | components.schemas {type:"string", enum:[...]} |
ArrayType | {type:"array", items:...} |
UnionType | {oneOf:[...]} |
SimpleType | Inlined primitive schema (string, integer, boolean, …) |
Named model types (ComplexType, EnumType, UnionType, ArrayType) are placed in components.schemas and referenced with $ref. Simple types are always inlined.
Quick example
import { ApiDocumentFactory, OpraSchema } from '@opra/common';
import { OpenApiDocumentFactory } from '@opra/openapi';
// Build (or obtain) your ApiDocument
const apiDocument = await ApiDocumentFactory.createDocument({ ... });
// Generate an OpenAPI 3.0 document
const openApiDoc = OpenApiDocumentFactory.generate(apiDocument);
// openApiDoc is a plain JSON-serialisable object — serve or write it
console.log(JSON.stringify(openApiDoc, null, 2));