
Research
Shai-Hulud Descends to Hades: Miasma Worm Campaign Spreads with New PyPI Wave
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.
keyv-cache-proxy
Advanced tools
A transparent caching proxy for any object using Keyv - automatically cache method calls with TTL support
A transparent caching proxy for any object using Keyv - automatically cache method calls with TTL support.
bun add keyv-cache-proxy keyv
Or with npm/yarn/pnpm:
npm install keyv-cache-proxy keyv
import { KeyvCacheProxy } from 'keyv-cache-proxy';
import Keyv from 'keyv';
// Create a Keyv instance with any storage backend
const store = new Keyv();
// Wrap any object with caching
const cachedAPI = KeyvCacheProxy({
store,
})(yourAPIClient);
// All method calls are now automatically cached!
const result = await cachedAPI.fetchData('param1', 'param2');
import { KeyvCacheProxy } from 'keyv-cache-proxy';
import Keyv from 'keyv';
const myObject = {
expensiveOperation(a: number, b: number) {
console.log('Computing...');
return a + b;
}
};
const cached = KeyvCacheProxy({
store: new Keyv(),
ttl: 60000, // 1 minute
})(myObject);
// First call: executes the method
await cached.expensiveOperation(1, 2); // Logs: "Computing..."
// Second call: returns cached result
await cached.expensiveOperation(1, 2); // No log, returns from cache
import { Octokit } from 'octokit';
import { KeyvCacheProxy } from 'keyv-cache-proxy';
import Keyv from 'keyv';
import KeyvNedbStore from 'keyv-nedb-store';
// Use persistent storage
const kv = new Keyv(new KeyvNedbStore('.cache/github.yaml'));
const gh = KeyvCacheProxy({
store: kv,
ttl: 600000, // 10 minutes
prefix: 'github.',
onCache: (key, value) => console.log('Cache hit:', key),
onFetch: (key, value) => console.log('Fetched fresh:', key),
})(new Octokit().rest);
// API calls are now cached
const repo = await gh.repos.get({ owner: 'snomiao', repo: 'keyv-cache-proxy' });
import { Client } from '@notionhq/client';
import { KeyvCacheProxy } from 'keyv-cache-proxy';
import Keyv from 'keyv';
const notion = new Client({ auth: process.env.NOTION_API_KEY });
// Cache Notion API calls to reduce rate limiting
const cachedNotion = KeyvCacheProxy({
store: new Keyv(),
ttl: 300000, // 5 minutes
prefix: 'notion.',
})(notion);
// These calls will be cached
const database = await cachedNotion.databases.query({
database_id: 'your-database-id',
});
const page = await cachedNotion.pages.retrieve({
page_id: 'your-page-id',
});
import { WebClient } from '@slack/web-api';
import { KeyvCacheProxy } from 'keyv-cache-proxy';
import Keyv from 'keyv';
const slack = new WebClient(process.env.SLACK_TOKEN);
// Cache Slack API calls
const cachedSlack = KeyvCacheProxy({
store: new Keyv(),
ttl: 600000, // 10 minutes
prefix: 'slack.',
})(slack);
// Cached API calls
const channels = await cachedSlack.conversations.list();
const userInfo = await cachedSlack.users.info({ user: 'U123456' });
const messages = await cachedSlack.conversations.history({
channel: 'C123456',
});
import { KeyvCacheProxy } from 'keyv-cache-proxy';
import Keyv from 'keyv';
import KeyvRedis from '@keyv/redis';
import KeyvMongo from '@keyv/mongo';
// Redis
const redisCache = KeyvCacheProxy({
store: new Keyv(new KeyvRedis('redis://localhost:6379')),
ttl: 3600000,
})(yourObject);
// MongoDB
const mongoCache = KeyvCacheProxy({
store: new Keyv(new KeyvMongo('mongodb://localhost:27017')),
ttl: 3600000,
})(yourObject);
// SQLite (via keyv-sqlite)
const sqliteCache = KeyvCacheProxy({
store: new Keyv('sqlite://cache.db'),
ttl: 3600000,
})(yourObject);
Track cache performance:
let hits = 0;
let fetches = 0;
const cached = KeyvCacheProxy({
store: new Keyv(),
ttl: 60000,
onCache: (key, value) => {
hits++;
console.log(`Cache hit for ${key}. Total hits: ${hits}`);
},
onFetch: (key, value) => {
fetches++;
console.log(`Fetched fresh for ${key}. Total fetches: ${fetches}`);
},
})(myObject);
Modify cached/fetched data:
const cached = KeyvCacheProxy({
store: new Keyv(),
ttl: 60000,
// Add metadata to cached data (called on every invocation)
onCache: (key, value) => {
if (value !== undefined) {
console.log('Returning cached data');
return { ...value, fromCache: true, cachedAt: Date.now() };
}
},
// Transform fetched data before caching
onFetch: (key, value) => {
console.log('Processing fresh data');
return { ...value, fetchedAt: Date.now(), processed: true };
},
})(myObject);
Force cache refresh:
const cached = KeyvCacheProxy({
store: new Keyv(),
ttl: 60000,
onCache: (key, value) => {
// Return null to force refetch even if cached
if (value && isStale(value)) {
return null; // Forces cache miss and refetch
}
return value; // Use cached value
},
})(myObject);
KeyvCacheProxy(options)Creates a cache proxy factory function.
store (required): A Keyv instance for cache storagettl (optional): Time-to-live in milliseconds for cached valuesprefix (optional): Prefix for cache keys (default: "")onCache (optional): Hook called on every invocation (before cache lookup). Receives cached value (or undefined on cache miss). Can modify the cached value or return null to force refetch: (key: string, value: any) => any | null | Promise<any | null>onFetch (optional): Hook called when data is freshly fetched (cache miss). Can modify the value before caching: (key: string, value: any) => any | Promise<any>A function that takes an object and returns a proxied version with automatic caching.
Cache keys are generated based on:
Format: ${prefix}${methodName}:${JSON.stringify(args)}
The proxy preserves TypeScript types and automatically converts all methods to async:
type DeepAsyncMethod<T> = {
[K in keyof T]: T[K] extends (...args: infer A) => infer R
? (...args: A) => Promise<Awaited<R>>
: T[K] extends object
? DeepAsyncMethod<T[K]>
: T[K];
};
The KeyvCacheProxy uses JavaScript Proxy to intercept method calls:
Nested objects are automatically wrapped with the same caching behavior.
You can use any Keyv-compatible storage adapter:
new Keyv()MIT © snomiao
Contributions are welcome! Please feel free to submit a Pull Request.
FAQs
A transparent caching proxy for any object using Keyv - automatically cache method calls with TTL support
The npm package keyv-cache-proxy receives a total of 841 weekly downloads. As such, keyv-cache-proxy popularity was classified as not popular.
We found that keyv-cache-proxy demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.

Security News
RubyGems and Bundler 4.0.13 introduced an opt-in cooldown feature that delays newly published gems during dependency resolution.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.