redis 3.0.1 → 3.1.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
@@ -9,12 +9,14 @@
9
9
  ---
10
10
 
11
11
  <p align="center">
12
- <a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/dm/redis.svg?style=flat-square" alt="NPM downloads"></a>
13
- <a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/v/redis.svg?style=flat-square" alt="NPM version"></a>
14
- <a href="https://travis-ci.org/NodeRedis/node-redis"><img src="https://travis-ci.org/NodeRedis/node-redis.svg?style=flat-square&branch=master" alt="Build Status" /></a>
15
- <a href="https://ci.appveyor.com/project/BridgeAR/node-redis/branch/master"><img src="https://img.shields.io/appveyor/ci/BridgeAR/node-redis/master.svg?style=flat-square&label=Windows%20Tests" alt="Windows Tests" /></a>
16
- <a href="https://coveralls.io/r/NodeRedis/node-redis?branch="><img src="https://coveralls.io/repos/NodeRedis/node-redis/badge.svg?style=flat-square&branch=" alt="Coverage Status" /></a>
17
- <a href="https://twitter.com/NodeRedis"><img src="https://img.shields.io/twitter/follow/NodeRedis.svg?style=flat-square&colorA=1da1f2&colorB=&label=Follow%20on%20Twitter" alt="Follow on Twitter"></a>
12
+ <a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/dm/redis.svg" alt="NPM downloads"></a>
13
+ <a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/v/redis.svg" alt="NPM version"></a>
14
+ <a href="https://github.com/NodeRedis/node-redis/actions?query=workflow%3ATests"><img src="https://github.com/NodeRedis/node-redis/workflows/Tests/badge.svg" alt="Build Status" /></a>
15
+ <a href="https://github.com/NodeRedis/node-redis/actions?query=workflow%3A%22Tests+Windows%22"><img src="https://github.com/NodeRedis/node-redis/workflows/Tests%20Windows/badge.svg" alt="Windows Build Status" /></a>
16
+ <a href="https://coveralls.io/r/NodeRedis/node-redis?branch="><img src="https://coveralls.io/repos/NodeRedis/node-redis/badge.svg?branch=master" alt="Coverage Status" /></a>
17
+ <a href="https://codeclimate.com/github/NodeRedis/node-redis/maintainability"><img src="https://api.codeclimate.com/v1/badges/f6d7063243c234237e73/maintainability" /></a>
18
+ <a href="https://lgtm.com/projects/g/NodeRedis/node-redis/context:javascript"><img src="https://img.shields.io/lgtm/grade/javascript/g/NodeRedis/node-redis.svg?logo=lgtm&logoWidth=18" alt="Coverage Status" /></a>
19
+ <a href="https://discord.gg/XMMVgxUm"><img src="https://img.shields.io/discord/697882427875393627?style=flat-square" /></a>
18
20
  </p>
19
21
 
20
22
  ---
@@ -171,15 +173,16 @@ using unix sockets if possible to increase throughput.
171
173
  | port | 6379 | Port of the Redis server |
172
174
  | path | null | The UNIX socket string of the Redis server |
173
175
  | url | null | The URL of the Redis server. Format: `[redis[s]:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]` (More info avaliable at [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)). |
174
- | string_numbers | null | Set to `true`, Node Redis will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
176
+ | string_numbers | null | Set to `true`, Node Redis will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
175
177
  | return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
176
178
  | detect_buffers | false | If set to `true`, then replies will be sent to callbacks as Buffers. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. **Note**: This doesn't work properly with the pubsub mode. A subscriber has to either always return Strings or Buffers. |
177
179
  | socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
178
180
  | socket_initial_delay | 0 | Initial Delay in milliseconds, and this will also behave the interval keep alive message sending to Redis. |
179
- | no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, Node Redis has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
181
+ | no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, Node Redis has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
180
182
  | enable_offline_queue | true | By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Setting `enable_offline_queue` to `false` will disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified. |
181
183
  | retry_unfulfilled_commands | false | If set to `true`, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g. `incr`). This is especially useful if you use blocking commands. |
182
- | password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` **Note** Node Redis < 2.5 must use `auth_pass` |
184
+ | password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` **Note** Node Redis < 2.5 must use `auth_pass` |
185
+ | user | null | The ACL user (only valid when `password` is set) |
183
186
  | db | null | If set, client will run Redis `select` command on connect. |
184
187
  | family | IPv4 | You can force using IPv6 if you set the family to 'IPv6'. See Node.js [net](https://nodejs.org/api/net.html) or [dns](https://nodejs.org/api/dns.html) modules on how to use the family type. |
185
188
  | disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
@@ -187,6 +190,7 @@ using unix sockets if possible to increase throughput.
187
190
  | tls | null | An object containing options to pass to [tls.connect](http://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback) to set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel). |
188
191
  | prefix | null | A string used to prefix all used keys (e.g. `namespace:test`). Please be aware that the `keys` command will not be prefixed. The `keys` command has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed. |
189
192
  | retry_strategy | function | A function that receives an options object as parameter including the retry `attempt`, the `total_retry_time` indicating how much time passed since the last time connected, the `error` why the connection was lost and the number of `times_connected` in total. If you return a number from this function, the retry will happen exactly after that time in milliseconds. If you return a non-number, no further retry will happen and all offline commands are flushed with errors. Return an error to return that specific error to all offline commands. Example below. |
193
+ | connect_timeout | 3600000 | In milliseconds. This should only be the timeout for connecting to redis, but for now it interferes with `retry_strategy` and stops it from reconnecting after this timeout. |
190
194
 
191
195
  **`detect_buffers` example:**
192
196
 
@@ -394,7 +398,7 @@ responses using JavaScript syntax.
394
398
  ```js
395
399
  client.hmset("key", "foo", "bar", "hello", "world");
396
400
 
397
- client.hgetall("hosts", function(err, value) {
401
+ client.hgetall("key", function(err, value) {
398
402
  console.log(value.foo); // > "bar"
399
403
  console.log(value.hello); // > "world"
400
404
  });
@@ -638,7 +642,7 @@ client.watch("foo", function(watchError) {
638
642
  * If err is null, it means Redis successfully attempted
639
643
  * the operation.
640
644
  */
641
- if (execError) throw err;
645
+ if (execError) throw execError;
642
646
 
643
647
  /**
644
648
  * If results === null, it means that a concurrent client
@@ -675,7 +679,7 @@ clients.watcher.watch("foo", function(watchError) {
675
679
 
676
680
  // if you comment out the next line, the transaction will work
677
681
  clients.modifier.set("foo", Math.random(), setError => {
678
- if (setError) throw err;
682
+ if (setError) throw setError;
679
683
  });
680
684
 
681
685
  // using a setTimeout here to ensure that the MULTI/EXEC will come after the SET.
@@ -847,19 +851,19 @@ non-blocking ones may be queued up until after the blocking ones finish.
847
851
  Another reason to use duplicate() is when multiple DBs on the same server are
848
852
  accessed via the redis SELECT command. Each DB could use its own connection.
849
853
 
850
- ### `client.send_command(command_name[, [args][, callback]])`
854
+ ### `client.sendCommand(command_name[, [args][, callback]])`
851
855
 
852
856
  All Redis commands have been added to the `client` object. However, if new
853
857
  commands are introduced before this library is updated or if you want to add
854
- individual commands you can use `send_command()` to send arbitrary commands to
858
+ individual commands you can use `sendCommand()` to send arbitrary commands to
855
859
  Redis.
856
860
 
857
861
  All commands are sent as multi-bulk commands. `args` can either be an Array of
858
862
  arguments, or omitted / set to undefined.
859
863
 
860
- ### `redis.add_command(command_name)`
864
+ ### `redis.addCommand(command_name)`
861
865
 
862
- Calling add_command will add a new command to the prototype. The exact command
866
+ Calling addCommand will add a new command to the prototype. The exact command
863
867
  name will be used when calling using this new command. Using arbitrary arguments
864
868
  is possible as with any other command.
865
869
 
package/index.js CHANGED
@@ -109,6 +109,7 @@ function RedisClient (options, stream) {
109
109
  this.closing = false;
110
110
  this.server_info = {};
111
111
  this.auth_pass = options.auth_pass || options.password;
112
+ this.auth_user = options.auth_user || options.user;
112
113
  this.selected_db = options.db; // Save the selected db here, used when reconnecting
113
114
  this.fire_strings = true; // Determine if strings or buffers should be written to the stream
114
115
  this.pipeline = false;
@@ -240,7 +241,7 @@ RedisClient.prototype.create_stream = function () {
240
241
  if (this.auth_pass !== undefined) {
241
242
  this.ready = true;
242
243
  // Fail silently as we might not be able to connect
243
- this.auth(this.auth_pass, function (err) {
244
+ this.auth(this.auth_pass, this.auth_user, function (err) {
244
245
  if (err && err.code !== 'UNCERTAIN_STATE') {
245
246
  self.emit('error', err);
246
247
  }
@@ -556,12 +557,8 @@ RedisClient.prototype.connection_gone = function (why, error) {
556
557
  if (this.retry_delay instanceof Error) {
557
558
  error = this.retry_delay;
558
559
  }
559
- var errorMessage = 'Redis connection in broken state: ';
560
- if (this.retry_totaltime >= this.connect_timeout) {
561
- errorMessage += 'connection timeout exceeded.';
562
- } else {
563
- errorMessage += 'maximum connection attempts exceeded.';
564
- }
560
+
561
+ var errorMessage = 'Redis connection in broken state: retry aborted.';
565
562
 
566
563
  this.flush_and_error({
567
564
  message: errorMessage,
@@ -581,13 +578,7 @@ RedisClient.prototype.connection_gone = function (why, error) {
581
578
  }
582
579
 
583
580
  if (this.retry_totaltime >= this.connect_timeout) {
584
- var message = 'Redis connection in broken state: ';
585
- if (this.retry_totaltime >= this.connect_timeout) {
586
- message += 'connection timeout exceeded.';
587
- } else {
588
- message += 'maximum connection attempts exceeded.';
589
- }
590
-
581
+ var message = 'Redis connection in broken state: connection timeout exceeded.';
591
582
  this.flush_and_error({
592
583
  message: message,
593
584
  code: 'CONNECTION_BROKEN',
@@ -864,11 +855,9 @@ RedisClient.prototype.internal_send_command = function (command_obj) {
864
855
  if (command_obj.args && command_obj.args.length) {
865
856
  undefinedArgError.args = command_obj.args;
866
857
  }
867
- if (command_obj.callback) {
868
- command_obj.callback(undefinedArgError);
869
- return false;
870
- }
871
- throw undefinedArgError;
858
+ // there is always a callback in this scenario
859
+ command_obj.callback(undefinedArgError);
860
+ return false;
872
861
  } else {
873
862
  // Seems like numbers are converted fast using string concatenation
874
863
  args_copy[i] = '' + args[i];
@@ -29,7 +29,11 @@ module.exports = function createClient (port_arg, host_arg, options) {
29
29
  // [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
30
30
  if (parsed.slashes) { // We require slashes
31
31
  if (parsed.auth) {
32
- options.password = parsed.auth.slice(parsed.auth.indexOf(':') + 1);
32
+ var columnIndex = parsed.auth.indexOf(':');
33
+ options.password = parsed.auth.slice(columnIndex + 1);
34
+ if (columnIndex > 0) {
35
+ options.user = parsed.auth.slice(0, columnIndex);
36
+ }
33
37
  }
34
38
  if (parsed.protocol) {
35
39
  if (parsed.protocol === 'rediss:') {
@@ -4,7 +4,7 @@ var utils = require('./utils');
4
4
  var debug = require('./debug');
5
5
  var Multi = require('./multi');
6
6
  var Command = require('./command');
7
- var no_password_is_set = /no password is set/;
7
+ var no_password_is_set = /no password is set|called without any password configured/;
8
8
  var loading = /LOADING/;
9
9
  var RedisClient = require('../').RedisClient;
10
10
 
@@ -180,7 +180,7 @@ Multi.prototype.info = Multi.prototype.INFO = function info (section, callback)
180
180
  return this;
181
181
  };
182
182
 
183
- function auth_callback (self, pass, callback) {
183
+ function auth_callback (self, pass, user, callback) {
184
184
  return function (err, res) {
185
185
  if (err) {
186
186
  if (no_password_is_set.test(err.message)) {
@@ -191,7 +191,7 @@ function auth_callback (self, pass, callback) {
191
191
  // If redis is still loading the db, it will not authenticate and everything else will fail
192
192
  debug('Redis still loading, trying to authenticate later');
193
193
  setTimeout(function () {
194
- self.auth(pass, callback);
194
+ self.auth(pass, user, callback);
195
195
  }, 100);
196
196
  return;
197
197
  }
@@ -200,25 +200,37 @@ function auth_callback (self, pass, callback) {
200
200
  };
201
201
  }
202
202
 
203
- RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, callback) {
203
+ RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, user, callback) {
204
204
  debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
205
205
 
206
+ // Backward compatibility support for auth with password only
207
+ if (user instanceof Function) {
208
+ callback = user;
209
+ user = null;
210
+ }
206
211
  // Stash auth for connect and reconnect.
207
212
  this.auth_pass = pass;
213
+ this.auth_user = user;
208
214
  var ready = this.ready;
209
215
  this.ready = ready || this.offline_queue.length === 0;
210
- var tmp = this.internal_send_command(new Command('auth', [pass], auth_callback(this, pass, callback)));
216
+ var tmp = this.internal_send_command(new Command('auth', user ? [user, pass] : [pass], auth_callback(this, pass, user, callback)));
211
217
  this.ready = ready;
212
218
  return tmp;
213
219
  };
214
220
 
215
221
  // Only works with batch, not in a transaction
216
- Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, callback) {
222
+ Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, user, callback) {
217
223
  debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
218
224
 
225
+ // Backward compatibility support for auth with password only
226
+ if (user instanceof Function) {
227
+ callback = user;
228
+ user = null;
229
+ }
219
230
  // Stash auth for connect and reconnect.
220
231
  this.auth_pass = pass;
221
- this.queue.push(new Command('auth', [pass], auth_callback(this._client, callback)));
232
+ this.auth_user = user;
233
+ this.queue.push(new Command('auth', user ? [user, pass] : [pass], auth_callback(this._client, pass, user, callback)));
222
234
  return this;
223
235
  };
224
236
 
package/lib/utils.js CHANGED
@@ -127,7 +127,7 @@ module.exports = {
127
127
  reply_to_object: replyToObject,
128
128
  print: print,
129
129
  err_code: /^([A-Z]+)\s+(.+)$/,
130
- monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\]( ".+?")+$/,
130
+ monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\].*"$/,
131
131
  clone: convenienceClone,
132
132
  callback_or_emit: callbackOrEmit,
133
133
  reply_in_order: replyInOrder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redis",
3
- "version": "3.0.1",
3
+ "version": "3.1.2",
4
4
  "description": "A high performance Redis client.",
5
5
  "keywords": [
6
6
  "database",
@@ -30,31 +30,33 @@
30
30
  "coveralls": "nyc report --reporter=text-lcov | coveralls",
31
31
  "coverage": "nyc report --reporter=html",
32
32
  "benchmark": "node benchmarks/multi_bench.js",
33
- "test": "nyc --cache mocha ./test/*.js ./test/commands/*.js --timeout=8000",
34
- "lint": "eslint . --fix && npm run coverage",
33
+ "test": "nyc --cache mocha ./test/*.spec.js ./test/commands/*.spec.js --timeout=8000 && npm run coverage",
34
+ "lint": "eslint .",
35
+ "lint:fix": "eslint . --fix",
36
+ "lint:report": "eslint --output-file=eslint-report.json --format=json .",
35
37
  "compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt"
36
38
  },
37
39
  "dependencies": {
38
- "denque": "^1.4.1",
39
- "redis-commands": "^1.5.0",
40
+ "denque": "^1.5.0",
41
+ "redis-commands": "^1.7.0",
40
42
  "redis-errors": "^1.2.0",
41
43
  "redis-parser": "^3.0.0"
42
44
  },
43
45
  "engines": {
44
- "node": ">=6"
46
+ "node": ">=10"
45
47
  },
46
48
  "devDependencies": {
47
- "prettier": "^1.19.1",
48
49
  "bluebird": "^3.7.2",
49
- "coveralls": "^2.11.2",
50
- "eslint": "^6.8.0",
50
+ "coveralls": "^3.1.0",
51
+ "cross-spawn": "^7.0.3",
52
+ "eslint": "^7.21.0",
51
53
  "intercept-stdout": "~0.1.2",
52
54
  "metrics": "^0.1.21",
53
- "mocha": "^4.1.0",
54
- "nyc": "^14.1.1",
55
+ "mocha": "^8.3.0",
56
+ "nyc": "^15.1.0",
57
+ "prettier": "^2.2.1",
55
58
  "tcp-port-used": "^1.0.1",
56
- "uuid": "^3.4.0",
57
- "cross-spawn": "^6.0.5"
59
+ "uuid": "^8.3.2"
58
60
  },
59
61
  "repository": {
60
62
  "type": "git",