You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
568 lines
15 KiB
568 lines
15 KiB
// Generated by CoffeeScript 1.4.0
|
|
(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(__dirname + '/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, 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 (caughtError) {
|
|
callback(caughtError);
|
|
}
|
|
} else {
|
|
err = null;
|
|
try {
|
|
result = method.apply(context, args);
|
|
if (balUtilTypes.isError(result)) {
|
|
err = result;
|
|
}
|
|
} catch (caughtError) {
|
|
err = caughtError;
|
|
}
|
|
callback(err, result);
|
|
}
|
|
return result;
|
|
},
|
|
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;
|
|
},
|
|
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;
|
|
},
|
|
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(opts) {
|
|
var action, actions, args, next, object, tasks;
|
|
object = opts.object, action = opts.action, args = opts.args, tasks = opts.tasks, next = opts.next;
|
|
if (!action) {
|
|
throw new Error('balUtilFlow.flow called without any action');
|
|
}
|
|
actions = action.split(/[,\s]+/g);
|
|
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 = object[action];
|
|
return fn.apply(object, argsClone);
|
|
});
|
|
});
|
|
tasks.sync();
|
|
return this;
|
|
}
|
|
};
|
|
|
|
/*
|
|
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.async()
|
|
|
|
# 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.sync()
|
|
*/
|
|
|
|
|
|
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 = 'async';
|
|
|
|
_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)) {
|
|
this.mode = arg;
|
|
} 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 === 'sync' && 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 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 === 'async' || (this.completed % 100) === 0)) {
|
|
setTimeout(run, 0);
|
|
} else {
|
|
run();
|
|
}
|
|
} catch (err) {
|
|
this.complete(err);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
_Class.prototype.run = function() {
|
|
var task, _i, _len, _ref;
|
|
if (this.isRunning() === false) {
|
|
this.hasExited(false);
|
|
if (this.hasTasks()) {
|
|
if (this.mode === 'sync') {
|
|
this.nextTask();
|
|
} else {
|
|
_ref = this.queue;
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
task = _ref[_i];
|
|
this.nextTask();
|
|
}
|
|
}
|
|
} else {
|
|
this.exit();
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
_Class.prototype.async = function() {
|
|
this.mode = 'async';
|
|
this.run();
|
|
return this;
|
|
};
|
|
|
|
_Class.prototype.sync = function() {
|
|
this.mode = 'sync';
|
|
this.run();
|
|
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, 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 (err) {
|
|
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);
|