Simple key-value storage with support for multiple backends
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
High-performance batch operations for working with multiple keys simultaneously, with optimizations for storage adapters that support native batch operations.
Retrieves multiple values simultaneously with better performance than individual get operations.
/**
* Get multiple values by keys array
* @param keys - Array of keys to retrieve
* @param options - Options including raw data access
* @returns Promise resolving to array of values in same order as keys
*/
async getMany<Value = GenericValue>(keys: string[], options?: {raw?: false}): Promise<Array<StoredDataNoRaw<Value>>>;
async getMany<Value = GenericValue>(keys: string[], options?: {raw?: true}): Promise<Array<StoredDataRaw<Value>>>;Usage Examples:
const keyv = new Keyv();
// Setup test data
await keyv.set('user:1', { name: 'Alice', age: 30 });
await keyv.set('user:2', { name: 'Bob', age: 25 });
await keyv.set('user:3', { name: 'Charlie', age: 35 });
// Get multiple users
const users = await keyv.getMany(['user:1', 'user:2', 'user:4']);
// [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }, undefined]
// Get raw data for multiple keys
const rawUsers = await keyv.getMany(['user:1', 'user:2'], { raw: true });
// [{ value: { name: 'Alice', age: 30 }, expires: undefined }, ...]
// Type safety with generics
interface User { name: string; age: number; }
const typedUsers = await keyv.getMany<User>(['user:1', 'user:2']);
// Array<User | undefined>
// Empty array handling
const empty = await keyv.getMany([]); // []Sets multiple key-value pairs simultaneously with optional individual TTL values.
/**
* Set multiple key-value pairs
* @param entries - Array of entries to set
* @returns Promise resolving to array of success booleans
*/
async setMany<Value = GenericValue>(entries: KeyvEntry[]): Promise<boolean[]>;
interface KeyvEntry {
/** Key to set */
key: string;
/** Value to set */
value: any;
/** Time to live in milliseconds (optional) */
ttl?: number;
}Usage Examples:
const keyv = new Keyv();
// Set multiple entries
const results = await keyv.setMany([
{ key: 'user:1', value: { name: 'Alice', age: 30 } },
{ key: 'user:2', value: { name: 'Bob', age: 25 } },
{ key: 'user:3', value: { name: 'Charlie', age: 35 } }
]);
// [true, true, true]
// Set with individual TTL values
await keyv.setMany([
{ key: 'session:1', value: 'abc123', ttl: 60000 }, // 1 minute
{ key: 'session:2', value: 'def456', ttl: 120000 }, // 2 minutes
{ key: 'permanent', value: 'data' } // no TTL, permanent
]);
// Mixed data types
await keyv.setMany([
{ key: 'string', value: 'hello' },
{ key: 'number', value: 42 },
{ key: 'object', value: { x: 1, y: 2 } },
{ key: 'array', value: [1, 2, 3] },
{ key: 'buffer', value: Buffer.from('data') }
]);
// Empty array handling
const emptyResults = await keyv.setMany([]); // []Deletes multiple keys simultaneously.
/**
* Delete multiple keys
* @param keys - Array of keys to delete
* @returns Promise resolving to true if operation succeeded
*/
async deleteMany(keys: string[]): Promise<boolean>;Usage Examples:
const keyv = new Keyv();
// Setup test data
await keyv.set('temp:1', 'data1');
await keyv.set('temp:2', 'data2');
await keyv.set('temp:3', 'data3');
// Delete multiple keys
const success = await keyv.deleteMany(['temp:1', 'temp:2', 'nonexistent']);
// true (returns true if operation completed, regardless of individual key existence)
// Verify deletion
const remaining = await keyv.getMany(['temp:1', 'temp:2', 'temp:3']);
// [undefined, undefined, 'data3']
// Delete all remaining
await keyv.deleteMany(['temp:3']); // true
// Empty array handling
const emptyResult = await keyv.deleteMany([]); // trueChecks existence of multiple keys simultaneously.
/**
* Check if multiple keys exist and are not expired
* @param keys - Array of keys to check
* @returns Promise resolving to array of existence booleans
*/
async hasMany(keys: string[]): Promise<boolean[]>;Usage Examples:
const keyv = new Keyv();
// Setup test data
await keyv.set('existing:1', 'value1');
await keyv.set('existing:2', 'value2');
await keyv.set('expiring', 'value', 1000); // expires in 1 second
// Check multiple keys
const exists = await keyv.hasMany(['existing:1', 'existing:2', 'nonexistent']);
// [true, true, false]
// Check with expired keys (after waiting > 1 second)
// const existsLater = await keyv.hasMany(['existing:1', 'expiring']);
// [true, false] - expired key returns false
// Empty array handling
const emptyExists = await keyv.hasMany([]); // []
// Type consistency
interface User { name: string; }
const keyvTyped = new Keyv<User>();
await keyvTyped.set('user:1', { name: 'Alice' });
const typedExists = await keyvTyped.hasMany(['user:1', 'user:2']);
// [true, false]Batch operations provide significant performance benefits:
Example with Redis adapter:
import Keyv from "keyv";
import KeyvRedis from "@keyv/redis";
const keyv = new Keyv(new KeyvRedis('redis://localhost:6379'));
// This uses Redis MGET internally for optimal performance
const values = await keyv.getMany(['key1', 'key2', 'key3']);
// This uses Redis MSET internally
await keyv.setMany([
{ key: 'key1', value: 'value1' },
{ key: 'key2', value: 'value2' },
{ key: 'key3', value: 'value3' }
]);