This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
# AGENTS.md - Coding Agent Guidelines
|
||||
|
||||
Bu dosya, bu repoda çalışan AI kodlama ajanları için rehberdir.
|
||||
|
||||
---
|
||||
|
||||
## 1. Build / Lint / Test Commands
|
||||
|
||||
```bash
|
||||
# Development
|
||||
npm run start:dev # Dev server with watch mode
|
||||
npm run build # Production build (nest build)
|
||||
|
||||
# Linting & Formatting
|
||||
npm run lint # ESLint with Prettier
|
||||
npm run format # Prettier write
|
||||
|
||||
# Testing
|
||||
npm run test # Run all unit tests
|
||||
npm run test:watch # Watch mode
|
||||
npm run test:e2e # End-to-end tests
|
||||
npx jest src/path/to/file.spec.ts # Run single test file
|
||||
npx jest --testNamePattern="test name" # Run specific test
|
||||
|
||||
# Database
|
||||
npx prisma generate # Generate Prisma client (required after install)
|
||||
npx prisma migrate dev # Run migrations
|
||||
npx prisma db seed # Seed database
|
||||
|
||||
# Feeder Scripts
|
||||
npm run feeder:historical # Historical data fetch
|
||||
npm run feeder:live # Live match data fetch
|
||||
npm run feeder:basketball # Basketball data fetch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Code Style Guidelines
|
||||
|
||||
### Imports (Sıralama)
|
||||
|
||||
```typescript
|
||||
// 1. NestJS/common imports
|
||||
import { Controller, Get, Post, Body } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||||
|
||||
// 2. External packages
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
// 3. Local imports (relative)
|
||||
import { UsersService } from './users.service';
|
||||
import { CreateUserDto } from './dto/user.dto';
|
||||
import { ApiResponse, createSuccessResponse } from '../../common/types';
|
||||
```
|
||||
|
||||
### Formatting
|
||||
|
||||
- **Single quotes** for strings
|
||||
- **Trailing commas** always
|
||||
- Prettier ile formatlama zorunlu
|
||||
- Dosya sonu boş satır
|
||||
|
||||
### Types & Type Safety
|
||||
|
||||
- `strictNullChecks: true` - null/undefined kontrolü zorunlu
|
||||
- `noImplicitAny: false` - any kullanımına izin var (Prisma dynamic access için)
|
||||
- Fonksiyon return type belirt: `async findOne(id: string): Promise<User>`
|
||||
- Interface > Type alias (objeler için)
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
```typescript
|
||||
// Classes & Interfaces: PascalCase
|
||||
class UsersService {}
|
||||
interface ApiResponse<T> {}
|
||||
|
||||
// Variables & Functions: camelCase
|
||||
const userService = new UsersService();
|
||||
async function findUserById() {}
|
||||
|
||||
// Constants: UPPER_SNAKE_CASE
|
||||
const JWT_SECRET = 'secret';
|
||||
const IS_PUBLIC_KEY = 'isPublic';
|
||||
|
||||
// Files: kebab-case
|
||||
user.dto.ts;
|
||||
users.service.ts;
|
||||
predictions.processor.spec.ts;
|
||||
|
||||
// DTOs: Entity + Dto suffix
|
||||
(CreateUserDto, UpdateUserDto, UserResponseDto);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. DTO Pattern
|
||||
|
||||
### Request DTOs
|
||||
|
||||
```typescript
|
||||
export class CreateUserDto {
|
||||
@ApiPropertyOptional({ example: 'user@example.com' })
|
||||
@IsEmail()
|
||||
email: string;
|
||||
|
||||
@IsString()
|
||||
@MinLength(8)
|
||||
password: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
firstName?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Response DTOs (Security Critical)
|
||||
|
||||
```typescript
|
||||
@Exclude()
|
||||
export class UserResponseDto {
|
||||
@Expose()
|
||||
id: string;
|
||||
|
||||
@Expose()
|
||||
email: string;
|
||||
|
||||
// passwordHash intentionally NOT exposed
|
||||
}
|
||||
```
|
||||
|
||||
### Controller Usage
|
||||
|
||||
```typescript
|
||||
@Get('me')
|
||||
async getMe(@CurrentUser() user: User): Promise<ApiResponse<UserResponseDto>> {
|
||||
const fullUser = await this.usersService.findOneWithDetails(user.id);
|
||||
return createSuccessResponse(
|
||||
plainToInstance(UserResponseDto, fullUser),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**KRITIK:** Asla raw Prisma entity döndürme. Her zaman Response DTO kullan.
|
||||
|
||||
---
|
||||
|
||||
## 4. Architecture Patterns
|
||||
|
||||
### Service Layer
|
||||
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class UsersService extends BaseService<
|
||||
User,
|
||||
CreateUserDto,
|
||||
UpdateUserDto
|
||||
> {
|
||||
constructor(prisma: PrismaService) {
|
||||
super(prisma, 'User');
|
||||
}
|
||||
|
||||
// Custom methods...
|
||||
}
|
||||
```
|
||||
|
||||
### Controller Layer
|
||||
|
||||
```typescript
|
||||
@ApiTags('Users')
|
||||
@ApiBearerAuth()
|
||||
@Controller('users')
|
||||
export class UsersController extends BaseController<
|
||||
User,
|
||||
CreateUserDto,
|
||||
UpdateUserDto
|
||||
> {
|
||||
constructor(private readonly usersService: UsersService) {
|
||||
super(usersService, 'User');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Response Format
|
||||
|
||||
```typescript
|
||||
// All responses use this structure
|
||||
{
|
||||
"success": true,
|
||||
"status": 200,
|
||||
"message": "Success",
|
||||
"data": { ... },
|
||||
"errors": []
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
createSuccessResponse(data, 'Message')
|
||||
createErrorResponse('Message', 400, ['error1'])
|
||||
createPaginatedResponse(items, total, page, limit)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Error Handling
|
||||
|
||||
### Throw NestJS HTTP Exceptions
|
||||
|
||||
```typescript
|
||||
// Correct
|
||||
throw new NotFoundException('User not found');
|
||||
throw new ConflictException('EMAIL_ALREADY_EXISTS');
|
||||
throw new UnauthorizedException('INVALID_CREDENTIALS');
|
||||
|
||||
// Wrong
|
||||
throw new Error('User not found'); // Don't use generic Error
|
||||
```
|
||||
|
||||
### i18n Error Keys
|
||||
|
||||
```typescript
|
||||
// Use translatable keys (check src/i18n/{lang}/errors.json)
|
||||
throw new ConflictException('EMAIL_ALREADY_EXISTS');
|
||||
// Translates to: "Email already exists" (en) / "Email zaten kayıtlı" (tr)
|
||||
```
|
||||
|
||||
### Global Exception Filter
|
||||
|
||||
- Tüm hatalar HTTP 200 ile döner (status body içinde)
|
||||
- `NODE_ENV=development` ise stack trace eklenir
|
||||
- Validation hataları otomatik formatlanır
|
||||
|
||||
---
|
||||
|
||||
## 6. Testing
|
||||
|
||||
### Unit Test Structure
|
||||
|
||||
```typescript
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
describe('UsersService', () => {
|
||||
let service: UsersService;
|
||||
let prisma: PrismaService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
UsersService,
|
||||
{ provide: PrismaService, useValue: mockPrisma },
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<UsersService>(UsersService);
|
||||
});
|
||||
|
||||
it('should find user by id', async () => {
|
||||
// Arrange
|
||||
mockPrisma.user.findUnique.mockResolvedValue(mockUser);
|
||||
|
||||
// Act
|
||||
const result = await service.findOne('id');
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Mocking External Dependencies
|
||||
|
||||
```typescript
|
||||
jest.mock('axios');
|
||||
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockedAxios.post.mockResolvedValue({ data: { ok: true } });
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Module Registration
|
||||
|
||||
Redis-enabled modüller için `app.module.ts`:
|
||||
|
||||
```typescript
|
||||
const redisEnabled = process.env.REDIS_ENABLED === 'true';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
...(redisEnabled ? [QueueModule, PredictionsModule] : []),
|
||||
// ...
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Environment Variables
|
||||
|
||||
Zorunlu (`.env`):
|
||||
|
||||
```env
|
||||
NODE_ENV=development
|
||||
PORT=3005
|
||||
DATABASE_URL=postgresql://postgres:password@localhost:15432/boilerplate_db
|
||||
JWT_SECRET=your-secret-key
|
||||
JWT_ACCESS_EXPIRATION=15m
|
||||
REDIS_ENABLED=false
|
||||
AI_ENGINE_URL=http://127.0.0.1:8000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Pre-commit Checklist
|
||||
|
||||
1. `npm run lint` - Lint errors fixed
|
||||
2. `npm run build` - Build succeeds
|
||||
3. `npm run test` - All tests pass
|
||||
4. Response DTOs used for all API responses
|
||||
5. No secrets/credentials in code
|
||||
Reference in New Issue
Block a user