Files
fahricansecer 7814e0bc6b
Deploy Iddaai Backend / build-and-deploy (push) Failing after 4s
first (part 1: root files)
2026-04-16 15:09:10 +03:00

6.6 KiB
Raw Permalink Blame History

AGENTS.md - Coding Agent Guidelines

Bu dosya, bu repoda çalışan AI kodlama ajanları için rehberdir.


1. Build / Lint / Test Commands

# 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)

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

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

export class CreateUserDto {
  @ApiPropertyOptional({ example: 'user@example.com' })
  @IsEmail()
  email: string;

  @IsString()
  @MinLength(8)
  password: string;

  @IsOptional()
  @IsString()
  firstName?: string;
}

Response DTOs (Security Critical)

@Exclude()
export class UserResponseDto {
  @Expose()
  id: string;

  @Expose()
  email: string;

  // passwordHash intentionally NOT exposed
}

Controller Usage

@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

@Injectable()
export class UsersService extends BaseService<
  User,
  CreateUserDto,
  UpdateUserDto
> {
  constructor(prisma: PrismaService) {
    super(prisma, 'User');
  }

  // Custom methods...
}

Controller Layer

@ApiTags('Users')
@ApiBearerAuth()
@Controller('users')
export class UsersController extends BaseController<
  User,
  CreateUserDto,
  UpdateUserDto
> {
  constructor(private readonly usersService: UsersService) {
    super(usersService, 'User');
  }
}

API Response Format

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

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

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

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

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:

const redisEnabled = process.env.REDIS_ENABLED === 'true';

@Module({
  imports: [
    ...(redisEnabled ? [QueueModule, PredictionsModule] : []),
    // ...
  ],
})

8. Environment Variables

Zorunlu (.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