Node.js, Express, Typescript でREST APIを作成する手順をまとめます。自分が好きな情報を詰め込んでいるので、必要ない物は省いてカスタマイズしてください。
準備
Node.jsとnpmがインストール済みであることを node -v
, npm -v
のコマンドを実行して確認します。
開発を行うディレクトリで npm init
を実行して package.json が作成されることを確認します。いくつか質問が出てきますが全てそのままエンターを押して大丈夫です。
必要なライブラリなどのインストール
express(4系)やTypescript用のパッケージをインストールします。
$ npm install express --save
$ npm install helmet --save
$ npm install cors --save
$ npm install mongodb mongoose --save
$ npm install body-parser --save
$ npm install moment --save
$ npm install -D typescript @types/node
$ npm install -D @types/express @types/helmet @types/cors @types/mongoose
$ npm install -D ts-node
npmを使ってインストールしていきます。
--save
のオプションをつけるとpackage.jsonの dependencies
に書き込まれます。
-D
のオプションをつけるとpackage.jsonの devDependencies
(開発用) に書き込まれます。
ディレクトリ構成
コードの見通しを意識して、とりあえず次のような構成にします。
express-api
|---- /app
| └ app.ts
| └ /models
|ㅤ └ /routes
| └ /services
|
|---- package.json
app.ts これを実行してサーバーを起動します
/models データベースのモデル情報
/routes 各apiの振り分け
/services サービスの処理
package.json パッケージ管理
Typescript準備
npx tsc --init
でtsconfig.jsonファイルを作成します。
tsconfig.jsonのtargetがes5だった場合、es6に変更します。
コードを書く
Hello World
まずはapp.ts
に以下を記述して、hello world が返却されることまで確認しましよう。
// ライブラリ読み込み
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
const app = express();
app.use(helmet());
app.use(cors());
const bodyParser = require('body-parser');
//body-parserの設定
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const port = process.env.PORT || 3000; // port番号を指定
app.get('/helloWorld', (req, res) => {
res.status(200).send({ message: 'hello, world' });
});
//サーバ起動
app.listen(port);
console.log('listen on port ' + port);
npx tsc
コマンドを実行するとコンパイルされ、jsファイルに変換されます。
node app/app.js
コマンドでファイルを実行します。
コンソールに listen on port 3000
が表示されたことを確認したら、postmanを立ち上げて、http://localhost:3000/helloWorld にGETリクエストを送りましょう。
以下のようにレスポンスが返ってくれば成功です!!
{
"message": "Hello, world"
}
ts-node コマンドを利用すると、 tsc -> node の実行を自動的に行ってくれるので開発効率をあげることができます。npx ts-node app/app.ts
で実行してみましょう。
ソースコードの変更を検知するたびに自動的に再実行してくれる ts-node-dev というコマンドもありますが、今回は省略します。
いずれも Ctrl + C
で終了できます。
apiをディレクトリで分けて綺麗にする
まず、app.ts
を以下のように書き換えます。
// ライブラリ読み込み
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
const app = express();
app.use(helmet());
app.use(cors());
const bodyParser = require('body-parser');
//body-parserの設定
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const port = process.env.PORT || 3000; // port番号を指定
// ------ ルーティング ------ //
const router = require('./routes/');
app.use('/', router);
//サーバ起動
app.listen(port);
console.log('listen on port ' + port);
これでroutesでルーティングする設定になりました。続いて、routes配下にindex.ts
を作成して、以下のように記述しましょう。
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
const app = express();
app.use(helmet());
app.use(cors());
// ルーティングする
const router = express.Router();
// routerにルーティングの動作を記述する
router.get('/helloWorld', (req, res) => {
res.status(200).send({ message: 'Hello, world' });
});
// -------------------------------------------------
// 以下、何のルーティングにもマッチしないorエラー
// -------------------------------------------------
// いずれのルーティングにもマッチしない(==NOT FOUND)
app.use((req, res) => {
res.status(404);
res.render('error', {
param: {
status: 404,
message: 'not found'
},
});
});
//routerをモジュールとして扱う準備
module.exports = router;
ts-node コマンドを実行して、postmanでAPIを叩くと同じ結果が返ってくることを確認します。
続いて、サービスに設定していきましょう。
routes/index.tsにtestという名前のAPIを追加しましょう。
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
import { TestService } from '../services/TestService';
const app = express();
app.use(helmet());
app.use(cors());
// ルーティングする
const router = express.Router();
// routerにルーティングの動作を記述する
router.get('/helloWorld', (req, res) => {
res.status(200).send({ message: 'Hello, world' });
});
router.get('/test', (req, res, next) => {
const service = new TestService();
service
.test()
.then(result => res.status(200).send(result))
.catch(next);
});
// -------------------------------------------------
// 以下、何のルーティングにもマッチしないorエラー
// -------------------------------------------------
// いずれのルーティングにもマッチしない(==NOT FOUND)
app.use((req, res) => {
res.status(404);
res.render('error', {
param: {
status: 404,
message: 'not found'
},
});
});
//routerをモジュールとして扱う準備
module.exports = router;
そして、services配下にTestService.ts
を作成して、以下のように記述します。
//インターフェース
export interface ITest {
test: string;
}
//クラス
export class TestService {
public async test(): Promise<ITest> {
return {
test: 'test1'
}
}
}
http://localhost:3000/test にGETリクエストを送り、以下のレスポンスが返ってくると成功です!
{
"test": "test1"
}
続いてDB、Schemaを設定していきましょう。
mongoDB準備
mongoDBインストール
以下のコマンドでmongoDBをインストールします。
brew tap mongodb/brew
brew install mongodb-community
mongodbの設定ファイルが/usr/local/etc/mongod.confに作成されます。
中身を確認するとログとデータベースの保存先のパスが記述されています。
mongoDBの起動
brew services start mongodb-community
mongo コマンドでDBに接続できます。
データ追加
以下コマンドで app1db というデータベースを作成します。
use app1db
データベースにswitchされるので、以下コマンドでデータを追加します。
> db.test_user.insert({"user":"user1","email":"user1@gmail.com"})
> db.test_user.insert({"user":"user2","email":"user2@gmail.com"})
このコマンドで test_user というcollection (RDBMSでいうtableのようなもの) にBSONのフォーマットでuserなどの情報が保存される。
DB接続部分の追加
mongoDBに接続する部分をapp.tsに追加します。
// mongodb
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const options = {
useUnifiedTopology : true,
useNewUrlParser : true
}
mongoose.connect('mongodb://localhost:27017/app1db', options);
mongoose.connection.on('error', function(err: any) {
console.error('MongoDB connection error: ' + err);
process.exit(-1);
});
Modelファイルを作成する
models配下にTestMongoModel.ts
を作成し、以下を記述します。
import mongoose from 'mongoose'; //mongoDBに接続するためのライブラリ
const Schema = mongoose.Schema; //mongoDBのスキーマを作る
const TestMongoSchema = new Schema({
user :String,
email: String
},{
collection: 'test_user'
});
// スキーマをモデルとしてコンパイルし、それをモジュールとして扱えるようにする
module.exports = mongoose.model('TestMongoModel', TestMongoSchema);
続いてDBからデータを取得する新規APIの準備をしていきましょう。
routes/index.tsに test/mongo/:user のパスを追加します。
router.get('/test/mongo/:user', (req, res, next) => {
const { user } = req.params;
const service = new TestMongoService();
service
.run(user)
.then(result => res.status(200).send(result))
.catch(next);
});
さらにservices配下にTestMongoService.ts
を作成し、以下を記述します。
//インターフェース
export interface ITest {
user: string;
email: string;
}
//クラス
export class TestMongoService {
public async run(params: any): Promise<ITest> {
const testAll = await TestMongoModel.find();
return testAll;
}
}
パスパラメータを活かせてませんが、これで一通りできました。
postmanでhttp://localhost:3000/test/mongo/alluser でAPIを叩くと以下が表示されることを確認できれば成功です!!
[
{
"_id": "5f12ec4732c83a71dcf0e7db",
"user": "user1",
"email": "user1@gmail.com"
},
{
"_id": "5f12ec5532c83a71dcf0e7dc",
"user": "user2",
"email": "user2@gmail.com"
}
]
参考資料
https://qiita.com/drafts/73cc7160d002a4989416/edit
https://qiita.com/notakaos/items/3bbd2293e2ff286d9f49