Compare commits
20 Commits
3caee6c45b
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f4d8dd91b4 | |||
| 8ac6f10679 | |||
| 33fe74cb35 | |||
| 1e365bd99e | |||
| 3ed06a5e6d | |||
| ed66b1b256 | |||
| f34b31f542 | |||
| dae54e90b6 | |||
| fc6a0174b9 | |||
| 041b02c793 | |||
| 89cc7d9152 | |||
| 6a5006077b | |||
| ea4f4d41c8 | |||
| fb3962accd | |||
| f6f87e0c47 | |||
| 74e796fe61 | |||
| a6ee653388 | |||
| 1f2abc7507 | |||
| 30ec00df9e | |||
| 01049bc24a |
@@ -1,3 +1,166 @@
|
||||
# Review Spec
|
||||
# Code Spec
|
||||
|
||||
该仓库是小管家代码规范仓库,规范是基于 Gitea Flows Review Spec 协议编写。
|
||||
该仓库是小管家代码规范仓库,规范基于 spaceflow [Review Spec](https://lydanne.github.io/spaceflow/reference/review-spec.html) 协议编写。
|
||||
|
||||
|
||||
## 目标
|
||||
|
||||
- 统一 JS/TS、NestJS、Mongoose Model、Vue 的代码风格与结构约束。
|
||||
- 提供可执行、可审查、可扩展的规则定义(含规则 ID、Good/Bad 示例、覆盖关系)。
|
||||
- 为自动化 Review 与人工 Code Review 提供统一判断标准。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```txt
|
||||
.
|
||||
├── README.md
|
||||
└── references/
|
||||
├── js&ts.base.md
|
||||
├── js&ts.file-name.md
|
||||
├── js&ts.nest.md
|
||||
├── js&ts.test-code.md
|
||||
├── js.models.md
|
||||
├── vue.base.md
|
||||
└── vue.file-name.md
|
||||
```
|
||||
|
||||
## 接入步骤(`.spaceflowrc`)
|
||||
|
||||
1. 在业务仓库根目录创建或修改 `.spaceflowrc`。
|
||||
2. 在 `review.references` 中引入本仓库 `references` 地址。
|
||||
3. 根据项目需要配置 `includes`、注释策略和重试策略。
|
||||
|
||||
```json
|
||||
{
|
||||
"review": {
|
||||
"references": ["https://git.bjxgj.com/xgj-pub/code-spec/src/branch/main/references"],
|
||||
"includes": [
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"!nest-src/errcode.ts",
|
||||
"!nest-src/libs/entity/**",
|
||||
"!**/dist/**",
|
||||
"!**/*.spec.*",
|
||||
"!**/*.config.*"
|
||||
],
|
||||
"generateDescription": true,
|
||||
"lineComments": true,
|
||||
"verifyFixes": true,
|
||||
"autoUpdatePrTitle": true,
|
||||
"analyzeDeletions": false,
|
||||
"deletionAnalysisMode": "open-code",
|
||||
"concurrency": 1,
|
||||
"retries": 3,
|
||||
"retryDelay": 1000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 说明:如果你的 `.spaceflowrc` 已有其他配置,请仅合并 `review` 字段,不要覆盖现有配置。
|
||||
|
||||
### MCP 配置(spaceflow)
|
||||
|
||||
如果你需要在支持 MCP 的客户端中接入 spaceflow,可加入以下配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"spaceflow": {
|
||||
"args": [
|
||||
"-y",
|
||||
"@spaceflow/cli",
|
||||
"mcp"
|
||||
],
|
||||
"command": "npx",
|
||||
"disabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
然后我们就可以使用这样的提示词让AI去拉规则了.
|
||||
|
||||
```
|
||||
请使用 spaceflow 工具去 review 代码。
|
||||
```
|
||||
|
||||
## 规范索引
|
||||
|
||||
| 规范集 | 规则 ID 前缀 | 作用范围(includes) | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| JS/TS 基础规范 | `JsTs.Base` | 通用 JS/TS 文件 | 命名、复杂度、行数、魔法值等基础约束 |
|
||||
| JS/TS 文件命名规范 | `JsTs.FileName` | 通用 JS/TS 文件 | class/interface 与函数文件命名规则 |
|
||||
| NestJS 规范 | `JsTs.Nest` | `*.controller.ts` `*.service.ts` `*.module.ts` `*.dto.ts` `*.pipe.ts` `*.guard.ts` `*.interceptor.ts` `*.filter.ts` `*.exception-filter.ts` `*.proxy.ts` `*.model.ts` | 目录结构、分层职责、文件命名与模块组织 |
|
||||
| 测试代码规范 | `JsTs.TestCode` | 测试文件(`.test.js` `.test.ts` `.spec.ts`) | 测试文件命名与 `describe/it` 结构约束 |
|
||||
| Mongoose Model 规范 | `Js.Model` | `*/models/*.js` | schema 字段、索引、钩子、方法、引用关系等 |
|
||||
| Vue 基础规范 | `Vue.Base` | `*.vue` | 自定义组件命名规范 |
|
||||
| Vue 文件命名规范 | `Vue.FileName` | `*.vue` | 组件文件命名规范 |
|
||||
|
||||
## 规则明细图表
|
||||
|
||||
| 规范集 | 规则 ID | 规则说明 | 文档 |
|
||||
| --- | --- | --- | --- |
|
||||
| JsTs.Base | `JsTs.Base.ConstUpperCase` | 常量名使用大写加下划线命名(UPPER_CASE),单词间以下划线分隔 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.FuncLowerCamel` | 函数名使用小驼峰命名 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.NoMagicVar` | 禁止使用字面量魔法数字 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.ConstantsDefinition` | 基于 JsTs.Base.NoMagicVar 抽离的静态常量需要放在对应文件里 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.ClassNaming` | class 和 interface 命名使用大驼峰命名 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.VarNaming` | 变量名使用小驼峰或者蛇形命名 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.CodeNotMoreThan700Lines` | 单文件代码不超过 700 行 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.FuncNotMoreThan200Lines` | 单个函数或方法不能超出 200 行 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.ComplexLogic` | 复杂的逻辑判断要添加注释 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.Base | `JsTs.Base.ComplexFunc` | 复杂的函数要添加注释 | [js&ts.base.md](references/js&ts.base.md) |
|
||||
| JsTs.FileName | `JsTs.FileName.UpperCamel` | class 和 interface 文件使用大驼峰命名 | [js&ts.file-name.md](references/js&ts.file-name.md) |
|
||||
| JsTs.FileName | `JsTs.FileName.LowerCamel` | 函数文件使用小驼峰命名 | [js&ts.file-name.md](references/js&ts.file-name.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.DirStructure` | 目录框架规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.ControllerDefinition` | 控制器命名规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.ServiceDefinition` | 服务命名规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.ModuleDefinition` | 模块命名规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.DtoDefinition` | Dto 命名规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.ProxyDefinition` | Proxy 编写规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.ModelDefinition` | Model 编写规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.BusinessDefinition` | 业务代码编写规范 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.Nest | `JsTs.Nest.ConstantsDefinition` | 基于 JsTs.Base.NoMagicStringsAndNumbers 抽离的静态常量需要放在对应文件里 | [js&ts.nest.md](references/js&ts.nest.md) |
|
||||
| JsTs.TestCode | `JsTs.TestCode.FileName` | 测试文件命名 | [js&ts.test-code.md](references/js&ts.test-code.md) |
|
||||
| JsTs.TestCode | `JsTs.TestCode.BlockName` | 测试代码块命名 | [js&ts.test-code.md](references/js&ts.test-code.md) |
|
||||
| Js.Model | `Js.Model.FileName` | 模型文件命名规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.FieldName` | Schema 字段命名规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.SchemaDefinition` | Schema 定义规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.IndexDefinition` | 索引定义规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.VirtualField` | 虚拟字段规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.Middleware` | 中间件/钩子规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.StaticMethod` | 静态方法规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.InstanceMethod` | 实例方法规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.Reference` | 关联引用规范 | [js.models.md](references/js.models.md) |
|
||||
| Js.Model | `Js.Model.FieldType` | 必须写明字段的类型 | [js.models.md](references/js.models.md) |
|
||||
| Vue.Base | `Vue.Base.CustomComponentName` | Vue 自定义组件命名规则 | [vue.base.md](references/vue.base.md) |
|
||||
| Vue.FileName | `Vue.FileName.UpperCamel` | Vue 组件文件使用大驼峰命名 | [vue.file-name.md](references/vue.file-name.md) |
|
||||
|
||||
## 规则覆盖关系(override)
|
||||
|
||||
当多个规范同时命中同一文件时,按以下覆盖关系处理冲突:
|
||||
|
||||
1. `JsTs.Nest` 覆盖 `JsTs.FileName`。
|
||||
2. `JsTs.Nest.DtoDefinition` 对 `JsTs.Base.NoMagicStringsAndNumbers` 做规则级覆盖。
|
||||
3. `Js.Model` 覆盖 `JsTs.Base`。
|
||||
4. `Js.Model.FileName` 覆盖 `JsTs.FileName`。
|
||||
|
||||
> 建议:在实现自动化检查时,先按 `includes` 过滤命中文件,再按 `override` 解析最终生效规则。
|
||||
|
||||
## 使用建议
|
||||
|
||||
1. **按文件类型匹配规范集**:先判断文件路径与后缀,再应用对应规则。
|
||||
2. **输出规则 ID**:Review 结果中保留规则 ID(如 `JsTs.Base.FuncLowerCamel`),便于追踪和整改。
|
||||
3. **先基础后专项**:优先接入 `JsTs.Base` 与 `JsTs.FileName`,再逐步接入 Nest / Model / Vue / Test 专项规则。
|
||||
4. **保持示例驱动**:新增规则时提供清晰的 Good/Bad 示例,降低理解成本。
|
||||
|
||||
## 维护约定
|
||||
|
||||
新增或修改规则时建议遵循以下格式:
|
||||
|
||||
- 一级标题:规范名称 + 规则前缀(如 ``[JsTs.Base]``)
|
||||
- 二级标题:单条规则描述 + 完整规则 ID(如 ``[JsTs.Base.ConstUpperCase]``)
|
||||
- 元信息:`includes` / `override` / `severity`(如适用)
|
||||
- 示例:使用 `### Example:` 分组,`#### Good:` 展示推荐做法,`#### Bad:` 展示不推荐做法
|
||||
|
||||
这样可以保证规则文档在人工阅读和自动化解析两种场景下都保持一致性。
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 代码规范技能
|
||||
name: code-review
|
||||
description: 当用户要求重构、审查或编写代码时,请参考此规范。
|
||||
metadata:
|
||||
spaceflow: true
|
||||
@@ -7,26 +7,26 @@ metadata:
|
||||
|
||||
## 功能
|
||||
|
||||
- 自动同步最新的代码规范
|
||||
- 自动检查代码是否符合规范
|
||||
- 自动修复代码
|
||||
|
||||
## 代码规范
|
||||
|
||||
在 references 目录下
|
||||
- 检查代码是否符合规范
|
||||
|
||||
## 命令
|
||||
|
||||
### 同步最新代码规范
|
||||
|
||||
```bash
|
||||
npx spaceflow install
|
||||
pnpm spaceflow install
|
||||
```
|
||||
|
||||
### 审查当前未提交的代码
|
||||
|
||||
```bash
|
||||
pnpm spaceflow review
|
||||
```
|
||||
|
||||
### 审查一个文件
|
||||
|
||||
```bash
|
||||
npx spaceflow review -b main --head develop -f $CODE_PATH
|
||||
pnpm spaceflow review -b main --head develop -f $CODE_PATH
|
||||
```
|
||||
|
||||
- `$CODE_PATH`:需要检查的文件路径
|
||||
@@ -36,7 +36,7 @@ npx spaceflow review -b main --head develop -f $CODE_PATH
|
||||
### 审查一个Commit
|
||||
|
||||
```bash
|
||||
npx spaceflow review -b main --head develop --commits $COMMIT_ID
|
||||
pnpm spaceflow review -b main --head develop --commits $COMMIT_ID
|
||||
```
|
||||
|
||||
- `$COMMIT_ID`:需要检查的Commit ID,可以是多个空格隔开
|
||||
@@ -46,7 +46,7 @@ npx spaceflow review -b main --head develop --commits $COMMIT_ID
|
||||
### 审查两个分支的差异代码
|
||||
|
||||
```bash
|
||||
npx spaceflow review -b main --head develop
|
||||
pnpm spaceflow review -b main --head develop
|
||||
```
|
||||
|
||||
- `-b main`:指定基准分支
|
||||
@@ -54,6 +54,10 @@ npx spaceflow review -b main --head develop
|
||||
|
||||
## 使用场景
|
||||
|
||||
### 当用户要求审查当前代码
|
||||
|
||||
首先需要同步最新的代码规范,然后直接执行上面的命令。
|
||||
|
||||
### 当用户要求审查代码时
|
||||
|
||||
首先需要同步最新的代码规范,然后用户有没有指定审查的文件路径,如果有则审查文件,否则审查两个分支的差异代码。
|
||||
|
||||
+144
-41
@@ -5,22 +5,29 @@
|
||||
## 常量名使用大写加下划线命名(UPPER_CASE),单词间以下划线分隔 `[JsTs.Base.ConstUpperCase]`
|
||||
|
||||
- 不检查 nodejs 的导包定义,比如 `const fs = require("fs")`
|
||||
- 常量检查只需检查 `const` 声明的静态值,但是不包含对象和函数
|
||||
|
||||
### Good
|
||||
### Example: 常量命名
|
||||
|
||||
#### Good: 使用大写加下划线
|
||||
|
||||
```javascript
|
||||
const MAX_COUNT = 100;
|
||||
const ROLE_ADMIN = 1;
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用小驼峰
|
||||
|
||||
```javascript
|
||||
const maxCount = 100;
|
||||
const roleAdmin = 1;
|
||||
```
|
||||
|
||||
## 函数名使用小驼峰命名 `[JsTs.Base.FuncLowerCamel]`
|
||||
|
||||
### Good
|
||||
> - severity `warn`
|
||||
|
||||
### Example: 函数命名
|
||||
|
||||
#### Good: 使用小驼峰
|
||||
|
||||
```javascript
|
||||
function getUserInfo() {
|
||||
@@ -28,7 +35,7 @@ function getUserInfo() {
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用全小写
|
||||
|
||||
```javascript
|
||||
function getuserinfo() {
|
||||
@@ -36,40 +43,66 @@ function getuserinfo() {
|
||||
}
|
||||
```
|
||||
|
||||
## 禁止使用字面量魔法字符串和魔法数字 `[JsTs.Base.NoMagicStringsAndNumbers]`
|
||||
## 禁止使用字面量魔法数字 `[JsTs.Base.NoMagicVar]`
|
||||
|
||||
- 只检查数字字面量和字符串字面量,不要检查其他(比如 布尔字面量)
|
||||
- 无需检查单词是否完整拼写
|
||||
- throw 的错误信息无需审查
|
||||
- new Error 的错误信息无需审查
|
||||
- console.log 的打印代码无需审查
|
||||
- console.error 的错误信息无需审查
|
||||
- console.warn 的错误信息无需审查
|
||||
- console.info 的错误信息无需审查
|
||||
- console.debug 的错误信息无需审查
|
||||
- console.trace 的错误信息无需审查
|
||||
- 无需考虑类型是否合理匹配
|
||||
> - severity `warn`
|
||||
|
||||
### Good
|
||||
- 仅检查**数字字面量**和**正则字面量**,不检查布尔、对象、函数、数组、字符串字面量
|
||||
- 仅检查含义不明确的数字,如 `0`、`1`、`2` 等;
|
||||
- `throw` / `new Error` 的错误信息无需审查
|
||||
- `console.*`(`log` / `error` / `warn` / `info` / `debug` / `trace`)的内容无需审查
|
||||
- 语义自明的数量类数字无需抽取常量,例如:时间戳、毫秒时长、元素数量、尺寸等一眼可理解的值
|
||||
|
||||
### Example: 魔法数字
|
||||
|
||||
#### Good: 使用常量替代魔法数字
|
||||
|
||||
```javascript
|
||||
const MAX_COUNT = 100;
|
||||
const USER_STATUS = {
|
||||
ACTIVE: "active",
|
||||
INACTIVE: "inactive",
|
||||
};
|
||||
const ROLE_ADMIN = 1;
|
||||
|
||||
if (user.role === ROLE_ADMIN) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用字面量魔法数字
|
||||
|
||||
```javascript
|
||||
const maxCount = 100;
|
||||
const userStatus = "active";
|
||||
if (user.role === 1) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## class 和 interface 命名使用大驼峰命名 `[JsTs.Base.ClassUpperCamel]`
|
||||
## 基于 JsTs.Base.NoMagicVar 抽离的静态常量需要放在对应文件里 `[JsTs.Base.ConstantsDefinition]`
|
||||
|
||||
### Good
|
||||
> - severity `error`
|
||||
|
||||
- 需要放在指定模块的 constants 文件里
|
||||
- constants 命名规则: user.constants.js 或者 user.constants.ts
|
||||
|
||||
### Example: 常量定义位置
|
||||
|
||||
#### Good: 常量放在对应模块的 constants 文件
|
||||
|
||||
```javascript
|
||||
// user.constants.js
|
||||
const ROLE_ADMIN = 1; // 这是 user 模块需要的
|
||||
```
|
||||
|
||||
#### Bad: 常量放在错误模块的 constants 文件
|
||||
|
||||
```javascript
|
||||
// class.constants.js
|
||||
const ROLE_ADMIN = 1; // 这是 user 模块需要的
|
||||
```
|
||||
|
||||
## class 和 interface 命名使用大驼峰命名 `[JsTs.Base.ClassNaming]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
### Example: 类和接口命名
|
||||
|
||||
#### Good: 使用大驼峰
|
||||
|
||||
```javascript
|
||||
class UserInfo {
|
||||
@@ -77,7 +110,7 @@ class UserInfo {
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用全小写
|
||||
|
||||
```javascript
|
||||
class userinfo {
|
||||
@@ -85,48 +118,118 @@ class userinfo {
|
||||
}
|
||||
```
|
||||
|
||||
## 变量名使用小驼峰命名 `[JsTs.Base.VarLowerCamel]`
|
||||
## 变量名使用小驼峰或者蛇形命名 `[JsTs.Base.VarNaming]`
|
||||
|
||||
### Good
|
||||
> - severity `warn`
|
||||
|
||||
- 需要注意的是从 require 导入的变量不受检查
|
||||
- 私有属性可以使用 `_` 开头,比如 `this._fromFeatureRecommendEntry`
|
||||
|
||||
### Example: 变量命名
|
||||
|
||||
#### Good: 使用小驼峰或蛇形命名
|
||||
|
||||
```javascript
|
||||
let userName = "John";
|
||||
let user_name = "John";
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用大驼峰
|
||||
|
||||
```javascript
|
||||
let username = "John";
|
||||
let Username = "John";
|
||||
```
|
||||
|
||||
## 单文件代码不超过 700 行 `[JsTs.Base.CodeNotMoreThan700Lines]`
|
||||
|
||||
### Good
|
||||
> - includes `added|*`
|
||||
|
||||
### Example: 文件行数
|
||||
|
||||
#### Good: 代码不超过 700 行
|
||||
|
||||
```javascript
|
||||
// 代码不超过 700 行
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 代码超过 700 行
|
||||
|
||||
```javascript
|
||||
// 代码超过 700 行
|
||||
```
|
||||
|
||||
## 单个函数或方法不能超出 200 行 `[JsTs.Base.FuncNotMoreThan200Lines]`
|
||||
## 单个函数或方法不能超出 300 行 `[JsTs.Base.FuncNotMoreThan300Lines]`
|
||||
|
||||
### Good
|
||||
### Example: 函数行数
|
||||
|
||||
#### Good: 函数不超过 300 行
|
||||
|
||||
```javascript
|
||||
function getUserInfo() {
|
||||
// ... 小于等于 200
|
||||
// ... 小于等于 300
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 函数超过 300 行
|
||||
|
||||
> - includes `added|*`
|
||||
|
||||
```javascript
|
||||
function getUserInfo() {
|
||||
// ... 大于 200
|
||||
// ... 大于 300
|
||||
}
|
||||
```
|
||||
|
||||
## 复杂的逻辑判断要添加注释 `[JsTs.Base.ComplexLogic]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
- 逻辑判断的复杂度大于等于 3 个的要添加注释
|
||||
|
||||
### Example: 复杂逻辑注释
|
||||
|
||||
#### Good: 复杂逻辑添加注释
|
||||
|
||||
```javascript
|
||||
// 逻辑判断复杂度大于等于 3 个
|
||||
if (a && b || c) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Bad: 复杂逻辑未添加注释
|
||||
|
||||
```javascript
|
||||
if (a && b && c && d) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 复杂的函数要添加注释 `[JsTs.Base.ComplexFunc]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
### Example: 复杂函数注释
|
||||
|
||||
#### Good: 复杂函数添加注释
|
||||
|
||||
> - includes `added|*`
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 复杂的算法逻辑
|
||||
*/
|
||||
function complexFunc() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Bad: 复杂函数未添加注释
|
||||
|
||||
> - includes `added|*`
|
||||
|
||||
```javascript
|
||||
function complexFunc() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
- 文件名必须与主导类或接口名称完全一致。
|
||||
- 适用于定义单一主要实体的文件。
|
||||
|
||||
### Good
|
||||
### Example: class 和 interface 文件命名
|
||||
|
||||
#### Good: 使用大驼峰命名
|
||||
|
||||
```javascript
|
||||
// UserInfo.js
|
||||
@@ -16,7 +18,7 @@ class UserInfo {
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用全小写命名
|
||||
|
||||
```javascript
|
||||
// userinfo.js
|
||||
@@ -30,7 +32,9 @@ class userinfo {
|
||||
- 适用于导出一个或多个工具函数的文件。
|
||||
- 文件名应反映其包含的核心功能。
|
||||
|
||||
### Good
|
||||
### Example: 函数文件命名
|
||||
|
||||
#### Good: 使用小驼峰命名
|
||||
|
||||
```javascript
|
||||
// getUserInfo.js
|
||||
@@ -39,7 +43,7 @@ function getUserInfo() {
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用全小写命名
|
||||
|
||||
```javascript
|
||||
// getuserinfo.js
|
||||
|
||||
+61
-17
@@ -1,6 +1,6 @@
|
||||
# Nestjs 项目下的规范 `[JsTs.Nest]`
|
||||
|
||||
> - includes `*.controller.ts` `*.service.ts` `*.module.ts` `*.dto.ts` `*.pipe.ts` `*.guard.ts` `*.interceptor.ts` `*.filter.ts` `*.exception-filter.ts` `*.proxy.ts` `*.model.ts`
|
||||
> - includes `*.controller.ts` `*.service.ts` `*.module.ts` `*.dto.ts` `*.pipe.ts` `*.guard.ts` `*.interceptor.ts` `*.filter.ts` `*.exception-filter.ts` `*.proxy.ts` `*.model.ts` `*.constants.ts`
|
||||
> - override `[JsTs.FileName]`
|
||||
|
||||
## 目录框架规范 `[JsTs.Nest.DirStructure]`
|
||||
@@ -16,7 +16,9 @@
|
||||
- 每个模块的目录下可以包含 `interceptor` 目录,用于存放拦截器
|
||||
- 每个模块的目录下可以包含 `filter` 目录,用于存放异常过滤器
|
||||
|
||||
### Good
|
||||
### Example: 目录结构
|
||||
|
||||
#### Good: 按模块组织的目录结构
|
||||
|
||||
```txt
|
||||
src/
|
||||
@@ -43,7 +45,7 @@ src/
|
||||
└── main.ts # 应用入口
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 扁平化的目录结构
|
||||
|
||||
```txt
|
||||
src/
|
||||
@@ -61,14 +63,17 @@ src/
|
||||
- 该文件不能写业务逻辑,只能写调用 service 的代码
|
||||
- 文件名使用小写加横线命名(如 `user-extends.controller.ts`)
|
||||
- 文件名必须加 `.controller.ts` 后缀
|
||||
- 注解和装饰器上的静态值无需进行魔法值的提炼 `[JsTs.Base.NoMagicStringsAndNumbers]`
|
||||
|
||||
### Good
|
||||
### Example: 控制器文件命名
|
||||
|
||||
#### Good: 使用小写加横线命名
|
||||
|
||||
```txt
|
||||
user-extends.controller.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用大驼峰命名
|
||||
|
||||
```txt
|
||||
userController.ts
|
||||
@@ -82,13 +87,15 @@ userController.ts
|
||||
- 文件名使用小写加横线命名(如 `user-extends.service.ts`)
|
||||
- 文件名必须加 `.service.ts` 后缀
|
||||
|
||||
### Good
|
||||
### Example: 服务文件命名
|
||||
|
||||
#### Good: 使用小写加横线命名
|
||||
|
||||
```txt
|
||||
user-extends.service.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用大驼峰命名
|
||||
|
||||
```txt
|
||||
userService.ts
|
||||
@@ -99,13 +106,15 @@ userService.ts
|
||||
- 文件名使用小写加横线命名(如 `user-extends.module.ts`)
|
||||
- 文件名必须加 `.module.ts` 后缀
|
||||
|
||||
### Good
|
||||
### Example: 模块文件命名
|
||||
|
||||
#### Good: 使用小写加横线命名
|
||||
|
||||
```txt
|
||||
user-extends.module.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用大驼峰命名
|
||||
|
||||
```txt
|
||||
userModule.ts
|
||||
@@ -113,18 +122,22 @@ userModule.ts
|
||||
|
||||
## Dto 命名规范 `[JsTs.Nest.DtoDefinition]`
|
||||
|
||||
> - override `[JsTs.Base.NoMagicStringsAndNumbers]`
|
||||
|
||||
- 文件名使用小写加横线命名(如 `user-extends.dto.ts`)
|
||||
- 文件名必须加 `.dto.ts` 后缀
|
||||
- dto 目录下必须包含 `dto.ts` 文件
|
||||
- dto 里的类的属性可以使用小驼峰或者下划线命名
|
||||
|
||||
### Good
|
||||
### Example: Dto 文件命名
|
||||
|
||||
#### Good: 使用小写加横线命名
|
||||
|
||||
```txt
|
||||
user-extends.dto.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用大驼峰命名
|
||||
|
||||
```txt
|
||||
userDto.ts
|
||||
@@ -138,7 +151,9 @@ userDto.ts
|
||||
- 内部只能写使用 syncService 调用的逻辑
|
||||
- SyncService 只能在 proxy.ts 中使用
|
||||
|
||||
### Good
|
||||
### Example: Proxy 编写
|
||||
|
||||
#### Good: Proxy 只使用 SyncService 调用旧业务
|
||||
|
||||
```typescript
|
||||
// user.proxy.ts
|
||||
@@ -156,7 +171,7 @@ export class UserProxy {
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: Proxy 中直接查询数据库
|
||||
|
||||
```typescript
|
||||
// user.proxy.ts
|
||||
@@ -178,11 +193,15 @@ export class UserProxy {
|
||||
|
||||
## Model 编写规范 `[JsTs.Nest.ModelDefinition]`
|
||||
|
||||
> - includes `*.model.ts`
|
||||
|
||||
- 内部只能写使用 model 数据库调用的逻辑
|
||||
- 文件名使用小写加横线命名(如 `user.model.ts`)
|
||||
- 文件名必须加 `.model.ts` 后缀
|
||||
|
||||
### Good
|
||||
### Example: Model 编写
|
||||
|
||||
#### Good: Model 只使用数据库调用
|
||||
|
||||
```typescript
|
||||
// user.model.ts
|
||||
@@ -201,7 +220,7 @@ export class UserProxy {
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: Model 中使用 SyncService 调用旧业务
|
||||
|
||||
```typescript
|
||||
// user.model.ts
|
||||
@@ -224,7 +243,9 @@ export class UserProxy {
|
||||
|
||||
- 目前所有的新代码都应该写在 nest 里
|
||||
|
||||
### Good
|
||||
### Example: 业务代码位置
|
||||
|
||||
#### Good: 新代码写在 nest 目录下
|
||||
|
||||
```typescript
|
||||
// nest-src/apps/app/src/user/user.controller.ts
|
||||
@@ -238,8 +259,31 @@ export class UserProxy {
|
||||
// nest-src/apps/app/src/user/user.module.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 新代码写在旧目录下
|
||||
|
||||
```typescript
|
||||
// proxy/user.js
|
||||
```
|
||||
|
||||
## 基于 JsTs.Base.NoMagicStringsAndNumbers 抽离的静态常量需要放在对应文件里 `[JsTs.Nest.ConstantsDefinition]`
|
||||
|
||||
> - severity `warn`
|
||||
> - override `[JsTs.Base.ConstantsDefinition]`
|
||||
|
||||
- 需要放在指定模块的 constants 文件里
|
||||
|
||||
### Example: 常量定义位置
|
||||
|
||||
#### Good: 常量放在对应模块的 constants 文件
|
||||
|
||||
```typescript
|
||||
// user.constants.ts
|
||||
const MAX_COUNT = 100; // 这是 user 模块需要的
|
||||
```
|
||||
|
||||
#### Bad: 常量放在错误模块的 constants 文件
|
||||
|
||||
```typescript
|
||||
// class.constants.ts
|
||||
const MAX_COUNT = 100; // 这是 user 模块需要的
|
||||
```
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
- 必须以 `.test.js` 或 `.test.ts`(或 `.spec.ts`)结尾。
|
||||
- 前缀部分应与被测试源文件名保持一致。
|
||||
|
||||
### Good
|
||||
### Example: 测试文件命名
|
||||
|
||||
#### Good: 测试文件名与源文件名一致
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
@@ -17,7 +19,7 @@ describe("UserInfo", () => {
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 测试文件名与源文件名不一致
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
@@ -32,7 +34,9 @@ describe("userinfo", () => {
|
||||
- 测试代码命名结构:`describe(文件名)` -> `describe(函数名/类名.方法名)` -> `it(场景描述)`。
|
||||
- 场景描述应使用 "should ..." 格式,描述预期行为。
|
||||
|
||||
### Good
|
||||
### Example: 测试代码块命名
|
||||
|
||||
#### Good: 使用 describe(文件名) -> describe(函数名/类名.方法名) -> it(场景描述)
|
||||
|
||||
```javascript
|
||||
// uUerInfo.js
|
||||
@@ -68,7 +72,7 @@ describe("userInfo", () => {
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 缺少 describe(函数名/类名.方法名) 层级
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
|
||||
+45
-22
@@ -1,13 +1,18 @@
|
||||
# mongoose 数据库模型 JS 规范 `[Js.Model]`
|
||||
|
||||
> - includes `models/*.js`
|
||||
> - includes `*/models/*.js`
|
||||
> - override `[JsTs.Base]`
|
||||
|
||||
## 模型文件命名规范 `[Js.Model.FileName]`
|
||||
|
||||
> - override `[JsTs.FileName]`
|
||||
|
||||
- 文件名使用小写加下划线命名(如 `user_extends.js`),或者使用小写加横线命名(如 `user-extends.js`)
|
||||
- 文件名应与模型名称对应
|
||||
|
||||
### Good
|
||||
### Example: 模型文件命名
|
||||
|
||||
#### Good: 使用小写加下划线或横线命名
|
||||
|
||||
```txt
|
||||
user.js
|
||||
@@ -15,7 +20,7 @@ user_extends.js
|
||||
user-profile.js
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用大驼峰命名
|
||||
|
||||
```txt
|
||||
User.js
|
||||
@@ -30,7 +35,9 @@ UserProfile.js
|
||||
- 要补充字段注释
|
||||
- 要补充字段类型
|
||||
|
||||
### Good
|
||||
### Example: Schema 字段命名
|
||||
|
||||
#### Good: 字段名使用 snake_case
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -40,7 +47,7 @@ const userSchema = new Schema({
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 字段名使用驼峰命名
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -56,19 +63,21 @@ const userSchema = new Schema({
|
||||
- 必要时添加 `required`、`default` 等属性
|
||||
- 复杂类型应使用嵌套 Schema 或引用
|
||||
|
||||
### Good
|
||||
### Example: Schema 定义
|
||||
|
||||
#### Good: 完整的字段定义
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
user_name: { type: String, required: true },
|
||||
email: { type: String, required: true, unique: true },
|
||||
email: { type: String, required: true },
|
||||
age: { type: Number, default: 0 },
|
||||
status: { type: String, enum: ["active", "inactive"], default: "active" },
|
||||
created_at: { type: Date, default: Date.now },
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 缺少 required/default 等属性
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -85,7 +94,9 @@ const userSchema = new Schema({
|
||||
- 需要添加注释说明索引用途
|
||||
- 不能在 Schema 定义中直接添加索引,添加到索引要注释掉
|
||||
|
||||
### Good
|
||||
### Example: 索引定义
|
||||
|
||||
#### Good: 索引注释掉并添加用途说明
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
@@ -100,7 +111,7 @@ const orderSchema = new Schema({
|
||||
// orderSchema.index({ order_no: 1 }, { unique: true });
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 在 Schema 定义中直接添加索引
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
@@ -116,7 +127,9 @@ const orderSchema = new Schema({
|
||||
- 虚拟字段应在 Schema 定义后声明
|
||||
- 需要添加注释说明虚拟字段用途
|
||||
|
||||
### Good
|
||||
### Example: 虚拟字段
|
||||
|
||||
#### Good: 使用 virtual 定义可计算字段
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -130,7 +143,7 @@ userSchema.virtual("full_name").get(function () {
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 存储可计算的字段
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -146,7 +159,9 @@ const userSchema = new Schema({
|
||||
- 需要添加注释说明中间件用途
|
||||
- 避免在中间件中执行耗时操作
|
||||
|
||||
### Good
|
||||
### Example: 中间件/钩子
|
||||
|
||||
#### Good: 中间件添加注释说明用途
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -169,7 +184,7 @@ userSchema.pre("save", async function (next) {
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 中间件缺少注释且使用同步方法
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -189,7 +204,9 @@ userSchema.pre("save", function (next) {
|
||||
- 静态方法应在 Schema 定义后声明
|
||||
- 需要添加注释说明方法用途
|
||||
|
||||
### Good
|
||||
### Example: 静态方法
|
||||
|
||||
#### Good: 静态方法使用小驼峰命名并添加注释
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -208,7 +225,7 @@ userSchema.statics.findActiveUsers = function () {
|
||||
};
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 静态方法使用下划线命名且缺少注释
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -228,7 +245,9 @@ userSchema.statics.find_by_email = function (email) {
|
||||
- 需要添加注释说明方法用途
|
||||
- 实例方法内部使用 `this` 访问文档属性
|
||||
|
||||
### Good
|
||||
### Example: 实例方法
|
||||
|
||||
#### Good: 实例方法使用小驼峰命名并添加注释
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -248,7 +267,7 @@ userSchema.methods.incrementLoginCount = function () {
|
||||
};
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 实例方法使用下划线命名且缺少注释
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -267,7 +286,9 @@ userSchema.methods.compare_password = function (candidatePassword) {
|
||||
- 必须指定 `ref` 属性
|
||||
- 需要添加注释说明关联关系
|
||||
|
||||
### Good
|
||||
### Example: 关联引用
|
||||
|
||||
#### Good: 引用字段使用 _id 后缀并指定 ref
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
@@ -278,7 +299,7 @@ const orderSchema = new Schema({
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 引用字段缺少 ref 且命名不规范
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
@@ -293,7 +314,9 @@ const orderSchema = new Schema({
|
||||
- 禁止使用简写形式(如 `field: String`)
|
||||
- 不允许使用 Object 等模糊类型
|
||||
|
||||
### Good
|
||||
### Example: 字段类型定义
|
||||
|
||||
#### Good: 字段定义使用对象形式明确指定 type
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
@@ -308,7 +331,7 @@ const userSchema = new Schema({
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用简写形式或模糊类型
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
必须使用大驼峰命名并且使用的时候也是,并且至少两个单词。
|
||||
|
||||
### Good
|
||||
### Example: 自定义组件命名
|
||||
|
||||
#### Good: 使用大驼峰且至少两个单词
|
||||
|
||||
```vue
|
||||
<!-- UserInfo.vue -->
|
||||
@@ -22,7 +24,7 @@ export default {
|
||||
</script>
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用全小写或单词不足
|
||||
|
||||
```vue
|
||||
<!-- userinfo.vue -->
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
## Vue 组件文件使用大驼峰命名 `[Vue.FileName.UpperCamel]`
|
||||
|
||||
### Good
|
||||
### Example: Vue 组件文件命名
|
||||
|
||||
#### Good: 使用大驼峰命名
|
||||
|
||||
```vue
|
||||
<!-- UserInfo.vue -->
|
||||
@@ -20,7 +22,7 @@ export default {
|
||||
</script>
|
||||
```
|
||||
|
||||
### Bad
|
||||
#### Bad: 使用全小写命名
|
||||
|
||||
```vue
|
||||
<!-- userinfo.vue -->
|
||||
|
||||
Reference in New Issue
Block a user