はじめに
Nest CLIでスケルトンを作成した状態でのスタートです。
Nest v10.4.2
TypeORM 0.3系
ライブラリのインストール
npm install @nestjs/typeorm typeorm pg
npm install ts-node
npm install class-validator class-transformer
1.TypeORMにNeonの接続情報をロードする
1. Neon
のダッシュボードからPostgresの接続アドレスを取得する
2. .envに記載する
3. app.module.tsからロードする設定を作成する
4. 作成した設定をapp.module.tsからロードする
src/config/typeormConfig.ts
import { TypeOrmModuleOptions } from "@nestjs/typeorm";
import { config } from 'dotenv';
config({ path: ".env" })
export const typeOrmConfig: TypeOrmModuleOptions = {
type: "postgres",
url: process.env.DB_URL,
synchronize: true, // 開発環境下のみtrueにしておく
}
src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { typeOrmConfig } from 'src/config/typeormConfig';
@Module({
imports: [
TypeOrmModule.forRoot(typeOrmConfig)
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
2.Entityを作ってmigrationする
1. Entity
を作成する
src/entity/product.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Product {
@PrimaryGeneratedColumn()
id: number;
@Column({ nullable: true })
imageSrcPath: string | null;
@Column({ nullable: true })
deployUrl: string | null;
@Column()
productName: string;
@Column()
overview: string;
@Column()
mainTechnology: string;
@Column({ nullable: true })
subTechnology: string | null;
@Column('text', { array: true })
productLinks: string[] | null;
}
2. migration
するための接続ファイルを書く
src/ormconfig.ts
import { config } from 'dotenv';
import { DataSource } from 'typeorm';
config({ path: '.env' });
export const dataSource = new DataSource({
type: 'postgres',
url: process.env.DB_URL,
entities: ['src/entity/*.entity.ts'],
migrations: ['src/migration/*.ts'],
});
3.entity
-> migrationファイル
の作成を行う
・package.jsonに追記
package.json
"scripts": {
"typeorm": "typeorm-ts-node-commonjs -d ./src/config/ormconfig.ts"
}
・migrationファイルを生成する
npm run typeorm migration:generate .\src\migration\addNullable
4.migarationファイル
-> DB
に反映する
npm run typeorm migration:run
3. DTO作ってリクエストのバリデーションを行う
1. main.tsにvalidationPipe
を適用する
src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
2. DTO
を作ってvalidationを作成する
src/dto/CreateProductDto.ts
import {
IsArray,
IsNotEmpty,
IsOptional,
IsString,
IsUrl,
} from 'class-validator';
export class CreateProductDto {
@IsOptional()
@IsString()
imageSrcPath: string | null;
@IsOptional()
@IsUrl()
deployUrl: string | null;
@IsString()
@IsNotEmpty()
productName: string;
@IsString()
@IsNotEmpty()
overview: string;
@IsString()
@IsNotEmpty()
mainTechnology: string;
@IsOptional()
@IsString()
subTechnology: string | null;
@IsOptional()
@IsArray()
@IsUrl({}, { each: true })
productLinks: string[] | null;
}
4.エンドポイントを作成してCRUDを通す
1. module
・controller
・service
を作成する
nest generate module products
nest generate controller products
nest generate service products
2. module
にTypeORMを読み込む
src/products/products.module.ts
import { Module } from '@nestjs/common';
import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Product } from 'src/entity/product.entity';
@Module({
imports: [TypeOrmModule.forFeature([Product])],
controllers: [ProductsController],
providers: [ProductsService],
})
export class ProductsModule {}
3. controller
にルーティングメソッドを追加する
src/products/products.controller.ts
import { Body, Controller, Get, Post, Put } from '@nestjs/common';
import { ProductsService } from './products.service';
import { CreateProductDto } from 'src/dto/CreateProductDto';
import { UpdateProductDto } from 'src/dto/UpdateProductDto';
@Controller('products')
export class ProductsController {
constructor(private readonly ProductsService: ProductsService) {}
@Get()
async readAll() {
return await this.ProductsService.read();
}
@Post()
async create(@Body() CreateProductDto: CreateProductDto) {
return await this.ProductsService.create(CreateProductDto);
}
@Put()
async update(@Body() updateProductDto: UpdateProductDto) {
return await this.ProductsService.update(updateProductDto);
}
}
4. service
にcontroller
から呼び出されるロジックをメソッドとして追加する
src/products/products.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateProductDto } from 'src/dto/CreateProductDto';
import { UpdateProductDto } from 'src/dto/UpdateProductDto';
import { Product } from 'src/entity/product.entity';
import { Repository } from 'typeorm';
@Injectable()
export class ProductsService {
constructor(
@InjectRepository(Product)
private productsRepository: Repository<Product>,
) {}
async read() {
const productsData = await this.productsRepository.find({
order: {
id: "ASC"
}
});
const formattedProductData = productsData.map((productData) => ({
...productData,
overview: productData.overview.split(","),
mainTechnology: productData.mainTechnology.split(","),
subTechnology: productData.subTechnology.split(",")
}));
return formattedProductData;
}
async create(CreateProductDto: CreateProductDto) {
return await this.productsRepository.save(CreateProductDto);
}
async update(updateProductDto: UpdateProductDto) {
return await this.productsRepository.update(
updateProductDto.id,
updateProductDto,
);
}
}
さいごに
学習させていただいた技術記事のリンクです。