code-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode Review Methodology
代码评审方法论
Systematic pre-PR code review for the project codebase. Identifies critical issues with focus on TRPC patterns, TanStack Router, Drizzle ORM, and security best practices.
针对项目代码库的系统化PR前代码评审。重点关注TRPC模式、TanStack Router、Drizzle ORM和安全最佳实践,识别关键问题。
Review Process
评审流程
- Identify Scope — Determine what code to review
- Scan Changes — Analyze against project-specific patterns
- Verify with Exa & Context7 — Validate uncertain patterns
- Categorize Findings — Organize by severity (Critical, Major, Minor)
- Generate Report — Structured report with actionable feedback
- Run Automated Checks — Execute
bun run check
- 确定范围 — 明确需要评审的代码内容
- 扫描变更 — 对照项目专属模式进行分析
- 通过Exa & Context7验证 — 对不确定的模式进行验证
- 分类发现的问题 — 按严重程度(关键、主要、次要)整理
- 生成报告 — 包含可执行反馈的结构化报告
- 运行自动化检查 — 执行
bun run check
Step 1: Identify Scope
步骤1:确定范围
Ask the user what to review:
- Recent commits (default):
git log -5 --oneline && git diff HEAD~5..HEAD --stat - Specific files/directories: User-provided paths
- Branch comparison:
git diff main..HEAD --stat
询问用户需要评审的内容:
- 最近提交记录(默认):
git log -5 --oneline && git diff HEAD~5..HEAD --stat - 特定文件/目录:用户提供的路径
- 分支对比:
git diff main..HEAD --stat
Step 2: Vivus-Specific Review Categories
步骤2:项目专属评审类别
1. TRPC Patterns
1. TRPC模式
Check against skill:
trpc-patternsCritical patterns to verify:
typescript
// ✅ Correct - Using RouterOutputs/RouterInputs
type SessionData = RouterOutputs["adminAuthSessions"]["listTokens"]["sessions"][0];
// ❌ Wrong - Manual type definitions
type SessionData = { sessionId: string; ... };typescript
// ✅ Correct - Using error helpers
throw notFoundError("Project not found");
// ❌ Wrong - Manual TRPCError
throw new TRPCError({ code: "NOT_FOUND", message: "..." });typescript
// ✅ Correct - protectedMemberAccessProcedure for org-scoped
export const router = {
getOrgData: protectedMemberAccessProcedure
.input(z.object({ organizationId: z.string() }))
.query(...)
}
// ❌ Wrong - Manual membership check in protectedProceduretypescript
// ✅ Correct - Inline simple schemas with common types
role: z.enum([OrganizationRoles.Owner, OrganizationRoles.Admin]);
// ❌ Wrong - Hardcoded enum values
role: z.enum(["owner", "admin"]);SQL Query Optimization:
typescript
// ✅ Correct - Single query with JOINs
const result = await db.select({...}).from(membersTable)
.innerJoin(organizationsTable, eq(...))
.leftJoin(projectsTable, eq(...))
// ❌ Wrong - Multiple separate queries (N+1)
const orgs = await db.select().from(organizationsTable);
const members = await db.select().from(membersTable);对照Skill检查:
trpc-patterns需要验证的关键模式:
typescript
// ✅ 正确用法 - 使用RouterOutputs/RouterInputs
type SessionData = RouterOutputs["adminAuthSessions"]["listTokens"]["sessions"][0];
// ❌ 错误用法 - 手动定义类型
type SessionData = { sessionId: string; ... };typescript
// ✅ 正确用法 - 使用错误助手函数
throw notFoundError("Project not found");
// ❌ 错误用法 - 手动创建TRPCError
throw new TRPCError({ code: "NOT_FOUND", message: "..." });typescript
// ✅ 正确用法 - 针对组织范围使用protectedMemberAccessProcedure
export const router = {
getOrgData: protectedMemberAccessProcedure
.input(z.object({ organizationId: z.string() }))
.query(...)
}
// ❌ 错误用法 - 在protectedProcedure中手动检查成员资格typescript
// ✅ 正确用法 - 结合通用类型内联简单枚举
role: z.enum([OrganizationRoles.Owner, OrganizationRoles.Admin]);
// ❌ 错误用法 - 硬编码枚举值
role: z.enum(["owner", "admin"]);SQL查询优化:
typescript
// ✅ 正确用法 - 使用JOIN的单查询
const result = await db.select({...}).from(membersTable)
.innerJoin(organizationsTable, eq(...))
.leftJoin(projectsTable, eq(...))
// ❌ 错误用法 - 多个独立查询(N+1问题)
const orgs = await db.select().from(organizationsTable);
const members = await db.select().from(membersTable);2. TanStack Router & Query Patterns
2. TanStack Router & Query模式
Check against skill:
tanstack-frontendCritical patterns to verify:
typescript
// ✅ Correct - TRPC v11 pattern with .queryOptions()
const { data } = useSuspenseQuery(trpc.organization.getById.queryOptions({ id }));
// ❌ Wrong - Old pattern (doesn't exist in v11)
const { data } = trpc.organization.getById.useQuery({ id });typescript
// ✅ Correct - Prefetch critical data with await
loader: async ({ context, params }) => {
await context.queryClient.prefetchQuery(
context.trpc.organization.getById.queryOptions({ id: params.id })
);
// Secondary data - void for optimization
void context.queryClient.prefetchQuery(
context.trpc.analytics.getStats.queryOptions({ id: params.id })
);
}
// ❌ Wrong - Sequential await (slow)
await context.queryClient.prefetchQuery(...);
await context.queryClient.prefetchQuery(...);
await context.queryClient.prefetchQuery(...);
// ❌ Wrong - All void (component will suspend)
void context.queryClient.prefetchQuery(...); // critical data!typescript
// ✅ Correct - Props type naming
type Props = { isOpen: boolean; onClose: () => void; };
// ❌ Wrong - Component-specific props naming
type DeleteMemberModalProps = { ... };typescript
// ✅ Correct - Cache invalidation
await queryClient.invalidateQueries({
queryKey: trpc.organization.queryKey(),
});对照Skill检查:
tanstack-frontend需要验证的关键模式:
typescript
// ✅ 正确用法 - TRPC v11的.queryOptions()模式
const { data } = useSuspenseQuery(trpc.organization.getById.queryOptions({ id }));
// ❌ 错误用法 - 旧模式(v11中已移除)
const { data } = trpc.organization.getById.useQuery({ id });typescript
// ✅ 正确用法 - 用await预取关键数据
loader: async ({ context, params }) => {
await context.queryClient.prefetchQuery(
context.trpc.organization.getById.queryOptions({ id: params.id })
);
// 次要数据 - 使用void优化
void context.queryClient.prefetchQuery(
context.trpc.analytics.getStats.queryOptions({ id: params.id })
);
}
// ❌ 错误用法 - 顺序await(速度慢)
await context.queryClient.prefetchQuery(...);
await context.queryClient.prefetchQuery(...);
await context.queryClient.prefetchQuery(...);
// ❌ 错误用法 - 全部用void(组件会挂起)
void context.queryClient.prefetchQuery(...); // 这是关键数据!typescript
// ✅ 正确用法 - Props类型命名
type Props = { isOpen: boolean; onClose: () => void; };
// ❌ 错误用法 - 组件专属Props命名
type DeleteMemberModalProps = { ... };typescript
// ✅ 正确用法 - 缓存失效
await queryClient.invalidateQueries({
queryKey: trpc.organization.queryKey(),
});3. Code Deduplication (DRY)
3. 代码去重(DRY原则)
Identify duplicate or near-duplicate code:
- Same logic implemented in multiple files with different approaches
- Copy-pasted functions with minor variations
- Repeated patterns that could be extracted to shared utilities
When to extract:
- Same logic appears in 2+ locations
- Functions differ only in minor details (parameterize instead)
- Utility is general enough to be reused
Where to place shared code:
- — Cross-service shared utilities
packages/services/src/ - — Cross-package shared types/utilities
packages/common/src/ - Same-directory — Local module utilities
utils.ts
识别重复或近似重复的代码:
- 同一逻辑在多个文件中用不同方式实现
- 复制粘贴后仅做微小修改的函数
- 可提取为共享工具的重复模式
提取时机:
- 同一逻辑出现在2个及以上位置
- 函数仅在细节上有差异(应参数化处理)
- 工具函数具有足够通用性可被复用
共享代码存放位置:
- — 跨服务共享工具
packages/services/src/ - — 跨包共享类型/工具
packages/common/src/ - 同目录下的— 本地模块工具
utils.ts
4. Code Quality & Style
4. 代码质量与风格
Check CLAUDE.md conventions:
- Imports: Always absolute (or
@/path), never relative in@project/*apps/web-app/src - Nullish coalescing: Use not
??for defaults|| - Bun APIs: Use ,
Bun.file()instead of Node.js polyfillsBun.spawn() - File naming: kebab-case (, not
contact-form.tsx)ContactForm.tsx - Types: Use not
typeunless extendinginterface - Logger: Use for backend,
@project/loggeris OK for frontend React componentsconsole.log/error - No barrel files: Don't create that only re-exports (causes circular imports, slow dev)
index.ts
DO NOT REPORT these as issues (they are acceptable):
- using
packages/*/src/index.ts— Package entry points are allowed exceptionsexport * - Relative imports () inside
../directories — Only apps/web-app requires absolute importspackages/ - in React components (frontend) — Only backend code requires
console.log/error@project/logger
检查CLAUDE.md约定:
- 导入方式: 始终使用绝对路径(或
@/path),@project/*中禁止使用相对路径apps/web-app/src - 空值合并: 默认值使用而非
??|| - Bun API: 使用、
Bun.file()替代Node.js兼容层Bun.spawn() - 文件命名: 使用短横线命名法(,而非
contact-form.tsx)ContactForm.tsx - 类型定义: 除非需要扩展,否则使用而非
typeinterface - 日志工具: 后端使用,前端React组件可使用
@project/loggerconsole.log/error - 禁止桶文件: 不要创建仅用于重新导出的(会导致循环导入、减慢开发速度)
index.ts
以下情况无需报告(属于可接受范围):
- 使用
packages/*/src/index.ts— 包入口文件允许例外export * - 目录内使用相对导入(
packages/) — 仅../要求绝对导入apps/web-app - React组件(前端)中使用— 仅后端代码要求使用
console.log/error@project/logger
5. Security
5. 安全检查
Critical checks:
- Hardcoded secrets/API keys:
grep -iE "api[_-]?key|password|secret|token" - SQL injection: String interpolation in queries
- Missing auth: Endpoints without or
protectedProcedureprotectedMemberAccessProcedure - Sensitive data in logs
- Missing input validation
Use error helpers from :
@/infrastructure/errors- ,
badRequestError(),unauthorizedError(),forbiddenError()notFoundError()
关键检查项:
- 硬编码的密钥/API密钥:
grep -iE "api[_-]?key|password|secret|token" - SQL注入:查询中使用字符串插值
- 缺失认证:未使用或
protectedProcedure的端点protectedMemberAccessProcedure - 日志中包含敏感数据
- 缺失输入验证
使用中的错误助手函数:
@/infrastructure/errors- 、
badRequestError()、unauthorizedError()、forbiddenError()notFoundError()
6. Performance
6. 性能检查
Database:
- N+1 queries (multiple queries that could be JOINs)
- Missing indexes on frequently queried columns
- Sequential API calls instead of
Promise.all()
Frontend:
- Missing prefetch in loaders
- Sequential instead of
awaitin loadersPromise.all() - when
fetchQuerywould sufficeprefetchQuery
数据库层面:
- N+1查询(可通过JOIN合并的多个查询)
- 频繁查询的列缺少索引
- 使用顺序API调用而非
Promise.all()
前端层面:
- Loader中缺失预取逻辑
- Loader中使用顺序而非
awaitPromise.all() - 可用时使用了
prefetchQueryfetchQuery
7. Testing
7. 测试检查
Check for:
- New TRPC endpoints without tests in
packages/services/src/__tests__/ - New components without tests
- Missing E2E tests for critical flows
检查内容:
- 新增TRPC端点但未在中添加测试
packages/services/src/__tests__/ - 新增组件但未添加测试
- 关键流程缺失E2E测试
8. Effect Patterns (if changes include Effect code)
8. Effect模式(若变更包含Effect代码)
Check against skill:
effect-tsApplies to: , , files with ,
packages/services/effect-runtime.tsEffect.genContext.Tagtypescript
// ✅ Correct - Service with @project namespace
export class MyService extends Context.Tag("@project/MyService")<...>() {}
// ❌ Wrong - Missing namespace
export class MyService extends Context.Tag("MyService")<...>() {}typescript
// ✅ Correct - Effect.fn for tracing
const doSomething = Effect.fn("MyService.doSomething")(
function* (params) { ... }
);
// ❌ Wrong - No tracing
const doSomething = (params) => Effect.gen(function* () { ... });typescript
// ✅ Correct - Schema.TaggedError
export class MyError extends Schema.TaggedError<MyError>()("MyError", {...}) {}
// ❌ Wrong - Data.TaggedError (less Schema interop)
export class MyError extends Data.TaggedError("MyError")<{...}> {}typescript
// ✅ Correct - ManagedRuntime for TRPC
import { runtime } from "@/infrastructure/effect-runtime";
await runtime.runPromise(Effect.gen(function* () { ... }));
// ❌ Wrong - Inline provide per request
await Effect.runPromise(effect.pipe(Effect.provide(ServiceLive)));For comprehensive Effect analysis, run:
/scan-effect-solutions对照Skill检查:
effect-ts适用范围: 、、包含、的文件
packages/services/effect-runtime.tsEffect.genContext.Tagtypescript
// ✅ 正确用法 - 使用@project命名空间的服务
export class MyService extends Context.Tag("@project/MyService")<...>() {}
// ❌ 错误用法 - 缺失命名空间
export class MyService extends Context.Tag("MyService")<...>() {}typescript
// ✅ 正确用法 - 使用Effect.fn实现追踪
const doSomething = Effect.fn("MyService.doSomething")(
function* (params) { ... }
);
// ❌ 错误用法 - 未实现追踪
const doSomething = (params) => Effect.gen(function* () { ... });typescript
// ✅ 正确用法 - 使用Schema.TaggedError
export class MyError extends Schema.TaggedError<MyError>()("MyError", {...}) {}
// ❌ 错误用法 - 使用Data.TaggedError(Schema互操作性差)
export class MyError extends Data.TaggedError("MyError")<{...}> {}typescript
// ✅ 正确用法 - 为TRPC使用ManagedRuntime
import { runtime } from "@/infrastructure/effect-runtime";
await runtime.runPromise(Effect.gen(function* () { ... }));
// ❌ 错误用法 - 每个请求内联提供依赖
await Effect.runPromise(effect.pipe(Effect.provide(ServiceLive)));如需全面的Effect分析,执行:
/scan-effect-solutionsVerify Uncertain Patterns
验证不确定的模式
Use Exa Search for real-world patterns:
Query: "React useEffect cleanup best practices"
Query: "TRPC v11 queryOptions pattern"Use Context7 for official docs:
1. context7-resolve-library-id(libraryName: "tanstack-query")
2. context7-get-library-docs(context7CompatibleLibraryID: "...", topic: "prefetchQuery")使用Exa Search查找真实场景模式:
查询:"React useEffect清理最佳实践"
查询:"TRPC v11 queryOptions模式"使用Context7获取官方文档:
1. context7-resolve-library-id(libraryName: "tanstack-query")
2. context7-get-library-docs(context7CompatibleLibraryID: "...", topic: "prefetchQuery")Finding Severity Classification
问题严重程度分类
CRITICAL (Must Fix Before Merge)
关键(合并前必须修复)
- Security vulnerabilities
- SQL injection, hardcoded secrets
- Missing authentication on protected endpoints
- Breaking changes to public APIs
- 安全漏洞
- SQL注入、硬编码密钥
- 受保护端点缺失认证
- 对公共API的破坏性变更
MAJOR (Should Fix)
主要(建议修复)
- Wrong TRPC v11 patterns (instead of
.useQuery).queryOptions - N+1 database queries
- Missing prefetch causing slow page loads
- Manual types instead of /
RouterInputsRouterOutputs - Code duplication — same logic in multiple files (DRY violation)
- TRPC v11模式错误(使用而非
.useQuery).queryOptions - N+1数据库查询
- 缺失预取导致页面加载缓慢
- 手动定义类型而非使用/
RouterInputsRouterOutputs - 代码重复——同一逻辑在多个文件中实现(违反DRY原则)
MINOR (Consider Fixing)
次要(考虑修复)
- Style inconsistencies
- Missing documentation
- Non-critical refactoring
- 风格不一致
- 缺失文档
- 非关键重构
Report Template
报告模板
markdown
undefinedmarkdown
undefinedCode Review Report
代码评审报告
Scope: [What was reviewed]
Date: [Current date]
范围: [评审内容]
日期: [当前日期]
CRITICAL ISSUES
关键问题
[List with file:line, description, fix]
[列出文件:行号、描述、修复方案]
MAJOR ISSUES
主要问题
[List with file:line, description, fix]
[列出文件:行号、描述、修复方案]
MINOR ISSUES
次要问题
[List with file:line, brief description]
[列出文件:行号、简要描述]
POSITIVE OBSERVATIONS
积极发现
- [Good patterns found]
- [发现的良好模式]
SUMMARY
总结
Assessment: [APPROVE / NEEDS_WORK / REJECT]
Next steps: [Specific actions]
评估结果: [通过 / 需要改进 / 拒绝]
下一步: [具体行动]
Quick Stats
快速统计
- Files reviewed: [N]
- Issues: Critical: [N], Major: [N], Minor: [N]
---- 评审文件数:[N]
- 问题数量:关键:[N],主要:[N],次要:[N]
---Assessment Criteria
评估标准
APPROVE
- No critical issues
- TRPC and TanStack patterns correct
- passes
bun run check
NEEDS_WORK
- Major pattern violations
- Missing tests for new functionality
- Performance issues
REJECT
- Security vulnerabilities
- Breaking changes without migration
- Fundamental design flaws
通过
- 无关键问题
- TRPC和TanStack模式正确
- 执行通过
bun run check
需要改进
- 存在主要模式违规
- 新增功能缺失测试
- 存在性能问题
拒绝
- 存在安全漏洞
- 无迁移方案的破坏性变更
- 基础设计缺陷
Related Skills
相关Skill
- — TRPC router patterns, procedures, error handling
trpc-patterns - — Router, Query, Form patterns
tanstack-frontend - — Effect services, layers, ManagedRuntime, error handling
effect-ts - — Deep Effect compliance scan
scan-effect-solutions - — Performance investigation
production-troubleshooting
- — TRPC路由模式、流程、错误处理
trpc-patterns - — 路由、查询、表单模式
tanstack-frontend - — Effect服务、层级、ManagedRuntime、错误处理
effect-ts - — 深度Effect合规扫描
scan-effect-solutions - — 性能排查
production-troubleshooting