# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **MemeMind-Server** is a NestJS backend for a WeChat mini-game called MemeMind. The server handles user authentication via WeChat login, manages game levels and progress, supports social sharing/challenges, and maintains user profiles. All API responses use a standardized format and are exposed under `/api` with Swagger docs at `/api/docs`. ## Tech Stack - **Framework**: NestJS 11 with TypeScript 5.7 - **Database**: MySQL (via TypeORM) - **Authentication**: JWT (7-day expiration) - **Package Manager**: pnpm (with pnpm-lock.yaml) - **Testing**: Jest (unit tests alongside source, e2e tests in `test/`) - **Code Quality**: ESLint + Prettier (single quotes, trailing commas) - **Deployment**: PM2 with rsync to remote server ## Project Structure ``` src/ ├── main.ts # App bootstrap (CORS, validation, Swagger) ├── app.module.ts # Root module importing all features ├── config/ │ ├── config.module.ts # Global config provider (env validation) │ ├── env.validation.ts # Environment variable schema validation │ └── database.config.ts # TypeORM configuration ├── database/ │ └── migrations/ # TypeORM migrations (not heavily used yet) ├── common/ │ ├── dto/api-response.dto.ts # Unified response wrapper (success/error) │ ├── filters/http-exception.filter.ts # Global error handling │ ├── guards/jwt-auth.guard.ts # JWT verification & payload extraction │ └── decorators/current-user.decorator.ts # Param decorator for @CurrentUser() └── modules/ ├── auth/ # WeChat login, user creation, JWT issuance ├── user/ # User profile and stamina management ├── level/ # Game level progression tracking ├── share/ # Social challenge/share features ├── game-config/ # Game configuration endpoints └── wechat-game/ # Shared game entities and repositories docs/ ├── api/ # API documentation (Markdown, auto-synced with code) ├── api/README.md # Index of all API modules └── superpowers/ # Legacy or undocumented features ``` ## Key Commands ### Development ```bash pnpm install # Install dependencies pnpm run start:dev # Run with file watching (http://localhost:3000/api) pnpm run start:debug # Debug mode with Node inspector pnpm run build # Compile TypeScript to dist/ pnpm run start:prod # Run compiled production build ``` ### Code Quality ```bash pnpm run lint # ESLint with auto-fix pnpm run format # Prettier format (src/ and test/) ``` ### Testing ```bash pnpm run test # All unit tests (*.spec.ts in src/) pnpm run test:watch # Watch mode pnpm run test:cov # Coverage report (outputs to coverage/) pnpm run test:debug # Debug unit tests pnpm run test:e2e # E2E tests (test/*.e2e-spec.ts) ``` ### Deployment ```bash pnpm run deploy # Build, rsync to server, restart PM2 cluster ``` ## Architecture Patterns ### Module Structure Each feature module follows NestJS conventions: ```typescript // module.ts: Declares imports (other modules, TypeORM entities, services) @Module({ imports: [TypeOrmModule.forFeature([Entity]), AuthModule], controllers: [FeatureController], providers: [FeatureService, CustomRepository], exports: [FeatureService], // For cross-module injection }) export class FeatureModule {} // controller.ts: HTTP routing, DTO validation, Swagger decorators @Controller('v1/feature') export class FeatureController { @Post() async create(@Body() dto: CreateDto): Promise> @UseGuards(JwtAuthGuard) // Applied per-endpoint @Get(':id') async getOne(@Param('id') id: string, @CurrentUser() user: JwtPayload) } // service.ts: Business logic, repository calls, external API calls @Injectable() export class FeatureService { constructor(private readonly repo: CustomRepository) {} async create(data: CreateDto): Promise { ... } } // repositories/: Custom data access logic (extend TypeORM repositories) @Injectable() export class CustomRepository extends Repository { async customQuery(): Promise { ... } } // dto/: Request/response schemas with class-validator decorators export class CreateDto { @IsString() @MinLength(1) name: string; } ``` ### Authentication & Authorization - **No global guard**: JWT validation is per-endpoint via `@UseGuards(JwtAuthGuard)` - **User extraction**: Use `@CurrentUser()` to inject `JwtPayload { sub: userId, openid }` - **WeChat integration**: `AuthService.wxLogin(code)` calls WeChat API, creates user on first login, issues JWT ### Request/Response Contract All endpoints return `ApiResponseDto`: ```typescript { success: boolean, // true on success, false on error data: T | null, // Response payload or null message: string | null, // Error message (null on success) timestamp: Date // ISO 8601 timestamp } ``` Errors are caught by `HttpExceptionFilter`, which formats exceptions as failed responses. ### Database - **ORM**: TypeORM with MySQL - **Entities**: Auto-loaded from `**/*.entity.ts`, sync mode in dev - **Migrations**: Located in `src/database/migrations/` (minimal usage) - **Connection**: Configured via `ConfigService` (env vars: DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_DATABASE) ## Configuration Environment variables are validated via `env.validation.ts` using class-validator: ``` NODE_ENV # development|production|test (default: development) PORT # Server port (default: 3000) DB_HOST # MySQL host (default: localhost) DB_PORT # MySQL port (default: 3306) DB_USERNAME # MySQL user (default: meme_user) DB_PASSWORD # MySQL password (default: '') DB_DATABASE # MySQL database (default: meme_mind) WX_APPID # WeChat mini-game app ID WX_SECRET # WeChat mini-game secret JWT_SECRET # JWT signing secret ``` Config files loaded in order: `.env.local` → `.env` → `.env.production`. Use `.env.local` for local overrides (never committed). ## Testing - **Unit tests**: Colocated with source as `*.spec.ts` (e.g., `auth.service.spec.ts`) - **E2E tests**: In `test/` directory (e.g., `test/app.e2e-spec.ts`) - **Framework**: Jest with ts-jest compiler - **Coverage**: Run `pnpm run test:cov` to generate coverage report in `coverage/` - **Individual tests**: `pnpm run test -- --testNamePattern="test name"` or `pnpm run test:debug` ## API Documentation API docs are maintained in `docs/api/` and **must be updated whenever controller/DTO changes occur**. The `api-doc-maintainer` skill automates this when editing `src/modules/*/`. **File mapping**: - `docs/api/auth-api.md` → `src/modules/auth/` - `docs/api/game-api.md` → `src/modules/wechat-game/` & `src/modules/level/` - `docs/api/share-challenge-api.md` → `src/modules/share/` **When to update docs**: - New endpoint added - Request/response DTO fields changed - Error codes or business logic modified - Authentication requirements changed Use the template in `AGENTS.md` (api-doc-maintainer skill) for consistent formatting. ## Deployment **Local to production**: 1. Ensure `.env.production` has correct credentials (WX_APPID, WX_SECRET, JWT_SECRET, DB credentials) 2. Run `pnpm run deploy` (triggers `deploy.sh`) 3. Script: builds locally → rsyncs `dist/`, `package.json`, `pnpm-lock.yaml` to `/var/www/MemeMind-Server/` on server → installs deps → restarts PM2 cluster (2 instances) **PM2 config** (`ecosystem.config.js`): Cluster mode (2 instances), auto-restart, 1GB memory limit, logs to `logs/*.log` **Important**: Before deploying, verify deploy.sh credentials (SERVER_IP, SERVER_USER, REMOTE_DIR, APP_NAME) match your target environment. ## Code Style & Conventions - **TypeScript**: Strict mode enabled, no implicit `any`, explicit types on public APIs - **Naming**: Classes PascalCase, methods/variables camelCase, directories kebab-case - **DTO files**: Semantic names (e.g., `wx-login.dto.ts`, `share-response.dto.ts`) - **Quotes**: Single quotes (enforced by Prettier) - **Indentation**: 2 spaces - **Commits**: Use Conventional Commits (e.g., `feat(auth):`, `fix(level):`, `docs(api):`) ## Key Integration Points ### Auth Module - **Controller**: `POST /api/v1/auth/wx-login` - **Flow**: WeChat code → `AuthService.wxLogin()` → calls WeChat API (`jscode2session`) → creates/updates user → signs JWT - **Exports**: `AuthService`, `UserRepository`, `UserLevelProgressRepository` (used by other modules) ### User Module - **Depends on**: AuthModule (for JWT guard, UserRepository) - **Usage**: Profile endpoints, stamina management ### Level Module - **Depends on**: AuthModule, UserModule, WechatGameModule - **Entities**: Reused from WechatGameModule (Level, UserLevelProgress) ### Share Module - **Entities**: ShareConfig, ShareParticipant, ShareLevelProgress (independent tables) - **Depends on**: WechatGameModule, AuthModule - **Pattern**: Multi-table repository pattern for complex queries ## Common Development Tasks - **Add a new API endpoint**: Create DTO in `modules/{feature}/dto/`, add method to controller, implement in service, call `pnpm run lint && pnpm run test` to verify - **Add a new entity**: Create `*.entity.ts` in module folder, add to TypeOrmModule.forFeature in module, update relevant repository - **Modify API response format**: Update DTO/entity, regenerate Swagger docs, update `docs/api/*.md` manually if not auto-synced - **Debug a failing test**: Run `pnpm run test:debug -- --testNamePattern="specific test"` and use Node inspector - **Run migrations**: TypeORM in-dev synchronize mode auto-creates tables; for production, use TypeORM CLI or manual SQL ## Troubleshooting - **Port 3000 in use**: `lsof -i :3000` and `kill -9 `, or change PORT env var - **Database connection fails**: Verify DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD in `.env.local` match your MySQL setup - **JWT verification fails**: Check JWT_SECRET is consistent across app instances and `.env` files - **Swagger not loading**: Ensure app.listen() completes; check browser console for CORS errors - **Tests hanging**: Check for open database connections; run `pnpm run test:debug` to inspect - **Prettier/ESLint conflicts**: Run `pnpm run format && pnpm run lint` in sequence (format first, then lint) ## Additional Resources - **NestJS docs**: https://docs.nestjs.com - **TypeORM docs**: https://typeorm.io - **Project-specific guidance**: See `AGENTS.md` for multi-agent collaboration patterns