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.3.4
to
5.4.0
+61
-11
dist/index.cjs

@@ -240,2 +240,3 @@ "use strict";

_useKeyPrefix = true;
_throwOnErrors = false;
/**

@@ -297,2 +298,5 @@ * Keyv Constructor

}
if (this.opts.throwOnErrors !== void 0) {
this._throwOnErrors = this.opts.throwOnErrors;
}
}

@@ -422,2 +426,17 @@ /**

}
/**
* Get the current throwErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @return {boolean} The current throwOnErrors value.
*/
get throwOnErrors() {
return this._throwOnErrors;
}
/**
* Set the current throwOnErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @param {boolean} value The throwOnErrors value to set.
*/
set throwOnErrors(value) {
this._throwOnErrors = value;
this.opts.throwOnErrors = value;
}
generateIterator(iterator) {

@@ -482,3 +501,10 @@ const function_ = async function* () {

this.hooks.trigger("preGet" /* PRE_GET */, { key: keyPrefixed });
const rawData = await store.get(keyPrefixed);
let rawData;
try {
rawData = await store.get(keyPrefixed);
} catch (error) {
if (this.throwOnErrors) {
throw error;
}
}
const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData;

@@ -526,2 +552,3 @@ if (deserializedData === void 0 || deserializedData === null) {

const result = [];
const expiredKeys = [];
for (const index in rawData) {

@@ -537,3 +564,3 @@ let row = rawData[index];

if (isDataExpired(row)) {
await this.delete(keys[index]);
expiredKeys.push(keys[index]);
result.push(void 0);

@@ -545,2 +572,5 @@ continue;

}
if (expiredKeys.length > 0) {
await this.deleteMany(expiredKeys);
}
this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);

@@ -584,2 +614,5 @@ if (result.length > 0) {

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
}

@@ -598,3 +631,10 @@ this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value: serializedValue, ttl });

try {
if (this._store.setMany !== void 0) {
if (this._store.setMany === void 0) {
const promises = [];
for (const entry of entries) {
promises.push(this.set(entry.key, entry.value, entry.ttl));
}
const promiseResults = await Promise.all(promises);
results = promiseResults;
} else {
const serializedEntries = await Promise.all(entries.map(async ({ key, value, ttl }) => {

@@ -616,10 +656,7 @@ ttl ??= this._ttl;

}
const promises = [];
for (const entry of entries) {
promises.push(this.set(entry.key, entry.value, entry.ttl));
}
const promiseResults = await Promise.allSettled(promises);
results = promiseResults.map((result) => result.value);
} catch (error) {
this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
results = entries.map(() => false);

@@ -650,2 +687,5 @@ }

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
}

@@ -670,4 +710,4 @@ this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: result });

const promises = keyPrefixed.map(async (key) => store.delete(key));
const results = await Promise.allSettled(promises);
const returnResult = results.every((x) => x.value === true);
const results = await Promise.all(promises);
const returnResult = results.every(Boolean);
this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: returnResult });

@@ -677,2 +717,5 @@ return returnResult;

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
return false;

@@ -692,2 +735,5 @@ }

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
}

@@ -709,2 +755,6 @@ }

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
return false;
}

@@ -711,0 +761,0 @@ if (rawData) {

@@ -105,20 +105,52 @@ type EventListener = (...arguments_: any[]) => void;

type KeyvOptions = {
/** Emit errors */
/**
* Emit errors
* @default true
*/
emitErrors?: boolean;
/** Namespace for the current instance. */
/**
* Namespace for the current instance.
* @default 'keyv'
*/
namespace?: string;
/** A custom serialization function. */
/**
* A custom serialization function.
* @default defaultSerialize using JSON.stringify
*/
serialize?: Serialize;
/** A custom deserialization function. */
/**
* A custom deserialization function.
* @default defaultDeserialize using JSON.parse
*/
deserialize?: Deserialize;
/** The storage adapter instance to be used by Keyv. */
/**
* The storage adapter instance to be used by Keyv.
* @default new Map() - in-memory store
*/
store?: KeyvStoreAdapter | Map<any, any> | any;
/** Default TTL. Can be overridden by specifying a TTL on `.set()`. */
/**
* Default TTL. Can be overridden by specifying a TTL on `.set()`.
* @default undefined
*/
ttl?: number;
/** Enable compression option **/
/**
* Enable compression option
* @default false
*/
compression?: CompressionAdapter | any;
/** Enable or disable statistics (default is false) */
/**
* Enable or disable statistics (default is false)
* @default false
*/
stats?: boolean;
/** Enable or disable key prefixing (default is true) */
/**
* Enable or disable key prefixing (default is true)
* @default true
*/
useKeyPrefix?: boolean;
/**
* Will enable throwing errors on methods in addition to emitting them.
* @default false
*/
throwOnErrors?: boolean;
};

@@ -150,2 +182,3 @@ type KeyvOptions_ = Omit<KeyvOptions, 'store'> & {

private _useKeyPrefix;
private _throwOnErrors;
/**

@@ -232,2 +265,12 @@ * Keyv Constructor

set useKeyPrefix(value: boolean);
/**
* Get the current throwErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @return {boolean} The current throwOnErrors value.
*/
get throwOnErrors(): boolean;
/**
* Set the current throwOnErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @param {boolean} value The throwOnErrors value to set.
*/
set throwOnErrors(value: boolean);
generateIterator(iterator: IteratorFunction): IteratorFunction;

@@ -234,0 +277,0 @@ _checkIterableAdapter(): boolean;

@@ -105,20 +105,52 @@ type EventListener = (...arguments_: any[]) => void;

type KeyvOptions = {
/** Emit errors */
/**
* Emit errors
* @default true
*/
emitErrors?: boolean;
/** Namespace for the current instance. */
/**
* Namespace for the current instance.
* @default 'keyv'
*/
namespace?: string;
/** A custom serialization function. */
/**
* A custom serialization function.
* @default defaultSerialize using JSON.stringify
*/
serialize?: Serialize;
/** A custom deserialization function. */
/**
* A custom deserialization function.
* @default defaultDeserialize using JSON.parse
*/
deserialize?: Deserialize;
/** The storage adapter instance to be used by Keyv. */
/**
* The storage adapter instance to be used by Keyv.
* @default new Map() - in-memory store
*/
store?: KeyvStoreAdapter | Map<any, any> | any;
/** Default TTL. Can be overridden by specifying a TTL on `.set()`. */
/**
* Default TTL. Can be overridden by specifying a TTL on `.set()`.
* @default undefined
*/
ttl?: number;
/** Enable compression option **/
/**
* Enable compression option
* @default false
*/
compression?: CompressionAdapter | any;
/** Enable or disable statistics (default is false) */
/**
* Enable or disable statistics (default is false)
* @default false
*/
stats?: boolean;
/** Enable or disable key prefixing (default is true) */
/**
* Enable or disable key prefixing (default is true)
* @default true
*/
useKeyPrefix?: boolean;
/**
* Will enable throwing errors on methods in addition to emitting them.
* @default false
*/
throwOnErrors?: boolean;
};

@@ -150,2 +182,3 @@ type KeyvOptions_ = Omit<KeyvOptions, 'store'> & {

private _useKeyPrefix;
private _throwOnErrors;
/**

@@ -232,2 +265,12 @@ * Keyv Constructor

set useKeyPrefix(value: boolean);
/**
* Get the current throwErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @return {boolean} The current throwOnErrors value.
*/
get throwOnErrors(): boolean;
/**
* Set the current throwOnErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @param {boolean} value The throwOnErrors value to set.
*/
set throwOnErrors(value: boolean);
generateIterator(iterator: IteratorFunction): IteratorFunction;

@@ -234,0 +277,0 @@ _checkIterableAdapter(): boolean;

@@ -214,2 +214,3 @@ // src/index.ts

_useKeyPrefix = true;
_throwOnErrors = false;
/**

@@ -271,2 +272,5 @@ * Keyv Constructor

}
if (this.opts.throwOnErrors !== void 0) {
this._throwOnErrors = this.opts.throwOnErrors;
}
}

@@ -396,2 +400,17 @@ /**

}
/**
* Get the current throwErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @return {boolean} The current throwOnErrors value.
*/
get throwOnErrors() {
return this._throwOnErrors;
}
/**
* Set the current throwOnErrors value. This will enable or disable throwing errors on methods in addition to emitting them.
* @param {boolean} value The throwOnErrors value to set.
*/
set throwOnErrors(value) {
this._throwOnErrors = value;
this.opts.throwOnErrors = value;
}
generateIterator(iterator) {

@@ -456,3 +475,10 @@ const function_ = async function* () {

this.hooks.trigger("preGet" /* PRE_GET */, { key: keyPrefixed });
const rawData = await store.get(keyPrefixed);
let rawData;
try {
rawData = await store.get(keyPrefixed);
} catch (error) {
if (this.throwOnErrors) {
throw error;
}
}
const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData;

@@ -500,2 +526,3 @@ if (deserializedData === void 0 || deserializedData === null) {

const result = [];
const expiredKeys = [];
for (const index in rawData) {

@@ -511,3 +538,3 @@ let row = rawData[index];

if (isDataExpired(row)) {
await this.delete(keys[index]);
expiredKeys.push(keys[index]);
result.push(void 0);

@@ -519,2 +546,5 @@ continue;

}
if (expiredKeys.length > 0) {
await this.deleteMany(expiredKeys);
}
this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result);

@@ -558,2 +588,5 @@ if (result.length > 0) {

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
}

@@ -572,3 +605,10 @@ this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value: serializedValue, ttl });

try {
if (this._store.setMany !== void 0) {
if (this._store.setMany === void 0) {
const promises = [];
for (const entry of entries) {
promises.push(this.set(entry.key, entry.value, entry.ttl));
}
const promiseResults = await Promise.all(promises);
results = promiseResults;
} else {
const serializedEntries = await Promise.all(entries.map(async ({ key, value, ttl }) => {

@@ -590,10 +630,7 @@ ttl ??= this._ttl;

}
const promises = [];
for (const entry of entries) {
promises.push(this.set(entry.key, entry.value, entry.ttl));
}
const promiseResults = await Promise.allSettled(promises);
results = promiseResults.map((result) => result.value);
} catch (error) {
this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
results = entries.map(() => false);

@@ -624,2 +661,5 @@ }

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
}

@@ -644,4 +684,4 @@ this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: result });

const promises = keyPrefixed.map(async (key) => store.delete(key));
const results = await Promise.allSettled(promises);
const returnResult = results.every((x) => x.value === true);
const results = await Promise.all(promises);
const returnResult = results.every(Boolean);
this.hooks.trigger("postDelete" /* POST_DELETE */, { key: keyPrefixed, value: returnResult });

@@ -651,2 +691,5 @@ return returnResult;

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
return false;

@@ -666,2 +709,5 @@ }

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
}

@@ -683,2 +729,6 @@ }

this.emit("error", error);
if (this._throwOnErrors) {
throw error;
}
return false;
}

@@ -685,0 +735,0 @@ if (rawData) {

+13
-13
{
"name": "keyv",
"version": "5.3.4",
"version": "5.4.0",
"description": "Simple key-value storage with support for multiple backends",

@@ -57,19 +57,19 @@ "type": "module",

"dependencies": {
"@keyv/serialize": "^1.0.3"
"@keyv/serialize": "^1.1.0"
},
"devDependencies": {
"@faker-js/faker": "^9.8.0",
"@vitest/coverage-v8": "^3.2.3",
"@faker-js/faker": "^9.9.0",
"@vitest/coverage-v8": "^3.2.4",
"rimraf": "^6.0.1",
"timekeeper": "^2.3.1",
"tsd": "^0.32.0",
"vitest": "^3.2.3",
"xo": "^1.1.0",
"@keyv/compress-brotli": "^2.0.4",
"vitest": "^3.2.4",
"xo": "^1.1.1",
"@keyv/memcache": "^2.0.2",
"@keyv/compress-gzip": "^2.0.3",
"@keyv/sqlite": "^4.0.4",
"@keyv/memcache": "^2.0.1",
"@keyv/test-suite": "^2.0.7",
"@keyv/mongo": "^3.0.2",
"@keyv/compress-lz4": "^1.0.0"
"@keyv/compress-lz4": "^1.0.1",
"@keyv/compress-brotli": "^2.0.5",
"@keyv/mongo": "^3.0.3",
"@keyv/test-suite": "^2.0.9",
"@keyv/sqlite": "^4.0.5"
},

@@ -86,5 +86,5 @@ "tsd": {

"test": "xo --fix && vitest run --coverage",
"test:ci": "xo && vitest --run --sequence.setupFiles=list",
"test:ci": "xo && vitest --run --sequence.setupFiles=list --coverage",
"clean": "rimraf ./node_modules ./coverage ./test/testdb.sqlite ./dist"
}
}
+47
-10

@@ -56,10 +56,2 @@ <h1 align="center"><img width="250" src="https://jaredwray.com/images/keyv.svg" alt="keyv"></h1>

- [.iterator()](#iterator)
- [API - Properties](#api---properties)
- [.namespace](#namespace-1)
- [.ttl](#ttl-1)
- [.store](#store-1)
- [.serialize](#serialize-1)
- [.deserialize](#deserialize-1)
- [.compression](#compression-1)
- [.useKeyPrefix](#usekeyprefix-1)
- [How to Contribute](#how-to-contribute)

@@ -87,2 +79,3 @@ - [License](#license)

npm install --save @keyv/memcache
npm install --save @keyv/dynamo
```

@@ -238,3 +231,3 @@

const keyv = new Keyv();
keyv.hooks.addHandler(KeyvHooks.POST_SET, (key, value) => console.log(`Set key ${key} to ${value}`));
keyv.hooks.addHandler(KeyvHooks.POST_SET, ({key, value}) => console.log(`Set key ${key} to ${value}`));
```

@@ -292,2 +285,3 @@

Memcache | [@keyv/memcache](https://github.com/jaredwray/keyv/tree/master/packages/memcache) | Yes
DynamoDB | [@keyv/dynamo](https://github.com/jaredwray/keyv/tree/master/packages/dynamo) | Yes

@@ -325,3 +319,2 @@ # Third-party Storage Adapters

- [keyv-file](https://github.com/zaaack/keyv-file) - File system storage adapter for Keyv
- [keyv-dynamodb](https://www.npmjs.com/package/keyv-dynamodb) - DynamoDB storage adapter for Keyv
- [keyv-lru](https://www.npmjs.com/package/keyv-lru) - LRU storage adapter for Keyv

@@ -631,2 +624,46 @@ - [keyv-null](https://www.npmjs.com/package/keyv-null) - Null storage adapter for Keyv

With many of the storage adapters you will also need to set the `namespace` option to `undefined` to have it work correctly. This is because in `v5` we started the transition to having the storage adapter handle the namespacing and `Keyv` will no longer handle it internally via KeyPrefixing. Here is an example of doing ith with `KeyvSqlite`:
```js
import Keyv from 'keyv';
import KeyvSqlite from '@keyv/sqlite';
const store = new KeyvSqlite('sqlite://path/to/database.sqlite');
const keyv = new Keyv({ store });
keyv.useKeyPrefix = false; // disable key prefixing
store.namespace = undefined; // disable namespacing in the storage adapter
await keyv.set('foo', 'bar'); // true
await keyv.get('foo'); // 'bar'
await keyv.clear();
```
## .throwOnErrors
Type: `Boolean`<br />
Default: `false`
If set to `true`, Keyv will throw an error if any operation fails. This is useful if you want to ensure that all operations are successful and you want to handle errors.
```js
const keyv = new Keyv({ throwOnErrors: true });
console.log(keyv.throwOnErrors); // true
keyv.throwOnErrors = false;
console.log(keyv.throwOnErrors); // false
```
A good example of this is with the `@keyv/redis` storage adapter. If you want to handle connection errors, retries, and timeouts more gracefully, you can use the `throwOnErrors` option. This will throw an error if any operation fails, allowing you to catch it and handle it accordingly:
```js
import Keyv from 'keyv';
import KeyvRedis from '@keyv/redis';
// create redis instance that will throw on connection error
const keyvRedis = new KeyvRedis('redis://user:pass@localhost:6379', { throwOnConnectErrors: true });
const keyv = new Keyv({ store: keyvRedis, throwOnErrors: true });
```
What this does is it only throw on connection errors with the Redis client.
# How to Contribute

@@ -633,0 +670,0 @@