@syllkom/hyper-db
v3.0.1
Published
High-performance NoSQL sharded database for Node.js. Features LMDB-backed binary storage, automatic partitioning, Memory Arenas, and transparent JS object persistence via Proxies.
Maintainers
Readme
HyperDB
HyperDB es una base de datos NoSQL de alto rendimiento y particionamiento automático (sharding) para Node.js.
Su filosofía es simple: Interactúa con tu base de datos exactamente igual que con un objeto de JavaScript. Gracias a su arquitectura basada en Proxies transparentes, LMDB (VaultEngine) y cachés LRU (Memory Arenas), HyperDB guarda, particiona y recupera tus datos en binario a velocidades extremas sin que tengas que escribir una sola consulta manual.
Características Principales
- Persistencia Transparente: Usa
db.data.prop = "valor"y se guardará en disco automáticamente. - Auto-Sharding (ShardMatrix): Los objetos anidados se separan automáticamente en archivos binarios independientes (
.node.biny.map.bin). Cargar la raíz no carga toda la base de datos en RAM. - Lazy Commits (WriteBuffer): Las escrituras se agrupan en lotes (debounce) para no saturar el I/O del disco.
- Motor LMDB: Lecturas y escrituras atómicas ultrarrápidas y seguras.
- Funciones Almacenables: Puedes guardar funciones de JS directamente en la base de datos y ejecutarlas después.
$ Instalación
Requiere Node.js >= 18.0.0.
npm install @syllkom/hyper-dbUso Básico
Olvídate de los INSERT, SELECT o UPDATE. En HyperDB todo es un objeto.
import { HyperDB } from '@syllkom/hyper-db';
// 1. Inicializar el motor
const db = new HyperDB({
folder: './db_data', // Carpeta donde se guardará la DB
memory: 50 // Límite de la Arena de Memoria en MB
});
// 2. Escribir datos (Se guarda en disco automáticamente en segundo plano)
db.data.nombre = "Servidor Alfa";
db.data.config = {
puerto: 8080,
mantenimiento: false
};
// 3. Leer datos (Se lee desde la Memory Arena o el disco instantáneamente)
console.log(db.data.config.puerto); // 8080Conceptos Avanzados y Prácticas
1. Auto-Sharding (Fragmentación Automática)
Cuando asignas un objeto a una propiedad, HyperDB crea un nuevo "Shard" (fragmento). Esto significa que la base de datos nunca carga todo a la vez.
// Esto crea un nodo raíz
db.data.usuarios = {};
// Esto crea un sub-shard solo para "alice".
// Leer la lista de usuarios NO cargará todo el perfil de Alice en RAM.
db.data.usuarios.alice = {
edad: 28,
rol: "admin",
inventario: ["espada", "escudo"]
};2. Navegación Profunda (navigate)
Si tienes una estructura muy profunda y no quieres cargar los objetos intermedios, puedes navegar directamente al shard que necesitas:
// Va directo al archivo binario de "alice" sin cargar "usuarios" completos
const aliceProxy = db.navigate('usuarios', 'alice');
if (aliceProxy) {
aliceProxy.edad = 29; // Actualiza directamente su shard
}3. Almacenar Funciones
A diferencia de un JSON tradicional o bases de datos comunes, HyperDB soporta la serialización y ejecución de funciones gracias a su HyperCodec.
db.data.utilidades = {
saludar: function(nombre) {
return `Hola, ${nombre}! Bienvenido a HyperDB.`;
}
};
// Ejecutar la función almacenada
const mensaje = db.data.utilidades.saludar("Zeppth");
console.log(mensaje);4. Interceptores de Proxy (Triggers)
Puedes reaccionar a eventos de lectura, escritura o eliminación directamente en la base de datos definiendo "traps" en la propiedad especial $proxy.
db.data.usuarios.$proxy.define({
set: function(target, key, value) {
console.log(`[LOG] Se modificó el usuario: ${key}`);
// Validación de datos antes de guardar
if (typeof value !== 'object') {
this.reject(new Error("Un usuario debe ser un objeto"));
return;
}
// Siempre debes resolver con el valor final que deseas guardar
this.resolve(value);
}
});
db.data.usuarios.bob = { edad: 30 }; // Imprime: [LOG] Se modificó el usuario: bob
db.data.usuarios.carlos = "Invalido"; // Lanza el Error definido en el rejectConfiguración del Motor (VaultEngine)
Al instanciar new HyperDB(config), puedes ajustar el rendimiento con las siguientes opciones:
| Parámetro | Tipo | Por defecto | Descripción |
| :--- | :--- | :--- | :--- |
| folder | String | './data' | Directorio donde se almacenarán los archivos .bin. |
| memory | Number | 50 | Memoria máxima asignada a las Cachés LRU (en Megabytes). |
| atomic | Boolean | true | Habilita operaciones de escritura atómicas en LMDB. |
| maps.threshold | Number | 10 | Cantidad de escrituras en mapas antes de un guardado forzoso. |
| maps.debounce | Number | 5000 | Milisegundos a esperar antes de agrupar y guardar mapas (Lazy commit). |
| nodes.threshold| Number | 10 | Cantidad de escrituras en nodos de estado antes de un guardado. |
| nodes.debounce | Number | 5000 | Milisegundos a esperar para guardar nodos. |
Métodos de Utilidad
// Fuerza a vaciar la caché y sincronizar todo el WriteBuffer al disco inmediatamente
db.flush();
// Obtiene estadísticas en vivo de la memoria caché (Arenas)
console.log(db.metrics());
/* Ejemplo de salida:
{
pointers: { used: '500.00 KB', limit: '5.00 MB', items: 12 },
nodes: { used: '1.20 MB', limit: '45.00 MB', items: 145 }
}
*/Buenas Prácticas
- Evita arrays inmensos: Debido a la naturaleza de los Proxies en JavaScript, hacer mutaciones continuas en arrays gigantes (ej.
push,splicemasivos) es menos eficiente que usar objetos con claves únicas ({ "id_1": {...}, "id_2": {...} }). - Aprovecha el debounce: No uses
db.flush()manualmente después de cada asignación. Deja que elWriteBufferinterno recoja los cambios durante el tiempo configurado (5000ms por defecto) para maximizar la vida útil del disco y el rendimiento. - Mide tu Memoria: Si vas a operar millones de registros en producción, usa
db.metrics()para monitorear tuMemoryArenay ajusta el límite de MB según el servidor que estés utilizando.
