关于 nestjs-typeorm-integration
用于在 NestJS 应用中集成 TypeORM 的技能,涵盖数据库配置、实体、迁移、仓库注入和事务。适合构建或重构数据库驱动的 NestJS 服务,并遵循现有项目结构。
主要功能
- 01NestJS 的 TypeORM 配置
- 02实体与关系设计
- 03基于迁移的架构变更
- 04通过 Nest DI 注入仓库
- 05事务与查询指导
适用场景
- 01为 NestJS API 连接数据库
- 02添加实体、关系和迁移
- 03重构手动创建仓库或连接的代码
- 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