query-engine
Version:
Query-Engine is a NoSQL and MongoDb compliant query engine. It can run on the server-side with Node.js, or on the client-side within web browsers
780 lines (682 loc) • 21.5 kB
JavaScript
// Generated by CoffeeScript 1.6.2
(function() {
var balUtilFlow, balUtilTypes,
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
balUtilTypes = (typeof require === "function" ? require('./types') : void 0) || this.balUtilTypes;
balUtilFlow = {
wait: function(delay, fn) {
return setTimeout(fn, delay);
},
extractOptsAndCallback: function(opts, next) {
if (balUtilTypes.isFunction(opts) && (next != null) === false) {
next = opts;
opts = {};
} else {
opts || (opts = {});
}
next || (next = opts.next || null);
return [opts, next];
},
fireWithOptionalCallback: function(method, args, context) {
var callback, caughtError, err, result;
args || (args = []);
callback = args[args.length - 1];
context || (context = null);
result = null;
if (method.length === args.length) {
try {
result = method.apply(context, args);
} catch (_error) {
caughtError = _error;
callback(caughtError);
}
} else {
err = null;
try {
result = method.apply(context, args);
if (balUtilTypes.isError(result)) {
err = result;
}
} catch (_error) {
caughtError = _error;
err = caughtError;
}
callback(err, result);
}
return result;
},
clone: function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
args.unshift({});
return this.shallowExtendPlainObjects.apply(this, args);
},
deepClone: function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
args.unshift({});
return this.deepExtendPlainObjects.apply(this, args);
},
extend: function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return this.shallowExtendPlainObjects.apply(this, args);
},
shallowExtendPlainObjects: function() {
var key, obj, objs, target, value, _i, _len;
target = arguments[0], objs = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = objs.length; _i < _len; _i++) {
obj = objs[_i];
obj || (obj = {});
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
value = obj[key];
target[key] = value;
}
}
return target;
},
safeShallowExtendPlainObjects: function() {
var key, obj, objs, target, value, _i, _len;
target = arguments[0], objs = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = objs.length; _i < _len; _i++) {
obj = objs[_i];
obj || (obj = {});
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
value = obj[key];
if (value == null) {
continue;
}
target[key] = value;
}
}
return target;
},
deepExtendPlainObjects: function() {
var key, obj, objs, target, value, _i, _len;
target = arguments[0], objs = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = objs.length; _i < _len; _i++) {
obj = objs[_i];
obj || (obj = {});
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
value = obj[key];
if (balUtilTypes.isPlainObject(value)) {
if (!balUtilTypes.isPlainObject(target[key])) {
target[key] = {};
}
balUtilFlow.deepExtendPlainObjects(target[key], value);
} else {
target[key] = value;
}
}
}
return target;
},
safeDeepExtendPlainObjects: function() {
var key, obj, objs, target, value, _i, _len;
target = arguments[0], objs = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = objs.length; _i < _len; _i++) {
obj = objs[_i];
obj || (obj = {});
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
value = obj[key];
if (value == null) {
continue;
}
if (balUtilTypes.isPlainObject(value)) {
if (!balUtilTypes.isPlainObject(target[key])) {
target[key] = {};
}
balUtilFlow.safeDeepExtendPlainObjects(target[key], value);
} else {
target[key] = value;
}
}
}
return target;
},
dereference: function(source) {
var target;
target = JSON.parse(JSON.stringify(source));
return target;
},
each: function(obj, callback, context) {
var item, key, _i, _len;
context || (context = obj);
if (balUtilTypes.isArray(obj)) {
for (key = _i = 0, _len = obj.length; _i < _len; key = ++_i) {
item = obj[key];
if (callback.call(context, item, key, obj) === false) {
break;
}
}
} else {
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
item = obj[key];
if (callback.call(context, item, key, obj) === false) {
break;
}
}
}
return this;
},
flow: function() {
var action, actions, args, next, object, tasks, _ref, _ref1, _ref2;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (args.length === 1) {
_ref = args[0], object = _ref.object, actions = _ref.actions, action = _ref.action, args = _ref.args, tasks = _ref.tasks, next = _ref.next;
} else if (args.length === 4) {
_ref1 = args, object = _ref1[0], action = _ref1[1], args = _ref1[2], next = _ref1[3];
} else if (args.length === 3) {
_ref2 = args, actions = _ref2[0], args = _ref2[1], next = _ref2[2];
}
if ((action != null) === false && (actions != null) === false) {
throw new Error('balUtilFlow.flow called without any action');
}
if (actions == null) {
actions = action.split(/[,\s]+/g);
}
if (object == null) {
object = global;
}
tasks || (tasks = new balUtilFlow.Group(next));
balUtilFlow.each(actions, function(action) {
return tasks.push(function(complete) {
var argsClone, fn;
argsClone = (args || []).slice();
argsClone.push(complete);
fn = balUtilTypes.isFunction(action) ? action : object[action];
return fn.apply(object, argsClone);
});
});
tasks.sync();
return this;
},
createSnore: function(message, opts) {
var snore, _ref;
opts || (opts = {});
if ((_ref = opts.delay) == null) {
opts.delay = 5000;
}
snore = {
snoring: false,
timer: setTimeout(function() {
snore.clear();
snore.snoring = true;
return typeof message === "function" ? message() : void 0;
}, opts.delay),
clear: function() {
if (snore.timer) {
clearTimeout(snore.timer);
return snore.timer = false;
}
}
};
return snore;
},
suffixArray: function() {
var arg, args, item, result, suffix, _i, _j, _len, _len1;
suffix = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
result = [];
for (_i = 0, _len = args.length; _i < _len; _i++) {
arg = args[_i];
if (!balUtilTypes.isArray(arg)) {
arg = [arg];
}
for (_j = 0, _len1 = arg.length; _j < _len1; _j++) {
item = arg[_j];
result.push(item + suffix);
}
}
return result;
},
setDeep: function(location, keys, value, safe) {
var key, result, _ref, _ref1, _ref2;
if (safe == null) {
safe = false;
}
if (!balUtilTypes.isArray(keys)) {
keys = keys.split('.');
}
if (keys.length === 0) {
return void 0;
}
if (keys.length === 0 || typeof location === 'undefined') {
result = void 0;
} else if (location === null) {
result = null;
} else {
key = keys[0];
location = (_ref = location.attributes) != null ? _ref : location;
if (keys.length === 1) {
if (safe) {
if ((_ref1 = location[key]) == null) {
location[key] = value;
}
} else {
if (typeof value === 'undefined') {
if (typeof location[key] !== 'undefined') {
delete location[key];
}
} else {
location[key] = value;
}
}
result = location[key];
} else {
location = (_ref2 = location[key]) != null ? _ref2 : location[key] = {};
result = balUtilFlow.setDeep(location, keys.slice(1), value, safe);
}
}
return result;
},
getDeep: function(location, keys) {
var key, result, _ref;
if (!balUtilTypes.isArray(keys)) {
keys = keys.split('.');
}
if (keys.length === 0 || typeof location === 'undefined') {
result = void 0;
} else if (location === null) {
result = null;
} else {
key = keys[0];
location = (_ref = location.attributes) != null ? _ref : location;
location = typeof location[key] === 'undefined' ? void 0 : location[key];
if (keys.length === 1) {
result = location;
} else {
result = balUtilFlow.getDeep(location, keys.slice(1));
}
}
return result;
}
};
/*
Usage:
# Add tasks to a queue then fire them in parallel (asynchronously)
tasks = new Group (err) -> next err
tasks.push (complete) -> someAsyncFunction(arg1, arg2, complete)
tasks.push (complete) -> anotherAsyncFunction(arg1, arg2, complete)
tasks.run()
# Add tasks to a queue then fire them in serial (synchronously)
tasks = new Group (err) -> next err
tasks.push (complete) -> someAsyncFunction(arg1, arg2, complete)
tasks.push (complete) -> anotherAsyncFunction(arg1, arg2, complete)
tasks.run('serial')
*/
balUtilFlow.Group = (function() {
_Class.prototype.total = 0;
_Class.prototype.completed = 0;
_Class.prototype.running = 0;
_Class.prototype.exited = false;
_Class.prototype.breakOnError = true;
_Class.prototype.autoClear = false;
_Class.prototype.queue = [];
_Class.prototype.mode = 'parallel';
_Class.prototype.lastResult = null;
_Class.prototype.results = [];
_Class.prototype.errors = [];
_Class.prototype.next = function() {
throw new Error('Groups require a completion callback');
};
function _Class() {
var arg, args, autoClear, breakOnError, mode, next, _i, _len;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
this.clear();
for (_i = 0, _len = args.length; _i < _len; _i++) {
arg = args[_i];
if (balUtilTypes.isString(arg)) {
if (arg === 'serial' || arg === 'sync') {
this.mode = 'serial';
}
} else if (balUtilTypes.isFunction(arg)) {
this.next = arg;
} else if (balUtilTypes.isObject(arg)) {
next = arg.next, mode = arg.mode, breakOnError = arg.breakOnError, autoClear = arg.autoClear;
if (next) {
this.next = next;
}
if (mode) {
this.mode = mode;
}
if (breakOnError) {
this.breakOnError = breakOnError;
}
if (autoClear) {
this.autoClear = autoClear;
}
} else {
throw new Error('Unknown argument sent to Groups constructor');
}
}
}
_Class.prototype.clear = function() {
this.total = 0;
this.completed = 0;
this.running = 0;
this.exited = false;
this.queue = [];
this.results = [];
this.errors = [];
this.lastResult = null;
return this;
};
_Class.prototype.hasTasks = function() {
return this.queue.length !== 0;
};
_Class.prototype.hasCompleted = function() {
return this.total !== 0 && this.total === this.completed;
};
_Class.prototype.isRunning = function() {
return this.running !== 0;
};
_Class.prototype.hasExited = function(value) {
if (value != null) {
this.exited = value;
}
return this.exited === true;
};
_Class.prototype.logError = function(err) {
if (this.errors[this.errors.length - 1] !== err) {
this.errors.push(err);
}
return this;
};
_Class.prototype.complete = function() {
var args, err;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
err = args[0] || void 0;
this.lastResult = args;
if (err) {
this.logError(err);
}
this.results.push(args);
if (this.running !== 0) {
--this.running;
}
if (this.hasExited()) {
} else {
if (err && this.breakOnError) {
this.exit();
} else {
++this.completed;
if (this.hasTasks()) {
this.nextTask();
} else if (this.isRunning() === false && this.hasCompleted()) {
this.exit();
}
}
}
return this;
};
_Class.prototype.completer = function() {
var _this = this;
return function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return _this.complete.apply(_this, args);
};
};
_Class.prototype.exit = function(err) {
var errors, lastResult, results;
if (err == null) {
err = null;
}
if (err) {
this.logError(err);
}
if (this.hasExited()) {
} else {
lastResult = this.lastResult;
results = this.results;
if (this.errors.length === 0) {
errors = null;
} else if (this.errors.length === 1) {
errors = this.errors[0];
} else {
errors = this.errors;
}
if (this.autoClear) {
this.clear();
} else {
this.hasExited(true);
}
this.next(errors, lastResult, results);
}
return this;
};
_Class.prototype.tasks = function(tasks) {
var task, _i, _len;
for (_i = 0, _len = tasks.length; _i < _len; _i++) {
task = tasks[_i];
this.push(task);
}
return this;
};
_Class.prototype.push = function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
++this.total;
this.queue.push(args);
return this;
};
_Class.prototype.pushAndRun = function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (this.mode === 'serial' && this.isRunning()) {
this.push.apply(this, args);
} else {
++this.total;
this.runTask(args);
}
return this;
};
_Class.prototype.nextTask = function() {
var task;
if (this.hasTasks()) {
task = this.queue.shift();
this.runTask(task);
}
return this;
};
_Class.prototype.runTask = function(task) {
var err, me, run;
me = this;
try {
run = function() {
var complete, _context, _task;
++me.running;
complete = me.completer();
if (balUtilTypes.isArray(task)) {
if (task.length === 2) {
_context = task[0];
_task = task[1];
} else if (task.length === 1) {
_task = task[0];
_context = null;
} else {
throw new Error('balUtilFlow.Group an invalid task was pushed');
}
} else {
_task = task;
}
return balUtilFlow.fireWithOptionalCallback(_task, [complete], _context);
};
if (this.completed !== 0 && (this.mode === 'parallel' || (this.completed % 100) === 0)) {
setTimeout(run, 0);
} else {
run();
}
} catch (_error) {
err = _error;
this.complete(err);
}
return this;
};
_Class.prototype.run = function(mode) {
var task, _i, _len, _ref, _ref1;
if (this.isRunning() === false) {
if (mode) {
this.mode = mode;
}
this.hasExited(false);
if (this.hasTasks()) {
if ((_ref = this.mode) === 'serial' || _ref === 'sync') {
this.nextTask();
} else {
_ref1 = this.queue;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
task = _ref1[_i];
this.nextTask();
}
}
} else {
this.exit();
}
}
return this;
};
_Class.prototype.async = function() {
return this.parallel();
};
_Class.prototype.parallel = function() {
this.run('parallel');
return this;
};
_Class.prototype.sync = function() {
return this.serial();
};
_Class.prototype.serial = function() {
this.run('serial');
return this;
};
return _Class;
})();
balUtilFlow.Block = (function(_super) {
__extends(_Class, _super);
_Class.prototype.blockBefore = function(block) {};
_Class.prototype.blockAfter = function(block, err) {};
_Class.prototype.blockTaskBefore = function(block, task, err) {};
_Class.prototype.blockTaskAfter = function(block, task, err) {};
function _Class(opts) {
var block, complete, err, fn, name, parentBlock;
block = this;
name = opts.name, fn = opts.fn, parentBlock = opts.parentBlock, complete = opts.complete;
block.blockName = name;
if (parentBlock != null) {
block.parentBlock = parentBlock;
}
block.mode = 'sync';
block.fn = fn;
_Class.__super__.constructor.call(this, function(err) {
block.blockAfter(block, err);
return typeof complete === "function" ? complete(err) : void 0;
});
block.blockBefore(block);
if (block.fn != null) {
if (block.fn.length === 3) {
block.total = Infinity;
}
try {
block.fn(function(name, fn) {
return block.block(name, fn);
}, function(name, fn) {
return block.task(name, fn);
}, function(err) {
return block.exit(err);
});
if (block.fn.length !== 3) {
block.run();
}
} catch (_error) {
err = _error;
block.exit(err);
}
} else {
block.total = Infinity;
}
this;
}
_Class.prototype.block = function(name, fn) {
var block, pushBlock;
block = this;
pushBlock = function(fn) {
if (block.total === Infinity) {
return block.pushAndRun(fn);
} else {
return block.push(fn);
}
};
pushBlock(function(complete) {
var subBlock;
return subBlock = block.createSubBlock({
name: name,
fn: fn,
complete: complete
});
});
return this;
};
_Class.prototype.createSubBlock = function(opts) {
opts.parentBlock = this;
return new balUtilFlow.Block(opts);
};
_Class.prototype.task = function(name, fn) {
var block, pushTask;
block = this;
pushTask = function(fn) {
if (block.total === Infinity) {
return block.pushAndRun(fn);
} else {
return block.push(fn);
}
};
pushTask(function(complete) {
var preComplete;
preComplete = function(err) {
block.blockTaskAfter(block, name, err);
return complete(err);
};
block.blockTaskBefore(block, name);
return balUtilFlow.fireWithOptionalCallback(fn, [preComplete]);
});
return this;
};
return _Class;
})(balUtilFlow.Group);
balUtilFlow.Runner = (function() {
_Class.prototype.runnerBlock = null;
function _Class() {
var _ref;
if ((_ref = this.runnerBlock) == null) {
this.runnerBlock = new balUtilFlow.Block();
}
}
_Class.prototype.getRunnerBlock = function() {
return this.runnerBlock;
};
_Class.prototype.block = function() {
var args, _ref;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return (_ref = this.getRunnerBlock()).block.apply(_ref, args);
};
_Class.prototype.task = function() {
var args, _ref;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return (_ref = this.getRunnerBlock()).task.apply(_ref, args);
};
return _Class;
})();
if (typeof module !== "undefined" && module !== null) {
module.exports = balUtilFlow;
} else {
this.balUtilFlow = balUtilFlow;
}
}).call(this);