You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

keyv

Package Overview
Dependencies
Maintainers
2
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

keyv - npm Package Compare versions

Comparing version
5.5.0
to
5.5.1
+98
-35
dist/index.cjs

@@ -52,3 +52,5 @@ "use strict";

if (listeners.length >= this._maxListeners) {
console.warn(`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`);
console.warn(
`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`
);
}

@@ -81,2 +83,3 @@ listeners.push(listener);

// Emit an event
// biome-ignore lint/suspicious/noExplicitAny: type format
emit(event, ...arguments_) {

@@ -136,2 +139,3 @@ const listeners = this._eventListeners.get(event);

// Triggers all handlers for a specific event with provided data
// biome-ignore lint/suspicious/noExplicitAny: type format
trigger(event, data) {

@@ -144,3 +148,8 @@ const eventHandlers = this._hookHandlers.get(event);

} catch (error) {
this.emit("error", new Error(`Error in hook handler for event "${event}": ${error.message}`));
this.emit(
"error",
new Error(
`Error in hook handler for event "${event}": ${error.message}`
)
);
}

@@ -252,2 +261,3 @@ }

*/
// biome-ignore lint/suspicious/noExplicitAny: type format
_store = /* @__PURE__ */ new Map();

@@ -301,5 +311,10 @@ _serialize = import_serialize.defaultSerialize;

if (typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map) {
this.iterator = this.generateIterator(this._store);
this.iterator = this.generateIterator(
this._store
);
} else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) {
this.iterator = this.generateIterator(this._store.iterator.bind(this._store));
this.iterator = this.generateIterator(
// biome-ignore lint/style/noNonNullAssertion: need to fix
this._store.iterator.bind(this._store)
);
}

@@ -323,2 +338,3 @@ }

*/
// biome-ignore lint/suspicious/noExplicitAny: type format
get store() {

@@ -331,2 +347,3 @@ return this._store;

*/
// biome-ignore lint/suspicious/noExplicitAny: type format
set store(store) {

@@ -343,5 +360,7 @@ if (this._isValidStorageAdapter(store)) {

if (typeof store[Symbol.iterator] === "function" && store instanceof Map) {
this.iterator = this.generateIterator(store);
this.iterator = this.generateIterator(
store
);
} else if ("iterator" in store && store.opts && this._checkIterableAdapter()) {
this.iterator = this.generateIterator(store.iterator.bind(store));
this.iterator = this.generateIterator(store.iterator?.bind(store));
}

@@ -478,3 +497,5 @@ } else {

_checkIterableAdapter() {
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some((element) => this._store.opts.url.includes(element));
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
(element) => this._store.opts.url.includes(element)
);
}

@@ -505,2 +526,3 @@ _getKeyPrefix(key) {

}
// biome-ignore lint/suspicious/noExplicitAny: type format
_isValidStorageAdapter(store) {

@@ -540,3 +562,6 @@ return store instanceof Map || typeof store.get === "function" && typeof store.set === "function" && typeof store.delete === "function" && typeof store.clear === "function";

}
this.hooks.trigger("postGet" /* POST_GET */, { key: keyPrefixed, value: deserializedData });
this.hooks.trigger("postGet" /* POST_GET */, {
key: keyPrefixed,
value: deserializedData
});
this.stats.hit();

@@ -564,3 +589,6 @@ return options?.raw ? deserializedData : deserializedData.value;

const deserializedRows = await Promise.allSettled(promises);
const result2 = deserializedRows.map((row) => row.value);
const result2 = deserializedRows.map(
// biome-ignore lint/suspicious/noExplicitAny: type format
(row) => row.value
);
this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);

@@ -616,3 +644,4 @@ if (result2.length > 0) {

const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData;
if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && deserializedData.expires < Date.now()) {
if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && // biome-ignore lint/style/noNonNullAssertion: need to fix
deserializedData.expires < Date.now()) {
this.stats.miss();

@@ -623,3 +652,6 @@ await this.delete(key);

this.stats.hit();
this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, { key: keyPrefixed, value: deserializedData });
this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
key: keyPrefixed,
value: deserializedData
});
return deserializedData;

@@ -631,3 +663,3 @@ }

* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
*/
*/
async getManyRaw(keys) {

@@ -637,5 +669,10 @@ const { store } = this.opts;

if (keys.length === 0) {
const result2 = Array.from({ length: keys.length }).fill(void 0);
const result2 = Array.from({ length: keys.length }).fill(
void 0
);
this.stats.misses += keys.length;
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, { keys: keyPrefixed, values: result2 });
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
keys: keyPrefixed,
values: result2
});
return result2;

@@ -653,3 +690,6 @@ }

const deserializedRows = await Promise.allSettled(promises);
result = deserializedRows.map((row) => row.value);
result = deserializedRows.map(
// biome-ignore lint/suspicious/noExplicitAny: type format
(row) => row.value
);
} else {

@@ -677,3 +717,6 @@ const rawData = await store.getMany(keyPrefixed);

this.stats.hitsOrMisses(result);
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, { keys: keyPrefixed, values: result });
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
keys: keyPrefixed,
values: result
});
return result;

@@ -717,3 +760,7 @@ }

}
this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value: serializedValue, ttl });
this.hooks.trigger("postSet" /* POST_SET */, {
key: keyPrefixed,
value: serializedValue,
ttl
});
this.stats.set();

@@ -727,2 +774,3 @@ return result;

*/
// biome-ignore lint/correctness/noUnusedVariables: type format
async setMany(entries) {

@@ -739,16 +787,18 @@ let results = [];

} else {
const serializedEntries = await Promise.all(entries.map(async ({ key, value, ttl }) => {
ttl ??= this._ttl;
if (ttl === 0) {
ttl = void 0;
}
const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
if (typeof value === "symbol") {
this.emit("error", "symbol cannot be serialized");
throw new Error("symbol cannot be serialized");
}
const formattedValue = { value, expires };
const serializedValue = await this.serializeData(formattedValue);
return { key, value: serializedValue, ttl };
}));
const serializedEntries = await Promise.all(
entries.map(async ({ key, value, ttl }) => {
ttl ??= this._ttl;
if (ttl === 0) {
ttl = void 0;
}
const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
if (typeof value === "symbol") {
this.emit("error", "symbol cannot be serialized");
throw new Error("symbol cannot be serialized");
}
const formattedValue = { value, expires };
const serializedValue = await this.serializeData(formattedValue);
return { key, value: serializedValue, ttl };
})
);
results = await this._store.setMany(serializedEntries);

@@ -790,3 +840,6 @@ }

}
this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: result });
this.hooks.trigger("postDelete" /* POST_DELETE */, {
key: keyPrefixed,
value: result
});
this.stats.delete();

@@ -811,3 +864,6 @@ return result;

const returnResult = results.every(Boolean);
this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: returnResult });
this.hooks.trigger("postDelete" /* POST_DELETE */, {
key: keyPrefixed,
value: returnResult
});
return returnResult;

@@ -896,2 +952,3 @@ } catch (error) {

}
// biome-ignore lint/suspicious/noExplicitAny: type format
emit(event, ...arguments_) {

@@ -908,3 +965,6 @@ if (event === "error" && !this.opts.emitErrors) {

if (this._compression?.compress) {
return this._serialize({ value: await this._compression.compress(data.value), expires: data.expires });
return this._serialize({
value: await this._compression.compress(data.value),
expires: data.expires
});
}

@@ -919,3 +979,6 @@ return this._serialize(data);

const result = await this._deserialize(data);
return { value: await this._compression.decompress(result?.value), expires: result?.expires };
return {
value: await this._compression.decompress(result?.value),
expires: result?.expires
};
}

@@ -922,0 +985,0 @@ if (typeof data === "string") {

@@ -113,3 +113,3 @@ type EventListener = (...arguments_: any[]) => void;

* @default true
*/
*/
emitErrors?: boolean;

@@ -119,3 +119,3 @@ /**

* @default 'keyv'
*/
*/
namespace?: string;

@@ -130,3 +130,3 @@ /**

* @default defaultDeserialize using JSON.parse
*/
*/
deserialize?: Deserialize;

@@ -164,4 +164,4 @@ /**

};
type KeyvOptions_ = Omit<KeyvOptions, 'store'> & {
store: KeyvStoreAdapter | Map<any, any> & KeyvStoreAdapter;
type KeyvOptions_ = Omit<KeyvOptions, "store"> & {
store: KeyvStoreAdapter | (Map<any, any> & KeyvStoreAdapter);
};

@@ -196,3 +196,3 @@ type IteratorFunction = (argument: any) => AsyncGenerator<any, void>;

*/
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, 'store'>);
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, "store">);
/**

@@ -327,3 +327,3 @@ * Keyv Constructor

* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
*/
*/
getManyRaw<Value = GenericValue>(keys: string[]): Promise<Array<StoredDataRaw<Value>>>;

@@ -330,0 +330,0 @@ /**

@@ -113,3 +113,3 @@ type EventListener = (...arguments_: any[]) => void;

* @default true
*/
*/
emitErrors?: boolean;

@@ -119,3 +119,3 @@ /**

* @default 'keyv'
*/
*/
namespace?: string;

@@ -130,3 +130,3 @@ /**

* @default defaultDeserialize using JSON.parse
*/
*/
deserialize?: Deserialize;

@@ -164,4 +164,4 @@ /**

};
type KeyvOptions_ = Omit<KeyvOptions, 'store'> & {
store: KeyvStoreAdapter | Map<any, any> & KeyvStoreAdapter;
type KeyvOptions_ = Omit<KeyvOptions, "store"> & {
store: KeyvStoreAdapter | (Map<any, any> & KeyvStoreAdapter);
};

@@ -196,3 +196,3 @@ type IteratorFunction = (argument: any) => AsyncGenerator<any, void>;

*/
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, 'store'>);
constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, "store">);
/**

@@ -327,3 +327,3 @@ * Keyv Constructor

* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
*/
*/
getManyRaw<Value = GenericValue>(keys: string[]): Promise<Array<StoredDataRaw<Value>>>;

@@ -330,0 +330,0 @@ /**

// src/index.ts
import { defaultSerialize, defaultDeserialize } from "@keyv/serialize";
import { defaultDeserialize, defaultSerialize } from "@keyv/serialize";

@@ -26,3 +26,5 @@ // src/event-manager.ts

if (listeners.length >= this._maxListeners) {
console.warn(`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`);
console.warn(
`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`
);
}

@@ -55,2 +57,3 @@ listeners.push(listener);

// Emit an event
// biome-ignore lint/suspicious/noExplicitAny: type format
emit(event, ...arguments_) {

@@ -110,2 +113,3 @@ const listeners = this._eventListeners.get(event);

// Triggers all handlers for a specific event with provided data
// biome-ignore lint/suspicious/noExplicitAny: type format
trigger(event, data) {

@@ -118,3 +122,8 @@ const eventHandlers = this._hookHandlers.get(event);

} catch (error) {
this.emit("error", new Error(`Error in hook handler for event "${event}": ${error.message}`));
this.emit(
"error",
new Error(
`Error in hook handler for event "${event}": ${error.message}`
)
);
}

@@ -226,2 +235,3 @@ }

*/
// biome-ignore lint/suspicious/noExplicitAny: type format
_store = /* @__PURE__ */ new Map();

@@ -275,5 +285,10 @@ _serialize = defaultSerialize;

if (typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map) {
this.iterator = this.generateIterator(this._store);
this.iterator = this.generateIterator(
this._store
);
} else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) {
this.iterator = this.generateIterator(this._store.iterator.bind(this._store));
this.iterator = this.generateIterator(
// biome-ignore lint/style/noNonNullAssertion: need to fix
this._store.iterator.bind(this._store)
);
}

@@ -297,2 +312,3 @@ }

*/
// biome-ignore lint/suspicious/noExplicitAny: type format
get store() {

@@ -305,2 +321,3 @@ return this._store;

*/
// biome-ignore lint/suspicious/noExplicitAny: type format
set store(store) {

@@ -317,5 +334,7 @@ if (this._isValidStorageAdapter(store)) {

if (typeof store[Symbol.iterator] === "function" && store instanceof Map) {
this.iterator = this.generateIterator(store);
this.iterator = this.generateIterator(
store
);
} else if ("iterator" in store && store.opts && this._checkIterableAdapter()) {
this.iterator = this.generateIterator(store.iterator.bind(store));
this.iterator = this.generateIterator(store.iterator?.bind(store));
}

@@ -452,3 +471,5 @@ } else {

_checkIterableAdapter() {
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some((element) => this._store.opts.url.includes(element));
return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some(
(element) => this._store.opts.url.includes(element)
);
}

@@ -479,2 +500,3 @@ _getKeyPrefix(key) {

}
// biome-ignore lint/suspicious/noExplicitAny: type format
_isValidStorageAdapter(store) {

@@ -514,3 +536,6 @@ return store instanceof Map || typeof store.get === "function" && typeof store.set === "function" && typeof store.delete === "function" && typeof store.clear === "function";

}
this.hooks.trigger("postGet" /* POST_GET */, { key: keyPrefixed, value: deserializedData });
this.hooks.trigger("postGet" /* POST_GET */, {
key: keyPrefixed,
value: deserializedData
});
this.stats.hit();

@@ -538,3 +563,6 @@ return options?.raw ? deserializedData : deserializedData.value;

const deserializedRows = await Promise.allSettled(promises);
const result2 = deserializedRows.map((row) => row.value);
const result2 = deserializedRows.map(
// biome-ignore lint/suspicious/noExplicitAny: type format
(row) => row.value
);
this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2);

@@ -590,3 +618,4 @@ if (result2.length > 0) {

const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData;
if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && deserializedData.expires < Date.now()) {
if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && // biome-ignore lint/style/noNonNullAssertion: need to fix
deserializedData.expires < Date.now()) {
this.stats.miss();

@@ -597,3 +626,6 @@ await this.delete(key);

this.stats.hit();
this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, { key: keyPrefixed, value: deserializedData });
this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, {
key: keyPrefixed,
value: deserializedData
});
return deserializedData;

@@ -605,3 +637,3 @@ }

* @returns {Promise<Array<StoredDataRaw<Value>>>} will return an array of StoredDataRaw<Value> or undefined if the key does not exist or is expired.
*/
*/
async getManyRaw(keys) {

@@ -611,5 +643,10 @@ const { store } = this.opts;

if (keys.length === 0) {
const result2 = Array.from({ length: keys.length }).fill(void 0);
const result2 = Array.from({ length: keys.length }).fill(
void 0
);
this.stats.misses += keys.length;
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, { keys: keyPrefixed, values: result2 });
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
keys: keyPrefixed,
values: result2
});
return result2;

@@ -627,3 +664,6 @@ }

const deserializedRows = await Promise.allSettled(promises);
result = deserializedRows.map((row) => row.value);
result = deserializedRows.map(
// biome-ignore lint/suspicious/noExplicitAny: type format
(row) => row.value
);
} else {

@@ -651,3 +691,6 @@ const rawData = await store.getMany(keyPrefixed);

this.stats.hitsOrMisses(result);
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, { keys: keyPrefixed, values: result });
this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, {
keys: keyPrefixed,
values: result
});
return result;

@@ -691,3 +734,7 @@ }

}
this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value: serializedValue, ttl });
this.hooks.trigger("postSet" /* POST_SET */, {
key: keyPrefixed,
value: serializedValue,
ttl
});
this.stats.set();

@@ -701,2 +748,3 @@ return result;

*/
// biome-ignore lint/correctness/noUnusedVariables: type format
async setMany(entries) {

@@ -713,16 +761,18 @@ let results = [];

} else {
const serializedEntries = await Promise.all(entries.map(async ({ key, value, ttl }) => {
ttl ??= this._ttl;
if (ttl === 0) {
ttl = void 0;
}
const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
if (typeof value === "symbol") {
this.emit("error", "symbol cannot be serialized");
throw new Error("symbol cannot be serialized");
}
const formattedValue = { value, expires };
const serializedValue = await this.serializeData(formattedValue);
return { key, value: serializedValue, ttl };
}));
const serializedEntries = await Promise.all(
entries.map(async ({ key, value, ttl }) => {
ttl ??= this._ttl;
if (ttl === 0) {
ttl = void 0;
}
const expires = typeof ttl === "number" ? Date.now() + ttl : void 0;
if (typeof value === "symbol") {
this.emit("error", "symbol cannot be serialized");
throw new Error("symbol cannot be serialized");
}
const formattedValue = { value, expires };
const serializedValue = await this.serializeData(formattedValue);
return { key, value: serializedValue, ttl };
})
);
results = await this._store.setMany(serializedEntries);

@@ -764,3 +814,6 @@ }

}
this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: result });
this.hooks.trigger("postDelete" /* POST_DELETE */, {
key: keyPrefixed,
value: result
});
this.stats.delete();

@@ -785,3 +838,6 @@ return result;

const returnResult = results.every(Boolean);
this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: returnResult });
this.hooks.trigger("postDelete" /* POST_DELETE */, {
key: keyPrefixed,
value: returnResult
});
return returnResult;

@@ -870,2 +926,3 @@ } catch (error) {

}
// biome-ignore lint/suspicious/noExplicitAny: type format
emit(event, ...arguments_) {

@@ -882,3 +939,6 @@ if (event === "error" && !this.opts.emitErrors) {

if (this._compression?.compress) {
return this._serialize({ value: await this._compression.compress(data.value), expires: data.expires });
return this._serialize({
value: await this._compression.compress(data.value),
expires: data.expires
});
}

@@ -893,3 +953,6 @@ return this._serialize(data);

const result = await this._deserialize(data);
return { value: await this._compression.decompress(result?.value), expires: result?.expires };
return {
value: await this._compression.decompress(result?.value),
expires: result?.expires
};
}

@@ -896,0 +959,0 @@ if (typeof data === "string") {

{
"name": "keyv",
"version": "5.5.0",
"version": "5.5.1",
"description": "Simple key-value storage with support for multiple backends",

@@ -15,12 +15,2 @@ "type": "module",

},
"xo": {
"rules": {
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-confusing-void-expression": "off"
}
},
"repository": {

@@ -58,19 +48,19 @@ "type": "git",

"dependencies": {
"@keyv/serialize": "^1.1.0"
"@keyv/serialize": "^1.1.1"
},
"devDependencies": {
"@faker-js/faker": "^9.9.0",
"@biomejs/biome": "^2.2.3",
"@faker-js/faker": "^10.0.0",
"@vitest/coverage-v8": "^3.2.4",
"rimraf": "^6.0.1",
"timekeeper": "^2.3.1",
"tsd": "^0.32.0",
"tsd": "^0.33.0",
"vitest": "^3.2.4",
"xo": "^1.2.0",
"@keyv/compress-brotli": "^2.0.5",
"@keyv/compress-gzip": "^2.0.3",
"@keyv/mongo": "^3.0.3",
"@keyv/compress-lz4": "^1.0.1",
"@keyv/memcache": "^2.0.2",
"@keyv/compress-lz4": "^1.0.1",
"@keyv/mongo": "^3.0.3",
"@keyv/sqlite": "^4.0.5",
"@keyv/test-suite": "^2.1.0"
"@keyv/test-suite": "^2.1.1",
"@keyv/compress-brotli": "^2.0.5",
"@keyv/compress-gzip": "^2.0.3"
},

@@ -86,6 +76,6 @@ "tsd": {

"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
"test": "xo --fix && vitest run --coverage",
"test:ci": "xo && vitest --run --sequence.setupFiles=list --coverage",
"test": "biome check --write && vitest run --coverage",
"test:ci": "biome check && vitest --run --sequence.setupFiles=list --coverage",
"clean": "rimraf ./node_modules ./coverage ./test/testdb.sqlite ./dist"
}
}