@apollo/utils.keyvaluecache
Advanced tools
Comparing version 3.0.0 to 3.1.0
@@ -1,13 +0,11 @@ | ||
import type { KeyValueCache } from "./KeyValueCache"; | ||
import type { KeyValueCache, KeyValueCacheSetOptions } from "./KeyValueCache"; | ||
import type { Logger } from "@apollo/utils.logger"; | ||
export declare class ErrorsAreMissesCache<V = string> implements KeyValueCache<V> { | ||
export declare class ErrorsAreMissesCache<V = string, SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions> implements KeyValueCache<V, SO> { | ||
private cache; | ||
private logger?; | ||
constructor(cache: KeyValueCache<V>, logger?: Logger | undefined); | ||
constructor(cache: KeyValueCache<V, SO>, logger?: Logger | undefined); | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, opts?: { | ||
ttl?: number; | ||
}): Promise<void>; | ||
set(key: string, value: V, opts?: SO): Promise<void>; | ||
delete(key: string): Promise<boolean | void>; | ||
} | ||
//# sourceMappingURL=ErrorsAreMissesCache.d.ts.map |
export type { KeyValueCache, KeyValueCacheSetOptions } from "./KeyValueCache"; | ||
export { PrefixingKeyValueCache } from "./PrefixingKeyValueCache"; | ||
export { InMemoryLRUCache } from "./InMemoryLRUCache"; | ||
export { InMemoryLRUCache, type InMemoryLRUCacheSetOptions, } from "./InMemoryLRUCache"; | ||
export { ErrorsAreMissesCache } from "./ErrorsAreMissesCache"; | ||
//# sourceMappingURL=index.d.ts.map |
import { LRUCache } from "lru-cache"; | ||
import type { KeyValueCache, KeyValueCacheSetOptions } from "./KeyValueCache"; | ||
export declare class InMemoryLRUCache<V extends {} = string> implements KeyValueCache<V> { | ||
export type InMemoryLRUCacheSetOptions<V extends {} = string, FC = unknown> = Omit<LRUCache.SetOptions<string, V, FC>, "ttl"> & KeyValueCacheSetOptions; | ||
export declare class InMemoryLRUCache<V extends {} = string, SO extends InMemoryLRUCacheSetOptions<V> = InMemoryLRUCacheSetOptions<V>> implements KeyValueCache<V, SO> { | ||
private cache; | ||
constructor(lruCacheOpts?: LRUCache.Options<string, V, any>); | ||
static sizeCalculation<V extends {}>(item: V): number; | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions): Promise<void>; | ||
set(key: string, value: V, options?: SO): Promise<void>; | ||
get(key: string): Promise<V | undefined>; | ||
@@ -9,0 +10,0 @@ delete(key: string): Promise<boolean>; |
@@ -23,8 +23,6 @@ "use strict"; | ||
async set(key, value, options) { | ||
if (options?.ttl) { | ||
this.cache.set(key, value, { ttl: options.ttl * 1000 }); | ||
} | ||
else { | ||
this.cache.set(key, value); | ||
} | ||
const lruOptions = options | ||
? { ...options, ttl: options.ttl ? options.ttl * 1000 : 0 } | ||
: undefined; | ||
this.cache.set(key, value, lruOptions); | ||
} | ||
@@ -31,0 +29,0 @@ async get(key) { |
@@ -1,4 +0,4 @@ | ||
export interface KeyValueCache<V = string> { | ||
export interface KeyValueCache<V = string, SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions> { | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions): Promise<void>; | ||
set(key: string, value: V, options?: SO): Promise<void>; | ||
delete(key: string): Promise<boolean | void>; | ||
@@ -5,0 +5,0 @@ } |
import type { KeyValueCache, KeyValueCacheSetOptions } from "."; | ||
declare const prefixesAreUnnecessaryForIsolationSymbol: unique symbol; | ||
export declare class PrefixingKeyValueCache<V = string> implements KeyValueCache<V> { | ||
export declare class PrefixingKeyValueCache<V = string, SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions> implements KeyValueCache<V, SO> { | ||
private wrapped; | ||
private prefix; | ||
[prefixesAreUnnecessaryForIsolationSymbol]?: true; | ||
constructor(wrapped: KeyValueCache<V>, prefix: string); | ||
constructor(wrapped: KeyValueCache<V, SO>, prefix: string); | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions): Promise<void>; | ||
set(key: string, value: V, options?: SO): Promise<void>; | ||
delete(key: string): Promise<boolean | void>; | ||
static prefixesAreUnnecessaryForIsolation<V = string>(c: KeyValueCache<V>): boolean; | ||
static cacheDangerouslyDoesNotNeedPrefixesForIsolation<V = string>(c: KeyValueCache<V>): KeyValueCache<V>; | ||
static prefixesAreUnnecessaryForIsolation<V = string, SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions>(c: KeyValueCache<V, SO>): boolean; | ||
static cacheDangerouslyDoesNotNeedPrefixesForIsolation<V = string, SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions>(c: KeyValueCache<V, SO>): KeyValueCache<V, SO>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=PrefixingKeyValueCache.d.ts.map |
{ | ||
"name": "@apollo/utils.keyvaluecache", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "Minimal key-value cache interface", | ||
@@ -25,4 +25,4 @@ "main": "dist/index.js", | ||
"@apollo/utils.logger": "^3.0.0", | ||
"lru-cache": "^9.0.3" | ||
"lru-cache": "^10.0.0" | ||
} | ||
} |
# KeyValueCache interface | ||
```ts | ||
export interface KeyValueCache<V = string> { | ||
export interface KeyValueCache< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
> { | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions): Promise<void>; | ||
set(key: string, value: V, options?: SO): Promise<void>; | ||
delete(key: string): Promise<boolean | void>; | ||
@@ -8,0 +11,0 @@ } |
import type { Logger } from "@apollo/utils.logger"; | ||
import { ErrorsAreMissesCache } from "../ErrorsAreMissesCache"; | ||
import type { KeyValueCache } from "../KeyValueCache"; | ||
import type { KeyValueCache, KeyValueCacheSetOptions } from "../KeyValueCache"; | ||
interface CustomKeyValueCacheSetOptions extends KeyValueCacheSetOptions { | ||
noDisposeOnSet?: boolean; | ||
noUpdateTTL?: boolean; | ||
} | ||
describe("ErrorsAreMissesCache", () => { | ||
@@ -38,3 +43,3 @@ const knownErrorMessage = "Service is down"; | ||
it("passes through calls to the underlying cache", async () => { | ||
const mockCache: KeyValueCache = { | ||
const mockCache: KeyValueCache<string, CustomKeyValueCacheSetOptions> = { | ||
get: jest.fn(async () => "foo"), | ||
@@ -51,6 +56,12 @@ set: jest.fn(), | ||
expect(mockCache.set).toHaveBeenCalledWith("key", "foo", undefined); | ||
await errorsAreMisses.set("keyWithTTL", "foo", { ttl: 1000 }); | ||
expect(mockCache.set).toHaveBeenLastCalledWith("keyWithTTL", "foo", { | ||
await errorsAreMisses.set("keyWithOptions", "foo", { | ||
ttl: 1000, | ||
noDisposeOnSet: true, | ||
noUpdateTTL: true, | ||
}); | ||
expect(mockCache.set).toHaveBeenLastCalledWith("keyWithOptions", "foo", { | ||
ttl: 1000, | ||
noDisposeOnSet: true, | ||
noUpdateTTL: true, | ||
}); | ||
@@ -57,0 +68,0 @@ await errorsAreMisses.delete("key"); |
@@ -0,3 +1,9 @@ | ||
import type { LRUCache } from "lru-cache"; | ||
import { InMemoryLRUCache } from ".."; | ||
interface CustomKeyValueCacheSetOptions | ||
extends LRUCache.SetOptions<string, string, Record<string, string>> { | ||
tags?: string[]; | ||
} | ||
describe("InMemoryLRUCache", () => { | ||
@@ -43,2 +49,30 @@ const cache = new InMemoryLRUCache(); | ||
}); | ||
it("with custom extended options", async () => { | ||
const customCache = new InMemoryLRUCache< | ||
string, | ||
CustomKeyValueCacheSetOptions | ||
>(); | ||
const spyOnCacheSet = jest.spyOn((customCache as any).cache, "set"); | ||
await customCache.set("key", "foo"); | ||
expect(spyOnCacheSet).toBeCalledWith("key", "foo", undefined); | ||
expect(await customCache.get("key")).toBe("foo"); | ||
await customCache.delete("key"); | ||
expect(await customCache.get("key")).toBe(undefined); | ||
await customCache.set("keyWithOptions", "bar", { | ||
ttl: 1000, | ||
tags: ["tag1", "tag2"], | ||
}); | ||
expect(spyOnCacheSet).toBeCalledWith("keyWithOptions", "bar", { | ||
ttl: 1000000, | ||
tags: ["tag1", "tag2"], | ||
}); | ||
expect(await customCache.get("keyWithOptions")).toBe("bar"); | ||
await customCache.delete("keyWithOptions"); | ||
expect(await customCache.get("keyWithOptions")).toBe(undefined); | ||
}); | ||
}); | ||
@@ -45,0 +79,0 @@ |
@@ -1,4 +0,8 @@ | ||
import { InMemoryLRUCache } from ".."; | ||
import { InMemoryLRUCache, type InMemoryLRUCacheSetOptions } from ".."; | ||
import { PrefixingKeyValueCache } from "../PrefixingKeyValueCache"; | ||
interface CustomKeyValueCacheSetOptions extends InMemoryLRUCacheSetOptions { | ||
tags?: string[]; | ||
} | ||
describe("PrefixingKeyValueCache", () => { | ||
@@ -14,2 +18,3 @@ it("prefixes", async () => { | ||
}); | ||
it("PrefixesAreUnnecessaryForIsolationCache", async () => { | ||
@@ -49,2 +54,30 @@ const inner = new InMemoryLRUCache(); | ||
}); | ||
it("prefixes with custom extended options", async () => { | ||
const inner = new InMemoryLRUCache<string, CustomKeyValueCacheSetOptions>(); | ||
const spyOnCacheSet = jest.spyOn(inner, "set"); | ||
const prefixing = new PrefixingKeyValueCache(inner, "prefix:"); | ||
await prefixing.set("key", "foo"); | ||
expect(spyOnCacheSet).toBeCalledWith("prefix:key", "foo", undefined); | ||
expect(await prefixing.get("key")).toBe("foo"); | ||
expect(await inner.get("prefix:key")).toBe("foo"); | ||
await prefixing.delete("key"); | ||
expect(await prefixing.get("key")).toBe(undefined); | ||
await prefixing.set("keyWithOptions", "bar", { | ||
ttl: 1000, | ||
tags: ["tag1", "tag2"], | ||
}); | ||
expect(spyOnCacheSet).toBeCalledWith("prefix:keyWithOptions", "bar", { | ||
ttl: 1000, | ||
tags: ["tag1", "tag2"], | ||
}); | ||
expect(await prefixing.get("keyWithOptions")).toBe("bar"); | ||
expect(await inner.get("prefix:keyWithOptions")).toBe("bar"); | ||
await prefixing.delete("keyWithOptions"); | ||
expect(await prefixing.get("keyWithOptions")).toBe(undefined); | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
import type { KeyValueCache } from "./KeyValueCache"; | ||
import type { KeyValueCache, KeyValueCacheSetOptions } from "./KeyValueCache"; | ||
import type { Logger } from "@apollo/utils.logger"; | ||
@@ -9,4 +9,11 @@ | ||
*/ | ||
export class ErrorsAreMissesCache<V = string> implements KeyValueCache<V> { | ||
constructor(private cache: KeyValueCache<V>, private logger?: Logger) {} | ||
export class ErrorsAreMissesCache< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
> implements KeyValueCache<V, SO> | ||
{ | ||
constructor( | ||
private cache: KeyValueCache<V, SO>, | ||
private logger?: Logger, | ||
) {} | ||
@@ -28,3 +35,3 @@ async get(key: string): Promise<V | undefined> { | ||
async set(key: string, value: V, opts?: { ttl?: number }): Promise<void> { | ||
async set(key: string, value: V, opts?: SO): Promise<void> { | ||
return this.cache.set(key, value, opts); | ||
@@ -31,0 +38,0 @@ } |
export type { KeyValueCache, KeyValueCacheSetOptions } from "./KeyValueCache"; | ||
export { PrefixingKeyValueCache } from "./PrefixingKeyValueCache"; | ||
export { InMemoryLRUCache } from "./InMemoryLRUCache"; | ||
export { | ||
InMemoryLRUCache, | ||
type InMemoryLRUCacheSetOptions, | ||
} from "./InMemoryLRUCache"; | ||
export { ErrorsAreMissesCache } from "./ErrorsAreMissesCache"; |
import { LRUCache } from "lru-cache"; | ||
import type { KeyValueCache, KeyValueCacheSetOptions } from "./KeyValueCache"; | ||
export type InMemoryLRUCacheSetOptions< | ||
V extends {} = string, | ||
FC = unknown, | ||
> = Omit<LRUCache.SetOptions<string, V, FC>, "ttl"> & KeyValueCacheSetOptions; | ||
// LRUCache wrapper to implement the KeyValueCache interface. | ||
export class InMemoryLRUCache<V extends {} = string> | ||
implements KeyValueCache<V> | ||
export class InMemoryLRUCache< | ||
V extends {} = string, | ||
SO extends InMemoryLRUCacheSetOptions<V> = InMemoryLRUCacheSetOptions<V>, | ||
> implements KeyValueCache<V, SO> | ||
{ | ||
@@ -35,8 +42,9 @@ private cache: LRUCache<string, V>; | ||
async set(key: string, value: V, options?: KeyValueCacheSetOptions) { | ||
if (options?.ttl) { | ||
this.cache.set(key, value, { ttl: options.ttl * 1000 }); | ||
} else { | ||
this.cache.set(key, value); | ||
} | ||
async set(key: string, value: V, options?: SO) { | ||
// If a TTL in seconds is provided, convert it to milliseconds. | ||
// Otherwise, default it to 0 to indicate "no TTL". | ||
const lruOptions = options | ||
? { ...options, ttl: options.ttl ? options.ttl * 1000 : 0 } | ||
: undefined; | ||
this.cache.set(key, value, lruOptions); | ||
} | ||
@@ -43,0 +51,0 @@ |
@@ -1,4 +0,7 @@ | ||
export interface KeyValueCache<V = string> { | ||
export interface KeyValueCache< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
> { | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions): Promise<void>; | ||
set(key: string, value: V, options?: SO): Promise<void>; | ||
delete(key: string): Promise<boolean | void>; | ||
@@ -5,0 +8,0 @@ } |
@@ -17,7 +17,14 @@ import type { KeyValueCache, KeyValueCacheSetOptions } from "."; | ||
// trying to provide a flush() method here could be confusingly dangerous. | ||
export class PrefixingKeyValueCache<V = string> implements KeyValueCache<V> { | ||
export class PrefixingKeyValueCache< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
> implements KeyValueCache<V, SO> | ||
{ | ||
private prefix: string; | ||
[prefixesAreUnnecessaryForIsolationSymbol]?: true; | ||
constructor(private wrapped: KeyValueCache<V>, prefix: string) { | ||
constructor( | ||
private wrapped: KeyValueCache<V, SO>, | ||
prefix: string, | ||
) { | ||
if (PrefixingKeyValueCache.prefixesAreUnnecessaryForIsolation(wrapped)) { | ||
@@ -38,3 +45,3 @@ this.prefix = ""; | ||
} | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions) { | ||
set(key: string, value: V, options?: SO) { | ||
return this.wrapped.set(this.prefix + key, value, options); | ||
@@ -49,11 +56,13 @@ } | ||
// package doesn't break things). | ||
static prefixesAreUnnecessaryForIsolation<V = string>( | ||
c: KeyValueCache<V>, | ||
): boolean { | ||
static prefixesAreUnnecessaryForIsolation< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
>(c: KeyValueCache<V, SO>): boolean { | ||
return prefixesAreUnnecessaryForIsolationSymbol in c; | ||
} | ||
static cacheDangerouslyDoesNotNeedPrefixesForIsolation<V = string>( | ||
c: KeyValueCache<V>, | ||
): KeyValueCache<V> { | ||
static cacheDangerouslyDoesNotNeedPrefixesForIsolation< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
>(c: KeyValueCache<V, SO>): KeyValueCache<V, SO> { | ||
return new PrefixesAreUnnecessaryForIsolationCache(c); | ||
@@ -65,8 +74,10 @@ } | ||
// PrefixingKeyValueCache. See the README for details. | ||
class PrefixesAreUnnecessaryForIsolationCache<V = string> | ||
implements KeyValueCache<V> | ||
class PrefixesAreUnnecessaryForIsolationCache< | ||
V = string, | ||
SO extends KeyValueCacheSetOptions = KeyValueCacheSetOptions, | ||
> implements KeyValueCache<V, SO> | ||
{ | ||
[prefixesAreUnnecessaryForIsolationSymbol] = true; | ||
constructor(private wrapped: KeyValueCache<V>) {} | ||
constructor(private wrapped: KeyValueCache<V, SO>) {} | ||
@@ -76,3 +87,3 @@ get(key: string) { | ||
} | ||
set(key: string, value: V, options?: KeyValueCacheSetOptions) { | ||
set(key: string, value: V, options?: SO) { | ||
return this.wrapped.set(key, value, options); | ||
@@ -79,0 +90,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38506
670
71
+ Addedlru-cache@10.4.3(transitive)
- Removedlru-cache@9.1.2(transitive)
Updatedlru-cache@^10.0.0