nestjs-typeorm-integration

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

NestJS + TypeORM Integration Skill

NestJS + TypeORM 集成技能

Purpose

用途

You are a specialized assistant for integrating TypeORM with NestJS in a clean, scalable, and production-friendly way.
Use this skill to:
  • Set up TypeORM in a NestJS project (data source, modules, config)
  • Define or refactor entities and their relations
  • Configure migrations and environment-specific DB settings
  • Wire repositories into services using Nest DI
  • Implement transactions and query patterns safely
  • Optimize DB usage (indexes, query patterns, relations loading) at a structural level
Do not use this skill for:
  • General NestJS module/service/controller scaffolding → use
    nestjs-project-scaffold
    /
    nestjs-modules-services-controllers
  • Authentication logic → use
    nestjs-authentication
  • Supabase-specific flows → use Supabase skills (unless Supabase Postgres is accessed via TypeORM as a plain DB)
If
CLAUDE.md
exists, follow its rules on database choice, naming conventions, and directory layout.

您是一位专注于以简洁、可扩展且适合生产环境的方式将TypeORM与NestJS集成的助手。
使用此技能可完成以下操作:
  • 在NestJS项目中设置TypeORM(数据源、模块、配置)
  • 定义或重构实体及其关联关系
  • Configure migrations以及特定环境的数据库设置
  • 使用Nest依赖注入(DI)将仓库接入服务
  • 安全地实现事务查询模式
  • 从结构层面优化数据库使用(索引、查询模式、关联关系加载)
请勿将此技能用于:
  • 通用NestJS模块/服务/控制器搭建 → 使用
    nestjs-project-scaffold
    /
    nestjs-modules-services-controllers
  • 认证逻辑 → 使用
    nestjs-authentication
  • Supabase特定流程 → 使用Supabase相关技能(除非通过TypeORM将Supabase Postgres作为普通数据库访问)
若项目中存在
CLAUDE.md
文件,请遵循其中关于数据库选择、命名规范和目录结构的规则。

When To Apply This Skill

适用场景

Trigger this skill when the user asks for things like:
  • “Set up TypeORM in this NestJS API.”
  • “Create entities and migrations for these tables in NestJS + TypeORM.”
  • “Wire repositories into my Nest services.”
  • “Fix or refactor our NestJS TypeORM config.”
  • “Add relations between these entities and update the service logic.”
  • “Handle transactions for this multi-step operation.”
Avoid using this skill when:
  • Only high-level REST API contracts are changing without DB impact.
  • Only pure in-memory logic is being implemented.

当用户提出以下需求时,触发此技能:
  • “在这个NestJS API中设置TypeORM。”
  • “为NestJS + TypeORM中的这些表创建实体和迁移。”
  • “将仓库接入我的Nest服务中。”
  • “修复或重构我们的NestJS TypeORM配置。”
  • “在这些实体之间添加关联关系并更新服务逻辑。”
  • “为这个多步骤操作处理事务。”
避免在以下场景使用此技能:
  • 仅修改高层REST API契约,且不涉及数据库影响。
  • 仅实现纯内存逻辑。

Assumptions & Defaults

假设与默认设置

Unless the project states otherwise, assume:
  • Database: Postgres (can be adapted to MySQL, SQLite, etc.)
  • TypeORM version: current stable for NestJS
  • Connection is configured via Nest’s
    TypeOrmModule
  • Config is environment-driven via
    @nestjs/config
    and
    .env
    files
  • Entities live in
    src/modules/<feature>/entities
    or
    src/entities
    depending on project style
  • Migrations live in
    src/migrations
    or
    migrations
    directory

除非项目另有说明,默认采用以下设置:
  • 数据库:Postgres(可适配MySQL、SQLite等)
  • TypeORM版本:适配NestJS的当前稳定版
  • 通过Nest的
    TypeOrmModule
    配置连接
  • 通过
    @nestjs/config
    .env
    文件实现环境驱动的配置
  • 实体存放于
    src/modules/<feature>/entities
    src/entities
    目录,具体取决于项目风格
  • 迁移文件存放于
    src/migrations
    migrations
    目录

High-Level Architecture

高层架构

Recommended structure (adapt as needed):
text
project-root/
  src/
    config/
      database.config.ts
    modules/
      user/
        user.module.ts
        user.service.ts
        user.controller.ts
        entities/
          user.entity.ts
      post/
        post.module.ts
        post.service.ts
        post.controller.ts
        entities/
          post.entity.ts
    infrastructure/
      database/
        ormconfig.ts or data-source.ts (optional central place)
  migrations/
    1710000000000-CreateUserTable.ts
    1710000001000-CreatePostTable.ts
This skill should align with the existing structure rather than forcing a totally new one, unless the project is greenfield.

推荐的目录结构(可按需调整):
text
project-root/
  src/
    config/
      database.config.ts
    modules/
      user/
        user.module.ts
        user.service.ts
        user.controller.ts
        entities/
          user.entity.ts
      post/
        post.module.ts
        post.service.ts
        post.controller.ts
        entities/
          post.entity.ts
    infrastructure/
      database/
        ormconfig.ts or data-source.ts (可选的集中配置位置)
  migrations/
    1710000000000-CreateUserTable.ts
    1710000001000-CreatePostTable.ts
此技能应适配现有项目结构,而非强制采用全新结构,除非项目是从零开始的新项目。

Step-by-Step Workflow

分步工作流程

When this skill is active, follow these steps:
激活此技能后,请遵循以下步骤:

1. Set Up TypeORM Module Configuration

1. 设置TypeORM模块配置

If TypeORM is not configured yet:
  • Install TypeORM + DB driver for the chosen database.
  • Configure
    TypeOrmModule
    in
    AppModule
    or a dedicated
    DatabaseModule
    .
Example using
@nestjs/config
:
ts
// src/config/database.config.ts
import { registerAs } from "@nestjs/config";

export default registerAs("database", () => ({
  type: "postgres",
  host: process.env.DB_HOST ?? "localhost",
  port: parseInt(process.env.DB_PORT ?? "5432", 10),
  username: process.env.DB_USERNAME ?? "postgres",
  password: process.env.DB_PASSWORD ?? "postgres",
  database: process.env.DB_NAME ?? "app_db",
}));
ts
// src/app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import databaseConfig from "./config/database.config";
import { TypeOrmModule } from "@nestjs/typeorm";

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [databaseConfig],
    }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => {
        const db = config.get("database");
        return {
          ...db,
          autoLoadEntities: true,
          synchronize: false, // prefer migrations in production
        };
      },
    }),
    // feature modules...
  ],
})
export class AppModule {}
Key rules:
  • synchronize: false
    in all non-dev environments (this skill encourages migrations).
  • autoLoadEntities: true
    is acceptable for many apps; for stricter control, explicitly list entities.
若TypeORM尚未配置:
  • 安装TypeORM及对应数据库的驱动。
  • AppModule
    或专用的
    DatabaseModule
    中配置
    TypeOrmModule
使用
@nestjs/config
的示例:
ts
// src/config/database.config.ts
import { registerAs } from "@nestjs/config";

export default registerAs("database", () => ({
  type: "postgres",
  host: process.env.DB_HOST ?? "localhost",
  port: parseInt(process.env.DB_PORT ?? "5432", 10),
  username: process.env.DB_USERNAME ?? "postgres",
  password: process.env.DB_PASSWORD ?? "postgres",
  database: process.env.DB_NAME ?? "app_db",
}));
ts
// src/app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import databaseConfig from "./config/database.config";
import { TypeOrmModule } from "@nestjs/typeorm";

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [databaseConfig],
    }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => {
        const db = config.get("database");
        return {
          ...db,
          autoLoadEntities: true,
          synchronize: false, // 生产环境优先使用迁移
        };
      },
    }),
    // 功能模块...
  ],
})
export class AppModule {}
核心规则:
  • 在所有非开发环境中设置
    synchronize: false
    (此技能推荐使用迁移)。
  • autoLoadEntities: true
    适用于多数应用;若需更严格的控制,可显式列出实体。

2. Environment Variables

2. 环境变量

Ensure
.env
(and
.env.example
) contain:
env
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=app_db
This skill should help keep secrets out of code and only in env/config.
确保
.env
(以及
.env.example
)包含以下内容:
env
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=app_db
此技能应帮助将敏感信息从代码中剥离,仅存于环境变量或配置文件中。

3. Entities Design

3. 实体设计

For each feature, create entity classes:
ts
// src/modules/user/entities/user.entity.ts
import {
  Column,
  CreateDateColumn,
  Entity,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from "typeorm";

@Entity({ name: "users" })
export class User {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column({ unique: true })
  email!: string;

  @Column()
  passwordHash!: string;

  @Column({ default: true })
  isActive!: boolean;

  @CreateDateColumn()
  createdAt!: Date;

  @UpdateDateColumn()
  updatedAt!: Date;
}
Relations example:
ts
// src/modules/post/entities/post.entity.ts
import {
  Column,
  CreateDateColumn,
  Entity,
  ManyToOne,
  PrimaryGeneratedColumn,
} from "typeorm";
import { User } from "../../user/entities/user.entity";

@Entity({ name: "posts" })
export class Post {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column()
  title!: string;

  @Column({ type: "text" })
  content!: string;

  @ManyToOne(() => User, (user) => user.posts, { onDelete: "CASCADE" })
  author!: User;

  @CreateDateColumn()
  createdAt!: Date;
}
This skill should:
  • Encourage using
    uuid
    or bigint for IDs consistently (per project preference).
  • Use clear relation options (
    onDelete
    ,
    eager
    ,
    lazy
    ) thoughtfully.
  • Avoid putting heavy business logic directly into entities.
为每个功能创建实体类:
ts
// src/modules/user/entities/user.entity.ts
import {
  Column,
  CreateDateColumn,
  Entity,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from "typeorm";

@Entity({ name: "users" })
export class User {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column({ unique: true })
  email!: string;

  @Column()
  passwordHash!: string;

  @Column({ default: true })
  isActive!: boolean;

  @CreateDateColumn()
  createdAt!: Date;

  @UpdateDateColumn()
  updatedAt!: Date;
}
关联关系示例:
ts
// src/modules/post/entities/post.entity.ts
import {
  Column,
  CreateDateColumn,
  Entity,
  ManyToOne,
  PrimaryGeneratedColumn,
} from "typeorm";
import { User } from "../../user/entities/user.entity";

@Entity({ name: "posts" })
export class Post {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column()
  title!: string;

  @Column({ type: "text" })
  content!: string;

  @ManyToOne(() => User, (user) => user.posts, { onDelete: "CASCADE" })
  author!: User;

  @CreateDateColumn()
  createdAt!: Date;
}
此技能应:
  • 推荐根据项目偏好,统一使用
    uuid
    或bigint作为ID。
  • 谨慎使用清晰的关联关系选项(
    onDelete
    eager
    lazy
    )。
  • 避免在实体中直接编写复杂业务逻辑。

4. Module & Repository Wiring

4. 模块与仓库接入

Use
TypeOrmModule.forFeature
to inject repositories into feature modules:
ts
// src/modules/user/user.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "./entities/user.entity";
import { UserService } from "./user.service";
import { UserController } from "./user.controller";

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],
})
export class UserModule {}
In
UserService
, inject the repository:
ts
// src/modules/user/user.service.ts
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "./entities/user.entity";
import { CreateUserDto } from "./dto/create-user.dto";

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly usersRepo: Repository<User>,
  ) {}

  create(dto: CreateUserDto) {
    const entity = this.usersRepo.create({
      email: dto.email,
      passwordHash: dto.passwordHash,
    });
    return this.usersRepo.save(entity);
  }

  findAll() {
    return this.usersRepo.find();
  }

  findOne(id: string) {
    return this.usersRepo.findOne({ where: { id } });
  }

  // etc...
}
This skill should enforce:
  • Repositories are injected via DI, not instantiated manually.
  • Services depend on repositories, not on the data source directly (except in advanced scenarios).
使用
TypeOrmModule.forFeature
将仓库注入功能模块:
ts
// src/modules/user/user.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "./entities/user.entity";
import { UserService } from "./user.service";
import { UserController } from "./user.controller";

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],
})
export class UserModule {}
UserService
中注入仓库:
ts
// src/modules/user/user.service.ts
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "./entities/user.entity";
import { CreateUserDto } from "./dto/create-user.dto";

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly usersRepo: Repository<User>,
  ) {}

  create(dto: CreateUserDto) {
    const entity = this.usersRepo.create({
      email: dto.email,
      passwordHash: dto.passwordHash,
    });
    return this.usersRepo.save(entity);
  }

  findAll() {
    return this.usersRepo.find();
  }

  findOne(id: string) {
    return this.usersRepo.findOne({ where: { id } });
  }

  // 其他方法...
}
此技能应遵循:
  • 通过依赖注入注入仓库,而非手动实例化。
  • 服务依赖于仓库,而非直接依赖数据源(高级场景除外)。

5. Migrations

5. 迁移

Encourage using migrations instead of
synchronize
for schema changes.
  • Create a
    data-source.ts
    file if needed for CLI migrations:
ts
// data-source.ts (or src/infrastructure/database/data-source.ts)
import "reflect-metadata";
import { DataSource } from "typeorm";
import databaseConfig from "./src/config/database.config";
import { config as loadEnv } from "dotenv";

loadEnv();

const db = databaseConfig();

export const AppDataSource = new DataSource({
  type: "postgres",
  host: db.database.host,
  port: db.database.port,
  username: db.database.username,
  password: db.database.password,
  database: db.database.database,
  entities: ["src/**/*.entity.{ts,js}"],
  migrations: ["migrations/*.{ts,js}"],
});
  • Add package.json scripts for migrations (exact form depends on project):
jsonc
{
  "scripts": {
    "typeorm:run": "typeorm-ts-node-commonjs migration:run -d data-source.ts",
    "typeorm:revert": "typeorm-ts-node-commonjs migration:revert -d data-source.ts",
    "typeorm:generate": "typeorm-ts-node-commonjs migration:generate -d data-source.ts migrations/AutoMigration"
  }
}
This skill should:
  • Prefer explicit migration generation (
    migration:generate
    ) over schema sync.
  • Keep migration files small, ordered, and committed to version control.
推荐使用迁移而非
synchronize
来处理 schema 变更。
  • 若需要通过CLI执行迁移,创建
    data-source.ts
    文件:
ts
// data-source.ts (或src/infrastructure/database/data-source.ts)
import "reflect-metadata";
import { DataSource } from "typeorm";
import databaseConfig from "./src/config/database.config";
import { config as loadEnv } from "dotenv";

loadEnv();

const db = databaseConfig();

export const AppDataSource = new DataSource({
  type: "postgres",
  host: db.database.host,
  port: db.database.port,
  username: db.database.username,
  password: db.database.password,
  database: db.database.database,
  entities: ["src/**/*.entity.{ts,js}"],
  migrations: ["migrations/*.{ts,js}"],
});
  • 在package.json中添加迁移相关脚本(具体形式取决于项目):
jsonc
{
  "scripts": {
    "typeorm:run": "typeorm-ts-node-commonjs migration:run -d data-source.ts",
    "typeorm:revert": "typeorm-ts-node-commonjs migration:revert -d data-source.ts",
    "typeorm:generate": "typeorm-ts-node-commonjs migration:generate -d data-source.ts migrations/AutoMigration"
  }
}
此技能应:
  • 优先使用显式迁移生成(
    migration:generate
    )而非 schema 同步。
  • 保持迁移文件体积小、有序,并提交至版本控制系统。

6. Transactions & Complex Operations

6. 事务与复杂操作

For operations that require multiple DB writes, this skill should:
  • Use
    QueryRunner
    or
    manager.transaction
    where needed.
Example:
ts
import { DataSource } from "typeorm";

@Injectable()
export class OrderService {
  constructor(private readonly dataSource: DataSource) {}

  async createOrderAndItems(dto: CreateOrderDto) {
    return this.dataSource.transaction(async (manager) => {
      const order = manager.create(Order, { /* ... */ });
      await manager.save(order);

      const items = dto.items.map((itemDto) =>
        manager.create(OrderItem, {
          order,
          // ...
        }),
      );
      await manager.save(items);

      return order;
    });
  }
}
Guidelines:
  • Use transactions only where needed; avoid wrapping everything by default.
  • Handle error propagation correctly; if the transaction throws, it rolls back.
对于需要多次数据库写入的操作,此技能应:
  • 按需使用
    QueryRunner
    manager.transaction
示例:
ts
import { DataSource } from "typeorm";

@Injectable()
export class OrderService {
  constructor(private readonly dataSource: DataSource) {}

  async createOrderAndItems(dto: CreateOrderDto) {
    return this.dataSource.transaction(async (manager) => {
      const order = manager.create(Order, { /* ... */ });
      await manager.save(order);

      const items = dto.items.map((itemDto) =>
        manager.create(OrderItem, {
          order,
          // ...
        }),
      );
      await manager.save(items);

      return order;
    });
  }
}
指导原则:
  • 仅在必要时使用事务;避免默认对所有操作添加事务。
  • 正确处理错误传播;若事务抛出异常,将自动回滚。

7. Performance & Query Patterns

7. 性能与查询模式

This skill should guide towards:
  • Using
    select
    and projections instead of always loading entire entities.
  • Avoiding N+1 queries with relation loading patterns when necessary.
  • Adding indexes in migrations for frequently queried columns.
  • Using pagination strategies (offset/limit or cursor-based) for large lists.
此技能应引导用户:
  • 使用
    select
    和投影,而非始终加载完整实体。
  • 必要时避免使用N+1查询的关联关系加载模式。
  • 在迁移中为频繁查询的列添加索引。
  • 对大型列表使用分页策略(偏移/限制或基于游标)。

8. Refactoring Existing TypeORM Usage

8. 重构现有TypeORM用法

When refactoring:
  • Identify anti-patterns:
    • Manual connection creation (bypassing Nest DI)
    • Direct use of global
      getRepository
      instead of injected repositories
    • synchronize: true
      in production
  • Replace with:
    • TypeOrmModule
      configuration
    • Injected
      Repository<T>
      or
      DataSource
    • Migrations for schema changes
This skill should try to minimize breaking changes while improving structure.

进行重构时:
  • 识别反模式:
    • 手动创建连接(绕过Nest依赖注入)
    • 直接使用全局
      getRepository
      而非注入的仓库
    • 生产环境中设置
      synchronize: true
  • 替换为:
    • TypeOrmModule
      配置
    • 注入的
      Repository<T>
      DataSource
    • 使用迁移处理 schema 变更
此技能应在改进结构的同时,尽量减少破坏性变更。

Interaction with Other Skills

与其他技能的交互

  • nestjs-project-scaffold
    :
    • Provides the base Nest structure; this skill plugs DB configuration into it.
  • nestjs-modules-services-controllers
    :
    • Uses modules/services; this skill adds entities + repositories behind those services.
  • nestjs-authentication
    :
    • Depends on user entities and user repository; this skill provides that layer.
  • TypeORM-specific skills (
    typeorm-schema-design
    ,
    typeorm-migrations-workflow
    ):
    • Can be used in addition for deeper DB design and migration strategies.

  • nestjs-project-scaffold
    :
    • 提供Nest项目的基础结构;此技能将数据库配置接入其中。
  • nestjs-modules-services-controllers
    :
    • 涉及模块/服务;此技能在这些服务背后添加实体和仓库层。
  • nestjs-authentication
    :
    • 依赖用户实体和用户仓库;此技能提供该层实现。
  • TypeORM特定技能(
    typeorm-schema-design
    ,
    typeorm-migrations-workflow
    ):
    • 可配合使用,以实现更深入的数据库设计和迁移策略。

Example Prompts That Should Use This Skill

应触发此技能的示例提示词

  • “Connect this NestJS app to Postgres via TypeORM and create User & Post entities.”
  • “Refactor this hand-rolled DB code into proper TypeORM modules and services.”
  • “Add migrations for these schema changes and wire them into our NestJS project.”
  • “Implement a transactional operation that creates an order and its items.”
  • “Fix this TypeORM config; it works locally but fails in production.”
For such prompts, rely on this skill to design and implement NestJS + TypeORM integration that is robust, maintainable, and ready for production, while delegating non-DB concerns to other skills.
  • “将这个NestJS应用通过TypeORM连接到Postgres,并创建User和Post实体。”
  • “将这套手动编写的数据库代码重构为标准的TypeORM模块和服务。”
  • “为这些schema变更添加迁移,并接入我们的NestJS项目。”
  • “实现一个事务操作,创建订单及其关联的订单项。”
  • “修复这个TypeORM配置;它在本地可用但在生产环境失败。”
对于此类提示词,请依托此技能设计并实现NestJS + TypeORM集成,确保其健壮、可维护且适合生产环境,同时将非数据库相关的工作委托给其他技能。