project-mcp-server 2.0.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/LICENSE +21 -0
- package/README.md +335 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/actions.d.ts +9 -0
- package/dist/scanner/actions.js +77 -0
- package/dist/scanner/actions.js.map +1 -0
- package/dist/scanner/cache.d.ts +4 -0
- package/dist/scanner/cache.js +34 -0
- package/dist/scanner/cache.js.map +1 -0
- package/dist/scanner/components.d.ts +17 -0
- package/dist/scanner/components.js +74 -0
- package/dist/scanner/components.js.map +1 -0
- package/dist/scanner/prisma.d.ts +17 -0
- package/dist/scanner/prisma.js +75 -0
- package/dist/scanner/prisma.js.map +1 -0
- package/dist/scanner/routes.d.ts +11 -0
- package/dist/scanner/routes.js +98 -0
- package/dist/scanner/routes.js.map +1 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +289 -0
- package/dist/setup.js.map +1 -0
- package/dist/tools/env/index.d.ts +2 -0
- package/dist/tools/env/index.js +152 -0
- package/dist/tools/env/index.js.map +1 -0
- package/dist/tools/generate/index.d.ts +2 -0
- package/dist/tools/generate/index.js +320 -0
- package/dist/tools/generate/index.js.map +1 -0
- package/dist/tools/project/index.d.ts +2 -0
- package/dist/tools/project/index.js +193 -0
- package/dist/tools/project/index.js.map +1 -0
- package/package.json +35 -0
- package/skills/commit.md +109 -0
- package/skills/infra.md +218 -0
- package/skills/nextauth.md +256 -0
- package/skills/nextjs.md +262 -0
- package/skills/prisma.md +281 -0
- package/skills/project-intelligence.SKILL.md +141 -0
- package/skills/security.md +353 -0
- package/skills/shadcn.md +299 -0
- package/skills/testing.md +188 -0
- package/skills/zod.md +253 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { scanRoutes } from "../../scanner/routes.js";
|
|
3
|
+
import { scanActions } from "../../scanner/actions.js";
|
|
4
|
+
import { scanPrismaSchemas } from "../../scanner/prisma.js";
|
|
5
|
+
import { scanComponents } from "../../scanner/components.js";
|
|
6
|
+
import { invalidate } from "../../scanner/cache.js";
|
|
7
|
+
import { config } from "../../config.js";
|
|
8
|
+
export function registerProjectTools(server) {
|
|
9
|
+
// ─── project_scan ──────────────────────────────────────────────────────────
|
|
10
|
+
server.registerTool("project_scan", {
|
|
11
|
+
title: "Escanear proyecto completo",
|
|
12
|
+
description: `Escanea el proyecto y devuelve un resumen de rutas, Server Actions,
|
|
13
|
+
schemas de Prisma y componentes instalados. Útil al inicio de una sesión
|
|
14
|
+
para tener el mapa completo del proyecto.
|
|
15
|
+
|
|
16
|
+
Returns: resumen con conteos y listado de entidades por categoría.`,
|
|
17
|
+
inputSchema: z.object({
|
|
18
|
+
force_refresh: z.boolean().default(false)
|
|
19
|
+
.describe("Forzar re-escaneo ignorando el cache")
|
|
20
|
+
}).strict(),
|
|
21
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false }
|
|
22
|
+
}, async ({ force_refresh }) => {
|
|
23
|
+
if (force_refresh)
|
|
24
|
+
invalidate();
|
|
25
|
+
const [routes, actions, models, components] = await Promise.all([
|
|
26
|
+
scanRoutes(),
|
|
27
|
+
scanActions(),
|
|
28
|
+
scanPrismaSchemas(),
|
|
29
|
+
scanComponents()
|
|
30
|
+
]);
|
|
31
|
+
const summary = {
|
|
32
|
+
projectRoot: config.projectRoot,
|
|
33
|
+
routes: {
|
|
34
|
+
total: routes.length,
|
|
35
|
+
pages: routes.filter(r => r.type === "page").length,
|
|
36
|
+
apiHandlers: routes.filter(r => r.type === "route-handler").length,
|
|
37
|
+
dynamic: routes.filter(r => r.dynamicParams.length > 0).length,
|
|
38
|
+
clientComponents: routes.filter(r => r.rendering === "client").length
|
|
39
|
+
},
|
|
40
|
+
actions: {
|
|
41
|
+
total: actions.length,
|
|
42
|
+
withAuth: actions.filter(a => a.hasAuth).length,
|
|
43
|
+
withZod: actions.filter(a => a.zodSchema).length
|
|
44
|
+
},
|
|
45
|
+
prisma: {
|
|
46
|
+
totalModels: models.length,
|
|
47
|
+
bySchema: Object.fromEntries([...new Set(models.map(m => m.schema))].map(s => [
|
|
48
|
+
s, models.filter(m => m.schema === s).length
|
|
49
|
+
]))
|
|
50
|
+
},
|
|
51
|
+
components: {
|
|
52
|
+
shadcnInstalled: components.ui.length,
|
|
53
|
+
custom: components.custom.length,
|
|
54
|
+
byFeature: Object.fromEntries([...new Set(components.custom.map(c => c.feature))].map(f => [
|
|
55
|
+
f, components.custom.filter(c => c.feature === f).length
|
|
56
|
+
]))
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const text = [
|
|
60
|
+
`## Proyecto: ${config.projectRoot.split("/").pop()}`,
|
|
61
|
+
``,
|
|
62
|
+
`### Rutas (${summary.routes.total})`,
|
|
63
|
+
`- Páginas: ${summary.routes.pages} · API handlers: ${summary.routes.apiHandlers}`,
|
|
64
|
+
`- Rutas dinámicas: ${summary.routes.dynamic} · Client components: ${summary.routes.clientComponents}`,
|
|
65
|
+
``,
|
|
66
|
+
`### Server Actions (${summary.actions.total})`,
|
|
67
|
+
`- Con autenticación: ${summary.actions.withAuth} · Con validación Zod: ${summary.actions.withZod}`,
|
|
68
|
+
``,
|
|
69
|
+
`### Prisma (${summary.prisma.totalModels} modelos)`,
|
|
70
|
+
...Object.entries(summary.prisma.bySchema).map(([s, n]) => `- Schema ${s}: ${n} modelos`),
|
|
71
|
+
``,
|
|
72
|
+
`### Componentes`,
|
|
73
|
+
`- shadcn/ui instalados: ${summary.components.shadcnInstalled}`,
|
|
74
|
+
`- Componentes propios: ${summary.components.custom}`,
|
|
75
|
+
].join("\n");
|
|
76
|
+
return { content: [{ type: "text", text }], structuredContent: summary };
|
|
77
|
+
});
|
|
78
|
+
// ─── project_routes ────────────────────────────────────────────────────────
|
|
79
|
+
server.registerTool("project_routes", {
|
|
80
|
+
title: "Listar rutas del proyecto",
|
|
81
|
+
description: `Lista todas las rutas del App Router con sus propiedades.
|
|
82
|
+
Útil para entender la estructura de navegación antes de crear una página nueva
|
|
83
|
+
o agregar un route handler.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
- filter: filtrar por "pages", "api", o "all" (default)
|
|
87
|
+
- dynamic_only: mostrar solo rutas con parámetros dinámicos
|
|
88
|
+
|
|
89
|
+
Returns: array de rutas con path, tipo, rendering, params dinámicos.`,
|
|
90
|
+
inputSchema: z.object({
|
|
91
|
+
filter: z.enum(["all", "pages", "api"]).default("all"),
|
|
92
|
+
dynamic_only: z.boolean().default(false)
|
|
93
|
+
}).strict(),
|
|
94
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false }
|
|
95
|
+
}, async ({ filter, dynamic_only }) => {
|
|
96
|
+
let routes = await scanRoutes();
|
|
97
|
+
if (filter === "pages")
|
|
98
|
+
routes = routes.filter(r => r.type === "page");
|
|
99
|
+
if (filter === "api")
|
|
100
|
+
routes = routes.filter(r => r.type === "route-handler");
|
|
101
|
+
if (dynamic_only)
|
|
102
|
+
routes = routes.filter(r => r.dynamicParams.length > 0);
|
|
103
|
+
const text = routes.map(r => {
|
|
104
|
+
const flags = [
|
|
105
|
+
r.rendering === "client" ? "client" : "rsc",
|
|
106
|
+
r.dynamicParams.length > 0 ? `[${r.dynamicParams.join(", ")}]` : null,
|
|
107
|
+
r.methods ? r.methods.join("|") : null,
|
|
108
|
+
r.hasLoading ? "loading" : null,
|
|
109
|
+
r.hasError ? "error" : null,
|
|
110
|
+
].filter(Boolean).join(" · ");
|
|
111
|
+
return `${r.path} ${flags}`;
|
|
112
|
+
}).join("\n");
|
|
113
|
+
return {
|
|
114
|
+
content: [{ type: "text", text: routes.length > 0 ? text : "No se encontraron rutas." }],
|
|
115
|
+
structuredContent: { routes, total: routes.length }
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
// ─── project_actions ───────────────────────────────────────────────────────
|
|
119
|
+
server.registerTool("project_actions", {
|
|
120
|
+
title: "Listar Server Actions",
|
|
121
|
+
description: `Lista todas las Server Actions del proyecto con sus schemas de validación.
|
|
122
|
+
Útil antes de crear una nueva action para ver los patrones existentes
|
|
123
|
+
y evitar duplicaciones.
|
|
124
|
+
|
|
125
|
+
Returns: array de actions con nombre, archivo, schema Zod, parámetros y flags.`,
|
|
126
|
+
inputSchema: z.object({
|
|
127
|
+
feature: z.string().optional()
|
|
128
|
+
.describe("Filtrar por feature (ej: 'users', 'posts')")
|
|
129
|
+
}).strict(),
|
|
130
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false }
|
|
131
|
+
}, async ({ feature }) => {
|
|
132
|
+
let actions = await scanActions();
|
|
133
|
+
if (feature) {
|
|
134
|
+
actions = actions.filter(a => a.file.toLowerCase().includes(feature.toLowerCase()));
|
|
135
|
+
}
|
|
136
|
+
const text = actions.map(a => {
|
|
137
|
+
const flags = [
|
|
138
|
+
a.hasAuth ? "auth" : "no-auth",
|
|
139
|
+
a.zodSchema ? `zod:${a.zodSchema}` : "no-zod",
|
|
140
|
+
a.hasRevalidate ? "revalidates" : null
|
|
141
|
+
].filter(Boolean).join(" · ");
|
|
142
|
+
return `${a.name} (${a.file}) ${flags}`;
|
|
143
|
+
}).join("\n");
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text: actions.length > 0 ? text : "No se encontraron Server Actions." }],
|
|
146
|
+
structuredContent: { actions, total: actions.length }
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
// ─── project_models ────────────────────────────────────────────────────────
|
|
150
|
+
server.registerTool("project_models", {
|
|
151
|
+
title: "Listar modelos de Prisma",
|
|
152
|
+
description: `Lista todos los modelos de Prisma con sus campos y schema.
|
|
153
|
+
Útil antes de crear una relación, migration, o Server Action
|
|
154
|
+
para conocer la estructura exacta de los datos.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
- schema: filtrar por schema (auth | rbac | audit | base)
|
|
158
|
+
- model_name: buscar un modelo específico por nombre
|
|
159
|
+
|
|
160
|
+
Returns: modelos con campos, tipos, relaciones y atributos.`,
|
|
161
|
+
inputSchema: z.object({
|
|
162
|
+
schema: z.enum(["auth", "rbac", "audit", "base"]).optional(),
|
|
163
|
+
model_name: z.string().optional()
|
|
164
|
+
}).strict(),
|
|
165
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
166
|
+
}, async ({ schema, model_name }) => {
|
|
167
|
+
let models = await scanPrismaSchemas();
|
|
168
|
+
if (schema)
|
|
169
|
+
models = models.filter(m => m.schema === schema);
|
|
170
|
+
if (model_name)
|
|
171
|
+
models = models.filter(m => m.name.toLowerCase().includes(model_name.toLowerCase()));
|
|
172
|
+
const text = models.map(m => {
|
|
173
|
+
const fields = m.fields
|
|
174
|
+
.filter(f => !f.isRelation)
|
|
175
|
+
.map(f => ` ${f.name}: ${f.type}${f.isOptional ? "?" : ""}${f.isArray ? "[]" : ""}`)
|
|
176
|
+
.join("\n");
|
|
177
|
+
const relations = m.fields
|
|
178
|
+
.filter(f => f.isRelation)
|
|
179
|
+
.map(f => ` ${f.name} → ${f.type}`)
|
|
180
|
+
.join("\n");
|
|
181
|
+
return [
|
|
182
|
+
`### ${m.name} (@schema: ${m.schema})`,
|
|
183
|
+
fields,
|
|
184
|
+
relations ? ` --- relaciones ---\n${relations}` : ""
|
|
185
|
+
].filter(Boolean).join("\n");
|
|
186
|
+
}).join("\n\n");
|
|
187
|
+
return {
|
|
188
|
+
content: [{ type: "text", text: models.length > 0 ? text : "No se encontraron modelos." }],
|
|
189
|
+
structuredContent: { models, total: models.length }
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/project/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "project-mcp-server",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "MCP server con inteligencia de proyecto, control de entorno y generación de código para Next.js + Prisma",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"project-mcp": "dist/index.js",
|
|
9
|
+
"project-mcp-setup": "dist/setup.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start": "node dist/index.js",
|
|
15
|
+
"setup": "node dist/setup.js",
|
|
16
|
+
"inspect": "npx @modelcontextprotocol/inspector node dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/fernandosecchi/project-mcp-server.git"
|
|
21
|
+
},
|
|
22
|
+
"keywords": ["mcp", "claude-code", "nextjs", "prisma", "ai-tools"],
|
|
23
|
+
"author": "Fernando Secchi",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"files": ["dist", "skills", "README.md", "LICENSE"],
|
|
26
|
+
"engines": { "node": ">=20" },
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
29
|
+
"zod": "^3.24.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
33
|
+
"typescript": "^5.9.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/skills/commit.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit
|
|
3
|
+
description: "Activar cuando se hace un commit, se abre un Pull Request o se prepara un release"
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill: Commits, PRs y releases
|
|
10
|
+
|
|
11
|
+
## Cuándo cargar esta skill
|
|
12
|
+
- Hacer un commit
|
|
13
|
+
- Abrir o cerrar un Pull Request
|
|
14
|
+
- Crear una release
|
|
15
|
+
- Revisar el estado del repo
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Conventional Commits
|
|
20
|
+
|
|
21
|
+
Formato: `tipo(scope): descripción en minúsculas`
|
|
22
|
+
|
|
23
|
+
| Tipo | Cuándo usarlo |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `feat` | Nueva feature visible para el usuario |
|
|
26
|
+
| `fix` | Bugfix |
|
|
27
|
+
| `refactor` | Cambio de código sin cambio de comportamiento |
|
|
28
|
+
| `chore` | Configuración, deps, tooling |
|
|
29
|
+
| `docs` | Solo documentación |
|
|
30
|
+
| `test` | Solo tests |
|
|
31
|
+
| `perf` | Mejora de performance |
|
|
32
|
+
| `ci` | Cambios en CI/CD |
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Ejemplos correctos
|
|
36
|
+
git commit -m "feat(auth): agregar login con credentials"
|
|
37
|
+
git commit -m "fix(prisma): corregir query de roles en schema rbac"
|
|
38
|
+
git commit -m "chore(deps): actualizar next a 16.1.0"
|
|
39
|
+
git commit -m "refactor(users): extraer helper de permisos a lib/auth"
|
|
40
|
+
|
|
41
|
+
# Breaking change
|
|
42
|
+
git commit -m "feat(api)!: cambiar estructura de respuesta de /api/users"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Flujo de trabajo con ramas
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Nueva feature
|
|
51
|
+
git checkout -b feat/nombre-descriptivo
|
|
52
|
+
|
|
53
|
+
# Bugfix
|
|
54
|
+
git checkout -b fix/descripcion-del-bug
|
|
55
|
+
|
|
56
|
+
# Chore / refactor
|
|
57
|
+
git checkout -b chore/descripcion
|
|
58
|
+
|
|
59
|
+
# Ver estado antes de commitear
|
|
60
|
+
git status
|
|
61
|
+
git diff
|
|
62
|
+
|
|
63
|
+
# Commitear
|
|
64
|
+
git add .
|
|
65
|
+
git commit -m "feat(scope): descripción"
|
|
66
|
+
|
|
67
|
+
# Push
|
|
68
|
+
git push origin feat/nombre-descriptivo
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Antes de cada commit — checklist
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 1. Tipos correctos
|
|
77
|
+
pnpm type-check
|
|
78
|
+
|
|
79
|
+
# 2. Linting
|
|
80
|
+
pnpm lint
|
|
81
|
+
|
|
82
|
+
# 3. Si hay tests
|
|
83
|
+
pnpm test
|
|
84
|
+
|
|
85
|
+
# 4. Build (en PRs importantes)
|
|
86
|
+
pnpm build
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## PR — descripción mínima esperada
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
## ¿Qué hace este PR?
|
|
95
|
+
Breve descripción del cambio.
|
|
96
|
+
|
|
97
|
+
## Tipo de cambio
|
|
98
|
+
- [ ] Nueva feature
|
|
99
|
+
- [ ] Bugfix
|
|
100
|
+
- [ ] Refactor
|
|
101
|
+
- [ ] Chore
|
|
102
|
+
|
|
103
|
+
## Checklist
|
|
104
|
+
- [ ] `pnpm type-check` pasa
|
|
105
|
+
- [ ] `pnpm lint` pasa
|
|
106
|
+
- [ ] Tests actualizados (si aplica)
|
|
107
|
+
- [ ] Migrations incluidas (si aplica)
|
|
108
|
+
- [ ] Variables de entorno documentadas en .env.example (si aplica)
|
|
109
|
+
```
|
package/skills/infra.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: infra
|
|
3
|
+
description: "Activar cuando se trabaja con Docker, variables de entorno, setup de base de datos o configuracion del entorno de desarrollo"
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill: Infra — Docker, variables de entorno, base de datos local
|
|
10
|
+
|
|
11
|
+
## Cuándo cargar esta skill
|
|
12
|
+
- Levantar o modificar servicios de Docker
|
|
13
|
+
- Trabajar con variables de entorno
|
|
14
|
+
- Setup inicial del proyecto
|
|
15
|
+
- Troubleshooting de conexiones a DB
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Docker Compose — servicios locales
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
# docker-compose.yml
|
|
23
|
+
services:
|
|
24
|
+
postgres:
|
|
25
|
+
image: postgres:16-alpine
|
|
26
|
+
container_name: app_postgres
|
|
27
|
+
environment:
|
|
28
|
+
POSTGRES_USER: ${POSTGRES_USER:-appuser}
|
|
29
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-apppassword}
|
|
30
|
+
POSTGRES_DB: ${POSTGRES_DB:-appdb}
|
|
31
|
+
ports:
|
|
32
|
+
- "5432:5432"
|
|
33
|
+
volumes:
|
|
34
|
+
- postgres_data:/var/lib/postgresql/data
|
|
35
|
+
healthcheck:
|
|
36
|
+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-appuser}"]
|
|
37
|
+
interval: 5s
|
|
38
|
+
timeout: 5s
|
|
39
|
+
retries: 5
|
|
40
|
+
|
|
41
|
+
mysql:
|
|
42
|
+
image: mysql:5.7
|
|
43
|
+
container_name: app_mysql
|
|
44
|
+
environment:
|
|
45
|
+
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword}
|
|
46
|
+
MYSQL_DATABASE: ${MYSQL_DB:-legacydb}
|
|
47
|
+
MYSQL_USER: ${MYSQL_USER:-appuser}
|
|
48
|
+
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-apppassword}
|
|
49
|
+
ports:
|
|
50
|
+
- "3306:3306"
|
|
51
|
+
volumes:
|
|
52
|
+
- mysql_data:/var/lib/mysql
|
|
53
|
+
healthcheck:
|
|
54
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
55
|
+
interval: 5s
|
|
56
|
+
timeout: 5s
|
|
57
|
+
retries: 10
|
|
58
|
+
|
|
59
|
+
volumes:
|
|
60
|
+
postgres_data:
|
|
61
|
+
mysql_data:
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Comandos Docker frecuentes
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Levantar todo en background
|
|
68
|
+
docker compose up -d
|
|
69
|
+
|
|
70
|
+
# Ver logs en vivo
|
|
71
|
+
docker compose logs -f postgres
|
|
72
|
+
docker compose logs -f mysql
|
|
73
|
+
|
|
74
|
+
# Reiniciar un servicio
|
|
75
|
+
docker compose restart postgres
|
|
76
|
+
|
|
77
|
+
# Bajar todo (conserva volúmenes)
|
|
78
|
+
docker compose down
|
|
79
|
+
|
|
80
|
+
# Bajar y eliminar volúmenes (reset total de datos)
|
|
81
|
+
docker compose down -v
|
|
82
|
+
|
|
83
|
+
# Ver estado de los servicios
|
|
84
|
+
docker compose ps
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Variables de entorno
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# .env.local (desarrollo local — no commitear)
|
|
93
|
+
# .env.example (template — sí commitear, sin valores reales)
|
|
94
|
+
|
|
95
|
+
# Base de datos PostgreSQL
|
|
96
|
+
DATABASE_URL="postgresql://appuser:apppassword@localhost:5432/appdb"
|
|
97
|
+
|
|
98
|
+
# Base de datos MySQL
|
|
99
|
+
MYSQL_DATABASE_URL="mysql://appuser:apppassword@localhost:3306/legacydb"
|
|
100
|
+
|
|
101
|
+
# NextAuth
|
|
102
|
+
NEXTAUTH_SECRET="genera-con: openssl rand -base64 32"
|
|
103
|
+
NEXTAUTH_URL="http://localhost:3000"
|
|
104
|
+
|
|
105
|
+
# App
|
|
106
|
+
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
|
107
|
+
NODE_ENV="development"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Generar NEXTAUTH_SECRET
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
openssl rand -base64 32
|
|
114
|
+
# Pegar el resultado en NEXTAUTH_SECRET
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Validar variables de entorno al iniciar
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// lib/env.ts — validación con Zod al startup
|
|
121
|
+
import { z } from "zod"
|
|
122
|
+
|
|
123
|
+
const EnvSchema = z.object({
|
|
124
|
+
DATABASE_URL: z.string().url(),
|
|
125
|
+
MYSQL_DATABASE_URL: z.string().url(),
|
|
126
|
+
NEXTAUTH_SECRET: z.string().min(32),
|
|
127
|
+
NEXTAUTH_URL: z.string().url(),
|
|
128
|
+
NODE_ENV: z.enum(["development", "test", "production"]).default("development")
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
export const env = EnvSchema.parse(process.env)
|
|
132
|
+
|
|
133
|
+
// Importar en lib/db/postgres.ts, lib/auth/config.ts, etc.
|
|
134
|
+
// Si falta una variable, el error explota al iniciar → fail fast
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Setup inicial completo
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 1. Instalar dependencias
|
|
143
|
+
pnpm install
|
|
144
|
+
|
|
145
|
+
# 2. Copiar variables de entorno
|
|
146
|
+
cp .env.example .env.local
|
|
147
|
+
# Editar .env.local con los valores correctos
|
|
148
|
+
|
|
149
|
+
# 3. Levantar bases de datos
|
|
150
|
+
docker compose up -d
|
|
151
|
+
|
|
152
|
+
# Esperar a que estén ready (healthcheck)
|
|
153
|
+
docker compose ps # status debe ser "healthy"
|
|
154
|
+
|
|
155
|
+
# 4. Correr migrations de Prisma
|
|
156
|
+
pnpm prisma migrate dev
|
|
157
|
+
|
|
158
|
+
# 5. Generar cliente Prisma
|
|
159
|
+
pnpm prisma generate
|
|
160
|
+
|
|
161
|
+
# 6. Correr seeds
|
|
162
|
+
pnpm tsx prisma/seeds/roles.ts
|
|
163
|
+
pnpm tsx prisma/seeds/admin-user.ts
|
|
164
|
+
|
|
165
|
+
# 7. Iniciar dev server
|
|
166
|
+
pnpm dev
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Troubleshooting de conexiones
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# PostgreSQL — verificar que acepta conexiones
|
|
175
|
+
docker compose exec postgres pg_isready -U appuser
|
|
176
|
+
|
|
177
|
+
# Conectarse con psql
|
|
178
|
+
docker compose exec postgres psql -U appuser -d appdb
|
|
179
|
+
|
|
180
|
+
# MySQL — verificar conexión
|
|
181
|
+
docker compose exec mysql mysqladmin ping -h localhost -u appuser -p
|
|
182
|
+
|
|
183
|
+
# Conectarse con mysql CLI
|
|
184
|
+
docker compose exec mysql mysql -u appuser -p legacydb
|
|
185
|
+
|
|
186
|
+
# Ver logs de error de conexión
|
|
187
|
+
docker compose logs postgres | grep -i error
|
|
188
|
+
docker compose logs mysql | grep -i error
|
|
189
|
+
|
|
190
|
+
# Si Prisma no conecta — verificar DATABASE_URL
|
|
191
|
+
pnpm prisma db pull # Si conecta, lista las tablas existentes
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Scripts útiles en package.json
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"scripts": {
|
|
201
|
+
"dev": "next dev --turbo",
|
|
202
|
+
"build": "next build",
|
|
203
|
+
"start": "next start",
|
|
204
|
+
"lint": "next lint",
|
|
205
|
+
"type-check": "tsc --noEmit",
|
|
206
|
+
"db:up": "docker compose up -d",
|
|
207
|
+
"db:down": "docker compose down",
|
|
208
|
+
"db:reset": "docker compose down -v && docker compose up -d",
|
|
209
|
+
"db:migrate": "prisma migrate dev",
|
|
210
|
+
"db:generate": "prisma generate",
|
|
211
|
+
"db:studio": "prisma studio",
|
|
212
|
+
"db:seed": "tsx prisma/seeds/index.ts",
|
|
213
|
+
"setup": "pnpm install && pnpm db:up && pnpm db:migrate && pnpm db:seed"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Con `pnpm setup` un desarrollador nuevo levanta todo el entorno en un comando.
|