Skip to content

Commit 6401e21

Browse files
spec.yaml -> openapi.yaml
1 parent 6217d22 commit 6401e21

File tree

9 files changed

+37
-28
lines changed

9 files changed

+37
-28
lines changed

examples/docs/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default function makeApp() {
1515
// Runtime validation (recommended)
1616
apiRouter.use(
1717
OpenApiValidator.middleware({
18-
apiSpec: "./spec.yaml",
18+
apiSpec: "./openapi.yaml",
1919
validateResponses: false,
2020
}),
2121
);
File renamed without changes.

examples/docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "module",
66
"scripts": {
77
"test": "node --test",
8-
"gen": "openapi-typescript ./spec.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./spec.yaml --types ./schema.d.ts --output ./gen/server.ts",
8+
"gen": "openapi-typescript ./openapi.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./openapi.yaml --types ./schema.d.ts --output ./gen/server.ts",
99
"start": "node --watch cmd/index.ts"
1010
},
1111
"dependencies": {

examples/kitchensink/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default function makeApp() {
2222

2323
apiRouter.use(
2424
OpenApiValidator.middleware({
25-
apiSpec: "./spec.yaml",
25+
apiSpec: "./openapi.yaml",
2626
validateResponses: false,
2727
}),
2828
);
File renamed without changes.

examples/kitchensink/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "module",
66
"scripts": {
77
"test": "node --test",
8-
"gen": "openapi-typescript ./spec.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./spec.yaml --types ./schema.d.ts --output ./gen/server.ts",
8+
"gen": "openapi-typescript ./openapi.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./openapi.yaml --types ./schema.d.ts --output ./gen/server.ts",
99
"start": "node --watch cmd/index.ts"
1010
},
1111
"dependencies": {
File renamed without changes.

examples/petstore/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"version": "0.0.9",
55
"type": "module",
66
"scripts": {
7-
"gen": "openapi-typescript ./spec.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./spec.yaml -t ./schema.d.ts -o ./gen/server.ts "
7+
"gen": "openapi-typescript ./openapi.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./openapi.yaml -t ./schema.d.ts -o ./gen/server.ts "
88
},
99
"dependencies": {
1010
"openapi-typescript": "^7.8.0",

packages/openapi-typescript-server/README.md

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,24 @@
22

33
`openapi-typescript-server` is a CLI and minimal runtime library that helps you implement type-safe APIs documented by OpenAPI.
44

5-
It works by generating a TypeScript server interface based on your OpenAPI spec using types from [openapi-typescript](https://github.com/openapi-ts/openapi-typescript).
5+
## Key Features
6+
7+
- ✅ Code gen server implementations of OpenAPI 3.0 and 3.1
8+
- ✅ Framework-agnostic core with Express adapter available
9+
- ✅ Minimal runtime footprint
10+
- ✅ Built on top of [openapi-typescript](https://github.com/openapi-ts/openapi-typescript)
11+
12+
## Overview
13+
14+
This library works by generating a TypeScript server interface based on your OpenAPI spec using types from [openapi-typescript](https://github.com/openapi-ts/openapi-typescript).
615

716
You provide a concrete implementation that satisfies the interface for each path operation.
817

918
At runtime, your implementation is converted into HTTP handlers for various frameworks like [Express](https://github.com/jasonblanchard/openapi-typescript-server/tree/main/packages/openapi-typescript-server).
1019

1120
## Stability
1221

13-
⚠️ This package is in very early development. Breaking changes may be introduced as the design and implementation takes shape towards a stable release. ⚠️
14-
15-
For now, proceed with caution!
22+
⚠️ This package is in very early development. Breaking changes may be introduced as the design and implementation takes shape towards a stable release. For now, proceed with caution! ⚠️
1623

1724
## Usage
1825

@@ -40,7 +47,7 @@ npm install express-openapi-validator
4047

4148
Given an OpenAPI spec like this:
4249

43-
`spec.yaml`
50+
`openapi.yaml`
4451

4552
```yaml
4653
openapi: 3.0.2
@@ -92,13 +99,13 @@ First, follow [recommended setup from openapi-typescript](https://openapi-ts.dev
9299
Generate types from your OpenAPI spec:
93100
94101
```bash
95-
npx openapi-typescript ./spec.yaml --output ./gen/schema.d.ts
102+
npx openapi-typescript ./openapi.yaml --output ./gen/schema.d.ts
96103
```
97104

98105
Generate the server interface:
99106

100107
```bash
101-
npx openapi-typescript-server ./spec.yaml --types ./schema.d.ts --output ./gen/server.ts
108+
npx openapi-typescript-server ./openapi.yaml --types ./schema.d.ts --output ./gen/server.ts
102109
```
103110

104111
> **Note**: The `--types` path is relative to the output directory so the generated code can import it correctly.
@@ -134,7 +141,7 @@ const API: ServerTypes.Server<Request, Response> = {
134141
export default API;
135142
```
136143

137-
Set up your Express server
144+
Set up your Express server:
138145

139146
`app.ts`
140147

@@ -156,7 +163,7 @@ export default function makeApp() {
156163
// Runtime validation (recommended)
157164
apiRouter.use(
158165
OpenApiValidator.middleware({
159-
apiSpec: "./spec.yaml",
166+
apiSpec: "./openapi.yaml",
160167
validateResponses: false,
161168
}),
162169
);
@@ -167,7 +174,7 @@ export default function makeApp() {
167174
// Make Express routes from your route handlers
168175
registerRoutes(routeHandlers, apiRouter);
169176

170-
// Mount to the correct base path
177+
// Mount to the base path
171178
app.use("/api/v3", apiRouter);
172179

173180
// Global error handler
@@ -184,7 +191,7 @@ export default function makeApp() {
184191
}
185192
```
186193

187-
Test your API
194+
Run this server and test your API:
188195

189196
```bash
190197
curl localhost:8080/api/v3/speak/123 \
@@ -198,6 +205,8 @@ Response:
198205
{ "greeting": "Pet 123 says \"grrrr\"" }
199206
```
200207

208+
See `examples/docs` for a fully working example.
209+
201210
### Making a change
202211

203212
Now, make a change to your OpenAPI spec:
@@ -249,7 +258,7 @@ Now, make a change to your OpenAPI spec:
249258
And re-generate the types and server interface:
250259

251260
```bash
252-
openapi-typescript ./spec.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./spec.yaml --types ./schema.d.ts --output ./gen/server.ts
261+
openapi-typescript ./openapi.yaml --output ./gen/schema.d.ts && openapi-typescript-server ./openapi.yaml --types ./schema.d.ts --output ./gen/server.ts
253262
```
254263

255264
You'll see that TypeScript will tell you exactly what needs to change in your code to conform to the new OpenAPI spec:
@@ -258,7 +267,7 @@ You'll see that TypeScript will tell you exactly what needs to change in your co
258267
Property 'vibe' is missing in type '{ greeting: string; }' but required in type '{ greeting: string; vibe: "friendly" | "fierce" | "playful" | "sleepy"; }'.ts(2322)
259268
```
260269

261-
> **Note**: You may need to restart the TS Server in VS Code to see the TypeScript error.
270+
> **Note**: You may need to restart the TS Server in VS Code to see the TypeScript error after re-generating the types and server interface.
262271
263272
Satisfy the compiler to get it working again:
264273

@@ -288,7 +297,7 @@ This pattern also guides you when adding or removing routes.
288297

289298
### Design goals
290299

291-
The main goal of this package is to ensure that the server implementation stays in sync with the API documentation by generating a typed interface _from_ the OpenAPI spec.
300+
The main goal of this package is to ensure that your server implementation stays in sync with the API documentation by generating a typed interface _from_ the OpenAPI spec.
292301

293302
This schema-first approach documents your system for humans or LLM coding agents, and helps you achieve type safety across the system.
294303

@@ -329,17 +338,17 @@ The route handler name uses the `operationId` if present. Otherwise it's generat
329338

330339
The return value is enveloped in `content` so that you can provide `headers` and `status` at the same level. `status` is required when the response variant is "default".
331340

332-
> **Note**: These return values are a bit verbose, but, since the HTTP handling is delegated to the adapters, they have the added benefit of being easily testable functions with data in and out.
341+
> **Note**: These return values are a bit verbose, but, since the HTTP handling side effects are delegated to the adapters, they have the added benefit of being easily testable functions with data in and out.
333342
334-
Your route handlers are packaged up into the generated `registerRouteHandlers` function which returns a list of objects containing the route method, path, and handler function.
343+
Your route handlers are packaged up in the generated `registerRouteHandlers` function which returns a list of objects containing route method, path, and handler function.
335344

336345
Adapters supply a `registerRoutes` function. It iterates through this data structure and uses the underlying framework (i.e. Express) to add each route, set headers, serialize response bodies, and terminate the response.
337346

338347
#### Content type serialization
339348

340-
Content type serialization and deserialization happens in the adapter layer.
349+
Content type serialization and deserialization happens in or near the adapter layer.
341350

342-
For Express, request bodies can be deserialized to JavaScript objects by middleware. The Express adapter assumes this has already happened and passes the deserialized (and presumably validated and coerced) JavaScript objects to your route handlers. The content type is passed as an argument to your handler in case you need to return a different response shape per.
351+
For Express, request bodies are deserialized into JavaScript objects prior to the Express adapter by Express middleware. The Express adapter assumes this has already happened, and passes the deserialized (and presumably validated and coerced) JavaScript objects to your route handlers. The content type is passed as an argument to your handler in case you need to return a different response shape per.
343352

344353
For response body serialization, `application/json` is built in and happens automatically. Other content types can be handled by supplying a `serializers` option to the `registerRoutes` function with custom serialization functions keyed by content type.
345354

@@ -433,21 +442,17 @@ components:
433442
import type * as ServerTypes from "./gen/server.ts";
434443
import type { Request, Response } from "express";
435444

436-
type DecoratedRequest = Request & {
437-
userId: string;
438-
};
439-
440445
const API: ServerTypes.Server<DecoratedRequest, Response> = {
441446
uhoh: async () => {
442447
return {
448+
status: 418,
443449
content: {
444450
default: {
445451
"application/json": {
446452
message: "This is what it looks like when something goes wrong",
447453
},
448454
},
449455
},
450-
status: 418,
451456
};
452457
},
453458
};
@@ -456,3 +461,7 @@ export default API;
456461
```
457462

458463
Otherwise, thrown errors will propagate up the call stack to your global error handler. You can check for `err instanceof NotImplementedError` if you want to handle those with a `501 Not Implemented` status code.
464+
465+
## Contributing
466+
467+
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.

0 commit comments

Comments
 (0)