npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jamx-framework/cache

v1.0.0

Published

JAMX Framework — Cache with memory and Redis drivers

Readme

@jamx-framework/cache

Descripción

Módulo de caching para JAMX Framework. Proporciona una API unificada para almacenamiento en caché con múltiples backends (memoria, Redis, etc.), soportando TTL, invalidación por clave, y estrategias de caché como write-through y write-behind. Ideal para acelerar respuestas de APIs, bases de datos y cálculos costosos.

Cómo funciona

El módulo implementa un patrón de repositorio de caché con drivers intercambiables:

  1. Cache: Clase principal que maneja operaciones de get/set/delete con TTL
  2. Drivers: Implementaciones concretas (MemoryDriver, RedisDriver) que definen la persistencia
  3. Estrategias: Soporte para write-through (actualizar caché y origen simultáneamente) y write-behind (actualizar caché primero, origen después)
  4. Invalidación: Permite invalidar por clave, por patrón (prefix) o por completo

Componentes principales

  • src/cache.ts: Clase Cache que gestiona operaciones de caché
  • src/drivers/memory.ts: Driver que almacena en memoria (Map)
  • src/drivers/redis.ts: Driver que almacena en Redis
  • src/drivers/types.ts: Tipos compartidos (CacheDriver, CacheEntry, etc.)
  • src/index.ts: Punto de exportación

Uso básico

import { Cache, MemoryDriver } from '@jamx-framework/cache';

// Crear caché en memoria
const cache = new Cache(new MemoryDriver());

// Guardar con TTL de 5 minutos
await cache.set('users:123', { name: 'Juan', email: '[email protected]' }, 300);

// Obtener (con deserialización automática)
const user = await cache.get('users:123');
console.log('Usuario desde caché:', user);

// Verificar existencia
const exists = await cache.has('users:123');
console.log('¿Existe?', exists);

// Invalidar
await cache.delete('users:123');

Con Redis

import { Cache, RedisDriver } from '@jamx-framework/cache';

const redisDriver = new RedisDriver({
  host: 'localhost',
  port: 6379,
  password: 'secret',
});

const cache = new Cache(redisDriver);
await cache.set('session:abc123', { userId: 1 }, 3600);

Ejemplos

Caché de consultas de base de datos

import { Cache, MemoryDriver } from '@jamx-framework/cache';

const cache = new Cache(new MemoryDriver());

async function findUser(id: string) {
  const key = `user:${id}`;
  
  // Intentar obtener desde caché
  const cached = await cache.get(key);
  if (cached) {
    console.log('Hit caché');
    return cached;
  }
  
  // Consultar base de datos
  const user = await db.users.findById(id);
  if (user) {
    // Guardar en caché por 10 minutos
    await cache.set(key, user, 600);
  }
  
  return user;
}

Caché con invalidación por patrón

import { Cache, MemoryDriver } from '@jamx-framework/cache';

const cache = new Cache(new MemoryDriver());

// Guardar múltiples claves con prefijo común
await cache.set('products:1', product1, 300);
await cache.set('products:2', product2, 300);
await cache.set('products:3', product3, 300);

// Invalidar todas las claves que empiezan con 'products:'
await cache.invalidatePattern('products:*');

// Invalidar todo el caché
await cache.clear();

Write-through pattern

import { Cache, MemoryDriver } from '@jamx-framework/cache';

const cache = new Cache(new MemoryDriver());

async function updateUser(id: string, data: Partial<User>) {
  // 1. Actualizar caché primero
  const existing = await cache.get(`user:${id}`) ?? null;
  const updated = { ...existing, ...data };
  await cache.set(`user:${id}`, updated, 600);
  
  // 2. Actualizar base de datos
  await db.users.update(id, data);
  
  return updated;
}

Caché de resultados de API

import { Cache, RedisDriver } from '@jamx-framework/cache';

const cache = new Cache(new RedisDriver({ url: 'redis://localhost:6379' }));

async function fetchExternalApi(endpoint: string, params: Record<string, string>) {
  const query = new URLSearchParams(params).toString();
  const key = `api:${endpoint}:${query}`;
  
  // Intentar obtener desde caché
  const cached = await cache.get(key);
  if (cached) {
    return cached as ApiResponse;
  }
  
  // Hacer request HTTP
  const response = await fetch(`${endpoint}?${query}`);
  const data = await response.json();
  
  // Guardar en caché por 1 minuto
  await cache.set(key, data, 60);
  
  return data;
}

Uso con inyección de dependencias

import { Container } from '@jamx-framework/core';
import { Cache, MemoryDriver } from '@jamx-framework/cache';

// Registrar en contenedor
Container.registerSingleton('cache', () => new Cache(new MemoryDriver()));

// Resolver y usar
const cache = Container.resolve<Cache>('cache');
await cache.set('config', { theme: 'dark' }, 3600);

Flujo interno

  1. Inicialización: Se crea un Cache con un driver específico (Memory, Redis, etc.)
  2. Operaciones: get(), set(), has(), delete() se delegan al driver
  3. TTL management: Cada entrada almacena expiresAt; get() elimina entradas expiradas
  4. Serialización: Los valores se serializan automáticamente (JSON.stringify/parse)
  5. Invalidación por patrón: invalidatePattern() usa keys() + delete() para eliminar coincidencias
  6. Estadísticas: El driver puede reportar hits/misses (opcional)

API Reference (Resumen)

Cache

  • constructor(driver: CacheDriver)
  • async get<T>(key: string): Promise<T | null>
  • async set<T>(key: string, value: T, ttl?: number): Promise<void>
  • async has(key: string): Promise<boolean>
  • async delete(key: string): Promise<void>
  • async invalidatePattern(pattern: string): Promise<number> (número de claves eliminadas)
  • async clear(): Promise<void>
  • async keys(): Promise<string[]>

CacheDriver (interface)

  • async get<T>(key: string): Promise<CacheEntry<T> | null>
  • async set<T>(key: string, value: T, ttl: number): Promise<void>
  • async delete(key: string): Promise<void>
  • async clear(): Promise<void>
  • async keys(): Promise<string[]>

CacheEntry

  • value: T
  • expiresAt: number (timestamp en ms)
  • createdAt: number

Performance Considerations

  • MemoryDriver: Máxima velocidad, datos volátiles, ideal para development y small-scale
  • RedisDriver: Persistencia, clustering, TTL nativo, ideal para production y distributed systems
  • TTL granular: Cada clave puede tener su propio TTL
  • Lazy expiration: Las entradas se eliminan al acceder (no hay background cleanup)
  • Batch operations: delete() y keys() pueden ser costosos en Redis con muchas claves

Configuration Options

// MemoryDriver (sin configuración)
const memoryDriver = new MemoryDriver();

// RedisDriver
const redisDriver = new RedisDriver({
  host: 'localhost',
  port: 6379,
  password: 'secret',
  db: 0,
  ttlSupport: true, // usar EXPIRE de Redis
  prefix: 'jamx:',   // prefijo para claves
});

Testing

Tests en packages/cache/tests/unit/:

pnpm test

Cubre:

  • Operaciones básicas (get/set/has/delete)
  • TTL y expiración automática
  • Invalidación por patrón
  • Clear completo
  • Drivers múltiples (memory, redis mock)

Compatibility

  • Compatible con Node.js 18+
  • Funciona en Windows, macOS, Linux
  • RedisDriver requiere servidor Redis accesible
  • No requiere dependencias globales

CLI Integration

  • jamx cache:clear: Limpia todo el caché
  • jamx cache:stats: Muestra estadísticas (hits, misses, tamaño)
  • jamx cache:invalidate <pattern>: Invalida claves por patrón

This cache module provides a flexible, type-safe caching layer for JAMX applications, enabling developers to improve performance by reducing database load and accelerating response times with minimal code changes.