diff --git a/API.md b/API.md index 23066791..ab0898e2 100644 --- a/API.md +++ b/API.md @@ -1,4 +1,5 @@ ## Classes +
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
Default options
@@ -16,26 +19,29 @@Default options
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
**Kind**: global class
**Extends:** [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
, [Commander](#Commander)
* [Redis](#Redis) ⇐ [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
- * [new Redis([port], [host], [options])](#new_Redis_new)
- * _instance_
- * [.connect(callback)](#Redis+connect) ⇒ Promise
- * [.disconnect()](#Redis+disconnect)
- * ~~[.end()](#Redis+end)~~
- * [.duplicate()](#Redis+duplicate)
- * [.monitor([callback])](#Redis+monitor)
- * [.getBuiltinCommands()](#Commander+getBuiltinCommands) ⇒ Array.<string>
- * [.createBuiltinCommand(commandName)](#Commander+createBuiltinCommand) ⇒ object
- * [.defineCommand(name, definition)](#Commander+defineCommand)
- * _static_
- * ~~[.createClient()](#Redis.createClient)~~
+ * [new Redis([port], [host], [options])](#new_Redis_new)
+ * _instance_
+ * [.connect(callback)](#Redis+connect) ⇒ Promise
+ * [.disconnect()](#Redis+disconnect)
+ * ~~[.end()](#Redis+end)~~
+ * [.duplicate()](#Redis+duplicate)
+ * [.monitor([callback])](#Redis+monitor)
+ * [.getBuiltinCommands()](#Commander+getBuiltinCommands) ⇒ Array.<string>
+ * [.createBuiltinCommand(commandName)](#Commander+createBuiltinCommand) ⇒ object
+ * [.defineCommand(name, definition)](#Commander+defineCommand)
+ * _static_
+ * ~~[.createClient()](#Redis.createClient)~~
+
### new Redis([port], [host], [options])
Creates a Redis instance
@@ -63,6 +69,7 @@ Creates a Redis instance
| [options.retryStrategy] | function
| | See "Quick Start" section |
| [options.reconnectOnError] | function
| | See "Quick Start" section |
| [options.readOnly] | boolean
| false
| Enable READONLY mode for the connection. Only available for cluster mode. |
+| [options.stringNumbers] | boolean
| false
| Force numbers to be always returned as JavaScript strings. This option is necessary when dealing with big numbers (exceed the [-2^53, +2^53] range). Notice that when this option is enabled, the JavaScript parser will be used even "hiredis" is specified because only JavaScript parser supports this feature for the time being. |
**Example**
```js
@@ -80,6 +87,7 @@ var urlRedis2 = new Redis('//localhost:6379');
var authedRedis = new Redis(6380, '192.168.100.1', { password: 'password' });
```
+
### redis.connect(callback) ⇒ Promise
Create a connection to Redis.
This method will be invoked automatically when creating a new Redis instance.
@@ -92,6 +100,7 @@ This method will be invoked automatically when creating a new Redis instance.
| callback | function
|
+
### redis.disconnect()
Disconnect from Redis.
@@ -102,6 +111,7 @@ If you want to wait for the pending replies, use Redis#quit instead.
**Kind**: instance method of [Redis](#Redis)
**Access:** public
+
### ~~redis.end()~~
***Deprecated***
@@ -109,6 +119,7 @@ Disconnect from Redis.
**Kind**: instance method of [Redis](#Redis)
+
### redis.duplicate()
Create a new instance with the same options as the current one.
@@ -120,6 +131,7 @@ var redis = new Redis(6380);
var anotherRedis = redis.duplicate();
```
+
### redis.monitor([callback])
Listen for all requests received by the server in real time.
@@ -152,6 +164,7 @@ redis.monitor().then(function (monitor) {
});
```
+
### redis.getBuiltinCommands() ⇒ Array.<string>
Return supported builtin commands
@@ -159,6 +172,7 @@ Return supported builtin commands
**Returns**: Array.<string>
- command list
**Access:** public
+
### redis.createBuiltinCommand(commandName) ⇒ object
Create a builtin command
@@ -171,6 +185,7 @@ Create a builtin command
| commandName | string
| command name |
+
### redis.defineCommand(name, definition)
Define a custom command using lua script
@@ -184,6 +199,7 @@ Define a custom command using lua script
| [definition.numberOfKeys] | number
|
| the number of keys. If omit, you have to pass the number of keys as the first argument every time you invoke the command |
+
### ~~Redis.createClient()~~
***Deprecated***
@@ -191,21 +207,23 @@ Create a Redis instance
**Kind**: static method of [Redis](#Redis)
+
## Cluster ⇐ [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
**Kind**: global class
**Extends:** [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
, [Commander](#Commander)
* [Cluster](#Cluster) ⇐ [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
- * [new Cluster(startupNodes, options)](#new_Cluster_new)
- * [.connect()](#Cluster+connect) ⇒ Promise
- * [.disconnect()](#Cluster+disconnect)
- * [.nodes([role])](#Cluster+nodes) ⇒ [Array.<Redis>](#Redis)
- * [.getBuiltinCommands()](#Commander+getBuiltinCommands) ⇒ Array.<string>
- * [.createBuiltinCommand(commandName)](#Commander+createBuiltinCommand) ⇒ object
- * [.defineCommand(name, definition)](#Commander+defineCommand)
- * *[.sendCommand()](#Commander+sendCommand)*
+ * [new Cluster(startupNodes, options)](#new_Cluster_new)
+ * [.connect()](#Cluster+connect) ⇒ Promise
+ * [.disconnect()](#Cluster+disconnect)
+ * [.nodes([role])](#Cluster+nodes) ⇒ [Array.<Redis>](#Redis)
+ * [.getBuiltinCommands()](#Commander+getBuiltinCommands) ⇒ Array.<string>
+ * [.createBuiltinCommand(commandName)](#Commander+createBuiltinCommand) ⇒ object
+ * [.defineCommand(name, definition)](#Commander+defineCommand)
+ * *[.sendCommand()](#Commander+sendCommand)*
+
### new Cluster(startupNodes, options)
Creates a Redis Cluster instance
@@ -225,18 +243,21 @@ Creates a Redis Cluster instance
| [options.redisOptions] | Object
| | Passed to the constructor of `Redis`. |
+
### cluster.connect() ⇒ Promise
Connect to a cluster
**Kind**: instance method of [Cluster](#Cluster)
**Access:** public
+
### cluster.disconnect()
Disconnect from every node in the cluster.
**Kind**: instance method of [Cluster](#Cluster)
**Access:** public
+
### cluster.nodes([role]) ⇒ [Array.<Redis>](#Redis)
Get nodes with the specified role
@@ -249,6 +270,7 @@ Get nodes with the specified role
| [role] | string
| "all"
| role, "master", "slave" or "all" |
+
### cluster.getBuiltinCommands() ⇒ Array.<string>
Return supported builtin commands
@@ -256,6 +278,7 @@ Return supported builtin commands
**Returns**: Array.<string>
- command list
**Access:** public
+
### cluster.createBuiltinCommand(commandName) ⇒ object
Create a builtin command
@@ -268,6 +291,7 @@ Create a builtin command
| commandName | string
| command name |
+
### cluster.defineCommand(name, definition)
Define a custom command using lua script
@@ -281,6 +305,7 @@ Define a custom command using lua script
| [definition.numberOfKeys] | number
|
| the number of keys. If omit, you have to pass the number of keys as the first argument every time you invoke the command |
+
### *cluster.sendCommand()*
Send a command
@@ -288,17 +313,19 @@ Send a command
**Overrides:** [sendCommand](#Commander+sendCommand)
**Access:** public
+
## Commander
**Kind**: global class
* [Commander](#Commander)
- * [new Commander()](#new_Commander_new)
- * [.getBuiltinCommands()](#Commander+getBuiltinCommands) ⇒ Array.<string>
- * [.createBuiltinCommand(commandName)](#Commander+createBuiltinCommand) ⇒ object
- * [.defineCommand(name, definition)](#Commander+defineCommand)
- * *[.sendCommand()](#Commander+sendCommand)*
+ * [new Commander()](#new_Commander_new)
+ * [.getBuiltinCommands()](#Commander+getBuiltinCommands) ⇒ Array.<string>
+ * [.createBuiltinCommand(commandName)](#Commander+createBuiltinCommand) ⇒ object
+ * [.defineCommand(name, definition)](#Commander+defineCommand)
+ * *[.sendCommand()](#Commander+sendCommand)*
+
### new Commander()
Commander
@@ -310,6 +337,7 @@ This is the base class of Redis, Redis.Cluster and Pipeline
| [options.showFriendlyErrorStack] | boolean
| false
| Whether to show a friendly error stack. Will decrease the performance significantly. |
+
### commander.getBuiltinCommands() ⇒ Array.<string>
Return supported builtin commands
@@ -317,6 +345,7 @@ Return supported builtin commands
**Returns**: Array.<string>
- command list
**Access:** public
+
### commander.createBuiltinCommand(commandName) ⇒ object
Create a builtin command
@@ -329,6 +358,7 @@ Create a builtin command
| commandName | string
| command name |
+
### commander.defineCommand(name, definition)
Define a custom command using lua script
@@ -342,18 +372,21 @@ Define a custom command using lua script
| [definition.numberOfKeys] | number
|
| the number of keys. If omit, you have to pass the number of keys as the first argument every time you invoke the command |
+
### *commander.sendCommand()*
Send a command
**Kind**: instance abstract method of [Commander](#Commander)
**Access:** public
+
## defaultOptions
Default options
**Kind**: global variable
**Access:** protected
+
## defaultOptions
Default options
diff --git a/lib/redis.js b/lib/redis.js
index d21ef97f..99bfd1fa 100644
--- a/lib/redis.js
+++ b/lib/redis.js
@@ -74,6 +74,10 @@ var ScanStream = require('./scan_stream');
* @param {function} [options.reconnectOnError] - See "Quick Start" section
* @param {boolean} [options.readOnly=false] - Enable READONLY mode for the connection.
* Only available for cluster mode.
+ * @param {boolean} [options.stringNumbers=false] - Force numbers to be always returned as JavaScript
+ * strings. This option is necessary when dealing with big numbers (exceed the [-2^53, +2^53] range).
+ * Notice that when this option is enabled, the JavaScript parser will be used even "hiredis" is specified
+ * because only JavaScript parser supports this feature for the time being.
* @extends [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
* @extends Commander
* @example
@@ -169,7 +173,8 @@ Redis.defaultOptions = {
lazyConnect: false,
keyPrefix: '',
reconnectOnError: null,
- readOnly: false
+ readOnly: false,
+ stringNumbers: false
};
Redis.prototype.resetCommandQueue = function () {
diff --git a/lib/redis/parser.js b/lib/redis/parser.js
index 433ebbd8..39c3ec66 100644
--- a/lib/redis/parser.js
+++ b/lib/redis/parser.js
@@ -19,6 +19,7 @@ exports.initParser = function () {
this.replyParser = new Parser({
name: this.options.parser,
+ stringNumbers: this.options.stringNumbers,
returnBuffers: true,
returnError: function (err) {
_this.returnError(new ReplyError(err.message));
diff --git a/test/functional/string_numbers.js b/test/functional/string_numbers.js
new file mode 100644
index 00000000..63fbe38c
--- /dev/null
+++ b/test/functional/string_numbers.js
@@ -0,0 +1,52 @@
+'use strict';
+
+var MAX_NUMBER = 9007199254740991; // Number.MAX_SAFE_INTEGER
+
+describe('stringNumbers', function () {
+ context('enabled', function () {
+ it('returns numbers as strings', function (done) {
+ var redis = new Redis({
+ stringNumbers: true
+ });
+
+ var pending = 0;
+
+ redis.set('foo', MAX_NUMBER);
+ redis.incr('foo', check('9007199254740992'));
+ redis.incr('foo', check('9007199254740993'));
+ redis.incr('foo', check('9007199254740994'));
+
+ // also works for small interger
+ redis.set('foo', 123);
+ redis.incr('foo', check('124'));
+
+ // and floats
+ redis.set('foo', 123.23);
+ redis.incrbyfloat('foo', 1.2, check('124.43'));
+
+ function check(expected) {
+ pending += 1;
+ return function (err, res) {
+ expect(res).to.eql(expected);
+ if (!--pending) {
+ redis.disconnect();
+ done();
+ }
+ };
+ }
+ });
+ });
+
+ context('disabled', function () {
+ it('returns numbers', function (done) {
+ var redis = new Redis();
+
+ redis.set('foo', '123');
+ redis.incr('foo', function (err, res) {
+ expect(res).to.eql(124);
+ redis.disconnect();
+ done();
+ });
+ });
+ });
+});