add AGENTS.md

This commit is contained in:
2026-02-12 19:32:41 +08:00
parent ec3cbe7a19
commit 0938cf1ccf

159
AGENTS.md Normal file
View File

@@ -0,0 +1,159 @@
# AGENTS.md - Coding Guidelines for Trace Backend
## Build, Lint, and Test Commands
### Essential Commands
- `pnpm run build` - Build the NestJS application to dist/
- `pnpm run lint` - Run ESLint and auto-fix issues
- `pnpm run format` - Format code with Prettier
- `pnpm run test` - Run all Jest tests
- `pnpm run test:watch` - Run tests in watch mode
- `pnpm run test:cov` - Run tests with coverage report
- `pnpm run start:dev` - Start development server with hot reload
- `pnpm run init-db` - Initialize database (run scripts/init-db.ts)
### Running Single Tests
- `jest path/to/test.spec.ts` - Run a specific test file
- `jest -t "test name"` - Run tests matching a pattern
## Project Overview
This is a NestJS backend for the Trace (贝凡溯源) management platform with:
- **Framework**: NestJS 11.x with TypeScript
- **Database**: SQLite via Prisma ORM with better-sqlite3 adapter
- **Validation**: Zod schemas with nestjs-zod global pipe
- **Auth**: JWT-based authentication with Passport
- **Package Manager**: pnpm 10.x
## Code Style Guidelines
### Imports and Organization
- Use double quotes for all imports: `import { X } from "package"`
- Group external framework imports first, then internal imports
- Use relative imports with `../` or `./` notation
- Example:
```typescript
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import * as bcrypt from "bcryptjs";
import { DatabaseService } from "../database/database.service";
import { User, AuthUser } from "../types";
```
### Naming Conventions
- **Classes**: PascalCase - `AuthService`, `AuthGuard`, `SerialsService`
- **Methods/Functions**: camelCase - `validateUser`, `login`, `getProfile`
- **Variables**: camelCase - `const prisma = ...`
- **Interfaces/Types**: PascalCase - `User`, `AuthUser`, `JWTPayload`
- **DTOs**: PascalCase with "Dto" suffix - `LoginDto`, `ChangePasswordDto`
- **Models**: PascalCase - `User`, `Company`, `Serial` (Prisma models)
### Module Structure
Each feature follows the NestJS pattern:
- `module-name/`
- `module-name.module.ts` - Module definition with imports/providers
- `module-name.controller.ts` - HTTP request handlers
- `module-name.service.ts` - Business logic and database operations
- `dto/` - Zod validation schemas
- `module-name.guard.ts` - Guards (if needed)
### Controllers
- Use appropriate decorators: `@Controller`, `@Get`, `@Post`, `@Patch`, `@Delete`
- Apply guards: `@UseGuards(AuthGuard)` or `@UseGuards(AuthGuard, AdminGuard)`
- Set status codes explicitly: `@HttpCode(HttpStatus.OK)`
- Extract params/query with decorators: `@Param`, `@Query`, `@Body`, `@Req`
- Validate DTOs: `@Body(LoginDto) loginDto: any`
- Return structured responses (see Response Format below)
Example:
```typescript
@Controller("auth")
export class AuthController {
constructor(private authService: AuthService) {}
@Post("login")
@HttpCode(HttpStatus.OK)
async login(@Body(LoginDto) loginDto: any) {
const user = await this.authService.validateUser(loginDto.username, loginDto.password);
return this.authService.login(user);
}
}
```
### Services
- Mark with `@Injectable()` decorator
- Inject dependencies via constructor
- Use `DatabaseService.getPrisma()` to get Prisma client
- Throw `Error` for business logic failures (guards handle auth)
- Use transactions with `prisma.$transaction()` for multi-step operations
### Validation (DTOs)
- Use Zod schemas in `dto/index.ts` files
- Define validation rules with Chinese error messages
- Export from `dto/index.ts` barrel file
Example:
```typescript
export const LoginDto = z.object({
username: z.string().min(1, "用户名不能为空"),
password: z.string().min(1, "密码不能为空"),
});
```
### Error Handling
- Throw NestJS exceptions in controllers/guards:
- `UnauthorizedException` - Auth failures
- `NotFoundException` - Resource not found
- Throw `Error` in services for business logic errors
- Provide Chinese error messages: `throw new Error("用户名或密码错误")`
### Response Format
API responses follow this structure:
```typescript
{
message: "操作描述(中文)",
data?: any,
pagination?: {
page: number,
limit: number,
total: number,
totalPages: number
}
}
```
### Database (Prisma)
- Access Prisma client via `DatabaseService.getPrisma()`
- Use `select` to limit returned fields for security
- Use `include` for relations (user, company)
- Serial numbers should be uppercase: `serialNumber.toUpperCase()`
### Authentication
- Use `@UseGuards(AuthGuard)` for authenticated routes
- Use `@UseGuards(AuthGuard, AdminGuard)` for admin-only routes
- Access user via `@Req() req: Request` and cast: `(req as any).user`
- User object contains: `id`, `username`, `name`, `role`
### TypeScript Configuration
- Target: ES2021
- Strict mode disabled (per tsconfig.json)
- Experimental decorators enabled
- Module: commonjs
### Database Schema
Located in `prisma/schema.prisma`:
- Models: User, Company, Serial
- Relations: User -> Serial, Company -> Serial
- After schema changes: `npx prisma migrate dev` then `npx prisma generate`
### Static Files
- Production: serves from `frontend/dist/`
- Development: serves from `frontend/public/`
- Static assets served via `@nestjs/serve-static`
## Development Notes
- Global API prefix: `/api`
- CORS enabled
- QR code color: dark="#165DFF", light="#ffffff"
- Default serial prefix: "BF" + current year (e.g., "BF26")