NestJS+PrismaでRESTAPIをつくる
準備
空のGitリポジトリをクローンしたあと、projectを新規作成
nest new .
無視リスト一部修正
node_modules
REST APIのリソース自動生成
nest g resource [Endpoint Name]
# REST APIを選択
# yを入力
DBコンテナおよびWEBクライアント用意する
docker-compose.ymlを用意して、docker compose upを実行する
version: '3'
services:
db:
image: mysql:5.7 # プロダクトで使うならバージョンはlatestじゃないほうが良いです
container_name: mysql_db
environment:
MYSQL_ROOT_PASSWORD: root # MySQLパスワード設定
MYSQL_DATABASE: test # MySQLデータベース名設定
TZ: 'Asia/Tokyo'
ports:
- '3306:3306'
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: mysql_web
ports:
- 8080:80
environment:
- PMA_ARBITRARY=1
- PMA_HOST=db
- PMA_USER=root
- PMA_PASSWORD=root
DB接続情報を.envに記載
DATABASE_URL="mysql://root:root@localhost/test"
DBモデリング
いくつかモデルを追加してみる。
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
name String
phone String
Call Call[]
Response Response[]
}
model Call {
id Int @id @default(autoincrement())
email String @unique
name String?
responses Response[]
patient User? @relation(fields: [patientId], references: [id])
patientId Int?
}
model Response {
id Int @id @default(autoincrement())
request String
pushed_no Int
call Call? @relation(fields: [callId], references: [id])
callId Int?
patient User? @relation(fields: [patientId], references: [id])
patientId Int?
}
マイグレーション実行
npx prisma migrate dev --name init
Prisma Clientのセットアップ
ファイルを作成
touch src/prisma.service.ts
ファイルにコード書く
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
}
REST APIを用意する
nest g resource responses calls users
VSCode拡張入れる
Prismaをインストールする
ER自動作図
インストール
npm i -D prisma-erd-generator @mermaid-js/mermaid-cli
# or
yarn add -D prisma-erd-generator @mermaid-js/mermaid-cli
shema.prismaに追記。
...
generator erd {
provider = "prisma-erd-generator"
output = "../scheme.svg"
theme = "forest"
}
...
実行コマンド
npx prisma generate
huskyを入れてpre-commit処理実装
私の過去の記事を参考に以下
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint-staged
npx prisma generate
AppRunnerにデプロイ
ルートディレクトリにapprunner.yamlを作成する
※--unsafe-permをオプション引数に渡さないとnpmインスールでコケる
version: 1.0
runtime: nodejs14
build:
commands:
build:
- npm ci --unsafe-perm
- npx prisma generate
- npx prisma migrate deploy
- npm run build
run:
command: npm prisma migrate deploy && npm run start
network:
port: 3000
AppRunnerのセットアップを行う。
- サービスの作成
- ソースコードリポジトリ を選択
- GitHubに接続 新規追加 を選択
- 別のアプリケーションをインストールする を選択
- GitHubにログインして認可
- 接続名 apprunner と入力
- リポジトリ及びブランチを選択
- デプロイ設定 自動 を選択 次へ
- 設定ファイルを使用 を選択 次へ
- アプリ名を入力して 次へ
- 作成とデプロイをクリック。
AppRunnerビルドはうまくいったが、Failする・・・
Dockerイメージで対応するか・・・
AppRunnerで上手く行く例。
NPMライブラリが原因で--unsafe-permオプションがいるっぽい。
version: 1.0
runtime: nodejs14
build:
commands:
build:
- npm i --unsafe-perm
- npx prisma generate
- npx prisma migrate deploy
- npm run build
run:
command: npm run start
network:
port: 3000
Seeding your database
公式を参考にSEED処理実装する。
package.jsonに追記する。
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
prismaディレクトリにseed.tsファイルを作成する。
適当なユーザデータをインサートするスクリプトを書く。
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const alice = await prisma.user.create({
data: {
hospitalId: 1,
name: 'Alice',
email: 'alice@prisma.io',
phone: '0000',
},
});
console.log({ alice });
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
seed.tsを実行する。
npx prisma db seed
実行後のメッセージ
Running seed command `ts-node prisma/seed.ts` ...
{
alice: {
id: 3,
hospitalId: 1,
name: 'Alice',
email: 'alice@prisma.io',
phone: '0000',
createdAt: 2022-05-29T23:30:04.762Z,
updatedAt: 2022-05-29T23:30:04.763Z
}
}
🌱 The seed command has been executed.
Prisma Studioを起動してデータを確認しておく。
npx prisma studio
Create multiple records
Userデータをまとめて作りたい。
しかし、createManyメソッドが存在しない。
調べる。
以下で対応する
categories.forEach(async (category) => {
console.log(`Creating category ${category.categoryName}...`);
await prisma.category.create({
data: {
categoryName: category.categoryName,
categoryDescription: category.categoryDescription
}
})
console.log(`Category ${category.categoryName} created!~`);
})
Json読み込みでエラー解消できず。
MySQLへ変更を試みる。
Prisma reset
SQLiteからMySQLへ変更する。
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
// provider = "sqlite"
// url = "file:./dev.db"
}
DATABASE_URL="mysql://root:root@localhost:3306/test"
npx prisma migrate reset
エラーするため、prismaディレクトリのmigrationsディレクトリを削除する
rm -rf migrations
再度マイグレーションを実施。
npx prisma migrate dev --name init
環境変数
Managing .env files and setting variablesを読む
Using dotenv via application code の方針で進める。
パッケージを入れる。
npm i dotenv
エントリーポイントで読み込み
import { config } from 'dotenv'
config({ path: '.env.' })
エラートラブルシュート関連
m ERR! code 1
npm ERR! path /root/repos/reborn/node_modules/puppeteer
npm ERR! command failed
npm ERR! command sh -c node install.js
npm ERR! ERROR: Failed to set up Chromium r991974! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.
npm ERR! Error: self signed certificate in certificate chain
npm ERR! at TLSSocket.onConnectSecure (_tls_wrap.js:1515:34)
npm ERR! at TLSSocket.emit (events.js:400:28)
npm ERR! at TLSSocket._finishInit (_tls_wrap.js:937:8)
npm ERR! at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:709:12) {
npm ERR! code: 'SELF_SIGNED_CERT_IN_CHAIN'
npm ERR! }
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2022-05-30T07_45_29_989Z-debug-0.log
調べた所、@mermaid-js/mermaid-cliの依存ライブラリで問題がり。
mermaidはER作図用途。アンインストールする
npm rm @mermaid-js/mermaid-cli
NestJSアプデ
4 high severity vulnerabilitiesとの警告が出ている。
NestJSをアップデート試みる
npm i -g @nestjs/cli npm-check-updates
nest update --force
DBとの連係
Herokuで用意したMySQLの場合、権限問題でMigrationに失敗する
Error: P3014
Prisma Migrate could not create the shadow database. Please make sure the database user has permission to create databases. Read more about the shadow database (and workarounds) at https://pris.ly/d/migrate-shadow
Original error: Error code: P1010
仕方がないのでAWS RDSを作る。
- RDS→サブネットグループ選択して、DBサブネットグループを作成
- AZを選択して、Publicアクセス可能なVPCを選択
- データベース→データベースの作成をクリック
- 標準作成、エンジンのタイプをAuroraを選択
- エディションはMySQL互換
- バージョンは2.10.2
- テンプレは開発/テスト
- DBインスタンスクラスはバースト可能クラスを選択←選択しないとデフォルトでlargeが選択される
- Auroraレプリカは作成しない をチェック
- VPCを選択後、先程作成したサブネットグループを選択
- パブリックアクセスあり を選択
- VPCセキュリティグループは新規作成
- defaultは選択解除
- あとは初期値でデータベースの作成 をクリック