/** * Script para crear contenido de ejemplo (seed data) */ import { query } from '../config/database.js'; import 'dotenv/config'; import { randomUUID as uuidv4 } from 'crypto'; // Obtener ID del admin (asumiendo que existe) async function getAdminId() { const result = await query( `SELECT id FROM emerges_content.users WHERE role = 'super_admin' LIMIT 1` ); return result.rows[0]?.id || uuidv4(); } async function seedContent() { try { console.log('🌱 Creando contenido de ejemplo...'); const adminId = await getAdminId(); // 1. Checklist: Electrodos/Parches DESA const checklistElectrodos = { id: 'checklist-electrodos-desa', type: 'checklist', level: 'operativo', title: 'Colocación de Electrodos/Parches DESA', shortTitle: 'Electrodos DESA', description: 'Checklist para la correcta colocación de electrodos en desfibrilación', content: { items: [ { id: '1', text: 'Verificar que el paciente está en superficie seca y no metálica', order: 1, critical: true }, { id: '2', text: 'Secar el tórax si está húmedo', order: 2, critical: true }, { id: '3', text: 'Rasurar vello excesivo si es necesario', order: 3 }, { id: '4', text: 'Colocar parche derecho: debajo de la clavícula derecha', order: 4, critical: true }, { id: '5', text: 'Colocar parche izquierdo: línea axilar media izquierda', order: 5, critical: true }, { id: '6', text: 'Verificar que los parches están bien adheridos', order: 6, critical: true }, { id: '7', text: 'Conectar cables al DESA', order: 7, critical: true }, { id: '8', text: 'Asegurar que nadie toca al paciente durante análisis', order: 8, critical: true }, ], description: 'Secuencia de pasos para colocación correcta de electrodos en desfibrilación', estimatedTime: '30-60 segundos', applicableProtocols: ['rcp-adulto-svb', 'rcp-adulto-sva'], tags: ['DESA', 'desfibrilación', 'electrodos'], }, }; await insertContentItem(checklistElectrodos, adminId); console.log(' ✅ Checklist: Electrodos DESA'); // 2. Checklist: Preparación Intubación const checklistIntubacion = { id: 'checklist-preparacion-intubacion', type: 'checklist', level: 'operativo', title: 'Preparación para Intubación Orotraqueal', shortTitle: 'Preparación IOT', description: 'Checklist completo de preparación antes de intubación', content: { items: [ { id: '1', text: 'Verificar material: laringoscopio, tubos, estilete', order: 1, critical: true, category: 'Material' }, { id: '2', text: 'Comprobar fuente de luz del laringoscopio', order: 2, critical: true, category: 'Material' }, { id: '3', text: 'Preparar tubo endotraqueal (talla adecuada)', order: 3, critical: true, category: 'Material' }, { id: '4', text: 'Preparar estilete (si se usa)', order: 4, category: 'Material' }, { id: '5', text: 'Preparar jeringa para balón', order: 5, category: 'Material' }, { id: '6', text: 'Verificar aspiración funcionando', order: 6, critical: true, category: 'Verificación' }, { id: '7', text: 'Preparar fármacos: sedación y relajante', order: 7, critical: true, category: 'Fármacos' }, { id: '8', text: 'Verificar monitorización: SpO₂, ECG, capnografía', order: 8, critical: true, category: 'Monitorización' }, { id: '9', text: 'Posicionar paciente: alineación cabeza-cuello-tórax', order: 9, critical: true, category: 'Posicionamiento' }, { id: '10', text: 'Preoxigenación: 3-5 minutos con mascarilla con reservorio', order: 10, critical: true, category: 'Preoxigenación' }, ], description: 'Checklist completo para preparación segura de intubación orotraqueal', estimatedTime: '5-10 minutos', applicableProtocols: ['via-aerea', 'rcp-adulto-sva'], tags: ['IOT', 'intubación', 'vía aérea avanzada'], }, }; await insertContentItem(checklistIntubacion, adminId); console.log(' ✅ Checklist: Preparación Intubación'); // 3. Checklist: RCP Checklist (versión mejorada) const checklistRCP = { id: 'checklist-rcp-adulto-svb', type: 'checklist', level: 'operativo', title: 'Checklist RCP Adulto SVB', shortTitle: 'RCP SVB Checklist', description: 'Checklist interactivo para RCP básico en adultos', content: { items: [ { id: '1', text: 'Seguridad de la escena', order: 1, critical: true }, { id: '2', text: 'Comprobación de respuesta', order: 2, critical: true }, { id: '3', text: 'Apertura de vía aérea', order: 3, critical: true }, { id: '4', text: 'Comprobación de respiración (<10s)', order: 4, critical: true }, { id: '5', text: 'Activación de emergencias', order: 5, critical: true }, { id: '6', text: 'Inicio de compresiones', order: 6, critical: true }, { id: '7', text: 'Colocación del DEA', order: 7, critical: true }, { id: '8', text: 'Análisis y descarga si indicada', order: 8, critical: true }, { id: '9', text: 'RCP de alta calidad continua', order: 9, critical: true }, { id: '10', text: 'Reevaluación cada 2 minutos', order: 10, critical: true }, ], description: 'Checklist esencial para RCP básico en adultos', estimatedTime: 'Continuo', applicableProtocols: ['rcp-adulto-svb'], tags: ['RCP', 'SVB', 'reanimación'], }, }; await insertContentItem(checklistRCP, adminId); console.log(' ✅ Checklist: RCP Adulto SVB'); // 4. Protocolo de ejemplo: RCP Adulto SVB (extendido) const protocolRCP = { id: 'rcp-adulto-svb-extended', type: 'protocol', level: 'operativo', title: 'RCP Adulto SVB - Versión Extendida', shortTitle: 'RCP SVB Ext', description: 'Protocolo RCP SVB con checklist integrado y dosis inline', category: 'soporte_vital', subcategory: 'rcp', priority: 'critico', ageGroup: 'adulto', content: { pasosRapidos: [ { order: 1, text: 'Garantizar seguridad de la escena', critical: true, timeEstimate: '5-10s' }, { order: 2, text: 'Comprobar consciencia: estimular y preguntar "¿Se encuentra bien?"', critical: true, timeEstimate: '5s' }, { order: 3, text: 'Si no responde, llamar inmediatamente al 112', critical: true, timeEstimate: '10s' }, { order: 4, text: 'Abrir vía aérea: maniobra frente-mentón', critical: true, timeEstimate: '5s' }, { order: 5, text: 'Comprobar respiración: VER-OÍR-SENTIR (máx. 10 segundos)', critical: true, timeEstimate: '10s' }, ], checklist: { enabled: true, items: [ { id: '1', text: 'Seguridad de la escena', order: 1, reusableChecklistId: null }, { id: '2', text: 'Comprobación de respuesta', order: 2, reusableChecklistId: null }, { id: '3', text: 'Apertura de vía aérea', order: 3, reusableChecklistId: null }, ], title: 'Checklist RCP SVB', }, dosisInline: [ { drugId: 'adrenalina', drugName: 'Adrenalina', adultDose: '1 mg IV/IO cada 3-5 min', route: 'IV', timing: 'Cada 3-5 minutos en PCR', context: 'En PCR, una vez establecida vía IV/IO', }, ], herramientasContexto: [ { id: 'calc-dosis-pediatrica', name: 'Calculadora de Dosis Pediátrica', type: 'calculator', description: 'Calcula dosis por peso para pacientes pediátricos', }, ], fuentes: [ { organization: 'ERC', guideline: 'European Resuscitation Council Guidelines 2021', year: 2021, section: 'Adult Basic Life Support', }, ], warnings: [ 'Profundidad compresiones: 5-6 cm', 'Frecuencia: 100-120 compresiones/min', ], keyPoints: [ 'Compresiones de calidad salvan vidas', 'No interrumpir para pulso hasta que haya signos de vida', ], equipment: ['DEA', 'Bolsa-mascarilla'], drugs: ['Adrenalina'], version: 1, lastUpdated: new Date().toISOString(), }, }; await insertContentItem(protocolRCP, adminId); console.log(' ✅ Protocolo: RCP Adulto SVB Extendido'); // 5. Protocolo de ejemplo: Shock Hemorrágico (extendido) const protocolShock = { id: 'shock-hemorragico-extended', type: 'protocol', level: 'operativo', title: 'Shock Hemorrágico - Versión Extendida', shortTitle: 'Shock Hemorrágico Ext', description: 'Protocolo de shock hemorrágico con checklist y dosis inline', category: 'soporte_vital', subcategory: 'shock', priority: 'critico', ageGroup: 'adulto', content: { pasosRapidos: [ { order: 1, text: 'Control de hemorragia externa: presión directa', critical: true, timeEstimate: 'Inmediato' }, { order: 2, text: 'Torniquete si hemorragia en extremidad no controlable', critical: true, timeEstimate: '30-60s' }, { order: 3, text: 'Oxigenoterapia alto flujo', critical: true, timeEstimate: '30s' }, ], dosisInline: [ { drugId: 'acido-tranexamico', drugName: 'Ácido Tranexámico', adultDose: '1g IV en bolo lento (10 min)', route: 'IV', timing: 'Lo antes posible en hemorragia grave', context: 'En hemorragia traumática grave', }, ], fuentes: [ { organization: 'SEMES', guideline: 'Protocolo de Shock Hemorrágico', year: 2023, }, ], warnings: [ 'Hipotensión permisiva: TAS 80-90 mmHg', 'Excepto en TCE: mantener TAS >90 mmHg', ], equipment: ['Torniquete', 'Agentes hemostáticos'], drugs: ['Ácido tranexámico'], version: 1, lastUpdated: new Date().toISOString(), }, }; await insertContentItem(protocolShock, adminId); console.log(' ✅ Protocolo: Shock Hemorrágico Extendido'); console.log('\n✅ Contenido de ejemplo creado exitosamente'); } catch (error) { console.error('❌ Error creando contenido de ejemplo:', error); process.exit(1); } } async function insertContentItem(item, userId) { // Verificar si ya existe const existing = await query( `SELECT id FROM emerges_content.content_items WHERE id = $1`, [item.id] ); if (existing.rows.length > 0) { console.log(` ⚠️ ${item.id} ya existe, saltando...`); return; } // Insertar item await query( `INSERT INTO emerges_content.content_items (id, type, level, title, short_title, description, category, subcategory, priority, age_group, status, version, latest_version, created_by, updated_by) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, 'draft', 1, 1, $11, $11)`, [ item.id, item.type, item.level, item.title, item.shortTitle, item.description, item.category, item.subcategory, item.priority, item.ageGroup, userId, ] ); // Insertar versión const versionId = uuidv4(); await query( `INSERT INTO emerges_content.content_versions (version_id, content_item_id, version_number, json_content, created_by) VALUES ($1, $2, 1, $3, $4)`, [versionId, item.id, 1, JSON.stringify(item.content), userId] ); // Actualizar current_version_id await query( `UPDATE emerges_content.content_items SET current_version_id = $1 WHERE id = $2`, [versionId, item.id] ); } seedContent();