CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-keyv

Simple key-value storage with support for multiple backends

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

storage-adapters.mddocs/

Storage Adapters

Pluggable storage backend system with support for Redis, MongoDB, SQLite, PostgreSQL, MySQL, and any Map-compatible storage.

Capabilities

Storage Adapter Interface

The KeyvStoreAdapter interface that all storage adapters must implement.

interface KeyvStoreAdapter {
  /** Configuration options for the adapter */
  opts: any;
  /** Optional namespace for key prefixing */
  namespace?: string;
  
  /** Get value by key */
  get<Value>(key: string): Promise<StoredData<Value> | undefined>;
  /** Set value with optional TTL */
  set(key: string, value: any, ttl?: number): any;
  /** Delete key */
  delete(key: string): Promise<boolean>;
  /** Clear all keys in namespace */
  clear(): Promise<void>;
  
  // Optional batch operations (provide better performance when implemented)
  /** Set multiple values */
  setMany?(values: Array<{key: string; value: any; ttl?: number}>): Promise<void>;
  /** Get multiple values */
  getMany?<Value>(keys: string[]): Promise<Array<StoredData<Value | undefined>>>;
  /** Check if key exists */
  has?(key: string): Promise<boolean>;
  /** Check if multiple keys exist */
  hasMany?(keys: string[]): Promise<boolean[]>;
  /** Delete multiple keys */
  deleteMany?(key: string[]): Promise<boolean>;
  /** Disconnect from storage */
  disconnect?(): Promise<void>;
  /** Iterator for all keys */
  iterator?<Value>(namespace?: string): AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>;
}

interface IEventEmitter {
  on(event: string, listener: (...arguments_: any[]) => void): IEventEmitter;
}

// KeyvStoreAdapter extends IEventEmitter for error handling

Using Built-in Map Storage

The default in-memory storage using JavaScript Map.

// Default constructor uses Map storage
new Keyv(); // Uses new Map() internally
new Keyv(new Map()); // Explicit Map usage

Usage Examples:

import Keyv from "keyv";

// Default in-memory storage
const keyv = new Keyv();
await keyv.set('key', 'value');
console.log(await keyv.get('key')); // 'value'

// Using existing Map
const existingMap = new Map();
existingMap.set('prefilled', 'data');
const keyvWithMap = new Keyv(existingMap);
console.log(await keyvWithMap.get('prefilled')); // 'data'

// Map with options
const keyvMapWithOptions = new Keyv(new Map(), { 
  namespace: 'cache',
  ttl: 60000 
});

Redis Adapter

High-performance Redis storage with native TTL support.

// Import pattern for Redis adapter
import KeyvRedis from "@keyv/redis";

const keyvRedis = new KeyvRedis(uri: string, options?: any);
const keyv = new Keyv(keyvRedis);

Usage Examples:

import Keyv from "keyv";
import KeyvRedis from "@keyv/redis";

// Basic Redis connection
const keyvRedis = new KeyvRedis('redis://localhost:6379');
const keyv = new Keyv(keyvRedis);

// Redis with authentication
const keyvAuth = new KeyvRedis('redis://user:pass@localhost:6379');
const keyvWithAuth = new Keyv(keyvAuth);

// Redis with options and Keyv config
const redisStore = new KeyvRedis('redis://localhost:6379', {
  // Redis-specific options
  retryDelayOnFailover: 100,
  maxRetriesPerRequest: 3
});

const keyv = new Keyv(redisStore, {
  namespace: 'app-cache',
  ttl: 300000 // 5 minutes default TTL
});

// Handle connection errors
keyv.on('error', (err) => console.error('Redis connection error:', err));

await keyv.set('user:123', { name: 'Alice', role: 'admin' });

MongoDB Adapter

MongoDB storage with TTL collection support.

// Import pattern for MongoDB adapter  
import KeyvMongo from "@keyv/mongo";

const keyvMongo = new KeyvMongo(uri: string, options?: any);
const keyv = new Keyv(keyvMongo);

Usage Examples:

import Keyv from "keyv";
import KeyvMongo from "@keyv/mongo";

// Basic MongoDB connection
const keyvMongo = new KeyvMongo('mongodb://localhost:27017/mydb');
const keyv = new Keyv(keyvMongo);

// MongoDB with authentication
const keyvAuth = new KeyvMongo('mongodb://user:pass@localhost:27017/mydb');

// MongoDB with options
const mongoStore = new KeyvMongo('mongodb://localhost:27017/mydb', {
  collection: 'cache', // Custom collection name
  // MongoDB-specific options
});

const keyv = new Keyv(mongoStore, { namespace: 'sessions' });

await keyv.set('session:abc123', { userId: 456, loginTime: Date.now() });

SQLite Adapter

Local SQLite storage for development and single-node deployments.

// Import pattern for SQLite adapter
import KeyvSqlite from "@keyv/sqlite";

const keyvSqlite = new KeyvSqlite(uri: string);
const keyv = new Keyv(keyvSqlite);

Usage Examples:

import Keyv from "keyv";
import KeyvSqlite from "@keyv/sqlite";

// File-based SQLite
const keyvSqlite = new KeyvSqlite('sqlite://path/to/database.sqlite');
const keyv = new Keyv(keyvSqlite);

// In-memory SQLite
const keyvMemory = new KeyvSqlite('sqlite://:memory:');
const keyvInMemory = new Keyv(keyvMemory);

// SQLite with options
const sqliteStore = new KeyvSqlite('sqlite://cache.db', {
  busyTimeout: 3000 // Wait up to 3 seconds for locks
});

const keyv = new Keyv(sqliteStore, { 
  namespace: 'file-cache',
  ttl: 86400000 // 24 hours
});

await keyv.set('file:readme.txt', 'File content here');

PostgreSQL Adapter

Enterprise PostgreSQL storage with connection pooling.

// Import pattern for PostgreSQL adapter
import KeyvPostgres from "@keyv/postgres";

const keyvPostgres = new KeyvPostgres(uri: string);
const keyv = new Keyv(keyvPostgres);

Usage Examples:

import Keyv from "keyv";
import KeyvPostgres from "@keyv/postgres";

// Basic PostgreSQL connection
const keyvPg = new KeyvPostgres('postgresql://user:pass@localhost:5432/mydb');
const keyv = new Keyv(keyvPg);

// PostgreSQL with SSL
const keyvSecure = new KeyvPostgres('postgresql://user:pass@localhost:5432/mydb?sslmode=require');

const keyv = new Keyv(keyvSecure, {
  namespace: 'production-cache',
  ttl: 3600000 // 1 hour
});

await keyv.set('config:app', { version: '1.0.0', features: ['auth', 'cache'] });

MySQL Adapter

MySQL/MariaDB storage support.

// Import pattern for MySQL adapter
import KeyvMysql from "@keyv/mysql";

const keyvMysql = new KeyvMysql(uri: string);
const keyv = new Keyv(keyvMysql);

Usage Examples:

import Keyv from "keyv";
import KeyvMysql from "@keyv/mysql";

// Basic MySQL connection
const keyvMysql = new KeyvMysql('mysql://user:pass@localhost:3306/mydb');
const keyv = new Keyv(keyvMysql);

// MySQL with options
const keyv = new Keyv(keyvMysql, {
  namespace: 'session-store',
  ttl: 1800000 // 30 minutes
});

await keyv.set('cart:user123', { items: [1, 2, 3], total: 99.99 });

Custom Storage Adapters

Creating custom storage adapters that implement the KeyvStoreAdapter interface.

// Custom adapter must implement KeyvStoreAdapter interface
class CustomStorageAdapter implements KeyvStoreAdapter {
  opts: any;
  namespace?: string;
  
  async get<Value>(key: string): Promise<StoredData<Value> | undefined> {
    // Implementation
  }
  
  async set(key: string, value: any, ttl?: number): Promise<any> {
    // Implementation  
  }
  
  async delete(key: string): Promise<boolean> {
    // Implementation
  }
  
  async clear(): Promise<void> {
    // Implementation
  }
}

Usage Examples:

import Keyv from "keyv";

// Custom file-based adapter example
class FileStorageAdapter {
  constructor(private filePath: string) {
    this.opts = { filePath };
  }
  
  async get(key: string) {
    // Read from file system
    try {
      const data = await fs.readFile(this.filePath, 'utf8');
      const store = JSON.parse(data);
      return store[key];
    } catch {
      return undefined;
    }
  }
  
  async set(key: string, value: any, ttl?: number) {
    // Write to file system
    try {
      const data = await fs.readFile(this.filePath, 'utf8').catch(() => '{}');
      const store = JSON.parse(data);
      store[key] = { value, expires: ttl ? Date.now() + ttl : undefined };
      await fs.writeFile(this.filePath, JSON.stringify(store));
      return true;
    } catch {
      return false;
    }
  }
  
  async delete(key: string) {
    // Delete from file
    try {
      const data = await fs.readFile(this.filePath, 'utf8');
      const store = JSON.parse(data);
      const existed = key in store;
      delete store[key];
      await fs.writeFile(this.filePath, JSON.stringify(store));
      return existed;
    } catch {
      return false;
    }
  }
  
  async clear() {
    await fs.writeFile(this.filePath, '{}');
  }
}

// Use custom adapter
const customAdapter = new FileStorageAdapter('./cache.json');
const keyv = new Keyv(customAdapter);

await keyv.set('test', 'Custom storage works!');

Third-Party Storage Adapters

Compatible third-party adapters that work with Keyv.

// Third-party adapters follow same pattern
import QuickLRU from "quick-lru";

const lru = new QuickLRU({ maxSize: 1000 });
const keyv = new Keyv(lru); // Any Map-compatible store works

Usage Examples:

import Keyv from "keyv";
import QuickLRU from "quick-lru";

// LRU cache with size limit
const lru = new QuickLRU({ maxSize: 1000 });
const keyv = new Keyv(lru);

await keyv.set('item1', 'data1');
await keyv.set('item2', 'data2');
// When maxSize reached, oldest items are evicted

// File system adapter
import KeyvFile from "keyv-file";
const fileStore = new KeyvFile('./cache-dir');
const keyvFile = new Keyv(fileStore);

// Null adapter (no storage, useful for testing)
import KeyvNull from "keyv-null";
const nullStore = new KeyvNull();
const keyvNull = new Keyv(nullStore); // All operations succeed but nothing is stored

Storage Adapter Properties

Runtime Store Management

class Keyv {
  /** Get current storage adapter */
  get store(): KeyvStoreAdapter | Map<any, any> | any;
  
  /** Set new storage adapter (validates and configures) */
  set store(store: KeyvStoreAdapter | Map<any, any> | any);
}

Usage Examples:

const keyv = new Keyv(); // Starts with Map storage

// Check current store
console.log(keyv.store instanceof Map); // true

// Switch to Redis
import KeyvRedis from "@keyv/redis";
const redisStore = new KeyvRedis('redis://localhost:6379');
keyv.store = redisStore; // Automatically configures events, namespace, etc.

// Store validation
try {
  keyv.store = {}; // Invalid store
} catch (error) {
  console.error('Invalid storage adapter'); // Throws error
}

docs

batch-operations.md

configuration.md

core-storage.md

events-hooks.md

index.md

raw-data-access.md

storage-adapters.md

tile.json