@keyv/redis 4.6.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,7 +25,11 @@ Redis storage adapter for [Keyv](https://github.com/jaredwray/keyv).
25
25
 
26
26
  # Table of Contents
27
27
  * [Usage](#usage)
28
+ * [Migrating from v4 to v5](#migrating-from-v4-to-v5)
29
+ * [Using the createKeyv function](#using-the-createkeyv-function)
30
+ * [Using the createKeyvNonBlocking function](#using-the-createkeyvnonblocking-function)
28
31
  * [Namespaces](#namespaces)
32
+ * [Fixing Double Prefixing of Keys](#fixing-double-prefixing-of-keys)
29
33
  * [Using Generic Types](#using-generic-types)
30
34
  * [Performance Considerations](#performance-considerations)
31
35
  * [High Memory Usage on Redis Server](#high-memory-usage-on-redis-server)
@@ -100,6 +104,10 @@ const keyvRedis = new KeyvRedis(redis);
100
104
  const keyv = new Keyv({ store: keyvRedis});
101
105
  ```
102
106
 
107
+ # Migrating from v4 to v5
108
+
109
+ The major change from v4 to v5 is that we are now using v5 of the `@redis/client` library which has a new API. This means that some methods have changed but it should be a drop-in replacement for most use cases.
110
+
103
111
  # Keyv Redis Options
104
112
 
105
113
  You can pass in options to the `KeyvRedis` constructor. Here are the available options:
@@ -143,7 +151,7 @@ export type KeyvRedisOptions = {
143
151
  * and returns no-op responses.
144
152
  * @default false
145
153
  */
146
- throwErrors?: boolean;
154
+ throwOnErrors?: boolean;
147
155
 
148
156
  /**
149
157
  * Timeout in milliseconds for the connection. Default is undefined, which uses the default timeout of the Redis client.
@@ -180,6 +188,30 @@ const keyv = createKeyv('redis://user:pass@localhost:6379');
180
188
  keyv.store.namespace = 'my-namespace';
181
189
  ```
182
190
 
191
+ # Using the `createKeyv` function
192
+
193
+ The `createKeyv` function is a convenience function that creates a new `Keyv` instance with the `@keyv/redis` store. It automatically sets the `useKeyPrefix` option to `false`. Here is an example of how to use it:
194
+
195
+ ```js
196
+ import { createKeyv } from '@keyv/redis';
197
+ const keyv = createKeyv('redis://user:pass@localhost:6379');
198
+ ```
199
+
200
+ To use a namespace you can do it here and this will set Keyv up correctly to avoid the double namespace issue:
201
+
202
+ ```js
203
+ import { createKeyv } from '@keyv/redis';
204
+ const keyv = createKeyv('redis://user:pass@localhost:6379', {namespace: 'my-namespace'});
205
+ ```
206
+
207
+ # Using the `createKeyvNonBlocking` function
208
+
209
+ The `createKeyvNonBlocking` function is a convenience function that creates a new `Keyv` instance with the `@keyv/redis` store does what `createKeyv` does but also disables throwing errors, removes the offline queue redis functionality, and reconnect strategy so that when used as a secondary cache in libraries such as [cacheable](https://npmjs.org/package/cacheable) it does not block the primary cache. This is useful when you want to use Redis as a secondary cache and do not want to block the primary cache on connection errors or timeouts when using `nonBlocking`. Here is an example of how to use it:
210
+
211
+ ```js
212
+ import { createKeyvNonBlocking } from '@keyv/redis';
213
+ const keyv = createKeyvNonBlocking('redis://user:pass@localhost:6379');
214
+ ```
183
215
 
184
216
  # Namespaces
185
217
 
@@ -191,10 +223,17 @@ import KeyvRedis, { createClient } from '@keyv/redis';
191
223
 
192
224
  const redis = createClient('redis://user:pass@localhost:6379');
193
225
  const keyvRedis = new KeyvRedis(redis);
194
- const keyv = new Keyv({ store: keyvRedis, namespace: 'my-namespace' });
226
+ const keyv = new Keyv({ store: keyvRedis, namespace: 'my-namespace', useKeyPrefix: false });
227
+ ```
228
+
229
+ To make this easier, you can use the `createKeyv` function which will automatically set the `namespace` option to the `KeyvRedis` instance:
230
+
231
+ ```js
232
+ import { createKeyv } from '@keyv/redis';
233
+ const keyv = createKeyv('redis://user:pass@localhost:6379', { namespace: 'my-namespace' });
195
234
  ```
196
235
 
197
- This will prefix all keys with `my-namespace:`. You can also set the namespace after the fact:
236
+ This will prefix all keys with `my-namespace:` and will also set `useKeyPrefix` to `false`. This is done to avoid double prefixing of keys as we transition out of the legacy behavior in Keyv. You can also set the namespace after the fact:
198
237
 
199
238
  ```js
200
239
  keyv.namespace = 'my-namespace';
@@ -202,6 +241,24 @@ keyv.namespace = 'my-namespace';
202
241
 
203
242
  NOTE: If you plan to do many clears or deletes, it is recommended to read the [Performance Considerations](#performance-considerations) section.
204
243
 
244
+ # Fixing Double Prefixing of Keys
245
+
246
+ If you are using `Keyv` with `@keyv/redis` as the storage adapter, you may notice that keys are being prefixed twice. This is because `Keyv` has a default prefixing behavior that is applied to all keys. To fix this, you can set the `useKeyPrefix` option to `false` when creating the `Keyv` instance:
247
+
248
+ ```js
249
+ import Keyv from 'keyv';
250
+ import KeyvRedis from '@keyv/redis';
251
+
252
+ const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379'), { useKeyPrefix: false });
253
+ ```
254
+
255
+ To make this easier, you can use the `createKeyv` function which will automatically set the `useKeyPrefix` option to `false`:
256
+
257
+ ```js
258
+ import { createKeyv } from '@keyv/redis';
259
+ const keyv = createKeyv('redis://user:pass@localhost:6379');
260
+ ```
261
+
205
262
  ## Using Generic Types
206
263
 
207
264
  When initializing `KeyvRedis`, you can specify the type of the values you are storing and you can also specify types when calling methods:
@@ -270,11 +327,21 @@ keyv.on('error', (error) => {
270
327
  });
271
328
  ```
272
329
 
273
- By default, the `KeyvRedis` instance will `throw an error` if the connection fails to connect. You can disable this behavior by setting the `throwOnConnectError` option to `false` when creating the `KeyvRedis` instance:
330
+ By default, the `KeyvRedis` instance will `throw an error` if the connection fails to connect. You can disable this behavior by setting the `throwOnConnectError` option to `false` when creating the `KeyvRedis` instance. If you want this to throw you will need to also set the Keyv instance to `throwOnErrors: true`:
331
+
332
+ ```js
333
+ import Keyv from 'keyv';
334
+ import KeyvRedis from '@keyv/redis';
335
+
336
+ const keyv = new Keyv(new KeyvRedis('redis://bad-uri:1111', { throwOnConnectError: false }));
337
+ keyv.throwOnErrors = true; // This will throw an error if the connection fails
338
+
339
+ await keyv.set('key', 'value'); // this will throw the connection error only.
340
+ ```
274
341
 
275
342
  On `get`, `getMany`, `set`, `setMany`, `delete`, and `deleteMany`, if the connection is lost, it will emit an error and return a no-op value. You can catch this error and handle it accordingly. This is important to ensure that your application does not crash due to a lost connection to Redis.
276
343
 
277
- If you want to handle connection errors, retries, and timeouts more gracefully, you can use the `throwErrors` option. This will throw an error if any operation fails, allowing you to catch it and handle it accordingly:
344
+ 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:
278
345
 
279
346
  There is a default `Reconnect Strategy` if you pass in just a `uri` connection string we will automatically create a Redis client for you with the following reconnect strategy:
280
347
 
package/dist/index.cjs CHANGED
@@ -35,6 +35,7 @@ __export(index_exports, {
35
35
  createClient: () => import_client2.createClient,
36
36
  createCluster: () => import_client2.createCluster,
37
37
  createKeyv: () => createKeyv,
38
+ createKeyvNonBlocking: () => createKeyvNonBlocking,
38
39
  default: () => KeyvRedis,
39
40
  defaultReconnectStrategy: () => defaultReconnectStrategy
40
41
  });
@@ -62,7 +63,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
62
63
  _useUnlink = true;
63
64
  _noNamespaceAffectsAll = false;
64
65
  _throwOnConnectError = true;
65
- _throwErrors = false;
66
+ _throwOnErrors = false;
66
67
  _connectionTimeout;
67
68
  /**
68
69
  * KeyvRedis constructor.
@@ -118,7 +119,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
118
119
  noNamespaceAffectsAll: this._noNamespaceAffectsAll,
119
120
  useUnlink: this._useUnlink,
120
121
  throwOnConnectError: this._throwOnConnectError,
121
- throwErrors: this._throwErrors,
122
+ throwOnErrors: this._throwOnErrors,
122
123
  connectionTimeout: this._connectionTimeout,
123
124
  dialect: "redis",
124
125
  url
@@ -220,25 +221,25 @@ var KeyvRedis = class extends import_hookified.Hookified {
220
221
  this._throwOnConnectError = value;
221
222
  }
222
223
  /**
223
- * Get if throwErrors is set to true.
224
+ * Get if throwOnErrors is set to true.
224
225
  * This is used to throw an error if at any point there is a failure. Use this if you want to
225
226
  * ensure that all operations are successful and you want to handle errors. By default, this is
226
227
  * set to false so that it does not throw an error on every operation and instead emits an error event
227
228
  * and returns no-op responses.
228
229
  * @default false
229
230
  */
230
- get throwErrors() {
231
- return this._throwErrors;
231
+ get throwOnErrors() {
232
+ return this._throwOnErrors;
232
233
  }
233
234
  /**
234
- * Set if throwErrors is set to true.
235
+ * Set if throwOnErrors is set to true.
235
236
  * This is used to throw an error if at any point there is a failure. Use this if you want to
236
237
  * ensure that all operations are successful and you want to handle errors. By default, this is
237
238
  * set to false so that it does not throw an error on every operation and instead emits an error event
238
239
  * and returns no-op responses.
239
240
  */
240
- set throwErrors(value) {
241
- this._throwErrors = value;
241
+ set throwOnErrors(value) {
242
+ this._throwOnErrors = value;
242
243
  }
243
244
  /**
244
245
  * Get the connection timeout in milliseconds such as 5000 (5 seconds). Default is undefined. If undefined, it will use the default.
@@ -272,10 +273,10 @@ var KeyvRedis = class extends import_hookified.Hookified {
272
273
  }
273
274
  } catch (error) {
274
275
  this.emit("error", error);
276
+ await this.disconnect(true);
275
277
  if (this._throwOnConnectError) {
276
278
  throw new Error("Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */);
277
279
  }
278
- await this.disconnect(true);
279
280
  }
280
281
  this.initClient();
281
282
  return this._client;
@@ -297,7 +298,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
297
298
  }
298
299
  } catch (error) {
299
300
  this.emit("error", error);
300
- if (this._throwErrors) {
301
+ if (this._throwOnErrors) {
301
302
  throw error;
302
303
  }
303
304
  }
@@ -321,7 +322,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
321
322
  await multi.exec();
322
323
  } catch (error) {
323
324
  this.emit("error", error);
324
- if (this._throwErrors) {
325
+ if (this._throwOnErrors) {
325
326
  throw error;
326
327
  }
327
328
  }
@@ -339,7 +340,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
339
340
  return exists === 1;
340
341
  } catch (error) {
341
342
  this.emit("error", error);
342
- if (this._throwErrors) {
343
+ if (this._throwOnErrors) {
343
344
  throw error;
344
345
  }
345
346
  return false;
@@ -359,10 +360,10 @@ var KeyvRedis = class extends import_hookified.Hookified {
359
360
  multi.exists(prefixedKey);
360
361
  }
361
362
  const results = await multi.exec();
362
- return results.map((result) => result === 1);
363
+ return results.map((result) => typeof result === "number" && result === 1);
363
364
  } catch (error) {
364
365
  this.emit("error", error);
365
- if (this._throwErrors) {
366
+ if (this._throwOnErrors) {
366
367
  throw error;
367
368
  }
368
369
  return Array.from({ length: keys.length }).fill(false);
@@ -384,7 +385,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
384
385
  return value;
385
386
  } catch (error) {
386
387
  this.emit("error", error);
387
- if (this._throwErrors) {
388
+ if (this._throwOnErrors) {
388
389
  throw error;
389
390
  }
390
391
  return void 0;
@@ -405,7 +406,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
405
406
  return values;
406
407
  } catch (error) {
407
408
  this.emit("error", error);
408
- if (this._throwErrors) {
409
+ if (this._throwOnErrors) {
409
410
  throw error;
410
411
  }
411
412
  return Array.from({ length: keys.length }).fill(void 0);
@@ -425,7 +426,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
425
426
  return deleted > 0;
426
427
  } catch (error) {
427
428
  this.emit("error", error);
428
- if (this._throwErrors) {
429
+ if (this._throwOnErrors) {
429
430
  throw error;
430
431
  }
431
432
  return false;
@@ -457,7 +458,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
457
458
  }
458
459
  } catch (error) {
459
460
  this.emit("error", error);
460
- if (this._throwErrors) {
461
+ if (this._throwOnErrors) {
461
462
  throw error;
462
463
  }
463
464
  }
@@ -471,7 +472,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
471
472
  */
472
473
  async disconnect(force) {
473
474
  if (this._client.isOpen) {
474
- await (force ? this._client.disconnect() : this._client.quit());
475
+ await (force ? this._client.destroy() : this._client.close());
475
476
  }
476
477
  }
477
478
  /**
@@ -513,7 +514,8 @@ var KeyvRedis = class extends import_hookified.Hookified {
513
514
  async getMasterNodes() {
514
515
  if (this.isCluster()) {
515
516
  const cluster = await this.getClient();
516
- return Promise.all(cluster.masters.map(async (main) => cluster.nodeClient(main)));
517
+ const nodes = cluster.masters.map(async (main) => cluster.nodeClient(main));
518
+ return Promise.all(nodes);
517
519
  }
518
520
  return [await this.getClient()];
519
521
  }
@@ -528,7 +530,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
528
530
  const match = namespace ? `${namespace}${this._keyPrefixSeparator}*` : "*";
529
531
  let cursor = "0";
530
532
  do {
531
- const result = await client.scan(Number.parseInt(cursor, 10), { MATCH: match, TYPE: "string" });
533
+ const result = await client.scan(cursor, { MATCH: match, TYPE: "string" });
532
534
  cursor = result.cursor.toString();
533
535
  let { keys } = result;
534
536
  if (!namespace && !this._noNamespaceAffectsAll) {
@@ -565,7 +567,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
565
567
  const match = this._namespace ? `${this._namespace}${this._keyPrefixSeparator}*` : "*";
566
568
  const deletePromises = [];
567
569
  do {
568
- const result = await client.scan(Number.parseInt(cursor, 10), { MATCH: match, COUNT: batchSize, TYPE: "string" });
570
+ const result = await client.scan(cursor, { MATCH: match, COUNT: batchSize, TYPE: "string" });
569
571
  cursor = result.cursor.toString();
570
572
  let { keys } = result;
571
573
  if (keys.length === 0) {
@@ -644,10 +646,7 @@ var KeyvRedis = class extends import_hookified.Hookified {
644
646
  return slotMap;
645
647
  }
646
648
  isClientCluster(client) {
647
- if (client.options === void 0 && client.scan === void 0) {
648
- return true;
649
- }
650
- return false;
649
+ return client.slots !== void 0;
651
650
  }
652
651
  setOptions(options) {
653
652
  if (!options) {
@@ -671,8 +670,8 @@ var KeyvRedis = class extends import_hookified.Hookified {
671
670
  if (options.throwOnConnectError !== void 0) {
672
671
  this._throwOnConnectError = options.throwOnConnectError;
673
672
  }
674
- if (options.throwErrors !== void 0) {
675
- this._throwErrors = options.throwErrors;
673
+ if (options.throwOnErrors !== void 0) {
674
+ this._throwOnErrors = options.throwOnErrors;
676
675
  }
677
676
  if (options.connectionTimeout !== void 0) {
678
677
  this._connectionTimeout = options.connectionTimeout;
@@ -704,7 +703,40 @@ var KeyvRedis = class extends import_hookified.Hookified {
704
703
  function createKeyv(connect, options) {
705
704
  connect ??= "redis://localhost:6379";
706
705
  const adapter = new KeyvRedis(connect, options);
707
- const keyv = new import_keyv.Keyv(adapter, { namespace: options?.namespace, useKeyPrefix: false });
706
+ if (options?.namespace) {
707
+ adapter.namespace = options.namespace;
708
+ const keyv2 = new import_keyv.Keyv(adapter, { namespace: options?.namespace, useKeyPrefix: false });
709
+ if (options?.throwOnConnectError) {
710
+ keyv2.throwOnErrors = true;
711
+ }
712
+ if (options?.throwOnErrors) {
713
+ keyv2.throwOnErrors = true;
714
+ }
715
+ return keyv2;
716
+ }
717
+ const keyv = new import_keyv.Keyv(adapter, { useKeyPrefix: false });
718
+ if (options?.throwOnConnectError) {
719
+ keyv.throwOnErrors = true;
720
+ }
721
+ if (options?.throwOnErrors) {
722
+ keyv.throwOnErrors = true;
723
+ }
724
+ keyv.namespace = void 0;
725
+ return keyv;
726
+ }
727
+ function createKeyvNonBlocking(connect, options) {
728
+ const keyv = createKeyv(connect, options);
729
+ const keyvStore = keyv.store;
730
+ keyvStore.throwOnConnectError = false;
731
+ keyvStore.throwOnErrors = false;
732
+ const redisClient = keyvStore.client;
733
+ if (redisClient.options) {
734
+ redisClient.options.disableOfflineQueue = true;
735
+ if (redisClient.options.socket) {
736
+ redisClient.options.socket.reconnectStrategy = false;
737
+ }
738
+ }
739
+ keyv.throwOnErrors = false;
708
740
  return keyv;
709
741
  }
710
742
  // Annotate the CommonJS export names for ESM import in node:
@@ -714,5 +746,6 @@ function createKeyv(connect, options) {
714
746
  createClient,
715
747
  createCluster,
716
748
  createKeyv,
749
+ createKeyvNonBlocking,
717
750
  defaultReconnectStrategy
718
751
  });
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { RedisClientOptions, RedisClusterOptions, RedisClientType, RedisClusterType, RedisModules, RedisFunctions, RedisScripts } from '@redis/client';
1
+ import { RedisClientOptions, RedisClusterOptions, RedisClientType, RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, RedisClusterType } from '@redis/client';
2
2
  export { RedisClientOptions, RedisClientType, RedisClusterOptions, RedisClusterType, createClient, createCluster } from '@redis/client';
3
3
  import { Hookified } from 'hookified';
4
4
  import { KeyvStoreAdapter, KeyvEntry, Keyv } from 'keyv';
@@ -39,7 +39,7 @@ type KeyvRedisOptions = {
39
39
  * and returns no-op responses.
40
40
  * @default false
41
41
  */
42
- throwErrors?: boolean;
42
+ throwOnErrors?: boolean;
43
43
  /**
44
44
  * Timeout in milliseconds for the connection. Default is undefined, which uses the default timeout of the Redis client.
45
45
  * If set, it will throw an error if the connection does not succeed within the specified time.
@@ -78,7 +78,9 @@ declare enum RedisErrorMessages {
78
78
  RedisClientNotConnectedThrown = "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true."
79
79
  }
80
80
  declare const defaultReconnectStrategy: (attempts: number) => number | Error;
81
- type RedisClientConnectionType = RedisClientType | RedisClusterType<RedisModules, RedisFunctions, RedisScripts>;
81
+ type RedisConnectionClientType = RedisClientType | RedisClientType<RedisModules, RedisFunctions, RedisScripts, RespVersions> | RedisClientType<RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping>;
82
+ type RedisConnectionClusterType = RedisClusterType | RedisClusterType<RedisModules, RedisFunctions, RedisScripts, RespVersions> | RedisClusterType<RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping>;
83
+ type RedisClientConnectionType = RedisConnectionClientType | RedisConnectionClusterType;
82
84
  declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
83
85
  private _client;
84
86
  private _namespace;
@@ -87,7 +89,7 @@ declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
87
89
  private _useUnlink;
88
90
  private _noNamespaceAffectsAll;
89
91
  private _throwOnConnectError;
90
- private _throwErrors;
92
+ private _throwOnErrors;
91
93
  private _connectionTimeout;
92
94
  /**
93
95
  * KeyvRedis constructor.
@@ -172,22 +174,22 @@ declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
172
174
  */
173
175
  set throwOnConnectError(value: boolean);
174
176
  /**
175
- * Get if throwErrors is set to true.
177
+ * Get if throwOnErrors is set to true.
176
178
  * This is used to throw an error if at any point there is a failure. Use this if you want to
177
179
  * ensure that all operations are successful and you want to handle errors. By default, this is
178
180
  * set to false so that it does not throw an error on every operation and instead emits an error event
179
181
  * and returns no-op responses.
180
182
  * @default false
181
183
  */
182
- get throwErrors(): boolean;
184
+ get throwOnErrors(): boolean;
183
185
  /**
184
- * Set if throwErrors is set to true.
186
+ * Set if throwOnErrors is set to true.
185
187
  * This is used to throw an error if at any point there is a failure. Use this if you want to
186
188
  * ensure that all operations are successful and you want to handle errors. By default, this is
187
189
  * set to false so that it does not throw an error on every operation and instead emits an error event
188
190
  * and returns no-op responses.
189
191
  */
190
- set throwErrors(value: boolean);
192
+ set throwOnErrors(value: boolean);
191
193
  /**
192
194
  * Get the connection timeout in milliseconds such as 5000 (5 seconds). Default is undefined. If undefined, it will use the default.
193
195
  * @default undefined
@@ -329,5 +331,6 @@ declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
329
331
  * @returns {Keyv} - Keyv instance with the Redis adapter
330
332
  */
331
333
  declare function createKeyv(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions): Keyv;
334
+ declare function createKeyvNonBlocking(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions): Keyv;
332
335
 
333
- export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, type RedisClientConnectionType, RedisErrorMessages, createKeyv, KeyvRedis as default, defaultReconnectStrategy };
336
+ export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, type RedisClientConnectionType, type RedisConnectionClientType, type RedisConnectionClusterType, RedisErrorMessages, createKeyv, createKeyvNonBlocking, KeyvRedis as default, defaultReconnectStrategy };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { RedisClientOptions, RedisClusterOptions, RedisClientType, RedisClusterType, RedisModules, RedisFunctions, RedisScripts } from '@redis/client';
1
+ import { RedisClientOptions, RedisClusterOptions, RedisClientType, RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, RedisClusterType } from '@redis/client';
2
2
  export { RedisClientOptions, RedisClientType, RedisClusterOptions, RedisClusterType, createClient, createCluster } from '@redis/client';
3
3
  import { Hookified } from 'hookified';
4
4
  import { KeyvStoreAdapter, KeyvEntry, Keyv } from 'keyv';
@@ -39,7 +39,7 @@ type KeyvRedisOptions = {
39
39
  * and returns no-op responses.
40
40
  * @default false
41
41
  */
42
- throwErrors?: boolean;
42
+ throwOnErrors?: boolean;
43
43
  /**
44
44
  * Timeout in milliseconds for the connection. Default is undefined, which uses the default timeout of the Redis client.
45
45
  * If set, it will throw an error if the connection does not succeed within the specified time.
@@ -78,7 +78,9 @@ declare enum RedisErrorMessages {
78
78
  RedisClientNotConnectedThrown = "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true."
79
79
  }
80
80
  declare const defaultReconnectStrategy: (attempts: number) => number | Error;
81
- type RedisClientConnectionType = RedisClientType | RedisClusterType<RedisModules, RedisFunctions, RedisScripts>;
81
+ type RedisConnectionClientType = RedisClientType | RedisClientType<RedisModules, RedisFunctions, RedisScripts, RespVersions> | RedisClientType<RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping>;
82
+ type RedisConnectionClusterType = RedisClusterType | RedisClusterType<RedisModules, RedisFunctions, RedisScripts, RespVersions> | RedisClusterType<RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping>;
83
+ type RedisClientConnectionType = RedisConnectionClientType | RedisConnectionClusterType;
82
84
  declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
83
85
  private _client;
84
86
  private _namespace;
@@ -87,7 +89,7 @@ declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
87
89
  private _useUnlink;
88
90
  private _noNamespaceAffectsAll;
89
91
  private _throwOnConnectError;
90
- private _throwErrors;
92
+ private _throwOnErrors;
91
93
  private _connectionTimeout;
92
94
  /**
93
95
  * KeyvRedis constructor.
@@ -172,22 +174,22 @@ declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
172
174
  */
173
175
  set throwOnConnectError(value: boolean);
174
176
  /**
175
- * Get if throwErrors is set to true.
177
+ * Get if throwOnErrors is set to true.
176
178
  * This is used to throw an error if at any point there is a failure. Use this if you want to
177
179
  * ensure that all operations are successful and you want to handle errors. By default, this is
178
180
  * set to false so that it does not throw an error on every operation and instead emits an error event
179
181
  * and returns no-op responses.
180
182
  * @default false
181
183
  */
182
- get throwErrors(): boolean;
184
+ get throwOnErrors(): boolean;
183
185
  /**
184
- * Set if throwErrors is set to true.
186
+ * Set if throwOnErrors is set to true.
185
187
  * This is used to throw an error if at any point there is a failure. Use this if you want to
186
188
  * ensure that all operations are successful and you want to handle errors. By default, this is
187
189
  * set to false so that it does not throw an error on every operation and instead emits an error event
188
190
  * and returns no-op responses.
189
191
  */
190
- set throwErrors(value: boolean);
192
+ set throwOnErrors(value: boolean);
191
193
  /**
192
194
  * Get the connection timeout in milliseconds such as 5000 (5 seconds). Default is undefined. If undefined, it will use the default.
193
195
  * @default undefined
@@ -329,5 +331,6 @@ declare class KeyvRedis<T> extends Hookified implements KeyvStoreAdapter {
329
331
  * @returns {Keyv} - Keyv instance with the Redis adapter
330
332
  */
331
333
  declare function createKeyv(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions): Keyv;
334
+ declare function createKeyvNonBlocking(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions): Keyv;
332
335
 
333
- export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, type RedisClientConnectionType, RedisErrorMessages, createKeyv, KeyvRedis as default, defaultReconnectStrategy };
336
+ export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, type RedisClientConnectionType, type RedisConnectionClientType, type RedisConnectionClusterType, RedisErrorMessages, createKeyv, createKeyvNonBlocking, KeyvRedis as default, defaultReconnectStrategy };
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ var KeyvRedis = class extends Hookified {
30
30
  _useUnlink = true;
31
31
  _noNamespaceAffectsAll = false;
32
32
  _throwOnConnectError = true;
33
- _throwErrors = false;
33
+ _throwOnErrors = false;
34
34
  _connectionTimeout;
35
35
  /**
36
36
  * KeyvRedis constructor.
@@ -86,7 +86,7 @@ var KeyvRedis = class extends Hookified {
86
86
  noNamespaceAffectsAll: this._noNamespaceAffectsAll,
87
87
  useUnlink: this._useUnlink,
88
88
  throwOnConnectError: this._throwOnConnectError,
89
- throwErrors: this._throwErrors,
89
+ throwOnErrors: this._throwOnErrors,
90
90
  connectionTimeout: this._connectionTimeout,
91
91
  dialect: "redis",
92
92
  url
@@ -188,25 +188,25 @@ var KeyvRedis = class extends Hookified {
188
188
  this._throwOnConnectError = value;
189
189
  }
190
190
  /**
191
- * Get if throwErrors is set to true.
191
+ * Get if throwOnErrors is set to true.
192
192
  * This is used to throw an error if at any point there is a failure. Use this if you want to
193
193
  * ensure that all operations are successful and you want to handle errors. By default, this is
194
194
  * set to false so that it does not throw an error on every operation and instead emits an error event
195
195
  * and returns no-op responses.
196
196
  * @default false
197
197
  */
198
- get throwErrors() {
199
- return this._throwErrors;
198
+ get throwOnErrors() {
199
+ return this._throwOnErrors;
200
200
  }
201
201
  /**
202
- * Set if throwErrors is set to true.
202
+ * Set if throwOnErrors is set to true.
203
203
  * This is used to throw an error if at any point there is a failure. Use this if you want to
204
204
  * ensure that all operations are successful and you want to handle errors. By default, this is
205
205
  * set to false so that it does not throw an error on every operation and instead emits an error event
206
206
  * and returns no-op responses.
207
207
  */
208
- set throwErrors(value) {
209
- this._throwErrors = value;
208
+ set throwOnErrors(value) {
209
+ this._throwOnErrors = value;
210
210
  }
211
211
  /**
212
212
  * Get the connection timeout in milliseconds such as 5000 (5 seconds). Default is undefined. If undefined, it will use the default.
@@ -240,10 +240,10 @@ var KeyvRedis = class extends Hookified {
240
240
  }
241
241
  } catch (error) {
242
242
  this.emit("error", error);
243
+ await this.disconnect(true);
243
244
  if (this._throwOnConnectError) {
244
245
  throw new Error("Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */);
245
246
  }
246
- await this.disconnect(true);
247
247
  }
248
248
  this.initClient();
249
249
  return this._client;
@@ -265,7 +265,7 @@ var KeyvRedis = class extends Hookified {
265
265
  }
266
266
  } catch (error) {
267
267
  this.emit("error", error);
268
- if (this._throwErrors) {
268
+ if (this._throwOnErrors) {
269
269
  throw error;
270
270
  }
271
271
  }
@@ -289,7 +289,7 @@ var KeyvRedis = class extends Hookified {
289
289
  await multi.exec();
290
290
  } catch (error) {
291
291
  this.emit("error", error);
292
- if (this._throwErrors) {
292
+ if (this._throwOnErrors) {
293
293
  throw error;
294
294
  }
295
295
  }
@@ -307,7 +307,7 @@ var KeyvRedis = class extends Hookified {
307
307
  return exists === 1;
308
308
  } catch (error) {
309
309
  this.emit("error", error);
310
- if (this._throwErrors) {
310
+ if (this._throwOnErrors) {
311
311
  throw error;
312
312
  }
313
313
  return false;
@@ -327,10 +327,10 @@ var KeyvRedis = class extends Hookified {
327
327
  multi.exists(prefixedKey);
328
328
  }
329
329
  const results = await multi.exec();
330
- return results.map((result) => result === 1);
330
+ return results.map((result) => typeof result === "number" && result === 1);
331
331
  } catch (error) {
332
332
  this.emit("error", error);
333
- if (this._throwErrors) {
333
+ if (this._throwOnErrors) {
334
334
  throw error;
335
335
  }
336
336
  return Array.from({ length: keys.length }).fill(false);
@@ -352,7 +352,7 @@ var KeyvRedis = class extends Hookified {
352
352
  return value;
353
353
  } catch (error) {
354
354
  this.emit("error", error);
355
- if (this._throwErrors) {
355
+ if (this._throwOnErrors) {
356
356
  throw error;
357
357
  }
358
358
  return void 0;
@@ -373,7 +373,7 @@ var KeyvRedis = class extends Hookified {
373
373
  return values;
374
374
  } catch (error) {
375
375
  this.emit("error", error);
376
- if (this._throwErrors) {
376
+ if (this._throwOnErrors) {
377
377
  throw error;
378
378
  }
379
379
  return Array.from({ length: keys.length }).fill(void 0);
@@ -393,7 +393,7 @@ var KeyvRedis = class extends Hookified {
393
393
  return deleted > 0;
394
394
  } catch (error) {
395
395
  this.emit("error", error);
396
- if (this._throwErrors) {
396
+ if (this._throwOnErrors) {
397
397
  throw error;
398
398
  }
399
399
  return false;
@@ -425,7 +425,7 @@ var KeyvRedis = class extends Hookified {
425
425
  }
426
426
  } catch (error) {
427
427
  this.emit("error", error);
428
- if (this._throwErrors) {
428
+ if (this._throwOnErrors) {
429
429
  throw error;
430
430
  }
431
431
  }
@@ -439,7 +439,7 @@ var KeyvRedis = class extends Hookified {
439
439
  */
440
440
  async disconnect(force) {
441
441
  if (this._client.isOpen) {
442
- await (force ? this._client.disconnect() : this._client.quit());
442
+ await (force ? this._client.destroy() : this._client.close());
443
443
  }
444
444
  }
445
445
  /**
@@ -481,7 +481,8 @@ var KeyvRedis = class extends Hookified {
481
481
  async getMasterNodes() {
482
482
  if (this.isCluster()) {
483
483
  const cluster = await this.getClient();
484
- return Promise.all(cluster.masters.map(async (main) => cluster.nodeClient(main)));
484
+ const nodes = cluster.masters.map(async (main) => cluster.nodeClient(main));
485
+ return Promise.all(nodes);
485
486
  }
486
487
  return [await this.getClient()];
487
488
  }
@@ -496,7 +497,7 @@ var KeyvRedis = class extends Hookified {
496
497
  const match = namespace ? `${namespace}${this._keyPrefixSeparator}*` : "*";
497
498
  let cursor = "0";
498
499
  do {
499
- const result = await client.scan(Number.parseInt(cursor, 10), { MATCH: match, TYPE: "string" });
500
+ const result = await client.scan(cursor, { MATCH: match, TYPE: "string" });
500
501
  cursor = result.cursor.toString();
501
502
  let { keys } = result;
502
503
  if (!namespace && !this._noNamespaceAffectsAll) {
@@ -533,7 +534,7 @@ var KeyvRedis = class extends Hookified {
533
534
  const match = this._namespace ? `${this._namespace}${this._keyPrefixSeparator}*` : "*";
534
535
  const deletePromises = [];
535
536
  do {
536
- const result = await client.scan(Number.parseInt(cursor, 10), { MATCH: match, COUNT: batchSize, TYPE: "string" });
537
+ const result = await client.scan(cursor, { MATCH: match, COUNT: batchSize, TYPE: "string" });
537
538
  cursor = result.cursor.toString();
538
539
  let { keys } = result;
539
540
  if (keys.length === 0) {
@@ -612,10 +613,7 @@ var KeyvRedis = class extends Hookified {
612
613
  return slotMap;
613
614
  }
614
615
  isClientCluster(client) {
615
- if (client.options === void 0 && client.scan === void 0) {
616
- return true;
617
- }
618
- return false;
616
+ return client.slots !== void 0;
619
617
  }
620
618
  setOptions(options) {
621
619
  if (!options) {
@@ -639,8 +637,8 @@ var KeyvRedis = class extends Hookified {
639
637
  if (options.throwOnConnectError !== void 0) {
640
638
  this._throwOnConnectError = options.throwOnConnectError;
641
639
  }
642
- if (options.throwErrors !== void 0) {
643
- this._throwErrors = options.throwErrors;
640
+ if (options.throwOnErrors !== void 0) {
641
+ this._throwOnErrors = options.throwOnErrors;
644
642
  }
645
643
  if (options.connectionTimeout !== void 0) {
646
644
  this._connectionTimeout = options.connectionTimeout;
@@ -672,7 +670,40 @@ var KeyvRedis = class extends Hookified {
672
670
  function createKeyv(connect, options) {
673
671
  connect ??= "redis://localhost:6379";
674
672
  const adapter = new KeyvRedis(connect, options);
675
- const keyv = new Keyv(adapter, { namespace: options?.namespace, useKeyPrefix: false });
673
+ if (options?.namespace) {
674
+ adapter.namespace = options.namespace;
675
+ const keyv2 = new Keyv(adapter, { namespace: options?.namespace, useKeyPrefix: false });
676
+ if (options?.throwOnConnectError) {
677
+ keyv2.throwOnErrors = true;
678
+ }
679
+ if (options?.throwOnErrors) {
680
+ keyv2.throwOnErrors = true;
681
+ }
682
+ return keyv2;
683
+ }
684
+ const keyv = new Keyv(adapter, { useKeyPrefix: false });
685
+ if (options?.throwOnConnectError) {
686
+ keyv.throwOnErrors = true;
687
+ }
688
+ if (options?.throwOnErrors) {
689
+ keyv.throwOnErrors = true;
690
+ }
691
+ keyv.namespace = void 0;
692
+ return keyv;
693
+ }
694
+ function createKeyvNonBlocking(connect, options) {
695
+ const keyv = createKeyv(connect, options);
696
+ const keyvStore = keyv.store;
697
+ keyvStore.throwOnConnectError = false;
698
+ keyvStore.throwOnErrors = false;
699
+ const redisClient = keyvStore.client;
700
+ if (redisClient.options) {
701
+ redisClient.options.disableOfflineQueue = true;
702
+ if (redisClient.options.socket) {
703
+ redisClient.options.socket.reconnectStrategy = false;
704
+ }
705
+ }
706
+ keyv.throwOnErrors = false;
676
707
  return keyv;
677
708
  }
678
709
  export {
@@ -681,6 +712,7 @@ export {
681
712
  createClient2 as createClient,
682
713
  createCluster2 as createCluster,
683
714
  createKeyv,
715
+ createKeyvNonBlocking,
684
716
  KeyvRedis as default,
685
717
  defaultReconnectStrategy
686
718
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keyv/redis",
3
- "version": "4.6.0",
3
+ "version": "5.0.0",
4
4
  "description": "Redis storage adapter for Keyv",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -34,12 +34,12 @@
34
34
  },
35
35
  "homepage": "https://github.com/jaredwray/keyv",
36
36
  "dependencies": {
37
- "@redis/client": "^1.6.0",
37
+ "@redis/client": "^5.6.0",
38
38
  "cluster-key-slot": "^1.1.2",
39
39
  "hookified": "^1.10.0"
40
40
  },
41
41
  "peerDependencies": {
42
- "keyv": "^5.3.4"
42
+ "keyv": "^5.4.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@faker-js/faker": "^9.9.0",
@@ -49,7 +49,7 @@
49
49
  "tsd": "^0.32.0",
50
50
  "vitest": "^3.2.4",
51
51
  "xo": "^1.1.1",
52
- "@keyv/test-suite": "^2.0.8"
52
+ "@keyv/test-suite": "^2.0.9"
53
53
  },
54
54
  "tsd": {
55
55
  "directory": "test"