@deepstorm/cli 0.10.2 → 0.11.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.
Files changed (124) hide show
  1. package/README.md +8 -8
  2. package/dist/build-registry.js +11 -5
  3. package/dist/cli.js +1256 -634
  4. package/dist/mcp/code-hosting/github.json +14 -1
  5. package/dist/mcp/docs-reference/context7.json +1 -10
  6. package/dist/mcp-skills/deepstorm-mcp-feishu-wiki-read/SKILL.md +8 -5
  7. package/dist/mcp-skills/deepstorm-mcp-feishu-wiki-write/SKILL.md +10 -8
  8. package/dist/mcp-skills/deepstorm-mcp-figma-read/SKILL.md +21 -20
  9. package/dist/mcp-skills/deepstorm-mcp-github-read/SKILL.md +17 -17
  10. package/dist/mcp-skills/deepstorm-mcp-github-write/SKILL.md +20 -20
  11. package/dist/mcp-skills/deepstorm-mcp-jira-read/SKILL.md +8 -8
  12. package/dist/mcp-skills/deepstorm-mcp-jira-write/SKILL.md +13 -12
  13. package/dist/mcp-skills/deepstorm-mcp-playwright-read/SKILL.md +10 -10
  14. package/dist/registry.json +10 -0
  15. package/dist/skills/atoll-ops/SKILL.md +4 -0
  16. package/dist/skills/reef-commit/SKILL.md +9 -5
  17. package/dist/skills/reef-commit/scripts/branch-check.mjs +5 -11
  18. package/dist/skills/reef-commit/scripts/check-openspec-status.mjs +6 -12
  19. package/dist/skills/reef-commit/scripts/collect-git-context.mjs +13 -11
  20. package/dist/skills/reef-gen-backend/variants/java/steps.md +7 -7
  21. package/dist/skills/reef-gen-backend/variants/nodejs/steps.md +7 -7
  22. package/dist/skills/reef-gen-backend/variants/python/steps.md +7 -7
  23. package/dist/skills/reef-gen-frontend/variants/angular/steps.md +5 -5
  24. package/dist/skills/reef-gen-frontend/variants/react/steps.md +6 -6
  25. package/dist/skills/reef-gen-frontend/variants/vue/steps.md +6 -6
  26. package/dist/skills/reef-harden/EXAMPLES.md +12 -10
  27. package/dist/skills/reef-harden/SKILL.md +6 -0
  28. package/dist/skills/reef-harden/scripts/find-change-dir.mjs +13 -13
  29. package/dist/skills/reef-pr/SKILL.md +7 -0
  30. package/dist/skills/reef-pr/scripts/create-pr.mjs +31 -29
  31. package/dist/skills/reef-scope/SKILL.md +6 -6
  32. package/dist/skills/reef-start/references/jira-start-subagent.md +7 -7
  33. package/dist/skills/reef-start/references/risk-routing-card.md +28 -25
  34. package/dist/skills/reef-start/references/stage-4-implementation.md +33 -21
  35. package/dist/skills/reef-start/references/superpowers-gate.md +9 -9
  36. package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/examples/structured-output.md +2 -2
  37. package/dist/skills/reef-style-backend/fragments/java/ai/spring-ai/quick-reference.md +11 -0
  38. package/dist/skills/reef-style-backend/fragments/java/api-spec/jackson-polymorphism.md +36 -40
  39. package/dist/skills/reef-style-backend/fragments/java/api-spec/quick-reference.md +11 -10
  40. package/dist/skills/reef-style-backend/fragments/java/db-migration/liquibase/examples/database-migration.md +7 -7
  41. package/dist/skills/reef-style-backend/fragments/java/dependency-management/quick-reference.md +24 -21
  42. package/dist/skills/reef-style-backend/fragments/java/exception-handling/examples/error-code-enum.md +7 -7
  43. package/dist/skills/reef-style-backend/fragments/java/exception-handling/quick-reference.md +10 -8
  44. package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/dto-mapper.md +2 -2
  45. package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/service-entity.md +5 -5
  46. package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/examples/testing.md +1 -0
  47. package/dist/skills/reef-style-backend/fragments/java/framework/spring-boot/quick-reference.md +12 -12
  48. package/dist/skills/reef-style-backend/fragments/java/orm/hibernate/quick-reference.md +13 -12
  49. package/dist/skills/reef-style-backend/fragments/java/security-redlines/quick-reference.md +11 -9
  50. package/dist/skills/reef-style-backend/fragments/java/test/data-jpa-test/quick-reference.md +7 -7
  51. package/dist/skills/reef-style-backend/fragments/java/test/junit5/quick-reference.md +6 -6
  52. package/dist/skills/reef-style-backend/fragments/java/test/spring-mvc-test/quick-reference.md +8 -8
  53. package/dist/skills/reef-style-backend/fragments/java/test/spring-service-test/quick-reference.md +8 -7
  54. package/dist/skills/reef-style-backend/fragments/nodejs/eslint-config.json +1 -4
  55. package/dist/skills/reef-style-backend/fragments/nodejs/nestjs-structure.md +9 -9
  56. package/dist/skills/reef-style-backend/fragments/python/alembic-migration/quick-reference.md +2 -1
  57. package/dist/skills/reef-style-backend/fragments/python/api-spec/quick-reference.md +10 -10
  58. package/dist/skills/reef-style-backend/fragments/python/dependency-management/quick-reference.md +24 -22
  59. package/dist/skills/reef-style-backend/fragments/python/exception-handling/quick-reference.md +10 -9
  60. package/dist/skills/reef-style-backend/fragments/python/fastapi-quick-reference/quick-reference.md +3 -0
  61. package/dist/skills/reef-style-backend/fragments/python/langchain/quick-reference.md +10 -7
  62. package/dist/skills/reef-style-backend/fragments/python/pytest-testing/quick-reference.md +2 -0
  63. package/dist/skills/reef-style-backend/fragments/python/ruff-mypy-toolchain/quick-reference.md +2 -0
  64. package/dist/skills/reef-style-backend/fragments/python/security-redlines/quick-reference.md +11 -9
  65. package/dist/skills/reef-style-backend/fragments/python/sqlalchemy-orm/quick-reference.md +3 -0
  66. package/dist/skills/reef-style-backend/variants/java/examples/code-wrapping.md +3 -4
  67. package/dist/skills/reef-style-backend/variants/java/quick-reference.md +31 -29
  68. package/dist/skills/reef-style-backend/variants/nodejs/examples/module-example.md +2 -8
  69. package/dist/skills/reef-style-backend/variants/nodejs/quick-reference.md +35 -36
  70. package/dist/skills/reef-style-backend/variants/python/quick-reference.md +32 -31
  71. package/dist/skills/reef-style-frontend/fragments/css/tailwind/quick-reference.md +9 -7
  72. package/dist/skills/reef-style-frontend/fragments/test/vitest/examples/testing.md +9 -4
  73. package/dist/skills/reef-style-frontend/fragments/test/vitest/quick-reference.md +4 -4
  74. package/dist/skills/reef-style-frontend/fragments/test/vitest-react/examples/testing.md +135 -140
  75. package/dist/skills/reef-style-frontend/fragments/test/vitest-react/quick-reference.md +32 -32
  76. package/dist/skills/reef-style-frontend/fragments/test/vitest-vue/examples/testing.md +161 -162
  77. package/dist/skills/reef-style-frontend/fragments/test/vitest-vue/quick-reference.md +42 -42
  78. package/dist/skills/reef-style-frontend/fragments/ts-config/strict/quick-reference.md +16 -10
  79. package/dist/skills/reef-style-frontend/fragments/ui-lib/antd/examples/ui-components.md +72 -87
  80. package/dist/skills/reef-style-frontend/fragments/ui-lib/antd/quick-reference.md +14 -10
  81. package/dist/skills/reef-style-frontend/fragments/ui-lib/antd-vue/examples/ui-components.md +93 -111
  82. package/dist/skills/reef-style-frontend/fragments/ui-lib/antd-vue/quick-reference.md +29 -33
  83. package/dist/skills/reef-style-frontend/fragments/ui-lib/primeng/examples/ui-components.md +14 -23
  84. package/dist/skills/reef-style-frontend/variants/angular/examples/code-wrapping.md +15 -17
  85. package/dist/skills/reef-style-frontend/variants/angular/examples/component-types-pipes.md +22 -5
  86. package/dist/skills/reef-style-frontend/variants/angular/examples/entity-types.md +52 -22
  87. package/dist/skills/reef-style-frontend/variants/angular/examples/forms-layer.md +17 -20
  88. package/dist/skills/reef-style-frontend/variants/angular/examples/service-routing.md +8 -11
  89. package/dist/skills/reef-style-frontend/variants/angular/quick-reference.md +27 -27
  90. package/dist/skills/reef-style-frontend/variants/react/examples/code-wrapping.md +14 -27
  91. package/dist/skills/reef-style-frontend/variants/react/examples/component-types-pipes.md +45 -52
  92. package/dist/skills/reef-style-frontend/variants/react/examples/entity-types.md +44 -44
  93. package/dist/skills/reef-style-frontend/variants/react/examples/forms-layer.md +56 -85
  94. package/dist/skills/reef-style-frontend/variants/react/examples/service-routing.md +114 -88
  95. package/dist/skills/reef-style-frontend/variants/react/quick-reference.md +48 -42
  96. package/dist/skills/reef-style-frontend/variants/vue/examples/code-wrapping.md +24 -43
  97. package/dist/skills/reef-style-frontend/variants/vue/examples/component-types-pipes.md +48 -49
  98. package/dist/skills/reef-style-frontend/variants/vue/examples/entity-types.md +45 -45
  99. package/dist/skills/reef-style-frontend/variants/vue/examples/forms-layer.md +64 -68
  100. package/dist/skills/reef-style-frontend/variants/vue/examples/service-routing.md +85 -84
  101. package/dist/skills/reef-style-frontend/variants/vue/quick-reference.md +46 -51
  102. package/dist/skills/reef-testcase/SKILL.md +19 -19
  103. package/dist/skills/reef-testcase/references/coverage-dimensions.md +8 -0
  104. package/dist/skills/reef-testcase/references/test-case-template.md +16 -16
  105. package/dist/skills/sweep-explore/SKILL.md +824 -0
  106. package/dist/skills/sweep-explore/references/explore-flow-template.md +61 -0
  107. package/dist/skills/sweep-init/SKILL.md +4 -0
  108. package/dist/skills/sweep-init/scripts/flow-selector.mjs +6 -11
  109. package/dist/skills/sweep-init/scripts/init-project.mjs +68 -51
  110. package/dist/skills/sweep-plan/references/test-flow-template.md +12 -6
  111. package/dist/skills/sweep-record/SKILL.md +358 -0
  112. package/dist/skills/sweep-run/SKILL.md +59 -50
  113. package/dist/skills/sweep-run/scripts/env-manager.mjs +4 -5
  114. package/dist/skills/sweep-run/scripts/flow-parser.mjs +7 -6
  115. package/dist/skills/sweep-run/scripts/flow-selector.mjs +4 -15
  116. package/dist/skills/sweep-run/scripts/generate-report.mjs +1 -2
  117. package/dist/skills/sweep-run/scripts/mcp-manager.mjs +107 -14
  118. package/dist/skills/sweep-run/scripts/spec-compiler.mjs +19 -9
  119. package/dist/skills/tide-discuss/references/checklists.md +32 -32
  120. package/dist/skills/tide-discuss/references/data-format.md +85 -77
  121. package/dist/skills/tide-discuss/references/prd-template.md +21 -19
  122. package/dist/skills/tide-discuss/references/publish-flow.md +30 -11
  123. package/dist/skills/tide-discuss/references/role-prompts.md +5 -5
  124. package/package.json +5 -3
@@ -5,6 +5,7 @@
5
5
  > 已安装子维度的规范,通过该维度的 `{value}.md` 文件阅读。本页只包含语言通用的核心规范。
6
6
  >
7
7
  > **跨维度规范(适用所有后端代码):**
8
+ >
8
9
  > - [API 规范](api-spec.md) — RESTful 命名、统一响应体、OpenAPI、版本策略
9
10
  > - [依赖管理规范](dependency-management.md) — Version Catalog、版本一致性、CVE
10
11
  > - [异常处理深度规范](exception-handling.md) — 异常层次、错误码、全局处理
@@ -12,17 +13,17 @@
12
13
 
13
14
  ## 速查
14
15
 
15
- | 场景 | 决策 |
16
- | --- | --- |
17
- | 字符串格式化 | 用 `formatted()`,不用 `+` 拼接 |
18
- | 类型分发 | 用多态,不用 `instanceof` 链 |
19
- | 控件能力查询 | 基类声明 `abstract boolean supportsXxx()`,子类按能力返回 `true/false` |
20
- | 领域事件 / POJO | `@Getter @AllArgsConstructor`,不手写 getter/constructor |
21
- | 参数顺序 | `appId` → 父级 ID → 自身 ID → name/描述 |
22
- | 字段注释 | Model/Entity/Event 加 `/** */`,DTO/Record 不加 |
23
- | 日志实体 | 继承 `LogEntry`(SINGLE_TABLE),不直接继承基类 |
24
- | 弃用 API | 编译警告中的 `@Deprecated` API 在同一次 PR 中替换为新 API |
25
- | 多行字符串 | 用 Text Block `"""..."""` + `formatted()` 嵌入 JSON/SQL/XML,禁止 `+` 拼接 |
16
+ | 场景 | 决策 |
17
+ | --------------- | -------------------------------------------------------------------------- |
18
+ | 字符串格式化 | 用 `formatted()`,不用 `+` 拼接 |
19
+ | 类型分发 | 用多态,不用 `instanceof` 链 |
20
+ | 控件能力查询 | 基类声明 `abstract boolean supportsXxx()`,子类按能力返回 `true/false` |
21
+ | 领域事件 / POJO | `@Getter @AllArgsConstructor`,不手写 getter/constructor |
22
+ | 参数顺序 | `appId` → 父级 ID → 自身 ID → name/描述 |
23
+ | 字段注释 | Model/Entity/Event 加 `/** */`,DTO/Record 不加 |
24
+ | 日志实体 | 继承 `LogEntry`(SINGLE_TABLE),不直接继承基类 |
25
+ | 弃用 API | 编译警告中的 `@Deprecated` API 在同一次 PR 中替换为新 API |
26
+ | 多行字符串 | 用 Text Block `"""..."""` + `formatted()` 嵌入 JSON/SQL/XML,禁止 `+` 拼接 |
26
27
 
27
28
  ## 代码风格
28
29
 
@@ -39,14 +40,15 @@
39
40
 
40
41
  ### Lombok 使用规范
41
42
 
42
- | 组件类型 | 必用注解 | 说明 |
43
- |---------|---------|------|
44
- | 领域事件 / POJO | `@Getter @AllArgsConstructor` | `private final` 不可变,不手写 getter/constructor(见下方示例) |
45
- | JPA Entity | `@Getter @NoArgsConstructor(access = PROTECTED)` + `@SuperBuilder`(按需) | 详见 [Hibernate 规范](hibernate.md) |
46
- | Service / Controller | `@AllArgsConstructor` / `@RequiredArgsConstructor` | 构造函数注入,不用 `@Autowired` 字段注入 |
47
- | 只读 DTO / Record 替代 | `@Value` | 不可变对象,自动生成 equals/hashCode/toString。Record 更简洁时优先用 record |
43
+ | 组件类型 | 必用注解 | 说明 |
44
+ | ---------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
45
+ | 领域事件 / POJO | `@Getter @AllArgsConstructor` | `private final` 不可变,不手写 getter/constructor(见下方示例) |
46
+ | JPA Entity | `@Getter @NoArgsConstructor(access = PROTECTED)` + `@SuperBuilder`(按需) | 详见 [Hibernate 规范](hibernate.md) |
47
+ | Service / Controller | `@AllArgsConstructor` / `@RequiredArgsConstructor` | 构造函数注入,不用 `@Autowired` 字段注入 |
48
+ | 只读 DTO / Record 替代 | `@Value` | 不可变对象,自动生成 equals/hashCode/toString。Record 更简洁时优先用 record |
48
49
 
49
50
  **禁止事项:**
51
+
50
52
  - `@Data` — 自动生成 `@Setter` 破坏不可变性,且 `@EqualsAndHashCode` 在有 JPA 代理时行为不可预期
51
53
  - `@Setter` on Entity — 破坏封装,业务状态变更应通过行为方法表达
52
54
  - `@Autowired` 字段注入 — 必须用构造函数注入
@@ -72,13 +74,13 @@ public abstract boolean supportsImporting();
72
74
 
73
75
  ## 注释规则
74
76
 
75
- | 文件类型 | 注释要求 |
76
- |---------|---------|
77
- | **Entity** | 类 Javadoc `/** 实体描述 */`;每个字段 `/** 字段含义 */` |
78
- | **DTO / Record** | 类 Javadoc `/** 用途说明 */`;字段不加 `/** */` 注释 |
79
- | **Repository** | 自定义查询方法加 `/** 查询意图、参数含义 */`;简单 CRUD 方法可不加 |
80
- | **Service** | 每个 public 方法加 Javadoc `/** 功能、@param、@return */` |
81
- | **Controller** | 每个端点加 `@Operation(summary=, description=)` 或等价 Javadoc |
77
+ | 文件类型 | 注释要求 |
78
+ | ---------------- | ------------------------------------------------------------------ |
79
+ | **Entity** | 类 Javadoc `/** 实体描述 */`;每个字段 `/** 字段含义 */` |
80
+ | **DTO / Record** | 类 Javadoc `/** 用途说明 */`;字段不加 `/** */` 注释 |
81
+ | **Repository** | 自定义查询方法加 `/** 查询意图、参数含义 */`;简单 CRUD 方法可不加 |
82
+ | **Service** | 每个 public 方法加 Javadoc `/** 功能、@param、@return */` |
83
+ | **Controller** | 每个端点加 `@Operation(summary=, description=)` 或等价 Javadoc |
82
84
 
83
85
  ## 领域事件 / POJO
84
86
 
@@ -102,8 +104,8 @@ public class FormDeletedEvent {
102
104
 
103
105
  ## 常见坑
104
106
 
105
- | 场景 | 问题 | 正确做法 |
106
- |------|------|---------|
107
- | `instanceof` 分发 | Service 层用 `instanceof` 链判断所有子类型 | 优先在实体/领域模型中用多态 |
108
- | 控件能力硬编码 | 用 `if (control instanceof TextControl)` 判断是否支持某能力 | 基类加 `abstract boolean supportsXxx()`,子类按能力覆盖 |
109
- | 弃用 API | 编译出现 `@Deprecated` 警告但不处理 | 同一次 PR 中替换为新 API |
107
+ | 场景 | 问题 | 正确做法 |
108
+ | ----------------- | ----------------------------------------------------------- | ------------------------------------------------------- |
109
+ | `instanceof` 分发 | Service 层用 `instanceof` 链判断所有子类型 | 优先在实体/领域模型中用多态 |
110
+ | 控件能力硬编码 | 用 `if (control instanceof TextControl)` 判断是否支持某能力 | 基类加 `abstract boolean supportsXxx()`,子类按能力覆盖 |
111
+ | 弃用 API | 编译出现 `@Deprecated` 警告但不处理 | 同一次 PR 中替换为新 API |
@@ -22,10 +22,7 @@ export class UsersModule {}
22
22
 
23
23
  ```typescript
24
24
  // users.controller.ts
25
- import {
26
- Controller, Get, Post, Body, Param, Put, Delete,
27
- ParseIntPipe,
28
- } from '@nestjs/common';
25
+ import { Controller, Get, Post, Body, Param, Put, Delete, ParseIntPipe } from '@nestjs/common';
29
26
  import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
30
27
  import { UsersService } from './users.service';
31
28
  import { CreateUserDto } from './dto/create-user.dto';
@@ -57,10 +54,7 @@ export class UsersController {
57
54
 
58
55
  @Put(':id')
59
56
  @ApiOperation({ summary: '更新用户信息' })
60
- update(
61
- @Param('id', ParseIntPipe) id: number,
62
- @Body() updateUserDto: UpdateUserDto,
63
- ) {
57
+ update(@Param('id', ParseIntPipe) id: number, @Body() updateUserDto: UpdateUserDto) {
64
58
  return this.usersService.update(id, updateUserDto);
65
59
  }
66
60
 
@@ -3,6 +3,7 @@
3
3
  按需加载。仅当你需要编写对应组件类型时阅读相关章节。
4
4
 
5
5
  > 跨维度规范(适用所有后端代码):
6
+ >
6
7
  > - [API 规范](api-spec.md) — RESTful 命名、统一响应体、OpenAPI、版本策略
7
8
  > - [依赖管理规范](dependency-management.md) — 版本一致性、CVE
8
9
  > - [异常处理深度规范](exception-handling.md) — 异常层次、错误码、全局过滤
@@ -10,18 +11,18 @@
10
11
 
11
12
  ## 速查
12
13
 
13
- | 场景 | 决策 |
14
- | --- | --- |
15
- | 模块结构 | 每个业务模块一个 NestJS Module,独立 Controller/Service/DTO/Entity |
16
- | 依赖注入 | 构造函数注入,`@Injectable()` 装饰器,禁止 `@Inject()` 字段注入 |
17
- | 参数验证 | DTO 使用 `class-validator` 装饰器(`@IsNotEmpty`、`@IsString`) |
18
- | 响应格式 | 统一使用 Controller 返回值,禁止在 Service 中直接返回 Response 对象 |
19
- | 异步处理 | 所有数据库/IO 操作用 `async/await`,禁止裸 `.subscribe()` 或 `.then()` |
20
- | 配置管理 | 使用 `@nestjs/config` 的 `ConfigService`,禁止 `process.env` 直读(测试不可 mock) |
21
- | 异常处理 | 使用 NestJS 全局异常过滤器(`ExceptionFilter`),禁止在 Controller 中 try-catch 吞异常 |
22
- | 日志 | 使用 `@nestjs/common` 的 `Logger`,构造函数中注入:`private readonly logger = new Logger(XxxService.name)` |
23
- | 类型安全 | 禁止 `any` 类型,优先用 `unknown` + 类型守卫 |
24
- | 模块注册 | 动态模块用 `forRoot()/forFeature()` 模式,禁止在 Module 中直接 `new Provider()` |
14
+ | 场景 | 决策 |
15
+ | -------- | ---------------------------------------------------------------------------------------------------------- |
16
+ | 模块结构 | 每个业务模块一个 NestJS Module,独立 Controller/Service/DTO/Entity |
17
+ | 依赖注入 | 构造函数注入,`@Injectable()` 装饰器,禁止 `@Inject()` 字段注入 |
18
+ | 参数验证 | DTO 使用 `class-validator` 装饰器(`@IsNotEmpty`、`@IsString`) |
19
+ | 响应格式 | 统一使用 Controller 返回值,禁止在 Service 中直接返回 Response 对象 |
20
+ | 异步处理 | 所有数据库/IO 操作用 `async/await`,禁止裸 `.subscribe()` 或 `.then()` |
21
+ | 配置管理 | 使用 `@nestjs/config` 的 `ConfigService`,禁止 `process.env` 直读(测试不可 mock) |
22
+ | 异常处理 | 使用 NestJS 全局异常过滤器(`ExceptionFilter`),禁止在 Controller 中 try-catch 吞异常 |
23
+ | 日志 | 使用 `@nestjs/common` 的 `Logger`,构造函数中注入:`private readonly logger = new Logger(XxxService.name)` |
24
+ | 类型安全 | 禁止 `any` 类型,优先用 `unknown` + 类型守卫 |
25
+ | 模块注册 | 动态模块用 `forRoot()/forFeature()` 模式,禁止在 Module 中直接 `new Provider()` |
25
26
 
26
27
  ## 代码风格
27
28
 
@@ -37,13 +38,13 @@
37
38
 
38
39
  ### TypeScript Decorator 使用规范
39
40
 
40
- | 组件类型 | 必用装饰器 | 说明 |
41
- |---------|-----------|------|
42
- | Controller | `@Controller('prefix')`、`@Get()`/`@Post()`/`@Put()`/`@Delete()` | 路由定义 |
43
- | DTO | `@ApiProperty()`、`@IsString()`/`@IsNumber()`/`@IsOptional()` | 验证 + Swagger |
44
- | Service | `@Injectable()` | DI 可注入 |
45
- | Module | `@Module()` | NestJS 模块定义 |
46
- | Entity (Prisma) | 使用 Prisma Schema 定义,不额外装饰 | TypeScript 类型由 `prisma generate` 生成 |
41
+ | 组件类型 | 必用装饰器 | 说明 |
42
+ | --------------- | ---------------------------------------------------------------- | ---------------------------------------- |
43
+ | Controller | `@Controller('prefix')`、`@Get()`/`@Post()`/`@Put()`/`@Delete()` | 路由定义 |
44
+ | DTO | `@ApiProperty()`、`@IsString()`/`@IsNumber()`/`@IsOptional()` | 验证 + Swagger |
45
+ | Service | `@Injectable()` | DI 可注入 |
46
+ | Module | `@Module()` | NestJS 模块定义 |
47
+ | Entity (Prisma) | 使用 Prisma Schema 定义,不额外装饰 | TypeScript 类型由 `prisma generate` 生成 |
47
48
 
48
49
  ### 控件能力声明模式
49
50
 
@@ -59,22 +60,20 @@ export interface ToolCapability {
59
60
 
60
61
  // 注册 Provider
61
62
  @Module({
62
- providers: [
63
- { provide: 'TOOL_CAPABILITIES', useClass: TextToolCapability, multi: true },
64
- ],
63
+ providers: [{ provide: 'TOOL_CAPABILITIES', useClass: TextToolCapability, multi: true }],
65
64
  })
66
65
  export class ToolsModule {}
67
66
  ```
68
67
 
69
68
  ## 注释规则
70
69
 
71
- | 文件类型 | 注释要求 |
72
- |---------|---------|
73
- | **Entity / Prisma Schema** | Prisma Schema 中每个 model 加 `/// 注释`;生成类型不修改 |
74
- | **DTO** | 类 JSDoc `/** 用途说明 */`;字段装饰器自带文档(`@ApiProperty({ description: '...' })`) |
75
- | **Service** | 每个 public 方法加 JSDoc `/** 功能、@param、@returns */` |
76
- | **Controller** | 每个端点加 `@ApiOperation({ summary: '...', description: '...' })` |
77
- | **Module** | 类 JSDoc `/** 模块职责 */`;`@Module({})` 中 imports/providers/exports 按字母排序 |
70
+ | 文件类型 | 注释要求 |
71
+ | -------------------------- | ---------------------------------------------------------------------------------------- |
72
+ | **Entity / Prisma Schema** | Prisma Schema 中每个 model 加 `/// 注释`;生成类型不修改 |
73
+ | **DTO** | 类 JSDoc `/** 用途说明 */`;字段装饰器自带文档(`@ApiProperty({ description: '...' })`) |
74
+ | **Service** | 每个 public 方法加 JSDoc `/** 功能、@param、@returns */` |
75
+ | **Controller** | 每个端点加 `@ApiOperation({ summary: '...', description: '...' })` |
76
+ | **Module** | 类 JSDoc `/** 模块职责 */`;`@Module({})` 中 imports/providers/exports 按字母排序 |
78
77
 
79
78
  ## 项目目录结构
80
79
 
@@ -108,10 +107,10 @@ server/src/
108
107
 
109
108
  ## 常见坑
110
109
 
111
- | 场景 | 问题 | 正确做法 |
112
- |------|------|---------|
113
- | 循环依赖 | Module A imports Module B,Module B imports Module A | 用 `forwardRef(() => ModuleB)` |
114
- | 异步初始化 | Service 的 `constructor` 中 await Prisma 连接 | 实现 `OnModuleInit` 接口,在 `onModuleInit()` 中初始化 |
115
- | 环境变量直读 | `process.env.DB_URL` 在代码中硬编码 | 通过 `ConfigService.get('DB_URL')` 读取 |
116
- | DTO 缺少装饰器 | `class-validator` 装饰器缺失导致验证不生效 | 每个 DTO 字段同时加 `@ApiProperty()` 和验证装饰器 |
117
- | 事务边界 | 事务内调用外部 HTTP 服务 | Prisma `$transaction` 中禁止非数据库操作 |
110
+ | 场景 | 问题 | 正确做法 |
111
+ | -------------- | ---------------------------------------------------- | ------------------------------------------------------ |
112
+ | 循环依赖 | Module A imports Module B,Module B imports Module A | 用 `forwardRef(() => ModuleB)` |
113
+ | 异步初始化 | Service 的 `constructor` 中 await Prisma 连接 | 实现 `OnModuleInit` 接口,在 `onModuleInit()` 中初始化 |
114
+ | 环境变量直读 | `process.env.DB_URL` 在代码中硬编码 | 通过 `ConfigService.get('DB_URL')` 读取 |
115
+ | DTO 缺少装饰器 | `class-validator` 装饰器缺失导致验证不生效 | 每个 DTO 字段同时加 `@ApiProperty()` 和验证装饰器 |
116
+ | 事务边界 | 事务内调用外部 HTTP 服务 | Prisma `$transaction` 中禁止非数据库操作 |
@@ -5,6 +5,7 @@
5
5
  > 已安装子维度的规范,通过该维度的 `{value}.md` 文件阅读。本页只包含 Python 语言通用的核心规范。
6
6
  >
7
7
  > **跨维度规范(适用所有后端代码):**
8
+ >
8
9
  > - [API 规范](api-spec.md) — RESTful 命名、统一响应体、OpenAPI、版本策略
9
10
  > - [依赖管理规范](dependency-management.md) — pyproject.toml、版本声明、CVE
10
11
  > - [异常处理深度规范](exception-handling.md) — AppError 层次、错误码、全局处理
@@ -28,17 +29,17 @@ app/
28
29
 
29
30
  ## 速查
30
31
 
31
- | 场景 | 决策 |
32
- | --- | --- |
33
- | 字符串格式化 | 用 f-string(`f"Hello {name}"`),不用 `%` 或 `.format()` |
34
- | 类型分发 | 用多态 / Protocol,不用 `isinstance()` 链 |
35
- | 类型注释 | 都标注返回类型和参数类型(mypy 检查通过) |
36
- | 参数顺序 | 路由可见参数 → body → query → dependency |
37
- | 模块名 | snake_case,禁止驼峰 |
38
- | 弃用 API | mypy / ruff 警告中的废弃 API 在同一次 PR 中替换为新 API |
39
- | 类命名 | PascalCase(如 `UserService`、`CreateUserRequest`) |
40
- | 函数/变量命名 | snake_case(如 `get_user()`、`user_service`) |
41
- | 常量命名 | UPPER_SNAKE_CASE(如 `MAX_RETRY_COUNT`) |
32
+ | 场景 | 决策 |
33
+ | ------------- | ---------------------------------------------------------- |
34
+ | 字符串格式化 | 用 f-string(`f"Hello {name}"`),不用 `%` 或 `.format()` |
35
+ | 类型分发 | 用多态 / Protocol,不用 `isinstance()` 链 |
36
+ | 类型注释 | 都标注返回类型和参数类型(mypy 检查通过) |
37
+ | 参数顺序 | 路由可见参数 → body → query → dependency |
38
+ | 模块名 | snake_case,禁止驼峰 |
39
+ | 弃用 API | mypy / ruff 警告中的废弃 API 在同一次 PR 中替换为新 API |
40
+ | 类命名 | PascalCase(如 `UserService`、`CreateUserRequest`) |
41
+ | 函数/变量命名 | snake_case(如 `get_user()`、`user_service`) |
42
+ | 常量命名 | UPPER_SNAKE_CASE(如 `MAX_RETRY_COUNT`) |
42
43
 
43
44
  ## 代码风格
44
45
 
@@ -76,23 +77,23 @@ class NumberControl(FormControl):
76
77
 
77
78
  ## 注释规则
78
79
 
79
- | 文件类型 | 注释要求 |
80
- |---------|---------|
81
- | **Model (SQLAlchemy)** | 类 docstring 说明表含义;复杂字段用 `comment=` 行内注释 |
82
- | **Schema (Pydantic)** | 类 docstring 说明用途;关键字段用 `Field(description=...)` |
83
- | **Service** | public 函数加 docstring,说明功能、参数和返回值 |
84
- | **Router** | 每个端点加 `summary=`/`description=` 参数 |
85
- | **Migration** | 每个 revision 加 docstring 说明变更意图 |
80
+ | 文件类型 | 注释要求 |
81
+ | ---------------------- | ---------------------------------------------------------- |
82
+ | **Model (SQLAlchemy)** | 类 docstring 说明表含义;复杂字段用 `comment=` 行内注释 |
83
+ | **Schema (Pydantic)** | 类 docstring 说明用途;关键字段用 `Field(description=...)` |
84
+ | **Service** | public 函数加 docstring,说明功能、参数和返回值 |
85
+ | **Router** | 每个端点加 `summary=`/`description=` 参数 |
86
+ | **Migration** | 每个 revision 加 docstring 说明变更意图 |
86
87
 
87
88
  ## 类型注释规则
88
89
 
89
- | 声明位置 | 需要类型注释 |
90
- |---------|-------------|
91
- | 函数参数 | ✓ 是 |
92
- | 函数返回值 | ✓ 是(`-> None` 也必须标注) |
93
- | 模块级变量 | ✓ 是 |
94
- | 类属性 / Pydantic Field | ✓ 是 |
95
- | 循环变量 / 列表推导 | ✗ 否 |
90
+ | 声明位置 | 需要类型注释 |
91
+ | ----------------------- | ---------------------------- |
92
+ | 函数参数 | ✓ 是 |
93
+ | 函数返回值 | ✓ 是(`-> None` 也必须标注) |
94
+ | 模块级变量 | ✓ 是 |
95
+ | 类属性 / Pydantic Field | ✓ 是 |
96
+ | 循环变量 / 列表推导 | ✗ 否 |
96
97
 
97
98
  ## 错误处理模式
98
99
 
@@ -113,9 +114,9 @@ class UserNotFoundError(AppError):
113
114
 
114
115
  ## 常见坑
115
116
 
116
- | 场景 | 问题 | 正确做法 |
117
- |------|------|---------|
118
- | `isinstance()` 分发 | Service 层用 `isinstance()` 链判断所有子类型 | 优先在基类中用抽象方法 / Protocol |
119
- | 裸 `async` 阻塞 | `async` 函数内调了同步 IO 操作 | 用 `httpx.AsyncClient`、`asyncio.to_thread`、异步 ORM |
120
- | N+1 查询 | 循环内访问关联对象的属性,逐条 SELECT | 用 `selectinload()` / `joinedload()` 主动预加载 |
121
- | 类型不兼容 | mypy strict 模式通不过 | 所有函数标注类型,`None` 必须显式声明 |
117
+ | 场景 | 问题 | 正确做法 |
118
+ | ------------------- | -------------------------------------------- | ----------------------------------------------------- |
119
+ | `isinstance()` 分发 | Service 层用 `isinstance()` 链判断所有子类型 | 优先在基类中用抽象方法 / Protocol |
120
+ | 裸 `async` 阻塞 | `async` 函数内调了同步 IO 操作 | 用 `httpx.AsyncClient`、`asyncio.to_thread`、异步 ORM |
121
+ | N+1 查询 | 循环内访问关联对象的属性,逐条 SELECT | 用 `selectinload()` / `joinedload()` 主动预加载 |
122
+ | 类型不兼容 | mypy strict 模式通不过 | 所有函数标注类型,`None` 必须显式声明 |
@@ -34,9 +34,9 @@
34
34
  ```html
35
35
  <!-- 内边距 -->
36
36
  <div class="p-4 px-6 py-2 pt-0">
37
-
38
- <!-- 外边距 -->
39
- <div class="m-4 mt-2 mx-auto">
37
+ <!-- 外边距 -->
38
+ <div class="m-4 mt-2 mx-auto"></div>
39
+ </div>
40
40
  ```
41
41
 
42
42
  ### 颜色
@@ -44,27 +44,29 @@
44
44
  ```html
45
45
  <!-- 使用 Tailwind 色板 -->
46
46
  <div class="bg-blue-500 text-white hover:bg-blue-600">
47
- <button class="text-gray-700 border border-gray-300 rounded">
47
+ <button class="text-gray-700 border border-gray-300 rounded"></button>
48
+ </div>
48
49
  ```
49
50
 
50
51
  ### 圆角与阴影
51
52
 
52
53
  ```html
53
54
  <div class="rounded-lg shadow-sm">
54
- <button class="rounded-full shadow-md">
55
+ <button class="rounded-full shadow-md"></button>
56
+ </div>
55
57
  ```
56
58
 
57
59
  ### 暗色模式
58
60
 
59
61
  ```html
60
- <div class="bg-white dark:bg-gray-900 text-black dark:text-white">
62
+ <div class="bg-white dark:bg-gray-900 text-black dark:text-white"></div>
61
63
  ```
62
64
 
63
65
  ## 自定义配置
64
66
 
65
67
  ```css
66
68
  /* app.css — 仅添加 Tailwind 不支持的全局样式 */
67
- @import "tailwindcss";
69
+ @import 'tailwindcss';
68
70
 
69
71
  @theme {
70
72
  --color-primary: #3b82f6;
@@ -38,7 +38,7 @@ describe('FormService', () => {
38
38
  });
39
39
 
40
40
  it('should GET forms', () => {
41
- service.list(1).subscribe(res => expect(res.items.length).toBe(2));
41
+ service.list(1).subscribe((res) => expect(res.items.length).toBe(2));
42
42
  const req = httpMock.expectOne('/api/v1/apps/1/forms');
43
43
  expect(req.request.method).toBe('GET');
44
44
  req.flush({ items: [{ id: 1 }, { id: 2 }], totalItems: 2 });
@@ -97,7 +97,10 @@ describe('ButtonComponent', () => {
97
97
  describe('UserListComponent(异步加载)', () => {
98
98
  it('加载完成后应显示用户列表', async () => {
99
99
  const mockService = {
100
- getUsers: vi.fn().mockResolvedValue([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]),
100
+ getUsers: vi.fn().mockResolvedValue([
101
+ { id: 1, name: 'Alice' },
102
+ { id: 2, name: 'Bob' },
103
+ ]),
101
104
  };
102
105
  await render(UserListComponent, {
103
106
  componentProviders: [{ provide: UserService, useValue: mockService }],
@@ -108,7 +111,9 @@ describe('UserListComponent(异步加载)', () => {
108
111
 
109
112
  it('加载失败时应显示错误提示', async () => {
110
113
  await render(UserListComponent, {
111
- componentProviders: [{ provide: UserService, useValue: { getUsers: vi.fn().mockRejectedValue(new Error('fail')) } }],
114
+ componentProviders: [
115
+ { provide: UserService, useValue: { getUsers: vi.fn().mockRejectedValue(new Error('fail')) } },
116
+ ],
112
117
  });
113
118
  expect(await screen.findByText(/加载失败/i)).toBeTruthy();
114
119
  });
@@ -130,7 +135,7 @@ describe('UserService(httpResource)', () => {
130
135
 
131
136
  it('应发送带 appId 的 GET 请求', () => {
132
137
  const httpMock = TestBed.inject(HttpTestingController);
133
- service.getUsers(1).subscribe(res => expect(res.items.length).toBe(1));
138
+ service.getUsers(1).subscribe((res) => expect(res.items.length).toBe(1));
134
139
  const req = httpMock.expectOne('/api/v1/apps/1/users');
135
140
  expect(req.request.method).toBe('GET');
136
141
  req.flush({ items: [{ id: 1, name: 'Alice' }], totalItems: 1 });
@@ -22,10 +22,10 @@ import { render, screen, fireEvent } from '@testing-library/angular';
22
22
 
23
23
  ## 测试类型
24
24
 
25
- | 测试类型 | 范围 | 工具 | 关键关注点 |
26
- |---------|------|------|-----------|
27
- | 单元测试 | 单个函数/方法 | Vitest | 逻辑正确性、边界条件 |
28
- | 组件测试 | 单个组件 | Testing Library | 渲染、交互、事件 |
25
+ | 测试类型 | 范围 | 工具 | 关键关注点 |
26
+ | -------- | ------------- | --------------- | -------------------- |
27
+ | 单元测试 | 单个函数/方法 | Vitest | 逻辑正确性、边界条件 |
28
+ | 组件测试 | 单个组件 | Testing Library | 渲染、交互、事件 |
29
29
 
30
30
  ## 基本模式
31
31