@qubiit/lmagent 2.5.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 (155) hide show
  1. package/.editorconfig +18 -0
  2. package/AGENTS.md +169 -0
  3. package/CLAUDE.md +122 -0
  4. package/CONTRIBUTING.md +90 -0
  5. package/LICENSE +21 -0
  6. package/README.md +195 -0
  7. package/config/commands.yaml +194 -0
  8. package/config/levels.yaml +135 -0
  9. package/config/models.yaml +192 -0
  10. package/config/settings.yaml +405 -0
  11. package/config/tools-extended.yaml +534 -0
  12. package/config/tools.yaml +437 -0
  13. package/docs/assets/logo.png +0 -0
  14. package/docs/commands.md +132 -0
  15. package/docs/customization-guide.md +445 -0
  16. package/docs/getting-started.md +154 -0
  17. package/docs/how-to-start.md +242 -0
  18. package/docs/navigation-index.md +227 -0
  19. package/docs/usage-guide.md +113 -0
  20. package/install.js +1044 -0
  21. package/package.json +35 -0
  22. package/pyproject.toml +182 -0
  23. package/rules/_bootstrap.md +138 -0
  24. package/rules/agents-ia.md +607 -0
  25. package/rules/api-design.md +337 -0
  26. package/rules/automations-n8n.md +646 -0
  27. package/rules/code-style.md +570 -0
  28. package/rules/documentation.md +98 -0
  29. package/rules/security.md +316 -0
  30. package/rules/stack.md +395 -0
  31. package/rules/testing.md +326 -0
  32. package/rules/workflow.md +353 -0
  33. package/scripts/create_skill.js +300 -0
  34. package/scripts/validate_skills.js +283 -0
  35. package/skills/ai-agent-engineer/SKILL.md +394 -0
  36. package/skills/ai-agent-engineer/references/agent-patterns.md +149 -0
  37. package/skills/api-designer/SKILL.md +429 -0
  38. package/skills/api-designer/references/api-standards.md +13 -0
  39. package/skills/architect/SKILL.md +285 -0
  40. package/skills/architect/references/c4-model.md +133 -0
  41. package/skills/automation-engineer/SKILL.md +352 -0
  42. package/skills/automation-engineer/references/n8n-patterns.md +127 -0
  43. package/skills/backend-engineer/SKILL.md +261 -0
  44. package/skills/backend-engineer/assets/fastapi-project-structure.yaml +74 -0
  45. package/skills/backend-engineer/references/debugging-guide.md +174 -0
  46. package/skills/backend-engineer/references/design-patterns.md +208 -0
  47. package/skills/backend-engineer/scripts/scaffold_backend.py +313 -0
  48. package/skills/bmad-methodology/SKILL.md +202 -0
  49. package/skills/bmad-methodology/references/scale-adaptive-levels.md +141 -0
  50. package/skills/browser-agent/SKILL.md +502 -0
  51. package/skills/browser-agent/scripts/playwright_setup.ts +16 -0
  52. package/skills/code-reviewer/SKILL.md +306 -0
  53. package/skills/code-reviewer/references/code-review-checklist.md +16 -0
  54. package/skills/data-engineer/SKILL.md +474 -0
  55. package/skills/data-engineer/assets/pg-monitoring-queries.sql +154 -0
  56. package/skills/data-engineer/references/index-strategy.md +128 -0
  57. package/skills/data-engineer/scripts/backup_postgres.py +221 -0
  58. package/skills/devops-engineer/SKILL.md +547 -0
  59. package/skills/devops-engineer/references/ci-cd-patterns.md +265 -0
  60. package/skills/devops-engineer/scripts/docker_healthcheck.py +125 -0
  61. package/skills/document-generator/SKILL.md +746 -0
  62. package/skills/document-generator/references/pdf-generation.md +22 -0
  63. package/skills/frontend-engineer/SKILL.md +532 -0
  64. package/skills/frontend-engineer/references/accessibility-guide.md +146 -0
  65. package/skills/frontend-engineer/scripts/audit_bundle.py +144 -0
  66. package/skills/git-workflow/SKILL.md +374 -0
  67. package/skills/git-workflow/references/git-flow.md +25 -0
  68. package/skills/mcp-builder/SKILL.md +471 -0
  69. package/skills/mcp-builder/references/mcp-server-guide.md +23 -0
  70. package/skills/mobile-engineer/SKILL.md +502 -0
  71. package/skills/mobile-engineer/references/platform-guidelines.md +160 -0
  72. package/skills/orchestrator/SKILL.md +246 -0
  73. package/skills/orchestrator/references/methodology-routing.md +117 -0
  74. package/skills/orchestrator/references/persona-mapping.md +85 -0
  75. package/skills/orchestrator/references/routing-logic.md +110 -0
  76. package/skills/performance-engineer/SKILL.md +549 -0
  77. package/skills/performance-engineer/references/caching-patterns.md +181 -0
  78. package/skills/performance-engineer/scripts/profile_endpoint.py +170 -0
  79. package/skills/product-manager/SKILL.md +488 -0
  80. package/skills/product-manager/references/prioritization-frameworks.md +126 -0
  81. package/skills/prompt-engineer/SKILL.md +433 -0
  82. package/skills/prompt-engineer/references/prompt-patterns.md +158 -0
  83. package/skills/qa-engineer/SKILL.md +441 -0
  84. package/skills/qa-engineer/references/testing-strategy.md +166 -0
  85. package/skills/qa-engineer/scripts/run_coverage.py +147 -0
  86. package/skills/scrum-master/SKILL.md +225 -0
  87. package/skills/scrum-master/references/sprint-ceremonies.md +159 -0
  88. package/skills/security-analyst/SKILL.md +390 -0
  89. package/skills/security-analyst/references/owasp-top10.md +188 -0
  90. package/skills/security-analyst/scripts/audit_security.py +242 -0
  91. package/skills/seo-auditor/SKILL.md +523 -0
  92. package/skills/seo-auditor/references/seo-checklist.md +17 -0
  93. package/skills/spec-driven-dev/SKILL.md +342 -0
  94. package/skills/spec-driven-dev/references/phase-gates.md +107 -0
  95. package/skills/supabase-expert/SKILL.md +602 -0
  96. package/skills/supabase-expert/references/supabase-patterns.md +19 -0
  97. package/skills/swe-agent/SKILL.md +311 -0
  98. package/skills/swe-agent/references/trajectory-format.md +134 -0
  99. package/skills/systematic-debugger/SKILL.md +512 -0
  100. package/skills/systematic-debugger/references/debugging-guide.md +12 -0
  101. package/skills/tech-lead/SKILL.md +409 -0
  102. package/skills/tech-lead/references/code-review-checklist.md +111 -0
  103. package/skills/technical-writer/SKILL.md +631 -0
  104. package/skills/technical-writer/references/doc-templates.md +218 -0
  105. package/skills/testing-strategist/SKILL.md +476 -0
  106. package/skills/testing-strategist/references/testing-pyramid.md +16 -0
  107. package/skills/ux-ui-designer/SKILL.md +419 -0
  108. package/skills/ux-ui-designer/references/design-system-foundation.md +168 -0
  109. package/skills_overview.txt +94 -0
  110. package/templates/PROJECT_KICKOFF.md +284 -0
  111. package/templates/SKILL_TEMPLATE.md +131 -0
  112. package/templates/USAGE.md +95 -0
  113. package/templates/agent-python/README.md +71 -0
  114. package/templates/agent-python/agent.py +272 -0
  115. package/templates/agent-python/config.yaml +76 -0
  116. package/templates/agent-python/prompts/system.md +109 -0
  117. package/templates/agent-python/requirements.txt +7 -0
  118. package/templates/automation-n8n/README.md +14 -0
  119. package/templates/automation-n8n/webhook-handler.json +57 -0
  120. package/templates/backend-node/Dockerfile +12 -0
  121. package/templates/backend-node/README.md +15 -0
  122. package/templates/backend-node/package.json +30 -0
  123. package/templates/backend-node/src/index.ts +19 -0
  124. package/templates/backend-node/src/routes.ts +7 -0
  125. package/templates/backend-node/tsconfig.json +22 -0
  126. package/templates/backend-python/Dockerfile +11 -0
  127. package/templates/backend-python/README.md +78 -0
  128. package/templates/backend-python/app/core/config.py +12 -0
  129. package/templates/backend-python/app/core/database.py +12 -0
  130. package/templates/backend-python/app/main.py +17 -0
  131. package/templates/backend-python/app/routers/__init__.py +1 -0
  132. package/templates/backend-python/app/routers/health.py +7 -0
  133. package/templates/backend-python/requirements-dev.txt +6 -0
  134. package/templates/backend-python/requirements.txt +4 -0
  135. package/templates/backend-python/tests/test_health.py +9 -0
  136. package/templates/checkpoint.yaml +117 -0
  137. package/templates/database/README.md +474 -0
  138. package/templates/frontend-react/README.md +446 -0
  139. package/templates/plan.yaml +320 -0
  140. package/templates/session.yaml +125 -0
  141. package/templates/spec.yaml +229 -0
  142. package/templates/tasks.yaml +330 -0
  143. package/workflows/bugfix-backend.md +380 -0
  144. package/workflows/documentation.md +232 -0
  145. package/workflows/generate-prd.md +320 -0
  146. package/workflows/ideation.md +396 -0
  147. package/workflows/new-agent-ia.md +497 -0
  148. package/workflows/new-automation.md +374 -0
  149. package/workflows/new-feature.md +290 -0
  150. package/workflows/optimize-performance.md +373 -0
  151. package/workflows/resolve-github-issue.md +524 -0
  152. package/workflows/security-review.md +291 -0
  153. package/workflows/spec-driven.md +476 -0
  154. package/workflows/testing-strategy.md +296 -0
  155. package/workflows/third-party-integration.md +277 -0
@@ -0,0 +1,208 @@
1
+ # Design Patterns Reference — Backend Engineer
2
+
3
+ > Patrones de diseño más usados en desarrollo backend con FastAPI y NestJS.
4
+
5
+ ## Patrones Estructurales
6
+
7
+ ### Repository Pattern
8
+
9
+ Separa la lógica de acceso a datos de la lógica de negocio.
10
+
11
+ ```python
12
+ # app/repositories/base.py
13
+ from typing import TypeVar, Generic, Type, Optional
14
+ from sqlmodel import Session, SQLModel, select
15
+
16
+ T = TypeVar("T", bound=SQLModel)
17
+
18
+
19
+ class BaseRepository(Generic[T]):
20
+ """Repositorio genérico con operaciones CRUD."""
21
+
22
+ def __init__(self, model: Type[T], session: Session):
23
+ self.model = model
24
+ self.session = session
25
+
26
+ def get_by_id(self, id: str) -> Optional[T]:
27
+ return self.session.get(self.model, id)
28
+
29
+ def get_all(self, skip: int = 0, limit: int = 100) -> list[T]:
30
+ statement = select(self.model).offset(skip).limit(limit)
31
+ return self.session.exec(statement).all()
32
+
33
+ def create(self, obj: T) -> T:
34
+ self.session.add(obj)
35
+ self.session.commit()
36
+ self.session.refresh(obj)
37
+ return obj
38
+
39
+ def update(self, obj: T) -> T:
40
+ self.session.add(obj)
41
+ self.session.commit()
42
+ self.session.refresh(obj)
43
+ return obj
44
+
45
+ def delete(self, id: str) -> bool:
46
+ obj = self.get_by_id(id)
47
+ if obj:
48
+ self.session.delete(obj)
49
+ self.session.commit()
50
+ return True
51
+ return False
52
+ ```
53
+
54
+ ### Service Layer Pattern
55
+
56
+ Encapsula lógica de negocio entre controllers y repositories.
57
+
58
+ ```python
59
+ # app/services/user_service.py
60
+ from app.repositories.user_repository import UserRepository
61
+ from app.schemas.user import UserCreate, UserUpdate
62
+ from app.models.user import User
63
+
64
+
65
+ class UserService:
66
+ """Lógica de negocio para usuarios."""
67
+
68
+ def __init__(self, repo: UserRepository):
69
+ self.repo = repo
70
+
71
+ async def create_user(self, data: UserCreate) -> User:
72
+ # Validación de negocio
73
+ existing = self.repo.get_by_email(data.email)
74
+ if existing:
75
+ raise ValueError(f"Email {data.email} ya registrado")
76
+
77
+ user = User(**data.model_dump())
78
+ return self.repo.create(user)
79
+
80
+ async def get_user(self, user_id: str) -> User:
81
+ user = self.repo.get_by_id(user_id)
82
+ if not user:
83
+ raise ValueError(f"Usuario {user_id} no encontrado")
84
+ return user
85
+ ```
86
+
87
+ ### Dependency Injection (FastAPI)
88
+
89
+ ```python
90
+ # app/api/deps.py
91
+ from typing import Annotated
92
+ from fastapi import Depends
93
+ from sqlmodel import Session
94
+ from app.core.database import get_session
95
+ from app.repositories.user_repository import UserRepository
96
+ from app.services.user_service import UserService
97
+
98
+
99
+ def get_user_repository(
100
+ session: Annotated[Session, Depends(get_session)]
101
+ ) -> UserRepository:
102
+ return UserRepository(session)
103
+
104
+
105
+ def get_user_service(
106
+ repo: Annotated[UserRepository, Depends(get_user_repository)]
107
+ ) -> UserService:
108
+ return UserService(repo)
109
+ ```
110
+
111
+ ## Patrones de Resiliencia
112
+
113
+ ### Circuit Breaker
114
+
115
+ ```python
116
+ import time
117
+ from enum import Enum
118
+ from typing import Callable, Any
119
+
120
+
121
+ class CircuitState(Enum):
122
+ CLOSED = "closed" # Funcionando normal
123
+ OPEN = "open" # Cortado, rechaza requests
124
+ HALF_OPEN = "half_open" # Probando si se recuperó
125
+
126
+
127
+ class CircuitBreaker:
128
+ """Implementación simple de Circuit Breaker."""
129
+
130
+ def __init__(
131
+ self,
132
+ failure_threshold: int = 5,
133
+ recovery_timeout: int = 30,
134
+ ):
135
+ self.failure_threshold = failure_threshold
136
+ self.recovery_timeout = recovery_timeout
137
+ self.failure_count = 0
138
+ self.state = CircuitState.CLOSED
139
+ self.last_failure_time = 0
140
+
141
+ async def call(self, func: Callable, *args, **kwargs) -> Any:
142
+ if self.state == CircuitState.OPEN:
143
+ if time.time() - self.last_failure_time > self.recovery_timeout:
144
+ self.state = CircuitState.HALF_OPEN
145
+ else:
146
+ raise Exception("Circuit breaker is OPEN")
147
+
148
+ try:
149
+ result = await func(*args, **kwargs)
150
+ self._on_success()
151
+ return result
152
+ except Exception as e:
153
+ self._on_failure()
154
+ raise e
155
+
156
+ def _on_success(self):
157
+ self.failure_count = 0
158
+ self.state = CircuitState.CLOSED
159
+
160
+ def _on_failure(self):
161
+ self.failure_count += 1
162
+ self.last_failure_time = time.time()
163
+ if self.failure_count >= self.failure_threshold:
164
+ self.state = CircuitState.OPEN
165
+ ```
166
+
167
+ ### Retry with Backoff
168
+
169
+ ```python
170
+ import asyncio
171
+ import random
172
+ from functools import wraps
173
+
174
+
175
+ def retry_with_backoff(
176
+ max_retries: int = 3,
177
+ base_delay: float = 1.0,
178
+ max_delay: float = 60.0,
179
+ ):
180
+ """Decorator para retry con exponential backoff + jitter."""
181
+ def decorator(func):
182
+ @wraps(func)
183
+ async def wrapper(*args, **kwargs):
184
+ for attempt in range(max_retries + 1):
185
+ try:
186
+ return await func(*args, **kwargs)
187
+ except Exception as e:
188
+ if attempt == max_retries:
189
+ raise e
190
+ delay = min(base_delay * (2 ** attempt), max_delay)
191
+ jitter = random.uniform(0, delay * 0.1)
192
+ await asyncio.sleep(delay + jitter)
193
+ return wrapper
194
+ return decorator
195
+ ```
196
+
197
+ ## Anti-Patterns a Evitar
198
+
199
+ | ❌ Anti-Pattern | ✅ Alternativa |
200
+ |----------------|---------------|
201
+ | Fat Controller (lógica en endpoint) | Service Layer Pattern |
202
+ | God Object (clase que hace todo) | Single Responsibility |
203
+ | N+1 Queries | Eager loading / JOINs |
204
+ | Hardcoded configs | Environment variables |
205
+ | String SQL | ORM / Prepared statements |
206
+ | Catch-all exceptions | Specific exception handling |
207
+ | Synchronous blocking in async | `asyncio.to_thread()` |
208
+ | Mutable default arguments | `field(default_factory=list)` |
@@ -0,0 +1,313 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ LMAgent - Backend Project Scaffolding Script
4
+ Genera la estructura base de un proyecto backend con FastAPI o NestJS.
5
+
6
+ Uso:
7
+ python scaffold_backend.py --framework fastapi --name mi-proyecto
8
+ python scaffold_backend.py --framework nestjs --name mi-proyecto
9
+ """
10
+
11
+ import os
12
+ import sys
13
+ import argparse
14
+ from pathlib import Path
15
+
16
+
17
+ def create_fastapi_structure(project_name: str, base_path: Path):
18
+ """Crea estructura de proyecto FastAPI estandarizada."""
19
+ dirs = [
20
+ f"{project_name}/app",
21
+ f"{project_name}/app/api",
22
+ f"{project_name}/app/api/v1",
23
+ f"{project_name}/app/api/v1/endpoints",
24
+ f"{project_name}/app/core",
25
+ f"{project_name}/app/models",
26
+ f"{project_name}/app/schemas",
27
+ f"{project_name}/app/services",
28
+ f"{project_name}/app/repositories",
29
+ f"{project_name}/app/middleware",
30
+ f"{project_name}/app/utils",
31
+ f"{project_name}/tests",
32
+ f"{project_name}/tests/unit",
33
+ f"{project_name}/tests/integration",
34
+ f"{project_name}/migrations",
35
+ f"{project_name}/migrations/versions",
36
+ f"{project_name}/docs",
37
+ ]
38
+
39
+ files = {
40
+ f"{project_name}/app/__init__.py": "",
41
+ f"{project_name}/app/main.py": '''"""FastAPI Application Entry Point."""
42
+ from fastapi import FastAPI
43
+ from fastapi.middleware.cors import CORSMiddleware
44
+ from app.core.config import settings
45
+
46
+ app = FastAPI(
47
+ title=settings.PROJECT_NAME,
48
+ version=settings.VERSION,
49
+ docs_url="/docs",
50
+ redoc_url="/redoc",
51
+ )
52
+
53
+ app.add_middleware(
54
+ CORSMiddleware,
55
+ allow_origins=settings.ALLOWED_ORIGINS,
56
+ allow_credentials=True,
57
+ allow_methods=["*"],
58
+ allow_headers=["*"],
59
+ )
60
+
61
+
62
+ @app.get("/health")
63
+ async def health_check():
64
+ return {"status": "healthy", "version": settings.VERSION}
65
+ ''',
66
+ f"{project_name}/app/core/__init__.py": "",
67
+ f"{project_name}/app/core/config.py": '''"""Application Configuration."""
68
+ import os
69
+ from pydantic_settings import BaseSettings
70
+
71
+
72
+ class Settings(BaseSettings):
73
+ PROJECT_NAME: str = os.getenv("PROJECT_NAME", "LMAgent Backend")
74
+ VERSION: str = os.getenv("VERSION", "0.1.0")
75
+ DEBUG: bool = os.getenv("DEBUG", "false").lower() == "true"
76
+
77
+ # Database
78
+ DATABASE_URL: str = os.getenv("DATABASE_URL", "postgresql://user:pass@localhost:5432/db")
79
+
80
+ # Redis
81
+ REDIS_URL: str = os.getenv("REDIS_URL", "redis://localhost:6379/0")
82
+
83
+ # Security
84
+ SECRET_KEY: str = os.getenv("SECRET_KEY", "change-me-in-production")
85
+ ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "30"))
86
+
87
+ # CORS
88
+ ALLOWED_ORIGINS: list[str] = os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(",")
89
+
90
+ class Config:
91
+ env_file = ".env"
92
+
93
+
94
+ settings = Settings()
95
+ ''',
96
+ f"{project_name}/app/api/__init__.py": "",
97
+ f"{project_name}/app/api/v1/__init__.py": "",
98
+ f"{project_name}/app/api/v1/endpoints/__init__.py": "",
99
+ f"{project_name}/app/models/__init__.py": "",
100
+ f"{project_name}/app/schemas/__init__.py": "",
101
+ f"{project_name}/app/services/__init__.py": "",
102
+ f"{project_name}/app/repositories/__init__.py": "",
103
+ f"{project_name}/app/middleware/__init__.py": "",
104
+ f"{project_name}/app/utils/__init__.py": "",
105
+ f"{project_name}/tests/__init__.py": "",
106
+ f"{project_name}/tests/conftest.py": '''"""Test Configuration and Fixtures."""
107
+ import pytest
108
+ from httpx import AsyncClient, ASGITransport
109
+ from app.main import app
110
+
111
+
112
+ @pytest.fixture
113
+ async def client():
114
+ """Async test client fixture."""
115
+ async with AsyncClient(
116
+ transport=ASGITransport(app=app),
117
+ base_url="http://test"
118
+ ) as ac:
119
+ yield ac
120
+ ''',
121
+ f"{project_name}/requirements.txt": """fastapi>=0.115.0
122
+ uvicorn[standard]>=0.30.0
123
+ pydantic>=2.0.0
124
+ pydantic-settings>=2.0.0
125
+ sqlmodel>=0.0.22
126
+ alembic>=1.14.0
127
+ asyncpg>=0.30.0
128
+ httpx>=0.27.0
129
+ redis>=5.0.0
130
+ python-jose[cryptography]>=3.3.0
131
+ passlib[bcrypt]>=1.7.4
132
+ python-multipart>=0.0.9
133
+ """,
134
+ f"{project_name}/requirements-dev.txt": """pytest>=8.0.0
135
+ pytest-asyncio>=0.23.0
136
+ pytest-cov>=5.0.0
137
+ httpx>=0.27.0
138
+ ruff>=0.8.0
139
+ mypy>=1.13.0
140
+ faker>=30.0.0
141
+ """,
142
+ f"{project_name}/.env.example": """# Application
143
+ PROJECT_NAME=mi-proyecto
144
+ VERSION=0.1.0
145
+ DEBUG=true
146
+
147
+ # Database
148
+ DATABASE_URL=postgresql://user:password@localhost:5432/mydb
149
+
150
+ # Redis
151
+ REDIS_URL=redis://localhost:6379/0
152
+
153
+ # Security
154
+ SECRET_KEY=change-me-in-production
155
+ ACCESS_TOKEN_EXPIRE_MINUTES=30
156
+
157
+ # CORS
158
+ ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
159
+ """,
160
+ f"{project_name}/Dockerfile": """# Multi-stage build
161
+ FROM python:3.12-slim AS builder
162
+ WORKDIR /app
163
+ COPY requirements.txt .
164
+ RUN pip install --no-cache-dir --user -r requirements.txt
165
+
166
+ FROM python:3.12-slim
167
+ WORKDIR /app
168
+ COPY --from=builder /root/.local /root/.local
169
+ COPY . .
170
+ ENV PATH=/root/.local/bin:$PATH
171
+ EXPOSE 8000
172
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
173
+ """,
174
+ f"{project_name}/pyproject.toml": f"""[project]
175
+ name = "{project_name}"
176
+ version = "0.1.0"
177
+ requires-python = ">=3.12"
178
+
179
+ [tool.ruff]
180
+ target-version = "py312"
181
+ line-length = 100
182
+
183
+ [tool.ruff.lint]
184
+ select = ["E", "W", "F", "I", "N", "UP", "S", "B", "A", "C4"]
185
+
186
+ [tool.pytest.ini_options]
187
+ asyncio_mode = "auto"
188
+ testpaths = ["tests"]
189
+
190
+ [tool.mypy]
191
+ python_version = "3.12"
192
+ strict = true
193
+ """,
194
+ }
195
+
196
+ for d in dirs:
197
+ (base_path / d).mkdir(parents=True, exist_ok=True)
198
+
199
+ for filepath, content in files.items():
200
+ (base_path / filepath).write_text(content, encoding="utf-8")
201
+
202
+ print(f"✅ Proyecto FastAPI '{project_name}' creado exitosamente.")
203
+ print(f" 📁 Ubicación: {base_path / project_name}")
204
+ print(f"\n Siguientes pasos:")
205
+ print(f" 1. cd {project_name}")
206
+ print(f" 2. cp .env.example .env")
207
+ print(f" 3. pip install -r requirements.txt")
208
+ print(f" 4. uvicorn app.main:app --reload")
209
+
210
+
211
+ def create_nestjs_structure(project_name: str, base_path: Path):
212
+ """Crea estructura de proyecto NestJS estandarizada."""
213
+ dirs = [
214
+ f"{project_name}/src",
215
+ f"{project_name}/src/common",
216
+ f"{project_name}/src/common/decorators",
217
+ f"{project_name}/src/common/filters",
218
+ f"{project_name}/src/common/guards",
219
+ f"{project_name}/src/common/interceptors",
220
+ f"{project_name}/src/common/pipes",
221
+ f"{project_name}/src/config",
222
+ f"{project_name}/src/modules",
223
+ f"{project_name}/src/modules/auth",
224
+ f"{project_name}/src/modules/users",
225
+ f"{project_name}/test",
226
+ f"{project_name}/prisma",
227
+ ]
228
+
229
+ files = {
230
+ f"{project_name}/src/main.ts": '''import { NestFactory } from "@nestjs/core";
231
+ import { ValidationPipe } from "@nestjs/common";
232
+ import { AppModule } from "./app.module";
233
+
234
+ async function bootstrap() {
235
+ const app = await NestFactory.create(AppModule);
236
+
237
+ app.enableCors({
238
+ origin: process.env.ALLOWED_ORIGINS?.split(",") || ["http://localhost:3000"],
239
+ credentials: true,
240
+ });
241
+
242
+ app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
243
+ app.setGlobalPrefix("api/v1");
244
+
245
+ const port = process.env.PORT || 3001;
246
+ await app.listen(port);
247
+ console.log(`🚀 Server running on http://localhost:${port}`);
248
+ }
249
+ bootstrap();
250
+ ''',
251
+ f"{project_name}/.env.example": """# Application
252
+ PORT=3001
253
+ NODE_ENV=development
254
+
255
+ # Database
256
+ DATABASE_URL=postgresql://user:password@localhost:5432/mydb
257
+
258
+ # JWT
259
+ JWT_SECRET=change-me-in-production
260
+ JWT_EXPIRES_IN=30m
261
+
262
+ # CORS
263
+ ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
264
+ """,
265
+ }
266
+
267
+ for d in dirs:
268
+ (base_path / d).mkdir(parents=True, exist_ok=True)
269
+
270
+ for filepath, content in files.items():
271
+ (base_path / filepath).write_text(content, encoding="utf-8")
272
+
273
+ print(f"✅ Proyecto NestJS '{project_name}' creado exitosamente.")
274
+ print(f" 📁 Ubicación: {base_path / project_name}")
275
+ print(f"\n Siguientes pasos:")
276
+ print(f" 1. cd {project_name}")
277
+ print(f" 2. cp .env.example .env")
278
+ print(f" 3. npm install")
279
+ print(f" 4. npm run start:dev")
280
+
281
+
282
+ def main():
283
+ parser = argparse.ArgumentParser(
284
+ description="LMAgent Backend Scaffolding — Genera estructura de proyecto backend"
285
+ )
286
+ parser.add_argument(
287
+ "--framework", "-f",
288
+ choices=["fastapi", "nestjs"],
289
+ required=True,
290
+ help="Framework a usar (fastapi o nestjs)"
291
+ )
292
+ parser.add_argument(
293
+ "--name", "-n",
294
+ required=True,
295
+ help="Nombre del proyecto"
296
+ )
297
+ parser.add_argument(
298
+ "--path", "-p",
299
+ default=".",
300
+ help="Ruta base donde crear el proyecto (default: directorio actual)"
301
+ )
302
+
303
+ args = parser.parse_args()
304
+ base_path = Path(args.path).resolve()
305
+
306
+ if args.framework == "fastapi":
307
+ create_fastapi_structure(args.name, base_path)
308
+ elif args.framework == "nestjs":
309
+ create_nestjs_structure(args.name, base_path)
310
+
311
+
312
+ if __name__ == "__main__":
313
+ main()