Files
backend-node/AGENTS.md
2026-02-12 19:32:41 +08:00

5.4 KiB

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:
    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:

@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:

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:

{
  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")