UNPKG

@velopays/prisma-crud-generator

Version:

Generate CRUD operations and tests from Prisma models for NestJS

343 lines (273 loc) 9.6 kB
# Prisma CRUD Generator 一个基于 Prisma 模型自动生成 NestJS CRUD 代码和测试文件的工具。 ## 特性 - 🚀 从 Prisma 模型自动生成完整的 CRUD 代码 - 📝 生成 Controller、Service、DTOs 和 Module 文件 - 🧪 自动生成单元测试文件 - 🔧 支持复合主键和索引 - 🎨 支持自定义模板 - 📚 集成 Swagger 文档 - 🔐 内置权限控制支持 - 📦 自动生成通用文件: - 统一响应格式(ApiResponseDto) - 高级查询支持(BaseQueryDto 支持过滤、排序、分页、搜索等) - 认证和权限(Guards、Decorators) - 拦截器(响应格式化、日志记录) - 管道和过滤器(验证、异常处理) - 工具类(Prisma 错误处理、查询构建器) ## 多文件 Schema 支持 -**支持多文件 Prisma schema 结构**:现在支持从生成的 Prisma 客户端获取 DMMF -**自动检测客户端路径**:自动搜索常见的客户端生成路径 -**自定义客户端路径**:支持通过 `--client-path` 参数指定自定义路径 ### 使用多文件 Schema 如果您使用多文件 Prisma schema 结构,请确保: 1. 先运行 `prisma generate` 生成客户端 2. 使用 `--client-path` 参数指定客户端路径(可选) ```bash # 先生成 Prisma 客户端 npx prisma generate # 使用生成器(会自动查找客户端) prisma-crud generate # 或指定客户端路径 prisma-crud generate --client-path ./generated/prisma ``` ## 安装 ```bash npm install -g @ateam/prisma-crud-generator ``` 或作为项目依赖: ```bash npm install --save-dev @ateam/prisma-crud-generator ``` ## 使用方法 ### CLI 命令 ```bash # 初始化配置文件 prisma-crud init # 使用配置文件生成(推荐) prisma-crud generate # 使用自定义配置文件路径 prisma-crud generate -c ./my-config.json # 直接指定参数(覆盖配置文件) prisma-crud generate -s ./prisma/schema.prisma -o ./src/modules # 覆盖配置文件中的部分选项 prisma-crud generate -p api/v2 --no-swagger # 使用自定义模板 prisma-crud generate -t ./custom-templates # 指定 schema 名称 prisma-crud generate -n user ``` ### 配置文件 创建 `prisma-crud.config.json````json { "schema": "./prisma/schema.prisma", "output": "./src/modules", "apiPrefix": "api", "swaggerEnabled": true, "customTemplatesPath": "./custom-templates", "schemaName": "main", // 可选,默认从文件名提取 "clientPath": "./generated/prisma", // 可选,用于多文件 schema 支持 "generateCommonFiles": true, // 可选,是否生成通用文件,默认为 true "includeRelationsInCreateDto": false, // 可选,是否在创建DTO中包含关系字段 "includeRelationsInQueryDto": false // 可选,是否在查询DTO中包含关系字段 } ``` ### 编程式使用 ```typescript import { generateAllCrudFiles, GeneratorConfig } from '@ateam/prisma-crud-generator'; const config: GeneratorConfig = { prismaSchemaPath: './prisma/schema.prisma', outputPath: './src/modules', apiPrefix: 'api', swaggerEnabled: true, }; await generateAllCrudFiles(config); ``` ## 生成的文件结构 对于每个 Prisma 模型,将生成以下文件结构: ``` src/modules/ ├── common/ # 通用文件(generateCommonFiles: true 时生成) │ ├── dto/ │ │ ├── api-response.dto.ts # 统一响应格式 │ │ ├── base-query.dto.ts # 高级查询基类(支持过滤、排序、分页等) │ │ ├── base-response.dto.ts # 基础响应 DTO │ │ └── base.dto.ts # 基础 DTO 工具类型 │ ├── guards/ │ │ ├── jwt-auth.guard.ts # JWT 认证守卫 │ │ └── permission.guard.ts # 权限守卫 │ ├── decorators/ │ │ └── require-permission.decorator.ts # 权限装饰器 │ ├── types/ │ │ └── permission.types.ts # 权限类型定义 │ ├── prisma/ │ │ ├── prisma.service.ts # Prisma 服务 │ │ └── prisma.module.ts # Prisma 模块 │ ├── interceptors/ │ │ ├── response.interceptor.ts # 响应格式化拦截器 │ │ └── logging.interceptor.ts # 日志记录拦截器 │ ├── pipes/ │ │ └── validation.pipe.ts # 验证管道 │ ├── filters/ │ │ └── http-exception.filter.ts # HTTP 异常过滤器 │ ├── services/ │ │ └── query-builder.service.ts # 查询构建服务 │ ├── utils/ │ │ └── prisma-error.util.ts # Prisma 错误处理工具 │ └── common.module.ts # 通用模块 └── [schema-name]/ # 从 Prisma schema 文件名提取的 schema 名称 └── user/ ├── controllers/ │ ├── user.controller.ts │ └── user.controller.spec.ts ├── services/ │ ├── user.service.ts │ └── user.service.spec.ts ├── dto/ │ ├── create-user.dto.ts │ ├── update-user.dto.ts │ ├── query-user.dto.ts │ └── user-response.dto.ts └── user.module.ts ``` 注意: - 如果 Prisma schema 文件名为 `user.prisma`,则 schema 名称为 `user` - 如果文件名为 `schema.prisma`,则默认 schema 名称为 `main` - 可以通过配置文件中的 `schemaName` 字段自定义 schema 名称 ## 支持的功能 ### Prisma 模型特性 - ✅ 基本字段类型(String, Int, Float, Boolean, DateTime, Json) - ✅ 可选字段 - ✅ 默认值 - ✅ 唯一约束 - ✅ 复合主键 - ✅ 关系(一对一、一对多、多对多) - ✅ 索引 - ✅ 枚举类型 ### 生成的代码特性 - 完整的 CRUD 操作(Create, Read, Update, Delete) - 分页查询支持 - 批量操作(createMany, updateMany, deleteMany) - 根据唯一字段查询(单字段和复合唯一索引) - 根据索引字段查询(支持复合索引) - 关联数据自动加载 - 错误处理(唯一约束、外键约束等) - 请求验证(class-validator) - Swagger 文档(包含完整的HTTP状态码定义) - 权限控制集成 ## 自定义模板 您可以通过提供自定义 Handlebars 模板来定制生成的代码: 1. 创建模板目录结构: ``` custom-templates/ ├── controller.hbs ├── controller.spec.hbs ├── service.hbs ├── service.spec.hbs ├── module.hbs └── dto/ ├── create.dto.hbs ├── update.dto.hbs ├── query.dto.hbs └── response.dto.hbs ``` 2. 使用自定义模板: ```bash prisma-crud generate -s ./prisma/schema.prisma -o ./src/modules -t ./custom-templates ``` ### 模板变量 模板中可用的变量: - `name` - 模型名称 - `pascalName` - PascalCase 格式的名称 - `camelName` - camelCase 格式的名称 - `kebabName` - kebab-case 格式的名称 - `pluralName` - 复数形式的名称 - `fields` - 字段数组 - `relations` - 关系数组 - `hasCompositeId` - 是否有复合主键 - `compositeIdFields` - 复合主键字段 - `uniqueFields` - 唯一约束 - `indexes` - 索引 - `apiPrefix` - API 前缀 - `swaggerEnabled` - 是否启用 Swagger ### 模板助手 可用的 Handlebars 助手: - `isCreateField` - 检查字段是否应包含在创建 DTO 中 - `isUpdateField` - 检查字段是否应包含在更新 DTO 中 - `isQueryField` - 检查字段是否应包含在查询 DTO 中 - `validationDecorators` - 生成验证装饰器 - `swaggerType` - 获取 Swagger 类型 - `compositeIdWhere` - 生成复合主键 where 子句 ## 示例 ### Prisma 模型 ```prisma model User { id String @id @default(uuid()) email String @unique name String? role UserRole @default(USER) posts Post[] profile Profile? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([email]) } enum UserRole { USER ADMIN } ``` ### 生成的 Service ```typescript @Injectable() export class UserService { constructor(private readonly prisma: PrismaService) {} async create(createUserDto: CreateUserDto) { try { const user = await this.prisma.user.create({ data: createUserDto, include: this.getIncludeOptions(), }); return user; } catch (error) { // 错误处理... } } // 根据唯一字段查询 async findByEmail(email: string) { const user = await this.prisma.user.findUnique({ where: { email }, include: this.getIncludeOptions(), }); if (!user) { throw new NotFoundException(`User with email: ${email} 不存在`); } return user; } // 根据索引查询(返回数组) async findByRole(role: string) { return await this.prisma.user.findMany({ where: { role }, include: this.getIncludeOptions(), }); } // 其他 CRUD 方法... private getIncludeOptions() { return { posts: true, profile: true, }; } } ``` ### 生成的 Controller 路由 - `GET /api/user` - 获取用户列表(分页) - `GET /api/user/:id` - 根据ID获取用户 - `GET /api/user/by-email/:email` - 根据邮箱获取用户(唯一索引) - `GET /api/user/by-username/:username` - 根据用户名获取用户(唯一索引) - `POST /api/user` - 创建用户 - `PATCH /api/user/:id` - 更新用户 - `DELETE /api/user/:id` - 删除用户 ## 许可证 MIT