用nest.js,typeorm和docker填充桌子
#教程 #node #postgres #nest

要求

创建一个崭新的NEST.JS应用程序

mkdir seed-demo
cd seed-demo
touch .env 
DATABASE_NAME=database
DATABASE_USER=user
DATABASE_PASSWORD=password
touch docker-compose.yaml
version: "3"

services:
  node:
    image: node:19.0.0-alpine
    user: node
    working_dir: /home/node
    tty: true
    stdin_open: true
    env_file: .env
    ports:
      - 3000:3000
    volumes:
      - .:/home/node

  postgresql:
    image: postgres:15.2-alpine3.17
    environment:
      POSTGRES_DB: $DATABASE_NAME
      POSTGRES_USER: $DATABASE_USER
      POSTGRES_PASSWORD: $DATABASE_PASSWORD
docker compose up --detach
docker compose exec node npx @nestjs/cli new .
docker compose exec node npm run start:dev

安装Typeorm

docker compose exec node npm install --save --save-exact typeorm @nestjs/typeorm pg

设置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({
      type: "postgres",
      host: "postgresql",
      port: 5432,
      username: "user",
      password: "password",
      database: "database",
      autoLoadEntities: true,
      synchronize: process.env.ENVIRONMENT === "seed"
    })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

创建一个模块

docker compose exec node npx nest generate module posts

创建一个实体

touch src/posts/posts.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity()
export class Post {
  @PrimaryGeneratedColumn("uuid")
  public id: string;

  @Column({
    type: "varchar",
    length: 50,
    nullable: false,
    unique: true
  })
  public title: string;

  @Column({
    type: "text",
    nullable: false
  })
  public body: string;
}

创建服务

docker compose exec node npx nest generate service posts
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { Post } from "./posts.entity";

@Injectable()
export class PostsService {
  public constructor(@InjectRepository(Post) private readonly postRepository: Repository<Post>) { }

  public async seed() {
    const post1 = this.postRepository.create({
      title: "How to use TypeORM with NestJS",
      body: "This is a test post."
    });

    const post2 = this.postRepository.create({
      title: "How to use React with NestJS",
      body: "This is another test post."
    });

    await this.postRepository.delete({});
    await this.postRepository.save([post1, post2]);
  }
}

更新模块

import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { Post } from "./posts.entity";
import { PostsService } from "./posts.service";

@Module({
  imports: [
    TypeOrmModule.forFeature([
      Post
    ])
  ],
  providers: [
    PostsService
  ],
  exports: [
    PostsService
  ]
})
export class PostsModule { }

创建播种机服务

docker compose exec node npx nest generate service seed
import { Injectable } from "@nestjs/common";
import { PostsService } from "../posts/posts.service";

@Injectable()
export class SeedService {
  public constructor(private readonly postsService: PostsService) { }

  public async seed() {
    await this.postsService.seed();
  }
}

创建播种机脚本

touch src/seed.ts
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { SeedService } from "./seed/seed.service";

const bootstrap = async () => {
  const app = await NestFactory.createApplicationContext(AppModule);
  const seedService = app.get(SeedService);

  await seedService.seed();
  await app.close();

  console.log("Seed complete.");
}

bootstrap();

更新软件包

{
  "scripts": {
    "seed": "ENVIRONMENT=seed ts-node src/seed.ts"
  }
}

运行种子

docker compose exec node npm run seed