Wrap native HTTP requests with RFC compliant cache support
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Configuration and setup of cache storage adapters using Keyv. Cacheable Request supports various storage backends including in-memory, Redis, SQLite, MongoDB, and custom adapters for flexible cache persistence.
Built-in memory storage that requires no additional configuration.
/**
* Creates cacheable request with default in-memory storage
* Uses Keyv with namespace 'cacheable-request'
*/
class CacheableRequest {
cache: Keyv;
constructor(cacheRequest: RequestFn);
}Usage Examples:
import CacheableRequest from "cacheable-request";
import { request } from "node:http";
// Default in-memory cache
const cacheableRequest = new CacheableRequest(request);
// Access the cache instance
console.log(cacheableRequest.cache); // Keyv instance with Map storeIntegration with official Keyv storage adapters for persistent caching.
/**
* Creates cacheable request with custom Keyv storage adapter
* @param cacheRequest - HTTP request function
* @param cacheAdapter - Keyv instance or compatible storage adapter
*/
constructor(cacheRequest: RequestFn, cacheAdapter: Keyv | any);Usage Examples:
import CacheableRequest from "cacheable-request";
import { Keyv } from "keyv";
import KeyvRedis from "@keyv/redis";
import KeyvSQLite from "@keyv/sqlite";
// Redis storage
const redisStore = new KeyvRedis("redis://localhost:6379");
const cacheableRedis = new CacheableRequest(request, redisStore);
// SQLite storage
const sqliteStore = new KeyvSQLite("cache.sqlite");
const cacheableSQLite = new CacheableRequest(request, sqliteStore);
// Pre-configured Keyv instance
const keyv = new Keyv({
store: new KeyvRedis("redis://localhost:6379"),
namespace: "my-app-cache",
ttl: 3600000 // 1 hour default TTL
});
const cacheableCustom = new CacheableRequest(request, keyv);Supported storage adapters and their use cases.
interface StorageOptions {
/** In-memory storage (default) */
memory: Map;
/** Redis for distributed caching */
redis: string | KeyvRedis;
/** SQLite for persistent local caching */
sqlite: string | KeyvSQLite;
/** MongoDB for document-based caching */
mongodb: string | KeyvMongoDB;
/** PostgreSQL for relational caching */
postgresql: string | KeyvPostgreSQL;
/** MySQL for relational caching */
mysql: string | KeyvMySQL;
/** Memcached for distributed memory caching */
memcached: string | KeyvMemcached;
}Usage Examples:
// Redis with connection string
const redisCache = new CacheableRequest(
request,
new KeyvRedis("redis://user:pass@localhost:6379/0")
);
// SQLite with file path
const sqliteCache = new CacheableRequest(
request,
new KeyvSQLite("./cache/requests.sqlite")
);
// MongoDB with connection string
import KeyvMongoDB from "@keyv/mongo";
const mongoCache = new CacheableRequest(
request,
new KeyvMongoDB("mongodb://localhost:27017/cache")
);Using custom storage solutions that implement the Map interface.
/**
* Custom storage adapter requirements
* Must implement basic Map interface methods
*/
interface CustomStorageAdapter {
get(key: string): Promise<any> | any;
set(key: string, value: any, ttl?: number): Promise<boolean> | boolean;
delete(key: string): Promise<boolean> | boolean;
clear(): Promise<void> | void;
}Usage Examples:
// Custom LRU cache adapter
import QuickLRU from "quick-lru";
const lruCache = new QuickLRU({ maxSize: 1000 });
const cacheableLRU = new CacheableRequest(request, lruCache);
// Custom adapter implementation
class CustomAdapter {
private store = new Map();
async get(key) {
return this.store.get(key);
}
async set(key, value, ttl) {
this.store.set(key, value);
if (ttl) {
setTimeout(() => this.store.delete(key), ttl);
}
return true;
}
async delete(key) {
return this.store.delete(key);
}
async clear() {
this.store.clear();
}
}
const customCache = new CacheableRequest(request, new CustomAdapter());Advanced configuration options for storage adapters.
interface KeyvOptions {
/** Storage adapter instance */
store?: any;
/** Namespace for cache keys */
namespace?: string;
/** Default TTL in milliseconds */
ttl?: number;
/** Custom serialization */
serialize?: (data: any) => string;
deserialize?: (data: string) => any;
/** Adapter-specific options */
[key: string]: any;
}Usage Examples:
import { Keyv } from "keyv";
import KeyvRedis from "@keyv/redis";
// Advanced Keyv configuration
const keyv = new Keyv({
store: new KeyvRedis("redis://localhost:6379"),
namespace: "cacheable-request-v2",
ttl: 1800000, // 30 minutes default
serialize: JSON.stringify,
deserialize: JSON.parse
});
const cacheableRequest = new CacheableRequest(request, keyv);
// Multiple namespaces for different endpoints
const apiCache = new Keyv({
store: new KeyvRedis("redis://localhost:6379"),
namespace: "api-cache",
ttl: 300000 // 5 minutes
});
const staticCache = new Keyv({
store: new KeyvRedis("redis://localhost:6379"),
namespace: "static-cache",
ttl: 3600000 // 1 hour
});
const apiRequests = new CacheableRequest(request, apiCache);
const staticRequests = new CacheableRequest(request, staticCache);Direct access to the underlying cache for management operations.
interface CacheableRequest {
/** Direct access to Keyv cache instance */
cache: Keyv;
}
interface CacheManagement {
/** Get cached value directly */
get(key: string): Promise<any>;
/** Set cached value directly */
set(key: string, value: any, ttl?: number): Promise<boolean>;
/** Delete cached value */
delete(key: string): Promise<boolean>;
/** Clear entire cache */
clear(): Promise<void>;
}Usage Examples:
const cacheableRequest = new CacheableRequest(request, redisStore);
// Direct cache operations
await cacheableRequest.cache.set("custom-key", { data: "value" }, 60000);
const cached = await cacheableRequest.cache.get("custom-key");
await cacheableRequest.cache.delete("custom-key");
// Cache statistics (if supported by adapter)
if (cacheableRequest.cache.store.stats) {
console.log("Cache stats:", cacheableRequest.cache.store.stats());
}
// Clear entire cache
await cacheableRequest.cache.clear();Handling storage-related errors and failover strategies.
interface StorageErrorHandling {
/** Enable automatic failover on storage errors */
automaticFailover: boolean;
/** Storage error event handling */
onStorageError: (error: Error) => void;
}Usage Examples:
import { Keyv } from "keyv";
import KeyvRedis from "@keyv/redis";
// Setup with error handling
const keyv = new Keyv({
store: new KeyvRedis("redis://localhost:6379")
});
// Listen for storage errors
keyv.on("error", (error) => {
console.error("Cache storage error:", error);
// Handle Redis connection issues, etc.
});
const cacheableRequest = new CacheableRequest(request, keyv);
// Use automatic failover for requests
const req = cacheableRequest({
hostname: "api.example.com",
path: "/data",
automaticFailover: true // Falls back to network on cache errors
});interface Keyv {
get(key: string): Promise<any>;
set(key: string, value: any, ttl?: number): Promise<boolean>;
delete(key: string): Promise<boolean>;
clear(): Promise<void>;
on(event: string, listener: Function): this;
}
interface StorageAdapter {
get(key: string): any;
set(key: string, value: any, ttl?: number): any;
delete(key: string): boolean;
clear?(): void;
}Install with Tessl CLI
npx tessl i tessl/npm-cacheable-request