Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Cody2333/koa-swagger-decorator
using decorator to automatically generate swagger doc for koa-router
https://github.com/Cody2333/koa-swagger-decorator
Last synced: about 2 months ago
JSON representation
using decorator to automatically generate swagger doc for koa-router
- Host: GitHub
- URL: https://github.com/Cody2333/koa-swagger-decorator
- Owner: Cody2333
- Created: 2017-07-19T10:06:36.000Z (over 7 years ago)
- Default Branch: main
- Last Pushed: 2023-09-22T07:25:16.000Z (over 1 year ago)
- Last Synced: 2024-10-14T08:33:00.775Z (3 months ago)
- Language: TypeScript
- Size: 767 KB
- Stars: 349
- Watchers: 9
- Forks: 81
- Open Issues: 36
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-koa - koa-swagger-decorator - 使用装饰器为 koa-router 自动生成 swagger 文档。 ![](https://img.shields.io/github/stars/Cody2333/koa-swagger-decorator.svg?style=social&label=Star) ![](https://img.shields.io/npm/dm/koa-swagger-decorator.svg?style=flat-square) (仓库 / 中间件)
README
# koa-swagger-decorator
> defined your api with simple decorators and generate api docs automatically
## Important
this docs is written for V2 and it's currently under development.
refer to [V1 Docs](https://github.com/Cody2333/koa-swagger-decorator/tree/develop) for V1 versionV2 version has undergone complete refactoring, introducing break change and new APIs to provide more type-safe functionality.
1. [Installation](#installation)
2. [Introduction](#introduction)
3. [Usage](#usage)
1. [Quick Example](#quick-example)
2. [Runnable Example](#runnable-example)
3. [Typescript Configuration](#typescript-configuration)
4. [Integrate with Koa](#integrate-with-koa)
5. [Define query/path params](#define-querypath-params)
6. [Define body/responses params](#define-bodyresponses-params)
7. [Using router.prefix](#using-routerprefix)
8. [Using Middlewares](#using-middlewares)4. [TODO List](#todo-list)
## Installation
`npm i koa-swagger-decorator@next`
## Introduction
Developing your type-safe API using simple decorators and zod schema with auto-generated OpenAPI docs based on [OpenAPI V3](https://swagger.io/specification/).
- use [zod schema](https://github.com/colinhacks/zod) to define and validate Request/Response objects.
- use [zod-to-openapi](https://github.com/asteasolutions/zod-to-openapi) to convert zod schema into [OpenAPI V3](https://swagger.io/specification/) schemas.
- use [@koa/router](https://github.com/koajs/router) to register routes & api handler to Koa application.## Usage
### Quick Example
```typescript
// define your api handler with @routeConfig decorator and it will generate OpenAPI Docs automatically
class UserController {
@routeConfig({ // define your API route info using @routeConfig decorator
method: "post",
path: "/users",
summary: "create a user",
tags: ["USER"],
operationId: "CreateUser",
})
@body(z.object({uid: z.string(), name: z.string(), age: z.number().min(18).optional()}))
async CreateUser(ctx: Context, args) {
// body params will be validated using zodSchema.parse(ctx.request.body)
// and assigned the parsed value to args.
console.log(args, args.body.uid, args.body.name);
ctx.body = { message: "create", id: "123" } as ICreateUserRes;
}
}
```
### Runnable Exampleyou can refer to example dir for details.
```typescript
git clone https://github.com/Cody2333/koa-swagger-decorator.git
cd koa-swagger-decorator
npm i
npm run dev// open http://localhost:3000/api/swagger-html to execute api
// open example dir for detail codes.
```
### Typescript Configurationtypescript is required. Please make sure **compilerOptions** is set correctly in tsconfig.json
```json
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
}
}
```### Integrate with Koa
following below steps to integrate your koa application with koa-swagger-decorator
1. Define your Request/Response with [Zod Schema](https://github.com/colinhacks/zod)
```typescript
// file -> ./schema/user.ts
import { z } from 'koa-swagger-decorator'
// define req/res schema
const CreateUserReq = z.object({
uid: z.string().nonempty(),
name: z.string().nullable().optional(),
age: z.number().min(18).nullable(),
operator: z.string().nonempty().optional(),
});const CreateUserRes = z.object({
id: z.string().nullable(),
message: z.string().nullable(),
});// export req/res typings
export type ICreateUserRes = z.infer;
export type ICreateUserReq = z.infer;
```
2. Write your API Handler with decorator and zod schema```typescript
// file -> ./controller/user.ts
import { Context } from "koa";
import { body, responses, routeConfig } from "../../lib/decorator";
import {
CreateUserReq,
CreateUserRes,
} from "../schemas/user";
import { ParsedArgs, z } from "../../lib";class UserController {
@routeConfig({ // define your API route info using @routeConfig decorator
method: "post",
path: "/users",
summary: "create a user",
tags: ["USER"],
operationId: "CreateUser",
})
@body(CreateUserReq)
@responses(CreateUserRes)
async CreateUser(ctx: Context, args: ParsedArgs) {
// args is injected with values = CreateUserReq.parse(ctx.request.body)
console.log(args, args.body.uid, args.body.name);
ctx.body = { message: "create", id: "123" } as ICreateUserRes;
}}
export { UserController };
```
3. Init SwaggerRouter Instance```typescript
// file -> ./routes/index.ts
import { SwaggerRouter } from 'koa-swagger-decorator'
import { UserController } from './controller/user'const router = new SwaggerRouter({
spec: {
info: {
title: "Example API Server",
version: "v1.0",
},
},
swaggerHtmlEndpoint: '/swagger-html',
swaggerJsonEndpoint: '/swagger-json',
});// apply swagger docs routes
router.swagger();// register user defined routes implementation
router
.applyRoute(UserController)
// .applyRoute(DemoController); // chained for more then one controller importsexport {router}
```4. Init Koa Application
```typescript
// file -> ./main.ts
import {router} from './routes/index'
const app = new Koa();
app
.use(cors())
.use(bodyParser())
.use(router.routes())
.use(router.allowedMethods());export default app.listen(config.port, () => {
console.log(`App is listening on ${config.port}.`);
});// running ts-node ./main.ts and that's all
```### Define query/path params
```typescript
@routeConfig({
method: "get",
path: "/user/{uid}",
summary: "get user by id",
description: "detailed user",
tags: ["USER"],
operationId: "GetUserById",
request: {
params: z.object({
uid: z.string().nonempty(), // path params, don't forget to add {uid} in [path] field.
}),
query: z.object({
count: z.coerce.number().default(10), // using z.coerce to convert query string into number & validate
limit: z.coerce.number().default(0),
})
},
})
```### Define body/responses params
define params by adding @body/@responses decorators to your handler
```typescript
@routeConfig({
path: "/users/update",
method: "put",
tags: ["USER"],
operationId: "UpdateUser",
})
@body([ZodSchema])
@responses([ZodSchema])
```### Using router.prefix
```typescript
const router = new SwaggerRouter({});router.prefix("/api");
```by calling router.prefix, your swagger docs routes & biz routes will automatically add prefix "**/api**".
Open http://localhost:3000/api/swagger-html to get swagger docs.### Using Middlewares
using @middlewares decorator for your handler method
```typescript
@middlewares([
async (ctx, next) => {
const x = ctx._swagger_decorator_meta as ItemMeta; // get swagger decorator meta info through ctx
console.log("biz mid", x.routeConfig);
await next();
},
])
```# TODO List
- [x] support request validation
- [ ] support response validation
- [x] support middleware decorator
- [x] support adding exist components to spec
- [ ] support generate openapi docs without starting app
- [ ] add unit test
- [ ] support form-data request
- [ ] support define non-200 responses
- [ ] support class decorators