apigenie-generatorOpenAPI serversserver orpc
server orpc
Generate a TypeScript server based on oRPC from an OpenAPI document.
Usage
apigenie-generator server orpc [...OPTIONS] INPUT_FILE
Description
The input must be an OpenAPI 3.0, 3.1 or 3.2 document; convert Swagger 2.0 documents with
apigenie convert, and bundle documents referencing other files
with apigenie bundle.
Every operation becomes an oRPC procedure, with Zod (v4) schemas validating its input and output. The generated npm package contains:
| File | Content |
|---|---|
src/schemas.ts |
Zod schemas, with their types, of the components, bodies, inputs and outputs |
src/contract/<group>.ts |
the contract of each procedure: route, input, output and errors |
src/contract/index.ts |
the contract router, by group |
src/handlers/<group>.ts |
a handler per procedure, throwing NOT_IMPLEMENTED |
src/orpc.ts |
the context of the procedures and implement(contract) |
src/router.ts |
the router assembling the handlers |
src/server.ts |
a Node.js HTTP server with oRPC’s OpenAPIHandler |
src/main.ts |
starts the server on the port in PORT (3000 by default) |
src/index.ts |
exports of the package |
Procedures are grouped by the first tag of their operations, or the first segment of their paths,
and named after their operationIds.
The handlers, orpc.ts, server.ts, main.ts, package.json and tsconfig.json are meant to
be edited, and are only written when they don’t exist. Regenerating updates the schemas, the
contract and the router; the TypeScript compiler then reports the handlers that new operations
need.
apigenie-generator server orpc openapi.yaml -o server
cd server && npm install && npm run dev
The server answers the operations under the path of the first server of the document (e.g. /v1),
and serves its OpenAPI document at /spec.json and an API reference at /. Operations with
servers of their own (operation or path item servers) with another path, e.g. a health check on
the root of a status host, are also answered at that path.
Inputs and outputs
A procedure receives the path parameters merged with the query parameters (GET) or the body
(other methods), oRPC’s compact input structure, unless that would lose part of the request:
operations with header or cookie parameters, query parameters in other methods than GET, or bodies
which can’t be merged with the path parameters get the detailed structure, with params,
query, headers (in lower case) and body. Parameters are converted from strings to the types of
their schemas, and array parameters accept repeated values, a single value, and the delimited values
of the form (with explode: false), spaceDelimited and pipeDelimited styles. Cookie
parameters are read from the Cookie header (headers.cookie), parameters described by
content: application/json are parsed as JSON, and a path segment of several parameters, such as
/labels/{labelId}.{extension}, is routed as one parameter and split into its parameters.
The body is read in any of the operation’s media types:
- JSON bodies, including other JSON media types such as
application/merge-patch+json, which the server parses before oRPC, and JSON Lines, which the procedure receives as an array; application/x-www-form-urlencodedandmultipart/form-databodies, whose fields are converted to the types of their schemas (an empty field isnullwhere the schema allows it) and whose binary parts areFiles;text/plainbodies as strings, other text and binary bodies asFiles.
A procedure returns the body of its response. When an operation has success responses with
different bodies, or response headers, it returns { status, headers, body } objects instead.
JSON bodies are objects; other bodies (text, files) are Blobs, which the server sends with their
media type. A text/event-stream response is an eventIterator() of its itemSchema (the
contentSchema of the events’ data, or the item of the operation’s JSON Lines response); when
the operation also answers JSON, the handler returns either a value or an async iterator, as the
client accepts. The writeOnly properties of a response are left out of what the server sends,
and the readOnly properties of a request out of what the handler receives.
A oneOf with a discriminator and a defaultMapping (x-defaultMapping in 3.0 and 3.1 documents)
validates the option its property selects, or the default one; closed allOf compositions
(unevaluatedProperties: false) reject properties none of their schemas declare.
Each 4xx and 5xx response becomes an error of the procedure: NOT_FOUND, CONFLICT and the other
codes of oRPC, or HTTP_<status> for other statuses. 4XX and 5XX ranges become the errors of
their first status (BAD_REQUEST, INTERNAL_SERVER_ERROR), and a default response next to
success responses INTERNAL_SERVER_ERROR, unless the document declares those statuses. Their
response bodies are their data, which the server sends as the body of the response:
throw errors.NOT_FOUND({ data: { code: 404, message: "No such pet" } });
Not supported, and reported as warnings: path parameters in other styles than simple, object
query parameters in the form style (read in the deepObject style), and operations with other
methods than GET, POST, PUT, DELETE, PATCH and HEAD (QUERY is routed with oRPC 2), which are
skipped. oRPC describes the procedures a server answers, not the requests it sends, so callbacks
and webhooks are not generated; it streams async iterators as server-sent events only, so a
JSON Lines response is answered as a Blob the handler builds.
Extensions
| Extension | Effect |
|---|---|
x-apigenie.codegen.name |
name of the schema and type of a component schema (AnimalSchema, Animal) |
x-apigenie.codegen.action-name |
name of the procedure of an operation, when action_naming lists extension |
The extensions can live in an overlay for this target instead of in the document, e.g.
orpc.overlay.yaml:
overlay: 1.0.0
info:
title: TypeScript names
version: 1.0.0
actions:
- target: $.components.schemas.Pet
update:
x-apigenie:
codegen:
name: Animal
apigenie-generator server orpc openapi.yaml --overlay orpc.overlay.yaml -o out
Options
-c, –config
Path to the configuration file to use. See the “Configuration” section for more information.
–overlay OVERLAY
Path to an OpenAPI Overlay (1.0 to 1.2) applied to the input before generating, e.g. one setting the
extensions of the “Extensions” section. Can be repeated: the overlays apply in order, after those
listed under commands.generate.server_orpc.overlay in the configuration file (with paths relative
to it). Warnings and errors about a value an overlay set point to the overlay.
–strict
Makes an overlay action whose target selects nothing an error (exit status 2, nothing is generated)
instead of a warning (OVERLAY:LINE:COL: action #N (TARGET) selects no nodes.).
-o, –output
Directory where the package is generated.
–package-name
Name of the package, <title>-server by default.
–package-version
Version of the package, the version of the API by default.
Configuration
version: '1.0'
commands:
generate:
server_orpc:
orpc_version: 1
input_structure: auto
| Option | Description |
|---|---|
orpc_version |
1 (default) for oRPC 1, 2 for oRPC 2 (beta): routes declared with oc.meta(openapi(...)) and queryStyles |
input_structure |
auto (default), compact (header parameters, and query parameters of other methods than GET, are dropped) or detailed |
layout |
package (default) for an npm package, sources for the sources only |
import_extension |
extension of relative imports: .js (default, Node.js) or "" (bundlers) |
action_naming |
sources of procedure names, in order: id (operationId), extension (x-apigenie), url; [id, url] by default |
additional_properties |
loose (default) keeps the properties of objects their schemas don’t list, strip removes them |
describe |
true attaches the descriptions of schemas with .describe() (default: false) |