From 5cc476cedce6ede52c299176a908dc81f312c46e Mon Sep 17 00:00:00 2001 From: imbytecat Date: Sat, 7 Feb 2026 01:14:12 +0800 Subject: [PATCH] docs: streamline AGENTS.md for AI agents - translate to English, reduce to 150 lines --- AGENTS.md | 344 +++++++++++++++++++++--------------------------------- 1 file changed, 130 insertions(+), 214 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 11bc1ea..0c73ad2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,248 +1,123 @@ # AGENTS.md - AI Coding Agent Guidelines -本文档为 AI 编程助手提供此 TanStack Start 全栈项目的开发规范和指南。 +## Project Overview -## 项目概览 +TanStack Start fullstack app with Tauri desktop shell. -- **框架**: TanStack Start (React SSR 框架,文件路由) -- **运行时**: Bun -- **语言**: TypeScript (strict mode, ESNext) -- **样式**: Tailwind CSS v4 -- **数据库**: PostgreSQL + Drizzle ORM -- **状态管理**: TanStack Query -- **路由**: TanStack Router (文件路由) -- **RPC**: ORPC (类型安全 RPC,契约优先) -- **构建工具**: Vite + Turbo -- **代码质量**: Biome (格式化 + Lint) -- **桌面壳** (可选): Tauri v2 (详见 `src-tauri/AGENTS.md`) +| Layer | Tech | +|-------|------| +| Framework | TanStack Start (React SSR, file-based routing) | +| Runtime | Bun | +| Language | TypeScript (strict mode) | +| Styling | Tailwind CSS v4 | +| Database | PostgreSQL + Drizzle ORM | +| RPC | ORPC (contract-first, type-safe) | +| Build | Vite + Turbo | +| Linting | Biome | +| Desktop | Tauri v2 (optional, see `src-tauri/AGENTS.md`) | -## 构建、Lint 和测试命令 +## Commands -### 开发 ```bash -bun dev # 使用 Turbo 并行启动 Tauri + Vite 开发服务器 -bun dev:vite # 仅启动 Vite 开发服务器 (localhost:3000) -bun dev:tauri # 启动 Tauri 桌面应用 -bun db:studio # 打开 Drizzle Studio 数据库管理界面 +# Development +bun dev # Start Tauri + Vite via Turbo +bun dev:vite # Vite only (localhost:3000) +bun db:studio # Drizzle Studio + +# Build +bun build # Full build (Vite → compile → Tauri) +bun build:vite # Vite only (outputs to .output/) + +# Code Quality +bun typecheck # TypeScript check (tsc -b) +bun fix # Biome auto-fix (format + lint) + +# Database +bun db:generate # Generate migrations from schema +bun db:migrate # Run migrations +bun db:push # Push schema changes (dev only) + +# Testing (not configured yet) +# When adding tests, use Vitest or Bun test runner: +# bun test path/to/test.ts # Single file +# bun test -t "pattern" # By test name ``` -### 构建 -```bash -bun build # 完整构建 (Vite → 编译 → Tauri 打包) -bun build:vite # 仅构建 Vite (输出到 .output/) -bun build:compile # 编译为独立可执行文件 (使用 build.ts) -bun build:tauri # 构建 Tauri 桌面安装包 -``` +## Code Style -### 代码质量 -```bash -bun typecheck # 运行 TypeScript 编译器检查 (tsc -b) -bun fix # 运行 Biome 自动修复格式和 Lint 问题 -biome check . # 检查但不自动修复 -biome format --write . # 仅格式化代码 -``` +### Formatting (Biome enforced) -### 数据库 -```bash -bun db:generate # 从 schema 生成迁移文件 -bun db:migrate # 执行数据库迁移 -bun db:push # 直接推送 schema 变更 (仅开发环境) -``` +- **Indent**: 2 spaces +- **Line endings**: LF +- **Quotes**: Single `'string'` +- **Semicolons**: As needed (ASI) +- **Arrow parens**: Always `(x) => x` -### 测试 -**注意**: 当前未配置测试框架。添加测试时: -- 使用 Vitest 或 Bun 内置测试运行器 -- 运行单个测试文件: `bun test path/to/test.ts` -- 运行特定测试: `bun test -t "测试名称模式"` +### Imports -## 代码风格指南 +Biome auto-organizes. Order: external → internal (`@/*`) → type-only imports. -### 格式化 (Biome) - -**缩进**: 2 空格 (不使用 tab) -**换行符**: LF (Unix 风格) -**引号**: 单引号 `'string'` -**分号**: 按需 (ASI - 自动分号插入) -**箭头函数括号**: 始终使用 `(x) => x` - -示例: -```typescript -const myFunc = (value: string) => { - return value.toUpperCase() -} -``` - -### 导入组织 - -Biome 自动组织导入。顺序: -1. 外部依赖 -2. 内部导入 (使用 `@/*` 别名) -3. 类型导入 (仅导入类型时使用 `type` 关键字) - -示例: ```typescript import { createFileRoute } from '@tanstack/react-router' -import { oc } from '@orpc/contract' import { z } from 'zod' import { db } from '@/db' -import { todoTable } from '@/db/schema' import type { ReactNode } from 'react' ``` ### TypeScript -**严格模式**: 启用了额外的严格检查 -- `strict: true` -- `noUncheckedIndexedAccess: true` - 数组/对象索引返回 `T | undefined` +Strict mode with extra checks: +- `noUncheckedIndexedAccess: true` - array/object index returns `T | undefined` - `noImplicitOverride: true` -- `noFallthroughCasesInSwitch: true` +- `verbatimModuleSyntax: true` -**模块解析**: `bundler` 模式 + `verbatimModuleSyntax` -- 导入时始终使用 `.ts`/`.tsx` 扩展名 -- 使用 `@/*` 路径别名指向 `src/*` +Path alias: `@/*` → `src/*` -**类型注解**: -- 公共 API 的函数参数和返回类型必须注解 -- 优先使用显式类型而非 `any` -- 对象形状用 `type`,可扩展契约用 `interface` -- 不可变 props 使用 `Readonly` +### Naming -### 命名规范 +| Entity | Convention | Example | +|--------|------------|---------| +| Files (utils) | kebab-case | `utils.ts`, `db-provider.ts` | +| Files (components) | PascalCase | `NotFound.tsx` | +| Routes | TanStack conventions | `routes/index.tsx`, `routes/__root.tsx` | +| Components | PascalCase arrow functions | `const MyComponent = () => {}` | +| Functions | camelCase | `handleSubmit` | +| Constants | UPPER_SNAKE_CASE | `MAX_RETRIES` | +| Types/Interfaces | PascalCase | `TodoItem`, `RouterContext` | -- **文件**: 工具函数用 kebab-case,组件用 PascalCase - - `utils.ts`, `todo.tsx`, `NotFound.tsx` -- **路由**: 遵循 TanStack Router 约定 - - `routes/index.tsx` → `/` - - `routes/__root.tsx` → 根布局 -- **组件**: PascalCase 箭头函数 (Biome 规则 `useArrowFunction` 强制) -- **函数**: camelCase -- **常量**: 真常量用 UPPER_SNAKE_CASE,配置对象用 camelCase -- **类型/接口**: PascalCase +### React Patterns -### React 模式 - -**组件**: 使用箭头函数 ```typescript +// Components: arrow functions (Biome enforces) const MyComponent = ({ title }: { title: string }) => { return
{title}
} -``` -**路由**: 使用 `createFileRoute` 定义路由 -```typescript +// Routes: createFileRoute export const Route = createFileRoute('/')({ component: Home, + loader: async ({ context }) => { + await context.queryClient.ensureQueryData(orpc.todo.list.queryOptions()) + }, }) + +// Data fetching: TanStack Query +const query = useSuspenseQuery(orpc.todo.list.queryOptions()) +const mutation = useMutation(orpc.todo.create.mutationOptions()) ``` -**数据获取**: 使用 TanStack Query hooks -- `useSuspenseQuery` - 保证有数据 -- `useQuery` - 数据可能为空 +### ORPC Pattern (Contract-First RPC) -**Props**: 禁止直接修改 props (Biome 规则 `noReactPropAssignments`) - -### 数据库 Schema (Drizzle) - -- 在 `src/db/schema/*.ts` 定义 schema -- 从 `src/db/schema/index.ts` 导出 -- 使用 `drizzle-orm/pg-core` 的 PostgreSQL 类型 -- 主键使用 `uuidv7()` (需要 PostgreSQL 扩展) -- 始终包含 `createdAt` 和 `updatedAt` 时间戳 - -示例: -```typescript -import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core' -import { sql } from 'drizzle-orm' - -export const myTable = pgTable('my_table', { - id: uuid().primaryKey().default(sql`uuidv7()`), - name: text().notNull(), - createdAt: timestamp({ withTimezone: true }).notNull().defaultNow(), - updatedAt: timestamp({ withTimezone: true }).notNull().defaultNow().$onUpdateFn(() => new Date()), -}) -``` - -### 环境变量 - -- 使用 `@t3-oss/env-core` 进行类型安全的环境变量验证 -- 在 `src/env.ts` 定义 schema -- 服务端变量: 无前缀 -- 客户端变量: 必须有 `VITE_` 前缀 -- 使用 Zod schema 验证 - -### 错误处理 - -- 异步操作使用 try-catch -- 抛出带有描述性消息的错误 -- 用户界面错误优先使用 Result 类型或错误边界 -- 适当记录错误 (避免记录敏感数据) - -### 样式 (Tailwind CSS) - -- 使用 Tailwind v4 工具类 -- 通过 `@/styles.css?url` 导入样式 -- 优先使用组合而非自定义 CSS -- 响应式修饰符: `sm:`, `md:`, `lg:` -- UI 文本适当使用中文 - -## 目录结构 - -``` -src/ -├── components/ # 可复用 React 组件 -├── db/ -│ ├── schema/ # Drizzle schema 定义 -│ └── index.ts # 数据库实例 -├── integrations/ # 第三方集成 (TanStack Query/Router) -├── lib/ # 工具函数 -├── orpc/ # ORPC (RPC 层) -│ ├── contracts/ # 契约定义 (input/output schemas) -│ ├── handlers/ # 服务端过程实现 -│ ├── middlewares/ # 中间件 (如 DB provider) -│ ├── contract.ts # 契约聚合 -│ ├── router.ts # 路由组合 -│ ├── server.ts # 服务端实例 -│ └── client.ts # 同构客户端 -├── routes/ # TanStack Router 文件路由 -│ ├── __root.tsx # 根布局 -│ ├── index.tsx # 首页 -│ └── api/rpc.$.ts # ORPC HTTP 端点 -├── env.ts # 环境变量验证 -└── router.tsx # 路由配置 -``` - -## 重要提示 - -- **禁止** 编辑 `src/routeTree.gen.ts` - 自动生成 -- **禁止** 提交 `.env` 文件 - 使用 `.env.example` 作为模板 -- **必须** 在提交前运行 `bun fix` -- **必须** 使用 `@/*` 路径别名而非相对导入 -- **必须** 利用 React Compiler (babel-plugin-react-compiler) - 避免手动 memoization - -## Git 工作流 - -1. 按照上述风格指南进行修改 -2. 运行 `bun fix` 自动格式化和 lint -3. 运行 `bun typecheck` 确保类型安全 -4. 使用 `bun dev` 本地测试变更 -5. 使用清晰的描述性消息提交 - -## 常见模式 - -### 创建 ORPC 过程 - -**步骤 1: 定义契约** (`src/orpc/contracts/my-feature.ts`) +1. **Define contract** (`src/orpc/contracts/my-feature.ts`): ```typescript import { oc } from '@orpc/contract' import { z } from 'zod' -export const myContract = { - get: oc.input(z.object({ id: z.uuid() })).output(mySchema), - create: oc.input(createSchema).output(mySchema), -} +export const get = oc.input(z.object({ id: z.uuid() })).output(schema) +export const create = oc.input(insertSchema).output(schema) ``` -**步骤 2: 实现处理器** (`src/orpc/handlers/my-feature.ts`) +2. **Implement handler** (`src/orpc/handlers/my-feature.ts`): ```typescript import { os } from '@/orpc/server' import { dbProvider } from '@/orpc/middlewares' @@ -254,24 +129,65 @@ export const get = os.myFeature.get }) ``` -**步骤 3: 注册到契约和路由** -```typescript -// src/orpc/contract.ts -export const contract = { myFeature: myContract } +3. **Register** in `contract.ts` and `router.ts` +4. **Use** in components via `orpc.myFeature.get.queryOptions()` -// src/orpc/router.ts -import * as myFeature from './handlers/my-feature' -export const router = os.router({ myFeature }) +### Drizzle Schema + +```typescript +import { sql } from 'drizzle-orm' +import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core' + +export const myTable = pgTable('my_table', { + id: uuid('id').primaryKey().default(sql`uuidv7()`), + name: text('name').notNull(), + createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), + updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow().$onUpdateFn(() => new Date()), +}) ``` -**步骤 4: 在组件中使用** -```typescript -import { orpc } from '@/orpc' -const query = useSuspenseQuery(orpc.myFeature.get.queryOptions({ id })) -const mutation = useMutation(orpc.myFeature.create.mutationOptions()) +### Environment Variables + +- Server: no prefix (e.g., `DATABASE_URL`) +- Client: `VITE_` prefix required +- Validated via `@t3-oss/env-core` in `src/env.ts` + +## Directory Structure + +``` +src/ +├── components/ # Reusable React components +├── db/ +│ ├── schema/ # Drizzle schema definitions +│ └── index.ts # Database instance +├── integrations/ # TanStack Query/Router setup +├── lib/ # Utility functions +├── orpc/ +│ ├── contracts/ # Input/output schemas +│ ├── handlers/ # Server procedure implementations +│ ├── middlewares/ # Middleware (e.g., dbProvider) +│ ├── contract.ts # Contract aggregation +│ ├── router.ts # Router composition +│ └── client.ts # Isomorphic client +├── routes/ # File-based routes +│ ├── __root.tsx # Root layout +│ └── api/rpc.$.ts # ORPC HTTP endpoint +└── env.ts # Environment validation ``` ---- +## Critical Rules -**最后更新**: 2026-01-18 -**项目版本**: 基于 package.json 依赖版本 +- **DO NOT** edit `src/routeTree.gen.ts` (auto-generated) +- **DO NOT** commit `.env` files +- **MUST** run `bun fix` before commits +- **MUST** use `@/*` path alias (not relative imports) +- **MUST** use React Compiler (no manual memoization needed) +- **MUST** use `Readonly` for immutable props + +## Git Workflow + +1. Make changes following style guide +2. Run `bun fix` (format + lint) +3. Run `bun typecheck` (type safety) +4. Test with `bun dev` +5. Commit with descriptive message