create-dp-koa 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-dp-koa",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Scaffold a DP-Koa framework project from the official template",
5
5
  "type": "module",
6
6
  "bin": {
7
- "create-dp-koa": "./index.mjs"
7
+ "create-dp-koa": "index.mjs"
8
8
  },
9
9
  "files": [
10
10
  "index.mjs",
@@ -0,0 +1,45 @@
1
+ # Command:Backend Controller Cheatsheet
2
+
3
+ 你现在是【后端 Controller 速查助手】。
4
+
5
+ ## 适用场景(触发条件)
6
+ - 用户想要 Cursor 快速给出:**Controller 推荐写法** + **常用注解用法** + **最小可复制模板**。
7
+ - 本 Command **不直接修改代码**(只输出建议与模板)。
8
+
9
+ ---
10
+
11
+ ## 必须遵守的 Skills / Rules
12
+ - 始终遵守:`00-backend-core.skill.md`
13
+ - 本次必须启用并参考:
14
+ - `10-backend-api.skill.md`
15
+ - `11-backend-controller-recipes.skill.md`
16
+
17
+ ---
18
+
19
+ ## 输出要求(严格遵守)
20
+ 请严格按以下结构输出(只输出文本,不直接生成业务代码文件):
21
+
22
+ ```text
23
+ 【适用结论】
24
+ - 这次是否属于“写/改 Controller 路由接口”:是/否
25
+ - 推荐启用的 Skills:
26
+
27
+ 【Controller 推荐骨架(最小模板)】
28
+ - 给出一个可复制的 Controller 方法模板(含 @Get/@Post + @Query/@Body/@State + try/catch + success/fail)
29
+
30
+ 【常用注解速查】
31
+ - @Get/@Post:说明 + 何时用
32
+ - @Query/@Body:说明 + DTO 写法
33
+ - @State() vs @State('user'):差异 + 推荐写法
34
+ - @ResponseCode/@ResponseHeader:何时用
35
+ - @ResponseValidator/@ResponseValidateIf:何时用(可选)
36
+
37
+ 【DTO/Service 设计建议】
38
+ - 入参 DTO 应放在哪个目录、命名建议
39
+ - Service 方法签名建议(含返回类型)
40
+
41
+ 【对齐的项目样例(必须列出)】
42
+ - 列出你参考的文件路径(至少 2 个)
43
+ ```
44
+
45
+
@@ -0,0 +1,58 @@
1
+ # Command:Implement Backend API Controller
2
+
3
+ 你现在是【后端 API Controller 实现器】。
4
+
5
+ ## 适用场景(触发条件)
6
+ - 仅当用户要 **新增/修改 Controller 路由接口**(含 DTO、Swagger、响应映射)时使用本 Command。
7
+ - 本 Command 的目标是:**直接落地代码改动**(不是只做规划)。
8
+ - 如果用户只要规划,请改用:`plan-backend.md`
9
+
10
+ ---
11
+
12
+ ## 必须遵守的 Skills / Rules
13
+ - 始终遵守:`00-backend-core.skill.md`
14
+ - 本次必须额外启用并严格遵守:`10-backend-api.skill.md`
15
+ - 强烈建议同时启用(用于让写法更“像本项目”):`11-backend-controller-recipes.skill.md`
16
+ - 同时配套使用(按需要):
17
+ - `30-backend-validation.skill.md`(DTO + 校验)
18
+ - `40-backend-error-logging.skill.md`(try/catch + 日志)
19
+ - `20-backend-repository.skill.md`(如涉及事务/数据访问)
20
+ - `90-backend-testing.skill.md`(如需要补测试)
21
+
22
+ ---
23
+
24
+ ## 输入要求(信息不足必须先澄清)
25
+ 当用户未提供以下信息时,必须先提问澄清再写代码:
26
+ - **接口清单**:路径、方法(GET/POST)、接口用途
27
+ - **入参**:Query/Body/State 的字段、类型、是否必填
28
+ - **输出**:成功返回 data 结构、失败场景与错误码/错误信息
29
+ - **Service 目标**:要调用的 Service 方法名(或由你提出建议)
30
+ - **是否需要 Swagger**:对外接口默认需要(若用户明确不需要则不加)
31
+
32
+ ---
33
+
34
+ ## 实现约束(执行时必须检查)
35
+ - **路由/参数装饰器必须使用**:`@Get/@Post` + `@Query/@Body/@State`
36
+ - **DTO 必须强类型**:禁止 `any`;DTO 放到 `src/dto/controller/{module}/`
37
+ - **Controller 必须 try/catch**
38
+ - **Controller 必须映射统一响应**:使用 `BaseController.success/fail`,禁止 `return result`
39
+ - **禁止在 Controller 写业务逻辑/直接访问数据库**
40
+
41
+ ---
42
+
43
+ ## 输出/交付(你必须做到)
44
+ 1. **明确将要修改/新增的文件列表**(含路径)
45
+ 2. **实现 DTO**(必要时新建文件)
46
+ 3. **实现/修改 Controller**(装饰器 + DTO + try/catch + 响应映射)
47
+ 4. **如需**:补 Swagger 装饰器、补/改 Service 接口签名
48
+ 5. **如需**:补 Jest 测试(至少覆盖成功/失败/边界之一)
49
+
50
+ ---
51
+
52
+ ## 写代码前的对齐动作(必须)
53
+ - 在生成/修改 Controller 代码前,先对齐本项目示例写法:
54
+ - `src/controllers/example/NewAnnotationExampleController.ts`
55
+ - `src/controllers/home/ytUser.controller.ts`
56
+ - `src/controllers/base.controller.ts`
57
+
58
+
@@ -0,0 +1,97 @@
1
+ # Command:Backend Skill Planner
2
+
3
+ 你现在是【后端技能规划器(Backend Skill Planner)】。
4
+
5
+ 你的职责是:
6
+ - 分析用户的后端开发需求
7
+ - 规划应该使用哪些 Backend Skills
8
+ - 给出清晰、可执行的技能调用顺序
9
+ - 不直接生成业务代码
10
+
11
+ ---
12
+
13
+ ## 一、你可以使用的 Skills(已定义)
14
+
15
+ - Backend Core Skill(始终生效)
16
+ - Backend API Skill
17
+ - Backend Service Skill
18
+ - Backend Repository Skill
19
+ - Backend Validation Skill
20
+ - Backend Error & Logging Skill
21
+ - Backend Testing Skill
22
+ - Backend Bootstrap Lifecycle Skill(启动生命周期:before/after/bootstrap)
23
+ - Backend Router Registration Skill(路由注册:routers/index.ts + bindRouter)
24
+
25
+ ---
26
+
27
+ ## 二、规划规则(必须遵守)
28
+
29
+ 1. **不要直接写代码**
30
+ 2. **不要跳过规划步骤**
31
+ 3. 每个 Skill 必须说明:
32
+ - 使用原因
33
+ - 预期输出
34
+ 4. 如果用户信息不足,必须先提出澄清问题
35
+ 5. 输出结构必须严格遵守下方格式
36
+ 6. 若需求涉及启动流程/中间件顺序/路由注册/数据库初始化/监控任务:
37
+ - 必须纳入 Backend Bootstrap Lifecycle Skill(`50-backend-bootstrap-lifecycle.skill.md`)
38
+ 7. 若需求涉及新增/修改路由绑定(`src/routers/index.ts`)、调整 `bindRouter` 或路由体系:
39
+ - 必须纳入 Backend Router Registration Skill(`60-backend-router-registration.skill.md`)
40
+
41
+ ---
42
+
43
+ ## 三、输出格式(严格遵守)
44
+
45
+ ```text
46
+ 【需求理解】
47
+ - 用户目标:
48
+ - 涉及模块:
49
+ - 是否新增 / 修改:
50
+
51
+ 【技能规划】
52
+ Step 1:Backend Validation Skill
53
+ - 原因:
54
+ - 输出:
55
+
56
+ Step 2:Backend API Skill
57
+ - 原因:
58
+ - 输出:
59
+
60
+ Step 3:Backend Service Skill
61
+ - 原因:
62
+ - 输出:
63
+
64
+ Step 4:Backend Repository Skill
65
+ - 原因:
66
+ - 输出:
67
+
68
+ Step 5:Backend Error & Logging Skill
69
+ - 原因:
70
+ - 输出:
71
+
72
+ Step 6:Backend Testing Skill(如需要)
73
+ - 原因:
74
+ - 输出:
75
+
76
+ Step X:Backend Bootstrap Lifecycle Skill(如涉及启动/bootstrapping)
77
+ - 原因:
78
+ - 输出:
79
+
80
+ Step Y:Backend Router Registration Skill(如涉及路由注册/routers/index.ts)
81
+ - 原因:
82
+ - 输出:
83
+
84
+ 【不确定点 / 需要澄清】
85
+ - 问题 1:
86
+ - 问题 2:
87
+
88
+ 【执行建议】
89
+ - 推荐使用的 Commands:
90
+ - 是否可以进入代码生成阶段:
91
+
92
+ ---
93
+
94
+ ## 四、可用 Commands(建议在【执行建议】中引用)
95
+ - `plan-backend.md`:只做技能规划,不直接写代码
96
+ - `implement-backend-api-controller.md`:新增/修改 Controller 路由接口(显式启用 Backend API Skill)
97
+ - `cheatsheet-backend-controller.md`:输出 Controller 推荐写法 + 常用注解速查(不直接改代码)
@@ -0,0 +1,61 @@
1
+ ---
2
+ alwaysApply: true
3
+ ---
4
+ # Skill:后端核心开发规范(Backend Core)
5
+
6
+ ## 适用范围
7
+ - 本项目所有 TypeScript 后端代码
8
+ - 技术栈:Koa + TypeORM + dp-ioc2 + 自定义装饰器体系
9
+ - **包管理工具:必须使用 yarn(禁止使用 npm)**
10
+
11
+ ---
12
+
13
+ ## 运行环境判定(debug 口径,必须)
14
+
15
+ **唯一标准**:以 `src/framework/utils/function.ts` 为准,**不要**用 `process.env.NODE_ENV` 作为“是否生产/是否调试”的单一判断。
16
+
17
+ - **`isDebug()`**:当进程启动参数中包含 `--env=debug` 时为 `true`。
18
+ - **非 debug**:一律按**生产口径**处理(例如:迁移、静态资源长缓存、对外错误信息脱敏等)。
19
+ - **`getRuntimeEnvironmentLabel()`**:返回 `'development' | 'production'`,用于日志与配置元数据,**与 `NODE_ENV` 解耦**。
20
+
21
+ **例外**:`NODE_ENV === 'test'`(Jest 等)仍保留用于测试专用分支,与上述 debug 口径并行,不互相替代。
22
+
23
+ ---
24
+
25
+ ## 一、分层架构(必须遵守)
26
+
27
+ ### 分层职责
28
+ - **Controller 层**
29
+ - 接收请求
30
+ - 参数校验
31
+ - 调用 Service
32
+ - 返回统一响应
33
+ - **Service 层**
34
+ - 编写业务逻辑
35
+ - 调用 Repository
36
+ - **Repository 层**
37
+ - 封装数据库访问逻辑(TypeORM)
38
+
39
+ ---
40
+
41
+ ## 二、基类与返回规范
42
+
43
+ ### 基类继承
44
+ - Controller **必须继承** `BaseController`
45
+ - Service **必须继承** `BaseService`
46
+
47
+ ### Service 返回值
48
+ - Service 方法必须返回 `CommonServiceResult<T>`
49
+
50
+ ### Controller 返回值
51
+ - Controller 必须通过:
52
+ - `this.success<T>(data, message?)`
53
+ - `this.fail<T>(code, message?)`
54
+
55
+ 返回 `ControllerResponse<T>`:
56
+ ```ts
57
+ {
58
+ code: number
59
+ data: T | null
60
+ message: string
61
+ }
@@ -0,0 +1,57 @@
1
+ ---
2
+ alwaysApply: true
3
+ ---
4
+ # Skill:Backend Skill Router(规则路由器)
5
+
6
+ 你现在的角色是【后端 Skill 路由器】:你的目标是帮助选择应启用的 rules/skills/commands,避免盲用规则。
7
+
8
+ ## 总原则(必须遵守)
9
+ - **优先使用 Commands** 来触发正确的 Skills,而不是把所有规则都写成 alwaysApply。
10
+ - 如果用户需求不清晰,必须先提问澄清(不要臆造不存在的接口/文件/配置)。
11
+
12
+ ---
13
+
14
+ ## 你必须做的事(每次用户提出开发/改动请求时)
15
+
16
+ ### 1) 识别任务类型(多选)
17
+ - Controller/API 开发
18
+ - DTO/参数校验
19
+ - Service/Repository/事务
20
+ - 错误处理/日志
21
+ - 启动流程(`app.ts`/`bootstrap.ts`,before/after)
22
+ - 路由注册(`routers/index.ts`、`bindRouter`)
23
+ - 中间件(`src/middlewares/*`)
24
+ - 测试(Jest)
25
+ - 目录结构与放置(libs/utils)
26
+
27
+ ### 2) 给出推荐启用的 Skills(只列文件名即可)
28
+ 按任务类型映射:
29
+ - **Controller/API**:
30
+ - `10-backend-api.skill.md`
31
+ -(需要范式/注解速查时)`11-backend-controller-recipes.skill.md`
32
+ - **Service**:
33
+ - `21-backend-service.skill.md`
34
+ - **DTO/校验**:`30-backend-validation.skill.md`
35
+ - **Service/Repository/事务**:`20-backend-repository.skill.md`
36
+ - **错误/日志**:`40-backend-error-logging.skill.md`
37
+ - **启动流程**:`50-backend-bootstrap-lifecycle.skill.md`
38
+ - **路由注册**:`60-backend-router-registration.skill.md`
39
+ - **中间件**:`70-backend-middleware.skill.md`
40
+ - **测试**:`90-backend-testing.skill.md`
41
+ - **libs/utils 放置**:`80-backend-utils-and-libs.skill.md`
42
+
43
+ 注意:
44
+ - `00-backend-core.skill.md` 已是 alwaysApply,无需重复声明
45
+
46
+ ### 3) 推荐使用的 Command(优先)
47
+ - 需要先规划:`.cursor/commands/plan-backend.md`
48
+ - 要实现/修改 Controller:`.cursor/commands/implement-backend-api-controller.md`
49
+ - 只要 Controller 速查:`.cursor/commands/cheatsheet-backend-controller.md`
50
+
51
+ ---
52
+
53
+ ## 输出要求(简短)
54
+ - 当用户让你“直接写代码”:直接进入实现,但先在心里完成上述路由选择
55
+ - 当用户不确定或信息不足:先问 2~5 个关键澄清问题
56
+
57
+
@@ -0,0 +1,55 @@
1
+ ---
2
+ alwaysApply: false
3
+ ---
4
+ # Skill:后端 API 开发规范
5
+
6
+ ## 适用与触发(重要)
7
+ - **仅在**你要生成/修改 **Controller 路由接口** 时应用本 Skill(否则忽略)
8
+ - 触发口令建议:
9
+ - “按 `10-backend-api.skill.md` 实现/重构这个 Controller”
10
+ - “按 API Skill 写路由 + DTO + 统一响应”
11
+
12
+ ---
13
+
14
+ ## 一、路由与参数装饰器(必须)
15
+ - 路由装饰器:`@Get` / `@Post`
16
+ - 参数装饰器:`@Query` / `@Body` / `@State`
17
+ - 禁止在 Controller 中手动解析 ctx(除非该 Controller 明确以 ctx 作为参数且项目已有同类写法)
18
+
19
+ ---
20
+
21
+ ## 二、Controller 编排规范(必须)
22
+
23
+ ### 2.1 只做三件事
24
+ - **参数接收与校验**(DTO)
25
+ - **调用 Service**
26
+ - **映射为统一响应**(`BaseController.success/fail`)
27
+
28
+ ### 2.2 统一响应(必须)
29
+ - Controller 必须返回 `ControllerResponse<T>`(通过 `this.success()` / `this.fail()`)
30
+ - 禁止 `return result`(Service 原始结果):
31
+ - 成功:`return this.success(result.data, result.message?)`
32
+ - 失败:`return this.fail(result.code, result.message)`
33
+
34
+ ### 2.3 错误处理(必须)
35
+ - Controller 的 `async` 方法必须 `try/catch`
36
+ - catch:记录日志(见 `40-backend-error-logging.skill.md`)+ 返回通用失败响应
37
+
38
+ ### 2.4 DTO(必须)
39
+ - `@Query()` / `@Body()` 必须使用 **DTO 类型**(禁止 `any`)
40
+ - DTO 的定义与校验遵循 `30-backend-validation.skill.md`
41
+
42
+ ---
43
+
44
+ ## 三、接口文档与元信息(可选但优先)
45
+ - 对外接口优先补齐 Swagger:`@ApiTags` / `@Api` / `@ApiResponse`
46
+ - 需要显式状态码/响应头时使用:`@ResponseCode` / `@ResponseHeader`
47
+
48
+ ---
49
+
50
+ ## 四、禁止行为(必须)
51
+ - ❌ Controller 中编写业务逻辑(应下沉到 Service)
52
+ - ❌ Controller 中直接访问数据库/Repository
53
+ - ❌ Controller 中返回 Service 原始结果(必须映射为统一响应)
54
+ - ❌ `@Query()` / `@Body()` 使用 `any` 或未校验的入参对象
55
+
@@ -0,0 +1,109 @@
1
+ ---
2
+ alwaysApply: false
3
+ ---
4
+ # Skill:Controller 推荐写法 + 常用注解速查(Recipes)
5
+
6
+ ## 适用与触发(重要)
7
+ - 仅当需要**新增/修改 Controller 路由接口**,且希望按本项目框架“推荐范式”实现时使用本 Skill。
8
+ - 触发口令建议:
9
+ - “请同时启用 `11-backend-controller-recipes.skill.md`,按项目范式实现 Controller”
10
+
11
+ ---
12
+
13
+ ## 一、写 Controller 的推荐范式(必须对齐)
14
+
15
+ ### 1.1 参考样例(写代码前先对齐)
16
+ - 推荐在实现前先对齐以下文件的写法(不要臆造新风格):
17
+ - `src/controllers/example/NewAnnotationExampleController.ts`
18
+ - `src/controllers/home/ytUser.controller.ts`
19
+ - `src/controllers/base.controller.ts`
20
+
21
+ ### 1.2 Controller 标准骨架(复制这个结构)
22
+ 目标:DTO 入参 → 调用 Service → 统一响应(`success/fail`)→ try/catch + logger
23
+
24
+ ```ts
25
+ import { Get, Post, Query, Body, State, ResponseCode, ResponseHeader } from '@src/framework/decorator/controller';
26
+ import { BaseController, ControllerResponse } from '@src/controllers/base.controller';
27
+ import { Inject } from 'dp-ioc2';
28
+ import { logger } from '@src/framework/utils/logger';
29
+ import { SomeService } from '@src/service/some.service';
30
+ import { SomeQueryDto, SomeBodyDto } from '@src/dto/controller/xxx/some.controller.dto';
31
+ import { CommonServiceResultCode } from '@src/framework/types/ServiceResult';
32
+
33
+ export class SomeController extends BaseController {
34
+ @Inject(SomeService)
35
+ private someService: SomeService;
36
+
37
+ @Get('/some/path')
38
+ @ResponseCode(200)
39
+ async getSomething(
40
+ @Query(SomeQueryDto) query: SomeQueryDto,
41
+ @State('user') user: { userId: number; type?: number },
42
+ ): Promise<ControllerResponse<any>> {
43
+ try {
44
+ const result = await this.someService.someMethod(query, user.userId);
45
+ if (result.code !== CommonServiceResultCode.SUCCESS) {
46
+ return this.fail(-1, result.message);
47
+ }
48
+ return this.success(result.data);
49
+ } catch (error) {
50
+ logger.error('getSomething 失败', error as Error);
51
+ return this.fail(-1, '系统错误');
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ 硬约束:
58
+ - Controller **不写业务逻辑**,只做编排
59
+ - Controller **不直接访问数据库/Repository**
60
+ - Controller **不 return Service 原始结果**,必须映射 `success/fail`
61
+ - Controller `async` **必须 try/catch**
62
+
63
+ ---
64
+
65
+ ## 二、常用注解速查(按本项目实现理解)
66
+
67
+ ### 2.1 路由类注解
68
+ - **`@Get('/path')`**:注册 GET 路由;不传参数时 url 默认使用方法名
69
+ - **`@Post('/path')`**:注册 POST 路由;不传参数时 url 默认使用方法名
70
+
71
+ ### 2.2 参数注解(重点)
72
+ - **`@Query()`**:
73
+ - 读取 query 参数
74
+ - 推荐写法:`@Query(SomeQueryDto) query: XxxQueryDto`
75
+ - **`@Body()`**:
76
+ - 读取 body 参数
77
+ - 推荐写法:`@Body(SomeBodyDto) body: XxxBodyDto`
78
+ - **`@State()`**:
79
+ - 读取整个 `ctx.state`(样例:`ytUser.controller.ts`)
80
+ - 推荐写法:`@State() state: { user: { userId: number; type?: number } }`
81
+ - **`@State('user')`**:
82
+ - 读取 `ctx.state.user`(样例:`NewAnnotationExampleController.ts`)
83
+ - 推荐写法:`@State('user') user: { userId: number; type?: number }`
84
+
85
+ 禁止:
86
+ - ❌ `@Query() query: any` / `@Body() body: any` / `@State() state: any`(尽量不要)
87
+
88
+ ### 2.3 响应元信息注解
89
+ - **`@ResponseCode(200|201|...)`**:设置 HTTP 状态码(样例中 GET 用 200,POST 用 201)
90
+ - **`@ResponseHeader(key, value)`**:为响应添加 header
91
+
92
+ ### 2.4 响应校验注解(进阶,按需)
93
+ - **`@ResponseValidator(DtoClass, objectKey?)`**:对响应数据做校验
94
+ - **`@ResponseValidateIf(DtoClass, fn)`**:仅当 fn 返回真时才校验(样例:`ytUser.controller.ts`)
95
+
96
+ ---
97
+
98
+ ## 三、常见组合(直接套用)
99
+
100
+ ### 3.1 需要登录用户的 GET 接口
101
+ - `@Get('/xxx') + @State('user')`(或 `@State()` 取整段 state)
102
+
103
+ ### 3.2 带 body 的 POST 接口
104
+ - `@Post('/xxx') + @Body(SomeBodyDto) body: DtSomeBodyDtoo + @ResponseCode(201)`
105
+
106
+ ### 3.3 需要自定义 header
107
+ - `@ResponseHeader('X-XXX', 'value')`
108
+
109
+
@@ -0,0 +1,25 @@
1
+ ---
2
+ alwaysApply: false
3
+ ---
4
+ # Skill:Repository 与数据访问规范
5
+
6
+ ## 一、Repository 使用方式
7
+
8
+ - Service 中通过:
9
+ - `getDataRepository<Entity>(EntityClass)`
10
+ - 或 `createLazyRepository()`(推荐)
11
+
12
+ ---
13
+
14
+ ## 二、事务管理
15
+
16
+ - 涉及多表操作时:
17
+ - 必须使用 `transactionManager.executeInTransaction()`
18
+ - 禁止手动管理事务
19
+
20
+ ---
21
+
22
+ ## 三、禁止行为
23
+
24
+ - ❌ Controller 中访问 Repository
25
+ - ❌ Service 中直接获取 DataSource
@@ -0,0 +1,137 @@
1
+ ---
2
+ alwaysApply: false
3
+ ---
4
+ # Skill:Service 层开发规范
5
+
6
+ ## 适用与触发(重要)
7
+ - 当需要新增/修改 Service 类(`src/service/**.service.ts` 或等价命名)时启用本 Skill。
8
+ - 典型场景:
9
+ - 新增业务用例(用户、店铺、商品等)的 Service 方法
10
+ - 重构/增强现有 Service(增加校验、事务、日志等)
11
+
12
+ ---
13
+
14
+ ## 一、Service 职责定位(必须)
15
+ - Service 负责:
16
+ - 业务规则/用例编排(多 Repository、多实体、多步骤)
17
+ - 参数校验(通过 `@ParamValidate` 装饰器,由 dp-ioc2 自动处理)
18
+ - 事务边界控制(通过 `transactionManager.executeInTransaction`)
19
+ - 组合/组装领域数据,返回适合 Controller 消费的结果结构
20
+ - Service 不负责:
21
+ - HTTP/路由层细节(status code、header、ctx 等)
22
+ - 直接与 Koa `Context` 交互
23
+ - 直接返回 Controller 统一响应结构(`ControllerResponse`)
24
+
25
+ ---
26
+
27
+ ## 二、类定义与依赖(必须)
28
+ - Service 类必须:
29
+ - 使用 `@Injectable()` 装饰器
30
+ - 继承 `BaseService`
31
+ - Repository 访问:
32
+ - 优先使用 `BaseService` 提供的:
33
+ - `getDataRepository(EntityClass)`(简单 CRUD)
34
+ - `createLazyRepository(EntityClass, RepositoryClass, cache)`(自定义 Repository,参考 `YtUserService`)
35
+ - 禁止在 Service 中直接获取 DataSource:
36
+ - ❌ `getDataSource()` 直接操作
37
+ - ✅ 通过 Repository 完成数据访问(见 `20-backend-repository.skill.md`)
38
+
39
+ ---
40
+
41
+ ## 三、返回值规范(必须)
42
+ - 对外公开的 Service 方法,应优先返回:
43
+ - `Promise<CommonServiceResult<T>>`
44
+ - 使用统一工厂方法:
45
+ - 成功:`CommonServiceResult.success(data, message?)`
46
+ - 各种错误:`validationError / notFound / conflict / unauthorized / forbidden / error` 等
47
+ - 仅在兼容旧接口或内部辅助方法时,可返回原始实体/值(需有明确注释说明原因)
48
+
49
+ ---
50
+
51
+ ## 四、参数校验规范(必须)
52
+
53
+ ### 4.1 使用 `@ParamValidate` 装饰器
54
+ - **必须**在方法参数上使用 `@ParamValidate` 装饰器进行自动校验
55
+ - 导入:`import { ParamValidate } from "dp-ioc2"`
56
+ - 对象参数(DTO)校验:
57
+ ```typescript
58
+ async createUser(@ParamValidate(CreateUserDto) dto: CreateUserDto): Promise<CommonServiceResult<T>> {
59
+ // dp-ioc2 会自动使用 class-validator 校验 DTO
60
+ // 校验失败会抛出 IOCValidationError
61
+ }
62
+ ```
63
+ - 非对象参数(基本类型)校验:
64
+ ```typescript
65
+ import Joi from "joi";
66
+ async getUserById(@ParamValidate(undefined, Joi.string().min(3).required()) id: string): Promise<CommonServiceResult<T>> {
67
+ // dp-ioc2 会自动使用 joi 校验基本类型参数
68
+ }
69
+ ```
70
+ - 混合使用:
71
+ ```typescript
72
+ async updateUser(
73
+ @ParamValidate(undefined, Joi.number().positive().required()) userId: number,
74
+ @ParamValidate(UpdateUserDto) dto: UpdateUserDto
75
+ ): Promise<CommonServiceResult<T>> {
76
+ // 可以同时校验基本类型和对象参数
77
+ }
78
+ ```
79
+
80
+ ### 4.2 错误处理
81
+ - `@ParamValidate` 校验失败会抛出 `IOCValidationError` 异常
82
+ - **必须**在方法内部捕获并转换为 `CommonServiceResult`:
83
+ ```typescript
84
+ import { IOCValidationError } from "dp-ioc2";
85
+
86
+ async createUser(@ParamValidate(CreateUserDto) dto: CreateUserDto): Promise<CommonServiceResult<T>> {
87
+ try {
88
+ // 业务逻辑...
89
+ } catch (error) {
90
+ if (error instanceof IOCValidationError) {
91
+ // 将 IOCValidationError 转换为统一的错误响应
92
+ return CommonServiceResult.validationError(
93
+ error.message || "参数校验失败",
94
+ error.errors // 可选:传递详细错误信息
95
+ );
96
+ }
97
+ // 其他错误处理...
98
+ }
99
+ }
100
+ ```
101
+
102
+ ### 4.3 DTO 定义要求
103
+ - DTO 类必须使用 `class-validator` 装饰器(`@IsString`、`@IsEmail`、`@MinLength` 等)
104
+ - DTO 定义与目录规范遵循:`30-backend-validation.skill.md`
105
+ - 禁止在 Service 方法内部手动调用 `DtoValidator`(已由 `@ParamValidate` 自动处理)
106
+
107
+ ### 4.4 注意事项
108
+ - `@ParamValidate` 在方法调用前自动执行,无需手动调用校验方法
109
+ - 对象参数会自动转换为 DTO 类实例(支持传入普通对象)
110
+ - 参数校验在 `@Before` hook 之前执行
111
+ - 如果方法有多个参数需要校验,每个参数都需要单独添加 `@ParamValidate` 装饰器
112
+
113
+ ---
114
+
115
+ ## 五、事务与错误处理(必须)
116
+
117
+ ### 5.1 事务使用
118
+ - 涉及多表、多步写操作时,必须使用:
119
+ - `transactionManager.executeInTransaction(async (manager) => { ... })`
120
+ - 不允许自行手动开启/提交/回滚事务(由 `TransactionManager` 统一处理)
121
+ - 事务内如果需要 Repository,优先通过自定义 Repository/manager 适配(见现有示例)
122
+
123
+ ### 5.2 错误处理与日志
124
+ - Service 方法内部应使用 `try/catch`:
125
+ - `catch` 中使用 `logger.error(...)` 记录上下文信息
126
+ - 返回 `CommonServiceResult.error(...)` 或更具体的错误码
127
+ - 生产环境避免将详细错误信息/堆栈返回给调用方(参考 `YtUserService` 的错误处理模式)
128
+ - 详细错误处理规范参见:`40-backend-error-logging.skill.md`
129
+
130
+ ---
131
+
132
+ ## 六、调用关系约束(必须)
133
+ - Controller 只能调用 Service 的公开方法,不应调用 Repository
134
+ - Service 不应调用 Controller,也不应依赖 Koa `Context`
135
+ - Service 之间如需调用,应通过依赖注入(`@Inject(OtherService)`),避免静态调用/循环依赖
136
+
137
+