ioredis 5.0.2 → 5.0.5

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
@@ -37,7 +37,7 @@ used in the world's biggest online commerce company [Alibaba](http://www.alibaba
37
37
 
38
38
  # Versions
39
39
 
40
- | NPM Version | Branch | Node.js Version | Redis Version |
40
+ | Version | Branch | Node.js Version | Redis Version |
41
41
  | -------------- | ------ | --------------- | --------------- |
42
42
  | 5.x.x (latest) | main | >= 12 | 2.6.12 ~ latest |
43
43
  | 4.x.x | v4 | >= 6 | 2.6.12 ~ 7 |
@@ -48,7 +48,7 @@ Refer to [CHANGELOG.md](CHANGELOG.md) for features and bug fixes introduced in v
48
48
 
49
49
  # Links
50
50
 
51
- - [API Documentation](http://luin.github.io/ioredis/) ([Redis](http://luin.github.io/ioredis/classes/default.html), [Cluster](http://luin.github.io/ioredis/classes/Cluster.html))
51
+ - [API Documentation](https://luin.github.io/ioredis/) ([Redis](https://luin.github.io/ioredis/classes/Redis.html), [Cluster](https://luin.github.io/ioredis/classes/Cluster.html))
52
52
  - [Changelog](CHANGELOG.md)
53
53
  - [Migrating from node_redis](https://github.com/luin/ioredis/wiki/Migrating-from-node_redis)
54
54
 
@@ -164,7 +164,7 @@ See the `examples/` folder for more examples. For example:
164
164
  * [Streams](examples/stream.js)
165
165
  * [Redis Modules](examples/module.js) e.g. RedisJSON
166
166
 
167
- All Redis commands are supported. See [the documentation](http://luin.github.io/ioredis/classes/default.html) for details.
167
+ All Redis commands are supported. See [the documentation](https://luin.github.io/ioredis/classes/Redis.html) for details.
168
168
 
169
169
  ## Connect to Redis
170
170
 
@@ -196,7 +196,7 @@ new Redis("redis://:authpassword@127.0.0.1:6380/4");
196
196
  new Redis("redis://username:authpassword@127.0.0.1:6380/4");
197
197
  ```
198
198
 
199
- See [API Documentation](http://luin.github.io/ioredis/index.html#RedisOptions) for all available options.
199
+ See [API Documentation](https://luin.github.io/ioredis/index.html#RedisOptions) for all available options.
200
200
 
201
201
  ## Pub/Sub
202
202
 
package/built/Redis.d.ts CHANGED
@@ -125,30 +125,20 @@ declare class Redis extends Commander {
125
125
  * });
126
126
  * ```
127
127
  */
128
- monitor(callback: Callback<Redis>): Promise<Redis>;
128
+ monitor(callback?: Callback<Redis>): Promise<Redis>;
129
129
  /**
130
130
  * Send a command to Redis
131
131
  *
132
- * This method is used internally by the `Redis#set`, `Redis#lpush` etc.
133
- * Most of the time you won't invoke this method directly.
134
- * However when you want to send a command that is not supported by ioredis yet,
135
- * this command will be useful.
132
+ * This method is used internally and in most cases you should not
133
+ * use it directly. If you need to send a command that is not supported
134
+ * by the library, you can use the `call` method:
136
135
  *
137
136
  * ```js
138
137
  * const redis = new Redis();
139
138
  *
140
- * // Use callback
141
- * const get = new Command('get', ['foo'], 'utf8', function (err, result) {
142
- * console.log(result);
143
- * });
144
- * redis.sendCommand(get);
145
- *
146
- * // Use promise
147
- * const set = new Command('set', ['foo', 'bar'], 'utf8');
148
- * set.promise.then(function (result) {
149
- * console.log(result);
150
- * });
151
- * redis.sendCommand(set);
139
+ * redis.call('set', 'foo', 'bar');
140
+ * // or
141
+ * redis.call(['set', 'foo', 'bar']);
152
142
  * ```
153
143
  *
154
144
  * @ignore
package/built/Redis.js CHANGED
@@ -135,8 +135,18 @@ class Redis extends Commander_1.default {
135
135
  CONNECT_EVENT = "connect";
136
136
  }
137
137
  _this.stream = stream;
138
- if (typeof options.keepAlive === "number") {
139
- stream.setKeepAlive(true, options.keepAlive);
138
+ if (options.noDelay) {
139
+ stream.setNoDelay(true);
140
+ }
141
+ // Node ignores setKeepAlive before connect, therefore we wait for the event:
142
+ // https://github.com/nodejs/node/issues/31663
143
+ if (typeof options.keepAlive === 'number') {
144
+ if (stream.connecting) {
145
+ stream.once(CONNECT_EVENT, () => stream.setKeepAlive(true, options.keepAlive));
146
+ }
147
+ else {
148
+ stream.setKeepAlive(true, options.keepAlive);
149
+ }
140
150
  }
141
151
  if (stream.connecting) {
142
152
  stream.once(CONNECT_EVENT, eventHandler.connectHandler(_this));
@@ -186,9 +196,6 @@ class Redis extends Commander_1.default {
186
196
  stream.once("error", eventHandler.errorHandler(_this));
187
197
  stream.once("close", eventHandler.closeHandler(_this));
188
198
  }
189
- if (options.noDelay) {
190
- stream.setNoDelay(true);
191
- }
192
199
  const connectionReadyHandler = function () {
193
200
  _this.removeListener("close", connectionCloseHandler);
194
201
  resolve();
@@ -276,7 +283,8 @@ class Redis extends Commander_1.default {
276
283
  monitor: true,
277
284
  lazyConnect: false,
278
285
  });
279
- return (0, standard_as_callback_1.default)(new Promise(function (resolve) {
286
+ return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) {
287
+ monitorInstance.once("error", reject);
280
288
  monitorInstance.once("monitoring", function () {
281
289
  resolve(monitorInstance);
282
290
  });
@@ -285,26 +293,16 @@ class Redis extends Commander_1.default {
285
293
  /**
286
294
  * Send a command to Redis
287
295
  *
288
- * This method is used internally by the `Redis#set`, `Redis#lpush` etc.
289
- * Most of the time you won't invoke this method directly.
290
- * However when you want to send a command that is not supported by ioredis yet,
291
- * this command will be useful.
296
+ * This method is used internally and in most cases you should not
297
+ * use it directly. If you need to send a command that is not supported
298
+ * by the library, you can use the `call` method:
292
299
  *
293
300
  * ```js
294
301
  * const redis = new Redis();
295
302
  *
296
- * // Use callback
297
- * const get = new Command('get', ['foo'], 'utf8', function (err, result) {
298
- * console.log(result);
299
- * });
300
- * redis.sendCommand(get);
301
- *
302
- * // Use promise
303
- * const set = new Command('set', ['foo', 'bar'], 'utf8');
304
- * set.promise.then(function (result) {
305
- * console.log(result);
306
- * });
307
- * redis.sendCommand(set);
303
+ * redis.call('set', 'foo', 'bar');
304
+ * // or
305
+ * redis.call(['set', 'foo', 'bar']);
308
306
  * ```
309
307
  *
310
308
  * @ignore
@@ -347,8 +345,7 @@ class Redis extends Commander_1.default {
347
345
  command.reject(new Error("Stream isn't writeable and enableOfflineQueue options is false"));
348
346
  return command.promise;
349
347
  }
350
- if (command.name === "quit" &&
351
- this.offlineQueue.length === 0) {
348
+ if (command.name === "quit" && this.offlineQueue.length === 0) {
352
349
  this.disconnect();
353
350
  command.resolve(Buffer.from("OK"));
354
351
  return command.promise;
@@ -148,6 +148,9 @@ function executeWithAutoPipelining(client, functionName, commandName, args, call
148
148
  }
149
149
  resolve(value);
150
150
  });
151
+ if (functionName === "call") {
152
+ args.unshift(commandName);
153
+ }
151
154
  pipeline[functionName](...args);
152
155
  });
153
156
  return (0, standard_as_callback_1.default)(autoPipelinePromise, callback);
@@ -3,8 +3,8 @@ import { SrvRecord } from "dns";
3
3
  import { RedisOptions } from "../redis/RedisOptions";
4
4
  import { CommanderOptions } from "../utils/Commander";
5
5
  import { NodeRole } from "./util";
6
- export declare type DNSResolveSrvFunction = (hostname: string, callback: (err: NodeJS.ErrnoException | undefined, records?: SrvRecord[]) => void) => void;
7
- export declare type DNSLookupFunction = (hostname: string, callback: (err: NodeJS.ErrnoException | undefined, address: string, family?: number) => void) => void;
6
+ export declare type DNSResolveSrvFunction = (hostname: string, callback: (err: NodeJS.ErrnoException | null | undefined, records?: SrvRecord[]) => void) => void;
7
+ export declare type DNSLookupFunction = (hostname: string, callback: (err: NodeJS.ErrnoException | null | undefined, address: string, family?: number) => void) => void;
8
8
  export interface NatMap {
9
9
  [key: string]: {
10
10
  host: string;
@@ -88,11 +88,12 @@ class SentinelConnector extends AbstractConnector_1.default {
88
88
  if (this.options.enableTLSForSentinelMode && this.options.tls) {
89
89
  Object.assign(resolved, this.options.tls);
90
90
  this.stream = (0, tls_1.connect)(resolved);
91
+ this.stream.once("secureConnect", this.initFailoverDetector.bind(this));
91
92
  }
92
93
  else {
93
94
  this.stream = (0, net_1.createConnection)(resolved);
95
+ this.stream.once("connect", this.initFailoverDetector.bind(this));
94
96
  }
95
- this.stream.once("connect", () => this.initFailoverDetector());
96
97
  this.stream.once("error", (err) => {
97
98
  this.firstError = err;
98
99
  });
package/built/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default } from "./Redis";
2
+ export type { default as Redis } from "./Redis";
2
3
  export { default as Cluster } from "./cluster";
3
4
  /**
4
5
  * @ignore
@@ -32,8 +33,9 @@ export { SentinelAddress, SentinelConnectionOptions, } from "./connectors/Sentin
32
33
  export { StandaloneConnectionOptions } from "./connectors/StandaloneConnector";
33
34
  export { RedisOptions, CommonRedisOptions } from "./redis/RedisOptions";
34
35
  export { ClusterNode } from "./cluster";
35
- export { ClusterOptions } from "./cluster/ClusterOptions";
36
+ export { ClusterOptions, DNSLookupFunction, DNSResolveSrvFunction, NatMap, } from "./cluster/ClusterOptions";
36
37
  export { NodeRole } from "./cluster/util";
38
+ export type { RedisKey, RedisValue, ChainableCommander, } from "./utils/RedisCommander";
37
39
  export declare const ReplyError: any;
38
40
  /**
39
41
  * @ignore
@@ -6,6 +6,10 @@ export declare type ReconnectOnError = (err: Error) => boolean | 1 | 2;
6
6
  export interface CommonRedisOptions extends CommanderOptions {
7
7
  Connector?: ConnectorConstructor;
8
8
  retryStrategy?: (times: number) => number | void | null;
9
+ /**
10
+ * If a command does not return a reply within a set number of milliseconds,
11
+ * a "Command timed out" error will be thrown.
12
+ */
9
13
  commandTimeout?: number;
10
14
  /**
11
15
  * Enable/disable keep-alive functionality.
@@ -25,13 +29,24 @@ export interface CommonRedisOptions extends CommanderOptions {
25
29
  * @link https://redis.io/commands/client-setname
26
30
  */
27
31
  connectionName?: string;
32
+ /**
33
+ * If set, client will send AUTH command with the value of this option as the first argument when connected.
34
+ * This is supported since Redis 6.
35
+ */
28
36
  username?: string;
37
+ /**
38
+ * If set, client will send AUTH command with the value of this option when connected.
39
+ */
29
40
  password?: string;
30
41
  /**
42
+ * Database index to use.
43
+ *
31
44
  * @default 0
32
45
  */
33
46
  db?: number;
34
47
  /**
48
+ * When the client reconnects, channels subscribed in the previous connection will be
49
+ * resubscribed automatically if `autoResubscribe` is `true`.
35
50
  * @default true
36
51
  */
37
52
  autoResubscribe?: boolean;
@@ -74,14 +89,25 @@ export interface CommonRedisOptions extends CommanderOptions {
74
89
  */
75
90
  stringNumbers?: boolean;
76
91
  /**
92
+ * How long the client will wait before killing a socket due to inactivity during initial connection.
77
93
  * @default 10000
78
94
  */
79
95
  connectTimeout?: number;
80
96
  /**
97
+ * This option is used internally when you call `redis.monitor()` to tell Redis
98
+ * to enter the monitor mode when the connection is established.
99
+ *
81
100
  * @default false
82
101
  */
83
102
  monitor?: boolean;
84
103
  /**
104
+ * The commands that don't get a reply due to the connection to the server is lost are
105
+ * put into a queue and will be resent on reconnect (if allowed by the `retryStrategy` option).
106
+ * This option is used to configure how many reconnection attempts should be allowed before
107
+ * the queue is flushed with a `MaxRetriesPerRequestError` error.
108
+ * Set this options to `null` instead of a number to let commands wait forever
109
+ * until the connection is alive again.
110
+ *
85
111
  * @default 20
86
112
  */
87
113
  maxRetriesPerRequest?: number | null;
@@ -100,14 +126,29 @@ export interface CommonRedisOptions extends CommanderOptions {
100
126
  offlineQueue?: boolean;
101
127
  commandQueue?: boolean;
102
128
  /**
129
+ *
130
+ * By default, if the connection to Redis server has not been established, commands are added to a queue
131
+ * and are executed once the connection is "ready" (when `enableReadyCheck` is true, "ready" means
132
+ * the Redis server has loaded the database from disk, otherwise means the connection to the Redis
133
+ * server has been established). If this option is false, when execute the command when the connection
134
+ * isn't ready, an error will be returned.
135
+ *
103
136
  * @default true
104
137
  */
105
138
  enableOfflineQueue?: boolean;
106
139
  /**
140
+ * The client will sent an INFO command to check whether the server is still loading data from the disk (
141
+ * which happens when the server is just launched) when the connection is established, and only wait until
142
+ * the loading process is finished before emitting the `ready` event.
143
+ *
107
144
  * @default true
108
145
  */
109
146
  enableReadyCheck?: boolean;
110
147
  /**
148
+ * When a Redis instance is initialized, a connection to the server is immediately established. Set this to
149
+ * true will delay the connection to the server until the first command is sent or `redis.connect()` is called
150
+ * explicitly.
151
+ *
111
152
  * @default false
112
153
  */
113
154
  lazyConnect?: boolean;
@@ -195,7 +195,7 @@ function readyHandler(self) {
195
195
  self.setStatus("ready");
196
196
  self.retryAttempts = 0;
197
197
  if (self.options.monitor) {
198
- self.call("monitor");
198
+ self.call("monitor").then(() => self.setStatus("monitoring"), (error) => self.emit("error", error));
199
199
  const { sendCommand } = self;
200
200
  self.sendCommand = function (command) {
201
201
  if (Command_1.default.checkFlag("VALID_IN_MONITOR_MODE", command.name)) {
@@ -207,7 +207,6 @@ function readyHandler(self) {
207
207
  self.once("close", function () {
208
208
  delete self.sendCommand;
209
209
  });
210
- self.setStatus("monitoring");
211
210
  return;
212
211
  }
213
212
  const finalSelect = self.prevCondition
@@ -1,6 +1,6 @@
1
1
  import { ChainableCommander } from "./utils/RedisCommander";
2
2
  export interface Transaction {
3
- pipeline(commands?: [name: string, ...args: unknown[]][]): ChainableCommander;
3
+ pipeline(commands?: unknown[][]): ChainableCommander;
4
4
  multi(options: {
5
5
  pipeline: false;
6
6
  }): Promise<"OK">;
@@ -8,6 +8,6 @@ export interface Transaction {
8
8
  multi(options: {
9
9
  pipeline: true;
10
10
  }): ChainableCommander;
11
- multi(commands?: [name: string, ...args: unknown[]][]): ChainableCommander;
11
+ multi(commands?: unknown[][]): ChainableCommander;
12
12
  }
13
13
  export declare function addTransactionSupport(redis: any): void;
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { Callback } from "../types";
3
- declare type RedisKey = string | Buffer;
4
- declare type RedisValue = string | Buffer | number;
3
+ export declare type RedisKey = string | Buffer;
4
+ export declare type RedisValue = string | Buffer | number;
5
5
  export interface ResultTypes<Result, Context> {
6
6
  default: Promise<Result>;
7
7
  pipeline: ChainableCommander;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ioredis",
3
- "version": "5.0.2",
3
+ "version": "5.0.5",
4
4
  "description": "A robust, performance-focused and full-featured Redis client for Node.js.",
5
5
  "main": "./built/index.js",
6
6
  "types": "./built/index.d.ts",
@@ -57,6 +57,7 @@
57
57
  "@semantic-release/commit-analyzer": "^9.0.2",
58
58
  "@semantic-release/git": "^10.0.1",
59
59
  "@types/chai": "^4.3.0",
60
+ "@types/chai-as-promised": "^7.1.5",
60
61
  "@types/debug": "^4.1.5",
61
62
  "@types/lodash.defaults": "^4.2.6",
62
63
  "@types/lodash.isarguments": "^3.1.6",