@mantlejs/openapi
OpenAPI 3.1 document generation for Mantle JS — walks your registered services and serves a live spec (and optional Swagger UI) with zero configuration.
Installation
Section titled “Installation”npm install @mantlejs/openapi@mantlejs/mantle is a peer dependency, and an HTTP transport (@mantlejs/express, @mantlejs/koa, or @mantlejs/http) must be configured first.
Concepts
Section titled “Concepts”Introspection-driven
Section titled “Introspection-driven”The plugin consumes ServiceHandle.describe() — the same machinery behind the transports’ /_services endpoint. For every registered service it reads:
methods→ REST operations (find→GET /path,get→GET /path/{id},create→POST /path,update→PUT /path/{id},patch→PATCH /path/{id},remove→DELETE /path/{id}, custom methods →POST /path/{method}).schema→ the entity schema undercomponents.schemas(a TypeBox schema stored viaServiceOptions.schemais JSON Schema and is embedded as-is). Services without a schema still appear with a genericobjectschema — missing coverage never skips a service or errors.authRequired→ operations are marked withbearerAuthsecurity when an auth hook (e.g.authenticate("jwt")from@mantlejs/auth) is registered inbefore.all. ThebearerAuthsecurity scheme is added tocomponents.securitySchemeswhen at least one service requires it.capabilities→ when the service exposes repository capabilities (e.g.RepositoryService),findresponses are documented as thePaginated<T>envelope and the supported query operators are listed in the operation description.
Live document
Section titled “Live document”The document is rebuilt on every request to specPath, so hooks and services registered after startup are always reflected.
Configure order
Section titled “Configure order”openapi() mounts its routes through the transport-neutral "http:router" contract, so configure it after the transport and before registering services:
const app = mantle() .configure(express()) .configure(openapi());Quick start
Section titled “Quick start”import { mantle, RepositoryService } from "@mantlejs/mantle";import { express } from "@mantlejs/express";import { openapi } from "@mantlejs/openapi";
const app = mantle() .configure(express()) .configure( openapi({ docsPath: "/docs", info: { title: "My API", version: "1.0.0" }, }), );
app.use("users", new RepositoryService(new UserRepository(app), { schema: userSchema }), { schema: userSchema,});
app.listen(3030);// GET /openapi.json → OpenAPI 3.1 document// GET /docs → Swagger UIopenapi(options?)
Section titled “openapi(options?)”Returns a MantlePlugin. Mounts GET <specPath> serving the OpenAPI 3.1 JSON document, and optionally GET <docsPath> serving a Swagger UI page (loaded from the unpkg CDN — the package itself stays dependency-free).
OpenApiOptions
Section titled “OpenApiOptions”| Field | Type | Default | Description |
|---|---|---|---|
specPath |
string |
"/openapi.json" |
Route the JSON document is served from. |
docsPath |
string |
— | When set, serves Swagger UI at this route. |
info |
{ title?: string; version?: string; description?: string } |
{ title: "Mantle API", version: "0.0.0" } |
OpenAPI info object. |
Throws GeneralError at configure time when no HTTP transport has registered "http:router".
buildOpenApiDocument(descriptors, info?)
Section titled “buildOpenApiDocument(descriptors, info?)”The pure document assembler, exported for tooling that wants the document without mounting routes:
import { buildOpenApiDocument } from "@mantlejs/openapi";
const doc = buildOpenApiDocument( ["users", "orders"].map((path) => app.service(path).describe()), { title: "My API", version: "1.0.0" },);Every document also includes a MantleError schema referenced by each operation’s default error response.
import type { OpenApiOptions, OpenApiInfo } from "@mantlejs/openapi";| Type | Description |
|---|---|
OpenApiOptions |
Options object accepted by openapi() |
OpenApiInfo |
The document info metadata (title, version) |
Development
Section titled “Development”npx nx build openapi # compilenpx nx test openapi # run testsnpx nx lint openapi # lintPublishing
Section titled “Publishing”Build before publishing:
npx nx build openapiFirst publish (scoped packages require --access public):
cd packages/openapinpm publish --access publicSubsequent releases — bump version in packages/openapi/package.json, then:
cd packages/openapinpm publishTesting locally with Verdaccio
Section titled “Testing locally with Verdaccio”# Terminal 1 — start the local registrynpx nx run @mantle/source:local-registry
# Terminal 2 — publish to itcd packages/openapinpm publish --registry http://localhost:4873
# Install from it in another projectnpm install @mantlejs/openapi --registry http://localhost:4873