+61
-11
@@ -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) { |
+52
-9
@@ -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; |
+52
-9
@@ -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; |
+61
-11
@@ -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 @@ |
99585
6.65%1960
7.87%674
5.81%Updated