Files
math2-platform/backend/ARCHITECTURE_PLAN.md
Renato bc43c9e772
Some checks failed
Test Suite / test-backend (push) Has been cancelled
Test Suite / test-frontend (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / coverage-check (push) Has been cancelled
🎓 Initial commit: Math2 Platform - Plataforma de Álgebra Lineal PRO
 Características:
- 45 ejercicios universitarios (Basic → Advanced)
- Renderizado LaTeX profesional
- IA generativa (Z.ai/DashScope)
- Docker 9 servicios
- Tests 123/123 pasando
- Seguridad enterprise (JWT, XSS, Rate limiting)

🐳 Infraestructura:
- Next.js 14 + Node.js 20
- PostgreSQL 15 + Redis 7
- Docker Compose completo
- Nginx + SSL ready

📚 Documentación:
- 5 informes técnicos completos
- README profesional
- Scripts de deployment automatizados

Estado: Producción lista 
2026-03-31 11:27:11 -03:00

12 KiB

Backend Professionalization Plan - Math Platform

Executive Summary

This document outlines the complete migration plan to transform the Math Platform backend into an enterprise-grade system with strict TypeScript, clean architecture, and professional patterns.

Current Status

Errors Found (Initial)

  • Total TypeScript Errors: 159
  • Categories:
    • TS6133: Unused variables/imports (~25)
    • TS2345: Type undefined not assignable to string (~40)
    • TS2375/TS2379: exactOptionalPropertyTypes issues (~60)
    • TS2322: Type null/undefined assignment errors (~20)
    • TS6196: Unused type declarations (~10)
    • Other misc errors (~4)

Errors Fixed in This Session

  1. ✓ Fixed jwt.sign type issues in auth.service.ts
  2. ✓ Fixed topicId null handling in exercise.service.ts
  3. ✓ Removed unused ValidationError import
  4. ✓ Removed unused adminChatId variable
  5. ✓ Removed unused getTelegramAdminChatId import
  6. ✓ Fixed module.controller.ts imports

Remaining: ~150 errors

Architecture Implemented

1. Configuration System ✓

Location: src/config/index.ts

Features:

  • Zod schema validation for all environment variables
  • Type-safe config object
  • Computed properties (isDevelopment, isProduction, etc.)
  • Centralized defaults and constants

Usage:

import { config } from './config';

// Type-safe access
const port = config.PORT;
const isDev = config.isDevelopment;

2. Enterprise Error System ✓

Location: src/core/errors/index.ts

Features:

  • Hierarchical error classes (AppError base)
  • Error codes enum for frontend mapping
  • HTTP status code mapping
  • Structured logging support
  • Prisma error mapping
  • Production vs development responses

Error Types:

  • ValidationError (400)
  • AuthenticationError (401)
  • AuthorizationError (403)
  • NotFoundError (404)
  • ConflictError (409)
  • RateLimitError (429)
  • DatabaseError (500)
  • ExternalServiceError (502)
  • ServiceUnavailableError (503)

3. Core Types ✓

Location: src/core/types/index.ts

Includes:

  • API response types (ApiSuccessResponse, ApiErrorResponse)
  • Pagination types (PaginatedResult, PaginationMeta)
  • Service types (ServiceResult, ServiceContext)
  • Repository types (QueryOptions, RepositoryOptions)
  • Event types (DomainEvent, EventHandler)
  • Utility types (Nullable, Optional, DeepPartial)

4. Error Middleware ✓

Location: src/shared/middleware/error.middleware.ts

Features:

  • Global error handling
  • Automatic Prisma error mapping
  • Structured logging with correlation IDs
  • Production-safe error messages
  • Async handler wrapper

5. Rate Limiting ✓

Location: src/shared/middleware/rate-limit.middleware.ts

Features:

  • Redis-backed store
  • Multiple limiter configurations
  • Custom key generation (user-based or IP-based)
  • Standard HTTP headers
  • Professional error responses

Limiters:

  • standardRateLimiter: 100 req/15min
  • authRateLimiter: 5 req/15min
  • exerciseRateLimiter: 30 req/5min
  • aiRateLimiter: 20 req/min
  • adminRateLimiter: 300 req/15min

6. Dependency Injection Container (In Progress)

Location: src/infrastructure/di/container.ts

Dependencies to install:

npm install tsyringe reflect-metadata

Update tsconfig.json:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

7. Repository Pattern (In Progress)

Location: src/repositories/

Structure:

repositories/
├── interfaces/
│   ├── exercise.repository.interface.ts
│   ├── user.repository.interface.ts
│   └── ...
├── exercise.repository.ts
├── user.repository.ts
└── ...

Features:

  • Interface-based design
  • Prisma implementation
  • Caching support hooks
  • Query optimization
  • Transaction support

8. Service Layer Refactor (TODO)

Pattern:

export interface IExerciseService {
  create(data: CreateExerciseDTO): Promise<Exercise>;
  findById(id: string): Promise<Exercise | null>;
  update(id: string, data: UpdateExerciseDTO): Promise<Exercise>;
  delete(id: string): Promise<void>;
}

@injectable()
export class ExerciseService implements IExerciseService {
  constructor(
    @inject(TOKENS.ExerciseRepository) 
    private readonly repository: IExerciseRepository,
    @inject(TOKENS.Logger)
    private readonly logger: Logger,
    @inject(TOKENS.CacheService)
    private readonly cache: CacheService
  ) {}
}

Migration Plan

Phase 1: Fix TypeScript Errors (Priority: High)

1.1 Fix exactOptionalPropertyTypes Issues

Pattern: Replace prop?: Type with prop: Type | undefined

Example:

// Before
interface Options {
  userId?: string;
  moduleId?: string;
}

// After
interface Options {
  userId: string | undefined;
  moduleId: string | undefined;
}

Files to fix (40+ occurrences):

  • exercise.controller.ts (7 errors)
  • module.controller.ts (7 errors)
  • progress.controller.ts (3 errors)
  • ranking.controller.ts (3 errors)
  • user.controller.ts (3 errors)
  • All *service.ts files

1.2 Fix undefined to string assignments

Pattern: Add null checks before function calls

Example:

// Before
const id = req.params.id; // string | undefined
await service.findById(id); // Error

// After
const id = req.params.id;
if (!id) {
  throw new ValidationError('ID is required');
}
await service.findById(id); // OK

1.3 Fix Prisma type issues

Pattern: Handle null types from Prisma

Example:

// Before
topicId: string; // But Prisma returns string | null

// After
topicId: string | null;

1.4 Remove unused imports and variables

Pattern: Clean up imports and use _ prefix for unused params

Example:

// Before
import { ValidationError } from '../types'; // Unused

const handler = (req, res, next) => { // req unused
  res.json({ data });
};

// After
const handler = (_req, res, _next) => {
  res.json({ data });
};

Phase 2: Implement Repository Pattern (Priority: High)

2.1 Create Repository Interfaces

For each entity (User, Exercise, Module, Progress, Ranking):

  • Define interface in src/repositories/interfaces/
  • Specify all CRUD operations
  • Include query options and filters

2.2 Implement Prisma Repositories

  • Create implementation in src/repositories/
  • Use dependency injection
  • Add caching hooks
  • Handle errors with AppError

2.3 Migrate Services

  • Update services to use repositories
  • Add proper typing
  • Implement logging

Phase 3: Implement DI Container (Priority: Medium)

3.1 Setup tsyringe

// In server.ts
import 'reflect-metadata';
import { container } from './infrastructure/di/container';

// Register dependencies
container.register(TOKENS.PrismaClient, { useValue: prisma });
container.register(TOKENS.ExerciseRepository, { useClass: ExerciseRepository });

3.2 Decorate Services

@injectable()
export class ExerciseService {
  constructor(
    @inject(TOKENS.ExerciseRepository)
    private readonly repository: IExerciseRepository
  ) {}
}

Phase 4: Update Server Configuration (Priority: Medium)

4.1 Replace Old Middleware

Update src/server.ts:

  • Use new error middleware
  • Use new rate limiters
  • Add correlation ID middleware
  • Use structured logging

4.2 Add Health Checks

  • Database health
  • Redis health
  • AI service health

Phase 5: Testing (Priority: High)

5.1 Unit Tests

Target: >80% coverage

  • Service layer tests
  • Repository tests
  • Error handling tests

5.2 Integration Tests

  • API endpoint tests
  • Database transaction tests
  • Redis integration tests

5.3 E2E Tests

  • Full user flows
  • Error scenarios

Code Examples

New Service Pattern

// src/modules/exercise/exercise.service.ts

import { injectable, inject } from 'tsyringe';
import { TOKENS } from '../../infrastructure/di/container';
import { IExerciseRepository } from '../../repositories/interfaces/exercise.repository.interface';
import { AppError, NotFoundError, ValidationError } from '../../core/errors';
import type { CreateExerciseDTO, UpdateExerciseDTO } from './dtos';
import type { Exercise } from '@prisma/client';

export interface IExerciseService {
  create(data: CreateExerciseDTO): Promise<Exercise>;
  findById(id: string): Promise<Exercise | null>;
  update(id: string, data: UpdateExerciseDTO): Promise<Exercise>;
  delete(id: string): Promise<void>;
  list(filters: ExerciseFilterOptions): Promise<PaginatedResult<Exercise>>;
}

@injectable()
export class ExerciseService implements IExerciseService {
  constructor(
    @inject(TOKENS.ExerciseRepository)
    private readonly repository: IExerciseRepository,
    @inject(TOKENS.Logger)
    private readonly logger: Logger
  ) {}

  async create(data: CreateExerciseDTO): Promise<Exercise> {
    this.logger.info('Creating exercise', { title: data.statement });
    
    try {
      const exercise = await this.repository.create(data);
      this.logger.info('Exercise created', { exerciseId: exercise.id });
      return exercise;
    } catch (error) {
      this.logger.error('Failed to create exercise', { error, data });
      throw new AppError('Failed to create exercise', ErrorCode.INTERNAL_ERROR);
    }
  }

  async findById(id: string): Promise<Exercise | null> {
    if (!id) {
      throw new ValidationError('Exercise ID is required');
    }

    const exercise = await this.repository.findById(id);
    
    if (!exercise) {
      throw new NotFoundError('Exercise');
    }

    return exercise;
  }

  // ... other methods
}

New Controller Pattern

// src/modules/exercise/exercise.controller.ts

import { Request, Response } from 'express';
import { injectable, inject } from 'tsyringe';
import { TOKENS } from '../../infrastructure/di/container';
import { IExerciseService } from './exercise.service';
import { asyncHandler } from '../../shared/middleware/error.middleware';

@injectable()
export class ExerciseController {
  constructor(
    @inject(TOKENS.ExerciseService)
    private readonly service: IExerciseService
  ) {}

  getById = asyncHandler(async (req: Request, res: Response): Promise<void> => {
    const id = req.params.id;
    
    if (!id) {
      throw new ValidationError('Exercise ID is required');
    }

    const exercise = await this.service.findById(id);
    
    res.json({
      success: true,
      data: exercise,
    });
  });

  // ... other methods
}

Error Handling

// In controllers - just throw
try {
  await service.doSomething();
} catch (error) {
  if (error instanceof Prisma.PrismaClientKnownRequestError) {
    throw mapPrismaError(error, req.correlationId);
  }
  throw new AppError(
    'Operation failed',
    ErrorCode.INTERNAL_ERROR,
    500,
    false,
    { originalError: error },
    req.correlationId
  );
}

// Middleware handles the rest

Commands

Check TypeScript Errors

cd /home/ren/Documents/math2/backend
npm run type-check

Fix Lint Issues

npm run lint:fix

Run Tests

npm run test:coverage

Build

npm run build

Recommendations

  1. Enable strict mode in phases: Fix errors in batches by directory
  2. Use type assertion sparingly: Only for external library issues
  3. Add comprehensive tests: Before refactoring, add tests for current behavior
  4. Use feature flags: For gradual rollout of new architecture
  5. Document breaking changes: Update API documentation
  6. Monitor error rates: After deployment

Timeline Estimate

  • Phase 1 (TypeScript fixes): 2-3 days
  • Phase 2 (Repositories): 3-4 days
  • Phase 3 (DI setup): 1-2 days
  • Phase 4 (Server update): 1-2 days
  • Phase 5 (Testing): 3-4 days

Total: ~10-15 days for complete migration

Next Steps

  1. Continue fixing TypeScript errors using the patterns above
  2. Create repository interfaces for all entities
  3. Implement Prisma repositories
  4. Refactor services one by one
  5. Update server.ts with new middleware
  6. Add comprehensive tests
  7. Deploy and monitor

Resources