TypeScript
docker
DynamoDB
TypeORM
NestJS

TypeScript + Serverless + ORM + RoutingMiddlewareを探す旅

こちらの続きです。


結論

このあたりをうまく組みあわせるとそこそこ楽ちんだった


僕のわがまま


  1. Requestの検証をしたい

  2. ドメイン駆動的にEntityを中心とした設計をしたい

  3. ローカル開発をDockerで、Deployはserverlessでやりたい

  4. DBは案件に応じて柔軟に変更できるようにしたい

  5. (後から出てきたけど)webpackもうやだ。消したい

今回はDynamoDB編として紹介します


1. Requestの検証をしたい

nestのこのへんの仕組みclass-validatorで無事解決。

書いておくだけで勝手に検証してくれて適切なエラーを返してくれるのでチョー楽。


UserController.ts

@Put(':id')

@HttpCode(200)
async update(@Param() params: IdRequest, @Body() body: AddUserRequest) {
await this.repository.save({...params, ...body});
}


2. ドメイン駆動的にEntityを中心とした設計をしたい

勝手にEntityつくればおk

1. と同様にclass-validatorのおかげでだいぶ楽

簡単に扱えるようにBaseEntityを生やした。


BaseEntity.ts

abstract class BaseEntity {

async validate(): Promise<void> {
const errors = await validate(this);

if (errors.length > 0) {
throw new BadRequestException(errors.toString());
}
}
}



User.ts

class User extends BaseEntity {

@IsNotEmpty()
id: string;
}


3. ローカル開発をDockerで、Deployはserverlessでやりたい

これも勝手にやれって感じなんだけど、DynamoDBはdynamodb-localなdocker imageが公開されてるのでそれを利用しました。

serverless.ymlは適宜いい感じに!


docker-compose.yml

version: '3'

services:
user-db:
image: amazon/dynamodb-local
ports:
- 8000:8000
user-app:
build: .
command: npm run start:dev
volumes:
- .:/app
- /app/node_modules
ports:
- 3000:3000
depends_on:
- user-db


Dockerfile

FROM node:8-alpine

RUN mkdir /app

WORKDIR /app

RUN npm install -g serverless

COPY package*.json ./

RUN set -x \
&& npm install


デプロイするときはこんだけ


deploy

$ docker-compose run --rm --no-deps user-app serverless deploy



4. DBは案件に応じて柔軟に変更できるようにしたい

以前はTypeORMマジヤベー!ブクロサイコー!ってノリでTypeORMばっか使ってたんですが、今回DynamoDB使いたかったのでDynamoDB Data Mapperってのを使いました。

そこそこ使いやすくてよい。

そうじゃない場合 === TypeORMを使って済む場合はnestの公式docを参考にやればおkっぽい。

これはまだ試してないけど問題ないっしょ!!


5. (後から出てきたけど)webpackもうやだ。消したい

nestのValidationPipeなるものを使って 1. を実現するんだけど、serverless-webpack/offlineな環境だとどうしても Cannot find module 'class-validator'. が発生して解決不能に。

nestのissueを見ても解決せず、でもなんとなくwebpackが悪いっぽいってところまで到達。

いろいろwebpackを騙そうとしたけど、最終的にはwebpackやめました。そしてwebpackを徐々に嫌いになっていっている自分に気づきました。

ローカル開発のときはnodemon、デプロイのときはserverless-plugin-typescriptを使うことで解決できそうってところまで調査して、webpack関連を全部消しました。


まとめ

TypeScriptっていうかJavaScriptっていうかその界隈は、フロントエンドな人たちもサーバーサイドな人たちも使っているせいかライブラリがかなり充実してるため、選択肢が数々ありながら最適なものを組み合わせて使うキメラフレームワークみたいな使い方がやりやすいなあっておもいましたあ!

ちょうどフロントはAngular、アプリはionicだったのでnestは違和感なく使えたのもなかなか面白いところですね。