docs: 完善 CLAUDE.md 开发指南和项目发现工作流文档
- 添加常见开发模式指南(API 端点、数据库字段、自定义 Agent、多语言内容) - 新增故障排除部分,涵盖常见问题和调试技巧 - 改进 GET /api/discovery/tasks 端点,支持通过查询参数传递 API key - 更新环境变量示例,使用更安全的 API key 格式
This commit is contained in:
@@ -228,6 +228,36 @@ Git 提交信息遵循约定式提交格式(详见上方 Code Quality & Standa
|
|||||||
- The middleware handles locale detection and routing automatically - no manual locale configuration needed
|
- The middleware handles locale detection and routing automatically - no manual locale configuration needed
|
||||||
- When adding new translations, update both `src/messages/zh.json` and `src/messages/en.json`
|
- When adding new translations, update both `src/messages/zh.json` and `src/messages/en.json`
|
||||||
- Database changes require running `pnpm prisma migrate dev` to update the schema
|
- Database changes require running `pnpm prisma migrate dev` to update the schema
|
||||||
|
- **Always verify API responses** with `WEBHOOK_API_KEY` when testing webhook or discovery endpoints
|
||||||
|
- **Use `pnpm prisma studio`** to inspect database state during development
|
||||||
|
|
||||||
|
## Common Development Patterns
|
||||||
|
|
||||||
|
### Adding a New API Endpoint
|
||||||
|
1. Create route file in `src/app/api/` (e.g., `src/app/api/your-endpoint/route.ts`)
|
||||||
|
2. Import validation schemas from `@/lib/validations`
|
||||||
|
3. Use `crypto.timingSafeEqual()` for API key authentication (see webhook route:36-43)
|
||||||
|
4. Implement partial success mode for batch operations (see webhook route:55-67)
|
||||||
|
5. Return structured errors with `NextResponse.json()`
|
||||||
|
|
||||||
|
### Adding New Database Fields
|
||||||
|
1. Update `prisma/schema.prisma` with new fields
|
||||||
|
2. Run `pnpm prisma migrate dev --name your_migration_name`
|
||||||
|
3. Update Zod schemas in `src/lib/validations.ts`
|
||||||
|
4. Update TypeScript types in `src/hooks/useProjects.ts` if needed
|
||||||
|
5. Regenerate Prisma client: `pnpm prisma generate`
|
||||||
|
|
||||||
|
### Creating Custom Agents
|
||||||
|
1. Create agent file in `.claude/agents/your-agent.md`
|
||||||
|
2. Define agent role, capabilities, and task instructions
|
||||||
|
3. Reference existing agents (`content-explorer-agent`, `api-submitter-agent`) as templates
|
||||||
|
4. Test via corresponding Claude Command in `.claude/commands/`
|
||||||
|
|
||||||
|
### Working with Multilingual Content
|
||||||
|
- All user-facing content should have both Chinese (`name`, `description`) and English (`nameEn`, `descriptionEn`) versions
|
||||||
|
- Use `src/messages/zh.json` and `src/messages/en.json` for UI translations
|
||||||
|
- For project data, prefer Chinese as primary language with English as optional
|
||||||
|
- When creating content, avoid mechanical translation - write naturally for each locale
|
||||||
|
|
||||||
## Code Quality & Standards
|
## Code Quality & Standards
|
||||||
|
|
||||||
@@ -283,3 +313,79 @@ Git 提交信息遵循约定式提交格式(详见上方 Code Quality & Standa
|
|||||||
- Webhook: Max 100 projects per request
|
- Webhook: Max 100 projects per request
|
||||||
- Discovery tasks: Max 50 tasks per batch creation
|
- Discovery tasks: Max 50 tasks per batch creation
|
||||||
- All queries: Max 100 items per page (enforced via Zod schemas)
|
- All queries: Max 100 items per page (enforced via Zod schemas)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**Database Connection Errors**
|
||||||
|
- Verify `DATABASE_URL` is set in `.env.local`
|
||||||
|
- Check Neon dashboard for database status
|
||||||
|
- Run `pnpm prisma db push` to sync schema if needed
|
||||||
|
|
||||||
|
**Webhook Authentication Failures**
|
||||||
|
- Ensure `WEBHOOK_API_KEY` is set and matches (32+ characters)
|
||||||
|
- Check that API key is sent in request body
|
||||||
|
- Verify timing-safe comparison is used (never log raw API keys)
|
||||||
|
|
||||||
|
**Missing Translations**
|
||||||
|
- All new UI text must be added to both `src/messages/zh.json` and `src/messages/en.json`
|
||||||
|
- Missing keys will display as `missing_key_name` in the UI
|
||||||
|
- Test both locales (switch via URL path `/zh/` or `/en/`)
|
||||||
|
|
||||||
|
**Build Errors After Schema Changes**
|
||||||
|
- Run `pnpm prisma generate` to regenerate Prisma client
|
||||||
|
- Restart dev server after schema changes
|
||||||
|
- Check for TypeScript errors in generated types
|
||||||
|
|
||||||
|
**Discovery Task Failures**
|
||||||
|
- Check `src/app/api/discovery/lib/discovery-service.ts:16-80` for deduplication logic
|
||||||
|
- Verify `WEBHOOK_API_KEY` is set for api-submitter-agent
|
||||||
|
- Use `pnpm prisma studio` to inspect task status and error messages
|
||||||
|
- Check browser console for agent-browser errors (requires chrome-devtools-mcp)
|
||||||
|
|
||||||
|
### Debugging Tips
|
||||||
|
|
||||||
|
1. **Enable Prisma Query Logging**:
|
||||||
|
```typescript
|
||||||
|
// In src/lib/prisma.ts
|
||||||
|
export const prisma = new PrismaClient({
|
||||||
|
log: ['query', 'error', 'warn'],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check Database State**:
|
||||||
|
```bash
|
||||||
|
pnpm prisma studio
|
||||||
|
# Opens at http://localhost:5555
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Test API Endpoints**:
|
||||||
|
```bash
|
||||||
|
# Create discovery task
|
||||||
|
curl -X POST http://localhost:3000/api/discovery/tasks \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"apiKey":"YOUR_KEY","tasks":[{"sourceUrl":"https://github.com/user/repo"}]}'
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Validate Request Payloads**:
|
||||||
|
- All schemas are in `src/lib/validations.ts`
|
||||||
|
- Check schema errors in API response `details` field
|
||||||
|
- Ensure all required fields are present
|
||||||
|
|
||||||
|
### Environment Variables Checklist
|
||||||
|
|
||||||
|
For local development, ensure these are set in `.env.local`:
|
||||||
|
```bash
|
||||||
|
# Database (Neon PostgreSQL)
|
||||||
|
DATABASE_URL="postgres://[user]:[password]@[host]/[database]?sslmode=require"
|
||||||
|
|
||||||
|
# Webhook API Key (32+ characters)
|
||||||
|
WEBHOOK_API_KEY="your-secret-api-key-min-32-chars"
|
||||||
|
```
|
||||||
|
|
||||||
|
For production deployment (Vercel):
|
||||||
|
- Set `DATABASE_URL` in Vercel Dashboard (Environment Variables)
|
||||||
|
- Set `WEBHOOK_API_KEY` in Vercel Dashboard
|
||||||
|
- Run `pnpm prisma db push` after first deployment to create tables
|
||||||
|
- Do NOT use `vercel.json` for environment variables
|
||||||
|
|||||||
@@ -372,11 +372,11 @@ ExternalLink (外部链接表)
|
|||||||
|
|
||||||
```env
|
```env
|
||||||
# .env.local (本地开发)
|
# .env.local (本地开发)
|
||||||
WEBHOOK_API_KEY=your-production-api-key-here # 用于调用完成 API
|
WEBHOOK_API_KEY=sk_live_your_secure_api_key_min_32_chars # 用于调用完成 API
|
||||||
|
|
||||||
# 生产环境 (Vercel Dashboard 配置)
|
# 生产环境 (Vercel Dashboard 配置)
|
||||||
DATABASE_URL=postgres://...
|
DATABASE_URL=postgres://...
|
||||||
WEBHOOK_API_KEY=your-production-api-key-here
|
WEBHOOK_API_KEY=sk_live_your_secure_api_key_min_32_chars
|
||||||
```
|
```
|
||||||
|
|
||||||
### 依赖服务
|
### 依赖服务
|
||||||
|
|||||||
@@ -96,8 +96,11 @@ export async function POST(request: NextRequest) {
|
|||||||
*/
|
*/
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
|
||||||
// 验证 API Key(只读权限)
|
// 验证 API Key(只读权限)
|
||||||
const apiKey = request.headers.get('x-api-key')
|
// 支持两种方式:1. 请求头 x-api-key 2. 查询参数 apiKey
|
||||||
|
const apiKey = request.headers.get('x-api-key') || searchParams.get('apiKey')
|
||||||
const validApiKey = process.env.WEBHOOK_API_KEY
|
const validApiKey = process.env.WEBHOOK_API_KEY
|
||||||
if (
|
if (
|
||||||
!validApiKey ||
|
!validApiKey ||
|
||||||
@@ -109,8 +112,6 @@ export async function GET(request: NextRequest) {
|
|||||||
{ status: 401 }
|
{ status: 401 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { searchParams } = new URL(request.url)
|
|
||||||
const validation = GetDiscoveryTasksQuerySchema.safeParse({
|
const validation = GetDiscoveryTasksQuerySchema.safeParse({
|
||||||
status: searchParams.get('status') || undefined,
|
status: searchParams.get('status') || undefined,
|
||||||
limit: searchParams.get('limit') || '10',
|
limit: searchParams.get('limit') || '10',
|
||||||
|
|||||||
Reference in New Issue
Block a user