#記事の内容
NestJS TypeORM postgresで環境構築します。
postgresはDocker上で起動します。
Dockerについては、完全初心者です。
ただ、dbをローカルに作るのが嫌でしたので導入してみました。
今回調べながらの環境構築なので
間違っている所やこうした方がいい所、等があった場合
教えていただけると嬉しいです。
環境構築を終えたら、
URLのアクセスからデータ操作までの流れを簡単に実装します。
ソースコードはこちら↓
https://github.com/tokio-k/docker-nest-postgres-sample
※Docker、yarnのインストールは前提で進めます。
※調べればすぐできると思うのでよろしくお願いします。
#プロジェクトの作成
###フォルダ作成
ターミナルで今回作成していくフォルダを作成し、そのフォルダに移動します。
(今回はdocker-nest-postgres-sampleというフォルダ)
# フォルダ作成
mkdir docker-nest-postgres-sample
# 移動
cd docker-nest-postgres-sample
(terminal. の「.」は気にしないでください。普通にターミナルで実行しています。)
###NestJSのプロジェクトを作成
Nest用CLIを用いて作成していきます。
Nest用CLIをインストールします。(既にインストールしてある場合は飛ばしてください。)
yarn global add @nestjs/cli
作成したフォルダの中に、Nestのプロジェクトを作成します。
簡単に雛形を作成できます。
# Nestのプロジェクトを作成
nest new .
ライブラリのインストール
TypeORM関連やバリデーションのライブラリをインストールしておきます。
DBにはpostgresを使用します。
#TypeORM関連
yarn add @nestjs/typeorm typeorm pg
#バリデーション
yarn add class-transformer class-validator
#Dockerでpostgresの環境構築
最初に作成したフォルダの中にdocker-compose.ymlを作成します。
srcフォルダやpackage.jsonと同じ階層です。
touch docker-compose.yml
作成したdocker-compose.ymlの中に以下の記述をします。
データベース接続情報などは好きに書いてください。(environment)
本当は、環境変数や.envファイルに記述し、参照する様にするみたいです。
いつか書き換えればいいので、今は直接書きで。
version: '3'
services:
postgres:
image: postgres:13.1
container_name: postgres
ports:
- 5432:5432
volumes:
- ./postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: password
POSTGRES_DB: test_db
POSTGRES_INITDB_ARGS: '--encoding=UTF-8'
TZ: 'Asia/Tokyo'
restart: always
docker-composeに記載した内容で、
docker上にpostgresの環境を立ち上げます。
docker-compose up -d
pgAdmin4などで確認してみると、データベースが作成されていることが確認できます。
#NestJSからTypeORMを使用
###ormconfig.jsonを作成
srcフォルダやpackage.jsonと同じ階層にormconfig.jsonを作成します。
touch ormconfig.json
ormconfig.jsonを編集していきます。
データベース情報は、先程設定したものと合わせてください。
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "root",
"password": "password",
"database": "test_db",
"entities": ["dist/entities/**/*.entity.js"],
"migrations": ["dist/migrations/**/*.js"],
"logging": true,
"synchronize": false
}
###app.module.tsを編集
app.module.tsを編集します。
これで、TypeORMの機能を呼び出すことができる様になります。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';//追加箇所
@Module({
imports: [TypeOrmModule.forRoot()],//編集箇所
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
テーブル作成
テーブルを作成していきます。
###Entityの作成
Entityを作成します。
Entityでは、テーブルの構造を定義し、これを元にテーブルが作成されます。
srcフォルダの中にentitiesフォルダを作成します。
entitiesフォルダの中にitem.entity.tsを作成します。
item.entity.tsを編集していきます。
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity()
export class Item {
@PrimaryGeneratedColumn()
readonly id: number;
@Column()
todo: string;
@Column('boolean', { default: false })
idDone: boolean;
@CreateDateColumn()
readonly createdAt?: Date;
@UpdateDateColumn()
readonly updatedAt?: Date;
}
id,todo,isDone,createdAt,updatedAtがそれぞれテーブルのカラムになります。
###マイグレーションファイルの作成/実行
マイグレーションファイルを作成していきます。
# ビルド
yarn build
#マイグレーションファイルの作成
yarn typeorm migration:generate -d src/migrations -n create-item
マイグレーションファイルを実行していきます。
# ビルド
yarn build
# マイグレーションファイルの実行 (DB作成)
yarn typeorm migration:run
pgAdmin4などで確認してみると、テーブルが作成されている事が確認できます。
#module,controller,serviceの作成
コマンドでそれぞれ作成していきます。
# module作成
yarn nest g module item
# controller作成
yarn nest g controller item
# service作成
yarn nest g service item
コマンドで作成すると、読み込まれるように、app.module.tsやitem.module.tsに自動で追記されます。
app.module.tsを編集します。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';//追加箇所
import { Item } from 'src/entities/item.entity';//追加箇所
import { ItemController } from './item.controller';
import { ItemService } from './item.service';
@Module({
controllers: [ItemController],
imports: [TypeOrmModule.forFeature([Item])],//編集箇所
providers: [ItemService],
})
export class ItemModule {}
#DTOの作成
###DTOを作成します。
データのやり取りをするときにデータ構造を表す箱のようなものです。
ここでバリデーション(入力チェック)などができます。
import { IsNotEmpty, IsString } from 'class-validator';
export class CreateItemDTO {
@IsNotEmpty()
@IsString()
todo: string;
}
todoを必須+文字列に制限しました。
データ追加をするときに、このクラスを使ってデータのやり取りをします。
###バリデーションを有効にする
src/main.tsを編集して、バリデーションを有効にします。
import { ValidationPipe } from '@nestjs/common';//追加箇所
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());//追加箇所
await app.listen(3000);
}
bootstrap();
#APIの実装
Service,Controllerを実装していきます。
###Serviceの実装
Serviceを実装していきます。
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Item } from 'src/entities/item.entity';
import { InsertResult, Repository } from 'typeorm';
import { CreateItemDTO } from './item.dto';
@Injectable()
export class ItemService {
constructor(
@InjectRepository(Item)
private readonly itemRepository: Repository<Item>,
) {}
// 全データ検索
async findAll(): Promise<Item[]> {
return await this.itemRepository.find();
}
//データ追加
async create(item: CreateItemDTO): Promise<InsertResult> {
return await this.itemRepository.insert(item);
}
}
constructorの部分でRepositoryをInjectionしています。
Repositoryに指示を出すことでテーブルのデータを変更できます。
###Controllerの実装
import { Body, Controller, Get, Post } from '@nestjs/common';
import { Item } from 'src/entities/item.entity';
import { InsertResult } from 'typeorm';
import { CreateItemDTO } from './item.dto';
import { ItemService } from './item.service';
@Controller('item')
export class ItemController {
constructor(private readonly service: ItemService) {}
// 全データ検索
@Get()
async getItemList(): Promise<Item[]> {
return await this.service.findAll();
}
//データ追加
@Post()
async addItem(@Body() item: CreateItemDTO): Promise<InsertResult> {
return await this.service.create(item);
}
}
/itemにGetでアクセスがあった時に「getItemList()」
/itemにPostでアクセスがあった時に「addItem(item)」が呼び出されます。
addItem(item)の「item」が先程作成したCreateItemDTOの型には入ります。
constructorでは、先程作成したServiceがInjectionされています。
とりあえず、実装は完成
#動作確認
###実行
以下のコマンドで実行できます。
yarn start dev
###新規データの追加 (addItemを呼び出す)
コマンドで以下を実行してデータを追加できます。
curl http://localhost:3000/item -X POST -d "todo=test"
###ブラウザからアクセス (getItemListを呼び出す)
ブラウザから以下で検索すると、追加したデータが表示されます。
http://localhost:3000/item
これで、全検索と追加のAPIが作成することができました。
##参考記事
How To Set Up TypeORM With Postgres in NestJS
NestJSの始め方
NestJSで簡単なtudoリストを実装するチュートリアル
Mac に Docker Desktop をインストール