いろいろな記事を探してみたが、わかりやすくまとまっているnestjs + typeormでのダミーデータ投入方法の記事がなかった(見つけられなかった)ので、備忘録として残しておきます。
結論
seeder/role.seeder.ts
import { DataSource } from 'typeorm';
import { Seeder } from 'typeorm-extension';
import { Role } from '../user/entities/role.entity';
export class RoleSeeder implements Seeder {
public async run(dataSource: DataSource): Promise<void> {
const roleRepository = dataSource.getRepository(Role);
const rolesList = [
{ roleName: 'admin' },
{ roleName: 'user' },
{ roleName: 'guest' },
];
for (const roleData of rolesList) {
const existingRole = await roleRepository.findOne({
where: { roleName: roleData.roleName },
});
if (!existingRole) {
const role = roleRepository.create(roleData);
await roleRepository.save(role);
}
}
}
}
seeder/seed.helper.ts
// src/seeder/seed.helper.ts
import { DataSource } from 'typeorm';
import { NestFactory } from '@nestjs/core';
import { AppModule } from '../app.module';
import { RoleSeeder } from './role.seeder';
async function runSeeder() {
const app = await NestFactory.create(AppModule);
const dataSource = app.get(DataSource);
// ここにどんどんシーダーを追加していく
const roleSeeder = new RoleSeeder();
await roleSeeder.run(dataSource); // シーダーの呼び出し
// ここまで
await app.close();
}
runSeeder();
package.json
{
"scripts": {
"data:sync": "ts-node -r tsconfig-paths/register ./src/seeder/seed.helper.ts",
}
}
ポイント
typeorm-extensionを使ったダミーデータの作成は、以下のポイントを抑えると楽かなと思います。
- DataSourceでリポジトリの取得
- NestFactoryを使うと凄い楽
- シーダー追加するのも楽
一つずつ詳細に解説します
DataSourceでリポジトリの取得
RoleSeederで、以下のようなコードが書いてあるのですが…
public async run(dataSource: DataSource): Promise<void> {
const roleRepository = dataSource.getRepository(Role);
getRepositoryメソッドでentityクラスを指定するだけで簡単に取ってきてくれます。便利。
NestFactoryを使うと凄い楽
基本的に、シーダーを使うときって、データベースの設定とかを引っ張ってくる必要があるのですが、今回の場合、AppModuleにTypeOrm.forRootで以下のように定義しているので、AppModuleをNestFactory.createメソッドに渡すだけでセットアップが完了してしまいます。
app.module
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
// その他のインポート部分は省略
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: `.env.${process.env.NODE_ENV || 'development'}.local`,
isGlobal: true,
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: configService.get<'mysql' | 'postgres'>('DB_TYPE'),
host: configService.get<string>('DB_HOST'),
port: configService.get<number>('DB_PORT'),
username: configService.get<string>('DB_USERNAME'),
password: configService.get<string>('DB_PASSWORD'),
database: configService.get<string>('DB_DATABASE'),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
inject: [ConfigService],
}),
// その他のコードは省略
],
})
このようにapp.module.tsを設定している場合、seed.helper.tsで以下のように書くだけ。
const app = await NestFactory.create(AppModule);
なんと楽なんでしょう。
その他、Factoryを用いてランダムなダミーデータの生成もできるのですが、こちらは余力があったら追記したいと思います。
シーダー追加するのも楽
新たにシーダーを作った場合、以下の部分にどんどん足していけばいいだけです。
// ここにどんどんシーダーを追加していく
const roleSeeder = new RoleSeeder();
await roleSeeder.run(dataSource); // シーダーの呼び出し
// 例えば新たにuserのシーダー作った場合、以下のように追加する
const userSeeder = new UserSeeder();
await userSeeder.run(dataSource);
じゃんじゃんシーダーを追加していきましょう。
多分もっといい方法あるはず…
こんな記事を書いてみたのですが、これが正解とは思ってないですし、もっといい方法があるはずなので、いい方法知っていたら教えてください。