@damenor/agent-docs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -0
- package/dist/index.js +568 -0
- package/package.json +53 -0
- package/templates/base/AGENTS.md +177 -0
- package/templates/base/CHANGELOG.md +86 -0
- package/templates/base/README.md +110 -0
- package/templates/base/docs/CONTEXT.md +111 -0
- package/templates/base/docs/README.md +131 -0
- package/templates/base/docs/adr/TEMPLATE.md +83 -0
- package/templates/modules/agents/.agents/agents/doc-designer.md +56 -0
- package/templates/modules/agents/.agents/agents/doc-maintainer.md +54 -0
- package/templates/modules/agents/.agents/agents/doc-reviewer.md +80 -0
- package/templates/modules/agents/.agents/agents/doc-writer.md +66 -0
- package/templates/modules/agents/.agents/agents/reviewer.md +138 -0
- package/templates/modules/agents/.agents/skills/doc-design/SKILL.md +359 -0
- package/templates/modules/agents/.agents/skills/doc-design/references/design-system-format.md +550 -0
- package/templates/modules/agents/.agents/skills/doc-maintain/SKILL.md +345 -0
- package/templates/modules/agents/.agents/skills/doc-maintain/references/triggers.md +311 -0
- package/templates/modules/agents/.agents/skills/doc-review/SKILL.md +324 -0
- package/templates/modules/agents/.agents/skills/doc-review/references/health-checklist.md +290 -0
- package/templates/modules/agents/.agents/skills/doc-scaffold/SKILL.md +277 -0
- package/templates/modules/agents/.agents/skills/doc-scaffold/references/diataxis-quick-ref.md +149 -0
- package/templates/modules/agents/.agents/skills/doc-write/SKILL.md +414 -0
- package/templates/modules/agents/.agents/skills/doc-write/references/adr-format.md +194 -0
- package/templates/modules/agents/.agents/skills/doc-write/references/diataxis-patterns.md +351 -0
- package/templates/modules/ci/.github/workflows/docs-check.yml +94 -0
- package/templates/modules/design/docs/DESIGN.md +253 -0
- package/templates/modules/explanation/docs/explanation/agent-flow.md +15 -0
- package/templates/modules/explanation/docs/explanation/architecture.md +138 -0
- package/templates/modules/guides/docs/guides/deployment.md +189 -0
- package/templates/modules/guides/docs/guides/runbooks/TEMPLATE.md +86 -0
- package/templates/modules/guides/docs/guides/troubleshooting.md +65 -0
- package/templates/modules/operations/docs/operations/README.md +115 -0
- package/templates/modules/product/docs/product/overview.md +90 -0
- package/templates/modules/product/docs/roadmap.md +80 -0
- package/templates/modules/reference/docs/reference/api.md +131 -0
- package/templates/modules/reference/docs/reference/code-style.md +275 -0
- package/templates/modules/reference/docs/reference/configuration.md +117 -0
- package/templates/modules/reference/docs/reference/infrastructure.md +191 -0
- package/templates/modules/tutorials/docs/tutorials/environment-setup.md +212 -0
- package/templates/modules/tutorials/docs/tutorials/first-task.md +246 -0
- package/templates/modules/tutorials/docs/tutorials/quick-start.md +146 -0
- package/templates/shared/.editorconfig +20 -0
- package/templates/shared/.markdownlint.json +14 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
created: "2025-01-01"
|
|
3
|
+
status: active
|
|
4
|
+
type: planning
|
|
5
|
+
tags: [roadmap, planificación, features, backlog]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Roadmap
|
|
9
|
+
|
|
10
|
+
## Estado actual
|
|
11
|
+
|
|
12
|
+
**Versión actual**: [versión — ej. 0.1.0]
|
|
13
|
+
**Fase**: [Discovery / MVP / Growth / Maintenance]
|
|
14
|
+
**Último release**: [fecha — ej. 2025-01-15]
|
|
15
|
+
**Próximo release planificado**: [fecha o "Por definir"]
|
|
16
|
+
|
|
17
|
+
Resumen del estado: [1-2 oraciones describiendo dónde está el proyecto ahora. Ej. "MVP funcional con autenticación y CRUD básico. Pendiente de integración con sistema de pagos."]
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Próximos features
|
|
22
|
+
|
|
23
|
+
| Feature | Descripción | Prioridad | Estado | Responsable | Target |
|
|
24
|
+
|---------|-------------|-----------|--------|-------------|--------|
|
|
25
|
+
| [Feature 1] | [Descripción breve de qué hace y por qué] | 🔴 Alta | [Estado: Planificado / En progreso / En QA / Listo] | [Nombre o rol] | [Fecha o sprint] |
|
|
26
|
+
| [Feature 2] | [Descripción] | 🟡 Media | [Estado] | [Responsable] | [Target] |
|
|
27
|
+
| [Feature 3] | [Descripción] | 🟢 Baja | [Estado] | [Responsable] | [Target] |
|
|
28
|
+
|
|
29
|
+
### Detalle por feature
|
|
30
|
+
|
|
31
|
+
#### [Feature 1]
|
|
32
|
+
- **Por qué**: [Justificación de negocio o técnica.]
|
|
33
|
+
- **Criterios de aceptación**:
|
|
34
|
+
- [ ] [Criterio 1]
|
|
35
|
+
- [ ] [Criterio 2]
|
|
36
|
+
- [ ] [Criterio 3]
|
|
37
|
+
- **Dependencias**: [Otros features, equipos, servicios externos.]
|
|
38
|
+
- **Riesgos**: [Qué podría salir mal. Mitigación.]
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Backlog
|
|
43
|
+
|
|
44
|
+
Ideas y features que se quieren hacer pero que no tienen fecha asignada aún.
|
|
45
|
+
|
|
46
|
+
| Feature | Descripción | Fuente de la idea |
|
|
47
|
+
|---------|-------------|------------------|
|
|
48
|
+
| [Feature idea 1] | [Qué es y por qué sería valioso] | [Stakeholder / usuario / equipo] |
|
|
49
|
+
| [Feature idea 2] | [Descripción] | [Fuente] |
|
|
50
|
+
| [Feature idea 3] | [Descripción] | [Fuente] |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Decisiones pendientes
|
|
55
|
+
|
|
56
|
+
| Decisión | Contexto | Opciones consideradas | Plazo para decidir | Responsable |
|
|
57
|
+
|----------|----------|----------------------|-------------------|-------------|
|
|
58
|
+
| [Decisión 1] | [Por qué hay que tomar esta decisión. Qué pasa si no se decide.] | [Opción A, Opción B] | [Fecha] | [Quién decide] |
|
|
59
|
+
| [Decisión 2] | [Contexto] | [Opciones] | [Fecha] | [Responsable] |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Historial de releases
|
|
64
|
+
|
|
65
|
+
| Versión | Fecha | Cambios principales | Notas |
|
|
66
|
+
|---------|-------|-------------------|-------|
|
|
67
|
+
| [0.1.0] | [2025-01-15] | Inicialización del proyecto, estructura base | Primer release |
|
|
68
|
+
| [0.2.0] | [YYYY-MM-DD] | [Features principales del release] | [Notas adicionales] |
|
|
69
|
+
|
|
70
|
+
Ver el detalle completo de cambios en [`CHANGELOG.md`](../../CHANGELOG.md).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Cómo actualizar este archivo
|
|
75
|
+
|
|
76
|
+
- **Al planificar un sprint**: Actualizar la tabla de "Próximos features" con prioridades y responsables.
|
|
77
|
+
- **Al iniciar un feature**: Cambiar estado a "En progreso".
|
|
78
|
+
- **Al completar un feature**: Cambiar estado a "Listo", mover a "Historial de releases".
|
|
79
|
+
- **Al recibir un request nuevo**: Añadir al Backlog si no es inmediato, o a "Próximos features" si sí.
|
|
80
|
+
- **Al tomar una decisión técnica**: Mover de "Decisiones pendientes" y crear un ADR en `docs/adr/`.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
created: "2026-05-07"
|
|
3
|
+
updated: "2026-05-07"
|
|
4
|
+
status: active
|
|
5
|
+
type: reference
|
|
6
|
+
tags: [api, reference, endpoints]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Referencia de API
|
|
10
|
+
|
|
11
|
+
Documentación de referencia de los endpoints del proyecto.
|
|
12
|
+
|
|
13
|
+
> [!tip] Convención
|
|
14
|
+
> Si la API crece a más de 10 endpoints, convierte este archivo en una carpeta `api/` con un archivo por dominio.
|
|
15
|
+
|
|
16
|
+
## Autenticación
|
|
17
|
+
|
|
18
|
+
| Método | Descripción | Header |
|
|
19
|
+
|--------|-------------|--------|
|
|
20
|
+
| Bearer Token | JWT enviado en header | `Authorization: Bearer <token>` |
|
|
21
|
+
|
|
22
|
+
**Flujo**:
|
|
23
|
+
1. Cliente envía credenciales a `/auth/login`
|
|
24
|
+
2. Server devuelve `{ token, refreshToken }`
|
|
25
|
+
3. Cliente incluye `Authorization: Bearer <token>` en requests siguientes
|
|
26
|
+
4. Si token expira, usar refresh token en `/auth/refresh`
|
|
27
|
+
|
|
28
|
+
## Endpoints
|
|
29
|
+
|
|
30
|
+
### [Recurso]
|
|
31
|
+
|
|
32
|
+
#### `GET /api/[recurso]`
|
|
33
|
+
|
|
34
|
+
Lista recursos con paginación.
|
|
35
|
+
|
|
36
|
+
**Headers**:
|
|
37
|
+
| Header | Requerido | Descripción |
|
|
38
|
+
|--------|-----------|-------------|
|
|
39
|
+
| `Authorization` | Sí | Bearer token |
|
|
40
|
+
|
|
41
|
+
**Query Parameters**:
|
|
42
|
+
| Param | Tipo | Default | Descripción |
|
|
43
|
+
|-------|------|---------|-------------|
|
|
44
|
+
| `page` | number | 1 | Página actual |
|
|
45
|
+
| `limit` | number | 20 | Items por página (max 100) |
|
|
46
|
+
| `sort` | string | `-createdAt` | Campo de orden (`-` para desc) |
|
|
47
|
+
|
|
48
|
+
**Response 200**:
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"data": [
|
|
52
|
+
{
|
|
53
|
+
"id": "string",
|
|
54
|
+
"name": "string",
|
|
55
|
+
"createdAt": "ISO 8601"
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"meta": {
|
|
59
|
+
"page": 1,
|
|
60
|
+
"limit": 20,
|
|
61
|
+
"total": 100
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### `POST /api/[recurso]`
|
|
67
|
+
|
|
68
|
+
Crea un nuevo recurso.
|
|
69
|
+
|
|
70
|
+
**Body**:
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"name": "string (required, max 200)",
|
|
74
|
+
"description": "string (optional)"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Response 201**:
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"id": "string",
|
|
82
|
+
"name": "string",
|
|
83
|
+
"description": "string",
|
|
84
|
+
"createdAt": "ISO 8601",
|
|
85
|
+
"updatedAt": "ISO 8601"
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Códigos de Error
|
|
90
|
+
|
|
91
|
+
| Status | Código | Descripción |
|
|
92
|
+
|--------|--------|-------------|
|
|
93
|
+
| 400 | `VALIDATION_ERROR` | Datos de entrada inválidos |
|
|
94
|
+
| 401 | `UNAUTHORIZED` | Token ausente o inválido |
|
|
95
|
+
| 403 | `FORBIDDEN` | Sin permisos para el recurso |
|
|
96
|
+
| 404 | `NOT_FOUND` | Recurso no encontrado |
|
|
97
|
+
| 409 | `CONFLICT` | Recurso ya existe |
|
|
98
|
+
| 422 | `UNPROCESSABLE` | Entidad no procesable |
|
|
99
|
+
| 429 | `RATE_LIMITED` | Demasiados requests |
|
|
100
|
+
| 500 | `INTERNAL_ERROR` | Error interno del servidor |
|
|
101
|
+
|
|
102
|
+
**Formato de error**:
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"error": {
|
|
106
|
+
"code": "VALIDATION_ERROR",
|
|
107
|
+
"message": "Descripción legible del error",
|
|
108
|
+
"details": [
|
|
109
|
+
{ "field": "name", "message": "Name is required" }
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Rate Limiting
|
|
116
|
+
|
|
117
|
+
| Tier | Requests/minuto | Burst |
|
|
118
|
+
|------|-----------------|-------|
|
|
119
|
+
| Standard | 60 | 10 |
|
|
120
|
+
| Premium | 300 | 50 |
|
|
121
|
+
|
|
122
|
+
Headers de respuesta:
|
|
123
|
+
- `X-RateLimit-Limit`: Límite por ventana
|
|
124
|
+
- `X-RateLimit-Remaining`: Requests restantes
|
|
125
|
+
- `X-RateLimit-Reset`: Timestamp cuando se resetea
|
|
126
|
+
|
|
127
|
+
## Versionado
|
|
128
|
+
|
|
129
|
+
La API usa versionado en URL: `/api/v1/`, `/api/v2/`.
|
|
130
|
+
|
|
131
|
+
Versiones anteriores se mantienen durante 6 meses después del release de una nueva versión mayor.
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
created: "2026-05-07"
|
|
3
|
+
updated: "2026-05-07"
|
|
4
|
+
status: active
|
|
5
|
+
type: reference
|
|
6
|
+
tags: [code-style, conventions, reference, standards]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Code Style
|
|
10
|
+
|
|
11
|
+
Convenciones de código del proyecto. Todo código nuevo DEBE seguir estas reglas.
|
|
12
|
+
|
|
13
|
+
> [!important] Regla general
|
|
14
|
+
> Lo que se puede automatizar (linter, formatter), se automatiza. Lo que no, se documenta aquí.
|
|
15
|
+
|
|
16
|
+
## Automatización
|
|
17
|
+
|
|
18
|
+
El proyecto usa estas herramientas para enforcear estilo automáticamente:
|
|
19
|
+
|
|
20
|
+
| Herramienta | Qué enforcea | Archivo config |
|
|
21
|
+
|-------------|-------------|----------------|
|
|
22
|
+
| [ESLint / Pylint / etc.] | Reglas de código | [config file] |
|
|
23
|
+
| [Prettier / Black / etc.] | Formateo | [config file] |
|
|
24
|
+
| [TypeScript / mypy / etc.] | Tipos | [config file] |
|
|
25
|
+
| EditorConfig | Configuración del editor | `.editorconfig` |
|
|
26
|
+
|
|
27
|
+
**Si el linter pasa, el estilo es correcto.** No discutir estilo que el linter ya resuelve.
|
|
28
|
+
|
|
29
|
+
## Nombramiento
|
|
30
|
+
|
|
31
|
+
### Archivos y Carpetas
|
|
32
|
+
|
|
33
|
+
| Tipo | Convención | Ejemplo |
|
|
34
|
+
|------|-----------|---------|
|
|
35
|
+
| Componentes UI | `PascalCase` | `Button.tsx`, `NavBar.vue` |
|
|
36
|
+
| Utilidades | `camelCase` | `formatDate.ts`, `parseConfig.js` |
|
|
37
|
+
| Tests | `[nombre].test/spec.[ext]` | `auth.test.ts`, `api.spec.ts` |
|
|
38
|
+
| Tipos/Interfaces | `PascalCase` | `User.ts`, `ApiResponse.ts` |
|
|
39
|
+
| Constantes | `UPPER_SNAKE_CASE` | `API_URLS.ts`, `MAX_RETRIES.ts` |
|
|
40
|
+
| Páginas/Rutas | `kebab-case` | `user-profile.tsx`, `about.vue` |
|
|
41
|
+
|
|
42
|
+
### Variables y Funciones
|
|
43
|
+
|
|
44
|
+
| Tipo | Convención | Ejemplo |
|
|
45
|
+
|------|-----------|---------|
|
|
46
|
+
| Variables | `camelCase` | `userName`, `isActive` |
|
|
47
|
+
| Constantes | `UPPER_SNAKE_CASE` | `MAX_RETRIES`, `API_BASE_URL` |
|
|
48
|
+
| Funciones | `camelCase` | `getUser()`, `calculateTotal()` |
|
|
49
|
+
| Booleanos | `is`/`has`/`should` prefix | `isLoading`, `hasPermission` |
|
|
50
|
+
| Clases | `PascalCase` | `UserService`, `HttpClient` |
|
|
51
|
+
| Interfaces/Types | `PascalCase` | `User`, `ApiResponse` |
|
|
52
|
+
| Enums | `PascalCase` | `UserRole`, `OrderStatus` |
|
|
53
|
+
| Eventos | `on` prefix | `onClick`, `onSubmit` |
|
|
54
|
+
|
|
55
|
+
## Imports
|
|
56
|
+
|
|
57
|
+
### Orden de imports
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// 1. Librerías externas
|
|
61
|
+
import { useState, useEffect } from 'react'
|
|
62
|
+
import axios from 'axios'
|
|
63
|
+
|
|
64
|
+
// 2. Imports internos (alias si están configurados)
|
|
65
|
+
import { Button } from '@/components/ui/Button'
|
|
66
|
+
import { useAuth } from '@/hooks/useAuth'
|
|
67
|
+
|
|
68
|
+
// 3. Tipos
|
|
69
|
+
import type { User, ApiResponse } from '@/types'
|
|
70
|
+
|
|
71
|
+
// 4. Estilos (si aplica)
|
|
72
|
+
import './styles.css'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Reglas
|
|
76
|
+
|
|
77
|
+
- Imports agrupados con línea en blanco entre grupos
|
|
78
|
+
- Sin imports wildcard (`import *`) a menos que sea necesario
|
|
79
|
+
- Usar alias de path configurados (`@/`, `~`, etc.)
|
|
80
|
+
- Imports de tipos con `import type` cuando sea solo tipo
|
|
81
|
+
|
|
82
|
+
## Estructura de Código
|
|
83
|
+
|
|
84
|
+
### Componentes UI
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Orden dentro de un componente:
|
|
88
|
+
// 1. Types/Interfaces
|
|
89
|
+
// 2. Constantes
|
|
90
|
+
// 3. Componente principal
|
|
91
|
+
// 4. Subcomponentes (si son pequeños)
|
|
92
|
+
// 5. Export
|
|
93
|
+
|
|
94
|
+
interface ButtonProps {
|
|
95
|
+
variant?: 'primary' | 'secondary'
|
|
96
|
+
children: React.ReactNode
|
|
97
|
+
onClick?: () => void
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const VARIANT_STYLES = {
|
|
101
|
+
primary: 'bg-blue-600 text-white',
|
|
102
|
+
secondary: 'bg-gray-200 text-gray-800',
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function Button({ variant = 'primary', children, onClick }: ButtonProps) {
|
|
106
|
+
return (
|
|
107
|
+
<button className={VARIANT_STYLES[variant]} onClick={onClick}>
|
|
108
|
+
{children}
|
|
109
|
+
</button>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Funciones de API / Servicios
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Orden:
|
|
118
|
+
// 1. Validación de inputs
|
|
119
|
+
// 2. Lógica de negocio
|
|
120
|
+
// 3. Side effects (logs, métricas)
|
|
121
|
+
// 4. Return
|
|
122
|
+
|
|
123
|
+
export async function createUser(input: CreateUserInput): Promise<User> {
|
|
124
|
+
// Validación
|
|
125
|
+
validateCreateUserInput(input)
|
|
126
|
+
|
|
127
|
+
// Lógica
|
|
128
|
+
const hashedPassword = await hashPassword(input.password)
|
|
129
|
+
const user = await db.user.create({ ...input, password: hashedPassword })
|
|
130
|
+
|
|
131
|
+
// Side effects
|
|
132
|
+
logger.info('User created', { userId: user.id })
|
|
133
|
+
|
|
134
|
+
return user
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Comentarios
|
|
139
|
+
|
|
140
|
+
### Cuándo comentar
|
|
141
|
+
|
|
142
|
+
Comentar el **por qué**, no el **qué**:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// ❌ Mal: Restate lo que el código ya dice
|
|
146
|
+
counter += 1
|
|
147
|
+
|
|
148
|
+
// ✅ Bien: Explica por qué
|
|
149
|
+
if (now - windowStart > WINDOW_SIZE_MS) {
|
|
150
|
+
counter = 0
|
|
151
|
+
windowStart = now
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Cuándo NO comentar
|
|
156
|
+
|
|
157
|
+
- Código auto-explicativo
|
|
158
|
+
- TODOs que deberías hacer ahora
|
|
159
|
+
- Código comentado (elimínalo, git tiene historia)
|
|
160
|
+
- **No usar comentarios inline** para explicar decisiones — usar JSDoc/docstring
|
|
161
|
+
|
|
162
|
+
### JSDoc / Docstrings
|
|
163
|
+
|
|
164
|
+
**OBLIGATORIO** para funciones públicas del módulo y componentes complejos. Explicar el POR QUÉ, no el qué:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
/**
|
|
168
|
+
* Creates a new user with hashed password.
|
|
169
|
+
* Uses bcrypt with 12 rounds — chose this over argon2 because
|
|
170
|
+
* we don't need GPU-resistant hashing for internal users.
|
|
171
|
+
*
|
|
172
|
+
* @param input - User creation data
|
|
173
|
+
* @returns Created user without password
|
|
174
|
+
* @throws {ValidationError} If email is invalid or already exists
|
|
175
|
+
*/
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
/**
|
|
180
|
+
* Debounced search that cancels previous requests.
|
|
181
|
+
* Needed because the API has a rate limit of 10 req/min
|
|
182
|
+
* and users type fast in the search bar.
|
|
183
|
+
*/
|
|
184
|
+
export function useSearch(query: string, delay = 300) { ... }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Cuando escribir JSDoc**:
|
|
188
|
+
- Funciones exportadas / públicas del módulo
|
|
189
|
+
- Componentes UI complejos (props no obvias, comportamiento especial)
|
|
190
|
+
- Hooks custom con lógica no trivial
|
|
191
|
+
- Funciones que resuelven un problema específico (documentar el problema)
|
|
192
|
+
- Funciones donde se tomó una decisión de implementación no obvia
|
|
193
|
+
|
|
194
|
+
## Manejo de Errores
|
|
195
|
+
|
|
196
|
+
- Nunca usar `any` como tipo de error
|
|
197
|
+
- Siempre manejar errores en el nivel apropiado
|
|
198
|
+
- Logear errores con contexto suficiente
|
|
199
|
+
- No swallow errors silenciosamente
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// ❌ Mal
|
|
203
|
+
try {
|
|
204
|
+
await doSomething()
|
|
205
|
+
} catch (e) {}
|
|
206
|
+
|
|
207
|
+
// ✅ Bien
|
|
208
|
+
try {
|
|
209
|
+
await doSomething()
|
|
210
|
+
} catch (error) {
|
|
211
|
+
logger.error('Failed to do something', { error, context })
|
|
212
|
+
throw new AppError('Something went wrong', { cause: error })
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Testing
|
|
217
|
+
|
|
218
|
+
### Convenciones de Tests
|
|
219
|
+
|
|
220
|
+
- Archivos de test junto al archivo que testean o en carpeta `__tests__/`
|
|
221
|
+
- Nombre descriptivo: `should [expected behavior] when [condition]`
|
|
222
|
+
- Patrón AAA: Arrange → Act → Assert
|
|
223
|
+
- Un assertion conceptual por test
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
describe('createUser', () => {
|
|
227
|
+
it('should create user with hashed password when input is valid', async () => {
|
|
228
|
+
// Arrange
|
|
229
|
+
const input = { email: 'test@test.com', password: 'password123' }
|
|
230
|
+
|
|
231
|
+
// Act
|
|
232
|
+
const user = await createUser(input)
|
|
233
|
+
|
|
234
|
+
// Assert
|
|
235
|
+
expect(user.email).toBe(input.email)
|
|
236
|
+
expect(user.password).not.toBe(input.password)
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Git
|
|
242
|
+
|
|
243
|
+
### Mensajes de Commit
|
|
244
|
+
|
|
245
|
+
Seguir [Conventional Commits](https://www.conventionalcommits.org/):
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
tipo(alcance): descripción breve
|
|
249
|
+
|
|
250
|
+
tipo: feat | fix | docs | style | refactor | perf | test | chore
|
|
251
|
+
alcance: módulo o componente afectado (opcional)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Ejemplos:
|
|
255
|
+
```
|
|
256
|
+
feat(auth): add JWT refresh token rotation
|
|
257
|
+
fix(api): handle null user in response
|
|
258
|
+
docs(readme): update setup instructions
|
|
259
|
+
refactor(utils): extract date formatting to shared util
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Nombres de Branches
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
tipo/descripción-corta
|
|
266
|
+
|
|
267
|
+
tipos: feat | fix | refactor | docs | chore
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Ejemplos:
|
|
271
|
+
```
|
|
272
|
+
feat/user-profile
|
|
273
|
+
fix/login-redirect
|
|
274
|
+
refactor/api-error-handling
|
|
275
|
+
```
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
created: "2025-01-01"
|
|
3
|
+
status: active
|
|
4
|
+
type: reference
|
|
5
|
+
tags: [referencia, configuración, variables, entorno, env]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Referencia de Configuración
|
|
9
|
+
|
|
10
|
+
Listado completo de variables de entorno y opciones de configuración del proyecto.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Variables de entorno
|
|
15
|
+
|
|
16
|
+
### Aplicación
|
|
17
|
+
|
|
18
|
+
| Variable | Requerida | Default | Descripción | Ejemplo |
|
|
19
|
+
|----------|-----------|---------|-------------|---------|
|
|
20
|
+
| `APP_ENV` | Sí | `development` | Entorno de ejecución. Valores: `development`, `staging`, `production` | `production` |
|
|
21
|
+
| `APP_PORT` | No | `[3000]` | Puerto donde escucha el servidor | `8080` |
|
|
22
|
+
| `APP_URL` | Sí (prod) | `http://localhost:3000` | URL pública de la aplicación | `https://[dominio]` |
|
|
23
|
+
| `APP_NAME` | No | `{{PROJECT_NAME}}` | Nombre de la aplicación para logs y metadata | `Mi Proyecto` |
|
|
24
|
+
| `LOG_LEVEL` | No | `info` | Nivel de logging. Valores: `debug`, `info`, `warn`, `error` | `debug` |
|
|
25
|
+
|
|
26
|
+
### Base de datos
|
|
27
|
+
|
|
28
|
+
| Variable | Requerida | Default | Descripción | Ejemplo |
|
|
29
|
+
|----------|-----------|---------|-------------|---------|
|
|
30
|
+
| `DATABASE_URL` | Sí | — | Connection string completo de la base de datos | `postgresql://user:pass@host:5432/dbname?ssl=true` |
|
|
31
|
+
| `DATABASE_POOL_SIZE` | No | `10` | Tamaño del pool de conexiones | `20` |
|
|
32
|
+
| `DATABASE_SSL` | No | `false` | Habilitar SSL para la conexión | `true` |
|
|
33
|
+
|
|
34
|
+
### Autenticación
|
|
35
|
+
|
|
36
|
+
| Variable | Requerida | Default | Descripción | Ejemplo |
|
|
37
|
+
|----------|-----------|---------|-------------|---------|
|
|
38
|
+
| `JWT_SECRET` | Sí | — | Secret para firmar JWTs. **Debe ser único por entorno y nunca commiteado.** | `[string aleatorio de 32+ caracteres]` |
|
|
39
|
+
| `JWT_EXPIRES_IN` | No | `1h` | Tiempo de expiración del token de acceso | `30m` |
|
|
40
|
+
| `JWT_REFRESH_EXPIRES_IN` | No | `7d` | Tiempo de expiración del refresh token | `30d` |
|
|
41
|
+
|
|
42
|
+
### Servicios externos
|
|
43
|
+
|
|
44
|
+
| Variable | Requerida | Default | Descripción | Ejemplo |
|
|
45
|
+
|----------|-----------|---------|-------------|---------|
|
|
46
|
+
| `[SERVICIO]_API_KEY` | Sí (prod) | — | API key para [servicio externo] | `[key]` |
|
|
47
|
+
| `[SERVICIO]_API_URL` | No | `[URL default]` | URL base de la API del servicio | `https://api.servicio.com/v1` |
|
|
48
|
+
| `[SERVICIO]_TIMEOUT` | No | `5000` | Timeout en ms para requests al servicio | `10000` |
|
|
49
|
+
|
|
50
|
+
### Email *(si aplica)*
|
|
51
|
+
|
|
52
|
+
| Variable | Requerida | Default | Descripción | Ejemplo |
|
|
53
|
+
|----------|-----------|---------|-------------|---------|
|
|
54
|
+
| `SMTP_HOST` | No | — | Host del servidor SMTP | `smtp.gmail.com` |
|
|
55
|
+
| `SMTP_PORT` | No | `587` | Puerto SMTP | `465` |
|
|
56
|
+
| `SMTP_USER` | No | — | Usuario SMTP | `noreply@[dominio]` |
|
|
57
|
+
| `SMTP_PASSWORD` | No | — | Contraseña SMTP | `[password]` |
|
|
58
|
+
| `EMAIL_FROM` | No | `noreply@[dominio]` | Email remitente por defecto | `contacto@[dominio]` |
|
|
59
|
+
|
|
60
|
+
### Storage / CDN *(si aplica)*
|
|
61
|
+
|
|
62
|
+
| Variable | Requerida | Default | Descripción | Ejemplo |
|
|
63
|
+
|----------|-----------|---------|-------------|---------|
|
|
64
|
+
| `STORAGE_BUCKET` | No | — | Nombre del bucket de storage | `mi-proyecto-assets` |
|
|
65
|
+
| `STORAGE_REGION` | No | — | Región del bucket | `us-east-1` |
|
|
66
|
+
| `CDN_URL` | No | — | URL del CDN para assets | `https://cdn.[dominio]` |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Valores por entorno
|
|
71
|
+
|
|
72
|
+
| Variable | Development | Staging | Production |
|
|
73
|
+
|----------|-------------|---------|------------|
|
|
74
|
+
| `APP_ENV` | `development` | `staging` | `production` |
|
|
75
|
+
| `LOG_LEVEL` | `debug` | `info` | `warn` |
|
|
76
|
+
| `DATABASE_URL` | Local DB | Staging DB | Production DB |
|
|
77
|
+
| `JWT_SECRET` | Cualquier valor para dev | Secret de staging | Secret de producción (rotado regularmente) |
|
|
78
|
+
| `[API_KEY]` | Key de testing | Key de staging | Key de producción |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Archivos de configuración
|
|
83
|
+
|
|
84
|
+
### `.env.example`
|
|
85
|
+
|
|
86
|
+
El archivo `.env.example` en la raíz del proyecto contiene **todas las variables posibles** con valores de ejemplo o placeholders. Se commitea al repo y sirve como referencia.
|
|
87
|
+
|
|
88
|
+
**Regla**: Si se añade una variable nueva, actualizar `.env.example` primero.
|
|
89
|
+
|
|
90
|
+
### Archivos de config del framework
|
|
91
|
+
|
|
92
|
+
| Archivo | Propósito | Formato |
|
|
93
|
+
|---------|-----------|---------|
|
|
94
|
+
| `[tsconfig.json / pyproject.toml / etc.]` | Configuración del lenguaje/framework | [JSON / TOML / YAML] |
|
|
95
|
+
| `[tailwind.config.js / etc.]` | Configuración de estilos | [JS / CSS] |
|
|
96
|
+
| `[docker-compose.yml]` | Servicios de desarrollo local | YAML |
|
|
97
|
+
| `[Dockerfile]` | Imagen Docker para producción | Dockerfile |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Reglas de configuración
|
|
102
|
+
|
|
103
|
+
1. **Nunca commitear secrets**: Todo valor sensible (passwords, API keys, secrets) va en `.env` que está en `.gitignore`.
|
|
104
|
+
2. **Defaults seguros**: Las variables que tienen default deben funcionar "out of the box" para desarrollo local.
|
|
105
|
+
3. **Fail fast**: Si una variable requerida no está configurada, la aplicación debe fallar al arrancar con un mensaje claro que diga cuál falta.
|
|
106
|
+
4. **Validación al inicio**: Las variables se validan al arrancar la aplicación, no en cada request.
|
|
107
|
+
5. **Documentar cambios**: Si se añade una variable nueva, actualizar este archivo y `.env.example` en el mismo commit.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Cómo añadir una variable nueva
|
|
112
|
+
|
|
113
|
+
1. Añadir la variable a `.env.example` con un valor de ejemplo o placeholder.
|
|
114
|
+
2. Añadir la variable a este archivo (`configuration.md`) en la sección correspondiente.
|
|
115
|
+
3. Implementar la lectura de la variable en código (con valor default si aplica).
|
|
116
|
+
4. Configurar la variable en los entornos de staging y production (CI/CD secrets, dashboard del hosting, etc.).
|
|
117
|
+
5. Commit todo junto (código + docs + `.env.example`).
|