workspace/projects/gamilit/CONTRIBUTING.md
rckrdmrd ea1879f4ad feat: Initial workspace structure with multi-level Git configuration
- Configure workspace Git repository with comprehensive .gitignore
- Add Odoo as submodule for ERP reference code
- Include documentation: SETUP.md, GIT-STRUCTURE.md
- Add gitignore templates for projects (backend, frontend, database)
- Structure supports independent repos per project/subproject level

Workspace includes:
- core/ - Reusable patterns, modules, orchestration system
- projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.)
- knowledge-base/ - Reference code and patterns (includes Odoo submodule)
- devtools/ - Development tools and templates
- customers/ - Client implementations template

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 10:44:23 -06:00

662 lines
14 KiB
Markdown

# Contributing to GAMILIT
¡Gracias por tu interés en contribuir a GAMILIT! Este documento te guiará a través del proceso de contribución.
---
## 📋 Tabla de Contenidos
1. [Código de Conducta](#código-de-conducta)
2. [Pre-requisitos](#pre-requisitos)
3. [Setup del Entorno de Desarrollo](#setup-del-entorno-de-desarrollo)
4. [Workflow de Desarrollo](#workflow-de-desarrollo)
5. [**Constants SSOT - Pre-Commit Checklist**](#constants-ssot---pre-commit-checklist) ⭐
6. [Estándares de Código](#estándares-de-código)
7. [Commits y Pull Requests](#commits-y-pull-requests)
8. [Testing](#testing)
9. [Documentación](#documentación)
---
## Código de Conducta
Este proyecto sigue un código de conducta profesional. Se espera que todos los contribuyentes:
- Sean respetuosos y constructivos en sus interacciones
- Acepten críticas constructivas con profesionalismo
- Se enfoquen en lo mejor para la comunidad y el proyecto
- Muestren empatía hacia otros miembros de la comunidad
---
## Pre-requisitos
Antes de contribuir, asegúrate de tener instalado:
- **Node.js** >= 18.0.0
- **npm** >= 9.0.0
- **Git** >= 2.30
- **PostgreSQL** >= 15.x (para desarrollo local)
- **Docker** (opcional, para contenedores)
---
## Setup del Entorno de Desarrollo
### 1. Fork y Clone
```bash
# Fork el repositorio en GitHub
# Luego clona tu fork
git clone https://github.com/TU_USUARIO/gamilit.git
cd gamilit/projects/gamilit
# Agrega el upstream
git remote add upstream https://github.com/GAMILIT_ORG/gamilit.git
```
### 2. Instalar Dependencias
```bash
# Instalar dependencias root (incluye postinstall que ejecuta sync:enums)
npm install
# Instalar dependencias Backend
cd apps/backend
npm install
# Instalar dependencias Frontend
cd ../frontend
npm install
# Volver a root
cd ../..
```
### 3. Configurar Variables de Entorno
```bash
# Backend
cp apps/backend/.env.example apps/backend/.env
# Editar apps/backend/.env con tus credenciales
# Frontend
cp apps/frontend/.env.example apps/frontend/.env
# Editar apps/frontend/.env con tu API URL
```
### 4. Setup de Base de Datos
```bash
# Crear base de datos
createdb gamilit_dev
# Ejecutar migraciones (cuando estén disponibles)
cd apps/backend
npm run migration:run
```
### 5. Verificar Setup
```bash
# Desde root, ejecutar validaciones
npm run validate:all
# Debe retornar:
# ✅ ENUMs sincronizados exitosamente
# ✅ EXCELENTE! No se encontraron violaciones de hardcoding
# ✅ API Contract validado
```
---
## Workflow de Desarrollo
### 1. Crear Branch
```bash
# Actualizar main
git checkout main
git pull upstream main
# Crear feature branch
git checkout -b feature/mi-nueva-funcionalidad
# O bug fix branch
git checkout -b fix/corregir-bug-autenticacion
```
**Convención de nombres de branches:**
- `feature/` - Nuevas funcionalidades
- `fix/` - Corrección de bugs
- `refactor/` - Refactorización de código
- `docs/` - Cambios en documentación
- `test/` - Agregar o mejorar tests
- `chore/` - Tareas de mantenimiento
### 2. Desarrollar
```bash
# Backend
cd apps/backend
npm run dev # Modo desarrollo con hot-reload
# Frontend (en otra terminal)
cd apps/frontend
npm run dev # Vite dev server
```
### 3. Hacer Commits
Ver sección [Commits y Pull Requests](#commits-y-pull-requests) para convenciones.
---
## Constants SSOT - Pre-Commit Checklist ⭐
**IMPORTANTE:** Antes de hacer commit, **SIEMPRE** ejecutar este checklist para asegurar el cumplimiento de la política SSOT.
### Checklist Obligatorio
```bash
# ✅ 1. Sincronizar ENUMs Backend → Frontend
npm run sync:enums
# ✅ 2. Validar que no haya hardcoding (33 patrones detectados)
npm run validate:constants
# ✅ 3. Validar contrato API Backend ↔ Frontend
npm run validate:api-contract
# ✅ 4. Ejecutar tests
npm run test
# ✅ 5. Ejecutar linter
npm run lint
# ✅ 6. Si TODO pasa, hacer commit
git add .
git commit -m "feat: agregar nueva funcionalidad"
```
**Atajo para validar todo:**
```bash
npm run validate:all && npm run test && git commit
```
### ¿Cuándo actualizar constantes?
#### Al crear nueva tabla Database:
1. ✅ Crear DDL en `platform/db/ddl/schemas/{schema}/tables/{tabla}.sql`
2.**INMEDIATAMENTE** agregar entrada en `apps/backend/src/shared/constants/database.constants.ts`:
```typescript
export const DB_TABLES = {
AUTH: {
// ... existing tables
NEW_TABLE: 'new_table', // ← AGREGAR AQUÍ
},
};
```
3. ✅ Crear Entity usando la nueva constante:
```typescript
import { DB_SCHEMAS, DB_TABLES } from '@/shared/constants';
@Entity({ schema: DB_SCHEMAS.AUTH, name: DB_TABLES.AUTH.NEW_TABLE })
export class NewTable { ... }
```
#### Al crear nueva ruta API Backend:
1.**PRIMERO** agregar entrada en `apps/backend/src/shared/constants/routes.constants.ts`:
```typescript
export const API_ROUTES = {
NEW_MODULE: {
BASE: '/new-module',
BY_ID: (id: string) => `/new-module/${id}`,
},
};
```
2. ✅ Crear Controller usando la nueva constante:
```typescript
import { API_ROUTES } from '@/shared/constants';
@Controller(API_ROUTES.NEW_MODULE.BASE.replace('/', ''))
export class NewModuleController { ... }
```
3.**INMEDIATAMENTE** agregar en Frontend `apps/frontend/src/shared/constants/api-endpoints.ts`:
```typescript
export const API_ENDPOINTS = {
NEW_MODULE: {
BASE: `${API_BASE_URL}/new-module`,
BY_ID: (id: string) => `${API_BASE_URL}/new-module/${id}`,
},
};
```
4. ✅ Validar sincronización:
```bash
npm run validate:api-contract
# Debe retornar: ✅ API Contract validado
```
#### Al crear nuevo ENUM:
1.**Definir ENUM solo en Backend** `apps/backend/src/shared/constants/enums.constants.ts`:
```typescript
export enum NewEnum {
VALUE_1 = 'value_1',
VALUE_2 = 'value_2',
}
```
2.**Ejecutar script de sincronización:**
```bash
npm run sync:enums
```
3.**Verificar** que Frontend tiene el mismo ENUM:
```bash
diff apps/backend/src/shared/constants/enums.constants.ts \
apps/frontend/src/shared/constants/enums.constants.ts
# Debe retornar: (sin diferencias)
```
4.**NO modificar manualmente** el archivo Frontend (se sobrescribe en sync).
### Violaciones Comunes y Cómo Evitarlas
#### ❌ Violación 1: Hardcoded schema en Entity
**Detectado por:** `npm run validate:constants`
```typescript
// ❌ MAL
@Entity({ schema: 'auth_management', name: 'users' })
export class User { ... }
// ✅ BIEN
import { DB_SCHEMAS, DB_TABLES } from '@/shared/constants';
@Entity({ schema: DB_SCHEMAS.AUTH, name: DB_TABLES.AUTH.USERS })
export class User { ... }
```
#### ❌ Violación 2: Hardcoded API URL en Frontend
**Detectado por:** `npm run validate:constants`
```typescript
// ❌ MAL
await fetch('http://localhost:3000/api/v1/users/123');
// ✅ BIEN
import { API_ENDPOINTS } from '@/shared/constants';
await fetch(API_ENDPOINTS.USERS.BY_ID('123'));
```
#### ❌ Violación 3: Discrepancia Backend ↔ Frontend
**Detectado por:** `npm run validate:api-contract`
```
❌ Ruta "/users/:id/settings" existe en Backend pero NO en Frontend
```
**Solución:** Sincronizar ambos archivos (Backend routes.constants.ts y Frontend api-endpoints.ts)
### Documentación de Referencia
- **Arquitectura completa:** [CONSTANTS-ARCHITECTURE.md](../../../docs-analysis/miniworkspace-migration/06-agents/migracion-desarrollo/CONSTANTS-ARCHITECTURE.md)
- **Políticas obligatorias:** [POLITICA-CONSTANTS-SSOT.md](../../../docs-analysis/miniworkspace-migration/06-agents/migracion-desarrollo/POLITICA-CONSTANTS-SSOT.md)
---
## Estándares de Código
### TypeScript
- **Estilo:** Airbnb TypeScript Style Guide
- **Linter:** ESLint con reglas de @typescript-eslint
- **Formatter:** Prettier con configuración del proyecto
```bash
# Ejecutar linter
npm run lint
# Ejecutar formatter
npm run format
```
### Naming Conventions
**Variables y Funciones:**
```typescript
// camelCase
const userName = 'John';
function getUserById(id: string) { ... }
```
**Clases y Interfaces:**
```typescript
// PascalCase
class UserService { ... }
interface IUserRepository { ... }
```
**Constantes:**
```typescript
// UPPER_SNAKE_CASE para constantes globales
export const MAX_LOGIN_ATTEMPTS = 3;
// PascalCase para ENUMs
export enum UserRole {
ADMIN = 'admin',
TEACHER = 'teacher',
STUDENT = 'student',
}
```
**Archivos:**
```
user.entity.ts # Entities
user.dto.ts # DTOs
user.service.ts # Services
user.controller.ts # Controllers
user.module.ts # Modules
user.spec.ts # Tests
```
### Import Organization
```typescript
// 1. Node modules
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
// 2. Internal modules
import { DB_SCHEMAS, DB_TABLES } from '@/shared/constants';
import { User } from '@/modules/auth/entities/user.entity';
// 3. Relative imports
import { CreateUserDto } from './dto/create-user.dto';
```
---
## Commits y Pull Requests
### Conventional Commits
Usamos [Conventional Commits](https://www.conventionalcommits.org/) para mensajes de commit:
```
<type>(<scope>): <subject>
[optional body]
[optional footer]
```
**Types:**
- `feat`: Nueva funcionalidad
- `fix`: Corrección de bug
- `refactor`: Refactorización de código
- `docs`: Cambios en documentación
- `test`: Agregar o mejorar tests
- `chore`: Tareas de mantenimiento
- `style`: Cambios de formato (no afectan lógica)
- `perf`: Mejoras de performance
**Ejemplos:**
```bash
feat(auth): agregar autenticación con Google OAuth
fix(gamification): corregir cálculo de puntos en quiz
refactor(database): migrar entities a usar DB_SCHEMAS constants
docs(readme): actualizar sección de Constants SSOT
test(users): agregar tests para UserService
```
### Pull Request Process
1. **Actualizar branch con main:**
```bash
git checkout main
git pull upstream main
git checkout tu-feature-branch
git rebase main
```
2. **Ejecutar validaciones:**
```bash
# ✅ Validar SSOT
npm run validate:all
# ✅ Ejecutar tests
npm run test
# ✅ Ejecutar linter
npm run lint
```
3. **Crear Pull Request en GitHub:**
**Título:** Usar Conventional Commits format
```
feat(auth): agregar autenticación con Google OAuth
```
**Descripción:** Incluir template
```markdown
## Descripción
Breve descripción de los cambios realizados.
## Tipo de cambio
- [ ] 🐛 Bug fix (cambio que corrige un issue)
- [ ] ✨ Nueva funcionalidad (cambio que agrega funcionalidad)
- [ ] 💥 Breaking change (fix o feature que causa cambios incompatibles)
- [ ] 📝 Documentación
## Checklist
- [ ] Mi código sigue las convenciones del proyecto
- [ ] He ejecutado `npm run validate:all`
- [ ] He ejecutado `npm run test` y todos los tests pasan ✅
- [ ] He ejecutado `npm run lint`
- [ ] He actualizado la documentación correspondiente
- [ ] Mis cambios no generan nuevas advertencias
- [ ] He agregado tests que prueban mi fix/funcionalidad
- [ ] Tests unitarios y de integración pasan localmente
- [ ] He sincronizado ENUMs si modifiqué Backend enums (`npm run sync:enums`)
- [ ] He actualizado constantes si agregué schemas/tablas/rutas
## Screenshots (si aplica)
## Notas adicionales
```
4. **Code Review:**
- Mínimo **1 aprobación** requerida
- CI/CD debe pasar (validate-constants.yml + tests)
- Resolver todos los comentarios antes de merge
5. **Merge:**
- **Squash and merge** preferido para features pequeñas
- **Merge commit** para features grandes
- **Rebase and merge** para branches con commits limpios
---
## Testing
### Backend Tests
```bash
cd apps/backend
# Ejecutar todos los tests
npm run test
# Tests en modo watch
npm run test:watch
# Cobertura de tests
npm run test:cov
```
**Estructura de tests:**
```typescript
describe('UserService', () => {
let service: UserService;
let repository: Repository<User>;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [UserService, /* ... */],
}).compile();
service = module.get<UserService>(UserService);
repository = module.get<Repository<User>>(getRepositoryToken(User));
});
describe('findById', () => {
it('should return a user when found', async () => {
const user = { id: '1', email: 'test@test.com' };
jest.spyOn(repository, 'findOne').mockResolvedValue(user as User);
expect(await service.findById('1')).toBe(user);
});
it('should throw NotFoundException when user not found', async () => {
jest.spyOn(repository, 'findOne').mockResolvedValue(null);
await expect(service.findById('999')).rejects.toThrow(NotFoundException);
});
});
});
```
### Frontend Tests
```bash
cd apps/frontend
# Ejecutar tests
npm run test
# Tests con UI
npm run test:ui
# Cobertura
npm run test:coverage
```
**Estructura de tests:**
```typescript
import { render, screen, fireEvent } from '@testing-library/react';
import { LoginForm } from './LoginForm';
describe('LoginForm', () => {
it('renders email and password inputs', () => {
render(<LoginForm />);
expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
});
it('calls onSubmit when form is submitted', async () => {
const mockSubmit = jest.fn();
render(<LoginForm onSubmit={mockSubmit} />);
fireEvent.change(screen.getByLabelText(/email/i), {
target: { value: 'test@test.com' },
});
fireEvent.click(screen.getByRole('button', { name: /login/i }));
expect(mockSubmit).toHaveBeenCalledWith({
email: 'test@test.com',
password: expect.any(String),
});
});
});
```
---
## Documentación
### Documentar Código
**JSDoc para funciones públicas:**
```typescript
/**
* Obtiene un usuario por su ID
*
* @param id - UUID del usuario
* @returns Promise con el usuario encontrado
* @throws NotFoundException si el usuario no existe
*
* @example
* ```typescript
* const user = await userService.findById('123e4567-e89b-12d3-a456-426614174000');
* ```
*/
async findById(id: string): Promise<User> {
// ...
}
```
### Actualizar Documentación
Si tus cambios afectan:
- **API Endpoints:** Actualizar Swagger/OpenAPI docs
- **Schemas de Database:** Actualizar DDL y documentation
- **Funcionalidades nuevas:** Actualizar README.md y docs relevantes
- **Cambios arquitectónicos:** Crear ADR (Architecture Decision Record)
---
## ¿Preguntas?
- **Slack:** #dev-support
- **Email:** dev@gamilit.com
- **Issues:** [GitHub Issues](https://github.com/GAMILIT_ORG/gamilit/issues)
---
**¡Gracias por contribuir a GAMILIT!** 🚀
**Versión:** 1.0
**Última actualización:** 2025-11-02