You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+44-40Lines changed: 44 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,11 +2,11 @@
2
2
3
3
`openapi-typescript-server` is a CLI and minimal runtime library that helps you implement type-safe APIs documented by OpenAPI.
4
4
5
-
It works by generating a TypeScript server interface based on the operations defined in your OpenAPI spec using types from the [openapi-typescript](https://github.com/openapi-ts/openapi-typescript) package.
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).
6
6
7
-
You provide a concrete implementation that satisfies the interface.
7
+
You provide a concrete implementation that satisfies the interface for each path operation.
8
8
9
-
At runtime, your implementation is handed off to adapters that convert it into HTTP handlers for various frameworks like [Express](https://expressjs.com/).
9
+
At runtime, your implementation is converted into HTTP handlers for various frameworks like [Express](./packages/openapi-typescript-server-express/README.md).
10
10
11
11
## Stability
12
12
@@ -18,13 +18,13 @@ For now, proceed with caution!
18
18
19
19
### Installation
20
20
21
-
Install the build-time packages as dev dependencies:
> **Note**: The `--types` path is relative to the output directory so the generated code can import it correctly.
105
105
106
-
Implement your API handlers
106
+
Implement your API handlers:
107
107
108
108
`api.ts`
109
109
110
110
```typescript
111
111
importtype*asServerTypesfrom"./gen/server.ts";
112
112
importtype { Request, Response } from"express";
113
113
114
-
// Explicitly specifying the type rather than relying on structural typing, gives you type inference for handler arguments and faster feedback in the definition vs at the call site.
114
+
// Explicitly specifying the type (rather than relying on structural typing)
115
+
// gives you type inference for handler arguments and faster feedback in the
@@ -162,7 +164,7 @@ export default function makeApp() {
162
164
// Register your typed route handlers
163
165
const routeHandlers =registerRouteHandlers(API);
164
166
165
-
// Make Express routes from your route handlers.
167
+
// Make Express routes from your route handlers
166
168
registerRoutes(routeHandlers, apiRouter);
167
169
168
170
// Mount to the correct base path
@@ -282,7 +284,35 @@ Satisfy the compiler to get it working again:
282
284
283
285
This pattern also guides you when adding or removing routes.
284
286
285
-
### How does this work?
287
+
## Deeper dive
288
+
289
+
### Design goals
290
+
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.
292
+
293
+
This schema-first approach documents your system for humans or LLM coding agents, and helps you achieve type safety across the system.
294
+
295
+
### In scope/goals
296
+
297
+
-**Trade off build time complexity for runtime simplicity**. By using codegen as a build step, the surface area of what's executed on the server is reduced.
298
+
-**Keep package footprint small**. Keep the solution space narrow by integrating with existing solutions.
299
+
300
+
### Out of scope/non-goals
301
+
302
+
-**Schema validation & type coercion**. This package assumes that all data inputs have been validated and coerced to the expected types by the time they get to your route handlers. Use other middleware like [express-openapi-validator](https://github.com/cdimascio/express-openapi-validator) to handle validation and coercion.
303
+
-**Security & auth scopes**. This package does not handle any authentication nor authorization and ignores all security aspects of your OpenAPI schema.
304
+
305
+
### Inspiration & prior art
306
+
307
+
This package was heavily influenced by the [Go oapi-codegen](https://github.com/oapi-codegen/oapi-codegen) package and gRPC ergonomics.
308
+
309
+
### Comparison to other solutions
310
+
311
+
-[openapi-typescript](https://github.com/openapi-ts/openapi-typescript). This library only generates types from an OpenAPI spec, not operation interfaces. This is foundational to this library, but only part of the solution.
312
+
-[openapi-ts-router](https://github.com/builder-group/community/tree/develop/packages/openapi-ts-router). This library works similarly, but requires that you bring your own path validators alongside the route handlers. It also doesn't ensure that you've implemented the entire spec.
313
+
-[tRPC](https://trpc.io/). This library tightly couples frontend and backend code and only works for systems that are TypeScript on the frontend and backend. It also requires a decent amount of runtime complexity to tie clients and servers together.
314
+
315
+
### How does it work?
286
316
287
317
#### Route handling
288
318
@@ -301,15 +331,15 @@ The return value is enveloped in `content` so that you can provide `headers` and
301
331
302
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.
303
333
304
-
Your route handlers are packaged up into the generated `registerRouteHandlers` function. This returns a list of objects containing the route method, path, and handler function.
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.
305
335
306
-
Adapters supply a `registerRoutes` function which 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.
336
+
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.
307
337
308
338
#### Content type serialization
309
339
310
340
Content type serialization and deserialization happens in the adapter layer.
311
341
312
-
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 content type.
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.
313
343
314
344
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.
315
345
@@ -426,29 +456,3 @@ export default API;
426
456
```
427
457
428
458
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.
429
-
430
-
## Design goals
431
-
432
-
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.
433
-
434
-
This schema-first approach documents your system for humans or LLM coding agents, and helps you achieve type safety across the system.
435
-
436
-
### In scope/goals
437
-
438
-
-**Trade off build time complexity for runtime simplicity**. By using codegen as a build step, the surface area of what's executed on the server is reduced.
439
-
-**Keep package footprint small**. Keep the solution space narrow by integrating with existing solutions.
440
-
441
-
### Out of scope/non-goals
442
-
443
-
-**Schema validation & type coercion**. This package assumes that all data inputs have been validated and coerced to the expected types by the time they get to your route handlers. Use other middleware like [express-openapi-validator](https://github.com/cdimascio/express-openapi-validator) to handle validation and coercion.
444
-
-**Security & auth scopes**. This package does not handle any authentication nor authorization and ignores all security aspects of your OpenAPI schema.
445
-
446
-
### Inspiration & prior art
447
-
448
-
This package was heavily influenced by the [Go oapi-codegen](https://github.com/oapi-codegen/oapi-codegen) package and gRPC ergonomics.
449
-
450
-
### Comparison to other solutions
451
-
452
-
-[openapi-typescript](https://github.com/openapi-ts/openapi-typescript). This library only generates types from an OpenAPI spec, not operation interfaces. This is foundational to this library, but only part of the solution.
453
-
-[openapi-ts-router](https://github.com/builder-group/community/tree/develop/packages/openapi-ts-router). This library works similarly, but requires that you bring your own path validators alongside the route handlers. It also doesn't ensure that you've implemented the entire spec.
454
-
-[tRPC](https://trpc.io/). This library tightly couples frontend and backend code and only works for systems that are TypeScript on the frontend and backend. It also requires a decent amount of runtime complexity to tie clients and servers together.
Copy file name to clipboardExpand all lines: examples/docs/api.ts
+3-1Lines changed: 3 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,9 @@
1
1
importtype*asServerTypesfrom"./gen/server.ts";
2
2
importtype{Request,Response}from"express";
3
3
4
-
// Explicitly specifying the type rather than relying on structural typing, gives you type inference for handler arguments and faster feedback in the definition vs at the call site.
4
+
// Explicitly specifying the type (rather than relying on structural typing)
5
+
// gives you type inference for handler arguments and faster feedback in the
0 commit comments