mirror of
https://github.com/amark/gun.git
synced 2025-06-09 15:46:44 +00:00
156 lines
5.0 KiB
JavaScript
156 lines
5.0 KiB
JavaScript
"use strict";
|
|
|
|
|
|
// By default fakeredis simulates a ridiculous amount of network latency
|
|
// to help you discover race-conditions when testing multi-client setups.
|
|
// Instantiate your 'clients' with a truthy .fast option,
|
|
// or set it here globally to make things go a bit faster.
|
|
exports.fast = false;
|
|
|
|
|
|
/**
|
|
|
|
TODO:
|
|
- lint negative count and offset LIMITs away,
|
|
SORT and ZRANGEBYSCORE treat them differently, so it's just confusing and a bad practice.
|
|
|
|
**/
|
|
|
|
var index = require ( "redis" ),
|
|
Backend = require ( "./lib/backend" ).Backend,
|
|
Connection = require ( "./lib/connection" ).Connection,
|
|
helpers = require ( "./lib/helpers" ),
|
|
|
|
backends = {},
|
|
RedisClient = index.RedisClient,
|
|
|
|
anon = 0;
|
|
|
|
|
|
//// Re-export redis exports.
|
|
|
|
exports.RedisClient = index.RedisClient;
|
|
exports.Multi = index.Multi;
|
|
exports.print = index.print;
|
|
|
|
|
|
//// Overriden client factory.
|
|
|
|
exports.createClient = function ( port, host, options )
|
|
{
|
|
var id = !port && !host ? 'fake_' + ( ++ anon ) : ( host || "" ) + ( port || "" ),
|
|
lat = options && options.fast || exports.fast ? 1 : null,
|
|
c = new Connection ( backends [ id ] || ( backends [ id ] = new Backend ), lat, lat ),
|
|
cl = new RedisClient ( { on : function () {} } /* , options */ ),
|
|
ns = options && options.no_sugar;
|
|
|
|
if ( options && options.verbose )
|
|
c.verbose = true;
|
|
|
|
cl.connected = true;
|
|
cl.ready = true;
|
|
|
|
cl.send_command = function ( command, args, callback )
|
|
{
|
|
//// Interpret arguments, copy-paste from mranney/redis/index.js for best compat.
|
|
|
|
if (typeof command !== "string") {
|
|
throw new Error("First argument to send_command must be the command name string, not " + typeof command);
|
|
}
|
|
|
|
if (Array.isArray(args)) {
|
|
if (typeof callback === "function") {
|
|
// probably the fastest way:
|
|
// client.command([arg1, arg2], cb); (straight passthrough)
|
|
// send_command(command, [arg1, arg2], cb);
|
|
} else if (! callback) {
|
|
// most people find this variable argument length form more convenient, but it uses arguments, which is slower
|
|
// client.command(arg1, arg2, cb); (wraps up arguments into an array)
|
|
// send_command(command, [arg1, arg2, cb]);
|
|
// client.command(arg1, arg2); (callback is optional)
|
|
// send_command(command, [arg1, arg2]);
|
|
// client.command(arg1, arg2, undefined); (callback is undefined)
|
|
// send_command(command, [arg1, arg2, undefined]);
|
|
var last_arg_type = typeof args[args.length - 1];
|
|
if (last_arg_type === "function" || last_arg_type === "undefined") {
|
|
callback = args.pop();
|
|
}
|
|
} else {
|
|
throw new Error("send_command: last argument must be a callback or undefined");
|
|
}
|
|
} else {
|
|
throw new Error("send_command: second argument must be an array");
|
|
}
|
|
|
|
// if the last argument is an array, expand it out. This allows commands like this:
|
|
// client.command(arg1, [arg2, arg3, arg4], cb);
|
|
// and converts to:
|
|
// client.command(arg1, arg2, arg3, arg4, cb);
|
|
// which is convenient for some things like sadd
|
|
if (Array.isArray(args[args.length - 1])) {
|
|
args = args.slice(0, -1).concat(args[args.length - 1]);
|
|
}
|
|
|
|
//// Lint args.
|
|
|
|
if ( !options || !options.no_lint )
|
|
{
|
|
var i, n;
|
|
n = args.length;
|
|
for ( i = 0; i < n; i ++ )
|
|
if ( typeof args [ i ] !== 'string' && typeof args [ i ] !== 'number' )
|
|
throw new Error ( "fakeredis/lint: Argument #" + i + " for " + command + " is not a String or Number: " + args [ i ] );
|
|
}
|
|
|
|
//// You can disable hash sugar with the no_sugar option.
|
|
|
|
var cb;
|
|
if ( callback && !ns && /^hgetall/i.test ( command ) )
|
|
cb = function ( err, data )
|
|
{
|
|
if ( !err && data )
|
|
data = reply_to_object ( data );
|
|
|
|
callback ( err, data );
|
|
};
|
|
|
|
else
|
|
cb = callback;
|
|
|
|
c.push ( this, command, args, cb );
|
|
};
|
|
|
|
cl.pushMessage = cl.emit.bind ( cl );
|
|
|
|
( function ()
|
|
{
|
|
var prop;
|
|
for ( prop in helpers )
|
|
cl [ prop ] = helpers [ prop ];
|
|
}
|
|
() );
|
|
|
|
return cl;
|
|
};
|
|
|
|
|
|
//// Helpers for node_redis compat.
|
|
|
|
// hgetall converts its replies to an Object. If the reply is empty, null is returned.
|
|
function reply_to_object(reply) {
|
|
var obj = {}, j, jl, key, val;
|
|
|
|
if (reply.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
for (j = 0, jl = reply.length; j < jl; j += 2) {
|
|
key = reply[j].toString();
|
|
val = reply[j + 1];
|
|
obj[key] = val;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|