Generating the OpenAPI Spec
Lombok’s HTTP API is described by an OpenAPI 3.1 document that is generated from
the NestJS backend’s controllers and nestjs-zod DTOs. The generated document
and the TypeScript types derived from it are committed to the repository, so any
change to the API surface needs to be followed by regenerating these artifacts
and committing the result.
This page covers the generation workflow. It assumes you already have a working dev environment. For setup and the broader local development loop, see Local Development with dx.
What gets generated
Section titled “What gets generated”Running the generator produces three artifacts, all under version control:
| File | Produced by | Purpose |
|---|---|---|
packages/api/src/nestjs-metadata.ts | generate:metadata | NestJS Swagger plugin metadata |
packages/api/src/openapi.json | generate:metadata | The OpenAPI 3.1 document |
packages/types/src/api-paths.d.ts | generate-openapi-spec.sh | TypeScript paths types generated from openapi.json |
The openapi.json document is consumed by the @lombokapp/types package, which
exposes the paths type and derives the API DTO types used by the UI and other
packages. Regenerating keeps these types in sync with the backend.
Regenerating everything
Section titled “Regenerating everything”The simplest path runs the full chain — metadata, spec, and the derived TypeScript types:
./dx generate openapiThis requires the dev container to be running. Under the hood it runs
bun --cwd packages/api generate:openapi, which is:
generate:metadata -> ./cmd/generate-openapi-spec.shYou can run the same thing from the repo root without dx:
bun run generate:openapiRegenerating only the metadata and spec
Section titled “Regenerating only the metadata and spec”If you only want to refresh nestjs-metadata.ts and openapi.json without
rebuilding the derived types:
./dx generate metadataThis runs inside the dev container. It bootstraps the Nest application in
preview mode, walks the TypeScript sources with the @nestjs/swagger
ReadonlyVisitor, and writes the two files.
How generation works
Section titled “How generation works”The generator lives in packages/api/script/generate-metadata.ts. At a high
level it:
- Type-checks the API sources, then runs the
@nestjs/swaggerplugin’sReadonlyVisitorto collect type metadata and writesrc/nestjs-metadata.ts. - Boots
CoreModulein preview mode and builds the document withDocumentBuilder. - Integrates
nestjs-zodviacleanupOpenApiDocso Zod-inferred DTOs land in the spec. - Runs a series of normalization and compression passes over the document.
- Writes the result to
packages/api/src/openapi.json.
The shell step (packages/api/cmd/generate-openapi-spec.sh) then runs
openapi-typescript against openapi.json to produce
packages/types/src/api-paths.d.ts, and rebuilds the @lombokapp/types
package.
These passes are why the committed spec does not look like a raw NestJS dump — the schema names and structure are deliberately normalized for cleaner downstream type generation.
When to regenerate
Section titled “When to regenerate”Regenerate whenever you change anything that affects the API contract, for example:
- adding, removing, or renaming a controller route
- changing a request or response DTO
- changing query or path parameters
- changing status codes or response shapes
Commit the regenerated nestjs-metadata.ts, openapi.json, and api-paths.d.ts
alongside your code change so the spec and derived types stay consistent with
the backend.
[!NOTE] The repository does not currently appear to enforce spec freshness in CI, so it is on the contributor to regenerate and commit these artifacts.
Troubleshooting
Section titled “Troubleshooting”./dx generate ...fails because nothing is running — these commands expect the dev container to be up. Run./dx upfirst.- Type errors during generation —
generate:metadatatype-checks the API sources before emitting. Fix the reported TypeScript errors, then rerun. - A DTO is missing or shows an empty schema — confirm the DTO is wired
through
nestjs-zodand reachable fromCoreModule.