codigo0/backend/scripts/seed-content.js

296 lines
12 KiB
JavaScript
Raw Normal View History

2026-01-19 08:10:16 +00:00
/**
* 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();