Skip to content

Commit 09624c3

Browse files
authored
openapi-metadata (#1992)
1 parent 7971500 commit 09624c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2447
-14
lines changed

.changeset/strange-nails-jam.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-metadata": patch
3+
---
4+
5+
Inititial release

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.DS_Store
22
dist
33
node_modules
4+
coverage
45

56
packages/openapi-typescript/test/fixtures/cli-outputs/out
67

docs/.vitepress/en.ts

+31-5
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,19 @@ export default defineConfig({
7171
},
7272
{
7373
text: "openapi-react-query",
74+
base: "/openapi-react-query",
7475
items: [
75-
{ text: "Getting Started", link: "/openapi-react-query/" },
76-
{ text: "useQuery", link: "/openapi-react-query/use-query" },
77-
{ text: "useMutation", link: "/openapi-react-query/use-mutation" },
78-
{ text: "useSuspenseQuery", link: "/openapi-react-query/use-suspense-query" },
79-
{ text: "queryOptions", link: "/openapi-react-query/query-options" },
76+
{ text: "Getting Started", link: "/" },
77+
{ text: "useQuery", link: "/use-query" },
78+
{ text: "useMutation", link: "/use-mutation" },
79+
{
80+
text: "useSuspenseQuery",
81+
link: "/use-suspense-query",
82+
},
83+
{
84+
text: "queryOptions",
85+
link: "/query-options",
86+
},
8087
{ text: "About", link: "/openapi-react-query/about" },
8188
],
8289
},
@@ -93,6 +100,19 @@ export default defineConfig({
93100
{ text: "About", link: "/about" },
94101
],
95102
},
103+
{
104+
text: "openapi-metadata",
105+
base: "/openapi-metadata",
106+
items: [
107+
{ text: "Getting Started", link: "/" },
108+
{ text: "Decorators", link: "/decorators" },
109+
{ text: "Metadata", link: "/metadata" },
110+
{ text: "Type loader", link: "/type-loader" },
111+
{ text: "UI Integrations", link: "/ui" },
112+
{ text: "Examples", link: "/examples" },
113+
{ text: "About", link: "/about" },
114+
],
115+
},
96116
],
97117
},
98118
search: {
@@ -103,6 +123,12 @@ export default defineConfig({
103123
indexName: "openapi-ts",
104124
},
105125
},
126+
socialLinks: [
127+
{
128+
icon: "github",
129+
link: "https://github.com/openapi-ts/openapi-typescript",
130+
},
131+
],
106132
footer: {
107133
message:
108134
'Released under the <a href="https://github.com/openapi-ts/openapi-typescript/blob/main/packages/openapi-typescript/LICENSE">MIT License</a>.',

docs/data/contributors.json

+1-1
Large diffs are not rendered by default.

docs/openapi-metadata/about.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: About openapi-metadata
3+
description: openapi-metadata Project Goals, comparisons, and more
4+
---
5+
6+
<script setup>
7+
import { VPTeamMembers } from 'vitepress/theme';
8+
import contributors from '../data/contributors.json';
9+
</script>
10+
11+
# About
12+
13+
## Project Goals
14+
15+
1. Must respect the OpenAPI V3 specification
16+
2. Be extensible and easily integrated inside backend frameworks
17+
3. Be focused around developer experience
18+
19+
## Contributors
20+
21+
This library wouldn’t be possible without all these amazing contributors:
22+
23+
<VPTeamMembers size="small" :members="contributors['openapi-metadata']" />

docs/openapi-metadata/decorators.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: Decorators
3+
---
4+
5+
# Decorators
6+
7+
Decorators are used to enrich your OpenAPI specifications. They can be applied on a Controller, a Method or a Model. They are all prefixed with `Api`.
8+
9+
> For more information about the decorators, you can directly refer to the [source code](https://github.com/openapi-ts/openapi-typescript/packages/openapi-metadata/src/decorators).
10+
11+
| Decorator | Usage | Description |
12+
| ----------------------- | ------------------- | ------------------------------------------------------------------------ |
13+
| `@ApiBody` | Method | Sets the requestBody of the operation. |
14+
| `@ApiCookie` | Controller / Method | Adds a cookie parameter to the operation(s). |
15+
| `@ApiExcludeController` | Method | Excludes the operations of this controller from the document generation. |
16+
| `@ApiExcludeOperation` | Method | Excludes this operation from the document generation. |
17+
| `@ApiExtraModels` | Controller | Adds extra models to be loaded in the schema. |
18+
| `@ApiHeader` | Controller / Method | Adds a header parameter to the operation(s). |
19+
| `@ApiOperation` | Method | Configures an operation. |
20+
| `@ApiParam` | Controller / Method | Adds a path parameter to the operation(s). |
21+
| `@ApiProperty` | Model | Configures a schema property property. |
22+
| `@ApiQuery` | Controller / Method | Adds a query parameter to the operation(s). |
23+
| `@ApiResponse` | Controller / Method | Adds a response to the operation(s). |
24+
| `@ApiSecurity` | Controller / Method | Sets the security scheme to the operation(s). |
25+
| `@ApiTags` | Controller / Method | Adds tags to the operation(s). |

docs/openapi-metadata/examples.md

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: Examples
3+
---
4+
5+
# Examples
6+
7+
This library is made to be used through an integration with your favorite framework but you can as well use it directly as a document generator.
8+
9+
## Express
10+
11+
```ts
12+
import express from "express";
13+
import { generateDocument } from "openapi-metadata";
14+
import { generateScalarUI } from "openapi-metadata/ui";
15+
16+
const app = express();
17+
18+
const document = await generateDocument(yourConfiguration);
19+
20+
app.get("/api", async (req, res) => {
21+
res.send(JSON.stringify(document));
22+
});
23+
24+
app.get("/api/docs", (req, res) => {
25+
const ui = generateScalarUI("/api");
26+
res.send(ui);
27+
});
28+
```
29+
30+
## Fastify
31+
32+
```ts
33+
import fastify from "fastify";
34+
import { generateDocument } from "openapi-metadata";
35+
import { generateScalarUI } from "openapi-metadata/ui";
36+
37+
const app = Fastify();
38+
39+
const document = await generateDocument(yourConfiguration);
40+
41+
app.get("/api", async () => {
42+
return document;
43+
});
44+
45+
app.get("/api/docs", () => {
46+
const ui = generateScalarUI("/api");
47+
return ui;
48+
});
49+
```

docs/openapi-metadata/index.md

+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
---
2+
title: "Getting started"
3+
---
4+
5+
# Introduction
6+
7+
`openapi-metadata` is a framework agnostic library to automatically generate OpenAPI schemas and documentation by using Typescript decorators and metadata.
8+
9+
::: code-group
10+
11+
```ts [users_controller.ts]
12+
import { ApiOperation, ApiResponse } from "openapi-metadata/decorators";
13+
import User from "./user";
14+
15+
class UsersController {
16+
@ApiOperation({
17+
method: "get",
18+
pattern: "/users",
19+
summary: "List users"
20+
})
21+
@ApiResponse({ type: [User] })
22+
async list() {
23+
...
24+
}
25+
}
26+
```
27+
28+
```ts [user.ts]
29+
import { ApiProperty } from "openapi-metadata/decorators";
30+
31+
class User {
32+
@ApiProperty()
33+
declare id: number;
34+
35+
@ApiProperty()
36+
declare name: string;
37+
38+
@ApiProperty({ required: false })
39+
declare mobile?: string;
40+
}
41+
```
42+
43+
```ts [index.ts]
44+
import "reflect-metadata";
45+
import { generateDocument } from "openapi-metadata";
46+
import UsersController from "./users_controller";
47+
48+
const document = await generateDocument({
49+
controllers: [UsersController],
50+
document: {
51+
info: {
52+
name: "My Api",
53+
version: "1.0.0",
54+
},
55+
},
56+
});
57+
58+
console.log(document); // <- Your generated OpenAPI specifications
59+
```
60+
61+
:::
62+
63+
- ✅ Fully compliant [OpenAPI V3](https://swagger.io/specification/)
64+
- ✅ Automatic type inference
65+
- ✅ Supports [Scalar](https://scalar.com/), [Swagger UI](https://swagger.io/tools/swagger-ui/) and [Rapidoc](https://rapidocweb.com/)
66+
- ✅ Extensible with custom type loaders
67+
- ✅ Ready to be integrated with your favorite framework
68+
69+
## Getting started
70+
71+
### Setup
72+
73+
Install `openapi-metadata` and `reflect-metadata` using your favorite package manager.
74+
75+
```bash
76+
npm install openapi-metadata reflect-metadata
77+
```
78+
79+
Import `reflect-metadata` in your main file.
80+
81+
::: code-group
82+
83+
```ts [index.ts]
84+
import "reflect-metadata";
85+
86+
// Rest of your app
87+
```
88+
89+
:::
90+
91+
Enable `experimentalDecorators` and `experimentalDecorators`.
92+
93+
::: code-group
94+
95+
```json [tsconfig.json]
96+
{
97+
"compilerOptions": {
98+
"emitDecoratorMetadata": true,
99+
"experimentalDecorators": true
100+
}
101+
}
102+
```
103+
104+
:::
105+
106+
### Create your OpenAPI document
107+
108+
To get started, you can use the `generateDocument` function to create an (almost) empty documentation. You can define a base document that will be merged with the generated one.
109+
110+
::: code-group
111+
112+
```ts [index.ts]
113+
import "reflect-metadata";
114+
import { generateDocument } from "openapi-metadata";
115+
116+
const builder = await generateDocument({
117+
controllers: [],
118+
document: {
119+
info: {
120+
name: "My API",
121+
version: "1.0.0",
122+
},
123+
},
124+
});
125+
126+
console.log(document.build()); // <- Your generated OpenAPI specifications
127+
```
128+
129+
:::
130+
131+
### Create your first controller
132+
133+
A controller is a simple class where each methods could be an Operation.
134+
In the following example we have a `UsersController` which declares an operation `GET /users` that returns a list of `Users`.
135+
136+
::: code-group
137+
138+
```ts [controllers/users_controller.ts]
139+
import { ApiOperation, ApiResponse } from "openapi-metadata/decorators";
140+
import User from "../schemas/user";
141+
142+
export default class UsersController {
143+
@ApiOperation({
144+
method: "get",
145+
pattern: "/users",
146+
summary: "List users",
147+
})
148+
@ApiResponse({ type: [User] })
149+
async list() {
150+
// ...your logic
151+
}
152+
}
153+
```
154+
155+
:::
156+
157+
### Create your first schema
158+
159+
In our controller we define the response of your operation to be `[User]` (a list of users). We now need to create this model.
160+
161+
By using the `@ApiProperty` decorator on class we can define the properties of our schema.
162+
163+
> Unlike other libraries like `@nestjs/swagger`, every element of your OpenAPI schema is lazy-loaded. Your models will only be part of your documentation if it is used.
164+
165+
::: code-group
166+
167+
```ts [schemas/user.ts]
168+
import { ApiProperty } from "openapi-metadata/decorators";
169+
170+
export default class User {
171+
@ApiProperty()
172+
declare id: string;
173+
174+
@ApiProperty({ example: "John Doe" })
175+
declare name: string;
176+
177+
@ApiProperty()
178+
declare email: string;
179+
180+
@ApiProperty({ required: false })
181+
declare mobile?: string;
182+
}
183+
```
184+
185+
:::
186+
187+
### Add the controller to the generated document
188+
189+
Now that we have our controller ready, we can use it to generate our document.
190+
191+
::: code-group
192+
193+
```ts [index.ts]
194+
import "reflect-metadata";
195+
import { generateDocument } from "openapi-metadata";
196+
import UsersController from "./controllers/users_controller.ts";
197+
198+
const builder = await generateDocument({
199+
controllers: [UsersController],
200+
document: {
201+
info: {
202+
name: "My API",
203+
version: "1.0.0",
204+
},
205+
},
206+
});
207+
208+
console.log(document.build()); // <- Your generated OpenAPI specifications
209+
```
210+
211+
:::
212+
213+
### Going further

0 commit comments

Comments
 (0)