123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- 'use strict';
- // hgetall converts its replies to an Object. If the reply is empty, null is returned.
- // These function are only called with internal data and have therefore always the same instanceof X
- function replyToObject (reply) {
- // The reply might be a string or a buffer if this is called in a transaction (multi)
- if (reply.length === 0 || !(reply instanceof Array)) {
- return null;
- }
- var obj = {};
- for (var i = 0; i < reply.length; i += 2) {
- obj[reply[i].toString('binary')] = reply[i + 1];
- }
- return obj;
- }
- function replyToStrings (reply) {
- if (reply instanceof Buffer) {
- return reply.toString();
- }
- if (reply instanceof Array) {
- var res = new Array(reply.length);
- for (var i = 0; i < reply.length; i++) {
- // Recusivly call the function as slowlog returns deep nested replies
- res[i] = replyToStrings(reply[i]);
- }
- return res;
- }
- return reply;
- }
- function print (err, reply) {
- if (err) {
- // A error always begins with Error:
- console.log(err.toString());
- } else {
- console.log('Reply: ' + reply);
- }
- }
- var camelCase;
- // Deep clone arbitrary objects with arrays. Can't handle cyclic structures (results in a range error)
- // Any attribute with a non primitive value besides object and array will be passed by reference (e.g. Buffers, Maps, Functions)
- // All capital letters are going to be replaced with a lower case letter and a underscore infront of it
- function clone (obj) {
- var copy;
- if (Array.isArray(obj)) {
- copy = new Array(obj.length);
- for (var i = 0; i < obj.length; i++) {
- copy[i] = clone(obj[i]);
- }
- return copy;
- }
- if (Object.prototype.toString.call(obj) === '[object Object]') {
- copy = {};
- var elems = Object.keys(obj);
- var elem;
- while (elem = elems.pop()) {
- if (elem === 'tls') { // special handle tls
- copy[elem] = obj[elem];
- continue;
- }
- // Accept camelCase options and convert them to snake_case
- var snake_case = elem.replace(/[A-Z][^A-Z]/g, '_$&').toLowerCase();
- // If camelCase is detected, pass it to the client, so all variables are going to be camelCased
- // There are no deep nested options objects yet, but let's handle this future proof
- if (snake_case !== elem.toLowerCase()) {
- camelCase = true;
- }
- copy[snake_case] = clone(obj[elem]);
- }
- return copy;
- }
- return obj;
- }
- function convenienceClone (obj) {
- camelCase = false;
- obj = clone(obj) || {};
- if (camelCase) {
- obj.camel_case = true;
- }
- return obj;
- }
- function callbackOrEmit (self, callback, err, res) {
- if (callback) {
- callback(err, res);
- } else if (err) {
- self.emit('error', err);
- }
- }
- function replyInOrder (self, callback, err, res, queue) {
- // If the queue is explicitly passed, use that, otherwise fall back to the offline queue first,
- // as there might be commands in both queues at the same time
- var command_obj;
- /* istanbul ignore if: TODO: Remove this as soon as we test Redis 3.2 on travis */
- if (queue) {
- command_obj = queue.peekBack();
- } else {
- command_obj = self.offline_queue.peekBack() || self.command_queue.peekBack();
- }
- if (!command_obj) {
- process.nextTick(function () {
- callbackOrEmit(self, callback, err, res);
- });
- } else {
- var tmp = command_obj.callback;
- command_obj.callback = tmp ?
- function (e, r) {
- tmp(e, r);
- callbackOrEmit(self, callback, err, res);
- } :
- function (e, r) {
- if (e) {
- self.emit('error', e);
- }
- callbackOrEmit(self, callback, err, res);
- };
- }
- }
- module.exports = {
- reply_to_strings: replyToStrings,
- reply_to_object: replyToObject,
- print: print,
- err_code: /^([A-Z]+)\s+(.+)$/,
- monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\]( ".+?")+$/,
- clone: convenienceClone,
- callback_or_emit: callbackOrEmit,
- reply_in_order: replyInOrder
- };
|