Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

keyv-cache-proxy

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

keyv-cache-proxy - npm Package Compare versions

Comparing version
0.0.12
to
0.1.0
+2
dist/index.test.d.ts
export {};
//# sourceMappingURL=index.test.d.ts.map
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
import { beforeEach, describe, expect, test } from "bun:test";
import Keyv from "keyv";
import KeyvCacheProxy, { globalThisCached } from "./index";
describe("KeyvCacheProxy", () => {
let store;
beforeEach(() => {
store = new Keyv();
});
describe("Basic Caching", () => {
test("should cache method results", async () => {
let callCount = 0;
const obj = {
getValue: (x) => {
callCount++;
return x * 2;
},
};
const cached = KeyvCacheProxy({ store })(obj);
// First call - should execute method
const result1 = await cached.getValue(5);
expect(result1).toBe(10);
expect(callCount).toBe(1);
// Second call - should return cached result
const result2 = await cached.getValue(5);
expect(result2).toBe(10);
expect(callCount).toBe(1); // Should not increment
});
test("should cache different arguments separately", async () => {
let callCount = 0;
const obj = {
add: (a, b) => {
callCount++;
return a + b;
},
};
const cached = KeyvCacheProxy({ store })(obj);
await cached.add(1, 2);
await cached.add(3, 4);
expect(callCount).toBe(2);
await cached.add(1, 2); // Cached
expect(callCount).toBe(2);
await cached.add(3, 4); // Cached
expect(callCount).toBe(2);
});
test("should handle async methods", async () => {
const obj = {
async fetchData(id) {
await new Promise((resolve) => setTimeout(resolve, 10));
return { id, data: "test" };
},
};
const cached = KeyvCacheProxy({ store })(obj);
const result = await cached.fetchData(1);
expect(result).toEqual({ id: 1, data: "test" });
});
test("should convert sync methods to async", async () => {
const obj = {
syncMethod: (x) => x * 2,
};
const cached = KeyvCacheProxy({ store })(obj);
const result = cached.syncMethod(5);
expect(result).toBeInstanceOf(Promise);
expect(await result).toBe(10);
});
});
describe("Hooks - onCache", () => {
test("should call onCache hook on every invocation", async () => {
const onCacheCalls = [];
const obj = {
getValue: (x) => x * 2,
};
const cached = KeyvCacheProxy({
store,
onCache: (key, value) => {
onCacheCalls.push({ key, value });
},
})(obj);
await cached.getValue(5); // First call - cache miss, onCache called with undefined
expect(onCacheCalls.length).toBe(1);
expect(onCacheCalls[0]?.value).toBe(undefined);
await cached.getValue(5); // Second call - cache hit, onCache called with cached value
expect(onCacheCalls.length).toBe(2);
expect(onCacheCalls[1]?.value).toBe(10);
expect(onCacheCalls[1]?.key).toContain("getValue");
});
test("should allow onCache to modify cached value", async () => {
const obj = {
getData: () => ({ value: 100 }),
};
const cached = KeyvCacheProxy({
store,
onCache: (_key, value) => {
// Only modify if value exists (cache hit)
if (value !== undefined) {
return { ...value, fromCache: true };
}
},
})(obj);
const result1 = await cached.getData();
expect(result1).toEqual({ value: 100 });
const result2 = await cached.getData();
expect(result2).toMatchObject({ value: 100, fromCache: true });
});
test("should return original value if onCache returns undefined", async () => {
const obj = {
getValue: () => 42,
};
const cached = KeyvCacheProxy({
store,
onCache: (_key, _value) => {
// Return undefined to keep original
return undefined;
},
})(obj);
await cached.getValue(); // Prime cache
const result = await cached.getValue();
expect(result).toBe(42);
});
test("should support async onCache hook", async () => {
const obj = {
getValue: () => 100,
};
const cached = KeyvCacheProxy({
store,
onCache: async (_key, value) => {
await new Promise((resolve) => setTimeout(resolve, 10));
// Only modify on cache hit
if (value !== undefined) {
return value * 2;
}
},
})(obj);
await cached.getValue(); // Prime cache
const result = await cached.getValue();
expect(result).toBe(200);
});
test("should force cache miss when onCache returns null", async () => {
let fetchCount = 0;
const obj = {
getValue: () => {
fetchCount++;
return fetchCount;
},
};
const cached = KeyvCacheProxy({
store,
onCache: (_key, value) => {
// Return null to force refetch even if cached
if (value !== undefined) {
return null; // Force cache miss
}
},
})(obj);
const result1 = await cached.getValue();
expect(result1).toBe(1);
const result2 = await cached.getValue(); // Should refetch due to null
expect(result2).toBe(2);
expect(fetchCount).toBe(2);
});
});
describe("Hooks - onFetch", () => {
test("should call onFetch hook on cache miss", async () => {
const onFetchCalls = [];
const obj = {
getValue: (x) => x * 2,
};
const cached = KeyvCacheProxy({
store,
onFetch: (key, value) => {
onFetchCalls.push({ key, value });
},
})(obj);
await cached.getValue(5);
expect(onFetchCalls.length).toBe(1);
expect(onFetchCalls[0]?.value).toBe(10);
expect(onFetchCalls[0]?.key).toContain("getValue");
await cached.getValue(5); // Cache hit - no fetch
expect(onFetchCalls.length).toBe(1);
});
test("should allow onFetch to modify value before caching", async () => {
const obj = {
getData: () => ({ value: 100 }),
};
const cached = KeyvCacheProxy({
store,
onFetch: (_key, value) => {
return { ...value, fetchedAt: Date.now() };
},
})(obj);
const result1 = await cached.getData();
expect(result1).toHaveProperty("fetchedAt");
expect(result1.value).toBe(100);
// Should return modified cached value
const result2 = await cached.getData();
expect(result2).toEqual(result1);
});
test("should support async onFetch hook", async () => {
const obj = {
getValue: () => 50,
};
const cached = KeyvCacheProxy({
store,
onFetch: async (_key, value) => {
await new Promise((resolve) => setTimeout(resolve, 10));
return value * 3;
},
})(obj);
const result = await cached.getValue();
expect(result).toBe(150);
});
test("should cache modified value from onFetch", async () => {
let callCount = 0;
const obj = {
getValue: () => {
callCount++;
return 10;
},
};
const cached = KeyvCacheProxy({
store,
onFetch: (_key, value) => value * 10,
})(obj);
const result1 = await cached.getValue();
expect(result1).toBe(100);
const result2 = await cached.getValue();
expect(result2).toBe(100);
expect(callCount).toBe(1); // Only called once
});
});
describe("Hooks - Combined", () => {
test("should call both hooks appropriately", async () => {
const hookCalls = [];
const obj = {
getValue: (x) => x,
};
const cached = KeyvCacheProxy({
store,
onCache: (_key, value) => {
hookCalls.push("cache");
return value;
},
onFetch: (_key, value) => {
hookCalls.push("fetch");
return value;
},
})(obj);
await cached.getValue(1); // cache miss: onCache(undefined), then onFetch
expect(hookCalls).toEqual(["cache", "fetch"]);
await cached.getValue(1); // cache hit: onCache(value)
expect(hookCalls).toEqual(["cache", "fetch", "cache"]);
await cached.getValue(2); // cache miss: onCache(undefined), then onFetch
expect(hookCalls).toEqual(["cache", "fetch", "cache", "cache", "fetch"]);
});
test("should apply both modifications correctly", async () => {
const obj = {
getValue: () => ({ base: 1 }),
};
const cached = KeyvCacheProxy({
store,
onCache: (_key, value) => {
// Only modify on cache hit
if (value !== undefined) {
return { ...value, fromCache: true };
}
},
onFetch: (_key, value) => ({ ...value, fromFetch: true }),
})(obj);
const result1 = await cached.getValue();
expect(result1).toMatchObject({ base: 1, fromFetch: true });
const result2 = await cached.getValue();
expect(result2).toMatchObject({
base: 1,
fromFetch: true,
fromCache: true,
});
});
});
describe("Nested Objects", () => {
test("should handle nested object methods", async () => {
let callCount = 0;
const obj = {
api: {
users: {
get: (id) => {
callCount++;
return { id, name: `User ${id}` };
},
},
},
};
const cached = KeyvCacheProxy({ store })(obj);
await cached.api.users.get(1);
await cached.api.users.get(1);
expect(callCount).toBe(1);
});
test("should propagate hooks to nested objects", async () => {
const hookCalls = [];
const obj = {
level1: {
level2: {
method: () => "result",
},
},
};
const cached = KeyvCacheProxy({
store,
onFetch: (key) => {
hookCalls.push(key);
},
})(obj);
await cached.level1.level2.method();
expect(hookCalls.length).toBe(1);
expect(hookCalls[0]).toContain("level1.level2.method");
});
test("should cache nested methods independently", async () => {
const calls = { method1: 0, method2: 0 };
const obj = {
nested: {
method1: () => {
calls.method1++;
return "result1";
},
method2: () => {
calls.method2++;
return "result2";
},
},
};
const cached = KeyvCacheProxy({ store })(obj);
await cached.nested.method1();
await cached.nested.method1();
await cached.nested.method2();
await cached.nested.method2();
expect(calls.method1).toBe(1);
expect(calls.method2).toBe(1);
});
});
describe("Prefix", () => {
test("should add prefix to cache keys", async () => {
const keys = [];
const obj = {
getData: () => "data",
};
const cached = KeyvCacheProxy({
store,
prefix: "myapp:",
onFetch: (key) => {
keys.push(key);
},
})(obj);
await cached.getData();
expect(keys[0]).toStartWith("myapp:");
});
test("should prefix nested object keys correctly", async () => {
const keys = [];
const obj = {
api: {
getData: () => "data",
},
};
const cached = KeyvCacheProxy({
store,
prefix: "app:",
onFetch: (key) => {
keys.push(key);
},
})(obj);
await cached.api.getData();
expect(keys[0]).toBe("app:api.getData:[]");
});
});
describe("TTL", () => {
test("should expire cache after TTL", async () => {
let callCount = 0;
const obj = {
getValue: () => {
callCount++;
return callCount;
},
};
const cached = KeyvCacheProxy({
store,
ttl: 100, // 100ms
})(obj);
const result1 = await cached.getValue();
expect(result1).toBe(1);
const result2 = await cached.getValue();
expect(result2).toBe(1); // Cached
// Wait for TTL to expire
await new Promise((resolve) => setTimeout(resolve, 150));
const result3 = await cached.getValue();
expect(result3).toBe(2); // Fresh call
});
});
describe("Non-function Properties", () => {
test("should return non-function properties as-is", async () => {
const obj = {
value: 42,
text: "hello",
method: () => "result",
};
const cached = KeyvCacheProxy({ store })(obj);
expect(cached.value).toBe(42);
expect(cached.text).toBe("hello");
});
test("should handle null and undefined properties", async () => {
const obj = {
nullValue: null,
undefinedValue: undefined,
method: () => "result",
};
const cached = KeyvCacheProxy({ store })(obj);
expect(cached.nullValue).toBe(null);
expect(cached.undefinedValue).toBe(undefined);
});
});
describe("Edge Cases", () => {
test("should handle methods with no arguments", async () => {
let callCount = 0;
const obj = {
getValue: () => {
callCount++;
return "value";
},
};
const cached = KeyvCacheProxy({ store })(obj);
await cached.getValue();
await cached.getValue();
expect(callCount).toBe(1);
});
test("should handle methods with complex object arguments", async () => {
let callCount = 0;
const obj = {
process: (data) => {
callCount++;
return data.nested.value;
},
};
const cached = KeyvCacheProxy({ store })(obj);
const arg = { id: 1, nested: { value: "test" } };
await cached.process(arg);
await cached.process(arg);
expect(callCount).toBe(1);
});
test("should handle undefined cache values", async () => {
const obj = {
getValue: () => undefined,
};
const cached = KeyvCacheProxy({ store })(obj);
const result = await cached.getValue();
expect(result).toBe(undefined);
});
test("should handle null return values", async () => {
let _callCount = 0;
const obj = {
getValue: () => {
_callCount++;
return null;
},
};
const cached = KeyvCacheProxy({ store })(obj);
await cached.getValue();
await cached.getValue();
// Note: null values won't be cached because store.get returns undefined for missing keys
// This is expected Keyv behavior
});
test("should handle errors in methods", async () => {
const obj = {
throwError: () => {
throw new Error("Test error");
},
};
const cached = KeyvCacheProxy({ store })(obj);
await expect(cached.throwError()).rejects.toThrow("Test error");
});
test("should handle errors in hooks", async () => {
const obj = {
getValue: () => 42,
};
const cached = KeyvCacheProxy({
store,
onFetch: () => {
throw new Error("Hook error");
},
})(obj);
await expect(cached.getValue()).rejects.toThrow("Hook error");
});
test("should work with Map as store", async () => {
let callCount = 0;
const mapStore = new Map();
const obj = {
getValue: (x) => {
callCount++;
return x * 2;
},
};
const cached = KeyvCacheProxy({ store: mapStore })(obj);
await cached.getValue(5);
await cached.getValue(5);
expect(callCount).toBe(1);
});
});
describe("Type Preservation", () => {
test("should preserve method signatures", async () => {
const obj = {
add: (a, b) => a + b,
concat: (a, b) => a + b,
};
const cached = KeyvCacheProxy({ store })(obj);
const sum = await cached.add(1, 2);
const text = await cached.concat("hello", "world");
expect(sum).toBe(3);
expect(text).toBe("helloworld");
});
});
});
describe("globalThisCached", () => {
test("should cache computed values", () => {
let callCount = 0;
const compute = () => {
callCount++;
return { value: 42 };
};
const uniqueKey = `test-key-${Math.random()}`;
const result1 = globalThisCached(uniqueKey, compute);
const result2 = globalThisCached(uniqueKey, compute);
expect(result1).toBe(result2);
expect(callCount).toBe(1);
});
test("should support different cache keys", () => {
const key1 = `key1-${Math.random()}`;
const key2 = `key2-${Math.random()}`;
const result1 = globalThisCached(key1, () => ({ id: 1 }));
const result2 = globalThisCached(key2, () => ({ id: 2 }));
expect(result1).not.toBe(result2);
expect(result1.id).toBe(1);
expect(result2.id).toBe(2);
});
test("should work with sync computations", () => {
const uniqueKey = `sync-${Math.random()}`;
const value = globalThisCached(uniqueKey, () => "test-value");
expect(value).toBe("test-value");
});
test("should handle primitive values", () => {
const num = globalThisCached(`number-${Math.random()}`, () => 123);
const str = globalThisCached(`string-${Math.random()}`, () => "hello");
const bool = globalThisCached(`boolean-${Math.random()}`, () => true);
expect(num).toBe(123);
expect(str).toBe("hello");
expect(bool).toBe(true);
});
});
//# sourceMappingURL=index.test.js.map
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
+10
-14

@@ -8,22 +8,18 @@ #!/usr/bin/env bun --watch

const gh = KeyvCacheProxy({
store: kv,
ttl: 600e3,
prefix: `github.`,
onHit: (key) => console.log(`Cache hit: ${key}`),
onMiss: (key) => console.log(`Cache miss: ${key}`),
store: kv,
ttl: 600e3,
prefix: `github.`,
onHit: (key) => console.log(`Cache hit: ${key}`),
onMiss: (key) => console.log(`Cache miss: ${key}`),
})(
new Octokit({
// auth
}).rest,
new Octokit({
// auth
}).rest,
);
console.log(
(await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url,
);
console.log((await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url);
// prints: cache miss: github.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
// returns fresh result
console.log(
(await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url,
);
console.log((await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url);
// prints: cache hit: github.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
// returns cached result
//# sourceMappingURL=github.js.map

@@ -10,4 +10,4 @@ import type Keyv from "keyv";

* @param ttl - Time-to-live for cached entries in milliseconds.
* @param onMiss - Optional callback function invoked on cache misses.
* @param onHit - Optional callback function invoked on cache hits.
* @param onCache - Optional hook called when data is loaded from cache. Receives key and cached value, can return modified value.
* @param onFetch - Optional hook called when data is freshly fetched. Receives key and fetched value, can return modified value before caching.
* @param prefix - Optional prefix to prepend to cache keys.

@@ -19,3 +19,3 @@ *

*
* for example, github api caching
* Basic usage with GitHub API caching
* ```ts

@@ -28,24 +28,58 @@ * import { Keyv } from "keyv";

* const gh = KeyvCacheProxy({
* store: kv,
* ttl: 600e3,
* prefix: `api.`,
* // hooks
* onHit: (key) => console.log(`Cache hit: ${key}`),
* onMiss: (key) => console.log(`Cache miss: ${key}`),
* store: kv,
* ttl: 600e3,
* prefix: `api.`,
* // hooks for logging
* onCache: (key, value) => value ? console.log(`Cache hit: ${key}`) : console.log(`Cache miss: ${key}`),
* onFetch: (key, value) => console.log(`Fetched fresh: ${key}`),
* })(new Octokit());
*r
* // first call - cache miss, fetches fresh data
* await gh.repos.get({ owner: "snomiao", repo: "snomiao" });
* // prints: Cache miss: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* // prints: Fetched fresh: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
*
* // first call, cache miss
* console.log(
* (await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url,
* );
* // prints: cache miss: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* // returns fresh result
* // second call - cache hit, returns cached data
* await gh.repos.get({ owner: "snomiao", repo: "snomiao" });
* // prints: Cache hit: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* ```
*
* // second call, cache hit
* console.log(
* (await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url,
* );
* // prints: cache hit: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* // returns cached result
* @example
*
* Advanced usage - modifying cached/fetched data
* ```ts
* const gh = KeyvCacheProxy({
* store: kv,
* ttl: 600e3,
* // Modify cached data before returning (called on every invocation)
* onCache: (key, value) => {
* if (value !== undefined) {
* console.log(`Using cached data for ${key}`);
* return { ...value, fromCache: true };
* }
* },
* // Transform fetched data before caching
* onFetch: (key, value) => {
* console.log(`Caching fresh data for ${key}`);
* return { ...value, fetchedAt: Date.now() };
* },
* })(new Octokit());
* ```
*
* @example
*
* Force cache refresh by returning null from onCache
* ```ts
* const gh = KeyvCacheProxy({
* store: kv,
* ttl: 600e3,
* onCache: (key, value) => {
* // Return null to force refetch even if cached
* if (shouldRefresh(value)) {
* return null; // Forces cache miss
* }
* return value; // Use cached value
* },
* })(new Octokit());
* ```
*/

@@ -55,4 +89,4 @@ export default function KeyvCacheProxy(options: {

ttl?: number;
onMiss?: (key: string) => void;
onHit?: (key: string) => void;
onCache?: (key: string, value: any) => Promise<any> | any;
onFetch?: (key: string, value: any) => Promise<any> | any;
prefix?: string;

@@ -59,0 +93,0 @@ hot?: boolean;

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,IAAI,GAAG,gBAAgB,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACd,IAGQ,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC,KAAG,eAAe,CAAC,CAAC,CAAC,CAmCrD;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;KAC/B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,GACvD,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GACnC,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAClB,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACrB,CAAC,CAAC,CAAC,CAAC;CACR,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAcrE"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,EAAE;IAC9C,KAAK,EAAE,IAAI,GAAG,gBAAgB,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAC1D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,IAGS,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC,KAAG,eAAe,CAAC,CAAC,CAAC,CAuDtD;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;KAC9B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,GACtD,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GACnC,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GACjB,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACrB,CAAC,CAAC,CAAC,CAAC;CACX,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAcrE"}

@@ -8,4 +8,4 @@ /**

* @param ttl - Time-to-live for cached entries in milliseconds.
* @param onMiss - Optional callback function invoked on cache misses.
* @param onHit - Optional callback function invoked on cache hits.
* @param onCache - Optional hook called when data is loaded from cache. Receives key and cached value, can return modified value.
* @param onFetch - Optional hook called when data is freshly fetched. Receives key and fetched value, can return modified value before caching.
* @param prefix - Optional prefix to prepend to cache keys.

@@ -17,3 +17,3 @@ *

*
* for example, github api caching
* Basic usage with GitHub API caching
* ```ts

@@ -26,27 +26,61 @@ * import { Keyv } from "keyv";

* const gh = KeyvCacheProxy({
* store: kv,
* ttl: 600e3,
* prefix: `api.`,
* // hooks
* onHit: (key) => console.log(`Cache hit: ${key}`),
* onMiss: (key) => console.log(`Cache miss: ${key}`),
* store: kv,
* ttl: 600e3,
* prefix: `api.`,
* // hooks for logging
* onCache: (key, value) => value ? console.log(`Cache hit: ${key}`) : console.log(`Cache miss: ${key}`),
* onFetch: (key, value) => console.log(`Fetched fresh: ${key}`),
* })(new Octokit());
*r
* // first call - cache miss, fetches fresh data
* await gh.repos.get({ owner: "snomiao", repo: "snomiao" });
* // prints: Cache miss: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* // prints: Fetched fresh: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
*
* // first call, cache miss
* console.log(
* (await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url,
* );
* // prints: cache miss: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* // returns fresh result
* // second call - cache hit, returns cached data
* await gh.repos.get({ owner: "snomiao", repo: "snomiao" });
* // prints: Cache hit: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* ```
*
* // second call, cache hit
* console.log(
* (await gh.repos.get({ owner: "snomiao", repo: "snomiao" })).data.html_url,
* );
* // prints: cache hit: api.repos.get:[{"owner":"snomiao","repo":"snomiao"}]
* // returns cached result
* @example
*
* Advanced usage - modifying cached/fetched data
* ```ts
* const gh = KeyvCacheProxy({
* store: kv,
* ttl: 600e3,
* // Modify cached data before returning (called on every invocation)
* onCache: (key, value) => {
* if (value !== undefined) {
* console.log(`Using cached data for ${key}`);
* return { ...value, fromCache: true };
* }
* },
* // Transform fetched data before caching
* onFetch: (key, value) => {
* console.log(`Caching fresh data for ${key}`);
* return { ...value, fetchedAt: Date.now() };
* },
* })(new Octokit());
* ```
*
* @example
*
* Force cache refresh by returning null from onCache
* ```ts
* const gh = KeyvCacheProxy({
* store: kv,
* ttl: 600e3,
* onCache: (key, value) => {
* // Return null to force refetch even if cached
* if (shouldRefresh(value)) {
* return null; // Forces cache miss
* }
* return value; // Use cached value
* },
* })(new Octokit());
* ```
*/
export default function KeyvCacheProxy(options) {
const { store, ttl, onMiss, onHit, prefix = "" } = options;
const { store, ttl, onCache, onFetch, prefix = "" } = options;
return (obj) => new Proxy(obj, {

@@ -60,9 +94,27 @@ get(target, prop, receiver) {

const key = `${prefix}${String(prop)}:${JSON.stringify(args)}`;
const cached = await store.get(key);
// Check cache
let cached = await store.get(key);
if (onCache) {
const modified = await onCache(key, cached);
if (modified === null) {
cached = undefined; // treat null as cache miss
}
else if (modified !== undefined) {
return modified; // return modified cached value
} // else return original cached value
}
if (cached !== undefined) {
onHit?.(key);
// onCache hook - can modify cached value before returning
return cached;
}
onMiss?.(key);
const result = await method(...args);
// Fetch fresh data
let result = await method(...args); // call original method
// onFetch hook - can modify result before caching
if (onFetch) {
// call onFetch hook, can modify result before caching
const modified = await onFetch(key, result);
if (modified !== undefined) {
result = modified;
}
}
await store.set(key, result, ttl);

@@ -77,4 +129,4 @@ return result;

ttl,
onMiss,
onHit,
onCache,
onFetch,
prefix: `${prefix}${String(prop)}.`,

@@ -81,0 +133,0 @@ })(val);

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAOtC;IACA,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAE3D,OAAO,CAAmB,GAAM,EAAsB,EAAE,CACvD,IAAI,KAAK,CAAC,GAAG,EAAE;QACd,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ;YACzB,wCAAwC;YACxC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAe,CAAC,CAAC;YACpC,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC7B,OAAO,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;oBAC/B,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;wBAC1B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;wBACb,OAAO,MAAM,CAAC;oBACf,CAAC;oBACD,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;oBACd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;oBAErC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;oBAClC,OAAO,MAAM,CAAC;gBACf,CAAC,CAAC;YACH,CAAC;YACD,gCAAgC;YAChC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC7C,OAAO,cAAc,CAAC;oBACrB,KAAK;oBACL,GAAG;oBACH,MAAM;oBACN,KAAK;oBACL,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG;iBACnC,CAAC,CAAC,GAAG,CAAC,CAAC;YACT,CAAC;YACD,oDAAoD;YACpD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;KACD,CAAuB,CAAC;AAC3B,CAAC;AAUD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAI,IAAY,EAAE,OAAgB;IACjE,MAAM,CAAC,GAAG,UAET,CAAC;IACF,CAAC,CAAC,iCAAiC,KAAK,IAAI,GAAG,EAAE,CAAC;IAElD,MAAM,KAAK,GAAG,CAAC,CAAC,iCAAiC,CAAC;IAClD,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAM,CAAC;IAC7B,CAAC;SAAM,CAAC;QACP,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;QACzB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC;IACf,CAAC;AACF,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
{
"name": "keyv-cache-proxy",
"version": "0.0.12",
"description": "A transparent caching proxy for any object using Keyv - automatically cache method calls with TTL support",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"keywords": [
"keyv",
"cache",
"proxy",
"caching",
"memoization",
"ttl",
"storage",
"key-value",
"method-cache",
"transparent-cache"
],
"author": "snomiao",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/snomiao/keyv-cache-proxy.git"
},
"bugs": {
"url": "https://github.com/snomiao/keyv-cache-proxy/issues"
},
"homepage": "https://github.com/snomiao/keyv-cache-proxy#readme",
"devDependencies": {
"@biomejs/biome": "^2.3.8",
"@types/bun": "latest",
"standard-version": "^9.5.0"
},
"peerDependencies": {
"typescript": "^5.9.3",
"keyv": "^5.0.0"
},
"dependencies": {},
"scripts": {
"build": "tsc",
"fmt": "biome check --unsafe --write",
"prepack": "bun fmt && bun run build",
"release": "standard-version && git push --follow-tags && npm publish"
},
"engines": {
"node": ">=18.0.0"
}
"name": "keyv-cache-proxy",
"version": "0.1.0",
"description": "A transparent caching proxy for any object using Keyv - automatically cache method calls with TTL support",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"keywords": [
"keyv",
"cache",
"proxy",
"caching",
"memoization",
"ttl",
"storage",
"key-value",
"method-cache",
"transparent-cache"
],
"author": "snomiao",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/snomiao/keyv-cache-proxy.git"
},
"bugs": {
"url": "https://github.com/snomiao/keyv-cache-proxy/issues"
},
"homepage": "https://github.com/snomiao/keyv-cache-proxy#readme",
"devDependencies": {
"@biomejs/biome": "^2.3.8",
"@types/bun": "latest",
"standard-version": "^9.5.0"
},
"peerDependencies": {
"typescript": "^5.9.3",
"keyv": "^5.0.0"
},
"dependencies": {},
"scripts": {
"build": "tsc",
"fmt": "biome check --unsafe --write",
"prepack": "bun fmt && bun run build",
"release": "standard-version && git push --follow-tags && npm publish"
},
"engines": {
"node": ">=18.0.0"
}
}
+51
-12

@@ -11,3 +11,3 @@ # keyv-cache-proxy

- 🎯 **Deep proxy**: Automatically handles nested objects
- 📊 **Cache observability**: Optional callbacks for cache hits and misses
- 📊 **Cache observability**: Optional hooks for monitoring and modifying cached/fetched data
- 🔄 **Async-first**: Automatically converts all methods to async

@@ -87,4 +87,4 @@

prefix: 'github.',
onHit: (key) => console.log('Cache hit:', key),
onMiss: (key) => console.log('Cache miss:', key),
onCache: (key, value) => console.log('Cache hit:', key),
onFetch: (key, value) => console.log('Fetched fresh:', key),
})(new Octokit().rest);

@@ -173,7 +173,9 @@

### Cache Observability
### Cache Observability & Data Modification
Track cache performance:
```typescript
let hits = 0;
let misses = 0;
let fetches = 0;

@@ -183,9 +185,9 @@ const cached = KeyvCacheProxy({

ttl: 60000,
onHit: (key) => {
onCache: (key, value) => {
hits++;
console.log(`Cache hit for ${key}. Total hits: ${hits}`);
},
onMiss: (key) => {
misses++;
console.log(`Cache miss for ${key}. Total misses: ${misses}`);
onFetch: (key, value) => {
fetches++;
console.log(`Fetched fresh for ${key}. Total fetches: ${fetches}`);
},

@@ -195,2 +197,39 @@ })(myObject);

Modify cached/fetched data:
```typescript
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:
```typescript
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);
```
## API

@@ -205,6 +244,6 @@

- `store` (required): A Keyv instance for cache storage
- `ttl` (required): Time-to-live in milliseconds for cached values
- `ttl` (optional): Time-to-live in milliseconds for cached values
- `prefix` (optional): Prefix for cache keys (default: `""`)
- `onHit` (optional): Callback function called on cache hits `(key: string) => void`
- `onMiss` (optional): Callback function called on cache misses `(key: string) => void`
- `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>`

@@ -211,0 +250,0 @@ #### Returns