keyv
Version:
Simple key-value storage with support for multiple backends
1,541 lines • 62.4 kB
text/typescript
import { Hookified, IEventEmitter } from "hookified";
//#region src/capabilities.d.ts
type MethodType = "sync" | "async" | "none";
type KeyvStorageMethod = {
exists: boolean;
methodType: MethodType;
};
declare const keyvMethodNames: readonly ["get", "set", "delete", "clear", "has", "getMany", "setMany", "deleteMany", "hasMany", "disconnect", "getRaw", "getManyRaw", "setRaw", "setManyRaw", "iterator"];
declare const keyvPropertyNames: readonly ["hooks", "stats"];
type KeyvMethods = Record<(typeof keyvMethodNames)[number], KeyvStorageMethod>;
type KeyvProperties = Record<(typeof keyvPropertyNames)[number], boolean>;
type KeyvCapability = {
compatible: boolean;
methods: KeyvMethods;
properties: KeyvProperties;
};
declare const keyvStorageMethodNames: readonly ["get", "getMany", "has", "hasMany", "set", "setMany", "delete", "deleteMany", "clear", "disconnect", "iterator"];
type KeyvStorageMethods = Record<(typeof keyvStorageMethodNames)[number], KeyvStorageMethod>;
type KeyvStorageCapability = {
compatible: boolean;
store: "mapLike" | "keyvStorage" | "asyncMap" | "none";
methods: KeyvStorageMethods;
/**
* Whether the adapter implements the v6 storage contract — it accepts an absolute
* `expires` timestamp (ms since epoch) on `set`/`setMany`. Adapters that omit this
* (legacy relative-`ttl` adapters) are wrapped by `KeyvBridgeAdapter`, which converts
* the absolute `expires` back to a relative ttl before delegating.
*
* Declaring `expires: true` means the adapter is used directly and should ENFORCE expiry —
* ideally via a native mechanism (TTL index, key expiry, lease) so the backend reclaims
* space, and/or a client-side check on read. Keyv core also filters expired reads by default
* (`checkExpired` is on), so an adapter with coarse or lazily-swept native expiry (e.g.
* Memcached, DynamoDB) still reads millisecond-precise. Validate with `@keyv/test-suite`'s
* `storageTtlTests`.
*/
expires?: boolean;
};
declare const keyvCompressionMethodNames: readonly ["compress", "decompress"];
type KeyvCompressionMethods = Record<(typeof keyvCompressionMethodNames)[number], KeyvStorageMethod>;
type KeyvCompressionCapability = {
compatible: boolean;
methods: KeyvCompressionMethods;
};
declare const keyvSerializationMethodNames: readonly ["stringify", "parse"];
type KeyvSerializationMethods = Record<(typeof keyvSerializationMethodNames)[number], KeyvStorageMethod>;
type KeyvSerializationCapability = {
compatible: boolean;
methods: KeyvSerializationMethods;
};
declare const keyvEncryptionMethodNames: readonly ["encrypt", "decrypt"];
type KeyvEncryptionMethods = Record<(typeof keyvEncryptionMethodNames)[number], KeyvStorageMethod>;
type KeyvEncryptionCapability = {
compatible: boolean;
methods: KeyvEncryptionMethods;
};
/**
* Detect whether an object implements the full Keyv interface
* @param obj - The object to check
* @returns A {@link KeyvCapability} where `compatible` is `true` only when all required capabilities are present
* @example
* ```typescript
* import Keyv, { detectKeyv } from 'keyv';
*
* const result = detectKeyv(new Keyv());
* result.compatible; // true — all capabilities present
* result.methods.get.exists; // true
* result.methods.get.methodType; // "async"
*
* const partial = detectKeyv(new Map());
* partial.compatible; // false — missing getMany, setMany, hooks, stats, etc.
* partial.methods.get.exists; // true
* ```
*/
declare function detectKeyv(obj: unknown): KeyvCapability;
/**
* Detect whether an object implements the Keyv storage adapter interface
* @param obj - The object to check
* @returns A {@link KeyvStorageCapability} where:
* - `compatible` is `true` when the object is a valid storage adapter (`"keyvStorage"`, `"mapLike"`, or `"asyncMap"`)
* - `store` indicates the detected store type: `"keyvStorage"`, `"mapLike"`, `"asyncMap"`, or `"none"`
* - `methods` maps each method name to `{ exists, methodType }`
* @example
* ```typescript
* import { detectKeyvStorage } from 'keyv';
*
* const map = detectKeyvStorage(new Map());
* map.compatible; // true
* map.store; // "mapLike"
* map.methods.get.exists; // true
* map.methods.get.methodType; // "sync"
*
* const adapter = detectKeyvStorage(asyncAdapter);
* adapter.compatible; // true
* adapter.store; // "keyvStorage"
* adapter.methods.get.methodType; // "async"
* ```
*/
declare function detectKeyvStorage(obj: unknown): KeyvStorageCapability;
/**
* Build the capability descriptor for a v6 storage adapter: the structurally detected
* methods plus `expires: true`, declaring that the adapter accepts an absolute `expires`
* timestamp on `set`/`setMany`. First-party adapters expose this from their `capabilities`
* getter so Keyv uses them directly instead of bridging.
* @param adapter - The storage adapter to describe (typically `this`).
* @returns A {@link KeyvStorageCapability} with `expires` set to `true`.
* @example
* ```typescript
* public get capabilities(): KeyvStorageCapability {
* return keyvStorageCapability(this);
* }
* ```
*/
declare function keyvStorageCapability(adapter: object): KeyvStorageCapability;
/**
* Detect whether an object implements the Keyv compression adapter interface
* @param obj - The object to check
* @returns A {@link KeyvCompressionCapability} where `compatible` is `true` when both `compress` and `decompress` methods are present
* @example
* ```typescript
* import { detectKeyvCompression } from 'keyv';
*
* detectKeyvCompression({ compress: (d) => d, decompress: (d) => d });
* // { compatible: true, methods: { compress: { exists: true, methodType: "sync" }, decompress: { exists: true, methodType: "sync" } } }
* ```
*/
declare function detectKeyvCompression(obj: unknown): KeyvCompressionCapability;
/**
* Detect whether an object implements the Keyv serialization adapter interface
* @param obj - The object to check
* @returns A {@link KeyvSerializationCapability} where `compatible` is `true` when both `stringify` and `parse` methods are present
* @example
* ```typescript
* import { detectKeyvSerialization } from 'keyv';
*
* detectKeyvSerialization(JSON);
* // { compatible: true, methods: { stringify: { exists: true, methodType: "sync" }, parse: { exists: true, methodType: "sync" } } }
* ```
*/
declare function detectKeyvSerialization(obj: unknown): KeyvSerializationCapability;
/**
* Detect whether an object implements the Keyv encryption adapter interface
* @param obj - The object to check
* @returns A {@link KeyvEncryptionCapability} where `compatible` is `true` when both `encrypt` and `decrypt` methods are present
* @example
* ```typescript
* import { detectKeyvEncryption } from 'keyv';
*
* detectKeyvEncryption({ encrypt: (d) => d, decrypt: (d) => d });
* // { compatible: true, methods: { encrypt: { exists: true, methodType: "sync" }, decrypt: { exists: true, methodType: "sync" } } }
* ```
*/
declare function detectKeyvEncryption(obj: unknown): KeyvEncryptionCapability;
//#endregion
//#region src/sanitize.d.ts
/**
* Which dangerous-pattern categories to detect and strip.
* Each defaults to `true` when the parent scope is enabled.
*/
type KeyvSanitizePatterns = {
/**
* Detect and strip SQL injection patterns: semicolons (`;`), SQL comments (`--` and `/*`).
* @default false
*/
sql: boolean;
/**
* Detect and strip MongoDB operator patterns: leading `$`, `{$` sequences.
* @default false
*/
mongo: boolean;
/**
* Detect and strip dangerous control sequences: null bytes (`\0`), carriage returns (`\r`), newlines (`\n`).
* @default false
*/
escape: boolean;
/**
* Detect and strip path traversal patterns: `../` and `..\\` sequences.
* @default false
*/
path: boolean;
};
/**
* Options for configuring sanitization pattern categories.
* All categories default to `true` when the parent scope is enabled.
*/
type KeyvSanitizePatternsOptions = {
/**
* Detect and strip SQL injection patterns: semicolons (`;`), SQL comments (`--` and `/*`).
* @default true
*/
sql?: boolean;
/**
* Detect and strip MongoDB operator patterns: leading `$`, `{$` sequences.
* @default true
*/
mongo?: boolean;
/**
* Detect and strip dangerous control sequences: null bytes (`\0`), carriage returns (`\r`), newlines (`\n`).
* @default true
*/
escape?: boolean;
/**
* Detect and strip path traversal patterns: `../` and `..\\` sequences.
* @default true
*/
path?: boolean;
};
/**
* Controls what gets sanitized and with which patterns.
*/
type KeyvSanitizeOptions = {
/**
* Sanitize keys. Pass `true` for all pattern categories, `false` to skip,
* or a `KeyvSanitizePatternOptions` object for granular control.
* @default false
*/
keys?: boolean | KeyvSanitizePatternsOptions;
/**
* Sanitize namespace strings. Pass `true` for all pattern categories, `false` to skip,
* or a `KeyvSanitizePatternOptions` object for granular control.
* @default false
*/
namespace?: boolean | KeyvSanitizePatternsOptions;
};
/**
* Adapter interface for key and namespace sanitization.
* Implement this to provide custom sanitization logic to Keyv.
*/
type KeyvSanitizeAdapter = {
/** Whether any sanitization is currently enabled. */
readonly enabled: boolean;
/** The key sanitization pattern configuration. */
readonly keys: KeyvSanitizePatterns;
/** The namespace sanitization pattern configuration. */
readonly namespace: KeyvSanitizePatterns;
/** Sanitize a single key. */
cleanKey(key: string): string;
/** Sanitize an array of keys. */
cleanKeys(keys: string[]): string[];
/** Sanitize a namespace string. */
cleanNamespace(ns: string): string;
};
/**
* Encapsulates key and namespace sanitization with an LRU result cache.
*/
declare class KeyvSanitize implements KeyvSanitizeAdapter {
private _keys;
private _namespace;
private _keyPatterns;
private _namespacePatterns;
private _enabled;
private _cacheKeys;
private _cacheNamespaces;
private _cacheMax;
constructor(options?: KeyvSanitizeOptions);
/**
* The key sanitization pattern configuration.
*/
get keys(): KeyvSanitizePatterns;
/**
* Whether any sanitization pattern (keys or namespace) is enabled.
*/
get enabled(): boolean;
/**
* The namespace sanitization pattern configuration.
*/
get namespace(): KeyvSanitizePatterns;
/**
* Update the sanitization configuration. Recompiles patterns and clears the cache.
*/
updateOptions(options: KeyvSanitizeOptions): void;
/**
* Sanitize a single key. Uses an LRU cache for repeated lookups.
*/
cleanKey(key: string): string;
/**
* Sanitize an array of keys.
*/
cleanKeys(keys: string[]): string[];
/**
* Sanitize a namespace string. Uses an LRU cache for repeated lookups.
*/
cleanNamespace(ns: string): string;
/**
* Clear the LRU caches.
*/
clearCache(): void;
private resolvePatterns;
}
//#endregion
//#region src/stats.d.ts
/**
* Structure of a telemetry event emitted by Keyv.
*/
type KeyvTelemetryEvent = {
/** The event type (e.g. "hit", "miss", "set", "delete", "error"). */
event: string;
/** The cache key involved, if applicable. */
key?: string;
/** The namespace of the Keyv instance. */
namespace?: string;
/** Unix timestamp in milliseconds when the event occurred. */
timestamp: number;
};
type KeyvStatsOptions = {
/**
* Enable or disable stats tracking.
* @default false
*/
enabled?: boolean;
/**
* Maximum number of entries per event-type LRU map.
* @default 1000
*/
maxEntries?: number;
/**
* The event emitter (e.g. a Keyv instance) to subscribe to for telemetry events.
* If provided, KeyvStats will automatically subscribe on construction.
*/
emitter?: IEventEmitter;
};
declare class KeyvStats {
private _hits;
private _misses;
private _sets;
private _deletes;
private _errors;
private _maxEntries;
private _enabled;
private readonly hitKeysMap;
private readonly missKeysMap;
private readonly setKeysMap;
private readonly deleteKeysMap;
private readonly errorKeysMap;
private _emitter?;
private readonly _listeners;
constructor(options?: KeyvStatsOptions);
/**
* Total number of cache hits.
*/
get hits(): number;
/**
* Total number of cache misses.
*/
get misses(): number;
/**
* Total number of cache sets.
*/
get sets(): number;
/**
* Total number of cache deletes.
*/
get deletes(): number;
/**
* Total number of cache errors.
*/
get errors(): number;
/**
* LRU-bounded map of key to hit count.
*/
get hitKeys(): Map<string, number>;
/**
* LRU-bounded map of key to miss count.
*/
get missKeys(): Map<string, number>;
/**
* LRU-bounded map of key to set count.
*/
get setKeys(): Map<string, number>;
/**
* LRU-bounded map of key to delete count.
*/
get deleteKeys(): Map<string, number>;
/**
* LRU-bounded map of key to error count.
*/
get errorKeys(): Map<string, number>;
/**
* Maximum number of entries per event-type LRU map.
* @default 1000
*/
get maxEntries(): number;
/**
* Set the maximum number of entries per event-type LRU map.
* @param {number} value the new maximum entries
*/
set maxEntries(value: number);
/**
* Whether stats tracking is enabled.
* @default false
*/
get enabled(): boolean;
/**
* Enable or disable stats tracking. If false it will unsubscribe from the events
* @param {boolean} value true to enable, false to disable
*/
set enabled(value: boolean);
/**
* Build a composite key from a telemetry event.
* Format: "namespace::key" if namespace is present, otherwise just "key".
*/
buildKeyEventName(event: KeyvTelemetryEvent): string;
/**
* Increment the count for a key in an LRU-bounded map.
* Deletes and re-inserts to maintain LRU order, evicts the oldest entry when full.
*/
incrementKeys(map: Map<string, number>, compositeKey: string): void;
/**
* Subscribe to telemetry events from an emitter (e.g. a Keyv instance).
* Automatically increments the corresponding stat counters and LRU key maps on each event.
* @param {IEventEmitter} emitter the event emitter to subscribe to
*/
subscribe(emitter: IEventEmitter): void;
/**
* Unsubscribe from the currently subscribed emitter, removing all telemetry event listeners.
*/
unsubscribe(): void;
/**
* Reset all counters and LRU key maps to their initial state.
*/
reset(): void;
}
//#endregion
//#region src/types/keyv.d.ts
/**
* A permissive `any` type used at Keyv's dynamic boundaries — untyped store
* values, parameterized query arguments, and other places where the concrete
* type is intentionally open. Centralizing it keeps the `noExplicitAny`
* suppression in one place instead of scattered across the codebase.
*/
type KeyvAny = any;
/**
* The array counterpart to {@link KeyvAny} (i.e. `any[]`).
*/
type KeyvAnyArray = KeyvAny[];
/**
* A Map or any Map-like object. Used as a flexible input type for stores.
*/
type KeyvMapAny = Map<KeyvAny, KeyvAny> | KeyvAny;
/**
* The envelope structure used to store values in Keyv.
* Wraps the actual value with an optional expiration timestamp.
*/
type KeyvValue<Value> = {
/** The stored value. */
value?: Value;
/** Absolute expiration timestamp in milliseconds since epoch, or `undefined` for no expiry. */
expires?: number | undefined;
};
/** @deprecated Use `KeyvValue` instead. */
type DeserializedData<Value> = KeyvValue<Value>;
/**
* Events emitted by Keyv for error handling and telemetry.
*/
declare enum KeyvEvents {
/** Emitted when an error occurs in a store operation. */
ERROR = "error",
/** Emitted for informational messages. */
INFO = "info",
/** Emitted for warning messages. */
WARN = "warn",
/** Telemetry: cache hit. */
STAT_HIT = "stat:hit",
/** Telemetry: cache miss. */
STAT_MISS = "stat:miss",
/** Telemetry: value set. */
STAT_SET = "stat:set",
/** Telemetry: value deleted. */
STAT_DELETE = "stat:delete",
/** Telemetry: operation error. */
STAT_ERROR = "stat:error"
}
/**
* Hook names for intercepting Keyv operations.
* Register hooks via `keyv.on(KeyvHooks.BEFORE_SET, callback)` to run logic before/after operations.
*/
declare enum KeyvHooks {
/** @deprecated Use BEFORE_SET instead */
PRE_SET = "preSet",
/** @deprecated Use AFTER_SET instead */
POST_SET = "postSet",
/** @deprecated Use BEFORE_GET instead */
PRE_GET = "preGet",
/** @deprecated Use AFTER_GET instead */
POST_GET = "postGet",
/** @deprecated Use BEFORE_GET_MANY instead */
PRE_GET_MANY = "preGetMany",
/** @deprecated Use AFTER_GET_MANY instead */
POST_GET_MANY = "postGetMany",
/** @deprecated Use BEFORE_GET_RAW instead */
PRE_GET_RAW = "preGetRaw",
/** @deprecated Use AFTER_GET_RAW instead */
POST_GET_RAW = "postGetRaw",
/** @deprecated Use BEFORE_GET_MANY_RAW instead */
PRE_GET_MANY_RAW = "preGetManyRaw",
/** @deprecated Use AFTER_GET_MANY_RAW instead */
POST_GET_MANY_RAW = "postGetManyRaw",
/** @deprecated Use BEFORE_SET_RAW instead */
PRE_SET_RAW = "preSetRaw",
/** @deprecated Use AFTER_SET_RAW instead */
POST_SET_RAW = "postSetRaw",
/** @deprecated Use BEFORE_SET_MANY_RAW instead */
PRE_SET_MANY_RAW = "preSetManyRaw",
/** @deprecated Use AFTER_SET_MANY_RAW instead */
POST_SET_MANY_RAW = "postSetManyRaw",
/** @deprecated Use BEFORE_SET_MANY instead */
PRE_SET_MANY = "preSetMany",
/** @deprecated Use AFTER_SET_MANY instead */
POST_SET_MANY = "postSetMany",
/** @deprecated Use BEFORE_DELETE instead */
PRE_DELETE = "preDelete",
/** @deprecated Use AFTER_DELETE instead */
POST_DELETE = "postDelete",
/** @deprecated Use BEFORE_DELETE_MANY instead */
PRE_DELETE_MANY = "preDeleteMany",
/** @deprecated Use AFTER_DELETE_MANY instead */
POST_DELETE_MANY = "postDeleteMany",
BEFORE_SET = "before:set",
AFTER_SET = "after:set",
BEFORE_GET = "before:get",
AFTER_GET = "after:get",
BEFORE_GET_MANY = "before:getMany",
AFTER_GET_MANY = "after:getMany",
BEFORE_GET_RAW = "before:getRaw",
AFTER_GET_RAW = "after:getRaw",
BEFORE_GET_MANY_RAW = "before:getManyRaw",
AFTER_GET_MANY_RAW = "after:getManyRaw",
BEFORE_SET_RAW = "before:setRaw",
AFTER_SET_RAW = "after:setRaw",
BEFORE_SET_MANY = "before:setMany",
AFTER_SET_MANY = "after:setMany",
BEFORE_SET_MANY_RAW = "before:setManyRaw",
AFTER_SET_MANY_RAW = "after:setManyRaw",
BEFORE_DELETE = "before:delete",
AFTER_DELETE = "after:delete",
BEFORE_DELETE_MANY = "before:deleteMany",
AFTER_DELETE_MANY = "after:deleteMany",
BEFORE_HAS = "before:has",
AFTER_HAS = "after:has",
BEFORE_HAS_MANY = "before:hasMany",
AFTER_HAS_MANY = "after:hasMany",
BEFORE_CLEAR = "before:clear",
AFTER_CLEAR = "after:clear",
BEFORE_DISCONNECT = "before:disconnect",
AFTER_DISCONNECT = "after:disconnect"
}
/**
* Represents a key-value entry with an optional TTL, used for the public
* batch API `Keyv.setMany`.
*/
type KeyvEntry<Value = KeyvAny> = {
/**
* Key to set.
*/
key: string;
/**
* Value to set.
*/
value: Value;
/**
* Time to live in milliseconds.
*/
ttl?: number;
};
/**
* Represents a key-value entry at the storage-adapter boundary, carrying an
* absolute `expires` timestamp instead of a relative `ttl`. Keyv core computes
* `expires` once and passes these to a storage adapter's `setMany`, so adapters
* never derive expiry themselves.
*/
type KeyvStorageEntry<Value = KeyvAny> = {
/** Key to set. */
key: string;
/** Value to set (already encoded by Keyv core). */
value: Value;
/** Absolute expiry as Unix ms since epoch, or `undefined` for no expiry. */
expires?: number;
};
/**
* Configuration options for the Keyv constructor.
*/
type KeyvOptions = {
/**
* Namespace for the current instance.
* @default undefined
*/
namespace?: string;
/**
* A custom serialization adapter with stringify and parse methods. Pass `false` to store
* values as they are, without compression. Encryption needs serialization, so with an
* encryption adapter set, `false` makes every write fail with an error.
* @default KeyvJsonSerializer (built-in)
*/
serialization?: KeyvSerializationAdapter | false;
/**
* The storage adapter instance to be used by Keyv.
* @default new Map() - in-memory store
*/
store?: KeyvStorageAdapter | Map<KeyvAny, KeyvAny> | KeyvAny;
/**
* Default TTL in milliseconds. Can be overridden by specifying a TTL on `.set()`.
* @default undefined
*/
ttl?: number;
/**
* Enable compression option
* @default undefined
*/
compression?: KeyvCompressionAdapter | KeyvAny;
/**
* Enable or disable statistics (default is false)
* @default false
*/
stats?: boolean;
/**
* Enable sanitization of keys and namespaces by detecting dangerous patterns
* for SQL, MongoDB, or filesystem-based storage backends. Pass a `KeyvSanitizeOptions`
* object for granular control over targets and patterns.
* @default undefined
*/
sanitize?: KeyvSanitizeOptions;
/**
* Enable encryption of stored values. Pass a `KeyvEncryptionAdapter` with
* `encrypt` and `decrypt` methods. Encryption runs on the serialized value, so it needs
* serialization. With `serialization: false`, writes fail with an error instead of storing
* values unencrypted.
* @default undefined
*/
encryption?: KeyvEncryptionAdapter;
/**
* When true (default), Keyv checks expiry on get/getMany/has/hasMany at its own layer,
* filtering (and deleting) expired entries using the absolute `expires` stored in the
* serialized envelope. This keeps reads millisecond-precise even on adapters whose native
* expiry is coarse or lazily swept (e.g. Memcached's second-granular exptime, DynamoDB's
* background TTL sweep that can lag for hours). Set to false to trust the storage adapter
* to handle expiry on its own (skips the extra decode + expiry check on reads).
* @default true
*/
checkExpired?: boolean;
};
//#endregion
//#region src/types/adapters.d.ts
/**
* Adapter interface for custom serialization.
* Implement `stringify` and `parse` to control how values are serialized to/from strings.
*/
type KeyvSerializationAdapter = {
/** Converts a value to a string representation. */
stringify: (object: unknown) => string | Promise<string>;
/** Parses a string back into its original value. */
parse: <T>(data: string) => T | Promise<T>;
};
/**
* Adapter interface for compression.
* Implement `compress` and `decompress` to add compression to stored values.
*/
type KeyvCompressionAdapter = {
/** Compresses a string value. */
compress(value: string): Promise<string>;
/** Decompresses a string value back to its original form. */
decompress(value: string): Promise<string>;
};
/**
* Adapter interface for encryption.
* Implement `encrypt` and `decrypt` to add encryption to stored values.
*/
type KeyvEncryptionAdapter = {
/** Encrypts a string value. */
encrypt: (data: string) => string | Promise<string>;
/** Decrypts a string value back to its original form. */
decrypt: (data: string) => string | Promise<string>;
};
type KeyvStorageGetResult<Value> = KeyvValue<Value> | string | undefined;
/**
* Interface that all Keyv storage adapters must implement.
* Adapters handle the actual persistence of key-value pairs.
*/
type KeyvStorageAdapter = {
/** Optional namespace for key isolation. */
namespace?: string | undefined;
/**
* The adapter's capabilities. v6 adapters set `capabilities.expires = true` (e.g. via
* `keyvStorageCapability(this)`) to declare they accept an absolute `expires` timestamp
* on `set`/`setMany`. Full storage adapters that omit it are treated as legacy relative-`ttl`
* adapters and wrapped by `KeyvBridgeAdapter`, which converts `expires` back to a ttl.
*
* Declaring `expires: true` means the adapter should enforce expiry on read so `get`/`getMany`/
* `has` do not return a key past its deadline (ideally backed by a native mechanism that also
* reclaims space). Keyv core additionally filters expired reads by default (`checkExpired` is
* on), as a safety net for backends with coarse or lazily-swept native expiry. See
* {@link KeyvStorageCapability.expires}.
*/
capabilities?: KeyvStorageCapability;
/** Retrieves a value by key. */
get<Value>(key: string): Promise<KeyvStorageGetResult<Value>>;
/**
* Stores a value with a key and optional absolute expiry.
* @param expires Absolute expiry as Unix ms since epoch; `undefined` means no expiry.
* A value `<= Date.now()` is already expired and the adapter may delete/skip it.
*/
set(key: string, value: unknown, expires?: number): Promise<boolean>;
/** Stores multiple entries at once, each with an absolute `expires` timestamp. */
setMany<Value>(values: KeyvStorageEntry<Value>[]): Promise<boolean[] | undefined>;
/** Deletes a key from the store. */
delete(key: string): Promise<boolean>;
/** Clears all entries from the store (respects namespace if set). */
clear(): Promise<void>;
/** Checks if a key exists in the store. */
has(key: string): Promise<boolean>;
/** Checks if multiple keys exist in the store. */
hasMany(keys: string[]): Promise<boolean[]>;
/** Retrieves multiple values by keys. */
getMany<Value>(keys: string[]): Promise<Array<KeyvStorageGetResult<Value | undefined>>>;
/** Disconnects from the store and releases resources. */
disconnect?(): Promise<void>;
/** Deletes multiple keys from the store. */
deleteMany(key: string[]): Promise<boolean[]>;
/** Returns an async iterator over all key-value pairs. */
iterator?<Value>(): AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>;
} & IEventEmitter;
/**
* @deprecated Use `KeyvStorageAdapter` instead.
*/
type KeyvStoreAdapter = KeyvStorageAdapter;
/**
* @deprecated Use `KeyvCompressionAdapter` instead.
*/
type KeyvCompression = KeyvCompressionAdapter;
//#endregion
//#region src/adapters/bridge.d.ts
/**
* Configuration options for KeyvBridgeAdapter.
*/
type KeyvBridgeAdapterOptions = {
/**
* The namespace to use for keys.
* When set, all keys will be prefixed with the namespace followed by the namespace separator.
*/
namespace?: string;
/**
* The separator between the namespace and the key. Defaults to `::`.
*/
namespaceSeparator?: string;
};
/**
* Interface for a promise-based store that can be used with KeyvBridgeAdapter.
* The store must implement get, set, delete, and clear as async operations.
* Optional methods (has, hasMany, getMany, setMany, deleteMany, iterator, disconnect)
* will be delegated to the store if present, otherwise fallback implementations are used.
*/
type KeyvBridgeStore = {
/** Store configuration/options (e.g. dialect, url) */
opts?: KeyvAny;
/** Namespace the store scopes its keys under, when it manages its own namespacing. */
namespace?: string;
/** Retrieves a value by key */
get(key: string): Promise<KeyvAny>;
/** Sets a value with a key and optional TTL */
set(key: string, value: KeyvAny, ttl?: number): Promise<KeyvAny>;
/** Deletes a key from the store */
delete(key: string): Promise<boolean>;
/** Clears all entries from the store */
clear(): Promise<void>;
/** Checks if a key exists in the store */
has?(key: string): Promise<boolean>;
/** Checks if multiple keys exist in the store */
hasMany?(keys: string[]): Promise<boolean[]>;
/** Retrieves multiple values by keys */
getMany?(keys: string[]): Promise<KeyvAnyArray>;
/** Sets multiple entries at once */
setMany?(entries: KeyvAnyArray): Promise<KeyvAny>;
/** Deletes multiple keys at once */
deleteMany?(keys: string[]): Promise<boolean | boolean[]>;
/** Iterates over all entries, optionally filtered by namespace */
iterator?(namespace?: string): AsyncGenerator<KeyvAny>;
/** Disconnects from the store */
disconnect?(): Promise<void>;
/** Subscribe to events (e.g. error events from v5 adapters) */
on?(event: string, listener: (...args: KeyvAnyArray) => void): KeyvAny;
};
/**
* Data structure returned when parsing a prefixed key.
*/
type KeyPrefixData = {
/** The namespace extracted from the key, if present */
namespace?: string;
/** The key without the namespace prefix */
key: string;
};
/**
* A bridge storage adapter for Keyv that wraps any promise-based store.
*
* This class provides a unified interface for using various async stores
* with Keyv, handling namespace prefixing, TTL-based expiration, and batch operations.
* If the underlying store implements optional methods (has, hasMany, getMany, etc.),
* the bridge will delegate to them. Otherwise, it falls back to using primitives.
*
* @example
* ```typescript
* // Using with a promise-based store
* const bridge = new KeyvBridgeAdapter(myAsyncStore, { namespace: 'cache' });
*
* // Using with Keyv
* const keyv = new Keyv({ store: new KeyvBridgeAdapter(myAsyncStore) });
* ```
*/
declare class KeyvBridgeAdapter extends Hookified implements KeyvStorageAdapter {
private _store;
private _namespace?;
private _namespaceSeparator;
private readonly _capabilities;
/**
* Whether the wrapped store manages its own namespace (exposes a `namespace` property).
* When true the bridge propagates its namespace to the store and does not prefix keys,
* so the store's native, namespace-scoped operations (notably `clear()`) are used directly.
*/
private readonly _storeHandlesNamespace;
/**
* Creates a new KeyvBridgeAdapter instance.
* @param store - The underlying promise-based store to bridge
* @param options - Configuration options for the adapter
*/
constructor(store: KeyvBridgeStore, options?: KeyvBridgeAdapterOptions);
/**
* Gets the underlying store instance.
*/
get store(): KeyvBridgeStore;
/**
* Sets the underlying store instance.
*/
set store(store: KeyvBridgeStore);
/**
* Gets the capabilities of the underlying store, with `expires: true` to declare that
* the bridge accepts an absolute `expires` timestamp (which it converts to a ttl for the
* wrapped legacy store).
*/
get capabilities(): KeyvStorageCapability;
/**
* Gets the separator between the namespace and the key. Defaults to `::`.
*/
get namespaceSeparator(): string;
/**
* Sets the separator between the namespace and the key.
*/
set namespaceSeparator(separator: string);
/**
* Gets the current namespace.
*/
get namespace(): string | undefined;
/**
* Sets the namespace. When the wrapped store manages its own namespace, the value is
* propagated to it so its native scoped operations stay in sync.
*/
set namespace(namespace: string | undefined);
/**
* Creates a prefixed key by combining the namespace and key with the separator.
* @param key - The base key
* @param namespace - Optional namespace to prefix the key with
* @returns The prefixed key if namespace is provided, otherwise the original key
*/
getKeyPrefix(key: string, namespace?: string): string;
/**
* Parses a prefixed key to extract the namespace and original key.
* @param key - The prefixed key to parse
* @returns An object containing the namespace (if present) and the original key
*/
getKeyPrefixData(key: string): KeyPrefixData;
/**
* Retrieves a value from the store by key.
* Automatically handles namespace prefixing and TTL expiration.
* @param key - The key to retrieve
* @returns The stored data, or undefined if not found or expired
*/
get<T>(key: string): Promise<KeyvStorageGetResult<T>>;
/**
* Retrieves multiple values from the store by their keys.
* Delegates to the store's native getMany if available.
* @param keys - Array of keys to retrieve
* @returns Array of stored data in the same order as the input keys
*/
getMany<T>(keys: string[]): Promise<Array<KeyvStorageGetResult<T | undefined>>>;
/**
* Stores a value in the store with an optional absolute expiry.
* The wrapped store's `set(key, value, ttl?)` expects a relative duration, so the absolute
* `expires` is converted to a remaining ttl (`undefined` when already expired or absent).
* The value is passed through unchanged — the bridge does not wrap it in an envelope — so
* expiry is enforced by the wrapped legacy store's own ttl handling. (The read-side
* {@link isDataExpired} check only fires when a caller stores a raw `{ value, expires }`
* object directly; when Keyv core drives the bridge the value arrives already encoded.)
* @param key - The key to store the value under
* @param value - The value to store
* @param expires - Optional absolute expiry as Unix ms since epoch
* @returns Always returns true indicating success
*/
set(key: string, value: KeyvAny, expires?: number): Promise<boolean>;
/**
* Stores multiple entries in the store at once.
* Delegates to the store's native setMany if available, otherwise loops over set.
* @param entries - Array of entries containing key, value, and optional absolute `expires`
* @returns One boolean per entry, `false` where the store reported that the write failed
*/
setMany<Value>(entries: KeyvStorageEntry<Value>[]): Promise<boolean[] | undefined>;
/**
* Checks if a key exists in the store and is not expired.
* Delegates to the store's native has if available.
* @param key - The key to check
* @returns True if the key exists and is not expired, false otherwise
*/
has(key: string): Promise<boolean>;
/**
* Checks if multiple keys exist in the store and are not expired.
* Delegates to the store's native hasMany if available.
* @param keys - Array of keys to check
* @returns Array of booleans indicating existence for each key
*/
hasMany(keys: string[]): Promise<boolean[]>;
/**
* Deletes a value from the store by key.
* @param key - The key to delete
* @returns True if the key was deleted, false otherwise
*/
delete(key: string): Promise<boolean>;
/**
* Deletes multiple keys from the store at once.
* Delegates to the store's native deleteMany if available.
* @param keys - Array of keys to delete
* @returns Array of booleans indicating success for each key
*/
deleteMany(keys: string[]): Promise<boolean[]>;
/**
* Clears entries from the store. With no namespace, the whole store is cleared. With a
* namespace, only that namespace's entries are removed: a store that manages its own
* namespace clears them itself, and otherwise the bridge finds them with the store's
* `iterator()`. A store with neither can't tell namespaces apart, so this throws rather
* than call the store's `clear()` and delete every namespace's entries.
* @throws {Error} If a namespace is set and the store neither manages it nor has `iterator()`.
*/
clear(): Promise<void>;
/**
* Creates an async iterator for iterating over store entries.
* If the underlying store does not support iteration, returns an empty generator.
* @returns An async generator yielding [key, value] pairs
*/
iterator<Value>(): AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>;
/**
* Disconnects from the underlying store.
* No-op if the store does not support disconnect.
*/
disconnect(): Promise<void>;
}
//#endregion
//#region src/keyv.d.ts
declare class Keyv<GenericValue = KeyvAny> extends Hookified {
/**
* Keyv Constructor
* @param {KeyvStorageAdapter | KeyvOptions | Map<any, any> | any} store to be provided or just the options
* @param {Omit<KeyvOptions, 'store'>} [options] if you provide the store you can then provide the Keyv Options
*/
constructor(store?: KeyvStorageAdapter | KeyvOptions | KeyvMapAny, options?: Omit<KeyvOptions, "store">);
/**
* Keyv Constructor
* @param {KeyvOptions} options to be provided
*/
constructor(options?: KeyvOptions);
/**
* Stats manager for tracking cache operation metrics (hits, misses, sets, deletes, errors).
* @default this is disabled.
*/
private _stats;
/**
* Default time to live in milliseconds. Can be overridden per-key via {@link set}.
*/
private _ttl?;
/**
* Key prefix namespace used to isolate keys across different Keyv instances sharing the same store.
*/
private _namespace?;
/**
* The underlying storage adapter. Defaults to an in-memory {@link Map}.
*/
private _store;
/**
* Pluggable serialization adapter with `stringify` and `parse` methods.
* When `undefined`, the built-in {@link KeyvJsonSerializer} is used.
*/
private _serialization;
/**
* Pluggable compression adapter with `compress` and `decompress` methods.
*/
private _compression;
/**
* Pluggable encryption adapter with `encrypt` and `decrypt` methods.
*/
private _encryption;
/**
* Sanitization handler for keys and namespaces. By default it is disabled.
*/
private _sanitize;
/**
* When true, Keyv checks expiry at its layer on get/getMany/has/hasMany.
* Defaults to true so reads stay millisecond-precise even on adapters whose
* native expiry is coarse or lazily swept (e.g. Memcached, DynamoDB).
*/
private _checkExpired;
/**
* Get the current storage adapter.
* @returns {KeyvStorageAdapter} The current storage adapter.
*/
get store(): KeyvStorageAdapter;
/**
* Set the storage adapter.
* @param {KeyvStorageAdapter | Map<any, any> | any} store The storage adapter to set.
*/
set store(store: KeyvStorageAdapter | KeyvMapAny);
/**
* Get the current compression adapter.
* @returns {KeyvCompressionAdapter | undefined} The current compression adapter.
*/
get compression(): KeyvCompressionAdapter | undefined;
/**
* Set the compression adapter.
* @param {KeyvCompressionAdapter | undefined} compress The compression adapter to set.
*/
set compression(compress: KeyvCompressionAdapter | undefined);
/**
* Get the current encryption adapter.
* @returns {KeyvEncryptionAdapter | undefined} The current encryption adapter.
*/
get encryption(): KeyvEncryptionAdapter | undefined;
/**
* Set the encryption adapter.
* @param {KeyvEncryptionAdapter | undefined} encryption The encryption adapter to set.
*/
set encryption(encryption: KeyvEncryptionAdapter | undefined);
/**
* Get the current namespace. When Keyv has no namespace of its own, this is the namespace
* configured on the storage adapter.
* @returns {string | undefined} The current namespace.
*/
get namespace(): string | undefined;
/**
* Set the current namespace.
* @param {string | undefined} namespace The namespace to set.
*/
set namespace(namespace: string | undefined);
/**
* Get the current TTL.
* @returns {number} The current TTL in milliseconds.
*/
get ttl(): number | undefined;
/**
* Set the current TTL.
* @param {number} ttl The TTL to set in milliseconds.
*/
set ttl(ttl: number | undefined);
/**
* Get the current serialization adapter. If `undefined`, serialization is not enabled.
* @returns {KeyvSerializationAdapter | undefined} The current serialization adapter.
*/
get serialization(): KeyvSerializationAdapter | undefined;
/**
* Set the current serialization adapter. Pass a `KeyvSerializationAdapter` to enable
* custom serialization, or `undefined` to disable serialization entirely.
* @param {KeyvSerializationAdapter | undefined} serialization The serialization adapter to set.
*/
set serialization(serialization: KeyvSerializationAdapter | false | undefined);
/**
* Get the current sanitize adapter. Sanitization is disabled by default. To
* enable it `sanitize.keys` or `sanitize.namespace` to true or set KeyvSanitizePatterns
* to each.
* @returns {KeyvSanitizeAdapter} The current sanitize adapter.
*/
get sanitize(): KeyvSanitizeAdapter;
/**
* Set the sanitize adapter directly and will run sanitization on namespace, including a
* namespace kept from the storage adapter, and apply the result to the adapter.
* @param {KeyvSanitizeAdapter} value The sanitize adapter to use.
*/
set sanitize(value: KeyvSanitizeAdapter);
/**
* Get the stats. This is just for this instance
* @returns {KeyvStats} The current stats.
*/
get stats(): KeyvStats;
/**
* Set the stats. When setting a new instance it will unsubscribe the old listeners
* and subscribe the new instance.
* @param {KeyvStats} stats The stats instance to set.
*/
set stats(stats: KeyvStats);
/**
* Get whether Keyv checks expiry at its own layer on get/getMany/has/hasMany.
* When true (default), expired entries are filtered (and deleted) by Keyv regardless of
* the adapter. Set to false to trust the storage adapter to handle expiry on its own.
* @returns {boolean} `true` if Keyv checks expiry at its layer.
*/
get checkExpired(): boolean;
/**
* Resolves a store to a fully-compliant KeyvStorageAdapter:
* 1. If the store declares the v6 `capabilities.expires` contract, use it directly (this takes
* precedence over structural detection, so a full adapter whose async methods aren't written
* with the `async` keyword is not mis-bridged).
* 2. If the store implements the full async storage interface (but doesn't declare `expires`),
* treat it as a legacy relative-`ttl` adapter and wrap it in KeyvBridgeAdapter.
* 3. If the store is map-like (get/set/delete/has that aren't native `async` functions), wrap it
* in KeyvMemoryAdapter. A store other than a Map is first asked once, through `has`, whether
* it returns promises; if it does, wrap it in KeyvBridgeAdapter instead.
* 4. If the store has async get/set/delete/clear, wrap it in KeyvBridgeAdapter.
* 5. Otherwise, emit an error and fall back to a default in-memory KeyvMemoryAdapter.
*
* NOTE: this is used for internal but provided public for custom adapter testing
* @param {unknown} store The store to resolve.
* @returns {KeyvStorageAdapter} A fully-compliant storage adapter.
*/
resolveStore(store: KeyvAny): KeyvStorageAdapter;
/**
* Sets the storage adapter by resolving it via {@link resolveStore}, then wires up
* error forwarding and namespace propagation. Keyv's namespace, when set, is applied to the
* adapter. Without one, the adapter keeps the namespace it was configured with.
* @param {KeyvStorageAdapter | Map<any, any> | any} store The storage adapter to set.
*/
setStore(store: KeyvStorageAdapter | KeyvMapAny): void;
/**
* Sets the TTL, treating zero and negative values as undefined (no TTL).
* @param {number | undefined} ttl The TTL to set in milliseconds.
*/
setTtl(ttl?: number): void;
/**
* Get the value of a key. If an array of keys is passed in it will return an array of values
* delegating to {@link getMany}.
* @param {string | string[]} key passing in a single key or multiple as an array
* @returns {Promise<Value | undefined | Array<Value | undefined>>} the value of the key, or
* `undefined` if the key does not exist or is expired. When an array of keys is passed in it
* returns an array of values in the same order (with `undefined` for missing keys).
*/
get<Value = GenericValue>(key: string): Promise<Value | undefined>;
get<Value = GenericValue>(key: string[]): Promise<Array<Value | undefined>>;
/**
* Reads many keys from the store, preferring its native `getMany` and falling back to parallel
* single `get`s when an adapter does not implement it. A directly-used v6 adapter is not
* structurally required to provide `getMany` (the bridge and memory adapters always do), so
* this keeps `getMany`/`getManyRaw` working regardless of the resolved adapter.
* @param keys - the keys to read
* @returns the raw store results in the same order as `keys`
*/
private storeGetMany;
/**
* Runs a batch operation without the keys or entries whose key is empty, then returns its results
* in the original order with `fallback` for each empty key. As with the single-key methods, an
* empty key never reaches hooks, telemetry or the store.
* @param items - the keys or entries of the batch
* @param fallback - the result for an item whose key is empty
* @param run - runs the batch operation on the items whose key is not empty
* @returns one result per item, in the same order as `items`
*/
private skipEmptyKeys;
/**
* Get many values for an array of keys.
* @param {string[]} keys the keys to get
* @returns {Promise<Array<Value | undefined>>} an array of values in the same order as the
* keys, with `undefined` for keys that do not exist or are expired.
*/
getMany<Value = GenericValue>(keys: string[]): Promise<Array<Value | undefined>>;
/**
* Get the raw value of a key. This is the replacement for setting raw to true in the get() method.
* @param {string} key the key to get
* @returns {Promise<KeyvStorageGetResult<Value>>} will return a KeyvStorageGetResult<Value> or undefined
* if the key does not exist or is expired.
*/
getRaw<Value = GenericValue>(key: string): Promise<KeyvStorageGetResult<Value>>;
/**
* Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method.
* @param {string[]} keys the keys to get
* @returns {Promise<Array<KeyvStorageGetResult<Value>>>} will return an array of KeyvStorageGetResult<Value> or undefined if the key does not exist or is expired.
*/
getManyRaw<Value = GenericValue>(keys: string[]): Promise<Array<KeyvStorageGetResult<Value>>>;
/**
* Set an item to the store
* @param {string} key the key to use
* @param {Value} value the value of the key
* @param {number} [ttl] time to live in milliseconds. Overrides the instance-level `ttl`.
* @returns {Promise<boolean>} `true` if it was set successfully, `false` on failure.
*/
set<Value = GenericValue>(key: string, value: Value, ttl?: number): Promise<boolean>;
/**
* Set many items to the store
* @param {Array<KeyvEntry<Value>>} entries the entries to set
* @returns {Promise<boolean[]>} an array of booleans, one per entry: `true` if set successfully, `false` on failure.
*/
setMany<Value = GenericValue>(entries: KeyvEntry<Value>[]): Promise<boolean[]>;
/**
* Set a raw value to the store without wrapping or serialization. This is the write-side counterpart to getRaw().
* The value should be a KeyvValue object with { value, expires? }. If you need TTL-based expiration,
* set `expires` on the value directly (e.g. `{ value: 'bar', expires: Date.now() + 60000 }`).
* The store-level expiry is derived automatically from `value.expires`, rounded up to a whole millisecond
* (a non-finite `expires` means no store-level expiry).
* @param {string} key the key to set
* @param {KeyvValue<Value>} value the raw value envelope to store
* @returns {Promise<boolean>} `true` if it was set successfully, `false` on failure.
*/
setRaw<Value = GenericValue>(key: string, value: KeyvValue<Value>): Promise<boolean>;
/**
* Set many raw values to the store without wrapping or serialization. This is the write-side counterpart to getManyRaw().
* Each entry's value should be a KeyvValue object with { value, expires? }. If you need TTL-based expiration,
* set `expires` on each value directly. The store-level expiry is derived automatically from `value.expires`,
* rounded up to a whole millisecond (a non-finite `expires` means no store-level expiry).
* @param {KeyvEntry<KeyvValue<Value>>[]} entries the raw entries to set
* @returns {Promise<boolean[]>} an array of booleans, one per entry: `true` if set successfully, `false` on failure.
*/
setManyRaw<Value = GenericValue>(entries: KeyvEntry<KeyvValue<Value>>[]): Promise<boolean[]>;
/**
* Delete an entry. If an array of keys is passed in it will delete many entries
* delegating to {@link deleteMany}.
* @param {string} key the key to be deleted
* @returns {Promise<boolean>} `true` if the item was deleted, `false` if there was an error.
*/
delete(key: string): Promise<boolean>;
/**
* Delete multiple entries
* @param {string[]} keys the keys to be deleted
* @returns {Promise<boolean[]>} an array of booleans indicating success for each key.
*/
delete(keys: string[]): Promise<boolean[]>;
/**
* Delete many items from the store
* @param {string[]} keys the keys to be deleted
* @returns {Promise<boolean[]>} an array of booleans indicating success for each key.
*/
deleteMany(keys: string[]): Promise<boolean[]>;
/**
* Check if a key exists. If an array of keys is passed in it will check many keys
* delegating to {@link hasMany}.
* @param {string | string[]} key the key (or keys) to check
* @returns {Promise<boolean | boolean[]>} `true` if the key exists, `false` if not. When an
* array of keys is passed in it returns an array of booleans in the same order.
*/
has(key: string[]): Promise<boolean[]>;
has(key: string): Promise<boolean>;
/**
* Check if many keys exist
* @param {string[]} keys the keys to check
* @returns {Promise<boolean[]>} an array of booleans in the same order as the keys, `true` if the key exists.
*/
hasMany(keys: string[]): Promise<boolean[]>;
/**
* Clear the store. If a namespace is set only entries in that namespace are removed. When the
* store can't limit the removal to the namespace, nothing is removed and `error` is emitted.
* Emits a `clear` event.
* @returns {Promise<void>} resolves once the entries have been cleared.
*/
clear(): Promise<void>;
/**
* Will disconnect the store. This is only available if the store has a disconnect method
* @returns {Promise<void>}
*/
disconnect(): Promise<void>;
/**
* Iterate over all key-value pairs in the store. Automatically deserializes values,
* filters out expired entries, and deletes them from the store.
* @returns {AsyncGenerator<Array<string | unknown>, void>} An async generator yielding `[key, value]` pairs.
*/
iterator(): AsyncGenerator<[string, KeyvAny], void>;
/**
* Encodes a value for storage. Pipeline: serialize → compress → encrypt.
* If serialization is not configured, returns the data as-is, skipping compression. With an
* encryption adapter set, it throws instead, since the value can't be encrypted and storing it
* unencrypted would defeat the adapter.
* @param {KeyvValue<T>} data The value envelope to encode.
* @returns {Promise<unknown>} The encoded value.
* @throws {Error} If an encryption adapter is set while serialization is disabled.
*/
encode<T>(data: KeyvValue<T>): Promise<unknown>;
/**
* Decodes a stored value. Pipeline: decrypt → decompress → deserialize (reverse of encode).
* If serialization is not configured, returns the data as a KeyvValue or undefined for strings.
* @param {unknown} data The raw data from the store.
* @returns {Promise<KeyvValue<T> | undefined>} The decoded value envelope, or undefined on failure.
*/
decode<T>(data: unknown): Promise<KeyvValue<T> | undefined>;
/**
* Deserializes raw data from the store, checks for expiry, and deletes expired keys.
* Accepts a single key/value or arrays. Returns an array of decoded KeyvValue objects
* (undefined for missing or expired entries).
* @param {string | string[]} keys the key(s) to process
* @param {unknown | unknown[]} rawData the raw data from the store
* @returns {Promise<Array<KeyvValue<Value> | undefined>>} decoded values with expired entries removed
*/
decodeWithExpire<Value>(keys: string | string[], rawData: unknown | unknown[]): Promise<Array<KeyvValue<Value> | undefined>>;
/**
* Fires a hook under its new name and also under the deprecated alias (if any),
* so that integrations still subscribing to the old PRE_/POST_ names keep working.
*/
private hookWithDeprecated;
/**
* Emit a telemetry event for cache operations.
* @param {KeyvEvents} event the telemetry event type
* @param {string | string[]} [key] the cache key or keys (emits one event per key)
*/
private emitTelemetry;
/**
* Merges the overloaded constructor arguments into a single KeyvOptions object.
*/
private static resolveOptions;
/**
* Initializes the serialization adapter from options.
*/
private initSerialization;
/**
* Initializes the sanitization handler from options.
*/
private initSanitize;
/**
* Initializes the stats manager from options.
*/
private initStats;
/**
* Initializes the namespace, applying sanitization if enabled.
*/
private initNamespace;
/**
* Sanitizes a namespace. When sanitizing leaves nothing, it returns {@link emptiedNamespace} so
* the instance keeps a namespace of its own.
*/
private cleanNamespace;
/**
* Sanitizes the namespace kept from the storage adapter when Keyv has none of its own.
*/
private sanitizeStoreNamespace;
}
//#endregion
//#region src/adapters/memory.d.ts
/**
* Configuration options for KeyvMemoryAdapter.
*/
type KeyvMemoryAdapterOptions = {
/**
* The namespace to use for keys.
* When set, all keys will be prefixed with the namespace followed by the namespace separator.
*/
namespace?: string;
/**
* The separator between the namespace and the key. Defaults to `::`.
*/
namespaceSeparator?: string;
};
/**
* Interface for a Map-like store that can be used with KeyvMemoryAdapter.
* This allows any object implementing these methods to be used as the underlying storage.
* Compatible with Map, QuickLRU, lru.min, and other LRU cache implementations.
*/
type KeyvMapType = {
/** Retrieves a value by key */
get: (key: string) => KeyvAny;
/** Sets a value with a key. Additional parameters (like TTL) vary by implementation. */
set: (key: string, value: KeyvAny, ...args: KeyvAnyArray) => KeyvAny;
/** Deletes a key from the store */
delete: (key: string) => boolean;
/** Clears all entries from the store */
clear: () => void;
/** Checks if a key exists in the store */
has: (key: string) => boolean;
};
/**
* An in-memory storage adapter for Keyv that wraps any Map-like object.
*
* This class provides a unified interface for using various Map-like stores
* with Keyv, handling namespace prefixing, TTL-based expiration, and batch operations.
*
* @example
* ```typescript
* // Using with a standard Map
* const store = new KeyvMemoryAdapter(new Map(), { namespace: 'cache' });
*
* // Using with a custom store
* const customStore = new KeyvMemoryAdapter(myCustomMapLikeStore, {
* namespace: 'tenant-123',
* namespaceSeparator: '::'
* });
* ```
*/
declare class KeyvMemoryAdapter extends Hookified implements KeyvStorageAdapter {
private _store;
private _namespace?;
private _namespaceSeparator;
private readonly _capabilities;
/**
* Creates a new KeyvMemoryAdapter instance.
* @param store - The underlying Map or Map-like object to use for storage
* @param options - Configuration options for the store
*/
constructor(store: KeyvMapType, options?: KeyvMemoryAdapterOptions);
/**
* Gets the capabilities of the underlying store, with `expires: true` to declare that
* this adapter accepts an absolute `expires` timestamp (the v6 storage contract).
*/
get capabilities(): KeyvStorageCapability;
/**
* Gets the underlying store instance.
*/
get store(): KeyvMapType;
/**
* Sets the underlying store instance.
*/
set store(store: KeyvMapType);
/**
* Gets the separator between the namespace and the key. Defaults to `::`.
*/
get namespaceSeparator(): string;
/**
* Sets the separator between the namespace and the key.
*/
set namespaceSeparator(separator: string);
/**
* Gets the current namespace.
*/
get namespace(): string | undefined;
/**
* Sets the namespace.
*/
set namespace(namespace: string | undefined);
/**
* Creates a prefixed key by combining the namespace and key with the separator.
* @param key - The base key
* @param namespace - Optional namespace to prefix the key with
* @returns The prefixed key if namespace is provided, otherwise the original key
*/
getKeyPrefix(key: string, namespace?: string): string;
/**
* Parses a prefixed key to extract the namespace and original key.
* @param key - The prefixed key to parse
* @returns An object containing the namespace (if present) and the original key
*/
getKeyPrefixData(key: string): {
namespace: string;
key: string;
} | {
namespace?: undefined;
key: string;
};
/**
* Retrieves a value from the store by key.
* Automatically handles namespace prefixing and TTL expiration.
* @param key - The key to retrieve
* @returns The stored data, or undefined if not found or expired
*/
get<T>(key: string): Promise<KeyvStorageGetResult<T>>;
/**
* Stores a value in the store with an optional absolute expiry.
* @param key - The key to store the value under
* @param value - The value to store
* @param expires - Optional absolute expiry as Unix ms since epoch
* @returns Always returns true indicating success
*/
set(key: string, value: KeyvAny, expires?: number): Promise<boolean>;
/**
* Stores multiple entries in the store at once.
* @param entries - Array of entries containing key, value, and optional absolute `expires`
*/
setMany<Value>(entries: KeyvStorageEntry<Value>[]): Promise<boolean[] | undefined>;
/**
* Deletes a value from the store by key.
* @param key - The key to delete
* @returns True if the key was deleted, false otherwise
*/
delete(key: string): Promise<boolean>;
/**
* Clears entries from the store. With no namespace, the whole store is cleared. With a
* namespace, only that namespace's entries are removed, found through the store's `keys()`.
* A store without `keys()` can't tell namespaces apart, so this throws rather than call the
* store's `clear()` and delete every namespace's entries.
* @throws {Error} If a namespace is set and the store has no `keys()`.
*/
clear(): Promise<void>;
/**
* Checks if a key exists in the store and is not expired.
* @param key - The key to check
* @returns True if the key exists and is not expired, false otherwise
*/
has(key: string): Promise<boolean>;
/**
* Checks if multiple keys exist in the store and are not expired.
* @param keys - Array of keys to check
* @returns Array of booleans indicating existence for each key
*/
hasMany(keys: string[]): Promise<boolean[]>;
/**
* Retrieves multiple values from the store by their keys.
* @param keys - Array of keys to retrieve
* @returns Array of stored data in the same order as the input keys
*/
getMany<T>(keys: string[]): Promise<Array<KeyvStorageGetResult<T | undefined>>>;
/**
* Deletes multiple keys from the store at once.
* @param keys - Array of keys to delete
* @returns Array of booleans indicating success for each key
*/
deleteMany(keys: string[]): Promise<boolean[]>;
/**
* Creates an async iterator for iterating over store entries.
* If the underlying store does not support iteration, returns an empty generator.
* @returns {AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>} An async generator yielding [key, value] pairs
*/
iterator<Value>(): AsyncGenerator<Array<string | Awaited<Value> | undefined>, void>;
/**
* No-op disconnect for in-memory stores.
*/
disconnect(): Promise<void>;
}
/**
* Creates a Keyv instance with a memory adapter optimized for in-memory storage.
*
* This factory function configures Keyv to bypass serialization/deserialization
* and key prefixing, resulting in faster performance for in-memory use cases
* where data doesn't need to be persisted or transmitted.
*
* @param store - The underlying Map or Map-like object to use for storage
* @param options - Configuration options for the memory adapter
* @returns A configured Keyv instance with optimized settings for in-memory storage
*
* @example
* ```typescript
* // Create a simple in-memory cache
* const cache = createKeyv(new Map());
* await cache.set('user:1', { name: 'John' });
*
* // Create with namespace for multi-tenant scenarios
* const tenantCache = createKeyv(new Map(), {
* namespace: 'tenant-123',
* namespaceSeparator: '::'
* });
* ```
*/
declare function createKeyv(store: KeyvMapType, options?: KeyvMemoryAdapterOptions): Keyv<any>;
//#endregion
//#region src/json-serializer.d.ts
declare class KeyvJsonSerializer implements KeyvSerializationAdapter {
stringify(object: unknown): string;
parse<T>(data: string): T;
}
declare const jsonSerializer: KeyvJsonSerializer;
//#endregion
export { type DeserializedData, Keyv, Keyv as default, type KeyvAny, type KeyvAnyArray, KeyvBridgeAdapter, type KeyvBridgeAdapterOptions, type KeyvBridgeStore, type KeyvCapability, type KeyvCompression, type KeyvCompressionAdapter, type KeyvCompressionCapability, type KeyvCompressionMethods, type KeyvEncryptionAdapter, type KeyvEncryptionCapability, type KeyvEncryptionMethods, type KeyvEntry, KeyvEvents, KeyvHooks, KeyvJsonSerializer, type KeyvMapAny, type KeyvMapType, KeyvMemoryAdapter, type KeyvMemoryAdapterOptions, type KeyvMethods, type KeyvOptions, type KeyvProperties, KeyvSanitize, type KeyvSanitizeAdapter, type KeyvSanitizeOptions, type KeyvSanitizePatterns, type KeyvSerializationAdapter, type KeyvSerializationCapability, type KeyvSerializationMethods, KeyvStats, type KeyvStatsOptions, type KeyvStorageAdapter, type KeyvStorageCapability, type KeyvStorageEntry, type KeyvStorageGetResult, type KeyvStorageMethod, type KeyvStorageMethods, type KeyvStoreAdapter, type KeyvTelemetryEvent, type KeyvValue, type MethodType, createKeyv, detectKeyv, detectKeyvCompression, detectKeyvEncryption, detectKeyvSerialization, detectKeyvStorage, jsonSerializer, keyvStorageCapability };