はじめに
Swagger形式のOASを自動生成してくれるパッケージは無いか探していたところ、、、
TSOAという良さげなやつを見つけたので試してみました!
本記事で紹介する技術は以下になります。
- TSOA
- Node.js
- TypeScript
- express
- swagger
作業環境
OS: Windows 10 Pro
Node: 12.1.0
npm: 6.9.0
準備
Node+TypeScriptの環境を構築します。
PS C:\Users\user\Desktop\> mkdir project; cd project;
PS C:\Users\user\Desktop\project> npm init -y
PS C:\Users\user\Desktop\project> npm install -D typescript @types/node ts-node
PS C:\Users\user\Desktop\project> ./node_modules/.bin/tsc --init
tsconfig.jsonの設定
今回、デコレータ、importでJSONの読み込みを行うので下記のように設定にしました。
{
"compilerOptions": {
// importでJSON読み込み用
"moduleResolution": "node",
"resolveJsonModule": true,
// デコレータ用
"experimentalDecorators": true,
// 初期のまま
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
}
}
package.jsonの設定
ts-node
をnpmスクリプトで実行できるようにpackage.json
を書き換えます。
"scripts": {
"ts-node": "ts-node"
}
簡易的なAPIを作ってみる
プロジェクトにTSOA
をNPMでインストールします。
PS C:\Users\user\Desktop\project> npm install tsoa --save
今回は下記のような単純なAPIを用意します。
- GETでリクエストされたユーザIDからユーザ情報を取得するAPI
- POSTでリクエストされた情報でユーザ情報を登録するAPI
まずは、APIのエンドポイントとなるControllerを作成します。
PS C:\Users\user\Desktop\project> vi /controllers/usersController.ts
import { Body, Controller, Get, Header, Path, Post, Query, Route, SuccessResponse } from 'tsoa'
import { User, RequestBody } from '../models/user'
import { getUser, createUser } from '../services/userService';
@Route('users')
export class UsersController extends Controller {
// IDをPATHに含めたGETなAPIを定義
@Get('/get/{id}')
public getUser(id: number): User {
return getUser(id)
}
// POSTなAPI
@Post('/create')
public createUser(@Body() requestBody: RequestBody): string {
createUser(requestBody)
return 'success'
}
}
続いて、ユーザ情報の型定義となるModelを作成します。
PS C:\Users\user\Desktop\project> vi /models/user.ts
// 「id」と「name」をプロパティに持つUser情報の型定義
export interface User {
id: number
name: string
}
// 「name」をプロパティに持つリクエスト情報の型定義
export interface RequestBody {
name: string
}
最後に、API側で処理を行う部分となるServiceを作成します。
PS C:\Users\user\Desktop\project> vi /services/userService.ts
import { User, RequestBody } from '../models/user'
// ※Databaseとかに下記のようなデータ格納されているとする
const users: Array<User> = [
{
id: 1,
name: 'Tanka'
},
{
id: 2,
name: 'Suzuki'
}
]
// IDでユーザ情報を取得する関数
export const getUser = (id: number): User => {
return users.find((user) => user.id === id) || {}
}
// リクエストされた情報からユーザ情報を登録する関数
export const createUser = (body: RequestBody): void => {
users.push({
id: users.length + 1,
name: body.name
})
}
簡易的なAPIの作成が完了しました。
続いて、Swagger.jsonとルーティングファイルを自動生成するプログラムの作成に取り掛かります。
自動生成プログラムの作成
プロジェクト直下に下記のような自動生成用プログラムを用意しましょう。
PS C:\Users\user\Desktop\project> vi /generate.ts
import { generateRoutes, generateSwaggerSpec, RoutesConfig, SwaggerConfig } from 'tsoa'
(async () => {
// 自動生成するSwagger.jsonの設定を定義
const swaggerOptions: SwaggerConfig = {
basePath: '/api',
entryFile: './api/server.ts',
specVersion: 3,
outputDirectory: './api/dist',
controllerPathGlobs: ['./controllers/*Controller.ts'],
}
// 自動生成するルーティングファイルの設定を定義
const routeOptions: RoutesConfig = {
basePath: '/api',
entryFile: './api/server.ts',
routesDir: './api',
}
// 自動生成の実行
await generateSwaggerSpec(swaggerOptions, routeOptions)
await generateRoutes(routeOptions, swaggerOptions)
})();
ここまでの作成が終わったらプロジェクトのディレクトリ構成は以下のような感じになっているのではないでしょうか。
では、実際に自動生成を行いたいと思います。
自動生成を行う
下記のコマンドを実行します。
PS C:\Users\user\Desktop\project> npm run ts-node generate.ts
すると、無事にSwagger.jsonとルーティングファイルが自動生成されました。
生成したファイルを使ってみる
実際に生成されたファイルを使ってみます。
express
を使ってAPIサーバを立ち上げて、自動生成されたルーティングファイルを使ってみましょう。
ついてに、swagger-ui-express
を使って、自動生成されたSwagger.jsonからSwaggerUI画面を立ち上げてみましょう。
PS C:\Users\user\Desktop\project> npm install --save express @types/express
PS C:\Users\user\Desktop\project> npm install --save swagger-ui-express @types/swagger-ui-express
PS C:\Users\user\Desktop\project> vi /api/server.ts
import express from 'express'
import { RegisterRoutes } from './routes'
import '../controllers/usersController'
import swaggerUi from 'swagger-ui-express'
import swaggerDocument from './dist/swagger.json'
// ユーザリクエストの解析等
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// ルーティングファイルの登録
RegisterRoutes(app)
// Swagger UIの登録
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
// サーバ起動
app.listen(3000, () => {
console.log('App running at http://localhost:3000')
})
サーバの準備ができたら起動しましょう。
PS C:\Users\user\Desktop\project> npm run ts-node api/server.ts
App running at http://localhost:3000
CurlでAPIを叩いてみます。
# 「Satou」さんを登録してみる
$ curl -X POST "http://localhost:3000/api/users/create" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"name\"
:\"Satou\"}"
"success"
# 「Satou」さんを取得してみる
$ curl -X GET http://localhost:3000/api/users/get/3 -H "accept: application/json"
{"id":3,"name":"Satou"}
無事に、ユーザの登録/取得が出来ました。
http://localhost:3000/api-docs/
にアクセスしてSwaggerUI
の画面も確認してみましょう。
無事に、SwaggerUIの立ち上げも出来ました。
以上、TSOAを使ってみたでした!