NestJS TypeORMの設定 ※postgresql
typeormのバージョンがアップしたので更新
1.構成
1-1.フォルダ構成
.
├── app/ # NestJSのフォルダ
├── .env
├── docker-compose.yml
└── Dockerfile
1-2. ファイル編集
Dockerfile
FROM node:18.12.1
RUN npm i -g @nestjs/cli
WORKDIR /app
docker-compose.yml
version: "3.7"
services:
app:
build: .
env_file:
- .env
environment:
TZ: "Asia/Tokyo"
ports:
- 3000:3000
tty: true
volumes:
- ./app:/app
db:
image: postgres:15.1
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: test
TZ: "Asia/Tokyo"
ports:
- 5432:5432
volumes:
- "./dbdata:/var/lib/postgresql/data"
.env
NODE_ENV=local
# db関連の設定
DATABASE_HOST=db
DATABASE_USER=postgres
DATABASE_PASSWORD=postgres
DATABASE_PORT=5432
DATABASE_DB=test
2. NestJSのプロジェクト生成
docker-compose up -d
docker-compose exec app bash
# container内作業
nest new .
yarn start:dev # localhost:3000で動作確認
3. Configurationのパッケージインストール&確認
3-1. Configurationのパッケージインストール
# container内で作業
yarn add @nestjs/config
3-2. ファイル編集
app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
@Module({
- imports: [],
+ imports: [ConfigModule.forRoot({ isGlobal: true})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
app.service.ts
import { Injectable } from '@nestjs/common';
+ import { ConfigService } from '@nestjs/config';
@Injectable()
export class AppService {
+ constructor(private configService: ConfigService) {}
getHello(): string {
+ console.log(this.configService.get('DATABASE_HOST'), this.configService.get('DATABASE_DB'));
return 'Hello World!';
}
}
3-3. 確認
yarn start:dev
※localhost:3000にアクセス
※環境変数が取得できていることを確認
4. Typeormの設定
4-1. packageインストール
yarn add @nestjs/typeorm typeorm pg
4-2. Typeormの設定反映
app/src/db/database.config.ts
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions {
const configService = new ConfigService();
return {
type: 'postgres',
host: configService.get('DATABASE_HOST'),
port: configService.get('DATABASE_PORT'),
username: configService.get('DATABASE_USER'),
password: configService.get('DATABASE_PASSWORD'),
database: configService.get('DATABASE_DB'),
entities: [],
synchronize: false, // 本番環境では必ずfalse
};
}
}
app/src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
+import { ConfigModule } from '@nestjs/config';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { TypeOrmConfigService } from './db/database.config';
@Module({
- imports: [ConfigModule.forRoot({ isGlobal: true})],
+ imports: [
+ ConfigModule.forRoot({ isGlobal: true}),
+ TypeOrmModule.forRootAsync({
+ imports: [ConfigModule],
+ useClass: TypeOrmConfigService
+ })
+ ],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
app/src/db/data-source.ts
import { DataSource } from "typeorm";
import { User } from "./entities/user.entity";
const DATABASE_HOST = process.env.DATABASE_HOST;
const DATABASE_USER = process.env.DATABASE_USER;
const DATABASE_PASSWORD = process.env.DATABASE_PASSWORD;
const DATABASE_PORT = process.env.DATABASE_PORT;
const DATABASE_DB = process.env.DATABASE_DB;
if (!DATABASE_HOST || !DATABASE_USER || !DATABASE_PASSWORD || !DATABASE_PORT || !DATABASE_DB) {
throw new Error('Enviroment Database Error');
}
const source = new DataSource({
type: 'postgres',
host: DATABASE_HOST,
port: Number(DATABASE_PORT),
username: DATABASE_USER,
password: DATABASE_PASSWORD,
database: DATABASE_DB,
entities: [],
migrations: ['src/db/migrations/**/*.ts'], // フォルダを作成すること
synchronize: false,
})
export default source;
5. Entity作成と設定追加
5-1. Entity作成
app/src/db/entities/user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column({ default: true })
isActive: boolean;
}
5-2. 設定に反映
app/src/db/data-source.ts
+import { User } from "./entities/user.entity";
const source = new DataSource({
type: 'postgres',
host: DATABASE_HOST,
port: Number(DATABASE_PORT),
username: DATABASE_USER,
password: DATABASE_PASSWORD,
database: DATABASE_DB,
- entities: [],
+ entities: ['src/db/**/*.entity.ts'],
migrations: ['src/db/migrations/**/*.ts'], // フォルダを作成すること
synchronize: false,
})
app/src/db/database.config.ts
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";
+import { User } from "./entities/user.entity";
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions {
const configService = new ConfigService();
return {
type: 'postgres',
host: configService.get('DATABASE_HOST'),
port: configService.get('DATABASE_PORT'),
username: configService.get('DATABASE_USER'),
password: configService.get('DATABASE_PASSWORD'),
database: configService.get('DATABASE_DB'),
- entities: [],
+ entities: [User],
synchronize: false, // 本番環境では必ずfalse
};
}
}
package.json
"scripts": {
...
+ "typeorm": "npx typeorm-ts-node-commonjs",
+ "migration:generate": "yarn typeorm -d src/db/data-source.ts migration:generate",
+ "migration:run": "yarn typeorm -d ./src/db/data-source.ts migration:run",
+ "migration:revert": "yarn typeorm -d src/db/data-source.ts migration:revert"
},
6. migration実行確認
6-1. migration:generateの実行
yarn migration:generate src/db/migrations/init
6-2. migration:runの実行
yarn migration:run
6-3. migration:revertの実行
yarn migration:revert