@deepstorm/cli 0.9.3 → 0.10.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.
@@ -104,7 +104,7 @@
104
104
  "buildTool": "pnpm:*",
105
105
  "formatCmd": "pnpm",
106
106
  "fileExt": "*.component.ts / *.service.ts / *.ts",
107
- "sourcePath": "src/main/web/",
107
+ "sourcePath": "client/src/",
108
108
  "styleRef": "→ 参考 [Angular 前端速查](quick-reference.md)"
109
109
  },
110
110
  "affectedTemplates": [
@@ -355,6 +355,9 @@
355
355
  "sourcePath": "src/main/java/ src/test/java/",
356
356
  "styleRef": "→ 参考 [Java 后端速查](quick-reference.md)"
357
357
  },
358
+ "availableAiFrameworks": [
359
+ "spring-ai"
360
+ ],
358
361
  "affectedTemplates": [
359
362
  "skills/reef-style-backend/SKILL.md.tmpl",
360
363
  "agents/reef-review-backend.md.tmpl",
@@ -380,6 +383,7 @@
380
383
  "styleRef": "→ 参考 [Python FastAPI 后瑞速查](quick-reference.md)",
381
384
  "isPython": "true"
382
385
  },
386
+ "availableAiFrameworks": [],
383
387
  "affectedTemplates": [
384
388
  "skills/reef-style-backend/SKILL.md.tmpl",
385
389
  "agents/reef-review-backend.md.tmpl",
@@ -393,6 +397,33 @@
393
397
  "python/security-redlines"
394
398
  ]
395
399
  },
400
+ {
401
+ "value": "nodejs",
402
+ "label": "Node.js / NestJS",
403
+ "template": {
404
+ "label": "NestJS + TypeScript + Prisma",
405
+ "buildTool": "pnpm:*",
406
+ "formatCmd": "npx eslint",
407
+ "fileExt": "*.ts",
408
+ "sourcePath": "server/src/ server/test/",
409
+ "styleRef": "→ 参考 [Node.js NestJS 后端速查](quick-reference.md)"
410
+ },
411
+ "availableAiFrameworks": [
412
+ "claude-agent-sdk"
413
+ ],
414
+ "affectedTemplates": [
415
+ "skills/reef-style-backend/SKILL.md.tmpl",
416
+ "agents/reef-review-backend.md.tmpl",
417
+ "skills/reef-review/SKILL.md.tmpl",
418
+ "skills/reef-gen-backend/SKILL.md.tmpl"
419
+ ],
420
+ "fragments": [
421
+ "nodejs/api-spec",
422
+ "nodejs/dependency-management",
423
+ "nodejs/exception-handling",
424
+ "nodejs/security-redlines"
425
+ ]
426
+ },
396
427
  {
397
428
  "value": "none",
398
429
  "label": "不使用后端",
@@ -790,6 +821,143 @@
790
821
  }
791
822
  ]
792
823
  },
824
+ {
825
+ "key": "reef.backend.nodejs.details",
826
+ "label": "Node.js 框架选型",
827
+ "description": "选择需要使用的 Node.js 框架和技术",
828
+ "type": "group",
829
+ "dependsOn": {
830
+ "key": "reef.backend.language",
831
+ "value": "nodejs"
832
+ },
833
+ "questions": [
834
+ {
835
+ "key": "reef.backend.nodejs.framework",
836
+ "label": "Web 框架",
837
+ "type": "select",
838
+ "options": [
839
+ {
840
+ "value": "nestjs",
841
+ "label": "NestJS",
842
+ "template": {
843
+ "styleRef": "→ 参考 [NestJS 后端速查](quick-reference.md)"
844
+ },
845
+ "affectedTemplates": [
846
+ "skills/reef-style-backend/SKILL.md.tmpl"
847
+ ],
848
+ "fragments": [
849
+ "nodejs/framework/nestjs"
850
+ ]
851
+ },
852
+ {
853
+ "value": "none",
854
+ "label": "不使用",
855
+ "template": {},
856
+ "affectedTemplates": [
857
+ "skills/reef-style-backend/SKILL.md.tmpl"
858
+ ]
859
+ }
860
+ ]
861
+ },
862
+ {
863
+ "key": "reef.backend.nodejs.orm",
864
+ "label": "ORM",
865
+ "type": "select",
866
+ "options": [
867
+ {
868
+ "value": "prisma",
869
+ "label": "Prisma",
870
+ "template": {
871
+ "styleRef": "→ 参考 [Prisma 规范](prisma.md)"
872
+ },
873
+ "affectedTemplates": [
874
+ "skills/reef-style-backend/SKILL.md.tmpl"
875
+ ],
876
+ "fragments": [
877
+ "nodejs/orm/prisma"
878
+ ]
879
+ },
880
+ {
881
+ "value": "none",
882
+ "label": "不使用",
883
+ "template": {},
884
+ "affectedTemplates": [
885
+ "skills/reef-style-backend/SKILL.md.tmpl"
886
+ ]
887
+ }
888
+ ]
889
+ },
890
+ {
891
+ "key": "reef.backend.nodejs.ai",
892
+ "label": "AI 集成",
893
+ "type": "select",
894
+ "options": [
895
+ {
896
+ "value": "claude-agent-sdk",
897
+ "label": "Claude Agent SDK",
898
+ "template": {
899
+ "styleRef": "→ 参考 [Claude Agent SDK 规范](claude-agent-sdk.md)"
900
+ },
901
+ "affectedTemplates": [
902
+ "skills/reef-style-backend/SKILL.md.tmpl"
903
+ ],
904
+ "fragments": [
905
+ "nodejs/ai/claude-agent-sdk"
906
+ ]
907
+ },
908
+ {
909
+ "value": "none",
910
+ "label": "不使用",
911
+ "template": {},
912
+ "affectedTemplates": [
913
+ "skills/reef-style-backend/SKILL.md.tmpl"
914
+ ]
915
+ }
916
+ ]
917
+ },
918
+ {
919
+ "key": "reef.backend.nodejs.test",
920
+ "label": "单元测试",
921
+ "type": "select",
922
+ "options": [
923
+ {
924
+ "value": "jest",
925
+ "label": "Jest",
926
+ "template": {
927
+ "styleRef": "→ 参考 [Jest 规范](jest-testing.md)"
928
+ },
929
+ "affectedTemplates": [
930
+ "skills/reef-style-backend/SKILL.md.tmpl"
931
+ ],
932
+ "fragments": [
933
+ "nodejs/test/jest"
934
+ ]
935
+ },
936
+ {
937
+ "value": "vitest",
938
+ "label": "Vitest",
939
+ "template": {
940
+ "styleRef": "→ 参考 [Vitest 规范](vitest-testing.md)"
941
+ },
942
+ "affectedTemplates": [
943
+ "skills/reef-style-backend/SKILL.md.tmpl"
944
+ ],
945
+ "fragments": [
946
+ "nodejs/test/vitest"
947
+ ]
948
+ },
949
+ {
950
+ "value": "none",
951
+ "label": "不使用",
952
+ "template": {},
953
+ "affectedTemplates": [
954
+ "skills/reef-style-backend/SKILL.md.tmpl"
955
+ ]
956
+ }
957
+ ]
958
+ }
959
+ ]
960
+ },
793
961
  {
794
962
  "key": "reef.formatter",
795
963
  "label": "格式化增强配置",
@@ -0,0 +1,53 @@
1
+ # Node.js / NestJS 后端编码步骤
2
+
3
+ 按以下顺序逐块编写,依赖关系由前向后:
4
+
5
+ 1. **Prisma Schema** — 定义数据模型(`prisma/schema.prisma`),**先于所有代码**,因为它决定类型结构
6
+ 2. **DTO** — 数据传输对象(请求/响应),使用 `class-validator` + `@nestjs/swagger` 装饰器
7
+ 3. **Entity** — Prisma 生成的 TypeScript 类型,必要时封装为 Entity 类(可选)
8
+ 4. **PrismaService** — 数据库访问服务(`PrismaModule` + `PrismaService`),如果尚未创建
9
+ 5. **Service** — 业务逻辑层,依赖 `PrismaService`,事务处理
10
+ 6. **Controller** — REST API,请求/响应,参数校验
11
+ 7. **Module** — NestJS 模块,将 Controller/Service 注册到 DI 容器
12
+
13
+ 每完成一块对照 `reef:reef-style-backend` 中对应章节检查。
14
+
15
+ ## 注释要求
16
+
17
+ 每类文件必须包含以下注释(缺少则视为未完成):
18
+
19
+ | 文件类型 | 注释要求 |
20
+ |---------|---------|
21
+ | **Prisma Schema** | 每个 model 加 `/// 注释` 描述实体用途;每个字段加 `/// 注释` |
22
+ | **DTO** | 类 JSDoc `/** 用途说明 */`;字段通过 `@ApiProperty({ description: '...' })` 提供文档 |
23
+ | **Service** | 每个 public 方法加 JSDoc `/** 功能、@param、@returns */`;复杂逻辑内联注释说明 |
24
+ | **Controller** | 每个端点加 `@ApiOperation({ summary: '...', description: '...' })` |
25
+ | **Module** | 类 JSDoc `/** 模块职责 */` |
26
+
27
+ ## 安全红线
28
+
29
+ - 所有环境变量通过 `ConfigService` 读取,禁止 `process.env` 直读
30
+ - 敏感字段(密码、Token)在 API 响应前使用 `select` 或 `@Exclude()` 排除
31
+ - 禁止在 TypeScript 代码中硬编码 API Key / Token
32
+ - Prisma 条件查询使用参数化查询(Prisma 默认安全),禁止手动拼接 `where` 条件
33
+ - API 端点需添加 `@ApiBearerAuth()` 和 `@UseGuards(AuthGuard())`
34
+
35
+ ## 构建命令
36
+
37
+ ```bash
38
+ # 依赖安装(在项目根目录执行)
39
+ pnpm install
40
+
41
+ # Prisma 客户端生成(在 server/ 目录执行)
42
+ cd server && npx prisma generate
43
+
44
+ # 代码检查
45
+ cd server && npx eslint src/ --ext .ts
46
+ cd server && npx prettier --check src/
47
+
48
+ # 测试
49
+ cd server && npx jest
50
+
51
+ # 构建
52
+ cd server && npx nest build
53
+ ```
@@ -0,0 +1,30 @@
1
+ {
2
+ "root": true,
3
+ "env": {
4
+ "node": true,
5
+ "jest": true
6
+ },
7
+ "parser": "@typescript-eslint/parser",
8
+ "parserOptions": {
9
+ "project": "tsconfig.json",
10
+ "sourceType": "module"
11
+ },
12
+ "plugins": ["@typescript-eslint/eslint-plugin"],
13
+ "extends": [
14
+ "plugin:@typescript-eslint/recommended",
15
+ "plugin:prettier/recommended"
16
+ ],
17
+ "rules": {
18
+ "@typescript-eslint/no-explicit-any": "error",
19
+ "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
20
+ "@typescript-eslint/explicit-function-return-type": "off",
21
+ "@typescript-eslint/explicit-module-boundary-types": "off",
22
+ "no-console": "warn",
23
+ "prefer-const": "error",
24
+ "no-var": "error",
25
+ "eqeqeq": ["error", "always"],
26
+ "curly": ["error", "all"],
27
+ "no-throw-literal": "error",
28
+ "prefer-promise-reject-errors": "error"
29
+ }
30
+ }
@@ -0,0 +1,58 @@
1
+ # NestJS 项目结构规范
2
+
3
+ ## 顶层目录
4
+
5
+ ```
6
+ src/
7
+ ├── main.ts # 入口(Bootstrap)
8
+ ├── app.module.ts # 根模块
9
+ ├── app.controller.ts # 健康检查
10
+ └── app.service.ts # 全局服务
11
+ ```
12
+
13
+ ## 模块目录规范
14
+
15
+ ```
16
+ src/modules/{module-name}/
17
+ ├── {module-name}.module.ts # Module 定义
18
+ ├── {module-name}.controller.ts # REST Controller
19
+ ├── {module-name}.service.ts # 业务逻辑
20
+ ├── dto/
21
+ │ ├── create-{entity}.dto.ts # 创建 DTO
22
+ │ └── update-{entity}.dto.ts # 更新 DTO(PartialType)
23
+ └── entities/
24
+ └── {entity}.entity.ts # Prisma 封装类型(可选)
25
+ ```
26
+
27
+ ## 公共目录
28
+
29
+ ```
30
+ src/
31
+ ├── prisma/
32
+ │ ├── prisma.module.ts
33
+ │ └── prisma.service.ts
34
+ ├── common/
35
+ │ ├── filters/
36
+ │ │ └── http-exception.filter.ts
37
+ │ ├── pipes/
38
+ │ │ └── validation.pipe.ts
39
+ │ ├── interceptors/
40
+ │ │ ├── transform.interceptor.ts
41
+ │ │ └── logging.interceptor.ts
42
+ │ └── guards/
43
+ │ └── auth.guard.ts
44
+ └── config/
45
+ └── configuration.ts
46
+ ```
47
+
48
+ ## 命名规范
49
+
50
+ | 类型 | 命名规则 | 示例 |
51
+ |------|---------|------|
52
+ | Module 类 | PascalCase + Module | `UsersModule` |
53
+ | Controller 类 | PascalCase + Controller | `UsersController` |
54
+ | Service 类 | PascalCase + Service | `UsersService` |
55
+ | DTO 类 | PascalCase + Dto | `CreateUserDto` |
56
+ | Module 目录 | kebab-case | `src/modules/user-roles/` |
57
+ | DTO 文件 | kebab-case | `create-user-role.dto.ts` |
58
+ | 配置键 | UPPER_SNAKE_CASE | `DATABASE_URL` |
@@ -0,0 +1,19 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "trailingComma": "all",
6
+ "printWidth": 100,
7
+ "bracketSpacing": true,
8
+ "arrowParens": "always",
9
+ "endOfLine": "lf",
10
+ "quoteProps": "as-needed",
11
+ "overrides": [
12
+ {
13
+ "files": "*.prisma",
14
+ "options": {
15
+ "tabWidth": 2
16
+ }
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,166 @@
1
+ # NestJS Module 示例 — Users 模块
2
+
3
+ ```typescript
4
+ // users.module.ts
5
+ import { Module } from '@nestjs/common';
6
+ import { UsersController } from './users.controller';
7
+ import { UsersService } from './users.service';
8
+ import { PrismaModule } from '../prisma/prisma.module';
9
+
10
+ /**
11
+ * 用户管理模块
12
+ * 提供用户 CRUD 操作和权限管理
13
+ */
14
+ @Module({
15
+ imports: [PrismaModule],
16
+ controllers: [UsersController],
17
+ providers: [UsersService],
18
+ exports: [UsersService],
19
+ })
20
+ export class UsersModule {}
21
+ ```
22
+
23
+ ```typescript
24
+ // users.controller.ts
25
+ import {
26
+ Controller, Get, Post, Body, Param, Put, Delete,
27
+ ParseIntPipe,
28
+ } from '@nestjs/common';
29
+ import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
30
+ import { UsersService } from './users.service';
31
+ import { CreateUserDto } from './dto/create-user.dto';
32
+ import { UpdateUserDto } from './dto/update-user.dto';
33
+
34
+ @ApiTags('Users')
35
+ @Controller('users')
36
+ @ApiBearerAuth()
37
+ export class UsersController {
38
+ constructor(private readonly usersService: UsersService) {}
39
+
40
+ @Post()
41
+ @ApiOperation({ summary: '创建用户', description: '创建一个新的系统用户' })
42
+ create(@Body() createUserDto: CreateUserDto) {
43
+ return this.usersService.create(createUserDto);
44
+ }
45
+
46
+ @Get()
47
+ @ApiOperation({ summary: '查询用户列表' })
48
+ findAll() {
49
+ return this.usersService.findAll();
50
+ }
51
+
52
+ @Get(':id')
53
+ @ApiOperation({ summary: '查询单个用户' })
54
+ findOne(@Param('id', ParseIntPipe) id: number) {
55
+ return this.usersService.findOne(id);
56
+ }
57
+
58
+ @Put(':id')
59
+ @ApiOperation({ summary: '更新用户信息' })
60
+ update(
61
+ @Param('id', ParseIntPipe) id: number,
62
+ @Body() updateUserDto: UpdateUserDto,
63
+ ) {
64
+ return this.usersService.update(id, updateUserDto);
65
+ }
66
+
67
+ @Delete(':id')
68
+ @ApiOperation({ summary: '删除用户' })
69
+ remove(@Param('id', ParseIntPipe) id: number) {
70
+ return this.usersService.remove(id);
71
+ }
72
+ }
73
+ ```
74
+
75
+ ```typescript
76
+ // users.service.ts
77
+ import { Injectable, Logger, NotFoundException } from '@nestjs/common';
78
+ import { PrismaService } from '../prisma/prisma.service';
79
+ import { CreateUserDto } from './dto/create-user.dto';
80
+ import { UpdateUserDto } from './dto/update-user.dto';
81
+
82
+ @Injectable()
83
+ export class UsersService {
84
+ private readonly logger = new Logger(UsersService.name);
85
+
86
+ constructor(private readonly prisma: PrismaService) {}
87
+
88
+ /**
89
+ * 创建用户
90
+ * @param createUserDto 用户创建参数
91
+ * @returns 创建的用户记录
92
+ */
93
+ async create(createUserDto: CreateUserDto) {
94
+ return this.prisma.user.create({ data: createUserDto });
95
+ }
96
+
97
+ /** 查询所有用户 */
98
+ async findAll() {
99
+ return this.prisma.user.findMany();
100
+ }
101
+
102
+ /**
103
+ * 根据 ID 查询用户
104
+ * @param id 用户 ID
105
+ * @throws NotFoundException 用户不存在
106
+ */
107
+ async findOne(id: number) {
108
+ const user = await this.prisma.user.findUnique({ where: { id } });
109
+ if (!user) throw new NotFoundException(`User #${id} not found`);
110
+ return user;
111
+ }
112
+
113
+ /**
114
+ * 更新用户信息
115
+ * @param id 用户 ID
116
+ * @param updateUserDto 更新参数
117
+ */
118
+ async update(id: number, updateUserDto: UpdateUserDto) {
119
+ await this.findOne(id);
120
+ return this.prisma.user.update({
121
+ where: { id },
122
+ data: updateUserDto,
123
+ });
124
+ }
125
+
126
+ /**
127
+ * 删除用户
128
+ * @param id 用户 ID
129
+ */
130
+ async remove(id: number) {
131
+ await this.findOne(id);
132
+ return this.prisma.user.delete({ where: { id } });
133
+ }
134
+ }
135
+ ```
136
+
137
+ ```typescript
138
+ // dto/create-user.dto.ts
139
+ import { ApiProperty } from '@nestjs/swagger';
140
+ import { IsString, IsEmail, IsOptional, IsBoolean } from 'class-validator';
141
+
142
+ /** 创建用户请求 DTO */
143
+ export class CreateUserDto {
144
+ @ApiProperty({ description: '用户名', example: 'john_doe' })
145
+ @IsString()
146
+ name!: string;
147
+
148
+ @ApiProperty({ description: '邮箱地址', example: 'john@example.com' })
149
+ @IsEmail()
150
+ email!: string;
151
+
152
+ @ApiProperty({ description: '是否激活', required: false, default: true })
153
+ @IsOptional()
154
+ @IsBoolean()
155
+ active?: boolean;
156
+ }
157
+ ```
158
+
159
+ ```typescript
160
+ // dto/update-user.dto.ts
161
+ import { PartialType } from '@nestjs/swagger';
162
+ import { CreateUserDto } from './create-user.dto';
163
+
164
+ /** 更新用户请求 DTO — 所有字段可选 */
165
+ export class UpdateUserDto extends PartialType(CreateUserDto) {}
166
+ ```
@@ -0,0 +1,115 @@
1
+ # Prisma Service 与 Schema 示例
2
+
3
+ ## Prisma Schema
4
+
5
+ ```prisma
6
+ // prisma/schema.prisma
7
+
8
+ generator client {
9
+ provider = "prisma-client-js"
10
+ }
11
+
12
+ datasource db {
13
+ provider = "postgresql"
14
+ url = env("DATABASE_URL")
15
+ }
16
+
17
+ /// 系统用户
18
+ model User {
19
+ id Int @id @default(autoincrement())
20
+ name String
21
+ email String @unique
22
+ active Boolean @default(true)
23
+ posts Post[]
24
+ createdAt DateTime @default(now())
25
+ updatedAt DateTime @updatedAt
26
+
27
+ @@map("users")
28
+ }
29
+
30
+ /// 文章
31
+ model Post {
32
+ id Int @id @default(autoincrement())
33
+ title String
34
+ content String
35
+ published Boolean @default(false)
36
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
37
+ authorId Int
38
+ createdAt DateTime @default(now())
39
+ updatedAt DateTime @updatedAt
40
+
41
+ @@map("posts")
42
+ }
43
+ ```
44
+
45
+ ## Prisma Module & Service
46
+
47
+ ```typescript
48
+ // prisma/prisma.module.ts
49
+ import { Global, Module } from '@nestjs/common';
50
+ import { PrismaService } from './prisma.service';
51
+
52
+ /**
53
+ * Prisma 全局模块
54
+ * 作为 Global 模块,所有其他模块无需 imports 即可注入 PrismaService
55
+ */
56
+ @Global()
57
+ @Module({
58
+ providers: [PrismaService],
59
+ exports: [PrismaService],
60
+ })
61
+ export class PrismaModule {}
62
+ ```
63
+
64
+ ```typescript
65
+ // prisma/prisma.service.ts
66
+ import { Injectable, Logger, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
67
+ import { PrismaClient } from '@prisma/client';
68
+
69
+ /**
70
+ * Prisma 数据库服务
71
+ * 封装 PrismaClient,提供数据库连接生命周期管理
72
+ */
73
+ @Injectable()
74
+ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
75
+ private readonly logger = new Logger(PrismaService.name);
76
+
77
+ async onModuleInit() {
78
+ await this.$connect();
79
+ this.logger.log('Database connected');
80
+ }
81
+
82
+ async onModuleDestroy() {
83
+ await this.$disconnect();
84
+ this.logger.log('Database disconnected');
85
+ }
86
+ }
87
+ ```
88
+
89
+ ## Prisma 查询最佳实践
90
+
91
+ ```typescript
92
+ // 使用事务:多个原子操作
93
+ const [user, post] = await this.prisma.$transaction([
94
+ this.prisma.user.create({ data: { name: 'Alice', email: 'alice@test.com' } }),
95
+ this.prisma.post.create({ data: { title: 'Hello', content: 'World', authorId: 1 } }),
96
+ ]);
97
+
98
+ // 使用 select 限制返回字段,避免 N+1
99
+ const users = await this.prisma.user.findMany({
100
+ select: {
101
+ id: true,
102
+ name: true,
103
+ email: true,
104
+ posts: {
105
+ select: { title: true, published: true },
106
+ where: { published: true },
107
+ },
108
+ },
109
+ });
110
+
111
+ // 使用 findFirstOrThrow 简化判空
112
+ const user = await this.prisma.user.findFirstOrThrow({
113
+ where: { email: 'alice@test.com' },
114
+ });
115
+ ```