Las herramientas de administración de bases de datos tradicionales suelen presentar interfaces saturadas que complican la curva de aprendizaje. Para entornos de desarrollo local y propósitos educativos, un cliente gráfico enfocado exclusviamente en operaciones CRUD básicas y conexión predeterminada optimiza significativamente el flujo de trabajo. A continuación, se detalla la arquitectura técnica para construir un administrador de Redis que prioriza la accesibilidad visual (elementos escalados al 150%) y la simplicidad operativa.
Dado que los navegadores web no pueden comunicarse directamente con el protocolo TCP de Redis, se requiere una arquitectura de dos capas: un backend ligero en Node.js para manejar la conexión y un frontend en HTML/CSS/JavaScript para la interfaz.
1. Servidor Intermediario y Lógica de Base de Datos
El servidor Node.js actuará como puente, configurado para detectar automáticamente la instancia local en el puerto 6379. Se implementa un endpoint REST genérico que encapsula y valida los cinco comandos fundamentales requeridos: PING, SET, GET, DEL y FLUSHALL.
const express = require('express');
const { createClient } = require('redis');
const app = express();
app.use(express.json());
app.use(express.static('public'));
// Inicialización del cliente con reconexión automática al puerto por defecto
const dbClient = createClient({ url: 'redis://127.0.0.1:6379' });
dbClient.on('error', err => console.error('Fallo crítico en la conexión Redis:', err));
dbClient.connect();
// Endpoint de verificación de estado inicial
app.get('/api/status', async (req, res) => {
try {
const pong = await dbClient.ping();
res.json({ connected: true, message: pong });
} catch (error) {
res.status(503).json({ connected: false, error: 'Servicio de base de datos no disponible' });
}
});
// Procesador centralizado de comandos
app.post('/api/exec', async (req, res) => {
const { command, key, value } = req.body;
try {
let result;
switch (command.toUpperCase()) {
case 'SET':
result = await dbClient.set(key, value);
break;
case 'GET':
result = await dbClient.get(key);
break;
case 'DEL':
result = await dbClient.del(key);
break;
case 'FLUSHALL':
result = await dbClient.flushAll();
break;
default:
return res.status(400).json({ error: 'Comando no soportado por el cliente' });
}
res.json({ success: true, data: result });
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
app.listen(3000, () => console.log('Gestor Redis activo en http://localhost:3000'));
2. Interfaz de Usuario Accesible
Para garantizar que la herramienta minimice la fricción cognitiva, el CSS aplica un factor de escala global del 150% utilizando variables personalizadas, y emplea una paleta de colores de alto contraste. El modelo de objetos del documento (DOM) se reduce estrictamente a dos contenedores: un panel de control interactivo y un visor de respuestas asíncronas.
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Redis Manager - Lite</title>
<style>
:root {
--bg-primary: #ffffff;
--text-main: #1e293b;
--accent-color: #2563eb;
--danger-color: #dc2626;
--success-color: #16a34a;
--ui-scale: 1.5;
}
body {
font-family: system-ui, sans-serif;
font-size: calc(1rem * var(--ui-scale));
background-color: var(--bg-primary);
color: var(--text-main);
padding: 2rem;
max-width: 800px;
margin: auto;
}
.control-panel {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
button {
font-size: inherit;
padding: 1rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
transition: transform 0.1s;
}
button:active { transform: scale(0.95); }
.btn-primary { background-color: var(--accent-color); color: white; }
.btn-danger { background-color: var(--danger-color); color: white; }
input {
font-size: inherit;
padding: 0.8rem;
width: 100%;
border: 2px solid #cbd5e1;
border-radius: 8px;
margin-bottom: 1rem;
box-sizing: border-box;
}
#output-console {
background: #f8fafc;
border: 2px dashed #cbd5e1;
padding: 1.5rem;
border-radius: 8px;
min-height: 100px;
font-family: monospace;
white-space: pre-wrap;
}
.guide-text { color: #64748b; font-size: 0.8em; margin-bottom: 1.5rem; }
</style>
</head>
<body>
<h1>Gestor Redis</h1>
<p class="guide-text">Conexión automática al puerto 6379. Ingrese los parámetros y ejecute una operación.</p>
<input type="text" id="keyInput" placeholder="Clave (Key)">
<input type="text" id="valueInput" placeholder="Valor (Value)">
<div class="control-panel">
<button class="btn-primary" onclick="executeOperation('PING')">PING</button>
<button class="btn-primary" onclick="executeOperation('SET')">SET</button>
<button class="btn-primary" onclick="executeOperation('GET')">GET</button>
<button class="btn-danger" onclick="executeOperation('DEL')">DEL</button>
<button class="btn-danger" onclick="executeOperation('FLUSHALL')">FLUSHALL</button>
</div>
<h2>Consola de Respuesta</h2>
<div id="output-console">Iniciando diagnóstico de conexión...</div>
<script>
const consoleEl = document.getElementById('output-console');
const keyField = document.getElementById('keyInput');
const valueField = document.getElementById('valueInput');
async function executeOperation(cmd) {
consoleEl.textContent = `Procesando comando: ${cmd}...`;
consoleEl.style.color = 'var(--text-main)';
try {
const httpResponse = await fetch('/api/exec', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
command: cmd,
key: keyField.value,
value: valueField.value
})
});
const payload = await httpResponse.json();
if (payload.success) {
consoleEl.textContent = `Operación exitosa:\n${JSON.stringify(payload.data, null, 2)}`;
consoleEl.style.color = 'var(--success-color)';
} else {
throw new Error(payload.error);
}
} catch (err) {
consoleEl.textContent = `Fallo de ejecución: ${err.message}\n\nAcción recomendada: Verifique el estado del servicio Redis.`;
consoleEl.style.color = 'var(--danger-color)';
}
}
// Diagnóstico inicial al cargar el DOM
window.onload = async () => {
const res = await fetch('/api/status');
const data = await res.json();
if (data.connected) {
consoleEl.textContent = 'Conexión establecida correctamente con localhost:6379';
consoleEl.style.color = 'var(--success-color)';
} else {
consoleEl.textContent = 'Imposible conectar. Asegúrese de que Redis esté corriendo en el puerto 6379.';
consoleEl.style.color = 'var(--danger-color)';
}
};
</script>
</body>
</html>
3. Gestión de Excepciones y Consideraciones de Entorno
El diseño expuesto resuelve eficientemente las necesidades de consultas rápidas, pero requiere mecanismos adicioanles para garantizar la robustez en distintos escenarios:
- Conflictos de Puerto: Si el puerto
6379está bloqueado por otro proceso, el backend captura el eventoerrordel cliente Redis y responde con un código HTTP 503. La lógica del frontend intercepta este estado y renderiza instrucciones de mitigación en color rojo para guiar al usuario. - Autenticación: Aunque el formulario omite campos de contraseña para mantener la simplicidad, la cadena de conexión en el backend puede refactorizarse para leer credenciales dinámicamente usando variables de entorno (ej.
redis://:password@127.0.0.1:6379). - Distribución Multiplaatforma: Al empaquetar el servidor Express y los archivos estáticos en una imagen Docker, la aplicación puede ejecutarse de forma aislada en cualquier sistema operativo sin requerir instalaciones nativas de Node.js, permitiendo un despliegue instantáneo a través de un enlace web local.