Skip to content

🚧 openapi-decorators and openapi-adonis #1834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.DS_Store
dist
node_modules
coverage

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

Expand Down
13 changes: 13 additions & 0 deletions docs/.vitepress/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ export const en = defineConfig({
{ text: "About", link: "/openapi-react-query/about" },
],
},
{
text: "openapi-adonis",
items: [
{ text: "Getting Started", link: "/openapi-adonis/" },
],
},
{
text: "openapi-decorators",
items: [
{ text: "Getting Started", link: "/openapi-decorators/" },
{ text: "Decorators", link: "/openapi-decorators/decorators" },
],
},
],
},
search: {
Expand Down
2 changes: 1 addition & 1 deletion docs/data/contributors.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions docs/openapi-adonis/decorators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: openapi-adonis
---

## `@apiProperty`


70 changes: 70 additions & 0 deletions docs/openapi-adonis/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: openapi-adonis
---

# Introduction

openapi-adonis is an [Adonis.js] library to automatically generate OpenAPI schemas and documentation.

- ✅ Creates operations from the Adonis Router
- ✅ Automatically adds your models to the schemas
- ✅ Automatically adds your `@vinejs/vine` validators to the schemas
- ✅ Extended type-inference using Typescript metadata
- ✅ Extensible using Typescript decorators
- ✅ Generates documentation for **Swagger, Scalar, Rapidoc**

The library is inspired by the popular library [@nestjs/swagger](https://www.npmjs.com/package/@nestjs/swagger) and is built on top of [openapi-decorators](https://github.com/openapi-ts/openapi-typescript/tree/main/packages/openapi-decorators).

::: code-group

```tsx [app/controllers/users_controller.ts]
import { apiOperation, apiResponse } from "openapi-adonis/decorators";
import User from "#models/user";

class UsersController {
@apiOperation({ summary: "List users" })
@apiResponse({ type: [User] })
async list() {
return User.findManyBy({});
}
}
```

```tsx [app/models/user.ts]
import { apiProperty } from "openapi-adonis/decorators";

class User {
@apiProperty()
declare id: number;

@apiProperty()
declare name: string;

@apiProperty({ required: false })
declare mobile?: string;
}
```

```tsx [start/routes.ts]
import router from "@adonisjs/core/services/router";
import AdonisOpenAPI from "openapi-adonis";

const UsersController = () => import("#controllers/users_controller");

router.post("/users", [UsersController, "create"]);

const builder = AdonisOpenAPI.document().setTitle("OpenAPI Adonis Example");
AdonisOpenAPI.setup("/docs", router, builder);
```

:::

## Setup

Install this library by using `ace`:

```bash
node ace add openapi-adonis
```

## Basic usage
20 changes: 20 additions & 0 deletions docs/openapi-decorators/decorators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: Decorators
---

# Decorators

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`.

> For more information about the decorators, you can directly refer to the [source code](https://github.com/openapi-ts/openapi-typescript/packages/openapi-decorators/src/decorators).

| Decorator | Usage | Description |
|-|-|-|
| `@apiProperty` | Model | Configures a schema property. |
| `@apiTags` | Controller / Method | Adds tags to the operation. When applied on a controller, the tags are applied to all of its operations. |
| `@apiOperation` | Method | Configures an operation. |
| `@apiQuery` | Method | Adds a query parameter to the operation. |
| `@apiParam` | Method | Adds a path parameter to the operation. |
| `@apiResponse` | Method | Adds a response to the operation. |
| `@apiBody` | Method | Sets the requestBody of the operation. |

194 changes: 194 additions & 0 deletions docs/openapi-decorators/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
---
title: 'Getting started'
---

# Introduction

`openapi-decorators` is a framework agnostic library to automatically generate OpenAPI schemas and documentation by using Typescript decorators and metadata.

::: code-group

```ts [users_controller.ts]
import { apiOperation, apiResponse } from "openapi-adonis/decorators";
import User from "./user";

class UsersController {
@apiOperation({
method: "get",
pattern: "/users",
summary: "List users"
})
@apiResponse({ type: [User] })
async list() {
...
}
}
```

```ts [user.ts]
import { apiProperty } from "openapi-adonis/decorators";

class User {
@apiProperty()
declare id: number;

@apiProperty()
declare name: string;

@apiProperty({ required: false })
declare mobile?: string;
}
```

```ts [index.ts]
import "reflect-metadata";
import { DocumentBuilder } from "openapi-decorators/builders";
import { loadController } from "openapi-decorators/loaders";
import UsersController from "./users_controller";

const builder = new DocumentBuilder()
.setTitle("My API")
.setVersion("1.0.0");

await loadController(builder, UsersController);

console.log(document.build()); // <- Your generated OpenAPI specifications
```

:::

## Getting started

### Setup

Install `openapi-decorators` and `reflect-metadata` using your favorite package manager.

```bash
npm install openapi-decorators reflect-metadata
```

Import `reflect-metadata` in your main file.

::: code-group

```ts [index.ts]
import "reflect-metadata";

// Rest of your app
```

:::

Enable `experimentalDecorators` and `experimentalDecorators`.


::: code-group

```json [tsconfig.json]
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
}
}
```

:::

### Create your OpenAPI document

To get started, create a new DocumentBuilder. It will hold all the informations required to generate your OpenAPI specifications.
By using the method `build()` you can already have an (almost) empty documentation.

::: code-group

```ts [index.ts]
import "reflect-metadata";
import { DocumentBuilder } from "openapi-decorators/builders";

const builder = new DocumentBuilder()
.setTitle("My API")
.setVersion("1.0.0");

console.log(document.build()); // <- Your generated OpenAPI specifications
```

:::

### Create your first model

Using the `apiProperty` decorator on class properties will allow your operations to use the class as a schema.

> 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.

::: code-group

```ts [user.ts]
import { apiProperty } from "openapi-decorators/decorators";

class User {
@apiProperty()
declare id: string;

@apiProperty({ example: "John Doe" })
declare name: string;

@apiProperty()
declare email: string;

@apiProperty({ required: false })
declare mobile?: string;
}
```

:::

### Create your first controller

Next we need to define our first operation. We can do this by using a controller.

In the following example we create an operation `GET /users` that returns a list of `User`.

::: code-group

```ts [users_controller.ts]
import { apiOperation, apiResponse } from "openapi-decorators/decorators";
import User from "./user";

class UsersController {
@apiOperation({
method: "get",
pattern: "/users",
summary: "List users"
})
@apiResponse({ type: [User] })
async list() {
...
}
}
```

:::

### Load the controller into your DocumentBuilder

You now simply have to load the controller into your DocumentBuilder and tada 🎉.

::: code-group

```ts [index.ts]
import "reflect-metadata";
import { DocumentBuilder } from "openapi-decorators/builders";
import { loadController } from "openapi-decorators/loaders";
import UsersController from "./users_controller";

const builder = new DocumentBuilder()
.setTitle("My API")
.setVersion("1.0.0");

await loadController(builder, UsersController);

console.log(document.build()); // <- Your generated OpenAPI specifications
```

:::
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
"email": "[email protected]"
},
"scripts": {
"build": "pnpm run -r --parallel --filter \"!*docs\" --aggregate-output build",
"build": "pnpm run -r --filter \"!*docs\" --aggregate-output build",
"lint": "pnpm run -r --parallel --aggregate-output lint",
"dev": "pnpm run -r --parallel --filter \"{packages/*}\" --aggregate-output dev",
"format": "pnpm run -r --parallel --aggregate-output format",
"test": "pnpm run -r --parallel --aggregate-output test",
"test-e2e": "pnpm run -r --parallel --aggregate-output test-e2e",
Expand Down
5 changes: 5 additions & 0 deletions packages/openapi-adonis/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
example
test
tsconfig*.json
vitest.config.ts
biome.json
17 changes: 17 additions & 0 deletions packages/openapi-adonis/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
"extends": ["../../biome.json"],
"files": {
"ignore": ["./example/", "./coverage/"]
},
"linter": {
"rules": {
"complexity": {
"noBannedTypes": "off"
},
"suspicious": {
"noConfusingVoidType": "off"
}
}
}
}
22 changes: 22 additions & 0 deletions packages/openapi-adonis/example/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# http://editorconfig.org

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.json]
insert_final_newline = unset

[**.min.js]
indent_style = unset
insert_final_newline = unset

[MakeFile]
indent_style = space

[*.md]
trim_trailing_whitespace = false
6 changes: 6 additions & 0 deletions packages/openapi-adonis/example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TZ=UTC
PORT=3333
HOST=localhost
LOG_LEVEL=info
APP_KEY=30kuDPpn6wxNER9r0phf-cfQTMT2h_n_
NODE_ENV=development
Loading