Node+TypeScript+ExpressでAPIサーバ構築

# はじめに
Node+TypeScript+ExpressでAPIサーバを作っていきます。
本記事はTypeScript環境の構築からAPIサーバの作成までの流れを記した初心者向けな記事になります。

本記事で紹介する技術は以下になります。

- Node.js
- TypeScript
- ts-node
- express
- swagger

**作業環境**

```
OS: Windows 10 Pro
Node: 12.1.0
npm: 6.9.0 
```

# TypeScript+Node環境の構築

## Node環境でTypeScriptを始めるには

※手元のOSにNode.jsがインストールされていることを前提に始めます。

まずは適当に作業ディレクトリを作成して、その中に**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
```
作業するプロジェクト配下で`typescript`と`@types/node`をインストールしましょう。

`@types/node`は、Node.jsの型定義ファイルになります。
型定義ファイルというのは、TypeScriptのコンパイラに型を教えてくれるようなものです。
JavaScriptのライブラリは本来、JavaScript上で使用される事を想定しているので型定義が無いままに用意されていることが多いです。
そのため、TypeScript上で型チェックの恩恵を受けながら使用するために`@types`から始まる型定義ファイルが別途用意されております。
※Angular等の初めから型定義ファイルが用意されているライブラリも存在しています。

無事にインストールが出来ましたら、試しにTypescriptのバージョンを確認してみましょう。

```
PS C:\Users\user\Desktop\project> ./node_modules/.bin/tsc -v
Version 3.7.2
```
上記のように`Path`を打ち込むのが辛い場合は**npm-scriptsのタスク実行**を活用しましょう。
`npm init -y`で作成した`package.json`の`scripts`に下記を追加することで、タスク実行が可能になります。

```package.json
  "scripts": {
    "tsc:ver": "tsc -v" // これ
  },
```
```
# npm-scriptsによるタスク実行
PS C:\Users\user\Desktop\project> npm run tsc:ver
Version 3.7.2
```

TypeScriptがインストールされている事を確認出来たので、実際にTypeScriptのファイルを作って動作検証をしてみます。

その前に、`tsconfig.json`を作成しときましょう。
`tsconfig.json`とは、TypeScriptで記述されたファイル(.ts)をJavaScriptファイル(.js)にコンパイルする時の設定を記述するファイルです。
TypeScriptのプロジェクトには設置しておく必要があります。
`./node_modules/.bin/tsc --init`を実行することで簡単に作成することが出来ます。

```
PS C:\Users\user\Desktop\project> ./node_modules/.bin/tsc --init
message TS6071: Successfully created a tsconfig.json file.
```
※`tsconfig.json`の中身については適宜調べておくと良いかもですね。

続いて、TypeScriptファイルを作成してみます。

```
PS C:\Users\user\Desktop\project> vi index.ts
```
```index.ts
const hello = (name: string): void => console.log('Hello',name)
hello('Tarou')
```
作成できたら、tsファイルをjsファイルにコンパイルした後実行してみましょう。
ここでは、`npm-scripts`にコンパイル用のコマンドを定義しておきます。

```package.json
  "scripts": {
    "tsc": "tsc"
  },
```
```
# 実行するとindex.jsが生成されます。
PS C:\Users\user\Desktop\project> npm run tsc
# 生成されてindex.jsを実行します。
PS C:\Users\user\Desktop\project> node index.js
Hello Tarou
```

以上が、Node環境でTypeScriptを利用する一例になります。

## ts-nodeを使う

TypeScriptで記述されたプログラムを実行するためには、**tscコマンドでコンパイルした後にnodeで実行**という手順を取りました。
正直、開発中にいちいちコンパイルして実行するのは面倒くさいです。
これらを一気に実行してくれるのが、`ts-node`というパッケージになります。
さっそくインストールしてみます。

```
PS C:\Users\user\Desktop\project> npm install -D ts-node
```
パッケージを追加したら、`npm-scripts`に定義しておきましょう。

```package.json
  "scripts": {
    "tsc": "tsc",
    "ts-node": "ts-node"
  },
```
では、先ほど作成したtsファイルを`ts-node`で実行してみます。

```
PS C:\Users\user\Desktop\project> npm run ts-node index.ts

> project@1.0.0 ts-node C:\Users\user\Desktop\project
> ts-node "index.ts"

Hello Tarou
```
コンパイルを行わなずに`index.ts`を実行することが出来ました。
ちなみに、`ts-node`は実行の度にtsファイルをコンパイルするので実行完了は毎回遅いです。
また、`index.js`のようなコンパイルされたファイルは生成されません。
JSファイルを生成したい時は`tsc`でビルドしましょう。

以上が、TypeScript+Node環境の構築の流れでした。

# expressを使ってみよう

ここでは、一度は耳にしたことがありそうなNode.jsフレームワーク`express`に触れます。
expressの事については[公式](https://expressjs.com/ja/)やネットの記事等をご参照頂ければと思います。
`express`を使用してAPIサーバを実際に作ってみます。

まずは、expressパッケージをインストールします。
型定義ファイルも一緒にインストールします。

```
PS C:\Users\user\Desktop\project> npm install express
PS C:\Users\user\Desktop\project> npm install -D @types/express
```
インストールしたら、index.tsに`get`と`post`のapiサーバを実装していきます。
[公式ガイド](https://expressjs.com/ja/guide/routing.html)を参考にしました。

```index.ts
import express from 'express'

const app: express.Express = express()

// CORSの許可
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*")
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
  next()
})

// body-parserに基づいた着信リクエストの解析
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// GetとPostのルーティング
const router: express.Router = express.Router()
router.get('/api/getTest', (req:express.Request, res:express.Response) => {
  res.send(req.query)
})
router.post('/api/postTest', (req:express.Request, res:express.Response) => {
  res.send(req.body)
})
app.use(router)

// 3000番ポートでAPIサーバ起動
app.listen(3000,()=>{ console.log('Example app listening on port 3000!') })
```
無事にGetとPostのAPIサーバが出来上がりました。

CORSの許可する記述については、ローカル環境以外からAPIを実行したい時に必要な記述になります。
ローカル以外の環境から上記のAPIを実行すると、セキュリティの観点からアクセスが許されません。
ローカル内での実行のみならCORS許可の記述は不要です。
CORSの詳細については[こちら](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#What_requests_use_CORS)が参考になります。

`express.json()`と`express.urlencoded()`についてはクライアントのデータを取得する際に必要な記述になります。
従来は`body-parser`というパッケージをインストールして実装しておりましたが、Express標準に組み込まれたようです。

```従来のやり方
import bodyParser from 'body-parser'
const app = express()
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
```
では、`ts-node`で`index.ts`を実行してAPIサーバを起動します。

```
PS C:\Users\user\Desktop\project> npm run ts-node index.ts
```
別のターミナルからCURLでリクエストしてみましょう。

```bash
$ curl localhost:3000/api/getTest?name=hoge
{"name":"hoge"}
$ curl -X POST localhost:3000/api/postTest -d "name=hoge"
{"name":"hoge"}
```
無事に`express`を用いてAPIサーバを構築することが出来たようです。

# Swaggerを利用してみる

突然ですが、**Swagger**をご存じでしょうか？
Swaggerとは、RestAPIを構築するためのオープンソースなフレームワークです。
RestAPIの設計をする時に利用したりするツールになります。

 - [Swagger Spec](https://swagger.io/specification/)
 - [Swagger Editor](https://swagger.io/tools/swagger-editor/)
 - [Swagger UI](https://swagger.io/tools/swagger-ui/)
 - [Swagger Codegen](https://swagger.io/tools/swagger-codegen/)

APIの仕様書を作成したい時等に凄く便利なので知らない人はぜひ覚えとくとよいかもしれません。

## Swagger Editorを使ってOASを作成してみる

試しに、先ほどExpressで作成したAPIの仕様書をOAS形式で作成してみましょう。
OASというのはRestAPIの仕様定義です。詳細は[OAS](https://github.com/OAI/OpenAPI-Specification)をご参照ください。
SwaggerでOASを作成するツールとして**Swagger Editor**があります。
Web版が用意されているので[Swagger-Editor](http://editor.swagger.io/)にアクセスして作成してみます。

```openapi.yaml
openapi: 3.0.0
info:
  title: Sample API
  version: 0.0.1
servers:
  - url: http://localhost:3000/api
    description: Sample Host
tags:
  - name: Sample
paths:
  /getTest:
    get:
      tags: [ "Sample" ]
      summary: Get test.
      description: Get test.
      operationId: getTest
      parameters:
        - in: query
          name: name
          schema:
            type: string
      responses:
        '200':
          description: Sample
  /postTest:
    post:
      tags: [ "Sample" ]
      summary: Post test.
      description: Post test.
      operationId: postTest
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                name:
                  type: string
      responses:
        '200':
          description: Sample
```
今回はOASv3.0の形式で作成しました。※OASv2.0とは文法が異なるのでご注意ください。
一からの作成が面倒くさい場合は、上記を丸々コピーして貼り付ければ動くと思います。

Swagger Editorの右側のほうでリクエストテストが行えるので動作確認してみましょう。
まずは、先ほど作成したExpressのAPIサーバを起動します。

```
PS C:\Users\user\Desktop\project> npm run ts-node index.ts
> project@1.0.0 ts-node C:\Users\user\Desktop\project
> ts-node "index.ts"
Example app listening on port 3000!
```
起動できましたら、Swagger Editorの画面にアクセスします。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518115/6df349db-14e1-4faf-9ed7-345e2733c900.png)
上画像の「Try it out」を押下後、リクエストするパラメータを入力して「Excute」で実行してみましょう。

先ほど、CURLでのリクエストテストを行った時と同じような結果が返ってきたかと思います。
API仕様書の作成と同時にテストが行えるのは素晴らしいですね。


以上が、TypeScript環境の構築からAPIサーバの作成までの基本的な流れでした。
なにかの参考になれば幸いです。