elsabro 2.1.0 → 2.3.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.
Files changed (64) hide show
  1. package/agents/elsabro-orchestrator.md +113 -0
  2. package/commands/elsabro/add-phase.md +17 -0
  3. package/commands/elsabro/add-todo.md +111 -53
  4. package/commands/elsabro/audit-milestone.md +19 -0
  5. package/commands/elsabro/check-todos.md +210 -31
  6. package/commands/elsabro/complete-milestone.md +20 -1
  7. package/commands/elsabro/debug.md +19 -0
  8. package/commands/elsabro/discuss-phase.md +18 -1
  9. package/commands/elsabro/execute.md +511 -58
  10. package/commands/elsabro/insert-phase.md +18 -1
  11. package/commands/elsabro/list-phase-assumptions.md +17 -0
  12. package/commands/elsabro/new-milestone.md +19 -0
  13. package/commands/elsabro/new.md +19 -0
  14. package/commands/elsabro/pause-work.md +19 -0
  15. package/commands/elsabro/plan-milestone-gaps.md +20 -1
  16. package/commands/elsabro/plan.md +264 -36
  17. package/commands/elsabro/progress.md +203 -79
  18. package/commands/elsabro/quick.md +19 -0
  19. package/commands/elsabro/remove-phase.md +17 -0
  20. package/commands/elsabro/research-phase.md +18 -1
  21. package/commands/elsabro/resume-work.md +19 -0
  22. package/commands/elsabro/start.md +399 -98
  23. package/commands/elsabro/verify-work.md +138 -5
  24. package/hooks/confirm-destructive.sh +145 -0
  25. package/hooks/hooks-config.json +81 -0
  26. package/hooks/lint-check.sh +238 -0
  27. package/hooks/post-edit-test.sh +189 -0
  28. package/package.json +3 -2
  29. package/references/SYSTEM_INDEX.md +241 -0
  30. package/references/command-flow.md +352 -0
  31. package/references/enforcement-rules.md +331 -0
  32. package/references/error-contracts-tests.md +1171 -0
  33. package/references/error-contracts.md +3102 -0
  34. package/references/error-handling-instructions.md +26 -12
  35. package/references/parallel-worktrees.md +293 -0
  36. package/references/state-sync.md +381 -0
  37. package/references/task-dispatcher.md +388 -0
  38. package/references/tasks-integration.md +380 -0
  39. package/scripts/setup-parallel-worktrees.sh +319 -0
  40. package/skills/api-microservice.md +765 -0
  41. package/skills/api-setup.md +76 -3
  42. package/skills/auth-setup.md +46 -6
  43. package/skills/chrome-extension.md +584 -0
  44. package/skills/cicd-setup.md +1206 -0
  45. package/skills/cli-tool.md +884 -0
  46. package/skills/database-setup.md +41 -5
  47. package/skills/desktop-app.md +1351 -0
  48. package/skills/expo-app.md +35 -2
  49. package/skills/full-stack-app.md +543 -0
  50. package/skills/memory-update.md +207 -0
  51. package/skills/mobile-app.md +813 -0
  52. package/skills/nextjs-app.md +33 -2
  53. package/skills/payments-setup.md +76 -1
  54. package/skills/review.md +331 -0
  55. package/skills/saas-starter.md +639 -0
  56. package/skills/sentry-setup.md +41 -7
  57. package/skills/techdebt.md +289 -0
  58. package/skills/testing-setup.md +1218 -0
  59. package/skills/tutor.md +219 -0
  60. package/templates/.planning/notes/.gitkeep +0 -0
  61. package/templates/CLAUDE.md.template +48 -0
  62. package/templates/error-handling-config.json +79 -2
  63. package/templates/mistakes.md.template +52 -0
  64. package/templates/patterns.md.template +114 -0
@@ -0,0 +1,765 @@
1
+ ---
2
+ name: api-microservice
3
+ description: Crear microservicio API con Node.js, Fastify, OpenAPI/Swagger, Docker, Prisma, rate limiting y health checks.
4
+ tags: [api, microservice, fastify, docker, openapi, swagger, nodejs, prisma]
5
+ difficulty: intermediate
6
+ estimated_time: 40min
7
+ ---
8
+
9
+ # Skill: API Microservice
10
+
11
+ <when_to_use>
12
+ Usar cuando el usuario menciona:
13
+ - "crear API"
14
+ - "microservicio"
15
+ - "backend API"
16
+ - "REST API"
17
+ - "API con documentacion"
18
+ </when_to_use>
19
+
20
+ <pre_requisites>
21
+ ## Pre-requisitos
22
+
23
+ - Node.js 20+
24
+ - Docker Desktop (opcional, para containerization)
25
+ - PostgreSQL (local o Neon/Supabase)
26
+ </pre_requisites>
27
+
28
+ <project_structure>
29
+ ## Estructura de Proyecto
30
+
31
+ ```
32
+ my-api/
33
+ ├── src/
34
+ │ ├── routes/
35
+ │ │ ├── health.ts # Health check endpoints
36
+ │ │ ├── users.ts # User CRUD
37
+ │ │ └── index.ts # Route registration
38
+ │ ├── schemas/
39
+ │ │ └── user.ts # Zod schemas
40
+ │ ├── services/
41
+ │ │ └── userService.ts # Business logic
42
+ │ ├── middleware/
43
+ │ │ ├── auth.ts # JWT auth
44
+ │ │ └── error-handler.ts # Global error handler
45
+ │ ├── plugins/
46
+ │ │ ├── prisma.ts # Prisma plugin
47
+ │ │ └── swagger.ts # Swagger plugin
48
+ │ ├── config/
49
+ │ │ └── env.ts # Environment validation
50
+ │ ├── app.ts # Fastify app builder
51
+ │ └── index.ts # Entry point
52
+ ├── prisma/
53
+ │ └── schema.prisma
54
+ ├── tests/
55
+ │ └── routes/
56
+ │ └── users.test.ts
57
+ ├── Dockerfile
58
+ ├── docker-compose.yml
59
+ ├── .env
60
+ ├── .env.example
61
+ ├── tsconfig.json
62
+ └── package.json
63
+ ```
64
+ </project_structure>
65
+
66
+ <setup_steps>
67
+ ## Pasos de Setup
68
+
69
+ ### Paso 1: Inicializar proyecto
70
+
71
+ ```bash
72
+ mkdir my-api && cd my-api
73
+ npm init -y
74
+ ```
75
+
76
+ ### Paso 2: Instalar dependencias
77
+
78
+ ```bash
79
+ npm install fastify @fastify/cors @fastify/helmet @fastify/rate-limit @fastify/swagger @fastify/swagger-ui @fastify/jwt
80
+ npm install prisma @prisma/client zod dotenv
81
+ npm install -D typescript tsx @types/node vitest
82
+ ```
83
+
84
+ ### Paso 3: Configurar TypeScript
85
+
86
+ Crear `tsconfig.json`:
87
+
88
+ ```json
89
+ {
90
+ "compilerOptions": {
91
+ "target": "ES2022",
92
+ "module": "NodeNext",
93
+ "moduleResolution": "NodeNext",
94
+ "outDir": "./dist",
95
+ "rootDir": "./src",
96
+ "strict": true,
97
+ "esModuleInterop": true,
98
+ "skipLibCheck": true,
99
+ "forceConsistentCasingInFileNames": true,
100
+ "resolveJsonModule": true,
101
+ "declaration": true
102
+ },
103
+ "include": ["src/**/*"],
104
+ "exclude": ["node_modules", "dist"]
105
+ }
106
+ ```
107
+
108
+ ### Paso 4: Configurar variables de entorno
109
+
110
+ Crear `src/config/env.ts`:
111
+
112
+ ```typescript
113
+ import { z } from "zod";
114
+ import "dotenv/config";
115
+
116
+ const envSchema = z.object({
117
+ NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
118
+ PORT: z.coerce.number().default(3000),
119
+ HOST: z.string().default("0.0.0.0"),
120
+ DATABASE_URL: z.string(),
121
+ JWT_SECRET: z.string().min(32),
122
+ RATE_LIMIT_MAX: z.coerce.number().default(100),
123
+ });
124
+
125
+ export const env = envSchema.parse(process.env);
126
+ ```
127
+
128
+ Crear `.env`:
129
+
130
+ ```env
131
+ NODE_ENV=development
132
+ PORT=3000
133
+ HOST=0.0.0.0
134
+ DATABASE_URL=postgresql://user:password@localhost:5432/myapi
135
+ JWT_SECRET=your-super-secret-key-at-least-32-characters
136
+ RATE_LIMIT_MAX=100
137
+ ```
138
+
139
+ ### Paso 5: Configurar Prisma
140
+
141
+ ```bash
142
+ npx prisma init
143
+ ```
144
+
145
+ Editar `prisma/schema.prisma`:
146
+
147
+ ```prisma
148
+ generator client {
149
+ provider = "prisma-client-js"
150
+ }
151
+
152
+ datasource db {
153
+ provider = "postgresql"
154
+ url = env("DATABASE_URL")
155
+ }
156
+
157
+ model User {
158
+ id String @id @default(cuid())
159
+ email String @unique
160
+ name String?
161
+ password String
162
+ role Role @default(USER)
163
+ createdAt DateTime @default(now())
164
+ updatedAt DateTime @updatedAt
165
+ }
166
+
167
+ enum Role {
168
+ USER
169
+ ADMIN
170
+ }
171
+ ```
172
+
173
+ ### Paso 6: Crear plugin de Prisma
174
+
175
+ Crear `src/plugins/prisma.ts`:
176
+
177
+ ```typescript
178
+ import { FastifyPluginAsync } from "fastify";
179
+ import fp from "fastify-plugin";
180
+ import { PrismaClient } from "@prisma/client";
181
+
182
+ declare module "fastify" {
183
+ interface FastifyInstance {
184
+ prisma: PrismaClient;
185
+ }
186
+ }
187
+
188
+ const prismaPlugin: FastifyPluginAsync = async (fastify) => {
189
+ const prisma = new PrismaClient({
190
+ log: fastify.log.level === "debug" ? ["query", "error", "warn"] : ["error"],
191
+ });
192
+
193
+ await prisma.$connect();
194
+
195
+ fastify.decorate("prisma", prisma);
196
+
197
+ fastify.addHook("onClose", async (server) => {
198
+ await server.prisma.$disconnect();
199
+ });
200
+ };
201
+
202
+ export default fp(prismaPlugin, { name: "prisma" });
203
+ ```
204
+
205
+ ### Paso 7: Crear plugin de Swagger
206
+
207
+ Crear `src/plugins/swagger.ts`:
208
+
209
+ ```typescript
210
+ import { FastifyPluginAsync } from "fastify";
211
+ import fp from "fastify-plugin";
212
+ import swagger from "@fastify/swagger";
213
+ import swaggerUi from "@fastify/swagger-ui";
214
+
215
+ const swaggerPlugin: FastifyPluginAsync = async (fastify) => {
216
+ await fastify.register(swagger, {
217
+ openapi: {
218
+ info: {
219
+ title: "My API",
220
+ description: "API documentation",
221
+ version: "1.0.0",
222
+ },
223
+ servers: [
224
+ {
225
+ url: "http://localhost:3000",
226
+ description: "Development server",
227
+ },
228
+ ],
229
+ components: {
230
+ securitySchemes: {
231
+ bearerAuth: {
232
+ type: "http",
233
+ scheme: "bearer",
234
+ bearerFormat: "JWT",
235
+ },
236
+ },
237
+ },
238
+ },
239
+ });
240
+
241
+ await fastify.register(swaggerUi, {
242
+ routePrefix: "/docs",
243
+ uiConfig: {
244
+ docExpansion: "list",
245
+ deepLinking: false,
246
+ },
247
+ });
248
+ };
249
+
250
+ export default fp(swaggerPlugin, { name: "swagger" });
251
+ ```
252
+
253
+ ### Paso 8: Crear schemas con Zod
254
+
255
+ Crear `src/schemas/user.ts`:
256
+
257
+ ```typescript
258
+ import { z } from "zod";
259
+
260
+ export const createUserSchema = z.object({
261
+ email: z.string().email(),
262
+ name: z.string().min(2).optional(),
263
+ password: z.string().min(8),
264
+ });
265
+
266
+ export const updateUserSchema = z.object({
267
+ name: z.string().min(2).optional(),
268
+ email: z.string().email().optional(),
269
+ });
270
+
271
+ export const userResponseSchema = z.object({
272
+ id: z.string(),
273
+ email: z.string(),
274
+ name: z.string().nullable(),
275
+ role: z.enum(["USER", "ADMIN"]),
276
+ createdAt: z.date(),
277
+ });
278
+
279
+ export type CreateUserInput = z.infer<typeof createUserSchema>;
280
+ export type UpdateUserInput = z.infer<typeof updateUserSchema>;
281
+ export type UserResponse = z.infer<typeof userResponseSchema>;
282
+ ```
283
+
284
+ ### Paso 9: Crear rutas de health
285
+
286
+ Crear `src/routes/health.ts`:
287
+
288
+ ```typescript
289
+ import { FastifyPluginAsync } from "fastify";
290
+
291
+ export const healthRoutes: FastifyPluginAsync = async (fastify) => {
292
+ fastify.get(
293
+ "/health",
294
+ {
295
+ schema: {
296
+ description: "Health check endpoint",
297
+ tags: ["Health"],
298
+ response: {
299
+ 200: {
300
+ type: "object",
301
+ properties: {
302
+ status: { type: "string" },
303
+ timestamp: { type: "string" },
304
+ uptime: { type: "number" },
305
+ },
306
+ },
307
+ },
308
+ },
309
+ },
310
+ async () => {
311
+ return {
312
+ status: "healthy",
313
+ timestamp: new Date().toISOString(),
314
+ uptime: process.uptime(),
315
+ };
316
+ }
317
+ );
318
+
319
+ fastify.get(
320
+ "/health/ready",
321
+ {
322
+ schema: {
323
+ description: "Readiness probe",
324
+ tags: ["Health"],
325
+ response: {
326
+ 200: {
327
+ type: "object",
328
+ properties: {
329
+ status: { type: "string" },
330
+ database: { type: "string" },
331
+ },
332
+ },
333
+ },
334
+ },
335
+ },
336
+ async () => {
337
+ try {
338
+ await fastify.prisma.$queryRaw`SELECT 1`;
339
+ return { status: "ready", database: "connected" };
340
+ } catch {
341
+ return { status: "not ready", database: "disconnected" };
342
+ }
343
+ }
344
+ );
345
+ };
346
+ ```
347
+
348
+ ### Paso 10: Crear rutas de usuarios
349
+
350
+ Crear `src/routes/users.ts`:
351
+
352
+ ```typescript
353
+ import { FastifyPluginAsync } from "fastify";
354
+ import { createUserSchema, updateUserSchema } from "../schemas/user";
355
+ import bcrypt from "bcryptjs";
356
+
357
+ export const userRoutes: FastifyPluginAsync = async (fastify) => {
358
+ // GET /users
359
+ fastify.get(
360
+ "/",
361
+ {
362
+ schema: {
363
+ description: "List all users",
364
+ tags: ["Users"],
365
+ response: {
366
+ 200: {
367
+ type: "array",
368
+ items: {
369
+ type: "object",
370
+ properties: {
371
+ id: { type: "string" },
372
+ email: { type: "string" },
373
+ name: { type: "string" },
374
+ role: { type: "string" },
375
+ },
376
+ },
377
+ },
378
+ },
379
+ },
380
+ },
381
+ async () => {
382
+ const users = await fastify.prisma.user.findMany({
383
+ select: { id: true, email: true, name: true, role: true },
384
+ });
385
+ return users;
386
+ }
387
+ );
388
+
389
+ // GET /users/:id
390
+ fastify.get<{ Params: { id: string } }>(
391
+ "/:id",
392
+ {
393
+ schema: {
394
+ description: "Get user by ID",
395
+ tags: ["Users"],
396
+ params: {
397
+ type: "object",
398
+ properties: {
399
+ id: { type: "string" },
400
+ },
401
+ required: ["id"],
402
+ },
403
+ response: {
404
+ 200: {
405
+ type: "object",
406
+ properties: {
407
+ id: { type: "string" },
408
+ email: { type: "string" },
409
+ name: { type: "string" },
410
+ role: { type: "string" },
411
+ },
412
+ },
413
+ 404: {
414
+ type: "object",
415
+ properties: {
416
+ error: { type: "string" },
417
+ },
418
+ },
419
+ },
420
+ },
421
+ },
422
+ async (request, reply) => {
423
+ const { id } = request.params;
424
+ const user = await fastify.prisma.user.findUnique({
425
+ where: { id },
426
+ select: { id: true, email: true, name: true, role: true },
427
+ });
428
+
429
+ if (!user) {
430
+ return reply.code(404).send({ error: "User not found" });
431
+ }
432
+
433
+ return user;
434
+ }
435
+ );
436
+
437
+ // POST /users
438
+ fastify.post<{ Body: { email: string; name?: string; password: string } }>(
439
+ "/",
440
+ {
441
+ schema: {
442
+ description: "Create a new user",
443
+ tags: ["Users"],
444
+ body: {
445
+ type: "object",
446
+ properties: {
447
+ email: { type: "string", format: "email" },
448
+ name: { type: "string" },
449
+ password: { type: "string", minLength: 8 },
450
+ },
451
+ required: ["email", "password"],
452
+ },
453
+ response: {
454
+ 201: {
455
+ type: "object",
456
+ properties: {
457
+ id: { type: "string" },
458
+ email: { type: "string" },
459
+ name: { type: "string" },
460
+ },
461
+ },
462
+ },
463
+ },
464
+ },
465
+ async (request, reply) => {
466
+ const input = createUserSchema.parse(request.body);
467
+ const hashedPassword = await bcrypt.hash(input.password, 10);
468
+
469
+ const user = await fastify.prisma.user.create({
470
+ data: {
471
+ ...input,
472
+ password: hashedPassword,
473
+ },
474
+ select: { id: true, email: true, name: true },
475
+ });
476
+
477
+ return reply.code(201).send(user);
478
+ }
479
+ );
480
+
481
+ // PATCH /users/:id
482
+ fastify.patch<{ Params: { id: string }; Body: { name?: string; email?: string } }>(
483
+ "/:id",
484
+ {
485
+ schema: {
486
+ description: "Update user",
487
+ tags: ["Users"],
488
+ params: {
489
+ type: "object",
490
+ properties: {
491
+ id: { type: "string" },
492
+ },
493
+ required: ["id"],
494
+ },
495
+ body: {
496
+ type: "object",
497
+ properties: {
498
+ name: { type: "string" },
499
+ email: { type: "string", format: "email" },
500
+ },
501
+ },
502
+ },
503
+ },
504
+ async (request, reply) => {
505
+ const { id } = request.params;
506
+ const input = updateUserSchema.parse(request.body);
507
+
508
+ const user = await fastify.prisma.user.update({
509
+ where: { id },
510
+ data: input,
511
+ select: { id: true, email: true, name: true },
512
+ });
513
+
514
+ return user;
515
+ }
516
+ );
517
+
518
+ // DELETE /users/:id
519
+ fastify.delete<{ Params: { id: string } }>(
520
+ "/:id",
521
+ {
522
+ schema: {
523
+ description: "Delete user",
524
+ tags: ["Users"],
525
+ params: {
526
+ type: "object",
527
+ properties: {
528
+ id: { type: "string" },
529
+ },
530
+ required: ["id"],
531
+ },
532
+ response: {
533
+ 204: { type: "null" },
534
+ },
535
+ },
536
+ },
537
+ async (request, reply) => {
538
+ const { id } = request.params;
539
+ await fastify.prisma.user.delete({ where: { id } });
540
+ return reply.code(204).send();
541
+ }
542
+ );
543
+ };
544
+ ```
545
+
546
+ ### Paso 11: Crear app builder
547
+
548
+ Crear `src/app.ts`:
549
+
550
+ ```typescript
551
+ import Fastify, { FastifyInstance } from "fastify";
552
+ import cors from "@fastify/cors";
553
+ import helmet from "@fastify/helmet";
554
+ import rateLimit from "@fastify/rate-limit";
555
+ import prismaPlugin from "./plugins/prisma";
556
+ import swaggerPlugin from "./plugins/swagger";
557
+ import { healthRoutes } from "./routes/health";
558
+ import { userRoutes } from "./routes/users";
559
+ import { env } from "./config/env";
560
+
561
+ export async function buildApp(): Promise<FastifyInstance> {
562
+ const app = Fastify({
563
+ logger: {
564
+ level: env.NODE_ENV === "production" ? "info" : "debug",
565
+ },
566
+ });
567
+
568
+ // Plugins de seguridad
569
+ await app.register(cors, {
570
+ origin: env.NODE_ENV === "production" ? "https://yourapp.com" : true,
571
+ });
572
+ await app.register(helmet);
573
+ await app.register(rateLimit, {
574
+ max: env.RATE_LIMIT_MAX,
575
+ timeWindow: "1 minute",
576
+ });
577
+
578
+ // Database
579
+ await app.register(prismaPlugin);
580
+
581
+ // Documentation
582
+ await app.register(swaggerPlugin);
583
+
584
+ // Routes
585
+ await app.register(healthRoutes);
586
+ await app.register(userRoutes, { prefix: "/users" });
587
+
588
+ return app;
589
+ }
590
+ ```
591
+
592
+ ### Paso 12: Crear entry point
593
+
594
+ Crear `src/index.ts`:
595
+
596
+ ```typescript
597
+ import { buildApp } from "./app";
598
+ import { env } from "./config/env";
599
+
600
+ async function main() {
601
+ const app = await buildApp();
602
+
603
+ try {
604
+ await app.listen({ port: env.PORT, host: env.HOST });
605
+ console.log(`Server running at http://${env.HOST}:${env.PORT}`);
606
+ console.log(`Docs at http://${env.HOST}:${env.PORT}/docs`);
607
+ } catch (err) {
608
+ app.log.error(err);
609
+ process.exit(1);
610
+ }
611
+ }
612
+
613
+ main();
614
+ ```
615
+
616
+ ### Paso 13: Configurar Docker
617
+
618
+ Crear `Dockerfile`:
619
+
620
+ ```dockerfile
621
+ FROM node:20-alpine AS base
622
+ WORKDIR /app
623
+
624
+ # Dependencies
625
+ FROM base AS deps
626
+ COPY package*.json ./
627
+ RUN npm ci --only=production
628
+
629
+ # Build
630
+ FROM base AS build
631
+ COPY package*.json ./
632
+ RUN npm ci
633
+ COPY . .
634
+ RUN npx prisma generate
635
+ RUN npm run build
636
+
637
+ # Production
638
+ FROM base AS production
639
+ ENV NODE_ENV=production
640
+
641
+ COPY --from=deps /app/node_modules ./node_modules
642
+ COPY --from=build /app/dist ./dist
643
+ COPY --from=build /app/node_modules/.prisma ./node_modules/.prisma
644
+ COPY prisma ./prisma
645
+
646
+ EXPOSE 3000
647
+
648
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
649
+ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
650
+
651
+ CMD ["node", "dist/index.js"]
652
+ ```
653
+
654
+ Crear `docker-compose.yml`:
655
+
656
+ ```yaml
657
+ version: "3.8"
658
+
659
+ services:
660
+ api:
661
+ build: .
662
+ ports:
663
+ - "3000:3000"
664
+ environment:
665
+ - NODE_ENV=production
666
+ - DATABASE_URL=postgresql://postgres:password@db:5432/myapi
667
+ - JWT_SECRET=your-secret-key-at-least-32-characters
668
+ depends_on:
669
+ db:
670
+ condition: service_healthy
671
+
672
+ db:
673
+ image: postgres:16-alpine
674
+ environment:
675
+ - POSTGRES_USER=postgres
676
+ - POSTGRES_PASSWORD=password
677
+ - POSTGRES_DB=myapi
678
+ volumes:
679
+ - postgres_data:/var/lib/postgresql/data
680
+ healthcheck:
681
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
682
+ interval: 5s
683
+ timeout: 5s
684
+ retries: 5
685
+
686
+ volumes:
687
+ postgres_data:
688
+ ```
689
+
690
+ ### Paso 14: Scripts de package.json
691
+
692
+ ```json
693
+ {
694
+ "scripts": {
695
+ "dev": "tsx watch src/index.ts",
696
+ "build": "tsc",
697
+ "start": "node dist/index.js",
698
+ "lint": "eslint src --ext .ts",
699
+ "test": "vitest",
700
+ "db:migrate": "prisma migrate dev",
701
+ "db:push": "prisma db push",
702
+ "db:studio": "prisma studio",
703
+ "docker:build": "docker build -t my-api .",
704
+ "docker:run": "docker-compose up -d"
705
+ }
706
+ }
707
+ ```
708
+ </setup_steps>
709
+
710
+ <verification>
711
+ ## Verificacion
712
+
713
+ ### 1. Ejecutar migraciones
714
+ ```bash
715
+ npx prisma migrate dev --name init
716
+ ```
717
+
718
+ ### 2. Iniciar servidor
719
+ ```bash
720
+ npm run dev
721
+ ```
722
+
723
+ ### 3. Verificar health check
724
+ ```bash
725
+ curl http://localhost:3000/health
726
+ ```
727
+
728
+ ### 4. Ver documentacion
729
+ Abrir http://localhost:3000/docs
730
+
731
+ ### 5. Probar CRUD
732
+ ```bash
733
+ # Crear usuario
734
+ curl -X POST http://localhost:3000/users \
735
+ -H "Content-Type: application/json" \
736
+ -d '{"email":"test@example.com","password":"password123"}'
737
+
738
+ # Listar usuarios
739
+ curl http://localhost:3000/users
740
+
741
+ # Obtener usuario
742
+ curl http://localhost:3000/users/{id}
743
+ ```
744
+
745
+ ### 6. Probar Docker
746
+ ```bash
747
+ docker-compose up -d
748
+ curl http://localhost:3000/health
749
+ ```
750
+ </verification>
751
+
752
+ <common_issues>
753
+ ## Problemas Comunes
754
+
755
+ ### "Cannot find module"
756
+ - Verificar tsconfig paths
757
+ - Ejecutar `npx prisma generate`
758
+
759
+ ### "Database connection failed"
760
+ - Verificar DATABASE_URL
761
+ - Verificar que PostgreSQL esta corriendo
762
+
763
+ ### "Rate limit exceeded"
764
+ - Ajustar RATE_LIMIT_MAX en .env
765
+ </common_issues>