|
|
'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 };
|