@keyv/redis 4.0.0 → 4.0.2

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
@@ -47,6 +47,16 @@ const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379'));
47
47
  keyv.on('error', handleConnectionError);
48
48
  ```
49
49
 
50
+ Here is the same example but with the `Keyv` instance created with the `createKeyv` function:
51
+
52
+ ```js
53
+ import { createKeyv } from '@keyv/redis';
54
+
55
+ const keyv = createKeyv('redis://user:pass@localhost:6379', { namespace: 'my-namespace' });
56
+ ```
57
+
58
+ You only have to import the `@keyv/redis` library if you are using the `createKeyv` function. 🎉 Otherwise, you can import `Keyv` and `@keyv/redis` independently.
59
+
50
60
  Here you can pass in the Redis options directly:
51
61
 
52
62
  ```js
@@ -81,17 +91,7 @@ const keyvRedis = new KeyvRedis(redis);
81
91
  const keyv = new Keyv({ store: keyvRedis });
82
92
  ```
83
93
 
84
- Here is the same example but with the `Keyv` instance created with the `createKeyv` function:
85
-
86
- ```js
87
- import { createKeyv } from '@keyv/redis';
88
-
89
- const keyv = createKeyv('redis://user:pass@localhost:6379', { namespace: 'my-namespace' });
90
- ```
91
-
92
- You only have to import the `@keyv/redis` library if you are using the `createKeyv` function. 🎉 Otherwise, you can import `Keyv` and `@keyv/redis` independently.
93
-
94
- # Namspaces
94
+ # Namespaces
95
95
 
96
96
  You can set a namespace for your keys. This is useful if you want to manage your keys in a more organized way. Here is an example of how to set a namespace:
97
97
 
@@ -121,7 +121,7 @@ With namespaces being prefix based it is critical to understand some of the perf
121
121
 
122
122
  * `useUnlink` - This option is set to `true` by default. This is because `UNLINK` is a non-blocking command that is more efficient than `DEL`. If you are not using `UNLINK` and are doing a lot of deletes it is recommended to set this option to `true`.
123
123
 
124
- * `setMany`, `getMany`, `deleteMany` - These methods are more efficient than their singular counterparts. If you are doing multiple operations it is recommended to use these methods.
124
+ * `setMany`, `getMany`, `deleteMany` - These methods are more efficient than their singular counterparts. These will be used by default in the `Keyv` library such as when using `keyv.delete(string[])` it will use `deleteMany()`.
125
125
 
126
126
  If you want to see even better performance please see the [Using Cacheable with Redis](#using-cacheable-with-redis) section as it has non-blocking and in-memory primary caching that goes along well with this library and Keyv.
127
127
 
@@ -183,6 +183,10 @@ const cluster = createCluster({
183
183
  const keyv = new Keyv({ store: new KeyvRedis(cluster) });
184
184
  ```
185
185
 
186
+ There are some features that are not supported in clustering such as `clear()` and `iterator()`. This is because the `SCAN` command is not supported in clustering. If you need to clear or delete keys you can use the `deleteMany()` method.
187
+
188
+ You can learn more about the `createCluster` function in the [documentation](https://github.com/redis/node-redis/blob/master/docs/clustering.md) at https://github.com/redis/node-redis/tree/master/docs.
189
+
186
190
  Here is an example of how to use TLS:
187
191
 
188
192
  ```js
@@ -227,7 +231,25 @@ const keyv = new Keyv({ store: new KeyvRedis(tlsOptions) });
227
231
 
228
232
  # Migrating from v3 to v4
229
233
 
230
- The main change in v4 is the removal of the `ioredis` library in favor of the `@keyv/redis` library. This was done to provide a more consistent experience across all Keyv storage adapters. The `@keyv/redis` library is a wrapper around the `redis` library and provides a more consistent experience across all Keyv storage adapters. The only other change is that we no longer do redis sets as they caused performance issues.
234
+ Overall the API is the same as v3 with additional options and performance improvements. Here are the main changes:
235
+ * The `ioredis` library has been removed in favor of the `redis` aka `node-redis` library. If you want to use ioredis you can use `@keyv/keyval`
236
+ * The `useUnlink` option has been added to use `UNLINK` instead of `DEL` and set to true by default.
237
+ * The `clearBatchSize` option has been added to set the number of keys to delete in a single batch.
238
+ * The `clear()` and `delete()` methods now use `UNLINK` instead of `DEL`. If you want to use `DEL` you can set the `useUnlink` option to `false`.
239
+ * BREAKING: We no longer support redis sets. This is due to the fact that it caused significant performance issues and was not a good fit for the library.
240
+ * BREAKING: YOUR PREVIOUS KEYS WILL NOT BE VALID. This is because of the fixe of the namespace support and how it is handled. Now, when using `keyv` with `@keyv/redis` as the storage adapter you can do the following:
241
+
242
+ ```js
243
+ import Keyv from 'keyv';
244
+ import KeyvRedis from '@keyv/redis';
245
+
246
+ const redis = new KeyvRedis('redis://user:pass@localhost:6379');
247
+ const keyv = new Keyv({ store: redis, namespace: 'my-namespace', useKeyPrefix: false });
248
+ ```
249
+
250
+ This will make it so the storage adapter `@keyv/redis` will handle the namespace and not the `keyv` instance. If you leave it on it will just look duplicated like `my-namespace:my-namespace:key`.
251
+
252
+
231
253
 
232
254
  # About Redis Sets and its Support in v4
233
255
 
package/dist/index.cjs CHANGED
@@ -37,12 +37,12 @@ __export(src_exports, {
37
37
  default: () => KeyvRedis
38
38
  });
39
39
  module.exports = __toCommonJS(src_exports);
40
- var import_events = __toESM(require("events"), 1);
40
+ var import_node_events = __toESM(require("events"), 1);
41
41
  var import_redis = require("redis");
42
42
  var import_keyv = require("keyv");
43
43
  var import_redis2 = require("redis");
44
44
  var import_keyv2 = require("keyv");
45
- var KeyvRedis = class extends import_events.default {
45
+ var KeyvRedis = class extends import_node_events.default {
46
46
  _client = (0, import_redis.createClient)();
47
47
  _namespace;
48
48
  _keyPrefixSeparator = "::";
@@ -59,9 +59,9 @@ var KeyvRedis = class extends import_events.default {
59
59
  if (typeof connect === "string") {
60
60
  this._client = (0, import_redis.createClient)({ url: connect });
61
61
  } else if (connect.connect !== void 0) {
62
- this._client = connect;
62
+ this._client = this.isClientCluster(connect) ? connect : connect;
63
63
  } else if (connect instanceof Object) {
64
- this._client = (0, import_redis.createClient)(connect);
64
+ this._client = connect.rootNodes === void 0 ? (0, import_redis.createClient)(connect) : (0, import_redis.createCluster)(connect);
65
65
  }
66
66
  }
67
67
  this.setOptions(options);
@@ -84,13 +84,18 @@ var KeyvRedis = class extends import_events.default {
84
84
  * Get the options for the adapter.
85
85
  */
86
86
  get opts() {
87
- return {
87
+ let url = "";
88
+ if (this._client.options) {
89
+ url = this._client.options?.url ?? "redis://localhost:6379";
90
+ }
91
+ const results = {
88
92
  namespace: this._namespace,
89
93
  keyPrefixSeparator: this._keyPrefixSeparator,
90
94
  clearBatchSize: this._clearBatchSize,
91
95
  dialect: "redis",
92
- url: this._client?.options?.url ?? "redis://localhost:6379"
96
+ url
93
97
  };
98
+ return results;
94
99
  }
95
100
  /**
96
101
  * Set the options for the adapter.
@@ -255,11 +260,7 @@ var KeyvRedis = class extends import_events.default {
255
260
  const client = await this.getClient();
256
261
  key = this.createKeyPrefix(key, this._namespace);
257
262
  let deleted = 0;
258
- if (this._useUnlink) {
259
- deleted = await client.unlink(key);
260
- } else {
261
- deleted = await client.del(key);
262
- }
263
+ deleted = await (this._useUnlink ? client.unlink(key) : client.del(key));
263
264
  return deleted > 0;
264
265
  }
265
266
  /**
@@ -320,12 +321,31 @@ var KeyvRedis = class extends import_events.default {
320
321
  }
321
322
  return key;
322
323
  }
324
+ /**
325
+ * Is the client a cluster.
326
+ * @returns {boolean} - true if the client is a cluster, false if not
327
+ */
328
+ isCluster() {
329
+ return this.isClientCluster(this._client);
330
+ }
323
331
  /**
324
332
  * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
325
333
  * @param {string} [namespace] - the namespace to iterate over
326
334
  * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
327
335
  */
328
336
  async *iterator(namespace) {
337
+ if (this.isCluster()) {
338
+ throw new Error("Iterating over keys in a cluster is not supported.");
339
+ } else {
340
+ yield* this.iteratorClient(namespace);
341
+ }
342
+ }
343
+ /**
344
+ * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
345
+ * @param {string} [namespace] - the namespace to iterate over
346
+ * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
347
+ */
348
+ async *iteratorClient(namespace) {
329
349
  const client = await this.getClient();
330
350
  const match = namespace ? `${namespace}${this._keyPrefixSeparator}*` : "*";
331
351
  let cursor = "0";
@@ -348,13 +368,13 @@ var KeyvRedis = class extends import_events.default {
348
368
  }
349
369
  /**
350
370
  * Clear all keys in the store.
351
- * IMPORTANT: this can cause performance issues if there are a large number of keys in the store. Use with caution as not recommended for production.
371
+ * IMPORTANT: this can cause performance issues if there are a large number of keys in the store and worse with clusters. Use with caution as not recommended for production.
352
372
  * If a namespace is not set it will clear all keys with no prefix.
353
373
  * If a namespace is set it will clear all keys with that namespace.
354
374
  * @returns {Promise<void>}
355
375
  */
356
376
  async clear() {
357
- await this.clearNamespace(this._namespace);
377
+ await (this.isCluster() ? this.clearNamespaceCluster(this._namespace) : this.clearNamespace(this._namespace));
358
378
  }
359
379
  async clearNamespace(namespace) {
360
380
  try {
@@ -384,6 +404,15 @@ var KeyvRedis = class extends import_events.default {
384
404
  this.emit("error", error);
385
405
  }
386
406
  }
407
+ async clearNamespaceCluster(namespace) {
408
+ throw new Error("Clearing all keys in a cluster is not supported.");
409
+ }
410
+ isClientCluster(client) {
411
+ if (client.options === void 0 && client.scan === void 0) {
412
+ return true;
413
+ }
414
+ return false;
415
+ }
387
416
  setOptions(options) {
388
417
  if (!options) {
389
418
  return;
@@ -409,7 +438,7 @@ var KeyvRedis = class extends import_events.default {
409
438
  };
410
439
  function createKeyv(connect, options) {
411
440
  const adapter = new KeyvRedis(connect, options);
412
- const keyv = new import_keyv.Keyv({ store: adapter, namespace: options?.namespace });
441
+ const keyv = new import_keyv.Keyv({ store: adapter, namespace: options?.namespace, useKeyPrefix: false });
413
442
  return keyv;
414
443
  }
415
444
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import EventEmitter from 'events';
2
- import { RedisClientOptions, RedisClientType } from 'redis';
3
- export { RedisClientOptions, RedisClientType, createClient, createCluster } from 'redis';
1
+ import EventEmitter from 'node:events';
2
+ import { RedisClientType, RedisClusterType, RedisModules, RedisFunctions, RedisScripts, RedisClientOptions, RedisClusterOptions } from 'redis';
3
+ export { RedisClientOptions, RedisClientType, RedisClusterOptions, RedisClusterType, createClient, createCluster } from 'redis';
4
4
  import { KeyvStoreAdapter, Keyv } from 'keyv';
5
5
  export { Keyv } from 'keyv';
6
6
 
@@ -46,6 +46,7 @@ type KeyvRedisEntry<T> = {
46
46
  */
47
47
  ttl?: number;
48
48
  };
49
+ type RedisClientConnectionType = RedisClientType | RedisClusterType<RedisModules, RedisFunctions, RedisScripts>;
49
50
  declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
50
51
  private _client;
51
52
  private _namespace;
@@ -57,15 +58,15 @@ declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
57
58
  * @param {string | RedisClientOptions | RedisClientType} [connect] How to connect to the Redis server. If string pass in the url, if object pass in the options, if RedisClient pass in the client.
58
59
  * @param {KeyvRedisOptions} [options] Options for the adapter such as namespace, keyPrefixSeparator, and clearBatchSize.
59
60
  */
60
- constructor(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions);
61
+ constructor(connect?: string | RedisClientOptions | RedisClusterOptions | RedisClientConnectionType, options?: KeyvRedisOptions);
61
62
  /**
62
63
  * Get the Redis client.
63
64
  */
64
- get client(): RedisClientType;
65
+ get client(): RedisClientConnectionType;
65
66
  /**
66
67
  * Set the Redis client.
67
68
  */
68
- set client(value: RedisClientType);
69
+ set client(value: RedisClientConnectionType);
69
70
  /**
70
71
  * Get the options for the adapter.
71
72
  */
@@ -113,7 +114,7 @@ declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
113
114
  /**
114
115
  * Get the Redis URL used to connect to the server. This is used to get a connected client.
115
116
  */
116
- getClient(): Promise<RedisClientType>;
117
+ getClient(): Promise<RedisClientConnectionType>;
117
118
  /**
118
119
  * Set a key value pair in the store. TTL is in milliseconds.
119
120
  * @param {string} key - the key to set
@@ -181,30 +182,43 @@ declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
181
182
  * @returns {string} - the key without the namespace such as 'key'
182
183
  */
183
184
  getKeyWithoutPrefix(key: string, namespace?: string): string;
185
+ /**
186
+ * Is the client a cluster.
187
+ * @returns {boolean} - true if the client is a cluster, false if not
188
+ */
189
+ isCluster(): boolean;
184
190
  /**
185
191
  * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
186
192
  * @param {string} [namespace] - the namespace to iterate over
187
193
  * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
188
194
  */
189
195
  iterator<Value>(namespace?: string): AsyncGenerator<[string, Value | undefined], void, unknown>;
196
+ /**
197
+ * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
198
+ * @param {string} [namespace] - the namespace to iterate over
199
+ * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
200
+ */
201
+ iteratorClient<Value>(namespace?: string): AsyncGenerator<[string, Value | undefined], void, unknown>;
190
202
  /**
191
203
  * Clear all keys in the store.
192
- * IMPORTANT: this can cause performance issues if there are a large number of keys in the store. Use with caution as not recommended for production.
204
+ * IMPORTANT: this can cause performance issues if there are a large number of keys in the store and worse with clusters. Use with caution as not recommended for production.
193
205
  * If a namespace is not set it will clear all keys with no prefix.
194
206
  * If a namespace is set it will clear all keys with that namespace.
195
207
  * @returns {Promise<void>}
196
208
  */
197
209
  clear(): Promise<void>;
198
210
  private clearNamespace;
211
+ private clearNamespaceCluster;
212
+ private isClientCluster;
199
213
  private setOptions;
200
214
  private initClient;
201
215
  }
202
216
  /**
203
- * Will create a Keyv instance with the Redis adapter.
217
+ * Will create a Keyv instance with the Redis adapter. This will also set the namespace and useKeyPrefix to false.
204
218
  * @param connect
205
219
  * @param options
206
220
  * @returns {Keyv} - Keyv instance with the Redis adapter
207
221
  */
208
222
  declare function createKeyv(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions): Keyv;
209
223
 
210
- export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, createKeyv, KeyvRedis as default };
224
+ export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, type RedisClientConnectionType, createKeyv, KeyvRedis as default };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import EventEmitter from 'events';
2
- import { RedisClientOptions, RedisClientType } from 'redis';
3
- export { RedisClientOptions, RedisClientType, createClient, createCluster } from 'redis';
1
+ import EventEmitter from 'node:events';
2
+ import { RedisClientType, RedisClusterType, RedisModules, RedisFunctions, RedisScripts, RedisClientOptions, RedisClusterOptions } from 'redis';
3
+ export { RedisClientOptions, RedisClientType, RedisClusterOptions, RedisClusterType, createClient, createCluster } from 'redis';
4
4
  import { KeyvStoreAdapter, Keyv } from 'keyv';
5
5
  export { Keyv } from 'keyv';
6
6
 
@@ -46,6 +46,7 @@ type KeyvRedisEntry<T> = {
46
46
  */
47
47
  ttl?: number;
48
48
  };
49
+ type RedisClientConnectionType = RedisClientType | RedisClusterType<RedisModules, RedisFunctions, RedisScripts>;
49
50
  declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
50
51
  private _client;
51
52
  private _namespace;
@@ -57,15 +58,15 @@ declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
57
58
  * @param {string | RedisClientOptions | RedisClientType} [connect] How to connect to the Redis server. If string pass in the url, if object pass in the options, if RedisClient pass in the client.
58
59
  * @param {KeyvRedisOptions} [options] Options for the adapter such as namespace, keyPrefixSeparator, and clearBatchSize.
59
60
  */
60
- constructor(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions);
61
+ constructor(connect?: string | RedisClientOptions | RedisClusterOptions | RedisClientConnectionType, options?: KeyvRedisOptions);
61
62
  /**
62
63
  * Get the Redis client.
63
64
  */
64
- get client(): RedisClientType;
65
+ get client(): RedisClientConnectionType;
65
66
  /**
66
67
  * Set the Redis client.
67
68
  */
68
- set client(value: RedisClientType);
69
+ set client(value: RedisClientConnectionType);
69
70
  /**
70
71
  * Get the options for the adapter.
71
72
  */
@@ -113,7 +114,7 @@ declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
113
114
  /**
114
115
  * Get the Redis URL used to connect to the server. This is used to get a connected client.
115
116
  */
116
- getClient(): Promise<RedisClientType>;
117
+ getClient(): Promise<RedisClientConnectionType>;
117
118
  /**
118
119
  * Set a key value pair in the store. TTL is in milliseconds.
119
120
  * @param {string} key - the key to set
@@ -181,30 +182,43 @@ declare class KeyvRedis extends EventEmitter implements KeyvStoreAdapter {
181
182
  * @returns {string} - the key without the namespace such as 'key'
182
183
  */
183
184
  getKeyWithoutPrefix(key: string, namespace?: string): string;
185
+ /**
186
+ * Is the client a cluster.
187
+ * @returns {boolean} - true if the client is a cluster, false if not
188
+ */
189
+ isCluster(): boolean;
184
190
  /**
185
191
  * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
186
192
  * @param {string} [namespace] - the namespace to iterate over
187
193
  * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
188
194
  */
189
195
  iterator<Value>(namespace?: string): AsyncGenerator<[string, Value | undefined], void, unknown>;
196
+ /**
197
+ * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
198
+ * @param {string} [namespace] - the namespace to iterate over
199
+ * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
200
+ */
201
+ iteratorClient<Value>(namespace?: string): AsyncGenerator<[string, Value | undefined], void, unknown>;
190
202
  /**
191
203
  * Clear all keys in the store.
192
- * IMPORTANT: this can cause performance issues if there are a large number of keys in the store. Use with caution as not recommended for production.
204
+ * IMPORTANT: this can cause performance issues if there are a large number of keys in the store and worse with clusters. Use with caution as not recommended for production.
193
205
  * If a namespace is not set it will clear all keys with no prefix.
194
206
  * If a namespace is set it will clear all keys with that namespace.
195
207
  * @returns {Promise<void>}
196
208
  */
197
209
  clear(): Promise<void>;
198
210
  private clearNamespace;
211
+ private clearNamespaceCluster;
212
+ private isClientCluster;
199
213
  private setOptions;
200
214
  private initClient;
201
215
  }
202
216
  /**
203
- * Will create a Keyv instance with the Redis adapter.
217
+ * Will create a Keyv instance with the Redis adapter. This will also set the namespace and useKeyPrefix to false.
204
218
  * @param connect
205
219
  * @param options
206
220
  * @returns {Keyv} - Keyv instance with the Redis adapter
207
221
  */
208
222
  declare function createKeyv(connect?: string | RedisClientOptions | RedisClientType, options?: KeyvRedisOptions): Keyv;
209
223
 
210
- export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, createKeyv, KeyvRedis as default };
224
+ export { type KeyvRedisEntry, type KeyvRedisOptions, type KeyvRedisPropertyOptions, type RedisClientConnectionType, createKeyv, KeyvRedis as default };
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
1
  // src/index.ts
2
- import EventEmitter from "events";
3
- import { createClient } from "redis";
2
+ import EventEmitter from "node:events";
3
+ import {
4
+ createClient,
5
+ createCluster
6
+ } from "redis";
4
7
  import { Keyv } from "keyv";
5
8
  import {
6
9
  createClient as createClient2,
7
- createCluster
10
+ createCluster as createCluster2
8
11
  } from "redis";
9
12
  import {
10
13
  Keyv as Keyv2
@@ -26,9 +29,9 @@ var KeyvRedis = class extends EventEmitter {
26
29
  if (typeof connect === "string") {
27
30
  this._client = createClient({ url: connect });
28
31
  } else if (connect.connect !== void 0) {
29
- this._client = connect;
32
+ this._client = this.isClientCluster(connect) ? connect : connect;
30
33
  } else if (connect instanceof Object) {
31
- this._client = createClient(connect);
34
+ this._client = connect.rootNodes === void 0 ? createClient(connect) : createCluster(connect);
32
35
  }
33
36
  }
34
37
  this.setOptions(options);
@@ -51,13 +54,18 @@ var KeyvRedis = class extends EventEmitter {
51
54
  * Get the options for the adapter.
52
55
  */
53
56
  get opts() {
54
- return {
57
+ let url = "";
58
+ if (this._client.options) {
59
+ url = this._client.options?.url ?? "redis://localhost:6379";
60
+ }
61
+ const results = {
55
62
  namespace: this._namespace,
56
63
  keyPrefixSeparator: this._keyPrefixSeparator,
57
64
  clearBatchSize: this._clearBatchSize,
58
65
  dialect: "redis",
59
- url: this._client?.options?.url ?? "redis://localhost:6379"
66
+ url
60
67
  };
68
+ return results;
61
69
  }
62
70
  /**
63
71
  * Set the options for the adapter.
@@ -222,11 +230,7 @@ var KeyvRedis = class extends EventEmitter {
222
230
  const client = await this.getClient();
223
231
  key = this.createKeyPrefix(key, this._namespace);
224
232
  let deleted = 0;
225
- if (this._useUnlink) {
226
- deleted = await client.unlink(key);
227
- } else {
228
- deleted = await client.del(key);
229
- }
233
+ deleted = await (this._useUnlink ? client.unlink(key) : client.del(key));
230
234
  return deleted > 0;
231
235
  }
232
236
  /**
@@ -287,12 +291,31 @@ var KeyvRedis = class extends EventEmitter {
287
291
  }
288
292
  return key;
289
293
  }
294
+ /**
295
+ * Is the client a cluster.
296
+ * @returns {boolean} - true if the client is a cluster, false if not
297
+ */
298
+ isCluster() {
299
+ return this.isClientCluster(this._client);
300
+ }
290
301
  /**
291
302
  * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
292
303
  * @param {string} [namespace] - the namespace to iterate over
293
304
  * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
294
305
  */
295
306
  async *iterator(namespace) {
307
+ if (this.isCluster()) {
308
+ throw new Error("Iterating over keys in a cluster is not supported.");
309
+ } else {
310
+ yield* this.iteratorClient(namespace);
311
+ }
312
+ }
313
+ /**
314
+ * Get an async iterator for the keys and values in the store. If a namespace is provided, it will only iterate over keys with that namespace.
315
+ * @param {string} [namespace] - the namespace to iterate over
316
+ * @returns {AsyncGenerator<[string, T | undefined], void, unknown>} - async iterator with key value pairs
317
+ */
318
+ async *iteratorClient(namespace) {
296
319
  const client = await this.getClient();
297
320
  const match = namespace ? `${namespace}${this._keyPrefixSeparator}*` : "*";
298
321
  let cursor = "0";
@@ -315,13 +338,13 @@ var KeyvRedis = class extends EventEmitter {
315
338
  }
316
339
  /**
317
340
  * Clear all keys in the store.
318
- * IMPORTANT: this can cause performance issues if there are a large number of keys in the store. Use with caution as not recommended for production.
341
+ * IMPORTANT: this can cause performance issues if there are a large number of keys in the store and worse with clusters. Use with caution as not recommended for production.
319
342
  * If a namespace is not set it will clear all keys with no prefix.
320
343
  * If a namespace is set it will clear all keys with that namespace.
321
344
  * @returns {Promise<void>}
322
345
  */
323
346
  async clear() {
324
- await this.clearNamespace(this._namespace);
347
+ await (this.isCluster() ? this.clearNamespaceCluster(this._namespace) : this.clearNamespace(this._namespace));
325
348
  }
326
349
  async clearNamespace(namespace) {
327
350
  try {
@@ -351,6 +374,15 @@ var KeyvRedis = class extends EventEmitter {
351
374
  this.emit("error", error);
352
375
  }
353
376
  }
377
+ async clearNamespaceCluster(namespace) {
378
+ throw new Error("Clearing all keys in a cluster is not supported.");
379
+ }
380
+ isClientCluster(client) {
381
+ if (client.options === void 0 && client.scan === void 0) {
382
+ return true;
383
+ }
384
+ return false;
385
+ }
354
386
  setOptions(options) {
355
387
  if (!options) {
356
388
  return;
@@ -376,13 +408,13 @@ var KeyvRedis = class extends EventEmitter {
376
408
  };
377
409
  function createKeyv(connect, options) {
378
410
  const adapter = new KeyvRedis(connect, options);
379
- const keyv = new Keyv({ store: adapter, namespace: options?.namespace });
411
+ const keyv = new Keyv({ store: adapter, namespace: options?.namespace, useKeyPrefix: false });
380
412
  return keyv;
381
413
  }
382
414
  export {
383
415
  Keyv2 as Keyv,
384
416
  createClient2 as createClient,
385
- createCluster,
417
+ createCluster2 as createCluster,
386
418
  createKeyv,
387
419
  KeyvRedis as default
388
420
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keyv/redis",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "Redis storage adapter for Keyv",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -12,23 +12,6 @@
12
12
  "import": "./dist/index.js"
13
13
  }
14
14
  },
15
- "xo": {
16
- "rules": {
17
- "import/no-named-as-default": "off",
18
- "unicorn/prefer-module": "off",
19
- "unicorn/prefer-event-target": "off",
20
- "unicorn/prefer-node-protocol": "off",
21
- "unicorn/no-typeof-undefined": "off",
22
- "import/extensions": "off",
23
- "@typescript-eslint/no-unsafe-call": "off",
24
- "@typescript-eslint/no-unsafe-assignment": "off",
25
- "@typescript-eslint/no-unsafe-return": "off",
26
- "unicorn/prefer-ternary": "off",
27
- "unicorn/no-array-callback-reference": "off",
28
- "import/no-extraneous-dependencies": "off",
29
- "@typescript-eslint/no-confusing-void-expression": "off"
30
- }
31
- },
32
15
  "repository": {
33
16
  "type": "git",
34
17
  "url": "git+https://github.com/jaredwray/keyv.git"
@@ -51,14 +34,16 @@
51
34
  },
52
35
  "homepage": "https://github.com/jaredwray/keyv",
53
36
  "dependencies": {
54
- "redis": "^4.7.0",
55
- "keyv": "*"
37
+ "keyv": "*",
38
+ "redis": "^4.7.0"
56
39
  },
57
40
  "devDependencies": {
58
41
  "@keyv/test-suite": "*",
42
+ "@vitest/coverage-v8": "^2.1.5",
59
43
  "rimraf": "^6.0.1",
60
44
  "timekeeper": "^2.3.1",
61
45
  "tsd": "^0.31.2",
46
+ "vitest": "^2.1.5",
62
47
  "xo": "^0.59.3"
63
48
  },
64
49
  "tsd": {