mcpField
N
nestjs-typeorm-integration

nestjs-typeorm-integration

github.com/vong3432开发097 次安装41 周前更新
代码仓库

关于 nestjs-typeorm-integration

用于在 NestJS 应用中集成 TypeORM 的技能,涵盖数据库配置、实体、迁移、仓库注入和事务。适合构建或重构数据库驱动的 NestJS 服务,并遵循现有项目结构。

主要功能

  1. 01NestJS 的 TypeORM 配置
  2. 02实体与关系设计
  3. 03基于迁移的架构变更
  4. 04通过 Nest DI 注入仓库
  5. 05事务与查询指导

适用场景

  1. 01为 NestJS API 连接数据库
  2. 02添加实体、关系和迁移
  3. 03重构手动创建仓库或连接的代码
  4. 04实现事务性数据库操作

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vong3432/vibemark --skill nestjs-typeorm-integration

安装后在 Claude Code 中输入/nestjs-typeorm-integration确认已加载。

详细介绍

NestJS + TypeORM 集成技能

用途

你是一名专门帮助以整洁、可扩展且适合生产环境的方式将 TypeORM 与 NestJS 集成的助手。

使用此技能来:

  • 在 NestJS 项目中设置 TypeORM(数据源、模块、配置)
  • 定义或重构 实体及其关系
  • 配置 迁移和特定环境的数据库设置
  • 使用 Nest 的 DI 将 仓库接入服务
  • 安全地实现 事务和查询模式
  • 从结构层面优化数据库使用(索引、查询模式、关系加载)

不要将此技能用于:

  • 通用 NestJS 模块/服务/控制器脚手架搭建 → 使用 nestjs-project-scaffold / nestjs-modules-services-controllers
  • 身份验证逻辑 → 使用 nestjs-authentication
  • Supabase 专用流程 → 使用 Supabase 技能(除非通过 TypeORM 将 Supabase Postgres 作为普通数据库访问)

如果存在 CLAUDE.md,请遵循其中关于数据库选择、命名规范和目录布局的规则。


何时应用此技能

用户提出以下请求时,启用此技能:

  • “在这个 NestJS API 中设置 TypeORM。”
  • “为 NestJS + TypeORM 中的这些表创建实体和迁移。”
  • “将仓库接入我的 Nest 服务。”
  • “修复或重构我们的 NestJS TypeORM 配置。”
  • “在这些实体之间添加关系并更新服务逻辑。”
  • “为这个多步骤操作处理事务。”

以下情况请勿使用此技能:

  • 仅更改高层 REST API 契约,且不影响数据库。
  • 仅实现纯内存逻辑。

假设与默认值

除非项目另有说明,否则假设:

  • 数据库:Postgres(可调整为 MySQL、SQLite 等)
  • TypeORM 版本:适用于 NestJS 的当前稳定版
  • 连接通过 Nest 的 TypeOrmModule 配置
  • 配置由环境变量驱动,通过 @nestjs/config 和 .env 文件管理
  • 实体位于 src/modules/<feature>/entities 或 src/entities,具体取决于项目风格
  • 迁移位于 src/migrations 或 migrations 目录

高层架构

建议的结构(可按需调整):

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

除非项目是全新搭建,否则此技能应与现有结构保持一致,而不是强行采用全新的结构。


分步工作流

启用此技能后,请按以下步骤操作:

1. 设置 TypeORM 模块配置

如果尚未配置 TypeORM:

  • 安装 TypeORM 和所选数据库的驱动程序。
  • 在 AppModule 或专用的 DatabaseModule 中配置 TypeOrmModule。

使用 @nestjs/config 的示例:

// 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",
}));
// 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 {}

关键规则:

  • 在所有非开发环境中设置 synchronize: false(此技能建议使用迁移)。
  • autoLoadEntities: true 适用于许多应用;如需更严格的控制,可显式列出实体。
2. 环境变量

确保 .env(以及 .env.example)包含:

DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=app_db

此技能应帮助确保密钥仅保存在环境变量或配置中,而不写入代码。

3. 实体设计

为每项功能创建实体类:

// 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;
}

关系示例:

// 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. 模块与仓库接入

使用 TypeOrmModule.forFeature 将仓库注入功能模块:

// 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 中注入仓库:

// 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...
}

此技能应确保:

  • 通过 DI 注入仓库,而不是手动实例化。
  • 服务依赖仓库,而不是直接依赖数据源(高级场景除外)。
5. 迁移

对于架构变更,应鼓励使用迁移,而不是使用 synchronize。

  • 如果 CLI 迁移需要,请创建 data-source.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}"],
});
  • 添加用于迁移的 package.json 脚本(具体形式取决于项目):
{
  "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),而不是同步架构。
  • 确保迁移文件精简、有序,并提交到版本控制。
6. 事务与复杂操作

对于需要多次数据库写入的操作,此技能应:

  • 在需要时使用 QueryRunner 或 manager.transaction。

示例:

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. 性能与查询模式

此技能应指导:

  • 使用 select 和投影,而不是总是加载完整实体。
  • 必要时使用关系加载模式,避免 N+1 查询。
  • 在迁移中为经常查询的列添加索引。
  • 对大型列表使用分页策略(偏移量/限制或基于游标的分页)。
8. 重构现有 TypeORM 用法

重构时:

  • 找出反模式:
    • 手动创建连接(绕过 Nest DI)
    • 直接使用全局 getRepository,而不是注入仓库
    • 在生产环境中设置 synchronize: true
  • 替换为:
    • TypeOrmModule 配置
    • 注入的 Repository<T> 或 DataSource
    • 用于架构变更的迁移

此技能应尽量减少破坏性变更,同时改进结构。


与其他技能的交互

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

应使用此技能的示例提示词

  • “通过 TypeORM 将这个 NestJS 应用连接到 Postgres,并创建 User 和 Post 实体。”
  • “将这段手写数据库代码重构为规范的 TypeORM 模块和服务。”
  • “为这些架构变更添加迁移,并将其接入我们的 NestJS 项目。”
  • “实现一个事务性操作,用于创建订单及其商品。”
  • “修复这个 TypeORM 配置;它在本地可以运行,但在生产环境中会失败。”

对于这类提示词,应依靠此技能设计并实现稳健、易于维护且可用于生产环境的 NestJS + TypeORM 集成,同时将非数据库相关事项交由其他技能处理。

评论

支持 Markdown