概要
Node.js、fastify、TypeScript、Swaggerで簡単なサンプルを作ってみたので共有します。
サンプルコード: https://github.com/swmokyun/sample-fastify-typescript-swagger
目的
- とにかくラクにRESTサーバを作りたい
- pythonでもいいけどフロントエンドでNext.jsとかつかうからNode.jsで言語を統一したい
- TypeScriptで型の恩恵を受けたい
- SwaggerでRESTスキーマまわりのあれこれをラクしたい
expressよりfastifyがいいらしい
Node.jsでサーバといえばexpressと思ってたけど、最近ではKoa.jsとかfastifyが有力候補らしい。fastifyの方がtypescriptまわりがいい感じにサポートされているっぽいのでこっちをチョイス。
fastify-swaggerがいい感じ
調べた感じではfastify-swaggerを使うとtypescriptで型補完しながらスキーマ定義が記述できるっぽい。これは素晴らしい。
https://github.com/fastify/fastify-swagger
typeboxでさらにいい感じ
typeboxを使うとfastifyでスキーマ定義と関数の型を共通化できる。これはさらに素晴らしい。
https://www.fastify.io/docs/latest/TypeScript/#json-schema
サンプル
公式を参考にGETやqueryのサンプルを追加したのが以下になります。
また、各モジュールのバージョンは以下になっています。fastifyはバージョンがあがると結構APIが変わるっぽいので注意。
"@sinclair/typebox": "^0.23.1",
"fastify": "^3.24.1",
"fastify-swagger": "^4.12.6"
import { Static, Type } from "@sinclair/typebox"
import fastify, { FastifyInstance } from "fastify"
import fastifySwagger from "fastify-swagger"
const PORT = 9000
const server: FastifyInstance = fastify({ logger: true })
/**
* swagger
*/
server.register(fastifySwagger, {
routePrefix: "/docs",
swagger: {
info: {
title: "Test swagger",
description: "Testing the Fastify swagger API",
version: "0.1.0",
},
},
exposeRoute: true,
})
/**
* test_post
* https://www.fastify.io/docs/latest/TypeScript/#typebox
*/
const User = Type.Object({
name: Type.String(),
mail: Type.Optional(Type.String({ format: "email" })),
})
type UserType = Static<typeof User>
server.post<{ Body: UserType; Reply: UserType }>(
"/test_post",
{
schema: {
body: User,
response: {
200: User,
},
},
},
(req, rep) => {
const { body: user } = req
rep.status(200).send(user)
}
)
/**
* test get, querystring
*/
const ErrorResponse = Type.Object({
msg: Type.String(),
})
type ErrorResponseType = Static<typeof ErrorResponse>
server.get<{ Querystring: UserType; Reply: UserType | ErrorResponseType }>(
"/test_get",
{
schema: {
querystring: User,
response: {
200: User,
400: ErrorResponse,
},
},
},
(req, rep) => {
const { query: user } = req
if (user.name.length < 3) {
rep.status(400).send({ msg: "name is too short" })
} else {
rep.status(200).send(user)
}
}
)
server.listen(PORT)
http://localhost:9000/docs
でSwaggerからAPIの確認やJSONスキーマの出力が可能。とっても便利で開発が捗ります。