Skip to main content

adela-integrate

Integrar módulos Adela en un proyecto Express o añadir nuevos tabs/frontend a un CRM Adela existente

설치로 이동

소스 정보

저장소
Ntizar/NtizarBrainMasterMind
최근 소스 활동
2026년 6월 26일 12:05
감지된 SKILL.md 언어
스페인어
스타
2
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
adela-integrate
description
Integrar módulos Adela en un proyecto Express o añadir nuevos tabs/frontend a un CRM Adela existente
## Adela Integrate Skill para integrar módulos Adela en un proyecto Express existente o nuevo, y para añadir nuevos tabs al frontend de un CRM Adela. ### Cuándo usarlo - El usuario dice "quiero una web con login y panel admin" - El usuario dice "añade Adela_auth a mi proyecto Express" - El usuario dice "crea un proyecto Express con Adela integrado" - El usuario dice "añade un nuevo tab/módulo al CRM" (ej: automatizaciones, contabilidad, etc.) ### Patrón de integración #### 1. Identificar qué módulos necesita Según la petición del usuario, seleccionar del registry.json: ```bash cat /root/workspace/AdelaMasterMind/registry.json ``` Módulos típicos y para qué sirven: - `Adela_auth` → Login con PIN + JWT + sesiones - `Adela_admin` → Panel admin + tracking de visitas - `Adela_health` → Endpoints /health y /ready - `Adela_i18n` → Internacionalización - `Adela_db` → Base de datos - `Adela_cache` → Caché - `Adela_http` → Cliente HTTP - `Adela_ai` → Proxy LLM #### 2. Instalar dependencias ```bash cd /ruta/del/proyecto npm install adela-db adela-auth adela-health adela-admin ``` Si los módulos no están publicados en npm, usar path local: ```bash npm install /root/workspace/Adela/Adela_db ``` #### 3. Configurar módulos Patrón típico de inicialización: ```typescript import { createDatabase } from 'adela-db' import { createAuth, authRouter } from 'adela-auth' import { createHealthRouter } from 'adela-health' import { createAdminPanel } from 'adela-admin' import { createI18n } from 'adela-i18n' import express from 'express' async function main() { const app = express() app.use(express.json()) // 1. Base de datos (primero — otros dependen de ella) const db = await createDatabase({ driver: 'sqlite', path: './datos.db' }) await db.connect() // 2. Internacionalización const i18n = await createI18n({ defaultLocale: 'es-ES' }) // 3. Autenticación const auth = createAuth({ db }) app.use('/auth', authRouter(auth)) // 4. Health checks app.use('/health', createHealthRouter({ version: '1.0.0' })) // 5. Admin panel const admin = createAdminPanel({ auth, db, prefix: '/admin' }) app.use('/admin', admin.getRouter()) // 6. Arrancar app.listen(3000, () => console.log('Servidor iniciado en :3000')) } main().catch(console.error) ``` #### 4. Rutas públicas vs protegidas ```typescript // Rutas públicas (no requieren auth) app.use('/health', healthRouter) app.use('/login', authRouter) app.get('/public/*', (req, res) => res.send('Público')) // Middleware de auth para rutas protegidas import { requireAuth } from 'adela-auth' // Rutas protegidas (requieren token JWT) app.use('/admin', requireAuth, adminRouter) app.use('/api', requireAuth, apiRouter) app.get('/perfil', requireAuth, (req, res) => { ... }) ``` #### 5. Verificar integración ```bash # Health check curl http://localhost:3000/health # Login curl -X POST http://localhost:3000/login -H 'Content-Type: application/json' \ -d '{"pin":"1234"}' # Admin (requiere token) curl http://localhost:3000/admin -H 'Authorization: Bearer <token>' ``` ### Proyecto completo de ejemplo Usar el template `adela-express-app`: ```bash cp -r /root/workspace/AdelaMasterMind/templates/adela-express-app/ /root/workspace/mi-proyecto/ cd /root/workspace/mi-proyecto/ npm install npm run dev ``` ### Dependencias entre módulos ``` Adela_admin → Adela_auth → Adela_db Adela_admin → Adela_i18n Adela_health → Adela_time Adela_auth → Adela_db ``` Siempre inicializar en orden: primero los que no dependen de nadie, luego los que dependen de ellos. ### Seguridad post-integración Después de integrar módulos, verificar que el proyecto cumple estas normas: 1. **PIN/contraseña hasheado con bcrypt** — nunca texto plano en BD 2. **JWT_SECRET compartido** — un solo `config.ts` exporta el secreto, todos importan de ahí 3. **API sin campos sensibles** — `pin_hash`, `password` nunca en respuestas. Usar `sanitizeUser()` 4. **Admin PIN desde env var** — `process.env.ADMIN_PIN`, nunca hardcodeado 5. **PIN no visible en HTML** — no mostrar credenciales en el frontend 6. **Healthcheck coincide** — Dockerfile `/health` = servidor `/health` 7. **.env.example documentado** — todas las variables de entorno visibles 8. **Migración automática** — si cambia el formato de un campo (plain → hash), detectar y migrar en `initDatabase()` ### CRM v2 Schema (7 entidades) Para proyectos CRM completos, usar el schema v2 documentado en `references/adela-crm-v2-schema.md`: - **empresas** (CIF, sector, dirección) → **contactos** (cargo, departamento) - **leads** con pipeline Kanban (nuevo → ganado/perdido) - **oportunidades** (valor €, fechas cierre) - **actividades** calendario (llamada/email/reunion/tarea/nota) - **notas** polimórficas (lead/empresa/contacto/oportunidad) ### CSS consistente — Preferencia de David ⚠️ **David odia diseños que no encajan** — especificamente mencionó "cuadrados" en el login que no combinaban con el resto. **Reglas para CSS en apps CRM/internas:** 1. **Tokens CSS primero** — definir `:root` variables ANTES de escribir componentes. Retroactive tokenization = 580 líneas de rework 2. Tokens consistentes (sin hex hardcodes): `--blue: #2563eb`, `--orange: #f97316` 3. Glass cards sutiles (`backdrop-filter: blur(12px)`) — no blancos planos 4. Border radius consistente: `--radius: 16px` para cards, `--radius-sm: 10px` para inputs 5. Responsive SIEMPRE 6. **NO** hacer cuadrados con bordes duros que no combinen con el estilo glass del resto 7. Si hay sidebar + main content, asegurar que ambos usan los mismos tokens 8. Botones: ghost para secundarios, primary para acciones principales 9. Modales: mismo estilo glass que las cards 10. Badges de color por estado (colores definidos en tokens, no inline) ### Deploy en NaN — Persistent Volumes ⚠️ **NaN soporta volúmenes persistentes, pero SOLO al crear la app nueva.** | Feature | Detalle | |---------|---------| | Configuración | Checkbox "Persistent storage" al crear app | | Mount point | `/data` (NO `/app/data`) | | Tamaño | `500Mi`, `5Gi`, `1Ti` (Kubernetes format) | | Réplicas | Máximo 1 efectiva | | Backup | NO — "Data is lost — there is no backup" | **Para activar:** 1. cloud.nanBuilders → Crear nueva app → Persistent storage ON 2. Volume size: `1Gi` mínimo 3. DB_PATH: `/data/datos.db` 4. Dockerfile: `RUN mkdir -p /data` **Si la app ya existe sin volumen:** crear app NUEVA con Persistent ON. No se puede añadir a una existente. ### Añadir nuevos tabs al frontend CRM Cuando se necesita añadir un nuevo módulo/tab a un CRM Adela existente (AdelaTest01), seguir este patrón de 4 pasos: #### Paso 1: Añadir nav link en index.html Insertar en `<ul class="nav-links">`, después del último `<li>`: ```html <li><a href="#" data-tab="nuevo-tab">🔣<span> Nombre Tab</span></a></li> ``` #### Paso 2: Añadir tab div en index.html Insertar en `<main class="main-content">`, en la posición deseada (orden visual del sidebar). Tres patrones: **Patrón tabla** (para listas de datos): ```html <div id="tab-nuevo-tab" class="tab"> <div class="tab-header"> <h1>Título</h1> <button id="btn-new-entidad" class="btn btn-primary">+ Nueva Entidad</button> </div> <div class="table-container glass-card"> <table class="data-table"> <thead><tr><th>Col1</th><th>Col2</th><th>Acciones</th></tr></thead> <tbody id="entidades-table-body"></tbody> </table> </div> </div> ``` **Patrón cards grid** (para visualización tipo kanban/cards): ```html <div id="tab-nuevo-tab" class="tab"> <div class="tab-header"> <h1>Título</h1> <button id="btn-new-entidad" class="btn btn-primary">+ Nueva Entidad</button> </div> <div class="cards-grid" id="entidades-grid"></div> </div> ``` **Patrón complejo** (dashboard con resumen + tablas múltiples, ej: Contabilidad): ```html <div id="tab-nuevo-tab" class="tab"> <div class="tab-header"> <h1>Título</h1> <div class="tab-actions"> <button id="btn-new-a" class="btn btn-primary">+ Nueva A</button> <button id="btn-new-b" class="btn btn-ghost">+ Nueva B</button> </div> </div> <div class="charts-row" style="margin-bottom:24px"> <div class="chart-section glass-card"> <h3>Resumen</h3> <div id="resumen-container" style="display:grid;grid-template-columns:repeat(2,1fr);gap:12px;padding:12px"> <div><small>Label1</small><br><strong id="res-val1">0</strong></div> <div><small>Label2</small><br><strong id="res-val2">0</strong></div> </div> </div> </div> <div class="table-container glass-card"> <h3>Tabla 1</h3> <table class="data-table"> <thead><tr><th>Col</th><th>Acciones</th></tr></thead> <tbody id="tabla1-body"></tbody> </table> </div> </div> ``` #### Paso 3: Añadir JS en crm.js **3a. Registrar en cambiarTab():** ```javascript if (tab === 'nuevo-tab') cargarEntidades() ``` **3b. Función de carga:** ```javascript async function cargarEntidades() { try { const data = await apiFetch('/api/entidades') const entidades = data.entidades || data.data || [] const tbody = document.getElementById('entidades-table-body') tbody.innerHTML = entidades.length === 0 ? '<tr><td colspan="N" class="empty-state">Sin datos</td></tr>' : entidades.map(e => `<tr>...`).join('') } catch (err) { console.error('Error entidades:', err) } } ``` **3c. Botón crear:** ```javascript document.getElementById('btn-new-entidad')?.addEventListener('click', () => { abrirModal('Nueva Entidad', [ { name: 'campo1', label: 'Campo 1', type: 'text', required: true }, { name: 'campo2', label: 'Campo 2', type: 'number' } ], async (data) => { await apiFetch('/api/entidades', { method: 'POST', body: JSON.stringify(data) }) cerrarModal(); cargarEntidades() }) }) ``` **3d. Helpers disponibles** (ya definidas en crm.js, usar sin reimplementar): - `apiFetch(url, options)` — fetch con auth bearer - `formatEuro(n)` → "1.234€" - `formatDate(d)` → "15 jun 2026" - `estadoBadge(estado)` → span con color según estado - `abrirModal(titulo, campos, onConfirm)` → modal genérico - `cerrarModal()` → cierra modal #### Paso 4: Verificar - Nav link aparece en sidebar - Tab div tiene `id="tab-nombre"` y clase `tab` - `cambiarTab()` llama la función de carga - Botón tiene listener con `?.addEventListener` (optional chaining — previene errores si el botón no existe en otro contexto) - Usar helpers existentes: `apiFetch()`, `formatEuro()`, `formatDate()`, `estadoBadge()`, `abrirModal()`, `cerrarModal()` **Nota:** El backend necesita los endpoints API correspondientes (`/api/entidades`, etc.) para que funcione el data fetching. El frontend es la capa de presentación; la lógica de negocio está en el servidor. #### Paso 5: Auditar compatibilidad Frontend↔Backend
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기