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 🙏

© 2025 – Pkg Stats / Ryan Hefner

simple-cache-ts

v1.0.2

Published

A lightweight, type-safe, in-memory cache with TTL and multiple eviction policies

Readme

SimpleCache

A lightweight, type-safe, in-memory cache implementation for TypeScript/JavaScript with configurable capacity, TTL (time-to-live), multiple eviction policies, and comprehensive statistics tracking.

Features

  • 🚀 Zero dependencies - Lightweight and fast
  • 🔒 Type-safe - Full TypeScript support with generics
  • ⏱️ TTL support - Global and per-entry time-to-live
  • 🎯 Multiple eviction policies - LRU, FIFO, Random, None
  • 📊 Built-in statistics - Track cache performance with detailed metrics
  • 📦 Dual module support - Works with both ES modules and CommonJS
  • 🌳 Tree-shakeable - Optimized for modern bundlers
  • Well-tested - Comprehensive test suite with 100% coverage

Installation

npm install simple-cache-ts

Quick Start

import { SimpleCache } from "simple-cache-ts";

// Basic usage
const cache = new SimpleCache<string, number>();
cache.set("age", 29);
console.log(cache.get("age")); // 29

// With configuration and stats
const apiCache = new SimpleCache<string, unknown>({
  capacity: 100,
  defaultTtl: 60000, // 1 minute
  evictionPolicy: "lru",
  enableStats: true, // Enable statistics tracking
});

// Check performance
console.log(apiCache.getStats());
// { hits: 0, misses: 0, hitRate: 0, missRate: 0, ... }

Performance

SimpleCache delivers excellent performance for real-world applications:

  • 7M+ operations/sec for SET operations
  • 8.6M+ operations/sec for GET operations (cache hits)
  • Minimal overhead - ~50% of native Map performance while adding TTL, eviction, and type safety

Perfect for high-throughput applications like API caching, session management, and request memoization.

Why SimpleCache?

| Feature | SimpleCache | Map | Other Libraries | | ----------------- | ----------- | ------ | --------------- | | TTL Support | ✅ | ❌ | ✅ | | Type Safety | ✅ | ✅ | Varies | | Zero Dependencies | ✅ | ✅ | ❌ | | Statistics | ✅ | ❌ | Varies | | Size | ~2KB | Native | 10KB+ | | Eviction Policies | 4 | None | Varies |

API Reference

Constructor

new SimpleCache<K, V>(options?: CacheOptions & { enableStats?: boolean })

CacheOptions

| Option | Type | Default | Description | | ---------------- | ---------------- | ----------- | ------------------------------------------ | | capacity | number | Infinity | Maximum number of entries | | defaultTtl | number | undefined | Default TTL in milliseconds | | evictionPolicy | EvictionPolicy | 'lru' | Eviction strategy when capacity is reached | | enableStats | boolean | false | Enable statistics tracking |

EvictionPolicy

  • 'lru' - Least Recently Used (default)
  • 'fifo' - First In, First Out
  • 'random' - Random eviction
  • 'none' - Throws error when capacity is reached

Core Methods

set(key: K, value: V, ttl?: number): void

Store a value with optional TTL override.

cache.set("user", { name: "John" });
cache.set("session", "abc123", 30000); // 30 second TTL

get(key: K): V | undefined

Retrieve a value. Returns undefined if key doesn't exist or has expired.

const user = cache.get("user");
if (user) {
  console.log(user.name);
}

has(key: K): boolean

Check if a key exists and hasn't expired.

if (cache.has("session")) {
  // Session is valid
}

delete(key: K): boolean

Remove a key from the cache. Returns true if the key existed.

cache.delete("oldSession"); // true if existed

clear(): void

Remove all entries from the cache.

cache.clear();

size(): number

Get the current number of entries in the cache.

console.log(`Cache has ${cache.size()} entries`);

TTL Utilities

ttl(key: K): number

Get the remaining TTL for a key in milliseconds.

const remaining = cache.ttl("session");
if (remaining > 0) {
  console.log(`Session expires in ${remaining}ms`);
} else if (remaining === -1) {
  console.log("Session has no expiry");
} else {
  console.log("Session does not exist");
}

Return values:

  • > 0 - Remaining TTL in milliseconds
  • -1 - Key exists but has no expiry
  • -2 - Key does not exist

expire(key: K, ttl: number): boolean

Set TTL on an existing key. Returns true if key exists.

cache.expire("session", 60000); // Expire in 1 minute

persist(key: K): boolean

Remove TTL from a key, making it permanent. Returns true if key exists.

cache.persist("config"); // Remove expiry

Iteration

keys(): IterableIterator<K>

Get an iterator of all keys.

for (const key of cache.keys()) {
  console.log(key);
}

// Or convert to array
const allKeys = Array.from(cache.keys());

Statistics

getStats(): CacheStats

Get detailed cache performance statistics.

const stats = cache.getStats();
console.log(`Hit rate: ${stats.hitRate}%`);
console.log(`Total requests: ${stats.totalRequests}`);

CacheStats Interface:

interface CacheStats {
  hits: number; // Successful cache retrievals
  misses: number; // Failed cache retrievals
  sets: number; // Number of items stored
  deletes: number; // Number of items deleted
  evictions: number; // Number of items evicted due to capacity
  expires: number; // Number of items expired due to TTL
  hitRate: number; // Percentage of successful retrievals (0-100)
  missRate: number; // Percentage of failed retrievals (0-100)
  totalRequests: number; // Total get operations (hits + misses)
}

resetStats(): void

Reset all statistics counters to zero.

cache.resetStats();

enableStats(): void

Enable statistics tracking if it was disabled.

cache.enableStats();

disableStats(): void

Disable statistics tracking to improve performance.

cache.disableStats();

isStatsEnabled(): boolean

Check if statistics tracking is currently enabled.

if (cache.isStatsEnabled()) {
  console.log("Stats are being tracked");
}

Examples

HTTP API Cache with Performance Monitoring

import { SimpleCache } from "simple-cache-ts";

const apiCache = new SimpleCache<string, unknown>({
  capacity: 100,
  evictionPolicy: "lru",
  enableStats: true, // Track performance
});

async function fetchWithCache(url: string) {
  if (apiCache.has(url)) {
    console.log(`Cache hit: ${url}`);
    return apiCache.get(url);
  }

  console.log(`Fetching: ${url}`);
  const response = await fetch(url);
  const data = await response.json();

  apiCache.set(url, data, 300000); // Cache for 5 minutes
  return data;
}

// Monitor cache performance
setInterval(() => {
  const stats = apiCache.getStats();
  console.log(
    `Cache performance: ${stats.hitRate}% hit rate, ${stats.totalRequests} total requests`
  );
}, 60000); // Log stats every minute

Session Management with Statistics

const sessionCache = new SimpleCache<string, UserSession>({
  capacity: 1000,
  defaultTtl: 30 * 60 * 1000, // 30 minutes
  evictionPolicy: "lru",
  enableStats: true,
});

function createSession(userId: string): string {
  const sessionId = generateSessionId();
  sessionCache.set(sessionId, { userId, createdAt: Date.now() });
  return sessionId;
}

function getSession(sessionId: string): UserSession | null {
  return sessionCache.get(sessionId) || null;
}

function extendSession(sessionId: string): boolean {
  return sessionCache.expire(sessionId, 30 * 60 * 1000);
}

// Performance monitoring
function getSessionStats() {
  const stats = sessionCache.getStats();
  return {
    activeSessions: sessionCache.size(),
    performance: {
      hitRate: stats.hitRate,
      totalRequests: stats.totalRequests,
      evictions: stats.evictions,
      expires: stats.expires,
    },
  };
}

Configuration Cache

const configCache = new SimpleCache<string, Config>({
  capacity: 50,
  evictionPolicy: "none", // Throw error instead of evicting
});

function loadConfig(key: string): Config {
  if (configCache.has(key)) {
    return configCache.get(key)!;
  }

  const config = loadConfigFromFile(key);
  configCache.set(key, config); // No TTL - permanent
  return config;
}

Performance Optimization with Stats

const cache = new SimpleCache<string, ExpensiveResult>({
  capacity: 500,
  defaultTtl: 300000, // 5 minutes
  evictionPolicy: "lru",
  enableStats: true,
});

async function expensiveOperation(key: string): Promise<ExpensiveResult> {
  // Check cache first
  const cached = cache.get(key);
  if (cached) {
    return cached;
  }

  // Perform expensive operation
  const result = await performExpensiveComputation(key);
  cache.set(key, result);

  return result;
}

// Analyze and optimize cache performance
function analyzeCachePerformance() {
  const stats = cache.getStats();

  if (stats.hitRate < 50) {
    console.warn("Low hit rate - consider increasing capacity or TTL");
  }

  if (stats.evictions > stats.expires) {
    console.warn("More evictions than expires - consider increasing capacity");
  }

  return {
    efficiency:
      stats.hitRate >= 80 ? "excellent" : stats.hitRate >= 60 ? "good" : "poor",
    recommendations: generateRecommendations(stats),
  };
}

Eviction Policies

LRU (Least Recently Used)

Evicts the item that hasn't been accessed for the longest time. Both get() and set() operations update the recency.

const cache = new SimpleCache({ capacity: 2, evictionPolicy: "lru" });
cache.set("a", 1);
cache.set("b", 2);
cache.get("a"); // 'a' becomes most recent
cache.set("c", 3); // 'b' is evicted (least recent)

FIFO (First In, First Out)

Evicts the oldest inserted item regardless of access patterns.

const cache = new SimpleCache({ capacity: 2, evictionPolicy: "fifo" });
cache.set("a", 1);
cache.set("b", 2);
cache.get("a"); // Access doesn't matter
cache.set("c", 3); // 'a' is evicted (oldest)

Random

Evicts a random item when capacity is reached.

const cache = new SimpleCache({ capacity: 2, evictionPolicy: "random" });
cache.set("a", 1);
cache.set("b", 2);
cache.set("c", 3); // Either 'a' or 'b' is randomly evicted

None

Throws an error when capacity is reached instead of evicting.

const cache = new SimpleCache({ capacity: 1, evictionPolicy: "none" });
cache.set("a", 1);
cache.set("b", 2); // Throws "Cache capacity reached"

TypeScript Usage

SimpleCache is fully typed and supports generic type parameters:

// Strongly typed cache
const userCache = new SimpleCache<number, User>();
userCache.set(123, { name: "John", email: "[email protected]" });
const user: User | undefined = userCache.get(123);

// Using with custom types
interface CacheEntry {
  data: unknown;
  metadata: { source: string; timestamp: number };
}

const metaCache = new SimpleCache<string, CacheEntry>();

Performance Characteristics

  • Time Complexity:

    • get(), set(), delete(), has(): O(1) average
    • LRU operations: O(1) (uses Map insertion order)
    • Random eviction: O(n) where n is cache size
  • Space Complexity: O(capacity)

  • Memory Usage: Minimal overhead, stores only the data you put in plus small metadata

Browser and Node.js Support

  • Node.js: 14+ (ES2020+ features)
  • Browsers: Chrome 80+, Firefox 72+, Safari 13.1+, Edge 80+
  • Module Systems: ESM and CommonJS

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build the library
npm run build

# Lint and format
npm run lint
npm run format

# Type check
npm run typecheck

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.