Overview
|
Coverage98.63
SLOC12999
LOC3567
Missed49
|
logging/appenders/rollingFileAppender.js
|
Coverage90.00
SLOC229
LOC90
Missed9
|
- 1
var define = require("../../define.js").define,
promise = require("../../promise"),
Promise = promise.Promise,
PromiseList = promise.PromiseList,
base = require("../../base"),
hitch = base.hitch,
string = base.string,
escape = base.regexp.escapeString,
style = string.style,
format = string.format,
FileAppender = require("./fileAppender"),
Level = require("../level"),
fs = require("fs"),
path = require("path");
- 1
var conversion = {
MB: 1048576,
KB: 1024,
GB: 1073741824
};
- 1
var DEFAULT_SIZE = "10MB";
- 1
var convertToBytes = function (str) {
- 3
var ret = DEFAULT_SIZE;
- 3
var match = str.match(/(\d+)(MB|KB|GB)$/);
- 3
if (match && match.length == 3) {
- 3
var size = parseInt(match[1], 10);
- 3
ret = size * conversion[match[2]];
}
- 3
return ret;
}
/**
* @class Appends messages to a file. Rolls files over when a size limit has been reached. Once the max file size has
* been reached it is rolled over to a file called <logName>.log.n where n is a number.
* </br></br>
* <p>Example. RollingFileAppender is current writing to myLog.log, the log reaches is max size to it is
* renamed to myLog.log.1 and a new myLog.log is created.</p>
* </br>
* If maxBackupIndex is reached then the log at that index is deleted. If maxBackupIndex is set to 0 then no log is
* rolled over.</p>
*
* @name RollingFileAppender
* @augments comb.logging.appenders.FileAppender
* @memberOf comb.logging.appenders
*
* @param {Object} [options] options to assign to this Appender
* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender
* on a logger it must have a different name.
* @param {String} [options.pattern="[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}"]
* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>
* <ul>
* <li>timeStamp - the timestamp of the event being logged</li>
* <li>level - the {@link comb.logging.Level} of the event</li>
* <li>levelName - the name of the level being logged</li>
* <li>name - the name of the logger logging the event</li>
* <li>message - the message being logged</li>
* </ul>
* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender
* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger
* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the
* appenders level is lower than the logger is will not recieve any messages.</p>
*
* @param {String} [options.file="./log.log"] the file to log events to.
* @param {String} [options.encoding="utf8"] the encoding of the file.
* @param {Boolean} [options.overwrite=false] if true the log file is overwritten otherwise it is appended to.
* @param {String} [options.maxSize="10MB"] the maxSize of a file. Valid options include "KB", "MB", or "GB"
*
* <pre class="code">
* maxSize = "100MB"
* //or
* maxSize = "100KB"
* //or
* maxSize = "1GB"
* </pre>
*
* @param {Number} [options.maxBackupIndex=10] the maximum number of files to rollOver.
*/
- 1
FileAppender.extend({
instance: {
__watching: false,
constructor: function (options) {
- 3
options = options || {};
- 3
this.maxSize = options.maxSize || DEFAULT_SIZE;
- 3
!options.name && (options.name = "rollingFileAppender");
- 3
this.maxBackupIndex = options.maxBackupIndex || 10;
- 3
this.__queue = [];
- 3
this.__inRollover = false;
- 3
this._super([options]);
},
__startCheck: function () {
- 1
if (!this.__watching) {
- 1
this.__watching = true;
- 1
fs.watchFile(this.__file, hitch(this, "__checkFile"));
- 1
fs.stat(this.__file, hitch(this, function (err, stat) {
- 1
this.__checkFile(stat);
}));
}
},
__checkFile: function (stats) {
- 5
var ret = new Promise(), self = this;
- 5
if (!this.__inRollover) {
- 3
if (stats.size >= this.maxSize) {
- 2
if (this.maxBackupIndex > 0) {
- 1
this.__inRollover = true;
- 1
this.__onExit()
.chain(function () {
- 1
return self.__rollover();
})
.chain(function () {
- 1
var ws = fs.createWriteStream(self.__file, {flags: "w", encoding: self.__encoding});
- 1
ws.on("open", function () {
- 1
self.__writeStream = ws;
- 1
self.__inRollover = false;
- 1
self.__checkQueue();
- 1
ret.callback();
});
}, function (err) {
- 0
process.stderr.write("comb.logging.appenders.RollingFileAppender : error rolling over files resuming writing");
- 0
process.stderr.write(err.stack);
- 0
var ws = fs.createWriteStream(self.__file, {flags: "w", encoding: self.__encoding});
- 0
ws.on("open", function () {
- 0
self.__writeStream = ws;
- 0
self.__inRollover = false;
- 0
self.__checkQueue();
- 0
ret.callback();
});
});
} else {
- 1
this.__writeStream = fs.createWriteStream(this.__file, {flags: "w", encoding: this.__encoding});
- 1
ret.callback();
}
} else {
- 1
ret.callback();
}
} else {
- 2
ret.callback();
}
- 5
return ret.promise();
},
append: function (event) {
- 12
if (this._canAppend(event)) {
- 12
!this.__watching && this.__startCheck();
- 12
var ws = this.__writeStream;
- 12
if (!this.__inRollover && ws && ws.writable) {
- 9
this._super(arguments);
} else {
- 3
this.__queue.push(event);
}
}
},
__checkQueue: function () {
- 1
this.__queue.forEach(this.append, this);
- 1
this.__queue.length = 0;
},
__rollover: function () {
- 1
var ret = new Promise(), file = this.__file, self = this;
- 1
var dir = path.dirname(file), baseName = new RegExp("(" + escape(path.basename(path.basename(file))) + ")(?:\\.(\\d*))*");
- 1
fs.readdir(dir, function (err, files) {
- 1
if (err) {
- 0
ret.errback(err);
} else {
- 1
files = files.filter(
function (f) {
- 5
var match = f.match(baseName);
- 5
if (match) {
- 4
return true;
} else {
- 1
return false;
}
});
- 1
files = files.sort(function (a, b) {
- 6
var ret = 0;
- 6
if (a > b) {
- 3
ret = 0;
- 3
} else if (a < b) {
- 3
ret = 1;
}
- 6
return ret;
});
- 1
var count = files.length, i = 0;
- 1
var checkFile = function () {
- 5
if (count > 0) {
- 4
var f = dir + "/" + files[i++];
- 4
if (count > self.maxBackupIndex) {
//drop the file;
- 1
count--;
- 1
fs.unlink(f, function (err) {
- 1
err ? ret.errback(err) : checkFile();
});
} else {
//rename the file
- 3
var rn = self.__file + "." + count--;
- 3
fs.rename(f, rn, function (err) {
- 3
err ? ret.errback(err) : checkFile();
});
}
} else {
- 1
ret.callback();
}
};
- 1
checkFile();
}
});
- 1
return ret.promise();
},
getters: {
maxSize: function () {
- 3
return this.__maxSize;
}
},
setters: {
maxSize: function (size) {
- 3
this.__maxSize = size ? convertToBytes(size) : DEFAULT_SIZE;
}
}
}
}).registerType("RollingFileAppender").as(module);
base/functions.js
|
Coverage90.91
SLOC374
LOC132
Missed12
|
- 1
var string = require("./string"),
object = require("./object"),
isArray = Array.isArray,
isObject = object.isObject,
isString = string.isString;
/**
* Determines if something is a function
* @param {Anything} obj the thing to test if it is a function
*
* @returns {Boolean} true if the obj is a function false otherwise
* @static
* @memberOf comb
*/
- 1
function isFunction(obj) {
- 18863
return typeof obj === "function";
}
- 1
function spreadArgs(f, args, scope) {
- 18114
var ret;
- 18114
switch ((args || []).length) {
case 0:
- 4985
ret = f.call(scope);
- 4980
break;
case 1:
- 7360
ret = f.call(scope, args[0]);
- 7348
break;
case 2:
- 3032
ret = f.call(scope, args[0], args[1]);
- 3031
break;
case 3:
- 2725
ret = f.call(scope, args[0], args[1], args[2]);
- 2725
break;
default:
- 12
ret = f.apply(scope, args);
}
- 18096
return ret;
}
/**
* Binds a method to a particular scope
*
* @static
* @memberOf comb
*
* @param {Object} scope the scope to bind the callback to
* @param {String|Function} method the method to callback
* @param [args] optional args to pass to the callback
*
* @returns {Function} the hitched function
*/
- 1
function hitch(scope, method, args) {
- 5235
args = Array.prototype.slice.call(arguments).slice(2);
- 5235
if ((isString(method) && !(method in scope))) {
- 2
throw new Error(method + " property not defined in scope");
- 5233
} else if (!isString(method) && !isFunction(method)) {
- 1
throw new Error(method + " is not a function");
}
- 5232
if (isString(method)) {
- 130
return function () {
- 379
var func = scope[method];
- 379
if (isFunction(func)) {
- 376
var scopeArgs = args.concat(Array.prototype.slice.call(arguments));
- 376
return spreadArgs(func, scopeArgs, scope);
} else {
- 3
return func;
}
};
} else {
- 5102
return function () {
- 3200
var scopeArgs = args.concat(Array.prototype.slice.call(arguments));
- 3200
return spreadArgs(method, scopeArgs, scope);
};
}
}
/**
* Binds a method to the scope of the first argument.
*
* This is useful if you have async actions and you just want to run a method or retrieve a property on the object.
*
* ```
* var arr = [], push = comb.applyFirst("push"), length = comb.applyFirst("length");
* push(arr, 1, 2,3,4);
* console.log(length(arr)); //4
* console.log(arr); //1,2,3,4
*
* ```
* @static
* @memberOf comb
* @param {String|Function} method the method to invoke in the scope of the first arument.
* @param [args] optional args to pass to the callback
*
* @returns {Function} a function that will execute the method in the scope of the first argument.
*/
- 1
function applyFirst(method, args) {
- 10
args = Array.prototype.slice.call(arguments).slice(1);
- 10
if (!isString(method) && !isFunction(method)) {
- 2
throw new Error(method + " must be the name of a property or function to execute");
}
- 8
if (isString(method)) {
- 4
return function () {
- 12
var scopeArgs = Array.prototype.slice.call(arguments), scope = scopeArgs.shift();
- 12
var func = scope[method];
- 12
if (isFunction(func)) {
- 6
scopeArgs = args.concat(scopeArgs);
- 6
return spreadArgs(func, scopeArgs, scope);
} else {
- 6
return func;
}
};
} else {
- 4
return function () {
- 4
var scopeArgs = Array.prototype.slice.call(arguments), scope = scopeArgs.shift();
- 4
scopeArgs = args.concat(scopeArgs);
- 4
return spreadArgs(method, scopeArgs, scope);
};
}
}
/**
* @function
* Binds a method to a particular scope
* @static
* @memberOf comb
* @param {Object} scope the scope to bind the callback to
* @param {String|Function} method the method to callback
* @param [args] optional args to pass to the callback
*
* @returns {Function} the hitched function
*/
- 1
exports.bind = hitch;
/**
* Binds a method to a particular scope ignoring any new arguments passed
* into the function. This is useful if you want to force particular arguments and
* ignore any new ones
* @static
* @memberOf comb
* @param {Object} scope the scope to bind the callback to
* @param {String|Function} method the method to callback
* @param [args] optional args to pass to the callback
*
* @returns {Function} the hitched function
*/
- 1
function hitchIgnore(scope, method, args) {
- 136
args = Array.prototype.slice.call(arguments).slice(2);
- 136
if ((isString(method) && !(method in scope))) {
- 2
throw new Error(method + " property not defined in scope");
- 134
} else if (!isString(method) && !isFunction(method)) {
- 1
throw new Error(method + " is not a function");
}
- 133
if (isString(method)) {
- 15
return function () {
- 15
var func = scope[method];
- 15
if (isFunction(func)) {
- 12
return spreadArgs(func, args, scope);
} else {
- 3
return func;
}
};
} else {
- 118
return function () {
- 107
return spreadArgs(method, args, scope);
};
}
}
/**
* @function
* Binds a method to a particular scope ignoring any new arguments passed
* into the function. This is useful if you want to force particular arguments and
* ignore any new ones
* @static
* @memberOf comb
* @param {Object} scope the scope to bind the callback to
* @param {String|Function} method the method to callback
* @param [args] optional args to pass to the callback
*
* @returns {Function} the hitched function
*/
- 1
exports.bindIgnore = hitchIgnore;
- 1
function hitchAll(scope, methods) {
- 0
var funcs = Array.prototype.slice.call(arguments).slice(1);
- 0
if (!isObject(scope)) {
- 0
throw new TypeError("scope must be an object");
}
- 0
if (funcs.length === 1 && isArray(funcs[0])) {
- 0
funcs = funcs[0];
}
- 0
if (!funcs.length) {
- 0
funcs = Object.keys(scope).filter(function (k) {
- 0
return isFunction(scope[k]);
});
}
- 0
for (var i = 0, l = funcs.length; i < l; i++) {
- 0
scope[funcs[i]] = hitch(scope, scope[funcs[i]]);
}
- 0
return object;
}
- 1
exports.hitchAll = hitchAll;
- 1
exports.bindAll = hitchAll;
/**
* Allows the passing of additional arguments to a function when it is called
* especially useful for callbacks that you want to provide additional parameters to
*
* @static
* @memberOf comb
* @param {String|Function} method the method to callback
* @param {Anything} [args] variable number of arguments to pass
*
* @returns {Function} partially hitched function
*/
- 1
function partial(method, args) {
- 8561
args = Array.prototype.slice.call(arguments).slice(1);
- 8561
if (!isString(method) && !isFunction(method)) {
- 2
throw new Error(method + " must be the name of a property or function to execute");
}
- 8559
if (isString(method)) {
- 4
return function () {
- 4
var func = this[method];
- 4
if (isFunction(func)) {
- 2
var scopeArgs = args.concat(Array.prototype.slice.call(arguments));
- 2
return spreadArgs(func, scopeArgs, this)
} else {
- 2
return func;
}
};
} else {
- 8555
return function () {
- 1728
var scopeArgs = args.concat(Array.prototype.slice.call(arguments));
- 1728
return spreadArgs(method, scopeArgs, this)
};
}
}
- 1
;
- 1
function curryFunc(f, execute) {
- 28
return function (arg) {
- 28
var args = Array.prototype.slice.call(arguments);
- 28
return execute ? f.apply(this, arguments) : function (arg) {
- 21
return spreadArgs(f, args.concat(Array.prototype.slice.call(arguments)), this);
};
};
}
/**
* Curries a function
* @example
* var curried = comb.curry(4, function(a,b,c,d){
* return [a,b,c,d].join(",");
* }
* curried("a");
* curried("b");
* curried("c");
* curried("d") => "a,b,c,d"
*
* //OR
*
* curried("a")("b")("c")("d") => "a,b,c,d"
*
* @static
* @memberOf comb
* @param {Number} depth the number of args you expect
* @param {Function} cb the function to call once all args are gathered
* @param {Object} [scope] what scope to call the function in
*
* @returns {Function} the curried version of the function
* */
- 1
function curry(depth, cb, scope) {
- 7
var f;
- 7
if (scope) {
- 5
f = hitch(scope, cb);
} else {
- 2
f = cb;
}
- 7
if (depth) {
- 7
var len = depth - 1;
- 7
for (var i = len; i >= 0; i--) {
- 28
f = curryFunc(f, i === len);
}
}
- 7
return f;
}
/**
* Binds all methods or a specified array of function to the scope of the object
* @example
* var f = {
* a: function(){
* return "a";
* },
* b: function(){
* return "b";
* }
* }
*
* comb.hitchAll(f, "a", "b");
*
* //or
*
* comb.hitchAll(f);
*
* @static
* @memberOf comb
* @param {Object} scope the object to bind methods on
* @param {...} funcs varargs of methods to bind
*
* @returns {Object} the originally scoped object.
* */
- 1
function hitchAll(scope) {
- 3
var funcs = Array.prototype.slice.call(arguments, 1);
- 3
if (!isObject(scope) && !isFunction(scope)) {
- 0
throw new TypeError("scope must be an object");
}
- 3
if (funcs.length === 1 && isArray(funcs[0])) {
- 1
funcs = funcs[0];
}
- 3
if (!funcs.length) {
- 1
funcs = [];
- 1
for (var k in scope) {
- 6
if (scope.hasOwnProperty(k) && isFunction(scope[k])) {
- 3
funcs.push(k);
}
}
}
- 3
for (var i = 0, l = funcs.length; i < l; i++) {
- 6
scope[funcs[i]] = hitch(scope, scope[funcs[i]]);
}
- 3
return scope;
}
/**
* Binds all methods or a specified array of function to the scope of the object
* @example
* var f = {
* a: function(){
* return "a";
* },
* b: function(){
* return "b";
* }
* }
*
* comb.bindAll(f, "a", "b");
*
* //or
*
* comb.bindAll(f);
*
* @static
* @memberOf comb
* @param {Object} scope the object to bind methods on
* @param {...} funcs varargs of methods to bind
*
* @returns {Object} the originally scoped object.
* */
- 1
exports.bindAll = hitchAll;
- 1
exports.hitchAll = hitchAll;
- 1
exports.isFunction = isFunction;
- 1
exports.hitch = hitch;
- 1
exports.hitchIgnore = hitchIgnore;
- 1
exports.partial = partial;
- 1
exports.applyFirst = applyFirst;
- 1
exports.bindFirst = applyFirst;
- 1
exports.curry = curry;
- 1
exports.__spreadArgs = spreadArgs;
plugins/Middleware.js
|
Coverage95.56
SLOC221
LOC45
Missed2
|
- 1
var func = require("../base/functions"),
obj = require("../base/object"),
Promise = require("../promise").Promise,
define = require("../define").define;
- 1
var nextTick;
- 1
if (typeof setImmediate === "function") {
// In IE10, or use https://github.com/NobleJS/setImmediate
- 1
nextTick = setImmediate;
} else {
- 0
nextTick = function (cb) {
- 0
process.nextTick(cb);
};
}
- 1
var Middleware = define(null, {
instance: {
/** @lends comb.plugins.Middleware.prototype */
__hooks: {pre: {}, post: {}},
/**
* @class Plugin to enable middleware on a class
*
* @example
*
* var Mammal = define(comb.plugins.Middleware, {
* instance : {
*
* constructor: function(options) {
* options = options || {};
* this.super(arguments);
* this._type = options.type || "mammal";
* },
*
* speak : function() {
* var ret = new comb.Promise();
* this._hook("pre", "speak")
* .then(comb.hitch(this, "_hook", "post", "speak"), hitch(ret, "errback"))
* .then(comb.hitch(ret, "callback"), comb.hitch(ret, "errback"));
* return ret;
* }
* }
*});
*
* Mammal.pre('speak', function(next){
* //do something meaningful
* next();
* });
* var m = new Mammal({color : "gold"});
* m.speak();
*
* @constructs
*/
constructor: function () {
- 6
this.__hooks = obj.merge({}, this.__hooks);
- 6
this._super(arguments);
},
/**
* <p>Protected!</p>
*
* <p>Call to initiate middleware for the topic</p>
* <p><b>NOTE:</b> this function takes a variable number of arguments
* whatever comes after the op param will be passed into
* the listening function, with the last argument to the listenting
* function being the next function</p>
*
*
* @public
* @param {"pre"|"post"} state the state in which the hook should be called
* @param {String} op the operation that is being acted upong
* @param args arguments to be passed into the listening functions.
* @returns {comb.Promise} a promise to use after middleware chain completes
*
*/
_hook: function (state, op, args) {
- 11
args = args || [];
- 11
var promise = new Promise();
- 11
var funcs, length;
- 11
if (this.__hooks[state] && (funcs = this.__hooks[state][op]) != null && (length = funcs.length) > 0) {
- 7
var count = 0;
- 7
var next = func.hitch(this, function (err) {
- 15
if (err) {
- 1
promise.errback(err);
} else {
- 14
nextTick(func.hitch(this, function () {
//if Ive looped through all of them callback
- 14
if (count == length) {
- 6
promise.callback();
} else {
//call next
- 8
var nextArgs = args.slice(0);
- 8
nextArgs.unshift(next);
- 8
funcs[count++].apply(this, nextArgs);
}
}));
}
});
- 7
next();
} else {
- 4
promise.callback();
}
- 11
return promise.promise();
},
/**
* Use to listen to before an event occurred i.e. pre save
*
* <b>NOTE:</b></br>
* <ul>
* <li>You must call next in order for the middleware chain to complete</li>
* <li>This connects to events on the instance of an object, not all instances!</li>
* <li>Hooks are called in the order they are received!</li>
* <li> When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>
* </ul>
*
* @example
* instance.pre("save", function(args,...., next){
* //do something...
* //you have to call next!!!!!
* next();
* });
*
* */
pre: function (fun, callback) {
- 1
var hook = this.__hooks.pre[fun];
- 1
if (!hook) {
- 1
hook = this.__hooks.pre[fun] = [];
}
- 1
hook.push(callback);
},
/**
* <p>Use to listen to after an event has occurred i.e. post save</p>
* <b>NOTE:</b></br>
* <ul>
* <li>You must call next in order for the middleware chain to complete</li>
* <li>This connects to events on the instance of an object, NOT all instances!</li>
* <li>Hooks are called in the order they are received!</li>
* <li>When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>
* </ul>
* @example
*
* instance.post("save", function(next){
* //do something...
* //you have to call next!!!!!
* next();
* });
* */
post: function (fun, callback) {
- 1
var hook = this.__hooks.post[fun];
//if I havent initialized it create it;
- 1
if (hook == undefined) {
- 1
hook = this.__hooks.post[fun] = [];
}
- 1
hook.push(callback);
}
},
static: {
/** @lends comb.plugins.Middleware */
/**
*<p> Use to listen to after an event has occurred i.e. post save</p>
*
* <b>NOTE:</b></br>
* <ul>
* <li>You must call next in order for the middleware chain to complete</li>
* <li>This connects to events on ALL instances of an object</li>
* <li>Hooks are called in the order they are received!</li>
* <li>When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>
* </ul>
*
* @example
* Class.pre("save", function(next){
* ...
* //you must call next
* });
* */
pre: function (name, cb) {
- 2
var hooks = this.prototype.__hooks;
- 2
var hook = hooks.pre[name];
- 2
if (!hook) {
- 1
hook = hooks.pre[name] = [];
}
- 2
hook.push(cb);
},
/**
*<p>Use to listen to after an event has occurred i.e. post save</p>
*
*<b>NOTE:</b></br>
* <ul>
* <li>You must call next in order for the middleware chain to complete</li>
* <li>This connects to events on ALL instances of an object</li>
* <li>Hooks are called in the order they are received!</li>
* <li>When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>
* </ul>
*
* @example
* Class.post("save", function(next){
* ...
* //you must call next
* });
* */
post: function (name, cb) {
- 1
var hooks = this.prototype.__hooks;
- 1
var hook = hooks.post[name];
- 1
if (!hook) {
- 1
hook = hooks.post[name] = [];
}
- 1
hook.push(cb);
}
}
});
- 1
module.exports = exports = Middleware;
promise.js
|
Coverage96.10
SLOC998
LOC282
Missed11
|
- 1
var define = require("./define").define,
base = require("./base"),
isObject = base.isObject,
hitch = base.hitch,
hitchAll = base.hitchAll,
partial = base.partial,
argsToArray = base.argsToArray,
array = base.array,
forEach = array.forEach,
zip = array.zip,
flatten = array.flatten,
isUndefinedOrNull = base.isUndefinedOrNull,
isArray = base.isArray,
isFunction = base.isFunction,
bindIgnore = base.bindIgnore,
isInstanceOf = base.isInstanceOf,
spreadArgs = base.__spreadArgs;
- 1
var nextTick;
- 1
if (typeof setImmediate === "function") {
// In IE10, or use https://github.com/NobleJS/setImmediate
- 1
nextTick = setImmediate;
} else {
- 0
nextTick = function (cb) {
- 0
process.nextTick(cb);
};
}
- 1
function reject(e) {
- 0
return new Promise().errback(e);
}
- 1
function promiseWrapper(wrapper, promise, action) {
- 0
var m = promise[action];
- 0
wrapper[action] = hitch(promise, function () {
- 0
spreadArgs(m, arguments, this);
- 0
return wrapper;
});
}
- 1
var Promise = define(null, {
instance: {
/** @lends comb.Promise.prototype */
__fired: false,
__results: null,
__error: null,
__errorCbs: null,
__cbs: null,
/**
* Promise object used to provide seperation of success and error resolution paths for async operations.
*
* @example
* var myFunc = function(){
* var promise = new Promise();
* //callback the promise after 10 Secs
* setTimeout(hitch(promise, "callback"), 10000);
* return promise.promise();
* }
* var myFunc2 = function(){
* var promises =[];
* for(var i = 0; i < 10; i++){
* promises.push(myFunc);
* }
* //create a new promise list with all 10 promises
* return new PromiseList(promises).promise();
* }
*
* myFunc.then(function(success){}, function(error){})
* //chain promise operations
* myFunc.chain(myfunc).then(function(success){}, function(error){})
*
* myFunc2.then(function(success){}, function(error){})
* //chain promise operations
* myFunc2.chain(myfunc).then(function(success){}, function(error){})
* @constructs
*/
constructor: function () {
- 2526
this.__errorCbs = [];
- 2526
this.__cbs = [];
- 2526
this.callback = hitch(this, this.callback);
- 2526
this.errback = hitch(this, this.errback);
},
/**
* @private
*/
__resolve: function () {
- 2374
var self = this;
- 2374
if (!self.__fired) {
- 2374
self.__fired = true;
- 2374
nextTick(function () {
- 2373
var cbs = self.__error ? self.__errorCbs : self.__cbs,
res = self.__error || self.__results,
i = -1, l = cbs.length;
- 2373
while (++i < l) {
- 2264
spreadArgs(cbs[i], res);
}
- 2373
self.__errorCbs.length = self.__cbs.length = 0;
- 2373
self = null;
});
}
},
__callNextTick: function (cb, results) {
- 760
nextTick(function () {
- 760
spreadArgs(cb, results);
- 760
cb = results = null;
});
},
/**
* Add a callback to the callback chain of the promise
*
*
* @param {Function|comb.Promise} cb the function or promise to callback when the promise is resolved.
*
* @return {comb.Promise} this promise for chaining
*/
addCallback: function (cb) {
- 3045
if (cb) {
- 3045
if (isPromise(cb)) {
- 2
cb = cb.callback;
}
- 3045
if (this.__fired && this.__results) {
- 740
this.__callNextTick(cb, this.__results);
} else {
- 2305
this.__cbs.push(cb);
}
}
- 3045
return this;
},
/**
* Add a callback to the errback chain of the promise
*
* @param {Function|comb.Promise} cb the function or promise to callback when the promise errors
*
* @return {comb.Promise} this promise for chaining
*/
addErrback: function (cb) {
- 2927
if (cb) {
- 2921
if (isPromise(cb)) {
- 0
cb = cb.errback;
}
- 2921
if (this.__fired && this.__error) {
- 20
this.__callNextTick(cb, this.__error);
} else {
- 2901
this.__errorCbs.push(cb);
}
}
- 2927
return this;
},
/**
*
* Adds a callback or promise to be resolved for both success
* and error.
*
* @param {Function|comb.Promise} cb callback or promise to be resolved for both success
* and error.
* @return {comb.Promise} this promise for chaining
*/
both: function (cb) {
- 580
this.addCallback(cb);
- 580
if (isPromise(cb)) {
- 2
this.addErrback(cb.callback);
} else {
- 578
this.addErrback(cb);
}
- 580
return this;
},
/**
* When called all functions registered as callbacks are called with the passed in results.
*
* @param {*} args variable number of results to pass back to listeners of the promise
*/
callback: function (args) {
- 2209
args = argsToArray(arguments);
- 2209
if (this.__fired) {
- 1
throw new Error("Already fired!");
}
- 2208
this.__results = args;
- 2208
this.__resolve();
- 2208
return this.promise();
},
/**
* When called all functions registered as errbacks are called with the passed in error(s)
*
* @param {*} args number of errors to pass back to listeners of the promise
*/
errback: function (args) {
- 170
if (this.__fired) {
- 4
throw args || new Error("Already fired");
}
- 166
this.__error = argsToArray(arguments);
- 166
this.__resolve();
- 166
return this.promise();
},
/**
* Resolved a promise using the node style callback.
*
* @example
*
* var promise = new Promise();
* fs.readFile("file.txt", "utf8", promise.resolve.bind(promise));
* promise.then(function(file){
* console.log(file);
* });
*
* @param {Error} [err=null] If specified then the promise will error out
* @param {...} [args] if err is null then the aruments will be used to resolve the promise.
*
* @return {comb.Promise} for chaining.
*/
resolve: function (err, args) {
- 4
if (err) {
- 1
this.errback(err);
} else {
- 3
spreadArgs(this.callback, argsToArray(arguments, 1), this);
}
- 4
return this;
},
/**
* Call to specify action to take after promise completes or errors
*
* @param {Function} [callback=null] function to call after the promise completes successfully
* @param {Function} [errback=null] function to call if the promise errors
*
* @return {comb.Promise} this promise for chaining
*/
then: function (callback, errback) {
- 1858
if (isPromise(callback)) {
- 153
errback = callback.errback;
- 153
callback = callback.callback;
}
- 1858
this.addCallback(callback);
- 1858
this.addErrback(errback);
- 1858
return this;
},
/**
* Call this function as a classic node callback where the first argument
* will be an error, or null if no error occured. The other arugments will
* be the result from the promise.
*
* @example
*
* promise.classic(function(err, res){
* if(err){
* console.log(err);
* }else{
* console.log(res);
* }
* });
*
* @param cb callback where the first argument
* will be an error, or null if no error occured. The other arugments will
* be the result from the promise.
* @return {comb.Promise} the promise to chain
*/
classic: function (cb) {
- 5
if ("function" === typeof cb) {
- 5
this.addErrback(cb);
- 5
this.addCallback(partial(cb, null));
}
- 5
return this;
},
/**
* Call to chaining of promises
*
* ```
* new Promise()
* .callback("hello")
* .chain(function(previousPromiseResults){
* return previousPromiseResults + " world";
* }, errorHandler)
* .chain(function(previousPromiseResults){
* return when(dbCall());
* }).classic(function(err, results){
* //all promises are done
* });
*
* ```
*
* You can also use static values
*
* ```
* new Promise().callback()
* .chain("hello")
* .chain(function(prev){
* return prev + " world!"
* }).then(function(str){
* console.log(str); //"hello world!"
* });
* ```
*
* If you do not provide an `errback` for each chain then it will be propogated to the final promise
*
*
* ```
* new Promise()
* .chain(function(){
* return new comb.Promise().errback(new Error("error"));
* })
* .chain(function(){
* return prev + " world!"
* })
* .classic(function(err, str){
* console.log(err.message); //"error"
* });
* ```
*
*
* @param callback method to call this one completes. If you return a promise the execution will delay until the returned promise has resolved.
* @param [errback=null] method to call if this promise errors. If errback is not specified then the returned promises
* errback method will be used.
*
* @return {comb.Promise} A new that wraps the promise for chaining
*/
chain: function (callback, errback) {
- 600
var promise = new Promise(),
self = this;
- 600
function _errback(e) {
- 94
if (isFunction(errback)) {
- 15
try {
- 15
var res = spreadArgs(errback, [e]);
- 11
isPromiseLike(res) ? res.then(promise.callback, promise.errback) : promise.callback(res);
} catch (e) {
- 4
promise.errback(e);
}
} else {
- 79
promise.errback(e);
}
}
- 600
function _callback() {
- 542
try {
- 542
var res = isFunction(callback) ? spreadArgs(callback, arguments) : callback;
- 538
if (isPromiseLike(res)) {
- 206
res.then(promise.callback, _errback);
} else {
- 332
promise.callback(res);
- 332
promise = null;
}
- 538
callback = res = null;
} catch (e) {
- 4
_errback(e);
}
}
- 600
self.addCallback(_callback);
- 600
self.addErrback(_errback);
- 600
return promise.promise();
},
/**
* Applies the same function that returns a promise to both the callback and errback.
*
* @param {Function} callback function to call. This function must return a Promise
*
* @return {comb.Promise} a promise to continue chaining or to resolve with.
*
*/
chainBoth: function (callback) {
- 10
var promise = new Promise();
- 10
this.addCallback(function () {
- 5
try {
- 5
when(isFunction(callback) ? callback.apply(this, arguments) : callback).then(promise);
} catch (e) {
- 1
promise.errback(e);
}
});
- 10
this.addErrback(function () {
- 5
try {
- 5
when(isFunction(callback) ? callback.apply(this, arguments) : callback).then(promise);
} catch (e) {
- 1
promise.errback(e);
}
});
- 10
return promise.promise();
},
/**
* Creates an object to that contains methods to listen to resolution but not the "callback" or "errback" methods.
*
* @example
*
* var asyncMethod = function(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, "hello"));
* return ret.promise();
* }
*
* asyncMethod().callback() //throws error
*
* @return {Object} an object containing "chain", "chainBoth", "promise", "addCallback", "addErrback", "then", "both".
*/
promise: function () {
- 4220
var ret = {
promise: function () {
- 765
return ret;
}
};
- 4220
var self = this;
- 4220
ret["chain"] = function () {
- 590
return spreadArgs(self["chain"], arguments, self);
};
- 4220
ret["chainBoth"] = function () {
- 5
return spreadArgs(self["chainBoth"], arguments, self);
};
- 4220
ret["addCallback"] = function () {
- 120
spreadArgs(self["addCallback"], arguments, self);
- 120
return ret;
};
- 4220
ret["addErrback"] = function () {
- 7
spreadArgs(self["addErrback"], arguments, self);
- 7
return ret;
};
- 4220
ret["then"] = function () {
- 1143
spreadArgs(self["then"], arguments, self);
- 1143
return ret;
};
- 4220
ret["both"] = function () {
- 0
spreadArgs(self["both"], arguments, self);
- 0
return ret;
};
- 4220
ret["classic"] = function () {
- 3
spreadArgs(self["classic"], arguments, self);
- 3
return ret;
};
- 4220
return ret;
}
}
});
- 1
var PromiseList = define(Promise, {
instance: {
/** @lends comb.PromiseList.prototype */
/*@private*/
__results: null,
/*@private*/
__errors: null,
/*@private*/
__promiseLength: 0,
/*@private*/
__defLength: 0,
/*@private*/
__firedLength: 0,
normalizeResults: false,
/**
* PromiseList object used for handling a list of Promises
*
* @example
* var myFunc = function(){
* var promise = new Promise();
* //callback the promise after 10 Secs
* setTimeout(hitch(promise, "callback"), 10000);
* return promise.promise();
* }
* var myFunc2 = function(){
* var promises =[];
* for(var i = 0; i < 10; i++){
* promises.push(myFunc);
* }
* //create a new promise list with all 10 promises
* return new PromiseList(promises).promise();
* }
*
* myFunc.then(function(success){}, function(error){})
* //chain promise operations
* myFunc.chain(myfunc).then(function(success){}, function(error){})
*
* myFunc2.then(function(success){}, function(error){})
* //chain promise operations
* myFunc2.chain(myfunc).then(function(success){}, function(error){})
*
* @param {comb.Promise[]} [defs=[]] the list of promises
* @constructs
* @augments comb.Promise
* @memberOf comb
* */
constructor: function (defs, normalizeResults) {
- 140
this.__errors = [];
- 140
this.__results = [];
- 140
this.normalizeResults = base.isBoolean(normalizeResults) ? normalizeResults : false;
- 140
this._super(arguments);
- 140
if (defs && defs.length) {
- 135
this.__defLength = defs.length;
- 135
forEach(defs, this.__addPromise, this);
} else {
- 5
this.__resolve();
}
},
/**
* Add a promise to our chain
* @private
* @param promise the promise to add to our chain
* @param i the index of the promise in our chain
*/
__addPromise: function (promise, i) {
- 757
var self = this;
- 757
promise.then(
function () {
- 742
var args = argsToArray(arguments);
- 742
args.unshift(i);
- 742
spreadArgs(self.callback, args, self);
- 742
promise = i = self = null;
},
function () {
- 15
var args = argsToArray(arguments);
- 15
args.unshift(i);
- 15
spreadArgs(self.errback, args, self);
- 15
promise = i = self = null;
});
},
/**
* Resolves the promise
* @private
*/
__resolve: function () {
- 140
if (!this.__fired) {
- 140
this.__fired = true;
- 140
var self = this;
- 140
nextTick(function () {
- 140
var cbs = self.__errors.length ? self.__errorCbs : self.__cbs,
len = cbs.length, i,
results = self.__errors.length ? self.__errors : self.__results;
- 140
for (i = 0; i < len; i++) {
- 136
spreadArgs(cbs[i], [results]);
}
});
}
},
__callNextTick: function (cb, results) {
- 7
nextTick(function () {
- 7
spreadArgs(cb, [results]);
- 7
cb = results = null;
});
},
addCallback: function (cb) {
- 143
if (cb) {
- 143
if (isPromise(cb)) {
- 1
cb = cb.callback;
}
- 143
if (this.__fired && !this.__errors.length) {
- 7
this.__callNextTick(cb, this.__results);
} else {
- 136
this.__cbs.push(cb);
}
}
- 143
return this;
},
addErrback: function (cb) {
- 141
if (cb) {
- 141
if (isPromise(cb)) {
- 1
cb = cb.errback;
}
- 141
if (this.__fired && this.__errors.length) {
- 0
this.__callNextTick(cb, this.__errors);
} else {
- 141
this.__errorCbs.push(cb);
}
}
- 141
return this;
},
callback: function (i) {
- 743
if (this.__fired) {
- 1
throw new Error("Already fired!");
}
- 742
var args = argsToArray(arguments);
- 742
if (this.normalizeResults) {
- 725
args = args.slice(1);
- 725
args = args.length == 1 ? args.pop() : args;
}
- 742
this.__results[i] = args;
- 742
this.__firedLength++;
- 742
if (this.__firedLength == this.__defLength) {
- 130
this.__resolve();
}
- 742
return this.promise();
},
errback: function (i) {
- 16
if (this.__fired) {
- 1
throw new Error("Already fired!");
}
- 15
var args = argsToArray(arguments);
- 15
if (this.normalizeResults) {
- 14
args = args.slice(1);
- 14
args = args.length == 1 ? args.pop() : args;
}
- 15
this.__errors[i] = args;
- 15
this.__firedLength++;
- 15
if (this.__firedLength == this.__defLength) {
- 5
this.__resolve();
}
- 15
return this.promise();
}
}
});
/**
* Creates the promise chain
* @ignore
* @private
*/
- 1
function callNext(list, results, propogate) {
- 59
var ret = new Promise().callback();
- 59
forEach(list, function (listItem) {
- 156
ret = ret.chain(propogate ? listItem : bindIgnore(null, listItem));
- 156
if (!propogate) {
- 112
ret.addCallback(function (res) {
- 89
results.push(res);
- 89
res = null;
});
}
});
- 59
return propogate ? ret.promise() : ret.chain(results);
}
/**
* Tests if an object is like a promise (i.e. it contains then, addCallback, addErrback)
* @param obj object to test
* @function
* @static
* @memberOf comb
*/
- 1
function isPromiseLike(obj) {
- 2731
return isObject(obj, Promise) && typeof obj.then === "function";
}
- 1
function isPromise(obj) {
- 8688
return obj instanceof Promise;
}
/**
* Waits for promise and non promise values to resolve and fires callback or errback appropriately. If you pass in an array of promises
* then it will wait for all promises in the list to resolve.
*
* @example
* var a = "hello";
* var b = new comb.Promise().callback(world);
* comb.when(a, b) => called back with ["hello", "world"];
*
* @param {Anything...} args variable number of arguments to wait for.
* @param {Function} cb the callback function
* @param {Function} eb the errback function
* @returns {comb.Promise} a promise that is fired when all values have resolved
* @static
* @memberOf comb
*/
- 1
function when(args, cb, eb) {
- 1373
var args = argsToArray(arguments), p;
- 1373
eb = base.isFunction(args[args.length - 1]) ? args.pop() : null;
- 1373
cb = base.isFunction(args[args.length - 1]) ? args.pop() : null;
- 1373
if (eb && !cb) {
- 9
cb = eb;
- 9
eb = null;
}
- 1373
if (!args.length) {
- 7
p = new Promise().callback(args);
- 1366
} else if (args.length == 1) {
- 1326
args = args.pop();
- 1326
if (isPromiseLike(args)) {
- 651
p = args;
- 675
} else if (isArray(args) && array.every(args, isPromiseLike)) {
- 89
p = new PromiseList(args, true);
} else {
- 586
p = new Promise().callback(args);
}
} else {
- 40
p = new PromiseList(args.map(function (a) {
- 135
return isPromiseLike(a) ? a : new Promise().callback(a);
}), true);
}
- 1373
if (cb) {
- 15
p.addCallback(cb);
}
- 1373
if (eb) {
- 6
p.addErrback(eb);
}
- 1373
return p.promise();
}
/**
* Wraps traditional node style functions with a promise.
* @example
*
* var fs = require("fs");
* var readFile = comb.wrap(fs.readFile, fs);
* readFile(__dirname + "/test.json").then(
* function(buffer){
* console.log(contents);
* },
* function(err){
*
* } console.error(err);
* );
*
*
* @param {Function} fn function to wrap
* @param {Object} scope scope to call the function in
*
* @return {Funciton} a wrapped function
* @static
* @memberOf comb
*/
- 1
function wrap(fn, scope) {
- 2
return function () {
- 2
var ret = new Promise();
- 2
var args = argsToArray(arguments);
- 2
args.push(ret.resolve.bind(ret));
- 2
fn.apply(scope || this, args);
- 2
return ret.promise();
}
}
/**
* Executes a list of items in a serial manner. If the list contains promises then each promise
* will be executed in a serial manner, if the list contains non async items then the next item in the list
* is called.
*
* @example
*
* var asyncAction = function(item, timeout){
* var ret = new comb.Promise();
* setTimeout(comb.hitchIgnore(ret, "callback", item), timeout);
* return ret.promise();
* };
*
* comb.serial([
* comb.partial(asyncAction, 1, 1000),
* comb.partial(asyncAction, 2, 900),
* comb.partial(asyncAction, 3, 800),
* comb.partial(asyncAction, 4, 700),
* comb.partial(asyncAction, 5, 600),
* comb.partial(asyncAction, 6, 500)
* ]).then(function(results){
* console.log(results); // [1,2,3,4,5,6];
* });
*
*
*
* @param list
* @param callback
* @param errback
* @static
* @memberOf comb
*/
- 1
function serial(list, callback, errback) {
- 56
if (base.isArray(list)) {
- 55
return callNext(list, [], false);
} else {
- 1
throw new Error("When calling comb.serial the first argument must be an array");
}
}
/**
* Works just like {@link comb.Promise#chain} method, allowing you to propogate results from one funciton to another.
* This is different than {@link comb.serial} in that it propogates results from one promise to the next, where
* {@link comb.serial} does not.
*
* @example
*
* function asyncAction(add, timeout) {
* return function (num) {
* num = num || 0;
* var ret = new comb.Promise();
* setTimeout(function () {
* ret.callback(num + add);
* }, timeout);
* return ret;
* }
* }
*
* comb.chain([
* asyncAction(1, 100),
* asyncAction(2, 100),
* asyncAction(3, 100),
* asyncAction(4, 100),
* asyncAction(5, 100),
* ]).then(function(results){
* console.log(results); //15
* });
*
* @param {function[]} list an array of function to call.
* @return {comb.Promise} a promise that will resolve with the results of the last function in the list.
* @static
* @memberOf comb
*/
- 1
function chain(list) {
- 5
if (base.isArray(list)) {
- 4
return callNext(list, [], true);
} else {
- 1
throw new Error("When calling comb.serial the first argument must be an array");
}
}
/**
* Ensures that a promise is resolved before a the function can be run.
*
* For example suppose you have to ensure that you are connected to a database before you execute a function.
*
* ```
* var findUser = comb.wait(connect(), function findUser(id){
* //this wont execute until we are connected
* return User.findById(id);
* });
*
* comb.when(findUser(1), findUser(2)).then(function(users){
* var user1 = users[0], user2 = users[1];
* });
*
* ```
*
* @param args variable number of arguments to wait on. See {@link comb.when}.
* @param {Function} fn function that will wait.
* @return {Function} a function that will wait on the args to resolve.
* @memberOf comb
* @static
*/
- 1
function wait(args, fn) {
- 2
var args = argsToArray(arguments), resolved = false;
- 2
fn = args.pop();
- 2
var p = when(args);
- 2
return function waiter() {
- 3
if (!resolved) {
- 2
var args = arguments;
- 2
return p.chain(function () {
- 2
resolved = true;
- 2
p = null;
- 2
return fn.apply(this, args);
}.bind(this));
} else {
- 1
return when(fn.apply(this, arguments));
}
};
}
/**
* Wraps a stream in a promise waiting for either the `"end"` or `"error"` event to be triggered.
*
* ```
* comb.promisfyStream(fs.createdReadStream("my.file")).chain(function(){
* console.log("done reading!");
* });
*
* ```
*
* @param stream stream to wrap
* @return {comb.Promise} a Promise is resolved if `"end"` is triggered before `"error"` or rejected if `"error"` is triggered.
* @memberOf comb
* @static
*/
- 1
function promisfyStream(stream) {
- 2
var ret = new Promise(), called;
- 2
function errorHandler() {
- 1
if (!called) {
- 1
called = true;
- 1
spreadArgs(ret.errback, arguments, ret);
- 1
stream.removeListener("error", endHandler);
- 1
stream.removeListener("end", endHandler);
- 1
stream = ret = null;
}
}
- 2
function endHandler() {
- 1
if (!called) {
- 1
called = true;
- 1
spreadArgs(ret.callback, arguments, ret);
- 1
stream.removeListener("error", endHandler);
- 1
stream.removeListener("end", endHandler);
- 1
stream = ret = null;
}
}
- 2
stream.on("error", errorHandler).on("end", endHandler);
- 2
return ret.promise();
}
/**
* Creates a new {@link comb.Promise} that is resolved with the given value.
*
* ```
* comb.resolved(1).chain(function(val){
* //val === 1
* });
* ```
*
* If you give it a promise it will wait for the promise to resolve or error.
*
* ```
* comb.resolved(new comb.Promise().callback(1)).chain(function(val){
* //val === 1
* });
* ```
*
* @param val - val to resolve with
* @returns {comb.Promise} a promisfied version of the value.
* @memberOf comb
* @static
*/
- 1
function resolved(val) {
- 5
var ret = new Promise();
- 5
when(val).chain(ret.callback, ret.errback);
- 5
return ret.promise();
}
/**
* Creates a new {@link comb.Promise} that is rejected with the given value.
*
* ```
* comb.resolved(new Error("error!")).chain(null, function(err){
* console.error(err.stack);
* });
* ```
*
* If you give it a promise it will wait for the promise to resolve or error but with reject either way.
*
* ```
* comb.resolved(new comb.Promise().callback(1)).chain(null, function(err){
* //err === 1
* });
* ```
*
* @param val - val to reject with
* @returns {comb.Promise} a rejected promise with the specified value.
* @memberOf comb
* @static
*/
- 1
function rejected(val) {
- 4
var ret = new Promise();
- 4
when(val).chain(ret.errback, ret.errback);
- 4
return ret.promise();
}
- 1
base.merge(exports, {
isPromiseLike: isPromiseLike,
when: when,
wrap: wrap,
wait: wait,
serial: serial,
chain: chain,
promisfyStream: promisfyStream,
resolved: resolved,
rejected: rejected,
Promise: Promise,
PromiseList: PromiseList
});
define.js
|
Coverage96.49
SLOC603
LOC171
Missed6
|
/**
* Used to keep track of classes and to create unique ids
* @ignore
*/
- 1
var classCounter = 0, Base,
_base = require("./base"),
isHash = _base.isHash,
isArray = _base.isArray,
SUPER_REGEXP = /(super)/ig,
invoke = _base.__spreadArgs;
- 1
function callSuper(args, a) {
- 1243
var meta = this.__meta,
supers = meta.supers,
l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;
- 1243
if (l > pos) {
- 1243
a && (args = a);
- 1243
var name = superMeta.name, f = superMeta.f, m;
- 1243
do {
- 1243
m = supers[pos][name];
- 1243
if ("function" === typeof m && (m = m._f || m) !== f) {
- 1239
superMeta.pos = 1 + pos;
- 1239
return invoke(m, args, this);
}
} while (l > ++pos);
}
- 4
return null;
}
- 1
function getSuper() {
- 2
var meta = this.__meta,
supers = meta.supers,
l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;
- 2
if (l > pos) {
- 2
var name = superMeta.name, f = superMeta.f, m;
- 2
do {
- 3
m = supers[pos][name];
- 3
if ("function" === typeof m && (m = m._f || m) !== f) {
- 1
superMeta.pos = 1 + pos;
- 1
return m.bind(this);
}
} while (l > ++pos);
}
- 1
return null;
}
- 1
function defaultFunction() {
- 287
var meta = this.__meta || {},
supers = meta.supers,
l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;
- 287
if (l > pos) {
- 143
var name = superMeta.name, f = superMeta.f, m;
- 143
do {
- 223
m = supers[pos][name];
- 223
if ("function" === typeof m && (m = m._f || m) !== f) {
- 96
superMeta.pos = 1 + pos;
- 96
return invoke(m, arguments, this);
}
} while (l > ++pos);
}
- 191
return null;
}
- 1
function functionWrapper(f, name) {
- 318
if (f.toString().match(SUPER_REGEXP)) {
- 104
var wrapper = function () {
- 2128
var ret, meta = this.__meta || {};
- 2128
var orig = meta.superMeta;
- 2128
meta.superMeta = {f: f, pos: 0, name: name};
- 2128
ret = invoke(f, arguments, this);
- 2128
meta.superMeta = orig;
- 2128
return ret;
};
- 104
wrapper._f = f;
- 104
return wrapper;
} else {
- 214
f._f = f;
- 214
return f;
}
}
/**
* @ignore
*/
- 1
function defineMixinProps(child, proto) {
- 34
var operations = proto.setters || {};
- 34
for (var i in operations) {
- 15
if (!child.__lookupSetter__(i)) { //make sure that the setter isnt already there
- 15
child.__defineSetter__(i, operations[i]);
}
}
- 34
operations = proto.getters || {};
- 34
for (i in operations) {
- 15
if (!child.__lookupGetter__(i)) {
//define the getter if the child does not already have it
- 15
child.__defineGetter__(i, operations[i]);
}
}
- 34
for (var j in proto) {
- 103
if (j != "getters" && j != "setters") {
- 83
var p = proto[j];
- 83
if ("function" === typeof p) {
- 78
if (!child.hasOwnProperty(j)) {
- 10
child[j] = functionWrapper(defaultFunction, j);
}
} else {
- 5
child[j] = p;
}
}
}
}
/**
* @ignore
*/
- 1
function mixin() {
- 7
var args = Array.prototype.slice.call(arguments), l = args.length;
- 7
var child = this.prototype, childMeta = child.__meta, thisMeta = this.__meta, bases = child.__meta.bases, staticBases = bases.slice(),
staticSupers = thisMeta.supers || [], supers = childMeta.supers || [];
- 7
for (var i = 0; i < l; i++) {
- 17
var m = args[i], mProto = m.prototype;
- 17
var protoMeta = mProto.__meta, meta = m.__meta;
- 17
if (!protoMeta) {
- 0
protoMeta = {proto: mProto || {}};
- 0
Object.defineProperty(mProto, "__meta", {
enumerable: false,
value: protoMeta
});
}
- 17
if (!meta) {
- 0
meta = {proto: m["__proto__"] || {}};
- 0
Object.defineProperty(m, "__meta", {
enumerable: false,
value: protoMeta
});
}
- 17
defineMixinProps(child, protoMeta.proto || {});
- 17
defineMixinProps(this, meta.proto || {});
//copy the bases for static,
- 17
mixinSupers(m.prototype, supers, bases);
- 17
mixinSupers(m, staticSupers, staticBases);
}
- 7
return this;
}
/**
* @ignore
*/
- 1
function mixinSupers(sup, arr, bases) {
- 386
var meta = sup.__meta;
- 386
if (!meta) {
- 0
meta = {};
- 0
Object.defineProperty(sup, "__meta", {
enumerable: false,
value: meta
});
}
- 386
var unique = sup.__meta.unique;
- 386
!unique && (meta.unique = "define" + ++classCounter);
//check it we already have this super mixed into our prototype chain
//if true then we have already looped their supers!
- 386
if (bases.indexOf(unique) == -1) {
//add their id to our bases
- 234
bases.push(unique);
- 234
var supers = sup.__meta.supers || [], i = supers.length - 1 || 0;
- 234
while (i >= 0) {
- 258
mixinSupers(supers[i--], arr, bases);
}
- 234
arr.unshift(sup);
}
}
/**
* @ignore
*/
- 1
function defineProps(child, proto) {
- 92
var operations = proto.setters;
- 92
if (operations) {
- 8
for (var i in operations) {
- 13
child.__defineSetter__(i, operations[i]);
}
}
- 92
operations = proto.getters || {};
- 92
if (operations) {
- 92
for (i in operations) {
- 47
child.__defineGetter__(i, operations[i]);
}
}
- 92
for (i in proto) {
- 359
if (i != "getters" && i != "setters") {
- 338
var f = proto[i];
- 338
if ("function" === typeof f) {
- 305
var meta = f.__meta || {};
- 305
if (!meta.isConstructor) {
- 304
child[i] = functionWrapper(f, i);
} else {
- 1
child[i] = f;
}
} else {
- 33
child[i] = f;
}
}
}
}
- 1
function _export(obj, name) {
- 11
if (obj && name) {
- 2
obj[name] = this;
} else {
- 9
obj.exports = obj = this;
}
- 11
return this;
}
- 1
function extend(proto) {
- 7
return define(this, proto);
}
/**
* @ignore
*/
- 1
function __define(child, sup, proto) {
- 48
var childProto = child.prototype, supers = [];
- 48
var unique = "define" + ++classCounter, bases = [], staticBases = [];
- 48
var instanceSupers = [], staticSupers = [];
- 48
var meta = {
supers: instanceSupers,
unique: unique,
bases: bases,
superMeta: {
f: null,
pos: 0,
name: null
}
};
- 48
Object.defineProperty(childProto, "__meta", {
enumerable: false,
value: meta
});
- 48
var childMeta = {
supers: staticSupers,
unique: unique,
bases: staticBases,
isConstructor: true,
superMeta: {
f: null,
pos: 0,
name: null
}
};
- 48
Object.defineProperty(child, "__meta", {
enumerable: false,
value: childMeta
});
- 48
if ((isHash(sup) && !proto)) {
- 2
proto = sup;
- 2
sup = Base;
- 46
} else if ((!sup && isHash(proto))) {
- 14
sup = Base;
}
- 48
if ("function" === typeof sup || isArray(sup)) {
- 47
supers = isArray(sup) ? sup : [sup];
- 47
sup = supers.shift();
- 47
child.__proto__ = sup;
- 47
childProto.__proto__ = sup.prototype;
- 47
mixinSupers(sup.prototype, instanceSupers, bases),
mixinSupers(sup, staticSupers, staticBases);
}
- 48
if (proto) {
- 46
var instance = meta.proto = proto.instance || {};
- 46
!instance.hasOwnProperty("constructor") && (instance.constructor = defaultFunction);
- 46
var stat = childMeta.proto = proto.static || {};
- 46
stat.init = stat.init || defaultFunction;
- 46
defineProps(childProto, instance, false);
- 46
defineProps(child, stat, true);
} else {
- 2
meta.proto = {};
- 2
childMeta.proto = {};
- 2
child.init = functionWrapper(defaultFunction, "init");
- 2
childProto.constructor = functionWrapper(defaultFunction, "constructor");
}
- 48
if (supers.length) {
- 7
invoke(mixin, supers, child);
}
- 48
Object.defineProperty(childProto, "_super", {
enumerable: false,
value: callSuper
});
- 48
Object.defineProperty(child, "_super", {
enumerable: false,
value: callSuper
});
- 48
Object.defineProperty(child, "_getSuper", {
enumerable: false,
value: getSuper
});
- 48
Object.defineProperty(childProto, "_getSuper", {
enumerable: false,
value: getSuper
});
- 48
Object.defineProperty(childProto, "_static", {
enumerable: false,
value: child
});
}
- 1
function define(sup, proto) {
- 45
function defineConstructor() {
- 2876
invoke(this.constructor, arguments, this);
- 2875
sup = proto = null;
}
- 45
__define(defineConstructor, sup, proto);
- 45
return defineConstructor.init() || defineConstructor;
}
- 1
function singleton(sup, proto) {
- 3
var retInstance;
- 3
function singletonConstructor() {
- 6
if (!retInstance) {
- 2
invoke(this.constructor, arguments, this);
- 2
retInstance = this;
}
- 6
return retInstance;
}
- 3
__define(singletonConstructor, sup, proto);
- 3
return singletonConstructor.init() || singletonConstructor;
}
- 1
Base = define({
instance: {},
"static": {
mixin: mixin,
extend: extend,
as: _export
}
});
/**
* Defines a new class to be used
*
* <p>
* Class methods
* <ul>
* <li>as(module | object, name): exports the object to module or the object with the name</li>
* <li>mixin(mixin) : mixes in an object</li>
* </ul>
* </br>
* Instance methods
* <ul>
* <li>_super(argumnents, [?newargs]): calls the super of the current method</li>
* </ul>
*
* </br>
* Instance properties
* <ul>
* <li>_static: use to reference class properties and methods</li>
* </ul>
*
* </p>
*
*
* @example
* //Class without a super class
* var Mammal = comb.define(null, {
* instance : {
*
* constructor: function(options) {
* options = options || {};
* this._super(arguments);
* this._type = options.type || "mammal";
* },
*
* speak : function() {
* return "A mammal of type " + this._type + " sounds like";
* },
*
* //Define your getters
* getters : {
* type : function() {
* return this._type;
* }
* },
*
* //Define your setters
* setters : {
* type : function(t) {
* this._type = t;
* }
* }
* },
*
* //Define your static methods
* static : {
* soundOff : function() {
* return "Im a mammal!!";
* }
* }
* });
*
* //Show singular inheritance
*var Wolf = comb.define(Mammal, {
* instance: {
* constructor: function(options) {
* options = options || {};
* //You can call your super constructor, or you may not
* //call it to prevent the super initializing parameters
* this._super(arguments);
* this._sound = "growl";
* this._color = options.color || "grey";
* },
*
* speak : function() {
* //override my super classes speak
* //Should return "A mammal of type mammal sounds like a growl"
* return this._super(arguments) + " a " + this._sound;
* },
*
* //add new getters for sound and color
* getters : {
*
* color : function() {
* return this._color;
* },
*
* sound : function() {
* return this._sound;
* }
* },
*
* setters : {
*
* //NOTE color is read only except on initialization
*
* sound : function(s) {
* this._sound = s;
* }
* }
*
* },
*
* static : {
* //override my satic soundOff
* soundOff : function() {
* //You can even call super in your statics!!!
* //should return "I'm a mammal!! that growls"
* return this._super(arguments) + " that growls";
* }
* }
*});
*
*
* //Typical hierarchical inheritance
* // Mammal->Wolf->Dog
* var Dog = comb.define(Wolf, {
* instance: {
* constructor: function(options) {
* options = options || {};
* this._super(arguments);
* //override Wolfs initialization of sound to woof.
* this._sound = "woof";
*
* },
*
* speak : function() {
* //Should return "A mammal of type mammal sounds like a growl thats domesticated"
* return this._super(arguments) + " thats domesticated";
* }
* },
*
* static : {
* soundOff : function() {
* //should return "I'm a mammal!! that growls but now barks"
* return this._super(arguments) + " but now barks";
* }
* }
*});
*
*
*
* dog instanceof Wolf => true
* dog instanceof Mammal => true
* dog.speak() => "A mammal of type mammal sounds like a woof thats domesticated"
* dog.type => "mammal"
* dog.color => "gold"
* dog.sound => "woof"
* Dog.soundOff() => "Im a mammal!! that growls but now barks"
*
* // Mammal->Wolf->Dog->Breed
*var Breed = comb.define(Dog, {
* instance: {
*
* //initialize outside of constructor
* _pitch : "high",
*
* constructor: function(options) {
* options = options || {};
* this._super(arguments);
* this.breed = options.breed || "lab";
* },
*
* speak : function() {
* //Should return "A mammal of type mammal sounds like a
* //growl thats domesticated with a high pitch!"
* return this._super(arguments) + " with a " + this._pitch + " pitch!";
* },
*
* getters : {
* pitch : function() {
* return this._pitch;
* }
* }
* },
*
* static : {
* soundOff : function() {
* //should return "I'M A MAMMAL!! THAT GROWLS BUT NOW BARKS!"
* return this._super(arguments).toUpperCase() + "!";
* }
* }
* });
*
*
* var breed = new Breed({color : "gold", type : "lab"}),
*
*
*
* breed instanceof Dog => true
* breed instanceof Wolf => true
* breed instanceof Mammal => true
* breed.speak() => "A mammal of type lab sounds like a woof "
* + "thats domesticated with a high pitch!"
* breed.type => "lab"
* breed.color => "gold"
* breed.sound => "woof"
* breed.soundOff() => "IM A MAMMAL!! THAT GROWLS BUT NOW BARKS!"
*
*
* //Example of multiple inheritance
* //NOTE proto is optional
*
* //Mammal is super class
* //Wolf Dog and Breed inject functionality into the prototype
* var Lab = comb.define([Mammal, Wolf, Dog, Breed]);
*
* var lab = new Lab();
* lab instanceof Wolf => false
* lab instanceof Dog => false
* lab instanceof Breed => false
* lab instanceof Mammal => true
* lab.speak() => "A mammal of type mammal sounds like a"
* + " woof thats domesticated with a high pitch!"
* Lab.soundOff() => "IM A MAMMAL!! THAT GROWLS BUT NOW BARKS!"
*
* @name define
* @memberOf comb
*
* @param {Array|Class} super the supers of this class
* @param {Object} [proto] the object used to define this class
* @param {Object} [proto.instance] the instance methods of the class
* @param {Object} [proto.instance.getters] the getters for the class
* @param {Object} [proto.instance.setters] the setters for the class
* @param {Object} [proto.static] the Class level methods of this class
* @param {Object} [proto.static.getters] static getters for the object
* @param {Object} [proto.static.setters] static setters for the object
*
* @returns {Object} the constructor of the class to be used with new keyword
*/
- 1
exports.define = define;
/**
* Defines a singleton instance of a Class. See {@link define}
* @example
* var MyLab = comb.singleton([Mammal, Wolf, Dog, Breed]);
* var myLab1 = new MyLab();
* myLab1.type = "collie"
* var myLab2 = new MyLab();
* myLab1 === myLab2 => true
* myLab1.type => "collie"
* myLab2.type => "collie"
*
*
* @name singleton
* @memberOf comb
*/
- 1
exports.singleton = singleton;
base/string.js
|
Coverage98.06
SLOC546
LOC155
Missed3
|
- 1
var comb = exports, date,
misc = require("./misc"),
object = require("./object"),
round = require("./number").number.round,
isHash = object.isHash,
pSlice = Array.prototype.slice,
toStr = Object.prototype.toString,
abs = Math.abs;
- 1
function getDate() {
- 70
return (date || (date = require("./date")));
}
/**
* Truncates a string to the specified length.
* @example
*
* //from the beginning
* comb.string.truncate("abcdefg", 3) => "abc";
* //from the end
* comb.string.truncate("abcdefg", 3,true) => "efg"
* //omit the length
* comb.string.truncate("abcdefg") => "abcdefg"
*
* @param {String} string the string to truncate
* @param {Number} [length = -1] the max length of the string, if the string is
* shorter than the length then the string is returned.
* @param {Boolean} [end=false] truncate starting at the end of the string
*
* @return {String} the truncated string.
* @memberOf comb.string
* @static
*/
- 1
function truncate(string, length, end) {
- 46
var ret = string;
- 46
if (comb.isString(ret)) {
- 44
if (string.length > length) {
- 27
if (end) {
- 8
var l = string.length;
- 8
ret = string.substring(l - length, l);
} else {
- 19
ret = string.substring(0, length);
}
}
} else {
- 2
ret = truncate("" + ret, length);
}
- 46
return ret;
}
/**
* Escapes an HTML string by replacing <>&" characters.
*
* @example
* comb.string.escapeHtml('<script>alert("test")</script>'); // <script>alert("test")</script>
*
* @param {String} str The string to escape.
* @memberOf comb.string
* @static
*/
- 1
function escapeHtml(str) {
- 1
return String(str)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
/**
* Pads a string
*
* @example
*
* comb.string.pad("STR", 5, " ", true) => "STR "
* comb.string.pad("STR", 5, "$") => "$$STR"
*
* @param {String} string the string to pad
* @param {Number} length the length of the string when padded
* @param {String} [ch= " "] character to pad the string with
* @param {Boolean} [end=false] if true then the padding is added to the end
*
* @returns {String} the padded string
* @memberOf comb.string
* @static
*/
- 1
function pad(string, length, ch, end) {
- 376
string = "" + string; //check for numbers
- 376
ch = ch || " ";
- 376
var strLen = string.length;
- 376
while (strLen < length) {
- 306
if (end) {
- 158
string += ch;
} else {
- 148
string = ch + string;
}
- 306
strLen++;
}
- 376
return string;
}
/**
* Tests if something is a string.
*
* @example
*
* comb.isString("true") //true
* comb.isString(true) //false
*
* @param obj the thing to test
* @return {Boolean} returns true if the argument is a string.
* @static
* @memberOf comb
*/
- 1
function isString(obj) {
- 36117
return toStr.call(obj) === '[object String]';
}
- 1
comb.isString = isString;
- 1
var FORMAT_REGEX = /%((?:-?[\+| ]?.?\d*(?:\.\d+)*)?|(?:\[[^\[|\]]*\]))?([sjdDZ])/g;
- 1
var INTERP_REGEX = /{(?:\[([^\[|\]]*)\])?(\w+)}/g;
- 1
var STR_FORMAT = /(-?)(\+?)([A-Z|a-z|\W]?)([1-9][0-9]*)?$/;
- 1
var NUMBER_FORMAT = /(-?)([\+| ]?)([^\.1-9])?([1-9][0-9]*)?(\.[1-9][0-9]*)?$/;
- 1
var OBJECT_FORMAT = /([1-9][0-9]*)$/g;
- 1
function formatString(string, format) {
- 64
var match = format.match(STR_FORMAT), ret = string;
- 64
if (match) {
- 64
var isLeftJustified = match[1], padChar = match[3], width = match[4];
- 64
if (width) {
- 64
width = parseInt(width, 10);
- 64
if (ret.length < width) {
- 35
ret = pad(ret, width, padChar, isLeftJustified);
} else {
- 29
ret = truncate(ret, width);
}
}
}
- 64
return ret;
}
- 1
function formatNumber(number, format) {
- 37
var ret = "";
- 37
if (typeof number === "number") {
- 35
ret = "" + abs(number);
- 35
var match = format.match(NUMBER_FORMAT);
- 35
if (match) {
- 35
var isLeftJustified = match[1], signed = (number < 0 ? '-' : match[2]), padChar = match[3] || ' ', width = match[4], precision = match[5];
- 35
if (precision) {
- 12
precision = parseInt(precision.replace(/^\./, ""), 10);
- 12
ret = round(abs(number), precision) + "";
//check and ensure we have padding zeros
- 12
var split = ret.split(".");
- 12
if (split.length === 1) {
- 12
ret = [split[0], pad("0", precision, "0", true)].join(".");
- 0
} else if (split[1].length < precision) {
- 0
ret = [split[0], pad(split[1], precision, "0", true)].join(".");
}
}
- 35
if (padChar === ' ') {
- 27
ret = signed + ret;
- 27
signed = false;
}
- 35
if (width) {
- 26
width = parseInt(width, 10);
- 26
if (signed) {
- 6
width--;
}
- 26
if (ret.length < width) {
- 23
ret = pad(ret, width, padChar || " ", isLeftJustified);
} else {
- 3
ret = truncate(ret, width);
}
}
- 35
if (signed) {
- 6
ret = signed + ret;
}
}
} else {
- 2
throw new Error("comb.string.format : when using %d the parameter must be a number!");
}
- 35
return ret;
}
- 1
function formatObject(object, format) {
- 8
var ret, match = format.match(OBJECT_FORMAT), spacing = 0;
- 8
if (match) {
- 8
spacing = parseInt(match[0], 10);
- 8
if (isNaN(spacing)) {
- 0
spacing = 0;
}
}
- 8
try {
- 8
ret = JSON.stringify(object, null, spacing);
} catch (e) {
- 2
throw new Error("comb.string.format : Unable to parse json from ", object);
}
- 6
return ret;
}
/**
* Formats a string with the specified format
*
* Format `String`s
*
* ```
* comb.string.format("%s", "Hello"); // "Hello"
* comb.string.format("%10s", "Hello"); // " Hello"
* comb.string.format("%-10s", "Hello"); // ""Hello ""
* comb.string.format('%.10s', "Hello"); //".....Hello"
* comb.string.format('%-!10s', "Hello"); //"Hello!!!!!"
* comb.string.format("%-.10s%s!", "Hello", "World"); //"Hello.....World!"
* ```
*
* Formatting Numbers
*
* ```
* comb.string.format('%d', 10); //"10"
*
* //setting precision
* comb.string.format('%.2d', 10); //"10.00"
*
* //specifying width
* comb.string.format('%5d', 10); //" 10"
*
* //Signed
* comb.string.format('%+d', 10); //"+10"
* comb.string.format('%+d', -10); //"-10"
*
* comb.string.format('% d', 10); //" 10"
* comb.string.format('% d', -10); //"-10"
*
* //width
* comb.string.format('%5d', 10); //" 10"
*
* //width and precision
* comb.string.format('%6.2d', 10); //" 10.00"
*
* //signed, width and precision
* comb.string.format('%+ 7.2d', 10); //" +10.00"
* comb.string.format('%+ 7.2d', -10); //" -10.00"
* comb.string.format('%+07.2d', 10); //"+010.00"
* comb.string.format('%+07.2d', -10); //"-010.00"
* comb.string.format('% 7.2d', 10); //" 10.00"
* comb.string.format('% 7.2d', -10); //" -10.00"
* comb.string.format('% 7.2d', 10); //" 10.00"
* comb.string.format('% 7.2d', -10); //" -10.00"
*
* //use a 0 as padding
* comb.string.format('%010d', 10); //"0000000010"
*
* //use an ! as padding
* comb.string.format('%!10d', 10); //"!!!!!!!!10"
*
* //left justify signed ! as padding and a width of 10
* comb.string.format('%-+!10d', 10); //"+10!!!!!!!"
*
* ```
*
* Formatting dates
*
* ```
* comb.string.format("%[h:mm a]D", new Date(2014, 05, 04, 7,6,1)); // 7:06 AM - local -
* comb.string.format("%[h:mm a]Z", new Date(2014, 05, 04, 7,6,1)); //12:06 PM - UTC
* comb.string.format("%[yyyy-MM-dd]D", new Date(2014, 05, 04, 7,6,1)); // 2014-06-04 - local
* comb.string.format("%[yyyy-MM-dd]Z", new Date(2014, 05, 04, 7,6,1)); // 2014-06-04 - UTC
* ```
*
* Formatting Objects
*
* ```
* //When using object formats they must be in an array otherwise
* //format will try to interpolate the properties into the string.
* comb.string.format("%j", [{a : "b"}]) // '{"a":"b"}'
*
* //Specifying spacing
* comb.string.format("%4j", [{a : "b"}]) // '{\n "a": "b"\n}'
*
* ```
*
* String interpolation
*
* ```
* comb.string.format("{hello}, {world}", {hello : "Hello", world : "World"); //"Hello, World";
* comb.string.format("{[.2]min}...{[.2]max}", {min: 1, max: 10}); //"1.00...10.00"
* ```
*
* @param {String} str the string to format, if you want to use a spacing character as padding (other than \\s) then put your format in brackets.
* <ol>
* <li>String Formats %[options]s</li>
* <ul>
* <li>- : left justified</li>
* <li>Char : padding character <b>Excludes d,j,s</b></li>
* <li>Number : width</li>
* </ul>
* </li>
* <li>Number Formats %[options]d</li>
* <ul>
* <li>`-` : left justified</li>
* <li>`+` or `<space>` : signed number if space is used the number will use a extra `<space>` instead of a `+`</li>
* <li>`<Char>` : padding character <b>Excludes d,j,s</b></li>
* <li>`Number` : width</li>
* <li>`.Number`: specify the precision of the number</li>
* </ul>
* </li>
* <li>Object Formats %[options]j</li>
* <ul>
* <li>Number : spacing for object properties.</li>
* </ul>
* </li>
* </ol>
*
*
* @param {Object|Array|Arguments...} obj the parameters to replace in the string
* if an array is passed then the array is used sequentially
* if an object is passed then the object keys are used
* if a variable number of args are passed then they are used like an array
*
* @returns {String} the formatted string
* @memberOf comb.string
* @static
*/
- 1
function format(str, obj) {
- 180
if (obj instanceof Array) {
- 82
var i = 0, len = obj.length;
//find the matches
- 82
return str.replace(FORMAT_REGEX, function (m, format, type) {
- 134
var replacer, ret;
- 134
if (i < len) {
- 132
replacer = obj[i++];
} else {
//we are out of things to replace with so
//just return the match?
- 2
return m;
}
- 132
if (m === "%s" || m === "%d" || m === "%D") {
//fast path!
- 61
ret = replacer + "";
- 71
} else if (m === "%Z") {
- 2
ret = replacer.toUTCString();
- 69
} else if (m === "%j") {
- 4
try {
- 4
ret = JSON.stringify(replacer);
} catch (e) {
- 2
throw new Error("comb.string.format : Unable to parse json from ", replacer);
}
} else {
- 65
format = format.replace(/^\[|\]$/g, "");
- 65
switch (type) {
case "s":
- 8
ret = formatString(replacer, format);
- 8
break;
case "d":
- 35
ret = formatNumber(replacer, format);
- 33
break;
case "j":
- 6
ret = formatObject(replacer, format);
- 4
break;
case "D":
- 8
ret = getDate().date.format(replacer, format);
- 8
break;
case "Z":
- 8
ret = getDate().date.format(replacer, format, true);
- 8
break;
}
}
- 126
return ret;
});
- 98
} else if (isHash(obj)) {
- 36
return str.replace(INTERP_REGEX, function (m, format, value) {
- 142
value = obj[value];
- 142
if (!misc.isUndefined(value)) {
- 140
if (format) {
- 86
if (comb.isString(value)) {
- 56
return formatString(value, format);
- 30
} else if (typeof value === "number") {
- 2
return formatNumber(value, format);
- 28
} else if (getDate().isDate(value)) {
- 26
return getDate().date.format(value, format);
- 2
} else if (typeof value === "object") {
- 2
return formatObject(value, format);
}
} else {
- 54
return "" + value;
}
}
- 2
return m;
});
} else {
- 62
var args = pSlice.call(arguments).slice(1);
- 62
return format(str, args);
}
}
- 1
var styles = {
//styles
bold: 1,
bright: 1,
italic: 3,
underline: 4,
blink: 5,
inverse: 7,
crossedOut: 9,
red: 31,
green: 32,
yellow: 33,
blue: 34,
magenta: 35,
cyan: 36,
white: 37,
redBackground: 41,
greenBackground: 42,
yellowBackground: 43,
blueBackground: 44,
magentaBackground: 45,
cyanBackground: 46,
whiteBackground: 47,
encircled: 52,
overlined: 53,
grey: 90,
black: 90
};
/**
* Styles a string according to the specified styles.
*
* @example
* //style a string red
* comb.string.style('myStr', 'red');
* //style a string red and bold
* comb.string.style('myStr', ['red', bold]);
*
* @param {String} str The string to style.
* @param {String|Array} styles the style or styles to apply to a string.
* options include :
* <ul>
* <li>bold</li>
* <li>bright</li>
* <li>italic</li>
* <li>underline</li>
* <li>inverse</li>
* <li>crossedOut</li>
* <li>blink</li>
* <li>red</li>
* <li>green</li>
* <li>yellow</li>
* <li>blue</li>
* <li>magenta</li>
* <li>cyan</li>
* <li>white</li>
* <li>redBackground</li>
* <li>greenBackground</li>
* <li>yellowBackground</li>
* <li>blueBackground</li>
* <li>magentaBackground</li>
* <li>cyanBackground</li>
* <li>whiteBackground</li>
* <li>grey</li>
* <li>black</li>
*
* </ul>
* @memberOf comb.string
* @static
*/
- 1
function style(str, options) {
- 89
var ret = str;
- 89
if (options) {
- 89
if (ret instanceof Array) {
- 2
ret = ret.map(function (s) {
- 6
return style(s, options);
});
- 87
} else if (options instanceof Array) {
- 8
options.forEach(function (option) {
- 24
ret = style(ret, option);
});
- 79
} else if (options in styles) {
- 79
ret = '\x1B[' + styles[options] + 'm' + str + '\x1B[0m';
}
}
- 89
return ret;
}
/**
* Returns a string duplicated n times;
*
* @example
*
* comb.string.multiply("HELLO", 5) => "HELLOHELLOHELLOHELLOHELLO"
*
* @memberOf comb.string
* @static
*/
- 1
function multiply(str, times) {
- 156
var ret = [];
- 156
if (times) {
- 150
for (var i = 0; i < times; i++) {
- 568
ret.push(str);
}
}
- 156
return ret.join("");
}
/**
* Converts a string to an array
*
* @example
*
* comb.string.toArray("a|b|c|d", "|") => ["a","b","c","d"]
* comb.string.toArray("a", "|") => ["a"]
* comb.string.toArray("", "|") => []
*
* @param {String} str the string to parse
* @param {String} delimeter the delimeter to use
* @memberOf comb.string
* @static
*/
- 1
function toArray(testStr, delim) {
- 6
var ret = [];
- 6
if (testStr) {
- 4
if (testStr.indexOf(delim) > 0) {
- 2
ret = testStr.replace(/\s+/g, "").split(delim);
} else {
- 2
ret = [testStr];
}
}
- 6
return ret;
}
/**@namespace String utilities*/
- 1
comb.string = {
pad: pad,
truncate: truncate,
format: format,
toArray: toArray,
multiply: multiply,
style: style,
escapeHtml: escapeHtml
};
async.js
|
Coverage98.88
SLOC1245
LOC179
Missed2
|
/**
* @ignoreCode
* @name async
* @memberOf comb
* @namespace utilities for working with promises.
*/
- 1
var promise = require("./promise.js"),
when = promise.when,
serial = promise.serial,
PromiseList = promise.PromiseList,
base = require("./base"),
merge = base.merge,
isDefined = base.isDefined,
isNumber = base.isNumber,
isString = base.isString,
argsToArray = base.argsToArray,
array = base.array,
isArray = base.isArray,
Promise = promise.Promise,
isFunction = base.isFunction,
sum = array.sum,
avg = array.avg,
sort = array.sort,
min = array.min,
max = array.max,
map = array.map,
forEach = array.forEach,
difference = array.difference,
removeDuplicates = array.removeDuplicates,
unique = array.unique,
rotate = array.rotate,
permutations = array.permutations,
zip = array.zip,
transpose = array.transpose,
valuesAt = array.valuesAt,
union = array.union,
intersect = array.intersect,
powerSet = array.powerSet,
cartesian = array.cartesian,
compact = array.compact,
multiply = array.multiply,
flatten = array.flatten,
invoke = array.invoke;
- 1
var nextTick;
- 1
if (typeof setImmediate === "function") {
// In IE10, or use https://github.com/NobleJS/setImmediate
- 1
nextTick = setImmediate;
} else {
- 0
nextTick = function (cb) {
- 0
process.nextTick(cb);
};
}
- 1
function _loopResults(cb, scope, results, index, offset, limit) {
- 79
return function () {
- 79
return when(results.slice(offset, limit + offset).map(function (r, i) {
- 574
var ret = new Promise();
- 574
nextTick(function () {
- 574
try {
- 574
when(cb.apply(scope || results, [r, i + offset, results])).then(function () {
- 564
ret.callback.apply(ret, arguments);
}, function () {
- 5
ret.errback.apply(ret, arguments);
});
} catch (e) {
- 5
ret.errback(e);
}
});
- 574
ret.both(function () {
- 574
cb = scope = results = index = offset = limit = null;
});
- 574
return ret;
}));
};
}
- 1
function asyncLoop(promise, cb, scope, limit) {
- 52
if (isNumber(scope)) {
- 13
limit = scope;
- 13
scope = null;
}
- 52
return when(promise).chain(function (results) {
- 52
var loopResults = (isArray(results) ? results : [results]);
- 52
limit = limit || loopResults.length;
- 52
var list = [];
- 52
for (var offset = 0, i = 0, l = loopResults.length; offset < l; offset += limit, i++) {
- 79
list.push(_loopResults(cb, scope, loopResults, i, offset, limit));
}
- 52
var ret = new Promise();
- 52
serial(list).then(function (loopResults) {
- 42
ret.callback({loopResults: flatten(loopResults) || [], arr: results});
// loopResults = null;
// results = null;
}, function (error) {
- 10
error = compact(error);
- 10
ret.errback(error.length === 1 ? error[0] : error);
// loopResults = null;
// results = null;
});
- 52
return ret;
});
}
- 1
function normalizeResult(result) {
- 92
return isArray(result) ? result : isDefined(result) ? [result] : result;
}
/**
* Loops through the results of an promise. The promise can return an array or just a single item.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.forEach(asyncArr(), function(){
* //do something with it
* }).then(function(arr){
* console.log(arr); //[1,2,3,4,5];
* });
*
* ```
*
* You may also return a promise from the iterator block.
*
* ```
* var myNewArr = [];
*
* comb.async.forEach(asyncArr(), function(item, index){
* var ret = new comb.Promise();
* process.nextTick(function(){
* myNewArr.push([item, index]);
* ret.callback();
* });
* return ret.promise();
* }).then(function(){
* console.log(myNewArr) //[[1,0], [2,1], [3,2], [4,3], [5,4]]
* });
* ```
*
*
* @param {comb.Promise|Array} promise the promise or array to loop through
* @param {Function} iterator a function to invoke for each item
* @param [scope] optional scope to execute the function in.
* @return {comb.Promise} a promise that is resolved with the original array.
* @static
* @memberof comb.async
* @name forEach
*/
- 1
function asyncForEach(promise, iterator, scope, limit) {
- 11
return asyncArray(asyncLoop(promise, iterator, scope, limit).chain(function (results) {
- 9
return results.arr;
}));
}
/**
* Loops through the results of an promise resolving with the return value of the iterator function.
* The promise can return an array or just a single item.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.map(asyncArr(), function(item){
* return item * 2;
* }).then(function(arr){
* console.log(arr); //[2,4,6,8,10];
* });
*
* ```
*
* You may also return a promise from the iterator block.
*
* ```
* comb.async.map(asyncArr(), function(item, index){
* var ret = new comb.Promise();
* process.nextTick(function(){
* ret.callback(item * 2);
* });
* return ret.promise();
* }).then(function(){
* console.log(myNewArr) //[2,4,6,8,10];
* });
* ```
*
*
* @param {comb.Promise|Array} promise the promise or array to loop through
* @param {Function} iterator a function to invoke for each item
* @param [scope] optional scope to execute the function in.
* @return {comb.Promise} a promise that is resolved with the mapped array.
* @static
* @memberof comb.async
* @name map
*/
- 1
function asyncMap(promise, iterator, scope, limit) {
- 15
return asyncArray(asyncLoop(promise, iterator, scope, limit).chain(function (results) {
- 13
return results.loopResults;
}));
}
/**
* Loops through the results of an promise resolving with the filtered array.
* The promise can return an array or just a single item.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.filter(asyncArr(), function(item){
* return item % 2;
* }).then(function(arr){
* console.log(arr); //[1,3,5];
* });
*
* ```
*
* You may also return a promise from the iterator block.
*
* ```
* comb.async.filter(asyncArr(), function(item, index){
* var ret = new comb.Promise();
* process.nextTick(function(){
* ret.callback(item % 2);
* });
* return ret.promise();
* }).then(function(){
* console.log(myNewArr) //[1,3,5];
* })
* ```
*
*
* @param {comb.Promise|Array} promise the promise or array to loop through
* @param {Function} iterator a function to invoke for each item
* @param [scope] optional scope to execute the function in.
* @return {comb.Promise} a promise that is resolved with the filtered array.
* @static
* @memberof comb.async
* @name filter
*/
- 1
function asyncFilter(promise, iterator, scope, limit) {
- 7
return asyncArray(asyncLoop(promise, iterator, scope, limit).chain(function (results) {
- 5
var loopResults = results.loopResults, resultArr = results.arr;
- 5
return (isArray(resultArr) ? resultArr : [resultArr]).filter(function (res, i) {
- 65
return loopResults[i];
});
}));
}
/**
* Loops through the results of an promise resolving with true if every item passed, false otherwise.
* The promise can return an array or just a single item.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.every(asyncArr(), function(item){
* return item <= 5;
* }).then(function(every){
* console.log(every); //true
* });
*
* ```
*
* You may also return a promise from the iterator block.
*
* ```
* comb.async.every(asyncArr(), function(item, index){
* var ret = new comb.Promise();
* process.nextTick(function(){
* ret.callback(item == 1);
* });
* return ret.promise();
* }).then(function(){
* console.log(myNewArr) //false;
* })
* ```
*
*
* @param {comb.Promise|Array} promise the promise or array to loop through
* @param {Function} iterator a function to invoke for each item
* @param [scope] optional scope to execute the function in.
* @return {comb.Promise} a promise that is resolved true if every item passed false otherwise.
* @static
* @memberof comb.async
* @name every
*/
- 1
function asyncEvery(promise, iterator, scope, limit) {
- 9
return asyncArray(asyncLoop(promise, iterator, scope, limit).chain(function (results) {
- 7
return results.loopResults.every(function (res) {
- 52
return !!res;
});
}));
}
/**
* Loops through the results of an promise resolving with true if some items passed, false otherwise.
* The promise can return an array or just a single item.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.some(asyncArr(), function(item){
* return item == 1;
* }).then(function(every){
* console.log(every); //true
* });
*
* ```
*
* You may also return a promise from the iterator block.
*
* ```
* comb.async.some(asyncArr(), function(item, index){
* var ret = new comb.Promise();
* process.nextTick(function(){
* ret.callback(item > 5);
* });
* return ret.promise();
* }).then(function(){
* console.log(myNewArr) //false;
* })
* ```
*
*
* @param {comb.Promise|Array} promise the promise or array to loop through
* @param {Function} iterator a function to invoke for each item
* @param [scope] optional scope to execute the function in.
* @return {comb.Promise} a promise that is resolved with true if some items passed false otherwise.
* @static
* @memberof comb.async
* @name some
*/
- 1
function asyncSome(promise, iterator, scope, limit) {
- 10
return asyncArray(asyncLoop(promise, iterator, scope, limit).chain(function (results) {
- 8
return results.loopResults.some(function (res) {
- 53
return !!res;
});
}));
}
/**
* Zips results from promises into an array.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.zip(asyncArr(), asyncArr()).then(function(zipped){
* console.log(zipped); //[[1,1],[2,2],[3,3], [4,4], [5,5]]
* });
*
* comb.async.array(asyncArr()).zip(asyncArr()).then(function(zipped){
* console.log(zipped); //[[1,1],[2,2],[3,3], [4,4], [5,5]]
* });
*
* ```
*
*
* @return {comb.Promise} an array with all the arrays zipped together.
* @static
* @memberof comb.async
* @name zip
*/
- 1
function asyncZip() {
- 1
return asyncArray(when.apply(null, argsToArray(arguments)).chain(function (result) {
- 1
return zip.apply(array, normalizeResult(result).map(function (arg) {
- 3
return isArray(arg) ? arg : [arg];
}));
}));
}
/**
* Async version of {@link comb.array.avg}.
*
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).avg().then(function(avg){
* console.log(avg); //3
* })
*
* comb.async.avg(asyncArr()).then(function(avg){
* console.log(avg); //3
* })
*
* ```
*
* @static
* @memberof comb.async
* @name avg
*/
- 1
function asyncAvg(avgPromise) {
- 5
return when(avgPromise).chain(function (result) {
- 5
return avg.call(array, normalizeResult(result));
});
}
/**
* Async version of {@link comb.array.cartesian}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).cartesian([1,2,3]).then(function(avg){
* console.log(avg); //[ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ] ]
* })
*
* comb.async.cartesian(asyncArr(), [1,2,3]).then(function(avg){
* console.log(avg); //[ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ] ]
* })
*
* ```
*
* @static
* @memberof comb.async
* @name cartesian
*/
- 1
function asyncCartesian() {
- 3
return asyncArray(when.apply(null, argsToArray(arguments)).chain(function (result) {
- 3
return cartesian.apply(array, normalizeResult(result).map(function (arg) {
- 6
return isArray(arg) ? arg : [arg];
}));
}));
}
/**
* Async version of {@link comb.array.compact}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,null,2,null,3,null,4,null,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).compact().then(function(compacted){
* console.log(compacted); //[1,2,3,4,5]
* })
*
* comb.async.compact(asyncArr()).then(function(compacted){
* console.log(compacted); //[1,2,3,4,5]
* })
*
* ```
*
* @static
* @memberof comb.async
* @name compact
*/
- 1
function asyncCompact(arr) {
- 2
return asyncArray(when(arr).chain(function (result) {
- 2
return compact.call(array, normalizeResult(result));
}));
}
/**
* Async version of {@link comb.array.difference}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).difference([3,4,5]).then(function(diff){
* console.log(diff); //[1,2]
* })
*
* comb.async.difference(asyncArr(), [3,4,5]).then(function(diff){
* console.log(diff); //[1,2]
* })
*
* ```
*
* @static
* @memberof comb.async
* @name difference
*/
- 1
function asyncDifference() {
- 5
return asyncArray(when.apply(null, argsToArray(arguments)).chain(function (result) {
- 5
return difference.apply(array, normalizeResult(result).map(function (arg) {
- 11
return isArray(arg) ? arg : [arg];
}));
}));
}
/**
* Async version of {@link comb.array.flatten}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [[1],[2],[3],[4],[5]]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).flatten().then(function(flat){
* console.log(flat); //[1,2,3,4,5]
* });
*
* comb.async.flatten(asyncArr()).then(function(flat){
* console.log(flat); //[1,2,3,4,5]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name flatten
*/
- 1
function asyncFlatten() {
- 4
return asyncArray(when.apply(null, argsToArray(arguments)).chain(function (result) {
- 4
return flatten.apply(array, normalizeResult(result).map(function (arg) {
- 12
return isArray(arg) ? arg : [arg];
}));
}));
}
/**
* Async version of {@link comb.array.intersect}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).intersect([3,4], [3]).then(function(intersection){
* console.log(intersection); //[3]
* });
*
* comb.async.intersect(asyncArr(), [3,4]).then(function(intersection){
* console.log(intersection); //[3,4]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name intersect
*/
- 1
function asyncIntersect() {
- 5
return asyncArray(when.apply(null, argsToArray(arguments)).chain(function (result) {
- 5
return intersect.apply(array, normalizeResult(result).map(function (arg) {
- 15
return isArray(arg) ? arg : [arg];
}));
}));
}
/**
* Async version of {@link comb.array.max}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).max().then(function(max){
* console.log(max); //5
* })
*
* comb.async.max(asyncArr()).then(function(max){
* console.log(max); //5
* })
*
* ```
*
* @static
* @memberof comb.async
* @name max
*/
- 1
function asyncMax() {
- 7
var args = argsToArray(arguments), last = args.pop(), cmp = null;
- 7
if (isFunction(last) || isString(last)) {
- 3
cmp = last;
} else {
- 4
args.push(last);
}
- 7
return when.apply(null, args).chain(function (result) {
- 7
return max.call(array, normalizeResult(result), cmp);
});
}
/**
* Async version of {@link comb.array.min}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).min().then(function(min){
* console.log(min) //3
* });
*
* comb.async.min(asyncArr()).then(function(min){
* console.log(min) //3
* });
*
* ```
*
* @static
* @memberof comb.async
* @name min
*/
- 1
function asyncMin() {
- 7
var args = argsToArray(arguments), last = args.pop(), cmp = null;
- 7
if (isFunction(last) || isString(last)) {
- 3
cmp = last;
} else {
- 4
args.push(last);
}
- 7
return when.apply(null, args).chain(function (result) {
- 7
return min.call(array, normalizeResult(result), cmp);
});
}
/**
* Async version of {@link comb.array.sort}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,3,2,5,4]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).sort().then(function(sorted){
* console.log(sorted); //[1,2,3,4,5]
* });
*
* comb.async.sort(asyncArr()).then(function(sorted){
* console.log(sorted); //[1,2,3,4,5]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name sort
*/
- 1
function asyncSort() {
- 8
var args = argsToArray(arguments), last = args.pop(), cmp = null;
- 8
if (isFunction(last) || isString(last)) {
- 4
cmp = last;
} else {
- 4
args.push(last);
}
- 8
return asyncArray(when.apply(null, args).chain(function (result) {
- 8
return sort.call(array, normalizeResult(result), cmp);
}));
}
/**
* Async version of {@link comb.array.multiply}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).multiply(2).then(function(mult){
* console.log(mult); //[1,2,3,4,5,1,2,3,4,5]
* });
*
* comb.async.multiply(asyncArr(),2 ).then(function(mult){
* console.log(mult); //[1,2,3,4,5,1,2,3,4,5]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name multiply
*/
- 1
function asyncMultiply() {
- 4
var args = argsToArray(arguments), last = args.pop(), times = null;
- 4
if (isNumber(last)) {
- 3
times = last;
} else {
- 1
args.push(last);
}
- 4
return asyncArray(when.apply(null, args).chain(function (result) {
- 4
return multiply.call(array, normalizeResult(result), times);
}));
}
/**
* Async version of {@link comb.array.permutations}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).permutations().then(function(permutations){
* console.log(permutations) //[ [ 1, 2, 3 ],
* // [ 1, 3, 2 ],
* // [ 2, 3, 1 ],
* // [ 2, 1, 3 ],
* // [ 3, 1, 2 ],
* // [ 3, 2, 1 ] ]
* });
*
* comb.async.permutations(asyncArr()).then(function(permutations){
* console.log(permutations) //[ [ 1, 2, 3 ],
* // [ 1, 3, 2 ],
* // [ 2, 3, 1 ],
* // [ 2, 1, 3 ],
* // [ 3, 1, 2 ],
* // [ 3, 2, 1 ] ]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name permutations
*/
- 1
function asyncPermutations() {
- 5
var args = argsToArray(arguments), last = args.pop(), times = null;
- 5
if (isNumber(last)) {
- 4
times = last;
} else {
- 1
args.push(last);
}
- 5
return asyncArray(when.apply(null, args).chain(function (result) {
- 5
return permutations.call(array, normalizeResult(result), times);
}));
}
/**
* Async version of {@link comb.array.powerSet}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).powerSet().then(function(set){
* console.log(set); //[ [], [ 1 ], [ 2 ], [ 1, 2 ], [ 3 ], [ 1, 3 ], [ 2, 3 ], [ 1, 2, 3 ] ]
* });
*
* comb.async.powerSet(asyncArr()).then(function(set){
* console.log(set); //[ [], [ 1 ], [ 2 ], [ 1, 2 ], [ 3 ], [ 1, 3 ], [ 2, 3 ], [ 1, 2, 3 ] ]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name powerSet
*/
- 1
function asyncPowerSet(arr) {
- 3
return asyncArray(when(arr).chain(function (result) {
- 3
return powerSet.call(array, normalizeResult(result));
}));
}
/**
* Async version of {@link comb.array.removeDuplicates}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,2,3,3,3,4,4,4]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).removeDuplicates().then(function(unique){
* console.log(unique); // [1, 2, 3, 4]
* });
*
* comb.async.removeDuplicates(asyncArray()).then(function(unique){
* console.log(unique); // [1, 2, 3, 4]
* });
* ```
*
* @static
* @memberof comb.async
* @name removeDuplicates
*/
- 1
function asyncRemoveDuplicates(arr) {
- 4
return asyncArray(when(arr).chain(function (result) {
- 4
return removeDuplicates.call(array, normalizeResult(result));
}));
}
/**
* Async version of {@link comb.array.rotate}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).rotate(2).then(function(rotated){
* console.log(rotated); // [ 3, 4, 5, 1, 2 ]
* });
*
* comb.async.rotate(asyncArr(), 2).then(function(rotated){
* console.log(rotated); // [ 3, 4, 5, 1, 2 ]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name rotate
*/
- 1
function asyncRotate() {
- 8
var args = argsToArray(arguments), last = args.pop(), times = null;
- 8
if (isNumber(last)) {
- 7
times = last;
} else {
- 1
args.push(last);
}
- 8
return asyncArray(when.apply(null, args).chain(function (result) {
- 8
return rotate.call(array, normalizeResult(result), times);
}));
}
/**
* Async version of {@link comb.array.sum}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).sum().then(function(sum){
* console.log(sum) //15
* })
*
* comb.async.sum(asyncArr()).then(function(sum){
* console.log(sum) //15
* })
*
* ```
*
* @static
* @memberof comb.async
* @name sum
*/
- 1
function asyncSum(arr) {
- 6
return when(arr).chain(function (result) {
- 6
return sum.call(array, normalizeResult(result));
});
}
/**
* Async version of {@link comb.array.transpose}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [[1, 2, 3], [4, 5, 6]]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).transpose().then(function(transposed){
* console.log(transposed); //[ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
* });
*
* comb.async.transpose(asyncArr()).then(function(transposed){
* console.log(transposed); //[ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name transpose
*/
- 1
function asyncTranspose(arr) {
- 3
return asyncArray(when(arr).chain(function (result) {
- 3
return transpose.call(array, normalizeResult(result));
}));
}
/**
* Async version of {@link comb.array.union}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).union([3],[7], [9,10]).then(function(union){
* console.log(union); //[1,2,3,4,5,7,9,10]
* });
*
* comb.async.union(asyncArr(), [3],[7], [9,10]).then(function(union){
* console.log(union); //[1,2,3,4,5,7,9,10]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name union
*/
- 1
function asyncUnion() {
- 2
return asyncArray(when.apply(null, argsToArray(arguments)).chain(function (result) {
- 2
return union.apply(array, (normalizeResult(result)).map(function (arg) {
- 7
return isArray(arg) ? arg : [arg];
}));
}));
}
/**
* Async version of {@link comb.array.unique}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,2,3,3,4,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).unique().then(function(unique){
* console.log(unique); //[1,2,3,4,5]
* });
*
* comb.async.unique(asyncArr()).then(function(unique){
* console.log(unique); //[1,2,3,4,5]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name unique
*/
- 1
function asyncUnique() {
- 2
return asyncRemoveDuplicates.apply(null, arguments);
}
/**
* Async version of {@link comb.array.valuesAt}.
*
* ```
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* comb.async.array(asyncArr()).valuesAt(2,3,4).then(function(values){
* console.log(values); //[3,4,5]
* });
*
* comb.async.valuesAt(asyncArr(), 2,3,4).then(function(values){
* console.log(values); //[3,4,5]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name valuesAt
*/
- 1
function asyncValuesAt(arrPromise) {
- 3
var args = argsToArray(arguments, 1);
- 3
return asyncArray(when(arrPromise).chain(function (result) {
- 3
return when(valuesAt.apply(array, [normalizeResult(result)].concat(args)));
}));
}
/**
* Async version of {@link comb.array.pluck}.
*
* ```
* var when = comb.when,
* array = comb.async.array;
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [
* {name:{first:when("Fred"), last:"Jones"}, age:when(50), roles:["a", "b", "c"]},
* {name:{first:"Bob", last:"Yukon"}, age:40, roles:when(["b", "c"])},
* {name:{first:"Alice", last:"Palace"}, age:when(35), roles:["c"]},
* {name:{first:when("Johnny"), last:"P."}, age:56, roles:when([])}
* ]);
* return ret.promise;
* }
*
* array(asyncArr()).pluck("name.first").then(function(values){
* console.log(values); //["Fred", "Bob", "Alice", "Johnny"]
* });
*
* pluck(asyncArr(), "age").then(function(values){
* console.log(values); //[50, 40, 35, 56]
* });
*
* ```
*
* @static
* @memberof comb.async
* @name pluck
*/
- 1
function asyncPluck(arrPromise, property) {
- 5
var args = argsToArray(arguments, 1);
- 5
return asyncArray(when(arrPromise).chain(function (result) {
- 5
var prop = property.split(".");
- 5
result = normalizeResult(result);
- 5
return asyncArray(prop).forEach(function (prop) {
- 8
var exec = prop.match(/(\w+)\(\)$/);
- 8
return asyncArray(result).map(function (item) {
- 32
return exec ? item[exec[1]]() : item[prop];
}, 1).chain(function (res) {
- 8
result = res;
});
}, 1).chain(function () {
- 5
return result;
});
}));
}
/**
*
* Async version of {@link comb.array.invoke}.
*
* ```
* function person(name, age) {
* return {
* getName:function () {
* return when(name);
* },
* getOlder:function () {
* age++;
* return when(this);
* },
* getAge:function () {
* return when(age);
* }
* };
* }
*
* var arr = [when(person("Bob", 40)), when(person("Alice", 35)), when(person("Fred", 50)), when(person("Johnny", 56))];
* console.log(comb.async.invoke(arr, "getName")); //["Bob", "Alice", "Fred", "Johnny"]
* console.log(array(arr).invoke("getOlder").pluck("getAge")) //[41, 36, 51, 57]
* ```
* @static
* @memberOf comb.async
* @name invoke
*/
- 1
function asyncInvoke(arrPromise) {
- 2
var args = argsToArray(arguments, 1);
- 2
return asyncArray(when(arrPromise).chain(function (result) {
- 2
return when(invoke.apply(array, [normalizeResult(result)].concat(args)));
}));
}
- 1
var asyncExports = (exports.async = {
array: asyncArray,
forEach: asyncForEach,
map: asyncMap,
filter: asyncFilter,
every: asyncEvery,
some: asyncSome,
zip: asyncZip,
sum: asyncSum,
avg: asyncAvg,
sort: asyncSort,
min: asyncMin,
max: asyncMax,
difference: asyncDifference,
removeDuplicates: asyncRemoveDuplicates,
unique: asyncUnique,
rotate: asyncRotate,
permutations: asyncPermutations,
transpose: asyncTranspose,
valuesAt: asyncValuesAt,
union: asyncUnion,
intersect: asyncIntersect,
powerSet: asyncPowerSet,
cartesian: asyncCartesian,
compact: asyncCompact,
multiply: asyncMultiply,
flatten: asyncFlatten,
pluck: asyncPluck,
invoke: asyncInvoke
});
- 1
var methods = ["forEach", "map", "filter", "some", "every", "zip", "sum", "avg", "sort", "min", "max", "difference", "removeDuplicates", "unique", "rotate",
"permutations", "transpose", "valuesAt", "union", "intersect", "powerSet", "cartesian", "compact",
"multiply", "flatten", "pluck", "invoke"];
/**
* Exposes array methods on a {@link comb.Promise}.
*
* The methods added are.
*
* * forEach : See {@link comb.async.forEach}.
* * map : See {@link comb.async.map}.
* * filter : See {@link comb.async.filter}.
* * some : See {@link comb.async.some}.
* * every : See {@link comb.async.every}.
* * zip : See {@link comb.async.zip}.
* * sum : See {@link comb.async.sum}.
* * avg : See {@link comb.async.avg}.
* * sort : See {@link comb.async.sort}.
* * min : See {@link comb.async.min}.
* * max : See {@link comb.async.max}.
* * difference : See {@link comb.async.difference}.
* * removeDuplicates : See {@link comb.async.removeDuplicates}.
* * unique : See {@link comb.async.unique}.
* * rotate : See {@link comb.async.rotate}.
* * permutations : See {@link comb.async.permutations}.
* * transpose : See {@link comb.async.transpose}.
* * valuesAt : See {@link comb.async.valuesAt}.
* * union : See {@link comb.async.union}.
* * intersect : See {@link comb.async.intersect}.
* * powerSet : See {@link comb.async.powerSet}.
* * cartesian : See {@link comb.async.cartesian}.
* * compact : See {@link comb.async.compact}.
* * multiply : See {@link comb.async.multiply}.
* * flatten : See {@link comb.async.flatten}.
* * pluck : See {@link comb.async.pluck}.
* * invoke : See {@link comb.async.invoke}.
*
* When using this method each of the methods are chainable so you can combine actions.
*
* ```
* var array = comb.async.array;
* function asyncArr(){
* var ret = new comb.Promise();
* process.nextTick(ret.callback.bind(ret, [1,2,3,4,5]);
* return ret.promise;
* }
*
* array(asyncArr())
* .map(function (num, i) {
* return num * (i + 1);
* }).filter(function (num) {
* return num % 2;
* }).avg().then(function(avg){
* console.log(avg); //11.666666666666666
* });
* ```
* @param {comb.Promise|[]} p the promise or array to use.
*
* @static
* @memberof comb.async
* @name array
*/
- 1
function asyncArray(p) {
- 626
var ret;
- 626
if (!p || !p.__isArrayAsync__) {
- 410
ret = merge(when(p), {
promise: function () {
- 216
return asyncArray(this);
}
});
- 410
forEach(methods, function (m) {
- 11070
var func = asyncExports[m];
- 11070
ret[m] = function () {
- 143
var args = argsToArray(arguments), mRet = new Promise();
- 143
nextTick(function () {
- 143
func.apply(null, [ret].concat(args)).then(mRet);
});
- 143
return asyncArray(mRet);
};
});
- 410
ret.__isArrayAsync__ = true;
} else {
- 216
ret = p;
}
- 626
p = null;
- 626
return ret;
}
logging/index.js
|
Coverage98.91
SLOC738
LOC184
Missed2
|
- 1
var os = require("os"),
define = require("../define.js"),
base = require("../base"),
isString = base.isString,
merge = base.merge,
isUndefinedOrNull = base.isUndefinedOrNull,
isHash = base.isHash,
isInstanceOf = base.isInstanceOf,
argsToArray = base.argsToArray,
format = base.string.format,
Level = require("./level"),
appenders = require("./appenders"),
Appender = appenders.Appender,
configurators = require("./config");
- 1
var rootTree;
- 1
var LoggerTree = define.define(null, {
instance: {
constructor: function (root) {
- 14
this.__root = root;
- 14
this.__name = root.name;
- 14
this.__level = root.level;
- 14
this.__parent = root._parent;
- 14
this.__map = {};
},
__getSubLoggers: function () {
- 6
var map = this.__map, ret = [], n;
- 6
for (var i in map) {
- 2
n = map[i];
- 2
if (n) {
- 2
ret = ret.concat(n.tree.getCurrentLoggers());
}
}
- 6
return ret;
},
__getLoggers: function () {
- 4
return [this.__root].concat(this.__getSubLoggers())
},
getCurrentLoggers: function () {
- 4
return this.__getLoggers();
},
getSubLoggers: function () {
- 2
return this.__getSubLoggers();
},
getLogger: function (name) {
- 31
var ret;
- 31
if (name) {
- 29
var parts = name.split(".");
- 29
if (parts.length) {
- 29
var category = parts.shift();
- 29
var lNode = this.__map[category];
- 29
if (!lNode) {
- 13
lNode = this.__map[category] = new Logger(category, this);
- 13
lNode.addAppenders(this.__root.appenders);
}
- 29
ret = lNode;
- 29
if (parts.length) {
//keep searching
- 10
name = parts.join(".");
- 10
ret = lNode.tree.getLogger(name);
}
}
} else {
- 2
ret = this.__root;
}
- 31
return ret;
},
getRootLogger: function () {
- 11
return this.__root;
},
isDisabled: function (level) {
},
resetConfiguration: function () {
},
/**
* level = string|Level
*/
addAppender: function (appender) {
- 63
var map = this.__map;
- 63
for (var i in map) {
- 41
map[i].addAppender(appender);
}
},
removeAppender: function (name) {
- 46
var map = this.__map;
- 46
for (var i in map) {
- 39
map[i].removeAppender(name);
}
},
setters: {
level: function (level) {
- 57
this.__level = level;
- 57
if (level && level instanceof Level) {
- 57
var map = this.__map;
- 57
for (var i in map) {
- 2
map[i].level = level;
}
}
}
},
getters: {
categories: function () {
- 2
return this.getCurrentLoggers().map(function (l) {
- 3
return l.fullName;
});
},
name: function () {
- 35
var ret = this.__name;
- 35
if (this.__parent) {
- 21
var pName = this.__parent.name;
- 21
if (pName) {
- 8
ret = pName + "." + ret;
}
}
- 35
return ret;
},
level: function () {
- 13
return this.__level;
},
additive: function () {
- 13
return this.__root.additive;
}
}
}
});
- 1
var comb = exports;
/**
* @ignore
* @namespace logging package*/
- 1
comb.logging = merge({
Level: Level
}, configurators);
/**
* @ignore
* @namespace appenders for logging*/
- 1
comb.logging.appenders = appenders;
- 1
var logging = comb.logging, hasGetGid = process.hasOwnProperty("getgid");
/**
* @class This class is the entry point for all logging actions in comb.
* <p><b>Logger should be retrieved by calling Logger.getLogger() NOT through the new keyword</b><p>
* <p>
* All loggers in comb follow a heirarchy of inheritance based on a dot notation.
* <pre class="code">
* rootLogger - ""
* / \
* "my" "myOther"
* / \
* "my.logger" "myOther.logger"
* / \
* "my.logger.Log" "myOther.logger.Log"
*
* </pre>
* In the above Tree the rootLogger is the base for all logger. my and myOther inherit from rootLogger
* my.logger inherits from my, and myOther.logger inherits from myOther. The logs do not have to be retrieved in
* order. If I set rootLogger to ERROR level and added a console appender to it the appender and level will be
* added to all logs. However if I set my to INFO level and add a fileAppender to it the level and appender will
* only be added to logs in "my" subtree. If you set my.logger to not be additive then levels, and appenders will not
* propogate down to the rest of the tree.
*
* </p>
*
* <p>For information on levels see {@link comb.logging.Level}.</p>
* <p>For information on appenders see
* <ul>
* <li>{@link comb.logging.appenders.Appender}</li>
* <li>{@link comb.logging.appenders.ConsoleAppender}</li>
* <li>{@link comb.logging.appenders.FileAppender}</li>
* <li>{@link comb.logging.appenders.JSONAppender}</li>
* <li>{@link comb.logging.appenders.RollingFileAppender}</li>
* </ul>
* </p>
* <p>For information on configurators see {@link comb.logging.BasicConfigurator} or {@link comb.logging.PropertyConfigurator}.</p>
*
* @example
*
* var logger = comb.logger;
*
* //configure you logging environement
* logger.configure();
*
* //add a file appender to all loggers
* logger.configure(logger.appender("FileAppender", {file : "/var/log/myLog.log"});
*
* //Retreiving a logger.
* var combLogger = logger("comb");
* var combCollectionLogger = logger("comb.collections");
* var treeLogger = logger("comb.collections.Tree")
* //add a JSON appender to tree logger just for fun!
* .addAppender("JSONAppender", {file : "/var/log/myTreeLogger.json"})
*
* //set my treeLogger to DEBUG Level
* treeLogger.level = "DEBUG";
*
*
* @name Logger
* @memberOf comb.logging
*
* @property {Array<comb.logging.Logger>} subLoggers all loggers this logger is the parent of.
* @property {comb.logging.Level} level the level of this Logger
* @property {Boolean} additive set to false to prevent changes to this logger from propogating down.
* @property {Boolean} isDebug true if this Loggers level is DEBUG
* @property {Boolean} isTrace true if this Loggers level is TRACE
* @property {Boolean} isInfo true if this Loggers level is INFO
* @property {Boolean} isWarn true if this Loggers level is WARN
* @property {Boolean} isError true if this Loggers level is ERROR
* @property {Boolean} isFatal true if this Loggers level is FATAL
* @property {Boolean} isOff true if this Loggers level is OFF
* @property {String} name the name of this logger this <b>does not</b> include the dot notated name
* @property {String} fullName the full path name of this Logger.
* @property {comb.logging.appenders.Appender} appenders list of appenders this logger currently contains.
* @ignoreCode
*/
- 1
var Logger = (logging.Logger = define.define(null, {
instance: {
/**@lends comb.logging.Logger.prototype*/
constructor: function (name, parent) {
- 14
this.__additive = true;
- 14
this.__name = name;
- 14
this._parent = parent;
- 14
this._tree = new LoggerTree(this);
- 14
this.fullName = this._tree.name;
- 14
if (!parent || !parent.additive) {
- 1
this.level = Level.ALL;
} else {
- 13
this.level = parent.level;
}
- 14
this.__appenders = {};
},
/**
* Log an info level message
*
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
info: function (message) {
- 17
return this.log.apply(this, [Level.INFO].concat(argsToArray(arguments)));
},
/**
* Log an debug level message
*
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
debug: function (message) {
- 14
return this.log.apply(this, [Level.DEBUG].concat(argsToArray(arguments)));
},
/**
* Log an error level message
*
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
error: function (message) {
- 14
return this.log.apply(this, [Level.ERROR].concat(argsToArray(arguments)));
},
/**
* Log an warn level message
*
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
warn: function (message) {
- 14
return this.log.apply(this, [Level.WARN].concat(argsToArray(arguments)));
},
/**
* Log an trace level message
*
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
trace: function (message) {
- 14
return this.log.apply(this, [Level.TRACE].concat(argsToArray(arguments)));
},
/**
* Log an fatal level message
*
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
fatal: function (message) {
- 14
return this.log.apply(this, [Level.FATAL].concat(argsToArray(arguments)));
},
/**
* Create a timer that can be used to log statements with a duration at the send.
*
* ```
* var timer = LOGGER.timer();
* setTimeout(function(){
* timer.info("HELLO TIMERS!!!"); //HELLO TIMERS!!! [Duration: 5000ms]
* }, 5000);
* ```
*
* @param timerFormat
* @returns {{info: *, debug: *, error: *, warn: *, trace: *, fatal: *, end: Function}}
*/
timer: function (timerFormat) {
- 6
timerFormat = timerFormat || " [Duration: %dms]";
- 6
function timerLog(level, start) {
- 42
return function (message) {
- 24
var args = argsToArray(arguments, 1);
- 24
message += timerFormat;
- 24
args.push(new Date() - start);
- 24
self.log.apply(self, [level, message].concat(args));
- 24
return ret;
};
}
- 6
var start = new Date(),
self = this,
ret = {
info: timerLog(Level.INFO, start),
debug: timerLog(Level.DEBUG, start),
error: timerLog(Level.ERROR, start),
warn: timerLog(Level.WARN, start),
trace: timerLog(Level.TRACE, start),
fatal: timerLog(Level.FATAL, start),
log: function (level) {
- 6
return timerLog(level, start).apply(this, argsToArray(arguments, 1));
},
end: function () {
- 0
start = self = null;
}
};
- 6
return ret;
},
/**
* Creates a log event to be passed to appenders
*
* @param {comb.logging.Level} level the level of the logging event
* @param {String} message the message to be logged
* @return {Object} the logging event
*/
getLogEvent: function getLogEvent(level, message) {
- 82
return {
hostname: os.hostname(),
pid: process.pid,
gid: hasGetGid ? process.getgid() : null,
processTitle: process.title,
level: level,
levelName: level.name,
message: message,
timeStamp: new Date(),
name: this.fullName
};
},
/**
* Log a message
*
* @param {comb.logging.Level} level the level the message is
* @param {String} message the message to log.
*
* @return {comb.logging.Logger} for chaining.
*/
log: function (level, message) {
- 117
level = Level.toLevel(level);
- 117
if (this.hasLevelGt(level)) {
- 81
var args = argsToArray(arguments, 1);
- 81
if (args.length > 1) {
- 30
message = format.apply(null, args);
}
- 81
if (Level.TRACE.equals(level)) {
- 13
var err = new Error;
- 13
err.name = "Trace";
- 13
err.message = message || '';
- 13
Error.captureStackTrace(err, arguments.callee);
- 13
message = err.stack;
- 68
} else if (Level.ERROR.equals(level) && isInstanceOf(message, Error)) {
- 0
message = message.stack;
}
- 81
var type = level.name.toLowerCase(), appenders = this.__appenders;
- 81
var event = this.getLogEvent(level, message);
- 81
Object.keys(appenders).forEach(function (i) {
- 81
appenders[i].append(event);
});
}
- 117
return this;
},
/**
* Add an appender to this logger. If this is additive then the appender is added to all subloggers.
*
* @example
* comb.logger("my.logger")
* .addAppender("ConsoleAppender")
* .addAppender("FileAppender", {file:'/var/log/my.log'})
* .addAppender("RollingFileAppender", {file:'/var/log/myRolling.log'})
* .addAppender("JSONAppender", {file:'/var/log/myJson.log'});
*
* @param {comb.logging.Appender|String} If the appender is an {@link comb.logging.appenders.Appender} then it is added.
* If the appender is a string then {@link comb.logging.appenders.Appender.createAppender} will be called to create it.
*
* @param {Object} [opts = null] If the first argument is a string then the opts will be used as constructor arguments for
* creating the appender.
*
* @return {comb.logging.Logger} for chaining.
*/
addAppender: function (appender, opts) {
- 82
var args = argsToArray(arguments);
- 82
if (isString(appender)) {
- 12
this.addAppender(Appender.createAppender(appender, opts));
} else {
- 70
if (!isUndefinedOrNull(appender)) {
- 70
var name = appender.name;
- 70
if (!(name in this.__appenders)) {
- 63
this.__appenders[name] = appender;
- 63
if (!appender.level) {
- 15
appender.level = this.level;
}
- 63
this._tree.addAppender(appender);
}
}
}
- 82
return this;
},
/**
* Short cut to add a list of appenders to this Logger
* @param {Array<comb.logging.Appender>} appenders
*
* @return {comb.logging.Logger} for chaining.
*/
addAppenders: function (appenders) {
- 14
appenders.forEach(this.addAppender.bind(this));
- 14
return this;
},
/**
* Removes and appender from this logger.
* @param {String} name the name of the appender
* @return {comb.logging.Logger} for chaining.
*/
removeAppender: function (name) {
- 46
if (name in this.__appenders) {
- 46
delete this.__appenders[name];
- 46
this._tree.removeAppender(name);
}
- 46
return this;
},
/**
* Removes a list of appenders from this logger.
*
* @param {String[]} appenders a list of names of appenders to remove
* @return {comb.logging.Logger} for chaining.
*/
removeAppenders: function (appenders) {
- 1
appenders.forEach(this.removeAppender, this);
- 1
return this;
},
/**
* Removes all appenders from this logger and sub loggers if this Logger is additive.
*
* @return {comb.logging.Logger} for chaining.
*/
removeAllAppenders: function () {
- 13
Object.keys(this.__appenders).forEach(this.removeAppender.bind(this));
- 13
return this;
},
/**
* Determines if an appender is attached.
*
* @param {String} name the name of the appender.
*/
isAppenderAttached: function (name) {
- 38
return (name in this.__appenders);
},
/**
* Gets an appender from this logger
*
* @param {String} name the name of the appender.
*
* @return {comb.logging.Appender|undefined} returns the appender with the specified name or
* undefined if it is not found.
*/
getAppender: function (name) {
- 8
var ret;
- 8
if (name in this.__appenders) {
- 8
ret = this.__appenders[name];
}
- 8
return ret;
},
hasLevelGt: function (level) {
- 117
var ret = level.isGreaterOrEqualToo(this.level), i, appenders, keys, l;
- 117
if (!ret) {
- 36
appenders = this.__appenders;
- 36
keys = Object.keys(appenders);
- 36
l = keys.length;
- 36
i = -1;
- 36
while (++i < l && !ret) {
- 36
ret = level.isGreaterOrEqualToo(appenders[keys[i]].level);
}
}
- 117
return ret;
},
/**
* @ignore
* */
setters: {
level: function (level) {
- 58
level = Level.toLevel(level);
- 58
if (this.__additive) {
- 57
this.__level = level;
- 57
var appenders = this.__appenders;
- 57
for (var i in appenders) {
- 47
appenders[i].level = level;
}
- 57
this._tree.level = level;
} else {
- 1
this.__level = level;
}
},
additive: function (additive) {
- 2
this.__additive = additive;
}
},
/**@ignore*/
getters: {
/**@ignore*/
/**@ignore*/
subLoggers: function () {
- 2
return this._tree.getSubLoggers();
},
/**@ignore*/
level: function () {
- 223
return this.__level;
},
/**@ignore*/
additive: function () {
- 15
return this.__additive;
},
isAll: function () {
- 8
return Level.ALL.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isDebug: function () {
- 8
return Level.DEBUG.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isTrace: function () {
- 8
return Level.TRACE.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isInfo: function () {
- 8
return Level.INFO.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isWarn: function () {
- 8
return Level.WARN.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isError: function () {
- 8
return Level.ERROR.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isFatal: function () {
- 8
return Level.FATAL.isGreaterOrEqualToo(this.level);
},
/**@ignore*/
isOff: function () {
- 9
return Level.OFF.equals(this.level);
},
/**@ignore*/
name: function () {
- 14
return this.__name;
},
/**@ignore*/
tree: function () {
- 13
return this._tree;
},
/**@ignore*/
appenders: function () {
- 18
var ret = [];
- 18
for (var i in this.__appenders) {
- 8
ret.push(this.__appenders[i]);
}
- 18
return ret;
},
categories: function () {
- 2
return this._tree.categories;
}
}
},
static: {
/**@lends comb.logging.Logger*/
/**
* Return the root of all loggers
*/
getRootLogger: function () {
- 11
return rootTree.getRootLogger();
},
/**
* Retrieves/Creates a logger based on the name passed in
*
* @param {String} name the name of the logger
*/
getLogger: function (name) {
- 21
return rootTree.getLogger(name);
}
}
}));
/**
*
* @function
* @description Alias to {@link comb.logging.Logger.getLogger}. See {@link comb.logging.Logger} for more information.
*
* @example
*
* comb.logger("my.logger");
*
* @memberOf comb
* @namespace
*/
- 1
exports.logger = Logger.getLogger.bind(Logger);
/**
* @function
* @description Shortcut to configure loggers.
*
* @example
*
* //same as new comb.logging.BasicConfigurator().configure();
* comb.logger.configure();
*
* //new comb.logging.PropertyConfigurator().configure("/location/to/logger/configuration.json");
* comb.logger.configure("/location/to/logger/configuration.json");
*
* @memberOf comb.logger
*/
- 1
exports.logger.configure = function configure() {
- 4
var args = argsToArray(arguments), configurator;
- 4
if (!args.length) {
- 1
configurator = new configurators.BasicConfigurator();
} else {
- 3
var first = args[0];
- 3
if (isHash(first) || isString(first)) {
- 2
configurator = new configurators.PropertyConfigurator();
} else {
- 1
configurator = new configurators.BasicConfigurator();
}
}
- 4
configurator.configure.apply(configurator, args);
- 4
return this;
};
/**
* @function
* @description Factory method for creating appenders. See {@link comb.logging.appenders.Appender.createAppender} for
* arguments.
*
* @example
*
* var appender = comb.logger.appender("ConsoleAppender");
* comb.logger("my.logger").addAppender(appender);
*
* @memberOf comb.logger
*
*/
- 1
exports.logger.appender = Appender.createAppender.bind(Appender);
- 1
var rootLogger = new Logger("");
- 1
rootTree = rootLogger._tree;
/**
* The root for all loggers.
* @memberOf comb.logger
* @type comb.logging.Logger
*/
- 1
exports.logger.rootLogger = rootLogger;
base/date/index.js
|
Coverage99.33
SLOC910
LOC300
Missed2
|
- 1
var string,
transforms = require("./transforms.js"),
addTransform = transforms.addTransform,
differenceTransform = transforms.differenceTransform;
- 1
function getString() {
- 298
return string || (string = require("../string").string);
}
/**
* @ignore
* Based on DOJO Date Implementation
*
* Dojo is available under *either* the terms of the modified BSD license *or* the
* Academic Free License version 2.1. As a recipient of Dojo, you may choose which
* license to receive this code under (except as noted in per-module LICENSE
* files). Some modules may not be the copyright of the Dojo Foundation. These
* modules contain explicit declarations of copyright in both the LICENSE files in
* the directories in which they reside and in the code itself. No external
* contributions are allowed under licenses which are fundamentally incompatible
* with the AFL or BSD licenses that Dojo is distributed under.
*
*/
- 1
var floor = Math.floor, round = Math.round, min = Math.min, pow = Math.pow, ceil = Math.ceil, abs = Math.abs;
- 1
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
- 1
var monthAbbr = ["Jan.", "Feb.", "Mar.", "Apr.", "May.", "Jun.", "Jul.", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."];
- 1
var monthLetter = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
- 1
var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
- 1
var dayAbbr = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
- 1
var dayLetter = ["S", "M", "T", "W", "T", "F", "S"];
- 1
var eraNames = ["Before Christ", "Anno Domini"];
- 1
var eraAbbr = ["BC", "AD"];
- 1
var eraLetter = ["B", "A"];
- 1
var comb = exports, date;
/**
* Determines if obj is a Date
*
* @param {Anything} obj the thing to test if it is a Date
* @memberOf comb
* @returns {Boolean} true if it is a Date false otherwise
*/
- 1
comb.isDate = function (obj) {
- 1252
var undef;
- 1252
return (obj !== undef && typeof obj === "object" && obj instanceof Date);
};
- 1
function getDayOfYear(/*Date*/dateObject, utc) {
// summary: gets the day of the year as represented by dateObject
- 6
return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject, null, utc) + 1; // Number
}
- 1
function getWeekOfYear(/*Date*/dateObject, /*Number*/firstDayOfWeek, utc) {
- 4
firstDayOfWeek = firstDayOfWeek || 0;
- 4
var fullYear = dateObject[utc ? "getUTCFullYear" : "getFullYear"]();
- 4
var firstDayOfYear = new Date(fullYear, 0, 1).getDay(),
adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
week = floor((getDayOfYear(dateObject) + adj - 1) / 7);
// if year starts on the specified day, start counting weeks at 1
- 4
if (firstDayOfYear === firstDayOfWeek) {
- 4
week++;
}
- 4
return week; // Number
}
- 1
function getTimezoneName(/*Date*/dateObject) {
- 37
var str = dateObject.toString();
- 37
var tz = '';
- 37
var pos = str.indexOf('(');
- 37
if (pos > -1) {
- 33
tz = str.substring(++pos, str.indexOf(')'));
}
- 37
return tz; // String
}
- 1
function buildDateEXP(pattern, tokens) {
- 55
return pattern.replace(/([a-z])\1*/ig, function (match) {
// Build a simple regexp. Avoid captures, which would ruin the tokens list
- 197
var s,
c = match.charAt(0),
l = match.length,
p2 = '', p3 = '';
- 197
p2 = '0?';
- 197
p3 = '0{0,2}';
- 197
if (c === 'y') {
- 33
s = '\\d{2,4}';
- 164
} else if (c === "M") {
- 33
s = (l > 2) ? '\\S+?' : '1[0-2]|' + p2 + '[1-9]';
- 131
} else if (c === "D") {
- 4
s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|' + p3 + '[1-9][0-9]|' + p2 + '[1-9]';
- 127
} else if (c === "d") {
- 31
s = '3[01]|[12]\\d|' + p2 + '[1-9]';
- 96
} else if (c === "w") {
- 4
s = '[1-4][0-9]|5[0-3]|' + p2 + '[1-9]';
- 92
} else if (c === "E") {
- 12
s = '\\S+';
- 80
} else if (c === "h") {
- 10
s = '1[0-2]|' + p2 + '[1-9]';
- 70
} else if (c === "K") {
- 4
s = '1[01]|' + p2 + '\\d';
- 66
} else if (c === "H") {
- 2
s = '1\\d|2[0-3]|' + p2 + '\\d';
- 64
} else if (c === "k") {
- 2
s = '1\\d|2[0-4]|' + p2 + '[1-9]';
- 62
} else if (c === "m" || c === "s") {
- 30
s = '[0-5]\\d';
- 32
} else if (c === "S") {
- 10
s = '\\d{' + l + '}';
- 22
} else if (c === "a") {
- 6
var am = 'AM', pm = 'PM';
- 6
s = am + '|' + pm;
- 6
if (am !== am.toLowerCase()) {
- 6
s += '|' + am.toLowerCase();
}
- 6
if (pm !== pm.toLowerCase()) {
- 6
s += '|' + pm.toLowerCase();
}
- 6
s = s.replace(/\./g, "\\.");
- 16
} else if (c === 'v' || c === 'z' || c === 'Z' || c === 'G' || c === 'q' || c === 'Q') {
- 12
s = ".*";
} else {
- 4
s = c === " " ? "\\s*" : c + "*";
}
- 197
if (tokens) {
- 197
tokens.push(match);
}
- 197
return "(" + s + ")"; // add capture
}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace. Need explicit handling of \xa0 for IE.
}
/**
* @namespace Utilities for Dates
*/
- 1
comb.date = {
/**@lends comb.date*/
/**
* Returns the number of days in the month of a date
*
* @example
*
* comb.date.getDaysInMonth(new Date(2006, 1, 1)); //28
* comb.date.getDaysInMonth(new Date(2004, 1, 1)); //29
* comb.date.getDaysInMonth(new Date(2006, 2, 1)); //31
* comb.date.getDaysInMonth(new Date(2006, 3, 1)); //30
* comb.date.getDaysInMonth(new Date(2006, 4, 1)); //31
* comb.date.getDaysInMonth(new Date(2006, 5, 1)); //30
* comb.date.getDaysInMonth(new Date(2006, 6, 1)); //31
* @param {Date} dateObject the date containing the month
* @return {Number} the number of days in the month
*/
getDaysInMonth: function (/*Date*/dateObject) {
// summary:
// Returns the number of days in the month used by dateObject
- 36
var month = dateObject.getMonth();
- 36
var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
- 36
if (month === 1 && date.isLeapYear(dateObject)) {
- 6
return 29;
} // Number
- 30
return days[month]; // Number
},
/**
* Determines if a date is a leap year
*
* @example
*
* comb.date.isLeapYear(new Date(1600, 0, 1)); //true
* comb.date.isLeapYear(new Date(2004, 0, 1)); //true
* comb.date.isLeapYear(new Date(2000, 0, 1)); //true
* comb.date.isLeapYear(new Date(2006, 0, 1)); //false
* comb.date.isLeapYear(new Date(1900, 0, 1)); //false
* comb.date.isLeapYear(new Date(1800, 0, 1)); //false
* comb.date.isLeapYear(new Date(1700, 0, 1)); //false
*
* @param {Date} dateObject
* @returns {Boolean} true if it is a leap year false otherwise
*/
isLeapYear: function (/*Date*/dateObject, utc) {
- 28
var year = dateObject[utc ? "getUTCFullYear" : "getFullYear"]();
- 28
return (year % 400 === 0) || (year % 4 === 0 && year % 100 !== 0);
},
/**
* Determines if a date is on a weekend
*
* @example
*
* var thursday = new Date(2006, 8, 21);
* var saturday = new Date(2006, 8, 23);
* var sunday = new Date(2006, 8, 24);
* var monday = new Date(2006, 8, 25);
* comb.date.isWeekend(thursday)); //false
* comb.date.isWeekend(saturday); //true
* comb.date.isWeekend(sunday); //true
* comb.date.isWeekend(monday)); //false
*
* @param {Date} dateObject the date to test
*
* @returns {Boolean} true if the date is a weekend
*/
isWeekend: function (/*Date?*/dateObject, utc) {
// summary:
// Determines if the date falls on a weekend, according to local custom.
- 4
var day = (dateObject || new Date())[utc ? "getUTCDay" : "getDay"]();
- 4
return day === 0 || day === 6;
},
/**
* Get the timezone of a date
*
* @example
* //just setting the strLocal to simulate the toString() of a date
* dt.str = 'Sun Sep 17 2006 22:25:51 GMT-0500 (CDT)';
* //just setting the strLocal to simulate the locale
* dt.strLocale = 'Sun 17 Sep 2006 10:25:51 PM CDT';
* comb.date.getTimezoneName(dt); //'CDT'
* dt.str = 'Sun Sep 17 2006 22:57:18 GMT-0500 (CDT)';
* dt.strLocale = 'Sun Sep 17 22:57:18 2006';
* comb.date.getTimezoneName(dt); //'CDT'
* @param dateObject the date to get the timezone from
*
* @returns {String} the timezone of the date
*/
getTimezoneName: getTimezoneName,
/**
* Compares two dates
*
* @example
*
* var d1 = new Date();
* d1.setHours(0);
* comb.date.compare(d1, d1); // 0
*
* var d1 = new Date();
* d1.setHours(0);
* var d2 = new Date();
* d2.setFullYear(2005);
* d2.setHours(12);
* comb.date.compare(d1, d2, "date"); // 1
* comb.date.compare(d1, d2, "datetime"); // 1
*
* var d1 = new Date();
* d1.setHours(0);
* var d2 = new Date();
* d2.setFullYear(2005);
* d2.setHours(12);
* comb.date.compare(d2, d1, "date"); // -1
* comb.date.compare(d1, d2, "time"); //-1
*
* @param {Date|String} date1 the date to comapare
* @param {Date|String} [date2=new Date()] the date to compare date1 againse
* @param {"date"|"time"|"datetime"} portion compares the portion specified
*
* @returns -1 if date1 is < date2 0 if date1 === date2 1 if date1 > date2
*/
compare: function (/*Date*/date1, /*Date*/date2, /*String*/portion) {
- 10
date1 = new Date(date1);
- 10
date2 = new Date((date2 || new Date()));
- 10
if (portion === "date") {
// Ignore times and compare dates.
- 4
date1.setHours(0, 0, 0, 0);
- 4
date2.setHours(0, 0, 0, 0);
- 6
} else if (portion === "time") {
// Ignore dates and compare times.
- 2
date1.setFullYear(0, 0, 0);
- 2
date2.setFullYear(0, 0, 0);
}
- 10
return date1 > date2 ? 1 : date1 < date2 ? -1 : 0;
},
/**
* Adds a specified interval and amount to a date
*
* @example
* var dtA = new Date(2005, 11, 27);
* comb.date.add(dtA, "year", 1); //new Date(2006, 11, 27);
* comb.date.add(dtA, "years", 1); //new Date(2006, 11, 27);
*
* dtA = new Date(2000, 0, 1);
* comb.date.add(dtA, "quarter", 1); //new Date(2000, 3, 1);
* comb.date.add(dtA, "quarters", 1); //new Date(2000, 3, 1);
*
* dtA = new Date(2000, 0, 1);
* comb.date.add(dtA, "month", 1); //new Date(2000, 1, 1);
* comb.date.add(dtA, "months", 1); //new Date(2000, 1, 1);
*
* dtA = new Date(2000, 0, 31);
* comb.date.add(dtA, "month", 1); //new Date(2000, 1, 29);
* comb.date.add(dtA, "months", 1); //new Date(2000, 1, 29);
*
* dtA = new Date(2000, 0, 1);
* comb.date.add(dtA, "week", 1); //new Date(2000, 0, 8);
* comb.date.add(dtA, "weeks", 1); //new Date(2000, 0, 8);
*
* dtA = new Date(2000, 0, 1);
* comb.date.add(dtA, "day", 1); //new Date(2000, 0, 2);
*
* dtA = new Date(2000, 0, 1);
* comb.date.add(dtA, "weekday", 1); //new Date(2000, 0, 3);
*
* dtA = new Date(2000, 0, 1, 11);
* comb.date.add(dtA, "hour", 1); //new Date(2000, 0, 1, 12);
*
* dtA = new Date(2000, 11, 31, 23, 59);
* comb.date.add(dtA, "minute", 1); //new Date(2001, 0, 1, 0, 0);
*
* dtA = new Date(2000, 11, 31, 23, 59, 59);
* comb.date.add(dtA, "second", 1); //new Date(2001, 0, 1, 0, 0, 0);
*
* dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
* comb.date.add(dtA, "millisecond", 1); //new Date(2001, 0, 1, 0, 0, 0, 0);
*
* @param {Date} date
* @param {String} interval the interval to add
* <ul>
* <li>day | days</li>
* <li>weekday | weekdays</li>
* <li>year | years</li>
* <li>week | weeks</li>
* <li>quarter | quarters</li>
* <li>months | months</li>
* <li>hour | hours</li>
* <li>minute | minutes</li>
* <li>second | seconds</li>
* <li>millisecond | milliseconds</li>
* </ul>
* @param {Number} [amount=0] the amount to add
*/
add: function (/*Date*/date, /*String*/interval, /*int*/amount) {
- 234
var res = addTransform(interval, date, amount || 0);
- 234
amount = res[0];
- 234
var property = res[1];
- 234
var sum = new Date(date);
- 234
var fixOvershoot = res[2];
- 234
if (property) {
- 234
sum["set" + property](sum["get" + property]() + amount);
}
- 234
if (fixOvershoot && (sum.getDate() < date.getDate())) {
- 26
sum.setDate(0);
}
- 234
return sum; // Date
},
/**
* Finds the difference between two dates based on the specified interval
*
* @example
*
* var dtA, dtB;
*
* dtA = new Date(2005, 11, 27);
* dtB = new Date(2006, 11, 27);
* comb.date.difference(dtA, dtB, "year"); //1
*
* dtA = new Date(2000, 1, 29);
* dtB = new Date(2001, 2, 1);
* comb.date.difference(dtA, dtB, "quarter"); //4
* comb.date.difference(dtA, dtB, "month"); //13
*
* dtA = new Date(2000, 1, 1);
* dtB = new Date(2000, 1, 8);
* comb.date.difference(dtA, dtB, "week"); //1
*
* dtA = new Date(2000, 1, 29);
* dtB = new Date(2000, 2, 1);
* comb.date.difference(dtA, dtB, "day"); //1
*
* dtA = new Date(2006, 7, 3);
* dtB = new Date(2006, 7, 11);
* comb.date.difference(dtA, dtB, "weekday"); //6
*
* dtA = new Date(2000, 11, 31, 23);
* dtB = new Date(2001, 0, 1, 0);
* comb.date.difference(dtA, dtB, "hour"); //1
*
* dtA = new Date(2000, 11, 31, 23, 59);
* dtB = new Date(2001, 0, 1, 0, 0);
* comb.date.difference(dtA, dtB, "minute"); //1
*
* dtA = new Date(2000, 11, 31, 23, 59, 59);
* dtB = new Date(2001, 0, 1, 0, 0, 0);
* comb.date.difference(dtA, dtB, "second"); //1
*
* dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
* dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
* comb.date.difference(dtA, dtB, "millisecond"); //1
*
*
* @param {Date} date1
* @param {Date} [date2 = new Date()]
* @param {String} [interval = "day"] the intercal to find the difference of.
* <ul>
* <li>day | days</li>
* <li>weekday | weekdays</li>
* <li>year | years</li>
* <li>week | weeks</li>
* <li>quarter | quarters</li>
* <li>months | months</li>
* <li>hour | hours</li>
* <li>minute | minutes</li>
* <li>second | seconds</li>
* <li>millisecond | milliseconds</li>
* </ul>
*/
difference: function (/*Date*/date1, /*Date?*/date2, /*String*/interval, utc) {
- 162
date2 = date2 || new Date();
- 162
interval = interval || "day";
- 162
return differenceTransform(interval, date1, date2, utc);
},
/**
* Parses a date string into a date object
*
* @example
* var aug_11_2006 = new Date(2006, 7, 11, 0);
* comb.date.parse("08/11/06", "MM/dd/yy"); //aug_11_2006
* comb.date.parse("11Aug2006", 'ddMMMyyyy'); //aug_11_2006
* comb.date.parse("Aug2006", 'MMMyyyy'); //new Date(2006, 7, 1)
* comb.date.parse("Aug 11, 2006", "MMM dd, yyyy"); //aug_11_2006
* comb.date.parse("August 11, 2006", "MMMM dd, yyyy"); //aug_11_2006
* comb.date.parse("Friday, August 11, 2006", "EEEE, MMMM dd, yyyy"); //aug_11_2006
*
* @param {String} dateStr The string to parse
* @param {String} format the format of the date composed of the following options
* <ul>
* <li> G Era designator Text AD</li>
* <li> y Year Year 1996; 96</li>
* <li> M Month in year Month July; Jul; 07</li>
* <li> w Week in year Number 27</li>
* <li> W Week in month Number 2</li>
* <li> D Day in year Number 189</li>
* <li> d Day in month Number 10</li>
* <li> E Day in week Text Tuesday; Tue</li>
* <li> a Am/pm marker Text PM</li>
* <li> H Hour in day (0-23) Number 0</li>
* <li> k Hour in day (1-24) Number 24</li>
* <li> K Hour in am/pm (0-11) Number 0</li>
* <li> h Hour in am/pm (1-12) Number 12</li>
* <li> m Minute in hour Number 30</li>
* <li> s Second in minute Number 55</li>
* <li> S Millisecond Number 978</li>
* <li> z Time zone General time zone Pacific Standard Time; PST; GMT-08:00</li>
* <li> Z Time zone RFC 822 time zone -0800 </li>
* </ul>
*
* @returns {Date} the parsed date
*
*
*/
parse: function (dateStr, format) {
- 57
if (!format) {
- 2
throw new Error('format required when calling comb.date.parse');
}
- 55
var tokens = [], regexp = buildDateEXP(format, tokens),
re = new RegExp("^" + regexp + "$", "i"),
match = re.exec(dateStr);
- 55
if (!match) {
- 7
return null;
} // null
- 48
var result = [1970, 0, 1, 0, 0, 0, 0], // will get converted to a Date at the end
amPm = "",
valid = match.every(function (v, i) {
- 212
if (i) {
- 164
var token = tokens[i - 1];
- 164
var l = token.length, type = token.charAt(0);
- 164
if (type === 'y') {
- 26
if (v < 100) {
- 6
v = parseInt(v, 10);
//choose century to apply, according to a sliding window
//of 80 years before and 20 years after present year
- 6
var year = '' + new Date().getFullYear(),
century = year.substring(0, 2) * 100,
cutoff = min(year.substring(2, 4) + 20, 99);
- 6
result[0] = (v < cutoff) ? century + v : century - 100 + v;
} else {
- 20
result[0] = v;
}
- 138
} else if (type === "M") {
- 28
if (l > 2) {
- 20
var months = monthNames;
- 20
if (l === 3) {
- 8
months = monthAbbr;
}
//Tolerate abbreviating period in month part
//Case-insensitive comparison
- 20
v = v.replace(".", "").toLowerCase();
- 20
months = months.map(function (s) {
- 240
return s.replace(".", "").toLowerCase();
});
- 20
if ((v = months.indexOf(v)) === -1) {
- 2
return false;
}
} else {
- 8
v--;
}
- 26
result[1] = v;
- 110
} else if (type === "E" || type === "e") {
- 12
var days = dayNames;
- 12
if (l === 3) {
- 4
days = dayAbbr;
}
//Case-insensitive comparison
- 12
v = v.toLowerCase();
- 12
days = days.map(function (d) {
- 84
return d.toLowerCase();
});
- 12
var d = days.indexOf(v);
- 12
if (d === -1) {
- 4
v = parseInt(v, 10);
- 4
if (isNaN(v) || v > days.length) {
- 2
return false;
}
} else {
- 8
v = d;
}
- 98
} else if (type === 'D' || type === "d") {
- 30
if (type === "D") {
- 4
result[1] = 0;
}
- 30
result[2] = v;
- 68
} else if (type === "a") {
- 4
var am = "am";
- 4
var pm = "pm";
- 4
var period = /\./g;
- 4
v = v.replace(period, '').toLowerCase();
// we might not have seen the hours field yet, so store the state and apply hour change later
- 4
amPm = (v === pm) ? 'p' : (v === am) ? 'a' : '';
- 64
} else if (type === "k" || type === "h" || type === "H" || type === "K") {
- 14
if (type === "k" && (+v) === 24) {
- 2
v = 0;
}
- 14
result[3] = v;
- 50
} else if (type === "m") {
- 14
result[4] = v;
- 36
} else if (type === "s") {
- 10
result[5] = v;
- 26
} else if (type === "S") {
- 8
result[6] = v;
}
}
- 208
return true;
});
- 48
if (valid) {
- 44
var hours = +result[3];
//account for am/pm
- 44
if (amPm === 'p' && hours < 12) {
- 2
result[3] = hours + 12; //e.g., 3pm -> 15
- 42
} else if (amPm === 'a' && hours === 12) {
- 2
result[3] = 0; //12am -> 0
}
- 44
var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date
- 44
var dateToken = (tokens.indexOf('d') !== -1),
monthToken = (tokens.indexOf('M') !== -1),
month = result[1],
day = result[2],
dateMonth = dateObject.getMonth(),
dateDay = dateObject.getDate();
- 44
if ((monthToken && dateMonth > month) || (dateToken && dateDay > day)) {
- 2
return null;
}
- 42
return dateObject; // Date
} else {
- 4
return null;
}
},
/**
* Formats a date to the specidifed format string
*
* @example
*
* var date = new Date(2006, 7, 11, 0, 55, 12, 345);
* comb.date.format(date, "EEEE, MMMM dd, yyyy"); //"Friday, August 11, 2006"
* comb.date.format(date, "M/dd/yy"); //"8/11/06"
* comb.date.format(date, "E"); //"6"
* comb.date.format(date, "h:m a"); //"12:55 AM"
* comb.date.format(date, 'h:m:s'); //"12:55:12"
* comb.date.format(date, 'h:m:s.SS'); //"12:55:12.35"
* comb.date.format(date, 'k:m:s.SS'); //"24:55:12.35"
* comb.date.format(date, 'H:m:s.SS'); //"0:55:12.35"
* comb.date.format(date, "ddMMyyyy"); //"11082006"
*
* @param date the date to format
* @param {String} format the format of the date composed of the following options
* <ul>
* <li> G Era designator Text AD</li>
* <li> y Year Year 1996; 96</li>
* <li> M Month in year Month July; Jul; 07</li>
* <li> w Week in year Number 27</li>
* <li> W Week in month Number 2</li>
* <li> D Day in year Number 189</li>
* <li> d Day in month Number 10</li>
* <li> E Day in week Text Tuesday; Tue</li>
* <li> a Am/pm marker Text PM</li>
* <li> H Hour in day (0-23) Number 0</li>
* <li> k Hour in day (1-24) Number 24</li>
* <li> K Hour in am/pm (0-11) Number 0</li>
* <li> h Hour in am/pm (1-12) Number 12</li>
* <li> m Minute in hour Number 30</li>
* <li> s Second in minute Number 55</li>
* <li> S Millisecond Number 978</li>
* <li> z Time zone General time zone Pacific Standard Time; PST; GMT-08:00</li>
* <li> Z Time zone RFC 822 time zone -0800 </li>
* </ul>
*/
format: function (date, format, utc) {
- 78
utc = utc || false;
- 78
var fullYear, month, day, d, hour, minute, second, millisecond;
- 78
if (utc) {
- 26
fullYear = date.getUTCFullYear();
- 26
month = date.getUTCMonth();
- 26
day = date.getUTCDay();
- 26
d = date.getUTCDate();
- 26
hour = date.getUTCHours();
- 26
minute = date.getUTCMinutes();
- 26
second = date.getUTCSeconds();
- 26
millisecond = date.getUTCMilliseconds();
} else {
- 52
fullYear = date.getFullYear();
- 52
month = date.getMonth();
- 52
d = date.getDate();
- 52
day = date.getDay();
- 52
hour = date.getHours();
- 52
minute = date.getMinutes();
- 52
second = date.getSeconds();
- 52
millisecond = date.getMilliseconds();
}
- 78
return format.replace(/([A-Za-z])\1*/g, function (match, options) {
- 372
var s, pad, h,
c = match.charAt(0),
l = match.length;
- 372
if (c === 'd') {
- 42
s = "" + d;
- 42
pad = true;
- 330
} else if (c === "H" && !s) {
- 30
s = "" + hour;
- 30
pad = true;
- 300
} else if (c === 'm' && !s) {
- 40
s = "" + minute;
- 40
pad = true;
- 260
} else if (c === 's') {
- 38
if (!s) {
- 38
s = "" + second;
}
- 38
pad = true;
- 222
} else if (c === "G") {
- 4
s = ((l < 4) ? eraAbbr : eraNames)[fullYear < 0 ? 0 : 1];
- 218
} else if (c === "y") {
- 48
s = fullYear;
- 48
if (l > 1) {
- 48
if (l === 2) {
- 6
s = getString().truncate("" + s, 2, true);
} else {
- 42
pad = true;
}
}
- 170
} else if (c.toUpperCase() === "Q") {
- 6
s = ceil((month + 1) / 3);
- 6
pad = true;
- 164
} else if (c === "M") {
- 42
if (l < 3) {
- 32
s = month + 1;
- 32
pad = true;
} else {
- 10
s = (l === 3 ? monthAbbr : monthNames)[month];
}
- 122
} else if (c === "w") {
- 4
s = getWeekOfYear(date, 0, utc);
- 4
pad = true;
- 118
} else if (c === "D") {
- 2
s = getDayOfYear(date, utc);
- 2
pad = true;
- 116
} else if (c === "E") {
- 12
if (l < 3) {
- 2
s = day + 1;
- 2
pad = true;
} else {
- 10
s = (l === -3 ? dayAbbr : dayNames)[day];
}
- 104
} else if (c === 'a') {
- 2
s = (hour < 12) ? 'AM' : 'PM';
- 102
} else if (c === "h") {
- 6
s = (hour % 12) || 12;
- 6
pad = true;
- 96
} else if (c === "K") {
- 2
s = (hour % 12);
- 2
pad = true;
- 94
} else if (c === "k") {
- 2
s = hour || 24;
- 2
pad = true;
- 92
} else if (c === "S") {
- 36
s = round(millisecond * pow(10, l - 3));
- 36
pad = true;
- 56
} else if (c === "z" || c === "v" || c === "Z") {
- 30
s = getTimezoneName(date);
- 30
if ((c === "z" || c === "v") && !s) {
- 4
l = 4;
}
- 30
if (!s || c === "Z") {
- 4
var offset = date.getTimezoneOffset();
- 4
var tz = [
(offset >= 0 ? "-" : "+"),
getString().pad(floor(abs(offset) / 60), 2, "0"),
getString().pad(abs(offset) % 60, 2, "0")
];
- 4
if (l === 4) {
- 4
tz.splice(0, 0, "GMT");
- 4
tz.splice(3, 0, ":");
}
- 4
s = tz.join("");
}
} else {
- 26
s = match;
}
- 372
if (pad) {
- 284
s = getString().pad(s, l, '0');
}
- 372
return s;
});
}
};
- 1
date = comb.date;
/**
* Adds the specified year/s to the current date.
*
* @example
*
* //assuming that current year is 2012
* comb.yearsFromNow(1); //2013-mm-dd hh:MM:ss
*
* @param {Number} val the number of years to add
*
* @return {Date} a date with the number of years added
*/
- 1
comb.yearsFromNow = function (val) {
- 1
return date.add(new Date(), "years", val);
};
/**
* Subtracts the specified year/s from the current date.
*
* @param {Number} val the number of years to subtract
*
* @return {Date} a date with the number of years subtracted
*/
- 1
comb.yearsAgo = function (val) {
- 1
return date.add(new Date(), "years", -val);
};
/**
* Adds the specified month/s to the current date.
*
* @example
*
* //assuming that current month is february
* comb.yearsFromNow(2); //yyyy-04-dd hh:MM:ss
*
* @param {Number} val the number of months to add
*
* @return {Date} a date with the number of years added
*/
- 1
comb.monthsFromNow = function (val) {
- 1
return date.add(new Date(), "months", val);
};
/**
* Subtracts the specified month/s from the current date.
*
* @param {Number} val the number of months to subtract
*
* @return {Date} a date with the number of months subtracted
*/
- 1
comb.monthsAgo = function (val) {
- 1
return date.add(new Date(), "months", -val);
};
/**
* Adds the specified day/s to the current date.
*
* @param {Number} val the number of days to add
*
* @return {Date} a date with the number of days added
*/
- 1
comb.daysFromNow = function (val) {
- 27
return date.add(new Date(), "days", val);
};
/**
* Subtracts the specified day/s from the current date.
*
* @param {Number} val the number of days to subtract
*
* @return {Date} a date with the number of days subtracted
*/
- 1
comb.daysAgo = function (val) {
- 1
return date.add(new Date(), "days", -val);
};
/**
* Adds the specified weekday/s to the current date.
*
* @param {Number} val the number of weekdays to add
*
* @return {Date} a date with the number of weekdays added
*/
- 1
comb.weekDaysFromNow = function (val) {
- 0
return date.add(new Date(), "weekdays", val);
};
/**
* Subtracts the specified weekday/s from the current date.
*
* @param {Number} val the number of weekdays to subtract
*
* @return {Date} a date with the number of weekdays subtracted
*/
- 1
comb.weekDaysAgo = function (val) {
- 0
return date.add(new Date(), "weekdays", -val);
};
/**
* Adds the specified hour/s to the current date.
*
* @param {Number} val the number of hours to add
*
* @return {Date} a date with the number of hours added
*/
- 1
comb.hoursFromNow = function (val) {
- 1
return date.add(new Date(), "hours", val);
};
/**
* Subtracts the specified hour/s from the current date.
*
* @param {Number} val the number of hours to subtract
*
* @return {Date} a date with the number of hours subtracted
*/
- 1
comb.hoursAgo = function (val) {
- 1
return date.add(new Date(), "hours", -val);
};
/**
* Adds the specified minute/s to the current date.
*
* @param {Number} val the number of minutes to add
*
* @return {Date} a date with the number of minutes added
*/
- 1
comb.minutesFromNow = function (val) {
- 1
return date.add(new Date(), "minutes", val);
};
/**
* Subtracts the specified minute/s from the current date.
*
* @param {Number} val the number of minutes to subtract
*
* @return {Date} a date with the number of minutes subtracted
*/
- 1
comb.minutesAgo = function (val) {
- 1
return date.add(new Date(), "minutes", -val);
};
/**
* Adds the specified second/s to the current date.
*
* @param {Number} val the number of seconds to add
*
* @return {Date} a date with the number of seconds added
*/
- 1
comb.secondsFromNow = function (val) {
- 1
return date.add(new Date(), "seconds", val);
};
/**
* Subtracts the specified second/s from the current date.
*
* @param {Number} val the number of seconds to subtract
*
* @return {Date} a date with the number of seconds subtracted
*/
- 1
comb.secondsAgo = function (val) {
- 1
return date.add(new Date(), "seconds", -val);
};
base/array.js
|
Coverage100.00
SLOC1123
LOC363
Missed0
|
- 1
var obj = require("./object"),
merge = obj.merge,
misc = require("./misc"),
argsToArray = misc.argsToArray,
string = require("./string"),
isString = string.isString,
number = require("./number.js"),
floor = Math.floor,
abs = Math.abs,
mathMax = Math.max,
mathMin = Math.min;
- 1
var isArray = exports.isArray = function isArray(obj) {
- 12427
return Object.prototype.toString.call(obj) === "[object Array]";
};
- 1
function isDate(obj) {
- 126
var undef;
- 126
return (obj !== undef && typeof obj === "object" && obj instanceof Date);
}
- 1
function cross(num, cros) {
- 21
var ret = reduceRight(cros, function (a, b) {
- 57
if (!isArray(b)) {
- 57
b = [b];
}
- 57
b.unshift(num);
- 57
a.unshift(b);
- 57
return a;
}, []);
- 21
return ret;
}
- 1
function permute(num, cross, length) {
- 18
var ret = [];
- 18
for (var i = 0; i < cross.length; i++) {
- 36
ret.push([num].concat(rotate(cross, i)).slice(0, length));
}
- 18
return ret;
}
- 1
function intersection(a, b) {
- 40
var ret = [], aOne;
- 40
if (isArray(a) && isArray(b) && a.length && b.length) {
- 38
for (var i = 0, l = a.length; i < l; i++) {
- 129
aOne = a[i];
- 129
if (indexOf(b, aOne) !== -1) {
- 94
ret.push(aOne);
}
}
}
- 40
return ret;
}
- 1
var _sort = (function () {
- 1
var isAll = function (arr, test) {
- 63
return every(arr, test);
};
- 1
var defaultCmp = function (a, b) {
- 90
return a - b;
};
- 1
var dateSort = function (a, b) {
- 27
return a.getTime() - b.getTime();
};
- 1
return function _sort(arr, property) {
- 66
var ret = [];
- 66
if (isArray(arr)) {
- 66
ret = arr.slice();
- 66
if (property) {
- 30
if (typeof property === "function") {
- 3
ret.sort(property);
} else {
- 27
ret.sort(function (a, b) {
- 81
var aProp = a[property], bProp = b[property];
- 81
if (isString(aProp) && isString(bProp)) {
- 27
return aProp > bProp ? 1 : aProp < bProp ? -1 : 0;
- 54
} else if (isDate(aProp) && isDate(bProp)) {
- 27
return aProp.getTime() - bProp.getTime()
} else {
- 27
return aProp - bProp;
}
});
}
} else {
- 36
if (isAll(ret, isString)) {
- 9
ret.sort();
- 27
} else if (isAll(ret, isDate)) {
- 9
ret.sort(dateSort);
} else {
- 18
ret.sort(defaultCmp);
}
}
}
- 66
return ret;
};
})();
- 1
function indexOf(arr, searchElement, fromIndex) {
- 363
if (!isArray(arr)) {
- 1
throw new TypeError();
}
- 362
var t = Object(arr);
- 362
var len = t.length >>> 0;
- 362
if (len === 0) {
- 39
return -1;
}
- 323
var n = 0;
- 323
if (arguments.length > 2) {
- 8
n = Number(arguments[2]);
- 8
if (n !== n) { // shortcut for verifying if it's NaN
- 2
n = 0;
- 6
} else if (n !== 0 && n !== Infinity && n !== -Infinity) {
- 2
n = (n > 0 || -1) * floor(abs(n));
}
}
- 323
if (n >= len) {
- 2
return -1;
}
- 321
var k = n >= 0 ? n : mathMax(len - abs(n), 0);
- 321
for (; k < len; k++) {
- 644
if (k in t && t[k] === searchElement) {
- 180
return k;
}
}
- 141
return -1;
}
- 1
function lastIndexOf(arr, searchElement, fromIndex) {
- 12
if (!isArray(arr)) {
- 1
throw new TypeError();
}
- 11
var t = Object(arr);
- 11
var len = t.length >>> 0;
- 11
if (len === 0) {
- 1
return -1;
}
- 10
var n = len;
- 10
if (arguments.length > 2) {
- 8
n = Number(arguments[2]);
- 8
if (n !== n) {
- 2
n = 0;
- 6
} else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
- 2
n = (n > 0 || -1) * floor(abs(n));
}
}
- 10
var k = n >= 0 ? mathMin(n, len - 1) : len - abs(n);
- 10
for (; k >= 0; k--) {
- 18
if (k in t && t[k] === searchElement) {
- 6
return k;
}
}
- 4
return -1;
}
- 1
function filter(arr, iterator, scope) {
- 47
if (!isArray(arr) || typeof iterator !== "function") {
- 1
throw new TypeError();
}
- 46
var t = Object(arr);
- 46
var len = t.length >>> 0;
- 46
var res = [];
- 46
for (var i = 0; i < len; i++) {
- 168
if (i in t) {
- 128
var val = t[i]; // in case fun mutates this
- 128
if (iterator.call(scope, val, i, t)) {
- 76
res.push(val);
}
}
}
- 46
return res;
}
- 1
function forEach(arr, iterator, scope) {
- 8495
if (!isArray(arr) || typeof iterator !== "function") {
- 1
throw new TypeError();
}
- 8494
for (var i = 0, len = arr.length; i < len; ++i) {
- 71440
iterator.call(scope || arr, arr[i], i, arr);
}
- 8494
return arr;
}
- 1
function every(arr, iterator, scope) {
- 281
if (!isArray(arr) || typeof iterator !== "function") {
- 1
throw new TypeError();
}
- 280
var t = Object(arr);
- 280
var len = t.length >>> 0;
- 280
for (var i = 0; i < len; i++) {
- 830
if (i in t && !iterator.call(scope, t[i], i, t)) {
- 171
return false;
}
}
- 109
return true;
}
- 1
function some(arr, iterator, scope) {
- 7
if (!isArray(arr) || typeof iterator !== "function") {
- 1
throw new TypeError();
}
- 6
var t = Object(arr);
- 6
var len = t.length >>> 0;
- 6
for (var i = 0; i < len; i++) {
- 30
if (i in t && iterator.call(scope, t[i], i, t)) {
- 2
return true;
}
}
- 4
return false;
}
- 1
function map(arr, iterator, scope) {
- 53
if (!isArray(arr) || typeof iterator !== "function") {
- 1
throw new TypeError();
}
- 52
var t = Object(arr);
- 52
var len = t.length >>> 0;
- 52
var res = [];
- 52
for (var i = 0; i < len; i++) {
- 177
if (i in t) {
- 177
res.push(iterator.call(scope, t[i], i, t));
}
}
- 52
return res;
}
- 1
function reduce(arr, accumulator, curr) {
- 211
if (!isArray(arr) || typeof accumulator !== "function") {
- 1
throw new TypeError();
}
- 210
var i = 0, l = arr.length >> 0;
- 210
if (arguments.length < 3) {
- 24
if (l === 0) {
- 1
throw new TypeError("Array length is 0 and no second argument");
}
- 23
curr = arr[0];
- 23
i = 1; // start accumulating at the second element
} else {
- 186
curr = arguments[2];
}
- 209
while (i < l) {
- 508
if (i in arr) {
- 508
curr = accumulator.call(undefined, curr, arr[i], i, arr);
}
- 508
++i;
}
- 209
return curr;
}
- 1
function reduceRight(arr, accumulator, curr) {
- 27
if (!isArray(arr) || typeof accumulator !== "function") {
- 1
throw new TypeError();
}
- 26
var t = Object(arr);
- 26
var len = t.length >>> 0;
// no value to return if no initial value, empty array
- 26
if (len === 0 && arguments.length === 2) {
- 1
throw new TypeError();
}
- 25
var k = len - 1;
- 25
if (arguments.length >= 3) {
- 23
curr = arguments[2];
} else {
- 2
do {
- 2
if (k in arr) {
- 2
curr = arr[k--];
- 2
break;
}
}
while (true);
}
- 25
while (k >= 0) {
- 75
if (k in t) {
- 75
curr = accumulator.call(undefined, curr, t[k], k, t);
}
- 75
k--;
}
- 25
return curr;
}
/**
* converts anything to an array
*
* @example
* comb.array.toArray({a : "b", b : "c"}) => [["a","b"], ["b","c"]];
* comb.array.toArray("a") => ["a"]
* comb.array.toArray(["a"]) => ["a"];
* comb.array.toArray() => [];
* comb.array.toArray("a", {a : "b"}) => ["a", ["a", "b"]];
*
* @static
* @memberOf comb.array
*/
- 1
function toArray(o) {
- 101
var ret = [];
- 101
if (o != null) {
- 100
var args = argsToArray(arguments);
- 100
if (args.length === 1) {
- 98
if (isArray(o)) {
- 85
ret = o;
- 13
} else if (obj.isHash(o)) {
- 4
for (var i in o) {
- 6
if (o.hasOwnProperty(i)) {
- 6
ret.push([i, o[i]]);
}
}
} else {
- 9
ret.push(o);
}
} else {
- 2
forEach(args, function (a) {
- 4
ret = ret.concat(toArray(a));
});
}
}
- 101
return ret;
}
/**
* Sums all items in an array
*
* @example
*
* comb.array.sum([1,2,3]) => 6
* comb.array.sum(["A","B","C"]) => "ABC";
* var d1 = new Date(1999), d2 = new Date(2000), d3 = new Date(3000);
* comb.array.sum([d1,d2,d3]) => "Wed Dec 31 1969 18:00:01 GMT-0600 (CST)"
* + "Wed Dec 31 1969" 18:00:02 GMT-0600 (CST)"
* + "Wed Dec 31 1969 18:00:03 GMT-0600 (CST)"
* comb.array.sum([{},{},{}]) => "[object Object][object Object][object Object]";
*
* @param {Number[]} array the array of numbers to sum
* @static
* @memberOf comb.array
*/
- 1
function sum(array) {
- 27
array = array || [];
- 27
if (array.length) {
- 21
return reduce(array, function (a, b) {
- 49
return a + b;
});
} else {
- 6
return 0;
}
}
/**
* Averages an array of numbers.
* @example
*
* comb.array.avg([1,2,3]); //2
*
* @param {Number[]} array - an array of numbers
* @return {Number} the average of all the numbers in the array.
* @throws {Error} if the array is not all numbers.
* @static
* @memberOf comb.array
*/
- 1
function avg(arr) {
- 13
arr = arr || [];
- 13
if (arr.length) {
- 8
var total = sum(arr);
- 8
if (number.isNumber(total)) {
- 4
return total / arr.length;
} else {
- 4
throw new Error("Cannot average an array of non numbers.");
}
} else {
- 5
return 0;
}
}
/**
* Allows the sorting of an array based on a property name instead. This can also
* act as a sort that does not change the original array.
*
* <b>NOTE:</b> this does not change the original array!
*
* @example
* comb.array.sort([{a : 1}, {a : 2}, {a : -2}], "a"); //[{a : -2}, {a : 1}, {a : 2}];
* @param {Array} arr the array to sort
* @param {String|Function} cmp the property to sort on. Or a function used to compare.
* @return {Array} a copy of the original array that is sorted.
*
* @static
* @memberOf comb.array
*/
- 1
function sort(arr, cmp) {
- 24
return _sort(arr, cmp);
}
/**
* Finds that min value of an array. If a second argument is provided and it is a function
* it will be used as a comparator function. If the second argument is a string then it will be used
* as a property look up on each item.
*
* @example
* comb.array.min([{a : 1}, {a : 2}, {a : -2}], "a"); //{a : -2}
* comb.array.min([{a : 1}, {a : 2}, {a : -2}], function(a,b){
* return a.a - b.a
* }); //{a : -2}
*
* @param {Array} arr the array to find the min value on
* @param {String|Function} cmp the property to sort on. Or a function used to compare.
* @return {*}
*
* @static
* @memberOf comb.array
*/
- 1
function min(arr, cmp) {
- 21
return _sort(arr, cmp)[0];
}
/**
* Finds that max value of an array. If a second argument is provided and it is a function
* it will be used as a comparator function. If the second argument is a string then it will be used
* as a property look up on each item.
*
* @example
* comb.array.max([{a : 1}, {a : 2}, {a : -2}], "a"); //{a : 2}
* comb.array.max([{a : 1}, {a : 2}, {a : -2}], function(a,b){
* return a.a - b.a
* }); //{a : 2}
*
* @param arr the array to find the max value on
* @param {String|Function} cmp the property to sort on. Or a function used to compare.
* @return {*} the maximum value of the array based on the provided cmp.
*
* @static
* @memberOf comb.array
*/
- 1
function max(arr, cmp) {
- 21
return _sort(arr, cmp)[arr.length - 1];
}
/**
* Finds the difference of the two arrays.
*
* @example
*
* comb.array.difference([1,2,3], [2,3]); //[1]
* comb.array.difference(["a","b",3], [3]); //["a","b"]
*
* @param {Array} arr1 the array we are subtracting from
* @param {Array} arr2 the array we are subtracting from arr1
* @return {*} the difference of the arrays.
*
* @static
* @memberOf comb.array
*/
- 1
function difference(arr1, arr2) {
- 25
var ret = arr1, args = flatten(argsToArray(arguments, 1));
- 25
if (isArray(arr1)) {
- 25
ret = filter(arr1, function (a) {
- 72
return indexOf(args, a) === -1;
});
}
- 25
return ret;
}
/**
* Removes duplicates from an array
*
* @example
*
* comb.array.removeDuplicates([1,1,1]) => [1]
* comb.array.removeDuplicates([1,2,3,2]) => [1,2,3]
*
* @param {Aray} array the array of elements to remove duplicates from
*
* @static
* @memberOf comb.array
*/
- 1
function removeDuplicates(arr) {
- 43
if (isArray(arr)) {
- 43
return reduce(arr, function (a, b) {
- 151
if (indexOf(a, b) === -1) {
- 106
return a.concat(b);
} else {
- 45
return a;
}
}, []);
}
}
/**
*
* See {@link comb.array.removeDuplicates}
*
* @static
* @memberOf comb.array
*/
- 1
function unique(arr) {
- 4
return removeDuplicates(arr);
}
/**
* Rotates an array the number of specified positions
*
* @example
* var arr = ["a", "b", "c", "d"];
* comb.array.rotate(arr) => ["b", "c", "d", "a"]
* comb.array.rotate(arr, 2) => ["c", "d", "a", "b"]);
* comb.array.rotate(arr, 3) => ["d", "a", "b", "c"]);
* comb.array.rotate(arr, 4) => ["a", "b", "c", "d"]);
* comb.array.rotate(arr, -1) => ["d", "a", "b", "c"]);
* comb.array.rotate(arr, -2) => ["c", "d", "a", "b"]);
* comb.array.rotate(arr, -3) => ["b", "c", "d", "a"]);
* comb.array.rotate(arr, -4) => ["a", "b", "c", "d"]);
*
* @param {Array} array the array of elements to remove duplicates from
* @param {Number} numberOfTimes the number of times to rotate the array
*
* @static
* @memberOf comb.array
*/
- 1
function rotate(arr, numberOfTimes) {
- 174
var ret = arr.slice();
- 174
if (typeof numberOfTimes !== "number") {
- 3
numberOfTimes = 1;
}
- 174
if (numberOfTimes && isArray(arr)) {
- 96
if (numberOfTimes > 0) {
- 66
ret.push(ret.shift());
- 66
numberOfTimes--;
} else {
- 30
ret.unshift(ret.pop());
- 30
numberOfTimes++;
}
- 96
return rotate(ret, numberOfTimes);
} else {
- 78
return ret;
}
}
/**
* Finds all permutations of an array
*
* @example
* var arr = [1,2,3];
* comb.array.permutations(arr) => [[ 1, 2, 3 ],[ 1, 3, 2 ],[ 2, 3, 1 ],
* [ 2, 1, 3 ],[ 3, 1, 2 ],[ 3, 2, 1 ]]
* comb.array.permutations(arr, 2) => [[ 1, 2],[ 1, 3],[ 2, 3],[ 2, 1],[ 3, 1],[ 3, 2]]
* comb.array.permutations(arr, 1) => [[1],[2],[3]]
* comb.array.permutations(arr, 0) => [[]]
* comb.array.permutations(arr, 4) => []
*
* @param {Array} arr the array to permute.
* @param {Number} length the number of elements to permute.
* @static
* @memberOf comb.array
*/
- 1
function permutations(arr, length) {
- 15
var ret = [];
- 15
if (isArray(arr)) {
- 15
var copy = arr.slice(0);
- 15
if (typeof length !== "number") {
- 3
length = arr.length;
}
- 15
if (!length) {
- 3
ret = [
[]
];
- 12
} else if (length <= arr.length) {
- 9
ret = reduce(arr, function (a, b, i) {
- 27
var ret;
- 27
if (length > 1) {
- 18
ret = permute(b, rotate(copy, i).slice(1), length);
} else {
- 9
ret = [
[b]
];
}
- 27
return a.concat(ret);
}, []);
}
}
- 15
return ret;
}
/**
* Zips to arrays together
*
* @example
* var a = [ 4, 5, 6 ], b = [ 7, 8, 9 ]
* comb.array.zip([1], [2], [3]) => [[ 1, 2, 3 ]]);
* comb.array.zip([1,2], [2], [3]) => [[ 1, 2, 3 ],[2, null, null]]
* comb.array.zip([1,2,3], a, b) => [[1, 4, 7],[2, 5, 8],[3, 6, 9]]
* comb.array.zip([1,2], a, b) => [[1, 4, 7],[2, 5, 8]]
* comb.array.zip(a, [1,2], [8]) => [[4,1,8],[5,2,null],[6,null,null]]
*
* @param arrays variable number of arrays to zip together
*
* @static
* @memberOf comb.array
*/
- 1
function zip() {
- 11
var ret = [];
- 11
var arrs = argsToArray(arguments);
- 11
if (arrs.length > 1) {
- 11
var arr1 = arrs.shift();
- 11
if (isArray(arr1)) {
- 11
ret = reduce(arr1, function (a, b, i) {
- 38
var curr = [b];
- 38
for (var j = 0; j < arrs.length; j++) {
- 76
var currArr = arrs[j];
- 76
if (isArray(currArr) && !misc.isUndefined(currArr[i])) {
- 66
curr.push(currArr[i]);
} else {
- 10
curr.push(null);
}
}
- 38
a.push(curr);
- 38
return a;
}, []);
}
}
- 11
return ret;
}
/**
* Transposes an array of arrays
* @example
*
* comb.array.transpose([[1,2,3], [4,5,6]]) => [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
* comb.array.transpose([[1,2], [3,4], [5,6]]) => [ [ 1, 3, 5 ], [ 2, 4, 6 ] ]
* comb.array.transpose([[1], [3,4], [5,6]]) => [[1]])
*
* @param [Array[Array[]]] arr Array of arrays
*
* @static
* @memberOf comb.array
*/
- 1
function transpose(arr) {
- 9
var ret = [];
- 9
if (isArray(arr) && arr.length) {
- 9
var last;
- 9
forEach(arr, function (a) {
- 24
if (isArray(a) && (!last || a.length === last.length)) {
- 18
forEach(a, function (b, i) {
- 39
if (!ret[i]) {
- 18
ret[i] = [];
}
- 39
ret[i].push(b);
});
- 18
last = a;
}
});
}
- 9
return ret;
}
/**
* Retrieves values at specified indexes in the array
*
* @example
*
* var arr =["a", "b", "c", "d"]
* comb.array.valuesAt(arr, 1,2,3) => ["b", "c", "d"];
* comb.array.valuesAt(arr, 1,2,3, 4) => ["b", "c", "d", null];
* comb.array.valuesAt(arr, 0,3) => ["a", "d"];
*
* @param {Array} arr the array to retrieve values from
* @param {Number} indexes variable number of indexes to retrieve
*
* @static
* @memberOf comb.array
*/
- 1
function valuesAt(arr, indexes) {
- 9
var ret = [];
- 9
indexes = argsToArray(arguments);
- 9
arr = indexes.shift();
- 9
var l = arr.length;
- 9
if (isArray(arr) && indexes.length) {
- 9
for (var i = 0; i < indexes.length; i++) {
- 27
ret.push(arr[indexes[i]] || null);
}
}
- 9
return ret;
}
/**
* Union a variable number of arrays together
*
* @example
*
* comb.array.union(['a','b','c'], ['b','c', 'd']) => ["a", "b", "c", "d"]
* comb.array.union(["a"], ["b"], ["c"], ["d"], ["c"]) => ["a", "b", "c", "d"]
*
* @param arrs variable number of arrays to union
*
* @static
* @memberOf comb.array
*/
- 1
function union() {
- 6
var ret = [];
- 6
var arrs = argsToArray(arguments);
- 6
if (arrs.length > 1) {
- 6
ret = removeDuplicates(reduce(arrs, function (a, b) {
- 21
return a.concat(b);
}, []));
}
- 6
return ret;
}
/**
* Finds the intersection of arrays
* NOTE : this function accepts an arbitrary number of arrays
*
* @example
* comb.array.intersect([1,2], [2,3], [2,3,5]) => [2]
* comb.array.intersect([1,2,3], [2,3,4,5], [2,3,5]) => [2,3]
* comb.array.intersect([1,2,3,4], [2,3,4,5], [2,3,4,5]) => [2,3,4]
* comb.array.intersect([1,2,3,4,5], [1,2,3,4,5], [1,2,3]) => [1,2,3]
* comb.array.intersect([[1,2,3,4,5],[1,2,3,4,5],[1,2,3]]) => [1,2,3]
*
* @param {Array} a
* @param {Array} b
*
* @static
* @memberOf comb.array
*/
- 1
function intersect(a, b) {
- 25
var collect = [], set;
- 25
var args = argsToArray(arguments);
- 25
if (args.length > 1) {
//assume we are intersections all the lists in the array
- 23
set = args;
} else {
- 2
set = args[0];
}
- 25
if (isArray(set)) {
- 25
var x = set.shift();
- 25
collect = reduce(set, function (a, b) {
- 40
return intersection(a, b);
}, x);
}
- 25
return removeDuplicates(collect);
}
/**
* Finds the powerset of an array
*
* @example
*
* comb.array.powerSet([1,2]) => [
* [],
* [ 1 ],
* [ 2 ],
* [ 1, 2 ]
* ]
* comb.array.powerSet([1,2,3]) => [
* [],
* [ 1 ],
* [ 2 ],
* [ 1, 2 ],
* [ 3 ],
* [ 1, 3 ],
* [ 2, 3 ],
* [ 1, 2, 3 ]
* ]
* comb.array.powerSet([1,2,3,4]) => [
* [],
* [ 1 ],
* [ 2 ],
* [ 1, 2 ],
* [ 3 ],
* [ 1, 3 ],
* [ 2, 3 ],
* [ 1, 2, 3 ],
* [ 4 ],
* [ 1, 4 ],
* [ 2, 4 ],
* [ 1, 2, 4 ],
* [ 3, 4 ],
* [ 1, 3, 4 ],
* [ 2, 3, 4 ],
* [ 1, 2, 3, 4 ]
* ]
*
* @param {Array} arr the array to find the powerset of
*
* @static
* @memberOf comb.array
*/
- 1
function powerSet(arr) {
- 9
var ret = [];
- 9
if (isArray(arr) && arr.length) {
- 9
ret = reduce(arr, function (a, b) {
- 27
var ret = map(a, function (c) {
- 75
return c.concat(b);
});
- 27
return a.concat(ret);
}, [
[]
]);
}
- 9
return ret;
}
/**
* Find the cartesian product of two arrays
*
* @example
*
* comb.array.cartesian([1,2], [2,3]) => [
* [1,2],
* [1,3],
* [2,2],
* [2,3]
* ]
* comb.array.cartesian([1,2], [2,3,4]) => [
* [1,2],
* [1,3],
* [1,4] ,
* [2,2],
* [2,3],
* [2,4]
* ]
* comb.array.cartesian([1,2,3], [2,3,4]) => [
* [1,2],
* [1,3],
* [1,4] ,
* [2,2],
* [2,3],
* [2,4] ,
* [3,2],
* [3,3],
* [3,4]
* ]
*
* @param {Array} a
* @param {Array} b
*
* @static
* @memberOf comb.array
*/
- 1
function cartesian(a, b) {
- 30
var ret = [];
- 30
if (isArray(a) && isArray(b) && a.length && b.length) {
- 21
ret = cross(a[0], b).concat(cartesian(a.slice(1), b));
}
- 30
return ret;
}
/**
* Compacts an array removing null or undefined objects from the array.
*
* @example
*
* var x;
* comb.array.compact([1,null,null,x,2]) => [1,2]
* comb.array.compact([1,2]) => [1,2]
*
* @param {Array} arr
* @static
* @memberOf comb.array
*/
- 1
function compact(arr) {
- 16
var ret = [];
- 16
if (isArray(arr) && arr.length) {
- 16
ret = filter(arr, function (item) {
- 31
return !misc.isUndefinedOrNull(item);
});
}
- 16
return ret;
}
/**
* Creates a new array that is the result of the array concated the number of
* times. If times is not specified or it equals 0 then it defaults to 1.
* @param {Array} arr the array to multiply.
* @param {Number} [times=1] the number of times to multiple the array.
* @return {Array} a new array that is the result of the array multiplied the number of times specified.
*
* @static
* @memberOf comb.array
*/
- 1
function multiply(arr, times) {
- 12
times = number.isNumber(times) ? times : 1;
- 12
if (!times) {
//make sure times is greater than zero if it is zero then dont multiply it
- 3
times = 1;
}
- 12
arr = toArray(arr || []);
- 12
var ret = [], i = 0;
- 12
while (++i <= times) {
- 15
ret = ret.concat(arr);
}
- 12
return ret;
}
/**
* Flatten multiple arrays into a single array
*
* @example
*
* comb.array.flatten([1,2], [2,3], [3,4]) => [1,2,2,3,3,4]
* comb.array.flatten([1,"A"], [2,"B"], [3,"C"]) => [1,"A",2,"B",3,"C"]
*
* @param array
*
* @static
* @memberOf comb.array
*/
- 1
function flatten(arr) {
- 81
var set;
- 81
var args = argsToArray(arguments);
- 81
if (args.length > 1) {
//assume we are intersections all the lists in the array
- 10
set = args;
} else {
- 71
set = toArray(arr);
}
- 81
return reduce(set, function (a, b) {
- 137
return a.concat(b);
}, []);
}
/**
* Plucks values from an array. Effectevily the same as using a array.map implementation. However the porperty specified supports
* a "dot" notation to access nested properties.
*
* @example
*
* var arr = [
* {name:{first:"Fred", last:"Jones"}, age:50, roles:["a", "b", "c"]},
* {name:{first:"Bob", last:"Yukon"}, age:40, roles:["b", "c"]},
* {name:{first:"Alice", last:"Palace"}, age:35, roles:["c"]},
* {name:{first:"Johnny", last:"P."}, age:56, roles:[]}
* ];
* console.log(comb.array.pluck(arr, "name.first")); //["Fred", "Bob", "Alice", "Johnny"]
* console.log(comb.array.pluck(arr, "age")); //[50, 40, 35, 56]
* console.log(comb.array.pluck(arr, "roles.length")); //[3, 2, 1, 0]
* console.log(comb.array.pluck(arr, "roles.0")); //["a", "b", "c", undefined]
*
* @param {Array} arr the array to pluck values from
* @param {String} prop the property to retrieve from each item in the array
* @return {Array} an array containing the plucked properties.
*
* @static
* @memberOf comb.array
*/
- 1
function pluck(arr, prop) {
- 7
prop = prop.split(".");
- 7
var result = arr.slice(0);
- 7
forEach(prop, function (prop) {
- 13
var exec = prop.match(/(\w+)\(\)$/);
- 13
result = map(result, function (item) {
- 52
return exec ? item[exec[1]]() : item[prop];
});
});
- 7
return result;
}
/**
* Invokes the method specified in the scope of each item in the array. If you supply addional arguments they will
* be applied to the function.
*
* ```
*
* function person(name, age){
* return {
* getName : function(){
* return name;
* },
* setName : function(newName){
* name = newName;
* },
*
* getOlder : function(){
* age++;
* return this;
* },
*
* getAge : function(){
* return age;
* }
* };
* }
*
* var arr = [person("Bob", 40), person("Alice", 35), person("Fred", 50), person("Johnny", 56)];
*
* console.log(comb.array.invoke(arr, "getName")); //["Bob", "Alice", "Fred", "Johnny"]
*
* console.log(comb.array(arr).invoke("getOlder").invoke("getAge")); //[41, 36, 51, 57];
*
* ```
*
* @param {Array} arr the array to iterate and invoke the functions on
* @param {String|Function} func the function to invoke, if it is a string then the function will be looked up on the
* each item in the array and invoked
* @param [args=null] variable number of arguments to apply to the function
* @return {Array} the return values of the functions invoked.
*
* @static
* @memberOf comb.array
*/
- 1
function invoke(arr, func, args) {
- 8
args = argsToArray(arguments, 2);
- 8
return map(arr, function (item) {
- 32
var exec = isString(func) ? item[func] : func;
- 32
return exec.apply(item, args);
});
}
/**
* Paritition an array.
*
* ```
* var arr = [1,2,3,4,5];
*
* comb.array.partition(arr, 1); //[[1], [2], [3], [4], [5]]
* comb.array.partition(arr, 2); //[[1,2], [3,4], [5]]
* comb.array.partition(arr, 3); //[[1,2,3], [4,5]]
*
* comb.array.partition(arr); //[[1, 2, 3, 4, 5]]
* comb.array.partition(arr, 0); //[[1, 2, 3, 4, 5]]
*
*
*
* ```
*
* @param array
* @param partitionSize
* @returns {Array}
*
* @static
* @memberOf comb.array
*/
- 1
function partition(array, partitionSize) {
- 14
partitionSize = partitionSize || array.length;
- 14
var ret = [];
- 14
for (var i = 0, l = array.length; i < l; i += partitionSize) {
- 30
ret.push(array.slice(i, i + partitionSize));
}
- 14
return ret;
}
- 1
var comb = exports;
/**
* @namespace Utilities for working with arrays.
*
* The `comb.array` namespace can be used to decorate arrays with additional chainable funcitonality.
*
* ```
*
* var arr = comb.array([1,3,2,5,4,6]);
* console.log(arr.sum()) //21
* console.log(arr.sort()) //[1,2,3,4,5,6]
* console.log(arr.min()) //[1]
* console.log(arr.max()) [6]
*
* ```
*
* @function
* @ignoreCode
*/
- 1
comb.array = {
toArray: toArray,
sum: sum,
avg: avg,
sort: sort,
min: min,
max: max,
difference: difference,
removeDuplicates: removeDuplicates,
unique: unique,
rotate: rotate,
permutations: permutations,
zip: zip,
transpose: transpose,
valuesAt: valuesAt,
union: union,
intersect: intersect,
powerSet: powerSet,
cartesian: cartesian,
compact: compact,
multiply: multiply,
flatten: flatten,
pluck: pluck,
invoke: invoke,
forEach: forEach,
map: map,
filter: filter,
reduce: reduce,
reduceRight: reduceRight,
some: some,
every: every,
indexOf: indexOf,
lastIndexOf: lastIndexOf,
partition: partition
};
base/broadcast.js
|
Coverage100.00
SLOC171
LOC63
Missed0
|
- 1
var func = require("./functions"),
obj = require("./object");
- 1
var comb = exports;
- 1
var wrapper = function() {
- 8
return function() {
- 31
var c = arguments.callee, listeners = c.__listeners, func = c.func, r;
- 31
if (func) {
- 31
r = func.apply(this, arguments);
}
- 31
for (var i = 0; i < listeners.length; i++) {
- 39
var lis = listeners[i];
- 39
if (lis) {
- 30
lis.apply(this, arguments);
}
}
- 31
return r;
}
};
- 1
var listeners = {};
- 1
obj.merge(comb, {
/**@lends comb*/
/**
* Disconnects a listener to a function
* @param {handle} A handle returned from comb.connect
*/
disconnect : function(handle) {
- 10
if (handle && handle.length == 3) {
- 9
var obj = handle[0], method = handle[1], cb = handle[2];
- 9
if (typeof method != "string") throw "comb.disconnect : When calling disconnect the method must be string";
- 9
var scope = obj || global, ls;
- 9
if (typeof scope[method] == "function") {
- 8
ls = scope[method].__listeners;
- 8
if (ls && cb-- > 0) {
//we dont want to splice it because our indexing will get off
- 8
ls[cb] = null;
}
} else {
- 1
throw new Error("unknown method " + method + " in object " + obj);
}
} else {
- 1
throw "comb.disconnect : invalid handle"
}
},
/**
* Function to listen when other functions are called
*
* @example
*
* comb.connect(obj, "event", myfunc);
* comb.connect(obj, "event", "log", console);
*
* @param {Object} obj the object in which the method you are connecting to resides
* @param {String} method the name of the method to connect to
* @param {Function} cb the function to callback
* @param {Object} [scope] the scope to call the specified cb in
*
* @returns {Array} handle to pass to {@link comb.disconnect}
*/
connect : function(obj, method, cb, scope) {
- 14
var index;
- 14
if (typeof method != "string") throw new Error("When calling connect the method must be string");
- 14
if (!func.isFunction(cb)) throw new Error("When calling connect callback must be a string");
- 14
var scope = obj || global, listeners, newMethod;
- 14
if (typeof scope[method] == "function") {
- 13
listeners = scope[method].__listeners;
- 13
if (!listeners) {
- 8
newMethod = wrapper();
- 8
newMethod.func = obj[method];
- 8
listeners = (newMethod.__listeners = []);
- 8
scope[method] = newMethod;
}
- 13
index = listeners.push(cb);
} else {
- 1
throw new Error("unknow method " + method + " in object " + obj);
}
- 13
return [obj, method, index];
},
/**
* Broadcasts an event to all listeners
* NOTE : the function takes a variable number of arguments
* i.e. all arguments after the topic will be passed to the listeners
*
* @example
*
*
* comb.broadcast("hello", "hello world");
* //the args "hello" and "world" will be passed to any listener of the topic
* //"hello"
* comb.broadcast("hello", "hello", "world");
*
* @param {String} topic the topic to brodcast
* @param params the information to bradcast
*/
broadcast : function() {
- 4
var args = Array.prototype.slice.call(arguments);
- 4
var topic = args.splice(0, 1)[0];
- 4
if (topic) {
- 4
var list = listeners[topic];
- 4
if (list) {
- 4
for (var i = list.length - 1; i >= 0; i--) {
- 4
var han = list[i], cb = han.cb;
- 4
if (cb) {
- 4
cb.apply(this, args);
}
}
}
}
},
/**
* Listen for the broadcast of certain events
*
* @example
* comb.listen("hello", function(arg1, arg2){
* console.log(arg1);
* console.log(arg2);
* });
*
* @param {String} topic the topic to listen for
* @param {Function} callback the funciton to call when the topic is published
*
* @returns a handle to pass to {@link comb.unListen}
*/
listen : function(topic, callback) {
- 3
if (!func.isFunction(callback)) throw new Error("callback must be a function");
- 3
var handle = {
topic : topic,
cb : callback,
pos : null
};
- 3
var list = listeners[topic];
- 3
if (!list) {
- 3
list = (listeners[topic] = []);
}
- 3
list.push(handle);
- 3
handle.pos = list.length - 1;
- 3
return handle;
},
/**
* Disconnects a listener
*
* @param handle a handle returned from {@link comb.listen}
*/
unListen : function(handle) {
- 2
if (handle) {
- 2
var topic = handle.topic, list = listeners[topic];
- 2
if (list) {
- 2
for (var i = list.length - 1; i >= 0; i--) {
- 2
if (list[i] == handle) {
- 2
list.splice(i, 1);
}
}
- 2
if (!list.length) {
- 2
delete listeners[topic];
}
}
}
}
});
base/characters.js
|
Coverage100.00
SLOC762
LOC2
Missed0
|
- 1
var comb = exports;
/**@namespace comb characters*/
- 1
comb.characters = {
/**@lends comb.characters*/
/**
* âº
*/
SMILEY: "âº",
/**
* â»
*/
SOLID_SMILEY: "â»",
/**
* â¥
*/
HEART: "â¥",
/**
* â¦
*/
DIAMOND: "â¦",
/**
* â£
*/
CLOVE: "â£",
/**
* â
*/
SPADE: "â ",
/**
* â¢
*/
DOT: "â¢",
/**
* â
*/
SQUARE_CIRCLE: "â",
/**
* â
*/
CIRCLE: "â",
/**
* â
*/
FILLED_SQUARE_CIRCLE: "â",
/**
* â
*/
MALE: "â",
/**
* â
*/
FEMALE: "â",
/**
* âª
*/
EIGHT_NOTE: "âª",
/**
* â«
*/
DOUBLE_EIGHT_NOTE: "â«",
/**
* â¼
*/
SUN: "â¼",
/**
* âº
*/
PLAY: "âº",
/**
* â
*/
REWIND: "â",
/**
* â
*/
UP_DOWN: "â",
/**
* ¶
*/
PILCROW: "¶",
/**
* §
*/
SECTION: "§",
/**
* â¬
*/
THICK_MINUS: "â¬",
/**
* â¨
*/
SMALL_UP_DOWN: "â¨",
/**
* â
*/
UP_ARROW: "â",
/**
* â
*/
DOWN_ARROW: "â",
/**
* â
*/
RIGHT_ARROW: "â",
/**
* â
*/
LEFT_ARROW: "â",
/**
* â
*/
RIGHT_ANGLE: "â",
/**
* â
*/
LEFT_RIGHT_ARROW: "â",
/**
* â²
*/
TRIANGLE: "â²",
/**
* â¼
*/
DOWN_TRIANGLE: "â¼",
/**
* â
*/
HOUSE: "â",
/**
* Ã
*/
C_CEDILLA: "Ã",
/**
* ü
*/
U_UMLAUT: "ü",
/**
* é
*/
E_ACCENT: "é",
/**
* â
*/
A_LOWER_CIRCUMFLEX: "â",
/**
* ä
*/
A_LOWER_UMLAUT: "ä",
/**
* Ã
*/
A_LOWER_GRAVE_ACCENT: "Ã ",
/**
* å
*/
A_LOWER_CIRCLE_OVER: "Ã¥",
/**
* ç
*/
C_LOWER_CIRCUMFLEX: "ç",
/**
* ê
*/
E_LOWER_CIRCUMFLEX: "ê",
/**
* ë
*/
E_LOWER_UMLAUT: "ë",
/**
* è
*/
E_LOWER_GRAVE_ACCENT: "è",
/**
* ï
*/
I_LOWER_UMLAUT: "ï",
/**
* î
*/
I_LOWER_CIRCUMFLEX: "î",
/**
* ì
*/
I_LOWER_GRAVE_ACCENT: "ì",
/**
* Ã
*/
A_UPPER_UMLAUT: "Ã",
/**
* Ã
*/
A_UPPER_CIRCLE: "Ã ",
/**
* Ã
*/
E_UPPER_ACCENT: "Ã",
/**
* æ
*/
A_E_LOWER: "æ",
/**
* Ã
*/
A_E_UPPER: "Ã",
/**
* ô
*/
O_LOWER_CIRCUMFLEX: "ô",
/**
* ö
*/
O_LOWER_UMLAUT: "ö",
/**
* ò
*/
O_LOWER_GRAVE_ACCENT: "ò",
/**
* û
*/
U_LOWER_CIRCUMFLEX: "û",
/**
* ù
*/
U_LOWER_GRAVE_ACCENT: "ù",
/**
* ÿ
*/
Y_LOWER_UMLAUT: "ÿ",
/**
* Ã
*/
O_UPPER_UMLAUT: "Ã",
/**
* Ã
*/
U_UPPER_UMLAUT: "Ã",
/**
* ¢
*/
CENTS: "¢",
/**
* £
*/
POUND: "£",
/**
* ¥
*/
YEN: "Â¥",
/**
* ¤
*/
CURRENCY: "¤",
/**
* â§
*/
PTS: "â§",
/**
* Æ
*/
FUNCTION: "Æ",
/**
* á
*/
A_LOWER_ACCENT: "á",
/**
* Ã
*/
I_LOWER_ACCENT: "Ã",
/**
* ó
*/
O_LOWER_ACCENT: "ó",
/**
* ú
*/
U_LOWER_ACCENT: "ú",
/**
* ñ
*/
N_LOWER_TILDE: "ñ",
/**
* Ã
*/
N_UPPER_TILDE: "Ã",
/**
* ª
*/
A_SUPER: "ª",
/**
* º
*/
O_SUPER: "º",
/**
* ¿
*/
UPSIDEDOWN_QUESTION: "¿",
/**
* â
*/
SIDEWAYS_L: "â",
/**
* ¬
*/
NEGATION: "¬",
/**
* ½
*/
ONE_HALF: "½",
/**
* ¼
*/
ONE_FOURTH: "¼",
/**
* ¡
*/
UPSIDEDOWN_EXCLAMATION: "¡",
/**
* «
*/
DOUBLE_LEFT: "«",
/**
* »
*/
DOUBLE_RIGHT: "»",
/**
* â
*/
LIGHT_SHADED_BOX: "â",
/**
* â
*/
MEDIUM_SHADED_BOX: "â",
/**
* â
*/
DARK_SHADED_BOX: "â",
/**
* â
*/
VERTICAL_LINE: "â",
/**
* â¤
*/
MAZE__SINGLE_RIGHT_T: "â¤",
/**
* â
*/
MAZE_SINGLE_RIGHT_TOP: "â",
/**
* â
*/
MAZE_SINGLE_RIGHT_BOTTOM_SMALL: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_TOP_SMALL: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_BOTTOM_SMALL: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_T: "â",
/**
* â´
*/
MAZE_SINGLE_BOTTOM_T: "â´",
/**
* â¬
*/
MAZE_SINGLE_TOP_T: "â¬",
/**
* â¼
*/
MAZE_SINGLE_CENTER: "â¼",
/**
* â
*/
MAZE_SINGLE_HORIZONTAL_LINE: "â",
/**
* â¡
*/
MAZE_SINGLE_RIGHT_DOUBLECENTER_T: "â¡",
/**
* â
*/
MAZE_SINGLE_RIGHT_DOUBLE_BL: "â",
/**
* â¢
*/
MAZE_SINGLE_RIGHT_DOUBLE_T: "â¢",
/**
* â
*/
MAZE_SINGLE_RIGHT_DOUBLEBOTTOM_TOP: "â",
/**
* â
*/
MAZE_SINGLE_RIGHT_DOUBLELEFT_TOP: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_DOUBLE_T: "â",
/**
* â§
*/
MAZE_SINGLE_BOTTOM_DOUBLE_T: "â§",
/**
* â¤
*/
MAZE_SINGLE_TOP_DOUBLE_T: "â¤",
/**
* â¥
*/
MAZE_SINGLE_TOP_DOUBLECENTER_T: "â¥",
/**
* â¨
*/
MAZE_SINGLE_BOTTOM_DOUBLECENTER_T: "â¨",
/**
* â
*/
MAZE_SINGLE_LEFT_DOUBLERIGHT_BOTTOM: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_DOUBLERIGHT_TOP: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_DOUBLEBOTTOM_TOP: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_DOUBLETOP_BOTTOM: "â",
/**
* Î
*/
MAZE_SINGLE_LEFT_TOP: "Î",
/**
* â
*/
MAZE_SINGLE_RIGHT_BOTTOM: "â",
/**
* â
*/
MAZE_SINGLE_LEFT_CENTER: "â",
/**
* â«
*/
MAZE_SINGLE_DOUBLECENTER_CENTER: "â«",
/**
* âª
*/
MAZE_SINGLE_DOUBLECROSS_CENTER: "âª",
/**
* â£
*/
MAZE_DOUBLE_LEFT_CENTER: "â£",
/**
* â
*/
MAZE_DOUBLE_VERTICAL: "â",
/**
* â
*/
MAZE_DOUBLE_RIGHT_TOP: "â",
/**
* â
*/
MAZE_DOUBLE_RIGHT_BOTTOM: "â",
/**
* â
*/
MAZE_DOUBLE_LEFT_BOTTOM: "â",
/**
* â
*/
MAZE_DOUBLE_LEFT_TOP: "â",
/**
* â©
*/
MAZE_DOUBLE_BOTTOM_T: "â©",
/**
* â¦
*/
MAZE_DOUBLE_TOP_T: "â¦",
/**
* â
*/
MAZE_DOUBLE_LEFT_T: "â ",
/**
* â
*/
MAZE_DOUBLE_HORIZONTAL: "â",
/**
* â¬
*/
MAZE_DOUBLE_CROSS: "â¬",
/**
* â
*/
SOLID_RECTANGLE: "â",
/**
* â
*/
THICK_LEFT_VERTICAL: "â",
/**
* â
*/
THICK_RIGHT_VERTICAL: "â",
/**
* â
*/
SOLID_SMALL_RECTANGLE_BOTTOM: "â",
/**
* â
*/
SOLID_SMALL_RECTANGLE_TOP: "â",
/**
* Φ
*/
PHI_UPPER: "Φ",
/**
* â
*/
INFINITY: "â",
/**
* â©
*/
INTERSECTION: "â©",
/**
* â¡
*/
DEFINITION: "â¡",
/**
* ±
*/
PLUS_MINUS: "±",
/**
* â¥
*/
GT_EQ: "â¥",
/**
* â¤
*/
LT_EQ: "â¤",
/**
* â
*/
THEREFORE: "â ",
/**
* âµ
*/
SINCE: "âµ",
/**
* â
*/
DOESNOT_EXIST: "â",
/**
* â
*/
EXISTS: "â",
/**
* â
*/
FOR_ALL: "â",
/**
* â
*/
EXCLUSIVE_OR: "â",
/**
* â¡
*/
BECAUSE: "â¡",
/**
* ÷
*/
DIVIDE: "÷",
/**
* â
*/
APPROX: "â",
/**
* °
*/
DEGREE: "°",
/**
* â
*/
BOLD_DOT: "â",
/**
* ·
*/
DOT_SMALL: "·",
/**
* â
*/
CHECK: "â",
/**
* â
*/
ITALIC_X: "â",
/**
* â¿
*/
SUPER_N: "â¿",
/**
* ²
*/
SQUARED: "²",
/**
* ³
*/
CUBED: "³",
/**
* â
*/
SOLID_BOX: "â ",
/**
* â°
*/
PERMILE: "â°",
/**
* ®
*/
REGISTERED_TM: "®",
/**
* ©
*/
COPYRIGHT: "©",
/**
* â¢
*/
TRADEMARK: "â¢",
/**
* β
*/
BETA: "β",
/**
* γ
*/
GAMMA: "γ",
/**
* ζ
*/
ZETA: "ζ",
/**
* η
*/
ETA: "η",
/**
* ι
*/
IOTA: "ι",
/**
* κ
*/
KAPPA: "κ",
/**
* λ
*/
LAMBDA: "λ",
/**
* ν
*/
NU: "ν",
/**
* ξ
*/
XI: "ξ",
/**
* ο
*/
OMICRON: "ο",
/**
* Ï
*/
RHO: "Ï",
/**
* Ï
*/
UPSILON: "Ï ",
/**
* Ï
*/
CHI_LOWER: "Ï",
/**
* Ï
*/
CHI_UPPER: "Ï",
/**
* Ï
*/
PSI: "Ï",
/**
* α
*/
ALPHA: "α",
/**
* Ã
*/
ESZETT: "Ã",
/**
* Ï
*/
PI: "Ï",
/**
* Σ
*/
SIGMA_UPPER: "Σ",
/**
* Ï
*/
SIGMA_LOWER: "Ï",
/**
* µ
*/
MU: "µ",
/**
* Ï
*/
TAU: "Ï",
/**
* Î
*/
THETA: "Î",
/**
* Ω
*/
OMEGA: "Ω",
/**
* δ
*/
DELTA: "δ",
/**
* Ï
*/
PHI_LOWER: "Ï",
/**
* ε
*/
EPSILON: "ε"
};
base/date/transforms.js
|
Coverage100.00
SLOC148
LOC75
Missed0
|
- 1
var floor = Math.floor, round = Math.round, min = Math.min, pow = Math.pow, ceil = Math.ceil, abs = Math.abs;
- 1
var addMap = {
day: function addDay(date, amount) {
- 62
return [amount, "Date", false];
},
weekday: function addWeekday(date, amount) {
// Divide the increment time span into weekspans plus leftover days
// e.g., 8 days is one 5-day weekspan / and two leftover days
// Can't have zero leftover days, so numbers divisible by 5 get
// a days value of 5, and the remaining days make up the number of weeks
- 38
var days, weeks, mod = amount % 5, strt = date.getDay(), adj = 0;
- 38
if (!mod) {
- 12
days = (amount > 0) ? 5 : -5;
- 12
weeks = (amount > 0) ? ((amount - 5) / 5) : ((amount + 5) / 5);
} else {
- 26
days = mod;
- 26
weeks = parseInt(amount / 5, 10);
}
- 38
if (strt === 6 && amount > 0) {
- 4
adj = 1;
- 34
} else if (strt === 0 && amount < 0) {
// Orig date is Sun / negative increment
// Jump back over Sat
- 8
adj = -1;
}
// Get weekday val for the new date
- 38
var trgt = strt + days;
// New date is on Sat or Sun
- 38
if ((trgt === 0 || trgt === 6) || ((trgt > 6 || trgt <= 0) && strt !== 6 && strt !== 0)) {
- 10
adj = (amount > 0) ? 2 : -2;
}
// Increment by number of weeks plus leftover days plus
// weekend adjustments
- 38
return [(7 * weeks) + days + adj, "Date", false];
},
year: function addYear(date, amount) {
- 36
return [amount, "FullYear", true];
},
week: function addWeek(date, amount) {
- 6
return [amount * 7, "Date", false];
},
quarter: function addYear(date, amount) {
- 18
return [amount * 3, "Month", true];
},
month: function addYear(date, amount) {
- 22
return [amount, "Month", true];
}
};
- 1
function addTransform(interval, date, amount) {
- 234
interval = interval.replace(/s$/, "");
- 234
if (addMap.hasOwnProperty(interval)) {
- 182
return addMap[interval](date, amount);
}
- 52
return [amount, "UTC" + interval.charAt(0).toUpperCase() + interval.substring(1) + "s", false];
}
- 1
var differenceMap = {
"quarter": function quarterDifference(date1, date2, utc) {
- 10
var yearDiff = date2.getFullYear() - date1.getFullYear();
- 10
var m1 = date1[utc ? "getUTCMonth" : "getMonth"]();
- 10
var m2 = date2[utc ? "getUTCMonth" : "getMonth"]();
// Figure out which quarter the months are in
- 10
var q1 = floor(m1 / 3) + 1;
- 10
var q2 = floor(m2 / 3) + 1;
// Add quarters for any year difference between the dates
- 10
q2 += (yearDiff * 4);
- 10
return q2 - q1;
},
"weekday": function weekdayDifference(date1, date2, utc) {
- 56
var days = differenceTransform("day", date1, date2, utc), weeks;
- 56
var mod = days % 7;
// Even number of weeks
- 56
if (mod === 0) {
- 14
days = differenceTransform("week", date1, date2, utc) * 5;
} else {
// Weeks plus spare change (< 7 days)
- 42
var adj = 0, aDay = date1[utc ? "getUTCDay" : "getDay"](), bDay = date2[utc ? "getUTCDay" : "getDay"]();
- 42
weeks = parseInt(days / 7, 10);
// Mark the date advanced by the number of
// round weeks (may be zero)
- 42
var dtMark = new Date(date1);
- 42
dtMark.setDate(dtMark[utc ? "getUTCDate" : "getDate"]() + (weeks * 7));
- 42
var dayMark = dtMark[utc ? "getUTCDay" : "getDay"]();
// Spare change days -- 6 or less
- 42
if (days > 0) {
- 24
if (aDay === 6 || bDay === 6) {
- 6
adj = -1;
- 18
} else if (aDay === 0) {
- 8
adj = 0;
- 10
} else if (bDay === 0 || (dayMark + mod) > 5) {
- 4
adj = -2;
}
- 18
} else if (days < 0) {
- 18
if (aDay === 6) {
- 2
adj = 0;
- 16
} else if (aDay === 0 || bDay === 0) {
- 8
adj = 1;
- 8
} else if (bDay === 6 || (dayMark + mod) < 0) {
- 4
adj = 2;
}
}
- 42
days += adj;
- 42
days -= (weeks * 2);
}
- 56
return days;
},
year: function (date1, date2) {
- 16
return date2.getFullYear() - date1.getFullYear();
},
month: function (date1, date2, utc) {
- 10
var m1 = date1[utc ? "getUTCMonth" : "getMonth"]();
- 10
var m2 = date2[utc ? "getUTCMonth" : "getMonth"]();
- 10
return (m2 - m1) + ((date2.getFullYear() - date1.getFullYear()) * 12);
},
week: function (date1, date2, utc) {
- 22
return round(differenceTransform("day", date1, date2, utc) / 7);
},
day: function (date1, date2) {
- 106
return 1.1574074074074074e-8 * (date2.getTime() - date1.getTime());
},
hour: function (date1, date2) {
- 12
return 2.7777777777777776e-7 * (date2.getTime() - date1.getTime());
},
minute: function (date1, date2) {
- 8
return 0.000016666666666666667 * (date2.getTime() - date1.getTime());
},
second: function (date1, date2) {
- 6
return 0.001 * (date2.getTime() - date1.getTime());
},
millisecond: function (date1, date2) {
- 8
return date2.getTime() - date1.getTime();
}
};
- 1
function differenceTransform(interval, date1, date2, utc) {
- 254
interval = interval.replace(/s$/, "");
- 254
return round(differenceMap[interval](date1, date2, utc));
}
- 1
exports.addTransform = addTransform;
- 1
exports.differenceTransform = differenceTransform;
base/index.js
|
Coverage100.00
SLOC13
LOC2
Missed0
|
- 1
var objectBase = require("./object");
- 1
objectBase.merge(exports, objectBase,
require("./broadcast"),
require("./functions"),
require("./string"),
require("./number"),
require("./misc"),
require("./date"),
require("./array"),
require("./regexp"),
require("./inflections"),
require("./characters"));
base/inflections.js
|
Coverage100.00
SLOC215
LOC93
Missed0
|
/*
* A port of the Rails/Sequel inflections class
* http://sequel.rubyforge.org/rdoc/classes/Sequel/Inflections.html
*/
- 1
var array = require("./array").array, misc = require("./misc");
- 1
var comb = exports;
- 1
var CAMELIZE_CONVERT_REGEXP = /_(.)/g;
- 1
var DASH = '-';
- 1
var UNDERSCORE = '_';
- 1
var UNDERSCORE_CONVERT_REGEXP1 = /([A-Z]+)(\d+|[A-Z][a-z])/g;
- 1
var UNDERSCORE_CONVERT_REGEXP2 = /(\d+|[a-z])(\d+|[A-Z])/g;
- 1
var UNDERSCORE_CONVERT_REPLACE = '$1_$2';
- 1
var PLURALS = [], SINGULARS = [], UNCOUNTABLES = [];
- 1
var _plural = function (rule, replacement) {
- 20
PLURALS.unshift([rule, replacement])
};
- 1
var _singular = function (rule, replacement) {
- 23
SINGULARS.unshift([rule, replacement])
};
/**
* Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
# for strings, not regular expressions. You simply pass the irregular in singular and plural form.
#
# Examples:
# irregular 'octopus', 'octopi'
# irregular 'person', 'people'
* @param singular the singular version
* @param plural the plural version
*/
- 1
var _irregular = function (singular, plural) {
- 7
_plural(new RegExp("(" + singular.substr(0, 1) + ")" + singular.substr(1) + "$"), "$1" + plural.substr(1));
- 7
_singular(new RegExp("(" + plural.substr(0, 1) + ")" + plural.substr(1) + "$"), "$1" + singular.substr(1));
};
- 1
var _uncountable = function (words) {
- 1
UNCOUNTABLES.push(misc.argsToArray(arguments))
- 1
UNCOUNTABLES = array.flatten(UNCOUNTABLES);
};
- 1
_plural(/$/, 's');
- 1
_plural(/s$/i, 's');
- 1
_plural(/(alias|(?:stat|octop|vir|b)us)$/i, '$1es');
- 1
_plural(/(buffal|tomat)o$/i, '$1oes');
- 1
_plural(/([ti])um$/i, '$1a');
- 1
_plural(/sis$/i, 'ses');
- 1
_plural(/(?:([^f])fe|([lr])f)$/i, '$1$2ves');
- 1
_plural(/(hive)$/i, '$1s');
- 1
_plural(/([^aeiouy]|qu)y$/i, '$1ies');
- 1
_plural(/(x|ch|ss|sh)$/i, '$1es');
- 1
_plural(/(matr|vert|ind)ix|ex$/i, '$1ices');
- 1
_plural(/([m|l])ouse$/i, '$1ice');
- 1
_plural(/^(ox)$/i, "$1en");
- 1
_singular(/s$/i, '');
- 1
_singular(/([ti])a$/i, '$1um');
- 1
_singular(/(analy|ba|cri|diagno|parenthe|progno|synop|the)ses$/i, '$1sis');
- 1
_singular(/([^f])ves$/i, '$1fe');
- 1
_singular(/([h|t]ive)s$/i, '$1');
- 1
_singular(/([lr])ves$/i, '$1f');
- 1
_singular(/([^aeiouy]|qu)ies$/i, '$1y');
- 1
_singular(/(m)ovies$/i, '$1ovie');
- 1
_singular(/(x|ch|ss|sh)es$/i, '$1');
- 1
_singular(/([m|l])ice$/i, '$1ouse');
- 1
_singular(/buses$/i, 'bus');
- 1
_singular(/oes$/i, 'o');
- 1
_singular(/shoes$/i, 'shoe');
- 1
_singular(/(alias|(?:stat|octop|vir|b)us)es$/i, '$1');
- 1
_singular(/(vert|ind)ices$/i, '$1ex');
- 1
_singular(/matrices$/i, 'matrix');
- 1
_irregular('person', 'people');
- 1
_irregular('man', 'men');
- 1
_irregular('child', 'children');
- 1
_irregular('sex', 'sexes');
- 1
_irregular('move', 'moves');
- 1
_irregular('quiz', 'quizzes');
- 1
_irregular('testis', 'testes');
- 1
_uncountable("equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "news");
- 1
exports.singular = _singular;
- 1
exports.plural = _plural;
- 1
exports.uncountable = _uncountable;
/**
* Converts a string to camelcase
*
* @example
* comb.camelize('hello_world') => helloWorld
* comb.camelize('column_name') => columnName
* comb.camelize('columnName') => columnName
* comb.camelize(null) => null
* comb.camelize() => undefined
*
* @param {String} str the string to camelize
* @memberOf comb
* @returns {String} the camelized version of the string
*/
- 1
comb.camelize = function (str) {
- 14
var ret = str;
- 14
if (!misc.isUndefinedOrNull(str)) {
- 12
ret = str.replace(CAMELIZE_CONVERT_REGEXP, function (a, b) {
- 8
return b.toUpperCase();
});
}
- 14
return ret;
};
/**
* The reverse of camelize. Makes an underscored form from the expression in the string.
*
* @example
* comb.underscore('helloWorld') => hello_world
* comb.underscore('column_name') => column_name
* comb.underscore('columnName') => column_name
* comb.underscore(null) => null
* comb.underscore() => undefined
* @param {String} str The string to underscore
* @memberOf comb
* @returns {String} the underscored version of the string
* */
- 1
comb.underscore = function (str) {
- 12
var ret = str;
- 12
if (!misc.isUndefinedOrNull(str)) {
- 10
ret = str.replace(UNDERSCORE_CONVERT_REGEXP1, UNDERSCORE_CONVERT_REPLACE)
.replace(UNDERSCORE_CONVERT_REGEXP2, UNDERSCORE_CONVERT_REPLACE)
.replace(DASH, UNDERSCORE).toLowerCase();
}
- 12
return ret;
};
/**
* Singularizes and camelizes the string. Also strips out all characters preceding
* and including a period (".").
*
* @example
* comb.classify('egg_and_hams') => "eggAndHam"
* comb.classify('post') => "post"
* comb.classify('schema.post') => "post"
*
* @param {String} str the string to classify
* @memberOf comb
* @returns {String} the classified version of the string
**/
- 1
comb.classify = function (str) {
- 8
var ret = str;
- 8
if (!misc.isUndefinedOrNull(str)) {
- 6
ret = comb.camelize(comb.singularize(str.replace(/.*\./g, '')));
}
- 8
return ret;
};
/**
* Returns the plural form of the word in the string.
*
* @example
* comb.pluralize("post") => "posts"
* comb.pluralize("octopus") => "octopi"
* comb.pluralize("sheep") => "sheep"
* comb.pluralize("words") => "words"
* comb.pluralize("the blue mailman") => "the blue mailmen"
* comb.pluralize("CamelOctopus") => "CamelOctopi"
*
* @param {String} str the string to pluralize
* @memberOf comb
* @returns {String} the pluralized version of the string
**/
- 1
comb.pluralize = function (str) {
- 100
var ret = str;
- 100
if (!misc.isUndefinedOrNull(str)) {
- 98
if (UNCOUNTABLES.indexOf(str) == -1) {
- 96
for (var i in PLURALS) {
- 1282
var s = PLURALS[i], rule = s[0], replacement = s[1];
- 1282
if ((ret = ret.replace(rule, replacement)) != str) {
- 96
break;
}
}
}
}
- 100
return ret;
};
/**
* The reverse of pluralize, returns the singular form of a word in a string.
*
* @example
* comb.singularize("posts") => "post"
* comb.singularize("octopi")=> "octopus"
* comb.singularize("sheep") => "sheep"
* comb.singularize("word") => "word"
* comb.singularize("the blue mailmen") => "the blue mailman"
* comb.singularize("CamelOctopi") => "CamelOctopus"
*
* @param {String} str the string to singularize
* @memberOf comb
* @returns {String} the singularized version of the string
* */
- 1
comb.singularize = function (str) {
- 106
var ret = str;
- 106
if (!misc.isUndefinedOrNull(str)) {
- 104
if (UNCOUNTABLES.indexOf(str) == -1) {
- 102
for (var i in SINGULARS) {
- 1570
var s = SINGULARS[i], rule = s[0], replacement = s[1];
- 1570
if ((ret = ret.replace(rule, replacement)) != str) {
- 98
break;
}
}
}
}
- 106
return ret;
};
base/misc.js
|
Coverage100.00
SLOC187
LOC51
Missed0
|
- 1
var comb = exports,
arraySlice = Array.prototype.slice;
/**
*
* Converts an arguments object to an array
*
* @example
*
* function test(){
* return comb.argsToArray(arguments);
* }
*
* function testSlice(){
* return comb.argsToArray(arguments, 3);
* }
*
* console.log(test(1,2,3)); //[1,2,3]
* console.log(test(1,2,3,4,5,6)); //[4,5,6]
*
* @function
* @param {Arguments} args the arguments object to convert
* @param {Number} [slice=0] the number of arguments to slice.
* @memberOf comb
* @static
* @returns {Array} array version of the arguments object
*/
- 1
function argsToArray(args, slice) {
- 16746
slice = slice || 0;
- 16746
return arraySlice.call(args, slice);
}
/**
* Determines if obj is a boolean
*
* @param {Anything} obj the thing to test if it is a boolean
*
* @returns {Boolean} true if it is a boolean false otherwise
* @memberOf comb
* @static
*/
- 1
function isBoolean(obj) {
- 12270
var undef, type = typeof obj;
- 12270
return obj != undef && type == "boolean" || type == "Boolean";
}
/**
* Determines if obj is undefined
*
* @param {Anything} obj the thing to test if it is undefined
* @returns {Boolean} true if it is undefined false otherwise
* @memberOf comb
* @static
*/
- 1
function isUndefined(obj) {
- 3334
var undef;
- 3334
return obj !== null && obj === undef;
}
/**
* Determins if the obj is not undefined
*
* @param obj the thing to test if it is not undefined
*
* @return {Boolean} true if it is defined false otherwise
* @memberOf comb
* @static
*/
- 1
function isDefined(obj) {
- 12
return !isUndefined(obj);
}
/**
* Determines if obj is undefined or null
*
* @param {Anything} obj the thing to test if it is undefined or null
* @returns {Boolean} true if it is undefined or null false otherwise
* @memberOf comb
* @static
*/
- 1
function isUndefinedOrNull(obj) {
- 3094
return isUndefined(obj) || isNull(obj);
}
/**
* Determines if obj is null
*
* @param {Anything} obj the thing to test if it is null
*
* @returns {Boolean} true if it is null false otherwise
* @memberOf comb
* @static
*/
- 1
function isNull(obj) {
- 3086
var undef;
- 3086
return obj !== undef && obj == null;
}
/**
* Determines if obj is an Arguments object;
*
* @param {Anything} obj the thing to test if it is null
*
* @returns {Boolean} true if it is an Arguments Object false otherwise
* @memberOf comb
* @static
*/
- 1
function isArguments(object) {
- 1257
return !isUndefinedOrNull(object) && Object.prototype.toString.call(object) == '[object Arguments]';
}
- 1
function isInstance(obj, clazz) {
- 1241
if (typeof clazz == "function") {
- 1240
return obj instanceof clazz;
} else {
- 1
return false;
}
}
/**
* Determines if obj is an instance of a particular class
*
* @param {Anything} obj the thing to test if it and instance of a class
* @param {Object} Clazz used to determine if the object is an instance of
*
* @returns {Boolean} true if it is an instance of the clazz false otherwise
* @memberOf comb
* @static
*/
- 1
function isInstanceOf(obj, clazz) {
- 1241
return argsToArray(arguments, 1).some(function (c) {
- 1241
return isInstance(obj, c);
});
}
- 1
(function () {
- 1
var listeners = [];
- 1
var setup = false;
- 1
function setupListener() {
- 13
if (!setup) {
- 1
var orig = process.emit;
- 1
process.emit = function (event) {
- 1
try {
- 1
if (event === 'exit') {
- 1
listeners.forEach(function (cb) {
- 13
cb();
});
}
} finally {
- 1
orig.apply(this, arguments);
}
};
- 1
setup = true;
}
}
/**
* Adds listeners to process.exit without having to change setMaxListeners useful if you
* are writing a library and do not want to change core setting.
*
* @param {Funciton} cb funciton to call when process is exiting
* @memberOf comb
* @static
*/
- 1
function listenForExit(cb) {
- 13
setupListener();
- 13
listeners.push(cb);
}
- 1
comb.listenForExit = listenForExit;
})();
- 1
comb.argsToArray = argsToArray;
- 1
comb.isBoolean = isBoolean;
- 1
comb.isUndefined = isUndefined;
- 1
comb.isDefined = isDefined;
- 1
comb.isUndefinedOrNull = isUndefinedOrNull;
- 1
comb.isNull = isNull;
- 1
comb.isArguments = isArguments;
- 1
comb.isInstanceOf = isInstanceOf;
base/number.js
|
Coverage100.00
SLOC66
LOC10
Missed0
|
- 1
var comb = exports;
/**
* Determines if obj is a number
*
* @param {Anything} obj the thing to test if it is a Number
*
* @returns {Boolean} true if it is a number false otherwise
*/
- 1
comb.isNumber = function(obj) {
- 2827
var undef;
- 2827
return obj !== undef && obj != null && (typeof obj == "number" || obj instanceof Number);
};
/**
* @private
*/
- 1
var round = Math.round, pow = Math.pow;
/**
* @namespace Utilities for numbers
*/
- 1
comb.number = {
/**@lends comb.number*/
/**
* Rounds a number to the specified places.
*
* @example
*
* comb.number.round(10.000009, 2); //10
* comb.number.round(10.000009, 5); //10.00001
* comb.number.round(10.0009, 3); //10.001
* comb.number.round(10.0009, 2); //10
* comb.number.round(10.0009, 3); //10.001
*
* @param {Number} num the number to round.
* @param {Number} places the number of places to round to.
*/
round : function(number, places, increment) {
- 24
increment = increment || 1e-20;
- 24
var factor = 10 / (10 * (increment || 10));
- 24
return (Math.ceil(factor * +number) / factor).toFixed(places) * 1; // Number
},
/**
* Rounds a number to the specified places, rounding up.
*
* @example
*
* comb.number.roundCeil(10.000001, 2); //10.01
* comb.number.roundCeil(10.000002, 5); //10.00001
* comb.number.roundCeil(10.0003, 3); //10.001
* comb.number.roundCeil(10.0004, 2); //10.01
* comb.number.roundCeil(10.0005, 3); //10.001
* comb.number.roundCeil(10.0002, 2); //10.01
*
* @param {Number} num the number to round.
* @param {Number} places the number of places to round to.
*/
roundCeil : function(number, places){
- 12
return Math.ceil(number * Math.pow(10, places))/Math.pow(10, places);
}
};
base/object.js
|
Coverage100.00
SLOC575
LOC162
Missed0
|
- 1
var comb = exports,
misc = require("./misc.js"),
isUndefinedOrNull = misc.isUndefinedOrNull,
isArguments = misc.isArguments,
pSlice = Array.prototype.slice,
pToString = Object.prototype.toString,
_baseArray, _baseString;
- 1
function baseArray() {
- 20
return _baseArray || (_baseArray = require("./array").array);
}
- 1
function baseString() {
- 20
return _baseString || (_baseString = require("./string"));
}
//taken from node js assert.js
//https://github.com/joyent/node/blob/master/lib/assert.js
- 1
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
- 79
if (actual === expected) {
- 6
return true;
- 73
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
- 2
if (actual.length != expected.length) return false;
- 2
for (var i = 0; i < actual.length; i++) {
- 6
if (actual[i] !== expected[i]) return false;
}
- 2
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
- 71
} else if (actual instanceof Date && expected instanceof Date) {
- 4
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
- 67
} else if (actual instanceof RegExp && expected instanceof RegExp) {
- 4
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
- 63
} else if (typeof actual != 'object' && typeof expected != 'object') {
- 23
return actual == expected;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
- 40
return objEquiv(actual, expected);
}
}
- 1
function objEquiv(a, b) {
- 40
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
- 10
return false;
// an identical 'prototype' property.
- 30
if (a.prototype !== b.prototype) return false;
//~~~I've managed to break Object.keys through screwy arguments passing.
// Converting to array solves the problem.
- 30
if (isArguments(a)) {
- 4
if (!isArguments(b)) {
- 2
return false;
}
- 2
a = pSlice.call(a);
- 2
b = pSlice.call(b);
- 2
return _deepEqual(a, b);
}
- 26
try {
- 26
var ka = Object.keys(a),
kb = Object.keys(b),
key, i;
} catch (e) {//happens when one is a string literal and the other isn't
- 2
return false;
}
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
- 24
if (ka.length != kb.length)
- 4
return false;
//the same set of keys (although not necessarily the same order),
- 20
ka.sort();
- 20
kb.sort();
//~~~cheap key test
- 20
for (i = ka.length - 1; i >= 0; i--) {
- 20
if (ka[i] != kb[i])
- 4
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
- 16
for (i = ka.length - 1; i >= 0; i--) {
- 16
key = ka[i];
- 22
if (!_deepEqual(a[key], b[key])) return false;
}
- 10
return true;
}
- 1
function merge(target, source) {
- 468
var name, s;
- 468
for (name in source) {
- 656
s = source[name];
- 656
if (!(name in target) || (target[name] !== s)) {
- 654
target[name] = s;
}
}
- 468
return target;
}
- 1
function deepMerge(target, source) {
- 27
var name, s, t;
- 27
for (name in source) {
- 37
s = source[name], t = target[name];
- 37
if (!_deepEqual(t, s)) {
- 37
if (comb.isHash(t) && comb.isHash(s)) {
- 8
target[name] = deepMerge(t, s);
- 29
} else if (comb.isHash(s)) {
- 8
target[name] = deepMerge({}, s);
} else {
- 21
target[name] = s;
}
}
}
- 27
return target;
}
/**
* Determines if an object is just a hash and not a qualified Object such as Number
*
* @example
* comb.isHash({}) => true
* comb.isHash({1 : 2, a : "b"}) => true
* comb.isHash(new Date()) => false
* comb.isHash(new String()) => false
* comb.isHash(new Number()) => false
* comb.isHash(new Boolean()) => false
* comb.isHash() => false
* comb.isHash("") => false
* comb.isHash(1) => false
* comb.isHash(false) => false
* comb.isHash(true) => false
* @param {Anything} obj the thing to test if it is a hash
*
* @returns {Boolean} true if it is a hash false otherwise
* @memberOf comb
* @static
*/
- 1
function isHash(obj) {
- 327
var ret = comb.isObject(obj);
- 327
return ret && obj.constructor === Object;
}
/**
* Merges objects together
* NOTE: this function takes a variable number of objects to merge
*
* @example
*
* var myObj = {};
* comb.merge(myObj, {test : true});
*
* myObj.test => true
*
* comb.merge(myObj, {test : false}, {test2 : false}, {test3 : "hello", test4 : "world"});
* myObj.test => false
* myObj.test2 => false
* myObj.test3 => "hello"
* myObj.test4 => "world"
*
*
* @param {Object} obj the object to merge into
* @param {Object} props variable number of objects to merge into the obj
*
* @returns {Object} the merged object
* @memberOf comb
* @name merge
* @static
*/
- 1
function combMerge(obj, props) {
- 442
if (!obj) {
- 1
obj = {};
}
- 442
for (var i = 1, l = arguments.length; i < l; i++) {
- 464
merge(obj, arguments[i]);
}
- 442
return obj; // Object
}
- 1
;
/**
* Merges objects together only overriding properties that are different.
* NOTE: this function takes a variable number of objects to merge
*
* @example
*
* var myObj = {my : {cool : {property1 : 1, property2 : 2}}};
* comb.deepMerge(myObj, {my : {cool : {property3 : 3}}});
*
* myObj.my.cool.property1 => 1
* myObj.my.cool.property2 => 2
* myObj.my.cool.property3 => 3
*
*
* @param {Object} obj the object to merge into
* @param {Object} props variable number of objects to merge into the obj
*
* @returns {Object} the merged object
* @memberOf comb
* @name deepMerge
* @static
*/
- 1
function combDeepMerge(obj, props) {
- 5
if (!obj) {
- 1
obj = {};
}
- 5
for (var i = 1, l = arguments.length; i < l; i++) {
- 11
deepMerge(obj, arguments[i]);
}
- 5
return obj; // Object
}
/**
* Extends the prototype of an object if it exists otherwise it extends the object.
*
* @example
*
* var MyObj = function(){};
* MyObj.prototype.test = true;
* comb.extend(MyObj, {test2 : false, test3 : "hello", test4 : "world"});
*
* var myObj = new MyObj();
*
* myObj.test => true
* myObj.test2 => false
* myObj.test3 => "hello"
* myObj.test4 => "world"
*
* var myObj2 = {};
* myObj2.test = true;
* comb.extend(myObj2, {test2 : false, test3 : "hello", test4 : "world"});
*
* myObj2.test => true
* myObj2.test2 => false
* myObj2.test3 => "hello"
* myObj2.test4 => "world"
*
*
* @param {Object} parent the parent object to extend
* @param {Object} extend the extension object to mixin to the parent
*
* @returns {Object} returns the extended object
* @memberOf comb
* @static
*/
- 1
function extend(parent, extend) {
- 4
var proto = parent.prototype || parent;
- 4
merge(proto, extend);
- 4
return parent;
}
/**
* Determines if obj is an object
*
* @param {Anything} obj the thing to test if it is an object
*
* @returns {Boolean} true if it is an object false otherwise
* @memberOf comb
* @static
*/
- 1
function isObject(obj) {
- 4303
var undef;
- 4303
return obj !== null && obj !== undef && typeof obj === "object";
}
/**
* Determines if an object is empty
*
* @example
*
* comb.isEmpty({}) => true
* comb.isEmpty({a : 1}) => false
*
* @param object the object to test
* @returns {Boolean} true if the object is empty;
* @memberOf comb
* @static
*/
- 1
function isEmpty(object) {
- 9
if (comb.isObject(object)) {
- 8
for (var i in object) {
- 4
if (object.hasOwnProperty(i)) {
- 4
return false;
}
}
}
- 5
return true;
}
/**
* Determines if two things are deep equal.
*
* @example
*
* comb.deepEqual({a : 1, b : 2}, {a : 1, b : 2}) => true
* comb.deepEqual({a : 1}, {a : 1, b : 2}) => false
*
* @param o1 the first thing to compare
* @param o3 the second thing to compare
* @return {Boolean}
* @memberOf comb
* @static
*/
- 1
function deepEqual(o1, o2) {
- 24
return _deepEqual(o1, o2);
}
- 1
comb.isHash = isHash;
- 1
comb.isEmpty = isEmpty;
- 1
comb.deepEqual = deepEqual;
- 1
comb.isObject = isObject;
- 1
comb.extend = extend;
- 1
comb.deepMerge = combDeepMerge;
- 1
comb.merge = combMerge;
/**
* Returns a new hash with the specified keys omitted from the hash.
*
* ```
* var obj = {a: "a", b: "b", c: "c"};
*
* //as a function
* comb.hash.omit(obj, ["a", "b"]); //{c: "c"}
* comb.hash.omit(obj, "c"); //{a: "a", b: "b"};
*
* //as a monad
* comb(obj).omit(["a", "b"]); //{c: "c"}
* comb(obj).omit("c"); //{a: "a", b: "b"};
*
* ```
*
* @param {Object} hash The hash to omit values from
* @param {Array|String} omitted the keys to omit.
* @returns {Object} a new Object with the keys omitted
* @memberOf comb.hash
*/
- 1
function omit(hash, omitted) {
- 11
if (!isHash(hash)) {
- 1
throw new TypeError("expected object got ", pToString.call(hash));
}
- 10
if (baseString().isString(omitted)) {
- 2
omitted = [omitted];
}
- 10
var objKeys = baseArray().difference(Object.keys(hash), omitted), key, ret = {};
- 10
for (var i = 0, len = objKeys.length; i < len; ++i) {
- 18
key = objKeys[i];
- 18
ret[key] = hash[key];
}
- 10
return ret;
}
/**
* Returns a new hash with the specified keys omitted from the hash.
*
* ```
* var obj = {a: "a", b: "b", c: "c"};
*
* //as a function
* comb.hash.pick(obj, ["a", "b"]); //{a: "a", b:'b'}
* comb.hash.pick(obj, "c"); //{c: "c"};
*
* //as a monad
* comb(obj).pick(["a", "b"]); //{a: "a", b:'b'}
* comb(obj).pick("c"); //{c: "c"};
*
* ```
*
* @param {Object} hash The hash to pick values from
* @param {Array|String} picked the keys to pick.
* @returns {Object} a new Object with only the keys specified
* @memberOf comb.hash
*/
- 1
function pick(hash, picked) {
- 11
if (!isHash(hash)) {
- 1
throw new TypeError("expected object got ", pToString.call(hash));
}
- 10
if (baseString().isString(picked)) {
- 2
picked = [picked];
}
- 10
var objKeys = baseArray().intersect(Object.keys(hash), picked), key, ret = {};
- 10
for (var i = 0, len = objKeys.length; i < len; ++i) {
- 10
key = objKeys[i];
- 10
ret[key] = hash[key];
}
- 10
return ret;
}
/**
* Loops through each k/v in a hash.
*
* ```
* var obj = {a : "b", c : "d", e : "f"};
* comb(obj).forEach(function(value, key){
* console.log(value, key);
* });
*
* comb.hash.forEach(obj, function(){
* console.log(value, key);
* });
*
* ```
* @param {Object} hash the hash to iterate
* @param {Function} iterator the interator function. Called with (key, value, hash).
* @param {Object} [scope=hash] the scope to invoke the interator in.
* @return {Object} the original hash.
* @memberOf comb.hash
*/
- 1
function forEach(hash, iterator, scope) {
- 6
if (!isHash(hash) || typeof iterator !== "function") {
- 4
throw new TypeError();
}
- 2
var keys = Object.keys(hash), key;
- 2
for (var i = 0, len = keys.length; i < len; ++i) {
- 6
key = keys[i];
- 6
iterator.call(scope || hash, hash[key], key, hash);
}
- 2
return hash;
}
/**
* Filters out key/value pairs in an object. Filters out key/value pairs that return a falsey value from the iterator.
*
* ```
* var obj = {a : "b", c : "d", e : "f"};
* comb(obj).filter(function(value, key){
* return value == "b" || key === "e";
* }); //{a : "b", e : "f"};
*
* comb.hash.filter(obj, function(){
* return value == "b" || key === "e";
* }); //{a : "b", e : "f"};
*
* ```
* @param {Object} hash the hash to filter.
* @param {Function} iterator the interator function. Called with (key, value, hash).
* @param {Object} [scope=hash] the scope to invoke the interator in.
* @return {Object} a new object with the values that returned true..
* @memberOf comb.hash
*/
- 1
function filter(hash, iterator, scope) {
- 6
if (!isHash(hash) || typeof iterator !== "function") {
- 4
throw new TypeError();
}
- 2
var keys = Object.keys(hash), key, value, ret = {};
- 2
for (var i = 0, len = keys.length; i < len; ++i) {
- 6
key = keys[i];
- 6
value = hash[key];
- 6
if (iterator.call(scope || hash, value, key, hash)) {
- 4
ret[key] = value;
}
}
- 2
return ret;
}
/**
* Returns the values of a hash.
*
* ```
* var obj = {a : "b", c : "d", e : "f"};
* comb(obj).values(); //["b", "d", "f"]
*
* comb.hash.values(obj); //["b", "d", "f"]
*
* ```
*
* @param {Object} hash the object to retrieve the values of.
* @return {Array} array of values.
* @memberOf comb.hash
*/
- 1
function values(hash) {
- 5
if (!isHash(hash)) {
- 3
throw new TypeError();
}
- 2
var keys = Object.keys(hash), ret = [];
- 2
for (var i = 0, len = keys.length; i < len; ++i) {
- 6
ret.push(hash[keys[i]]);
}
- 2
return ret;
}
/**
* Returns a new hash that is the invert of the hash.
*
* ```
* var obj = {a : "b", c : "d", e : "f"};
* comb(obj).invert(); //{b : "a", d : "c", f : "e"}
*
* comb.hash.invert(obj); //{b : "a", d : "c", f : "e"}
* ```
*
* @param {Object} hash the hash to invert.
* @return {Object} A new hash that is the invert of hash.
* @memberOf comb.hash
*/
- 1
function invert(hash) {
- 5
if (!isHash(hash)) {
- 3
throw new TypeError();
}
- 2
var keys = Object.keys(hash), key, ret = {};
- 2
for (var i = 0, len = keys.length; i < len; ++i) {
- 6
key = keys[i];
- 6
ret[hash[key]] = key;
}
- 2
return ret;
}
/**
* Converts a hash to an array.
*
* ```
* var obj = {a : "b", c : "d", e : "f"};
* comb(obj).toArray(); //[["a", "b"], ["c", "d"], ["e", "f"]]
*
* comb.hash.toArray(obj); //[["a", "b"], ["c", "d"], ["e", "f"]]
* ```
*
* @param {Object} hash the hash to convert to an array.
* @return {Array} a two dimensional array representing the hash.
* @memberOf comb.hash
*/
- 1
function toArray(hash) {
- 5
if (!isHash(hash)) {
- 3
throw new TypeError();
}
- 2
var keys = Object.keys(hash), key, ret = [];
- 2
for (var i = 0, len = keys.length; i < len; ++i) {
- 6
key = keys[i];
- 6
ret.push([key, hash[key]]);
}
- 2
return ret;
}
/**
* @namespace utilities for working with hases i.e. {}
* @ignoreCode
*/
- 1
comb.hash = {
forEach: forEach,
omit: omit,
pick: pick,
filter: filter,
invert: invert,
values: values,
toArray: toArray
};
base/regexp.js
|
Coverage100.00
SLOC48
LOC11
Missed0
|
- 1
var comb = exports;
/**
* Tests if something is a regular expression.
*
* @example
*
* comb.isRegExp(/hello/); //true
* comb.isRegExp("hello"); //false
*
* @param obj the thing to test.
* @return {Boolean}
* @static
* @memberOf comb
*
*/
- 1
function isRegExp(obj) {
- 13
var undef;
- 13
return obj !== undef && obj != null && (obj instanceof RegExp);
}
- 1
comb.isRexExp = isRegExp;
- 1
comb.isRegExp = isRegExp;
/**
* @namespace Regeular expression utilities
*
*/
- 1
comb.regexp = {
/**@lends comb.regexp*/
/**
* Escapes a string
*
* @param {String} str the string to escape
* @param {String} [except] characters to ignore
*
* @returns {String} the escaped string
*/
escapeString:function (str, except) {
- 46
return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function (ch) {
- 46
if (except && except.indexOf(ch) != -1) {
- 15
return ch;
}
- 31
return "\\" + ch;
}); // String
}
};
collections/AVLTree.js
|
Coverage100.00
SLOC203
LOC100
Missed0
|
- 1
var define = require("../define").define,
Tree = require("./Tree"),
base = require("../base"),
multiply = base.string.multiply;
- 1
var abs = Math.abs;
- 1
var makeNode = function(data) {
- 122
return {
data : data,
balance : 0,
left : null,
right : null
}
};
- 1
var rotateSingle = function(root, dir, otherDir) {
- 80
var save = root[otherDir];
- 80
root[otherDir] = save[dir];
- 80
save[dir] = root;
- 80
return save;
};
- 1
var rotateDouble = function(root, dir, otherDir) {
- 15
root[otherDir] = rotateSingle(root[otherDir], otherDir, dir);
- 15
return rotateSingle(root, dir, otherDir);
};
- 1
var adjustBalance = function(root, dir, bal) {
- 15
var otherDir = dir == "left" ? "right" : "left";
- 15
var n = root[dir], nn = n[otherDir];
- 15
if (nn.balance == 0)
- 11
root.balance = n.balance = 0;
- 4
else if (nn.balance == bal) {
- 2
root.balance = -bal;
- 2
n.balance = 0;
}
else { /* nn.balance == -bal */
- 2
root.balance = 0;
- 2
n.balance = bal;
}
- 15
nn.balance = 0;
};
- 1
var insertAdjustBalance = function(root, dir) {
- 60
var otherDir = dir == "left" ? "right" : "left";
- 60
var n = root[dir];
- 60
var bal = dir == "left" ? -1 : +1;
- 60
if (n.balance == bal) {
- 46
root.balance = n.balance = 0;
- 46
root = rotateSingle(root, otherDir, dir);
}
else {
- 14
adjustBalance(root, dir, bal);
- 14
root = rotateDouble(root, otherDir, dir);
}
- 60
return root;
};
- 1
var removeAdjustBalance = function(root, dir, done) {
- 5
var otherDir = dir == "left" ? "right" : "left";
- 5
var n = root[otherDir];
- 5
var bal = dir == "left" ? -1 : 1;
- 5
if (n.balance == -bal) {
- 1
root.balance = n.balance = 0;
- 1
root = rotateSingle(root, dir, otherDir);
}
- 4
else if (n.balance == bal) {
- 1
adjustBalance(root, otherDir, -bal);
- 1
root = rotateDouble(root, dir, otherDir);
}
else { /* n.balance == 0 */
- 3
root.balance = -bal;
- 3
n.balance = bal;
- 3
root = rotateSingle(root, dir, otherDir);
- 3
done.done = true;
}
- 5
return root;
};
- 1
var insert = function(root, data, done, compare) {
- 472
if (root == null || root == undefined)
- 122
root = makeNode(data);
else {
- 350
var dir = compare(data, root.data) == -1 ? "left" : "right";
- 350
root[dir] = insert(root[dir], data, done, compare);
- 350
if (!done.done) {
/* Update balance factors */
- 255
root.balance += dir == "left" ? -1 : 1;
/* Rebalance as necessary and terminate */
- 255
if (root.balance == 0)
- 21
done.done = true;
- 234
else if (abs(root.balance) > 1) {
- 60
root = insertAdjustBalance(root, dir);
- 60
done.done = true;
}
}
}
- 472
return root;
};
- 1
var remove = function(root, data, done, compare) {
- 57
var dir, cmp, save, b;
- 57
if (root) {
//Remove node
- 57
cmp = compare(data, root.data);
- 57
if (cmp === 0) {
// Unlink and fix parent
- 26
var l = root.left, r = root.right;
- 26
if (!l || !r) {
- 18
dir = !l ? "right" : "left";
- 18
save = root[dir];
- 18
return save;
}
else {
- 8
var heir = l, r;
- 8
while ((r = heir.right) != null) {
- 3
heir = r;
}
- 8
root.data = heir.data;
//reset and start searching
- 8
data = heir.data;
}
}
- 39
dir = compare(root.data, data) == -1 ? "right" : "left";
- 39
root[dir] = remove(root[dir], data, done, compare);
- 39
if (!done.done) {
/* Update balance factors */
- 24
b = (root.balance += (dir == "left" ? 1 : -1));
/* Terminate or rebalance as necessary */
- 24
var a = abs(b);
- 24
if (a === 1)
- 10
done.done = true;
- 14
else if (a > 1)
- 5
root = removeAdjustBalance(root, dir, done);
}
}
- 39
return root;
};
/**
* @ignoreCode
* @class <p>An AVL tree is a self-balancing binary search tree.
* In an AVL tree, the heights of the two child subtrees of any node differ by at most one.
* Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases,
* where n is the number of nodes in the tree prior to the operation.
* Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.</p>
* <p>AVL trees are more rigidly balanced than red-black trees, leading to slower insertion and removal but faster retrieval</p>
*
* <b>Performance</b>
* <table>
* <tr><td></td><td>Best</td><td>Worst</td></tr>
* <tr><td>Space</td><td>O(n)</td><td>O(n)</td></tr>
* <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr>
* <table>
* @name AVLTree
* @augments comb.collections.Tree
* @memberOf comb.collections
*/
- 1
module.exports = exports = define(Tree, {
instance : {
/**@lends comb.collections.AVLTree.prototype*/
insert : function(data) {
- 122
var done = {done : false};
- 122
this.__root = insert(this.__root, data, done, this.compare);
},
remove : function(data) {
- 18
this.__root = remove(this.__root, data, {done : false}, this.compare);
},
__printNode : function(node, level) {
- 37
var str = [];
- 37
if (node == null) {
- 19
str.push(multiply('\t', level));
- 19
str.push("~");
- 19
console.log(str.join(""));
} else {
- 18
this.__printNode(node.right, level + 1);
- 18
str.push(multiply('\t', level));
- 18
str.push(node.data + ":" + node.balance + "\n");
- 18
console.log(str.join(""));
- 18
this.__printNode(node.left, level + 1);
}
}
}
});
collections/AnderssonTree.js
|
Coverage100.00
SLOC165
LOC76
Missed0
|
- 1
var define = require("../define").define,
Tree = require("./Tree"),
base = require("../base"),
multiply = base.string.multiply;
- 1
var RED = "red", BLACK = "black";
- 1
var nil = {level:0, data:null};
- 1
var makeNode = function (data, level) {
- 122
return {
data:data,
level:level,
left:nil,
right:nil
}
};
- 1
var skew = function (root) {
- 384
if (root.level != 0 && root.left.level == root.level) {
- 66
var save = root.left;
- 66
root.left = save.right;
- 66
save.right = root;
- 66
root = save;
}
- 384
return root;
};
- 1
var split = function (root) {
- 384
if (root.level != 0 && root.right.right.level == root.level) {
- 79
var save = root.right;
- 79
root.right = save.left;
- 79
save.left = root;
- 79
root = save;
- 79
++root.level;
}
- 384
return root;
};
- 1
var insert = function (root, data, compare) {
- 492
if (root == nil) {
- 122
root = makeNode(data, 1);
}
else {
- 370
var dir = compare(data, root.data) == -1 ? "left" : "right";
- 370
root[dir] = insert(root[dir], data, compare);
- 370
root = skew(root);
- 370
root = split(root);
}
- 492
return root;
};
- 1
var remove = function (root, data, compare) {
- 59
var rLeft, rRight;
- 59
if (root != nil) {
- 59
var cmp = compare(data, root.data);
- 59
if (cmp == 0) {
- 26
rLeft = root.left, rRight = root.right;
- 26
if (rLeft != nil && rRight != nil) {
- 8
var heir = rLeft;
- 8
while (heir.right != nil)
- 3
heir = heir.right;
- 8
root.data = heir.data;
- 8
root.left = remove(rLeft, heir.data, compare);
} else {
- 18
root = root[rLeft == nil ? "right" : "left"];
}
} else {
- 33
var dir = cmp == -1 ? "left" : "right";
- 33
root[dir] = remove(root[dir], data, compare);
}
}
- 59
if (root != nil) {
- 42
var rLevel = root.level;
- 42
var rLeftLevel = root.left.level, rRightLevel = root.right.level;
- 42
if (rLeftLevel < rLevel - 1 || rRightLevel < rLevel - 1) {
- 14
if (rRightLevel > --root.level)
- 2
root.right.level = root.level;
- 14
root = skew(root);
- 14
root = split(root);
}
}
- 59
return root;
};
/**
*
* @ignoreCode
* @class <p>Andersson Trees are a version of a balanced Binary tree, while similar to RedBlack Trees the balancing is not as strict.</p>
*
* <b>Performance</b>
* <table>
* <tr><td></td><td>Best</td><td>Worst</td></tr>
* <tr><td>space</td><td>O(n)</td><td>O(n)</td></tr>
* <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr>
* <table>
* @name AnderssonTree
* @augments comb.collections.Tree
* @memberOf comb.collections
*/
- 1
module.exports = exports = define(Tree, {
instance:{
/**@lends comb.collections.AnderssonTree.prototype*/
isEmpty:function () {
- 4
return this.__root == nil || this._super(arguments);
},
insert:function (data) {
- 130
if (this.__root == null) this.__root = nil;
- 122
this.__root = insert(this.__root, data, this.compare);
},
remove:function (data) {
- 18
this.__root = remove(this.__root, data, this.compare);
},
traverseWithCondition:function (node, order, callback) {
- 614
var cont = true;
- 614
if (node != nil) {
- 317
return this._super(arguments);
}
- 297
return cont;
},
traverse:function (node, order, callback) {
- 989
if (node != nil) {
- 482
this._super(arguments);
}
},
contains:function (value) {
- 44
if (this.__root != nil) {
- 26
return this._super(arguments);
}
- 18
return false;
},
__printNode:function (node, level) {
- 37
var str = [];
- 37
if (node.data == null || node == null) {
- 19
str.push(multiply('\t', level));
- 19
str.push("~");
- 19
console.log(str.join(""));
} else {
- 18
this.__printNode(node.right, level + 1);
- 18
str.push(multiply('\t', level));
- 18
str.push(node.data + ":" + node.level + "\n");
- 18
console.log(str.join(""));
- 18
this.__printNode(node.left, level + 1);
}
}
}
});
collections/BinaryTree.js
|
Coverage100.00
SLOC83
LOC30
Missed0
|
- 1
var define = require("../define").define,
Tree = require("./Tree"),
base = require("../base");
/**
*
* @ignoreCode
* @class <p>A Search tree that maintains the following properties</p>
* <ul>
* <li>The left subtree of a node contains only nodes with keys less than the node's key.
* <li>The right subtree of a node contains only nodes with keys greater than the node's key.
* <li>Both the left and right subtrees must also be binary search trees.
* </ul>
*
* <b>Performance</b>
* <table>
* <tr><td></td><td>Best</td><td>Worst</td></tr>
* <tr><td>Space</td><td>O(n)</td><td>O(n)</td></tr>
* <tr><td>Search</td><td>O(log n)</td><td>O(n)</td></tr>
* <tr><td>Insert</td><td>O(log n)</td><td>O(n)</td></tr>
* <tr><td>Delete</td><td>O(log n)</td><td>O(n)</td></tr>
* <table>
* @name BinaryTree
* @augments comb.collections.Tree
* @memberOf comb.collections
*/
- 1
module.exports = exports = define(Tree, {
instance : {
/**@lends comb.collections.BinaryTree.prototype*/
insert : function(data) {
- 124
if (this.__root == null) {
- 9
return (this.__root = {
data : data,
parent : null,
left : null,
right : null
});
}
- 115
var compare = this.compare;
- 115
var root = this.__root;
- 115
while (root != null) {
- 505
var cmp = compare(data, root.data);
- 505
if (cmp) {
- 503
var leaf = (cmp == -1) ? "left" : "right";
- 503
var next = root[leaf];
- 503
if (next == null) {
- 113
return (root[leaf] = {data : data, parent : root, left : null, right : null});
} else {
- 390
root = next;
}
} else {
- 2
return;
}
}
},
remove : function(data) {
- 19
if (this.__root != null) {
- 19
var head = {right : this.__root}, it = head;
- 19
var p, f = null;
- 19
var dir = "right";
- 19
while (it[dir] != null) {
- 51
p = it;
- 51
it = it[dir];
- 51
var cmp = this.compare(data, it.data);
- 51
if (!cmp) {
- 18
f = it;
}
- 51
dir = (cmp == -1 ? "left" : "right");
}
- 19
if (f != null) {
- 18
f.data = it.data;
- 18
p[p.right == it ? "right" : "left"] = it[it.left == null ? "right" : "left"];
}
- 19
this.__root = head.right;
}
}
}
});
collections/Collection.js
|
Coverage100.00
SLOC56
LOC8
Missed0
|
- 1
var define = require("../define").define,
base = require("../base");
/**
* @ignoreCode
* @class Base class for all collections
* @name Collection
* @memberOf comb.collections
*/
- 1
define(null, {
instance:{
/**@lends comb.collections.Collection.prototype*/
/**
* Concats two collections
*/
concat:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Joins two collections
*/
join:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Slice a portion from a collection
*/
slice:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Convert a collection to a string
*/
toString:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Find the index of an item in a collection
*/
indexOf:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Find the last index of an item in a collection
*/
lastIndexOf:function () {
- 1
throw new Error("Not Implemented");
}
}
}).as(module);
collections/HashTable.js
|
Coverage100.00
SLOC378
LOC126
Missed0
|
- 1
var define = require("../define").define,
Collection = require("./Collection"),
Iterable = require("./Iterable"),
base = require("../base");
- 1
var hashFunction = function (key) {
- 100
if (typeof key == "string") {
- 26
return key;
- 74
} else if (typeof key == "object") {
- 44
return key.hashCode ? key.hashCode() : "" + key;
} else {
- 30
return "" + key;
}
};
- 1
var Bucket = define(null, {
instance:{
constructor:function () {
- 32
this.__entries = [];
},
pushValue:function (key, value) {
- 36
this.__entries.push({key:key, value:value});
- 36
return value;
},
remove:function (key) {
- 14
var ret = null, map = this.__entries, val;
- 14
var i = map.length - 1;
- 14
for (; i >= 0; i--) {
- 16
if ((val = map[i]) != null && val.key === key) {
- 12
map[i] = null;
- 12
return val.value;
}
}
- 2
return ret;
},
"set":function (key, value) {
- 14
var ret = null, map = this.__entries;
- 14
var i = map.length - 1;
- 14
for (; i >= 0; i--) {
- 18
var val = map[i];
- 18
if (val && key === val.key) {
- 6
val.value = value;
- 6
ret = value;
- 6
break;
}
}
- 14
if (!ret) {
- 8
map.push({key:key, value:value});
}
- 14
return ret;
},
find:function (key) {
- 34
var ret = null, map = this.__entries, val;
- 34
var i = map.length - 1;
- 34
for (; i >= 0; i--) {
- 43
val = map[i];
- 43
if (val && key === val.key) {
- 26
ret = val.value;
- 26
break;
}
}
- 34
return ret;
},
getEntrySet:function (arr) {
- 78
var map = this.__entries, l = map.length;
- 78
if (l) {
- 78
for (var i = 0; i < l; i++) {
- 88
var e = map[i];
- 88
if (e) {
- 80
arr.push(e);
}
}
}
},
getKeys:function (arr) {
- 21
var map = this.__entries, l = map.length;
- 21
if (l) {
- 21
for (var i = 0; i < l; i++) {
- 24
var e = map[i];
- 24
if (e) {
- 8
arr.push(e.key);
}
}
}
- 21
return arr;
},
getValues:function (arr) {
- 14
var map = this.__entries, l = map.length;
- 14
if (l) {
- 14
for (var i = 0; i < l; i++) {
- 16
var e = map[i];
- 16
if (e) {
- 8
arr.push(e.value);
}
}
}
- 14
return arr;
}
}
});
/**
* @ignoreCode
* @class <p>Implementation of a HashTable for javascript.
* This HashTable implementation allows one to use anything as a key.
* </p>
* <b>NOTE: THIS IS ~ 3 times slower than javascript native objects</b>
*
* <p> A use case for this collection is when one needs to store items in which the key will not be a string, or number</p>
*
* @name HashTable
* @augments comb.collections.Collection
* @memberOf comb.collections
*
* @property {Array} keys all keys contained in the table
* @property {Array} values all values contained in the table
* @property {Array} entrySet an array of objects. Each object contains a key, and value property.
*/
- 1
define([Collection, Iterable], {
instance:{
/**@lends comb.collections.HashTable.prototype*/
constructor:function () {
- 13
this.__map = {};
},
__entrySet:function () {
- 14
var ret = [], es = [];
- 14
for (var i in this.__map) {
- 78
this.__map[i].getEntrySet(ret);
}
- 14
return ret;
},
/**
* Put a key, value pair into the table
*
* <b>NOTE :</b> the collection will not check if the key previously existed.
*
* @param {Anything} key the key to look up the object.
* @param {Anything} value the value that corresponds to the key.
*
* @returns the value
*/
put:function (key, value) {
- 29
var hash = hashFunction(key);
- 29
var bucket = null;
- 29
if ((bucket = this.__map[hash]) == null) {
- 25
bucket = (this.__map[hash] = new Bucket());
}
- 29
bucket.pushValue(key, value);
- 29
return value;
},
/**
* Remove a key value pair from the table.
*
* @param key the key of the key value pair to remove.
*
* @returns the removed value.
*/
remove:function (key) {
- 16
var hash = hashFunction(key), ret = null;
- 16
var bucket = this.__map[hash];
- 16
if (bucket) {
- 14
ret = bucket.remove(key);
}
- 16
return ret;
},
/**
* Get the value corresponding to the key.
*
* @param key the key used to look up the value
*
* @returns null if not found, or the value.
*/
"get":function (key) {
- 26
var hash = hashFunction(key), ret = null;
- 26
var bucket = null;
- 26
if ((bucket = this.__map[hash]) != null) {
- 26
ret = bucket.find(key);
}
- 26
return ret;
},
/**
* Set the value of a previously existing key,value pair or create a new entry.
*
* @param key the key to be be used
* @param value the value to be set
*
* @returns the value.
*/
"set":function (key, value) {
- 21
var hash = hashFunction(key), ret = null, bucket = null, map = this.__map;
- 21
if ((bucket = map[hash]) != null) {
- 14
ret = bucket.set(key, value);
} else {
- 7
ret = (map[hash] = new Bucket()).pushValue(key, value);
}
- 21
return ret;
},
/**
* Tests if the table contains a particular key
* @param key the key to test
*
* @returns {Boolean} true if it exitsts false otherwise.
*/
contains:function (key) {
- 8
var hash = hashFunction(key), ret = false;
- 8
var bucket = null;
- 8
if ((bucket = this.__map[hash]) != null) {
- 8
ret = bucket.find(key) != null;
}
- 8
return ret;
},
/**
* Returns a new HashTable containing the values of this HashTable, and the other table.
* </br>
* <b> DOES NOT CHANGE THE ORIGINAL!</b>
* @param {comb.collections.HashTable} hashTable the hash table to concat with this.
*
* @returns {comb.collections.HashTable} a new HashTable containing all values from both tables.
*/
concat:function (hashTable) {
- 2
if (hashTable instanceof this._static) {
- 1
var ret = new this._static();
- 1
var otherEntrySet = hashTable.entrySet.concat(this.entrySet);
- 1
for (var i = otherEntrySet.length - 1; i >= 0; i--) {
- 4
var e = otherEntrySet[i];
- 4
ret.put(e.key, e.value);
}
- 1
return ret;
} else {
- 1
throw new TypeError("When joining hashtables the joining arg must be a HashTable");
}
},
/**
* Creates a new HashTable containg values that passed the filtering function.
*
* @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field
* @param {Object} scope the scope to call the function.
*
* @returns {comb.collections.HashTable} the HashTable containing the values that passed the filter.
*/
filter:function (cb, scope) {
- 1
var es = this.__entrySet(), ret = new this._static();
- 1
es = es.filter.apply(es, arguments);
- 1
for (var i = es.length - 1; i >= 0; i--) {
- 4
var e = es[i];
- 4
ret.put(e.key, e.value);
}
- 1
return ret;
},
/**
* Loop through each value in the hashtable
*
* @param {Function} cb the function to call with an object containing a key and value field
* @param {Object} scope the scope to call the funciton in
*/
forEach:function (cb, scope) {
- 1
var es = this.__entrySet(), l = es.length, f = cb.bind(scope || this);
- 1
es.forEach.apply(es, arguments);
},
/**
* Determines if every item meets the condition returned by the callback.
*
* @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field
* @param {Object} [scope=this] scope to call the function in
*
* @returns {Boolean} True if every item passed false otherwise
*/
every:function () {
- 2
var es = this.__entrySet();
- 2
return es.every.apply(es, arguments);
},
/**
* Loop through each value in the hashtable, collecting the value returned by the callback function.
* @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field
* @param {Object} [scope=this] scope to call the function in
*
* @returns {Array} an array containing the mapped values.
*/
map:function () {
- 1
var es = this.__entrySet(), ret = new this._static();
- 1
return es.map.apply(es, arguments);
},
/**
* Determines if some items meet the condition returned by the callback.
*
* @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field
* @param {Object} [scope=this] scope to call the function in
*
* @returns {Boolean} True if some items passed false otherwise
*/
some:function () {
- 2
var es = this.__entrySet();
- 2
return es.some.apply(es, arguments);
},
/**
* Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
*
* @param {Function} callback Function to execute on each value in the array.
* @param initialValue Value to use as the first argument to the first call of the callback..
*/
reduce:function () {
- 1
var es = this.__entrySet();
- 1
return es.reduce.apply(es, arguments);
},
/**
* Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.
*
* @param {Function} callback Function to execute on each value in the array.
* @param initialValue Value to use as the first argument to the first call of the callback..
*/
reduceRight:function () {
- 1
var es = this.__entrySet();
- 1
return es.reduceRight.apply(es, arguments);
},
/**
* Clears out all items from the table.
*/
clear:function () {
- 1
this.__map = {};
},
getters:{
keys:function () {
- 8
var ret = [], es = [];
- 8
for (var i in this.__map) {
- 21
this.__map[i].getKeys(ret);
}
- 8
return ret;
},
values:function () {
- 6
var ret = [], es = [];
- 6
for (var i in this.__map) {
- 14
this.__map[i].getValues(ret);
}
- 6
return ret;
},
entrySet:function () {
- 5
return this.__entrySet();
},
isEmpty:function () {
- 2
return this.keys.length == 0;
}
}
}
}).as(module);
collections/Heap.js
|
Coverage100.00
SLOC218
LOC62
Missed0
|
- 1
var define = require("../define").define,
Collection = require("./Collection"),
base = require("../base");
- 1
var padding = function(char, numSpaces) {
- 9
var ret = [];
- 9
for (var i = 0; i < numSpaces; i++)
- 16
ret.push(char);
- 9
return ret.join("");
};
- 1
module.exports = exports = define(Collection, {
instance : {
/**@lends comb.collections.Heap.prototype*/
__getParentIndex : function(index) {
- 192
return Math.floor((index - 1) / 2);
},
__getLeftChildIndex : function(index) {
- 28
return (index * 2) + 1;
},
__getRightChildIndex : function(index) {
- 28
return (index * 2) + 2;
},
__makeNode : function(key, value) {
- 137
return {key : key, value : value};
},
/**
* Base class for Heap Implementations.
*
*
* @constructs
* @augments comb.collections.Collection
* @memberOf comb.collections
*
* @property {Number} count the current number of elements.
* @property {Array} keys the keys of all items in the heap.
* @property {Array} values the values contained in the heap.
* @property {Boolean} isEmpty true if the Heap is empty.
*/
constructor : function() {
- 32
this.__heap = [];
},
/**
* Insert a key value into the key
* @param key
* @param value
*/
insert : function(key, value) {
- 138
if (!base.isString(key)) {
- 137
var l = this.__heap.push(this.__makeNode(key, value));
- 137
this.__upHeap(l - 1);
} else {
- 1
throw TypeError("Invalid key");
}
},
/**
* Removes the root from the heap
*
* @returns the value of the root
*/
remove : function() {
- 48
var ret = undefined, heap = this.__heap, l = heap.length;
- 48
if (l) {
- 48
ret = heap[0];
- 48
if (l == 1) {
- 12
heap.length = 0;
} else {
- 36
heap[0] = heap.pop();
- 36
this.__downHeap(0);
}
}
- 48
return ret ? ret.value : ret;
},
/**
* Gets he value of the root node with out removing it.
*
* @returns the value of the root
*/
peek : function() {
- 33
var ret = undefined, heap = this.__heap, l = heap.length;
- 33
if (l) {
- 30
ret = heap[0];
}
- 33
return ret ? ret.value : ret;
},
/**
* Gets the key of the root node without removing it.
*
* @returns the key of the root
*/
peekKey : function() {
- 6
var ret = undefined, heap = this.__heap, l = heap.length;
- 6
if (l) {
- 4
ret = heap[0];
}
- 6
return ret ? ret.key : ret;
},
/**
* Perform the heapify operation after the an
* item as been added to the bottom of the heap.
*
* @param index the index in which the new item was added
*/
__upHeap : function(index) {
- 1
throw Error("NOT IMPLEMENTED");
},
/**
* Heapify the heap after the root has been removed
*
* @param index the index of the root
*/
__downHeap : function(index) {
- 1
throw Error("NOT IMPLEMENTED");
},
/**
*
* Determine if the heap contains a particular key.
*
* @param key key to test.
*
* @returns {Boolean} true if the key is contained in this heap.
*/
containsKey : function(key) {
- 15
var heap = this.__heap;
- 15
for (var i = heap.length - 1; i >= 0; i--) {
- 42
if (heap[i].key == key) {
- 12
return true;
}
}
- 3
return false;
},
/**
*
* Determine if the heap contains a particular value.
*
* @param value value to test.
*
* @returns {Boolean} true if the value is contained in this heap.
*/
containsValue : function(value) {
- 15
var heap = this.__heap;
- 15
for (var i = heap.length - 1; i >= 0; i--) {
- 42
if (heap[i].value == value) {
- 12
return true;
}
}
- 3
return false;
},
/**
* Empty the heap.
*/
clear : function() {
- 9
this.__heap.length = 0;
},
__printNode : function(index, level) {
//console.log(level);
- 9
var str = [], node = this.__heap[index];
- 9
if (node == null || node == undefined) {
- 5
str.push(padding('\t', level));
- 5
str.push("~");
- 5
console.log(str.join(""));
} else {
- 4
this.__printNode(this.__getRightChildIndex(index), level + 1);
- 4
str.push(padding('\t', level));
- 4
str.push(node.key + " : " + node.value + "\n");
- 4
console.log(str.join(""));
- 4
this.__printNode(this.__getLeftChildIndex(index), level + 1);
}
},
/**
* Print the heap.
*/
print : function() {
- 1
this.__printNode(0, 0);
},
getters : {
count : function() {
- 12
return this.__heap.length;
},
keys : function() {
- 3
return this.__heap.map(function(n) {
- 12
return n.key;
});
},
values : function() {
- 3
return this.__heap.map(function(n) {
- 12
return n.value;
});
},
isEmpty : function() {
- 18
return this.__heap.length == 0;
}
}
}
});
collections/Iterable.js
|
Coverage100.00
SLOC63
LOC9
Missed0
|
- 1
var define = require("../define").define,
base = require("../base");
/**
* @ignoreCode
* @class Base class for all collections
* @name Iterable
* @memberOf comb.collections
*/
- 1
define(null, {
instance:{
/**@lends comb.collections.Iterable.prototype*/
/**
* Filter items from a collection
*/
filter:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Loop through the items in a collection
*/
forEach:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Determine if every item in a collection meets the criteria
*/
every:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Map every item in a collection
*/
map:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Determing if some items in a colleciton meet the criteria
*/
some:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Reduce a collection
*/
reduce:function () {
- 1
throw new Error("Not Implemented");
},
/**
* Reduce a collection starting from the right most position
*/
reduceRight:function () {
- 1
throw new Error("Not Implemented");
}
}
}).as(module);
collections/MaxHeap.js
|
Coverage100.00
SLOC66
LOC25
Missed0
|
- 1
var define = require("../define").define,
Heap = require("./Heap"),
base = require("../base");
/**
* @ignoreCode
*
* @class <p> Max Heap implementation, lowest value in heap is always at the root.</p>
* </br>
* <b>Performance</b>
* <table>
* <tr><td></td><td>Best</td><td>Worst</td></tr>
* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Remove</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Peek</td><td>O(1)</td><td>O(1)</td></tr>
* <tr><td>Contains</td><td>O(n)</td><td>O(n)</td></tr>
* <table>
* @name MaxHeap
* @augments comb.collections.Heap
* @memberOf comb.collections
*/
- 1
exports = module.exports = define(Heap, {
instance : {
__upHeap : function(index) {
- 48
var heap = this.__heap;
- 48
var node = heap[index];
- 48
while (index >= 0) {
- 84
var parentIndex = this.__getParentIndex(index), parent = heap[parentIndex];
- 84
if (parent && parent.key < node.key) {
- 36
heap[index] = parent;
- 36
index = parentIndex;
} else {
- 48
break;
}
}
- 48
heap[index] = node;
},
__downHeap : function(index) {
- 12
var heap = this.__heap;
- 12
var node = heap[index], length = heap.length;
- 12
while (index < Math.floor(length / 2)) {
- 8
var leftIndex = this.__getLeftChildIndex(index),
rightIndex = this.__getRightChildIndex(index), left = heap[leftIndex], right = heap[rightIndex], child, childIndex;
- 8
if (rightIndex < length && right.key < left.key) {
- 4
childIndex = leftIndex;
- 4
child = left
} else {
- 4
childIndex = leftIndex;
- 4
child = heap[leftIndex];
}
- 8
if(child.key > node.key){
- 5
heap[index] = child;
- 5
index = childIndex;
}else{
- 3
break;
}
}
- 12
heap[index] = node;
}
}
});
collections/MinHeap.js
|
Coverage100.00
SLOC65
LOC26
Missed0
|
- 1
var define = require("../define").define,
Heap = require("./Heap"),
base = require("../base");
- 1
var floor = Math.floor, MinHeap;
/**
* @class <p> Min Heap implementation, lowest value in heap is always at the root.</p>
* </br>
* <b>Performance</b>
* <table>
* <tr><td></td><td>Best</td><td>Worst</td></tr>
* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Remove</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Peek</td><td>O(1)</td><td>O(1)</td></tr>
* <tr><td>Contains</td><td>O(n)</td><td>O(n)</td></tr>
* <table>
* @name MinHeap
* @augments comb.collections.Heap
* @memberOf comb.collections
* @ignoreCode
*/
- 1
module.exports = exports = define(Heap, {
instance : {
__upHeap : function(index) {
- 88
var heap = this.__heap;
- 88
var node = heap[index], key = node.key, gpi = this.__getParentIndex;
- 88
while (index >= 0) {
- 108
var parentIndex = gpi(index), parent = heap[parentIndex];
- 108
if (parent && parent.key > key) {
- 20
heap[index] = parent;
- 20
index = parentIndex;
} else {
- 88
break;
}
}
- 88
heap[index] = node;
},
__downHeap : function(index) {
- 24
var heap = this.__heap;
- 24
var node = heap[index], key = node.key, length = heap.length, max = floor(length / 2), glci = this.__getLeftChildIndex, grci = this.__getRightChildIndex;
- 24
while (index < max) {
- 16
var leftIndex = glci(index),
rightIndex = grci(index), left = heap[leftIndex], right = heap[rightIndex], child, childIndex;
- 16
if (rightIndex < length && right.key < left.key) {
- 2
childIndex = rightIndex;
- 2
child = right;
} else {
- 14
childIndex = leftIndex;
- 14
child = left;
}
- 16
if (child.key < key) {
- 10
heap[index] = child;
- 10
index = childIndex;
} else {
- 6
break;
}
}
- 24
heap[index] = node;
}
}
});
collections/Pool.js
|
Coverage100.00
SLOC161
LOC50
Missed0
|
- 1
var define = require("../define").define,
Collection = require("./Collection"),
Queue = require("./Queue"),
base = require("../base");
/**
* @class Base class for a pool.
*
* @name Pool
* @memberOf comb.collections
*
* @property {Number} count the total number of objects in the pool, including free and in use objects.
* @property {Number} freeCount the number of free objects in this pool.
* @property {Number} inUseCount the number of objects in use in this pool.
* @property {Number} [minObjects=0] the minimum number of objects this pool should contain.
* @property {Number} [maxObjects=1] the maximum number of objects this pool should contain
* @ignoreCode
*/
- 1
exports = module.exports = define(null, {
instance: {
/**@lends comb.collections.Pool.prototype*/
__minObjects: 0,
__maxObjects: 1,
constructor: function (options) {
- 5
options = options || {};
- 5
this.__freeObjects = new Queue();
- 5
this.__inUseObjects = [];
- 5
this.__minObjects = options.minObjects || 0;
- 5
this.__maxObjects = options.maxObjects || 1;
- 5
this.minObjects = this.__minObjects;
- 4
this.maxObjects = this.__maxObjects;
},
/**
* Retrieves an object from this pool.
* `
* @return {*} an object to contained in this pool
*/
getObject: function () {
- 19
var ret = undefined;
- 19
if (this.count <= this.__maxObjects && this.freeCount > 0) {
- 2
ret = this.__freeObjects.dequeue();
- 2
this.__inUseObjects.push(ret);
- 17
} else if (this.count < this.__maxObjects) {
- 12
ret = this.createObject();
- 12
this.__inUseObjects.push(ret);
}
- 19
return ret;
},
/**
* Returns an object to this pool. The object is validated before it is returned to the pool,
* if the validation fails then it is removed from the pool;
* @param {*} obj the object to return to the pool
*/
returnObject: function (obj) {
- 8
var index;
- 8
if (this.validate(obj) && this.count <= this.__maxObjects && (index = this.__inUseObjects.indexOf(obj)) > -1) {
- 7
this.__freeObjects.enqueue(obj);
- 7
this.__inUseObjects.splice(index, 1);
} else {
- 1
this.removeObject(obj);
}
},
/**
* Removes an object from the pool, this can be overriden to provide any
* teardown of objects that needs to take place.
*
* @param {*} obj the object that needs to be removed.
*
* @return {*} the object removed.
*/
removeObject: function (obj) {
- 2
var index;
- 2
if (this.__freeObjects.contains(obj)) {
- 1
this.__freeObjects.remove(obj);
- 1
} else if ((index = this.__inUseObjects.indexOf(obj)) > -1) {
- 1
this.__inUseObjects.splice(index, 1);
}
//otherwise its not contained in this pool;
- 2
return obj;
},
/**
* Validates an object in this pool.
* </br>
* <b>THIS SHOULD BE OVERRIDDEN TO VALIDATE</b>
*
* @param {*} obj the object to validate.
*/
validate: function (obj) {
- 8
return true;
},
/**
* Creates a new object for this pool.
* * </br>
* <b>THIS SHOULD BE OVERRIDDEN TO ADD THE CORRECT TYPE OF OBJECT</b>
*
* @return {Object} be default just creates an object.
*/
createObject: function () {
- 16
return {};
},
setters: {
minObjects: function (l) {
- 6
if (l <= this.__maxObjects) {
- 5
this.__minObjects = l;
- 5
var i;
- 5
if ((i = this.count) < l) {
- 1
while (i++ < l) {
- 4
this.__freeObjects.enqueue(this.createObject());
}
}
} else {
- 1
throw "comb.collections.Pool : minObjects cannot be greater than maxObjects.";
}
},
maxObjects: function (l) {
- 9
if (l >= this.__minObjects) {
- 8
this.__maxObjects = l;
- 8
var i = this.count, j = this.freeCount, fo = this.__freeObjects;
- 8
while (i > l && j >= 0) {
- 1
this.removeObject(fo.dequeue());
- 1
j--;
- 1
i--;
}
} else {
- 1
throw "comb.collections.Pool : maxObjects cannot be less than maxObjects.";
}
}
},
getters: {
freeCount: function () {
- 41
return this.__freeObjects.count;
},
inUseCount: function () {
- 14
return this.__inUseObjects.length;
},
count: function () {
- 71
return this.__freeObjects.count + this.__inUseObjects.length;
},
minObjects: function () {
- 2
return this.__minObjects;
},
maxObjects: function () {
- 1
return this.__maxObjects;
}
}
}
});
collections/PriorityQueue.js
|
Coverage100.00
SLOC41
LOC6
Missed0
|
- 1
var define = require("../define").define,
MinHeap = require("./MinHeap"),
base = require("../base");
- 1
var PriorityQueue;
/**
* @class PriorityQueue Implementation where the value with the highest priority moves to the front
* Priority starts at 0, and the greatest value being the lowest priority;
* @name PriorityQueue
* @augments comb.collections.MinHeap
* @memberOf comb.collections
* @ignoreCode
*/
- 1
PriorityQueue = define(MinHeap, {
instance : {
/**@lends comb.collections.PriorityQueue.prototype*/
/**
* Adds the value with the specified priority to the queue
*
* @param {Number} priority the priority of the item
* </br>
* <b>0 = Highest, n = lowest</b>
* @param value
*/
enqueue : function(priority, value) {
- 44
return this.insert(priority, value);
},
/**
* Removes the item with the highest priority from the queue
*
* @returns the value of the item
*/
dequeue : function() {
- 16
return this.remove();
}
}
});
- 1
module.exports = exports = PriorityQueue;
collections/Queue.js
|
Coverage100.00
SLOC119
LOC32
Missed0
|
- 1
var define = require("../define").define,
Collection = require("./Collection"),
base = require("../base");
/**
* @class <p>FIFO Data structure</p>
* @name Queue
* @augments comb.collections.Collection
* @memberOf comb.collections
*
* @property {Number} count the current number of elements in this queue
* @property {Boolean} isEmpty true if this queue is empty
* @property {Array} values a copy of the values contained in this queue
* @ignoreCode
*/
- 1
module.exports = exports = define(Collection, {
instance : {
/**@lends comb.collections.Queue.prototype*/
constructor : function() {
- 6
this.__queue = [];
- 6
this.__next = 0;
- 6
this.__last = 0;
},
/**
* Add data to this queue
* @param {*} data element to add
*/
enqueue : function(data) {
- 27
this.__queue[this.__last++] = data;
},
/**
* Removes first item from the head of the queue
*
* @return {*} The element removed from this queue. Returns undefined if the queue is empty.
*/
dequeue : function() {
- 7
var ret = undefined,next = this.__next, queue;
- 7
if (next != this.__last) {
- 5
queue = this.__queue;
- 5
ret = queue[next];
- 5
queue[this.__next++] = undefined;
}
- 7
return ret;
},
/**
* Retrieves the item at the head of the queue without removing it
*
* @return {*} The element at the head of the queue. Returns undefined if the queue is empty.
*/
peek : function() {
- 1
var ret = undefined, next = this.__next;
- 1
if (next != this.__last) {
- 1
ret = this.__queue[next];
}
- 1
return ret;
},
/**
* Removes all items from this queue
*/
clear : function() {
- 1
this.__queue.length = 0;
- 1
this.__next = 0;
- 1
this.__last = 0;
},
/**
* Determine if this queue contains the element
* @param {*} obj the object to find
*
* @return {Boolean} true if this queue contains the element
*/
contains : function(obj) {
- 5
return this.__queue.indexOf(obj) != -1;
},
/**
* Removes an element from this queue.
* @param {*} obj the data to remove.
*
* @return {Boolean} true if the element was removed, false otherwise.
*/
remove : function(obj) {
- 8
var index = this.__queue.indexOf(obj), ret = false;
- 8
if (index != -1) {
- 8
if (index == this.__next) {
- 1
this.dequeue();
} else {
- 7
this.__queue.splice(index, 1);
- 7
this.__last--;
}
- 8
ret = true;
}
- 8
return ret;
},
toString : function(){
- 3
return this.__queue.toString();
},
getters : {
count : function() {
- 114
return this.__last - this.__next;
},
isEmpty : function() {
- 5
return this.__last - this.__next == 0;
},
values : function() {
- 1
return this.__queue.slice(this.__next, this.__last);
}
}
}
});
collections/RedBlackTree.js
|
Coverage100.00
SLOC188
LOC101
Missed0
|
- 1
var define = require("../define").define,
Tree = require("./Tree"),
base = require("../base"),
multiply = base.string.multiply;
- 1
var RED = "red", BLACK = "black";
- 1
var isRed = function(node) {
- 1156
return node != null && node.red;
};
- 1
var makeNode = function(data, parent) {
- 122
return {
data : data,
red : true,
left : null,
right : null
}
};
- 1
var insert = function(root, data, compare) {
- 503
if (root == null) {
- 122
return makeNode(data, null);
} else {
- 381
var cmp = compare(data, root.data);
- 381
if (cmp) {
- 381
var dir = cmp == -1 ? "left" : "right";
- 381
var otherDir = dir == "left" ? "right" : "left";
- 381
root[dir] = insert(root[dir], data, compare);
- 381
var node = root[dir];
- 381
if (isRed(node)) {
- 294
var sibling = root[otherDir];
- 294
if (isRed(sibling)) {
/* Case 1 */
- 68
root.red = true;
- 68
node.red = false;
- 68
sibling.red = false;
} else {
- 226
if (isRed(node[dir])) {
- 43
root = rotateSingle(root, otherDir);
- 183
} else if (isRed(node[otherDir])) {
- 11
root = rotateDouble(root, otherDir);
}
}
}
}
}
- 381
return root;
};
- 1
var rotateSingle = function(root, dir) {
- 70
var otherDir = dir == "left" ? "right" : "left";
- 70
var save = root[otherDir];
- 70
root[otherDir] = save[dir];
- 70
save[dir] = root;
- 70
root.red = true;
- 70
save.red = false;
- 70
return save;
};
- 1
var rotateDouble = function(root, dir) {
- 12
var otherDir = dir == "left" ? "right" : "left";
- 12
root[otherDir] = rotateSingle(root[otherDir], otherDir);
- 12
return rotateSingle(root, dir);
};
- 1
var remove = function (root, data, done, compare) {
- 52
if (root == null) {
- 2
done.done = true;
} else {
- 50
var dir;
- 50
if (compare(data, root.data) == 0) {
- 22
if (root.left == null || root.right == null) {
- 16
var save = root[root.left == null ? "right" : "left"];
/* Case 0 */
- 16
if (isRed(root)) {
- 2
done.done = true;
- 14
} else if (isRed(save)) {
- 5
save.red = false;
- 5
done.done = true;
}
- 16
return save;
}
else {
- 6
var heir = root.right, p;
- 6
while (heir.left != null) {
- 2
p = heir;
- 2
heir = heir.left;
}
- 6
p && (p.left = null);
- 6
root.data = heir.data;
- 6
data = heir.data;
}
}
- 34
dir = compare(data, root.data) == -1 ? "left" : "right";
- 34
root[dir] = remove(root[dir], data, done, compare);
- 34
!done.done && (root = removeBalance(root, dir, done));
}
- 36
return root;
};
- 1
var removeBalance = function(root, dir, done) {
- 11
var notDir = dir == "left" ? "right" : "left";
- 11
var p = root, s = p[notDir];
- 11
if (isRed(s)) {
- 2
root = rotateSingle(root, dir);
- 2
s = p[notDir];
}
- 11
if (s != null) {
- 11
if (!isRed(s.left) && !isRed(s.right)) {
- 9
isRed(p) && (done.done = true);
- 9
p.red = 0;
- 9
s.red = 1;
} else {
- 2
var save = p.red, newRoot = ( root === p );
- 2
p = (isRed(s[notDir]) ? rotateSingle : rotateDouble)(p, dir);
- 2
p.red = save;
- 2
p.left.red = p.right.red = 0;
- 2
if (newRoot) {
- 1
root = p;
} else {
- 1
root[dir] = p;
}
- 2
done.done = true;
}
}
- 11
return root;
};
- 1
var RedBlackTree;
/**
* @class <p>A RedBlack tree is a form of a self balancing binary tree.</p>
*
* <b>Performance</b>
* <table>
* <tr><td></td><td>Best</td><td>Worst</td></tr>
* <tr><td>Space</td><td>O(n)</td><td>O(n)</td></tr>
* <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>
* <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr>
* <table>
* @name RedBlackTree
* @augments comb.collections.Tree
* @memberOf comb.collections
* @ignoreCode
*/
- 1
module.exports = exports = define(Tree, {
instance : {
/**@lends comb.collections.RedBlackTree.prototype*/
insert : function(data) {
- 122
this.__root = insert(this.__root, data, this.compare);
- 122
this.__root.red = false;
},
remove : function(data) {
- 18
var done = {done : false};
- 18
var root = remove(this.__root, data, done, this.compare);
- 18
if (root != null)
- 17
root.red = 0;
- 18
this.__root = root;
},
__printNode : function(node, level) {
- 37
var str = [];
- 37
if (node == null || node == undefined) {
- 19
str.push(multiply('\t', level));
- 19
str.push("~");
- 19
console.log(str.join(""));
} else {
- 18
this.__printNode(node.right, level + 1);
- 18
str.push(multiply('\t', level));
- 18
str.push((node.red ? "RED" : "BLACK") + ":" + node.data + "\n");
- 18
console.log(str.join(""));
- 18
this.__printNode(node.left, level + 1);
}
}
}
});
collections/Stack.js
|
Coverage100.00
SLOC117
LOC30
Missed0
|
- 1
var define = require("../define").define,
Collection = require("./Collection"),
base = require("../base");
/**
* @class <p>LIFO Data structure</p>
* @name Stack
* @augments comb.collections.Collection
* @memberOf comb.collections
*
* @property {Number} count the current number of elements in this queue
* @property {Boolean} isEmpty true if this queue is empty
* @property {Array} values a copy of the values contained in this queue
* @ignoreCode
*/
- 1
module.exports = exports = define(Collection, {
instance : {
/**@lends comb.collections.Stack.prototype*/
constructor : function() {
- 1
this.__stack = [];
- 1
this.__next = -1;
},
/**
* Add an item to the tail of this stack
* @param {*} data item to qppend to this stack
*
*/
push : function(data) {
- 23
this.__stack[++this.__next] = data;
},
/**
* Removes the tail of this static
* @return {*} the data at the tail of this stack
*/
pop : function() {
- 11
var ret = undefined, stack, next = this.__next;
- 11
if (next >= 0) {
- 10
stack = this.__stack;
- 10
ret = stack[next];
- 10
stack[this.__next--] = undefined;
}
- 11
return ret;
},
/**
* Retrieves the item at the tail of the stack without removing it
*
* @return {*} The element at the tail of the stack. Returns undefined if the stack is empty.
*/
peek : function() {
- 1
var ret = undefined,next = this.__next;
- 1
if (next >= 0) {
- 1
ret = this.__stack[next];
}
- 1
return ret;
},
/**
* Removes all items from this stack.
*/
clear : function() {
- 1
this.__stack.length = 0;
- 1
this.__next = -1;
},
/**
* Determine if this stack contains the element
* @param {*} obj the object to find
*
* @return {Boolean} true if this stack contains the element
*/
contains : function(obj) {
- 3
return this.__stack.indexOf(obj) != -1;
},
/**
* Removes an element from this stack.
* @param {*} obj the data to remove.
*
* @return {Boolean} true if the element was removed, false otherwise.
*/
remove : function(obj) {
- 7
var index = this.__stack.indexOf(obj), ret = false;
- 7
if (index != -1) {
- 7
if (index == this.__next) {
- 1
this.pop();
} else {
- 6
this.__stack.splice(index, 1);
- 6
this.__next--;
}
- 7
ret = true;
}
- 7
return ret;
},
toString : function(){
- 3
return this.__stack.toString();
},
getters : {
count : function() {
- 3
return this.__next + 1;
},
isEmpty : function() {
- 5
return this.__next < 0;
},
values : function() {
- 1
return this.__stack.slice(0, this.__next + 1).reverse();
}
}
}
});
collections/Tree.js
|
Coverage100.00
SLOC457
LOC160
Missed0
|
- 1
var define = require("../define").define,
Collection = require("./Collection"),
Iterable = require("./Iterable"),
base = require("../base"),
multiply = base.string.multiply;
- 1
var compare = function(a, b) {
- 2757
var ret = 0;
- 2757
if (a > b) {
- 1571
return 1;
- 1186
} else if (a < b) {
- 936
return -1;
- 250
}else if(!b){
- 1
return 1;
}
- 249
return ret;
};
- 1
var Tree = define([Collection, Iterable], {
instance : {
/**@lends comb.collections.Tree.prototype*/
/**
* Prints a node
* @param node node to print
* @param level the current level the node is at, Used for formatting
*/
__printNode : function(node, level) {
//console.log(level);
- 37
var str = [];
- 37
if (node == null || node == undefined) {
- 19
str.push(multiply('\t', level));
- 19
str.push("~");
- 19
console.log(str.join(""));
} else {
- 18
this.__printNode(node.right, level + 1);
- 18
str.push(multiply('\t', level));
- 18
str.push(node.data + "\n");
- 18
console.log(str.join(""));
- 18
this.__printNode(node.left, level + 1);
}
},
/**
* Base Class for all tree implementations
* @constructs
* @augments comb.collections.Collection
* @augments comb.collections.Iterable
* @memberOf comb.collections
*
* @param {Object} options options to initialize the tree
* @param {Function} options.compare function used to compare items in a tree must return an integer
* <ul>
* </li>-1 for less than</li>
* </li>0 for equal</li>
* </li>1 for greater than</li>
* </ul>
*
*/
constructor : function(options) {
- 45
options = options || {};
- 45
this.compare = options.compare || compare;
- 45
this.__root = null;
},
/**
* Inserts an item into the tree
* @param {Anything} data the item to insert
*/
insert : function(data) {
- 1
throw new Error("Not Implemented");
},
/**
* Removes an item from the tree
* @param {Anything} data the item to insert
*/
remove : function(data) {
- 1
throw new Error("Not Implemented");
},
/**
* Clear all items from a tree
*/
clear : function() {
- 4
this.__root = null;
},
/**
* Test if a tree is empty
*
* @return {Boolean} true if empty false otherwise
*/
isEmpty : function() {
- 15
return this.__root == null;
},
/**
* Traverse a tree until the callback function returns false
*
* <p><b>Not typically used directly</b></p>
*
* @param {Object} node the node to start at
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
* @param {Function} callback called for each item, traversal continues until the function returns false
*
*/
traverseWithCondition : function(node, order, callback) {
- 2172
var cont = true;
- 2172
if (node) {
- 1270
order = order || Tree.PRE_ORDER;
- 1270
if (order === Tree.PRE_ORDER) {
- 152
cont = callback(node.data);
- 152
if (cont) {
- 144
cont = this.traverseWithCondition(node.left, order, callback);
- 144
cont && (cont = this.traverseWithCondition(node.right, order, callback));
}
- 1118
} else if (order === Tree.IN_ORDER) {
- 510
cont = this.traverseWithCondition(node.left, order, callback);
- 510
if (cont) {
- 444
cont = callback(node.data);
- 444
cont && (cont = this.traverseWithCondition(node.right, order, callback));
}
- 608
} else if (order === Tree.POST_ORDER) {
- 178
cont = this.traverseWithCondition(node.left, order, callback);
- 178
if (cont) {
- 158
cont && (cont = this.traverseWithCondition(node.right, order, callback));
- 158
cont && (cont = callback(node.data));
}
- 430
} else if (order === Tree.REVERSE_ORDER) {
- 430
cont = this.traverseWithCondition(node.right, order, callback);
- 430
if (cont) {
- 384
cont = callback(node.data);
- 384
cont && (cont = this.traverseWithCondition(node.left, order, callback));
}
}
}
- 2172
return cont;
},
/**
* Traverse a tree
*
* <p><b>Not typically used directly</b></p>
*
* @param {Object} node the node to start at
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
* @param {Function} callback called for each item
*
*/
traverse : function(node, order, callback) {
- 3449
if (node) {
- 1928
order = order || Tree.PRE_ORDER;
- 1928
if (order === Tree.PRE_ORDER) {
- 632
callback(node.data);
- 632
this.traverse(node.left, order, callback);
- 632
this.traverse(node.right, order, callback);
- 1296
} else if (order === Tree.IN_ORDER) {
- 632
this.traverse(node.left, order, callback);
- 632
callback(node.data);
- 632
this.traverse(node.right, order, callback);
- 664
} else if (order === Tree.POST_ORDER) {
- 632
this.traverse(node.left, order, callback);
- 632
this.traverse(node.right, order, callback);
- 632
callback(node.data);
- 32
} else if (order === Tree.REVERSE_ORDER) {
- 32
this.traverseWithCondition(node.right, order, callback);
- 32
callback(node.data);
- 32
this.traverseWithCondition(node.left, order, callback);
}
}
},
/**
* Loop through each item in the tree
* @param {Function} cb called for each item in the tree
* @param {Object} [scope=this] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*/
forEach : function(cb, scope, order) {
- 28
if (typeof cb !== "function")
- 4
throw new TypeError();
- 24
order = order || Tree.IN_ORDER;
- 24
scope = scope || this;
- 24
this.traverse(this.__root, order, function(node) {
- 312
cb.call(scope, node, this);
});
},
/**
* Loop through each item in the tree, collecting the value returned by the callback funciton.
* @param {Function} cb called for each item in the tree.
* Whatever the function returns is inserted into the return tree
* @param {Object} [scope=this] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return {comb.collections.Tree} the tree with the mapped items
*/
map : function(cb, scope, order) {
- 28
if (typeof cb !== "function")
- 4
throw new TypeError();
- 24
order = order || Tree.IN_ORDER;
- 24
scope = scope || this;
- 24
var construct = this._static;
- 24
var ret = new this._static();
- 24
this.traverse(this.__root, order, function(node) {
- 312
ret.insert(cb.call(scope, node, this));
});
- 24
return ret;
},
/**
* Filters a tree, only returning items that result in true being returned from the callback
*
* @param {Function} cb called for each item in the tree
* @param {Object} [scope=this] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return {comb.collections.Tree} the tree with items that resulted in true being returned from the callback
*/
filter : function(cb, scope, order) {
- 16
if (typeof cb !== "function")
- 4
throw new TypeError();
- 12
order = order || Tree.IN_ORDER;
- 12
scope = scope || this;
- 12
var ret = new this._static();
- 12
this.traverse(this.__root, order, function(node) {
- 216
var include = cb.call(scope, node, this);
- 216
include && ret.insert(node);
});
- 12
return ret;
},
/**
* Reduces a tree
*
* @param {Function} fun called for each item in the tree
* @param [accumulator=First item in tree(Order dependant)] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return the result of the reduce function
*/
reduce : function(fun, accumulator, order) {
- 36
var arr = this.toArray(order);
- 36
var args = [fun];
- 36
!base.isUndefinedOrNull(accumulator) && args.push(accumulator)
- 36
return arr.reduce.apply(arr, args);
},
/**
* Reduces from right to left
*
* @param {Function} fun called for each item in the tree
* @param [accumulator=First item in tree(Order dependant)] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return the result of the reduce function
*/
reduceRight : function(fun, accumulator, order) {
- 12
var arr = this.toArray(order);
- 12
var args = [fun];
- 12
!base.isUndefinedOrNull(accumulator) && args.push(accumulator)
- 12
return arr.reduceRight.apply(arr, args);
},
/**
* Determines if every item meets the condition returned by the callback.
*
* @param {Function} cb called for each item in the tree
* @param {Object} [scope=this] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return {Boolean} True if every item passed false otherwise
*/
every : function(cb, scope, order) {
- 36
if (typeof cb !== "function")
- 4
throw new TypeError();
- 32
order = order || Tree.IN_ORDER;
- 32
scope = scope || this;
- 32
var ret = false;
- 32
this.traverseWithCondition(this.__root, order, function(node) {
- 264
return (ret = cb.call(scope, node, this));
});
- 32
return ret;
},
/**
* Determines if some item meet the condition returned by the callback. Traversal ends the first time true is found.
*
* @param {Function} cb called for each item in the tree
* @param {Object} [scope=this] scope to call the function in
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return {Boolean} True if every item passed false otherwise
*/
some : function(cb, scope, order) {
- 36
if (typeof cb !== "function")
- 4
throw new TypeError();
- 32
order = order || Tree.IN_ORDER;
- 32
scope = scope || this;
- 32
var ret;
- 32
this.traverseWithCondition(this.__root, order, function(node) {
- 284
ret = cb.call(scope, node, this);
- 284
return !ret;
});
- 32
return ret;
},
/**
* Converts a tree into an array based on the specified order
*
* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme
*
* @return {Array} array of all items in the order specified.
*/
toArray : function(order) {
- 72
order = order || Tree.IN_ORDER;
- 72
var arr = [];
- 72
this.traverse(this.__root, order, function(node) {
- 1056
arr.push(node);
});
- 72
return arr;
},
/**
* Determines if a value is contained in the tree
* @param {*} value the value to find
*
* @return {Boolean} true if the tree contains the item false otherwise.
*/
contains : function(value) {
- 160
var ret = false;
- 160
var root = this.__root;
- 160
while (root != null) {
- 376
var cmp = this.compare(value, root.data);
- 376
if (cmp) {
- 271
root = root[(cmp == -1) ? "left" : "right"];
} else {
- 105
ret = true;
- 105
root = null;
}
}
- 160
return ret;
},
/**
* Finds a value in the tree
* @param {*} value the value to find
*
* @return the value of the node that matched
*/
find : function(value) {
- 8
var ret;
- 8
var root = this.__root;
- 8
while (root != null) {
- 35
var cmp = this.compare(value, root.data);
- 35
if (cmp) {
- 31
root = root[(cmp == -1) ? "left" : "right"];
} else {
- 4
ret = root.data;
- 4
break;
}
}
- 8
return ret;
},
/**
* Find all values less than a value
* @param {*} value the value to find nodes less than
* @param {Boolean} [exclusive=false] if true the value will NOT be included in the return array
*
* @return {Array} the array containing all values less than
*/
findLessThan : function(value, exclusive) {
//find a better way!!!!
- 32
var ret = [], compare = this.compare;
- 32
this.traverseWithCondition(this.__root, exports.IN_ORDER, function(v) {
- 200
var cmp = compare(value, v);
- 200
if ((!exclusive && cmp == 0) || cmp == 1) {
- 168
ret.push(v);
- 168
return true;
} else {
- 32
return false;
}
});
- 32
return ret;
},
/**
* Find all greater than a value
* @param {*} value the value to find nodes greater than
* @param {Boolean} [exclusive=false] if true the value will NOT be included in the return array
*
* @return {Array} the array containing all values greater than
*/
findGreaterThan : function(value, exclusive) {
//find a better way!!!!
- 32
var ret = [], compare = this.compare;
- 32
this.traverse(this.__root, exports.REVERSE_ORDER, function(v) {
- 416
var cmp = compare(value, v);
- 416
if ((!exclusive && cmp == 0) || cmp == -1) {
- 372
ret.push(v);
- 372
return true;
} else {
- 44
return false;
}
});
- 32
return ret;
},
/**
* Prints a tree to the console.
*/
print : function() {
- 4
this.__printNode(this.__root, 0);
}
},
static : {
/** @lends comb.collections.Tree */
/**
* Pre Order
*/
PRE_ORDER : "pre_order",
/**
* In Order
*/
IN_ORDER : "in_order",
/**
* Post Order
*/
POST_ORDER:"post_order",
/**
* Reverse Order
*/
REVERSE_ORDER : "reverse_order"
}
});
/**@ignore*/
- 1
module.exports = exports = Tree;
collections/index.js
|
Coverage100.00
SLOC21
LOC2
Missed0
|
- 1
var comb = exports;
/**
* @ignore
* @namespace Various collections*/
- 1
comb.collections = {
Collection : require("./Collection"),
Iterable : require("./Iterable"),
Tree : require("./Tree"),
BinaryTree : require("./BinaryTree"),
RedBlackTree : require("./RedBlackTree"),
AnderssonTree : require("./AnderssonTree"),
AVLTree : require("./AVLTree"),
HashTable : require("./HashTable"),
Queue : require("./Queue"),
Stack : require("./Stack"),
Heap : require("./Heap"),
MinHeap : require("./MinHeap"),
MaxHeap : require("./MaxHeap"),
PriorityQueue : require("./PriorityQueue"),
Pool : require("./Pool")
};
extensions/arguments.js
|
Coverage100.00
SLOC14
LOC4
Missed0
|
- 1
var base = require("../base"),
utils = require("./utils"),
extend = utils.extend,
array = base.array;
- 1
var methods = [
["argsToArray", "toArray"]
];
- 1
module.exports = function (o) {
- 4
return extend(o, methods, base);
};
extensions/array.js
|
Coverage100.00
SLOC21
LOC7
Missed0
|
- 1
var base = require("../base"),
array = base.array,
string = base.string,
utils = require("./utils"),
extend = utils.extend;
- 1
var stringMethods = ["style"];
- 1
var methods = ["forEach", "map", "filter", "reduce", "reduceRight", "some", "every", "indexOf", "lastIndexOf",
"zip", "sum", "avg", "sort", "min", "max", "difference", "removeDuplicates", "unique", "rotate",
"permutations", "transpose", "valuesAt", "union", "intersect", "powerSet", "cartesian", "compact",
"multiply", "flatten", "pluck", "invoke", "partition"];
- 1
module.exports = function (o) {
- 191
extend(o, methods, array);
- 191
extend(o, stringMethods, string);
- 191
return o;
};
extensions/cast.js
|
Coverage100.00
SLOC45
LOC13
Missed0
|
- 1
var base = require("../base"),
define = require("../define").define,
utils = require("./utils"),
extend = utils.extend,
arrayExtension = require("./array"),
argumentsExtension = require("./arguments"),
dateExtension = require("./date"),
functionExtension = require("./function"),
numberExtension = require("./number"),
objectExtension = require("./object"),
stringExtension = require("./string");
- 1
var methods = {
array:function () {
- 191
return arrayExtension(this);
},
date:function () {
- 277
return dateExtension(this);
},
args:function () {
- 4
return argumentsExtension(this);
},
func:function () {
- 42
return functionExtension(this);
},
number:function () {
- 159
return numberExtension(this);
},
string:function () {
- 485
return stringExtension(this);
},
object:function () {
- 535
return objectExtension(this);
}
};
- 1
module.exports = function (o) {
- 1214
extend(o, Object.keys(methods), methods, function (name, func) {
- 8498
return base.partial(func);
});
- 1214
return o;
};
extensions/date.js
|
Coverage100.00
SLOC26
LOC5
Missed0
|
- 1
var base = require("../base"),
define = require("../define").define,
utils = require("./utils"),
extend = utils.extend,
date = base.date,
string = base.string;
- 1
var methods = [
"add",
"compare",
"difference",
"format",
"getDaysInMonth",
"getTimezoneName",
"isLeapYear",
"isWeekend"
];
- 1
module.exports = function (o) {
- 277
extend(o, methods, date);
- 277
return o;
};
extensions/function.js
|
Coverage100.00
SLOC42
LOC16
Missed0
|
- 1
var base = require("../base"),
argsToArray = base.argsToArray,
utils = require("./utils"),
array = base.array,
extend = utils.extend,
comb;
- 1
var methods = [
"hitch",
"bind",
"hitchIgnore",
"bindIgnore",
"partial",
"applyFirst",
"bindFirst",
"curry",
"extend"
];
- 1
var baseMethods = ["extend"];
- 1
module.exports = function (o) {
- 42
comb = comb || (require("../index"));
- 42
extend(o, methods, base, function (name, func) {
- 378
var ret;
- 378
if (name !== 'partial' && name !== "applyFirst") {
- 294
ret = function (arg1) {
- 7
var args = argsToArray(arguments, 1);
- 7
return comb(func.apply(null, [arg1, this].concat(args)));
};
} else {
- 84
ret = function (arg1) {
- 3
return comb(func.apply(null, [this].concat(argsToArray(arguments))));
};
}
- 378
return ret;
});
- 42
extend(o, baseMethods, base);
- 42
return o;
};
extensions/index.js
|
Coverage100.00
SLOC47
LOC24
Missed0
|
- 1
var base = require("../base"),
stringExtension = require("./string"),
functionExtension = require("./function"),
objectExtension = require("./object"),
argumentsExtension = require("./arguments"),
dateExtension = require("./date"),
isExtension = require("./is"),
castExtension = require("./cast.js"),
numberExtension = require("./number"),
arrayExtension = require("./array");
- 1
var TRUE = isExtension(true),
FALSE = isExtension(false);
- 1
function createExtension(obj) {
- 1302
if (base.isBoolean(obj)) {
- 17
return obj ? TRUE : FALSE;
}
- 1285
if (!base.isUndefinedOrNull(obj) && !obj.__isExtended__) {
- 1214
obj = isExtension(obj);
- 1214
obj = castExtension(obj);
- 1214
if (obj.isObject()) {
- 535
obj.object();
}
- 1214
if (obj.isArguments()) {
- 4
obj.args();
}
- 1214
if (obj.isArray()) {
- 191
obj.array();
}
- 1214
if (obj.isFunction()) {
- 42
obj.func();
}
- 1214
if (obj.isString()) {
- 485
obj.string();
}
- 1214
if (obj.isDate()) {
- 275
obj.date();
}
- 1214
if (obj.isNumber()) {
- 159
obj.number();
}
}
- 1285
return obj;
}
- 1
exports.createExtension = createExtension;
extensions/is.js
|
Coverage100.00
SLOC87
LOC28
Missed0
|
- 1
var base = require("../base"),
define = require("../define").define,
utils = require("./utils"),
extend = utils.extend;
- 1
var methods = [
"isDefined",
"isUndefined",
"isNull",
"isUndefinedOrNull",
"isArguments",
"isObject",
"isHash",
"isBoolean",
"isDate",
"isEmpty",
"isArray",
"isFunction",
"isInstanceOf",
"isNumber",
"isPromiseLike",
"isRegExp",
"isString",
"deepEqual"
];
- 1
module.exports = function (o) {
- 1216
var valueOf = false, val;
- 1216
if (!base.isInstanceOf(o, Object)) {
- 639
if (base.isBoolean(o)) {
- 2
val = new Boolean(o);
- 2
valueOf = true;
- 637
} else if (base.isNumber(o)) {
- 155
val = new Number(o);
- 155
valueOf = true;
- 482
} else if (base.isString(o)) {
- 482
val = new String(o);
- 482
valueOf = true;
}
} else {
- 577
val = o;
}
- 1216
var ret = extend(val, methods, base, null, valueOf);
- 1216
if (valueOf) {
- 639
Object.defineProperty(ret, "valueOf", {
value:function () {
- 5102
return o;
},
writable:false,
enumerable:false,
configurable:true
});
}
- 1216
Object.defineProperty(ret, "eq", {
value:function (other) {
- 6
return o === other;
},
writable:false,
enumerable:false,
configurable:true
});
- 1216
Object.defineProperty(ret, "neq", {
value:function (other) {
- 6
return o !== other;
},
writable:false,
enumerable:false,
configurable:true
});
- 1216
Object.defineProperty(ret, "print", {
value:function () {
- 3
console.log(o);
- 3
return val;
},
writable:false,
enumerable:false,
configurable:true
});
- 1216
Object.defineProperty(ret, "__isExtended__", {
value:true,
writable:false,
enumerable:false,
configurable:true
});
- 1216
return ret;
};
extensions/number.js
|
Coverage100.00
SLOC17
LOC5
Missed0
|
- 1
var base = require("../base"),
define = require("../define").define,
utils = require("./utils"),
extend = utils.extend,
number = base.number,
string = base.string;
- 1
var methods = [
"round",
"roundCeil"
];
- 1
module.exports = function (o) {
- 159
extend(o, methods, number, null, true);
- 159
return o;
};
extensions/object.js
|
Coverage100.00
SLOC41
LOC12
Missed0
|
- 1
var base = require("../base"),
define = require("../define").define,
utils = require("./utils"),
extend = utils.extend,
hash = base.hash,
argsToArray = base.argsToArray,
comb;
- 1
var methods = [
"hitch",
"hitchIgnore",
"bind",
"bindIgnore",
"merge",
"extend",
"deepMerge"
];
- 1
var lastMethod = ["curry"];
- 1
var hashMethods = [
"forEach",
"filter",
"invert",
"values",
"toArray",
"omit",
"pick",
"keys"
];
- 1
module.exports = function (o) {
- 535
comb = comb || (require("../index"));
- 535
extend(o, methods, base);
- 535
extend(o, hashMethods, hash);
- 535
extend(o, lastMethod, base, function (name, func) {
- 535
return function () {
- 1
return comb(func.apply(null, argsToArray(arguments).concat([this])));
};
});
- 535
return o;
};
extensions/string.js
|
Coverage100.00
SLOC45
LOC21
Missed0
|
- 1
var base = require("../base"),
string = base.string,
date = base.date,
utils = require("./utils"),
extend = utils.extend,
regexp = base.regexp,
array = base.array,
argsToArray = base.argsToArray,
comb;
- 1
var methods = ["style", "multiply", "toArray", "format", "truncate", "pad"];
- 1
var baseMethods = ["camelize", "underscore", "classify", "pluralize", "singularize", "applyFirst", "bindFirst", "partial"];
- 1
var functionMethods = ["hitch", "bind", "hitchIgnore", "bindIgnore","curry"];
- 1
var arrayMethods = ["pluck", "invoke"];
- 1
var dateMethods = [
["parse", "parseDate"]
];
- 1
var regexpMethods = [
["escapeString", "escape"]
];
- 1
module.exports = function (o) {
- 485
comb = comb || (require("../index"));
- 485
extend(o, methods, string, null, true);
- 485
extend(o, baseMethods, base, null, true);
- 485
extend(o, dateMethods, date, null, true);
- 485
extend(o, regexpMethods, regexp, null, true);
- 485
extend(o, arrayMethods, array, function (name, func) {
- 970
return function () {
- 7
return comb(func.apply(null, argsToArray(arguments).concat([this.valueOf()])));
};
}, true);
- 485
extend(o, functionMethods, base, function (name, func) {
- 2425
return function (arg1) {
- 3
var args = argsToArray(arguments, 1);
- 3
return comb(func.apply(null, [arg1, this.valueOf()].concat(args)));
};
});
- 485
return o;
};
extensions/utils.js
|
Coverage100.00
SLOC45
LOC19
Missed0
|
- 1
var define = require("../define").define,
base = require("../base"),
array = base.array,
isBoolean = base.isBoolean,
argsToArray = base.argsToArray,
comb;
- 1
function proxyFunc(name, func, valueOf, scope) {
- 46556
return function proxy() {
- 9212
comb || (comb = require("../index"));
- 9212
var ret = func.apply(scope, [valueOf ? this.valueOf() : this].concat(argsToArray(arguments)));
- 9209
if (ret && !base.isBoolean(ret) && ret !== this && !ret.__isExtended__) {
- 586
ret = comb(ret);
}
- 9209
return ret;
};
}
- 1
function extend(obj, methods, base, creator, valueOf) {
- 7851
valueOf = isBoolean(valueOf) ? valueOf : false;
- 7851
array.forEach(methods, function (method) {
- 59362
var newFunc, func, m, name;
- 59362
if (Array.isArray(method) && method.length === 2) {
- 974
m = method[0];
- 974
name = method[1];
} else {
- 58388
m = name = method;
}
- 59362
Object.defineProperty(obj, name, {
value:(creator || proxyFunc)(name, base[m], valueOf, base),
writable:false,
enumerable:false,
configurable:true
});
});
- 7851
return obj;
}
- 1
module.exports = {
proxyFunc:proxyFunc,
extend:extend
};
index.js
|
Coverage100.00
SLOC110
LOC8
Missed0
|
- 1
var base = require("./base"),
extension = require("./extensions"),
createExtension = extension.createExtension;
/**
* @projectName comb
*
* @github https://github.com/C2FO/comb
*
* @includeDoc [Getting Started] ../docs-md/introduction.md
* @includeDoc [OO] ../docs-md/define.md
* @includeDoc [Promises] ../docs-md/promise.md
* @includeDoc [Logging] ../docs-md/logging.md
* @includeDoc [Utilities] ../docs-md/utilities.md
* @includeDoc [Change Log] ../History.md
* @includeDoc [Test Coverage] [../docs-md/coverage.html]
*
*
* @header
* [![build status](https://secure.travis-ci.org/C2FO/comb.png)](http://travis-ci.org/C2FO/comb)
* #Comb
*
* ##Overview
*
* Framework for node that provides a one stop shop for frequently needed utilities, including:
*
* * [OO utilties](./define.html)
* * Collections
* * [Logging](./logging.html)
* * [String & date formatting](./utilities)
* * [Flow control](./promise.html)
*
*
* ##Installation
*
* `npm install comb`
*
* ###[Getting Started](./introduction.html)
*
* ##Highlights
*
* * 100% test coverage!
* * comb([define](./comb.html#.define)|[singleton](./comb.html#.singleton))
* * The backbone of comb.
* * Options for classical inheritance models as well as mixins(pseudo multi-inheritance)
* * You can call this._super from any method. Including statically defined ones!
* * Access to your class level properties within an instance
* * Logging
* * Logger inheritance through name spaces
* * Predefined [level](./comb_logging_Level.html) level definition along with the ability to define your own.
* * Multiple appenders including
* * [FileAppender](./comb_logging_appenders_FileAppender.html) - log it to a file
* * [RollingFileAppender](./comb_logging_appenders_RollingFileAppender.html) - log it to a file up to a customizable size then create a new one.
* * [JSONAppender](./comb_logging_appenders_JSONAppender.html) - write it out as JSON to a file.
* * [ConsoleAppender](./comb_logging_appenders_ConsoleAppender.html)- log it to the console
* * Configurable with [files OR programatically](./comb_logger.html#.configure)
* * Collections
* * [RedBlackTree](./comb_collections_RedBlackTree.html)
* * [AVLTree](./comb_collections_AVLTree.html)
* * [AnderssonTree](./comb_collections_AnderssonTree.html)
* * [BinaryTree](./comb_collections_BinaryTree.html)
* * [HashTable](./comb_collections_HashTable.html)
* * [MaxHeap](./comb_collections_MaxHeap.html)
* * [MinHeap](./comb_collections_MinHeap.html)
* * [Pool](./comb_collections_Pool.html)
* * [PriorityQueue](./comb_collections_PriorityQueue.html)
* * [Queue](./comb_collections_Queue.html)
* * [Stack](./comb_collections_Stack.html)
*
* * [Flow control](./promise.html)
* * [Promises](./comb_Promise.html)
* * [PromiseList](./comb_PromiseList.html)
* * [comb.when](./comb.html#.when)
* * [comb.serial](./comb.html#.serial)
*
* @footer
* ##License
*
* MIT <https://github.com/C2FO/comb/raw/master/LICENSE>
*
* ##Meta
* * Code: `git clone git://github.com/C2FO/comb.git`
* * Website: <http://c2fo.com>
* * Twitter: [http://twitter.com/c2fo](http://twitter.com/c2fo) - 877.465.4045
*/
/**
* Utilities for javascript, optimized for the server environment.
*
*
* @namespace
* @ignoreCode
*/
- 1
var comb = createExtension;
- 1
base.merge(comb, base, require("./define"), require("./promise"), require("./async"), require("./plugins"), require("./collections"), require("./logging"));
- 1
comb.definePlugin = function (obj) {
- 1
if (comb.isHash(obj)) {
- 1
comb.deepMerge(comb, obj);
}
- 1
return comb;
};
- 1
module.exports = comb;
logging/appenders/appender.js
|
Coverage100.00
SLOC167
LOC30
Missed0
|
- 1
var define = require("../../define.js").define, base = require("../../base"), Level = require("../level");
- 1
var APPENDER_TYPES = {};
/**
* @class Base class for all appenders
*
* @name Appender
* @memberOf comb.logging.appenders
*
* @param {Object} [options] options to assign to this Appender
* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender
* on a logger it must have a different name.
* @param {String} [options.pattern="[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}"]
* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>
* <ul>
* <li>timeStamp - the timestamp of the event being logged</li>
* <li>level - the {@link comb.logging.Level} of the event</li>
* <li>levelName - the name of the level being logged</li>
* <li>name - the name of the logger logging the event</li>
* <li>message - the message being logged</li>
* </ul>
* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender
* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger
* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the
* appenders level is lower than the logger is will not receive any messages.</p>
*
* @property {String} name the name of this Appender.
* @property {String} pattern the pattern for this Appender.
* @property {comb.logging.Level} level the level of this Appender.
* @ignoreCode
*/
- 1
define(null, {
instance:{
/**@lends comb.logging.appenders.Appender.prototype*/
constructor:function (options) {
- 19
options = options || {};
- 19
this.name = options.name || "appender";
- 19
this.pattern = options.pattern || "[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}";
- 19
var level = options.level;
- 19
if (options.level && (level = Level.toLevel(level))) {
- 3
this.__level = level;
}
},
/**
* Appends a message to a log.
* <b>This method is abstract and must be implemented in subclasses</b>
* @param {Object} event the logging event to log.
* @param {Date} event.timeStamp the timeStamp of the event.
* @param {comb.logging.Level} level the level of the event.
* @param {String} name the name of the logger the event was emitted from.
* @param {String} message the message that is being logged.
*
*/
append:function (event) {
- 1
throw new Error("abstract method");
},
_canAppend:function (event) {
- 93
return !base.isUndefinedOrNull(this.__level) && event.level.isGreaterOrEqualToo(this.__level);
},
/**@ignore*/
setters:{
/**@ignore*/
level:function (level) {
- 69
if (level && level instanceof Level) {
- 62
this.__level = level;
} else {
//try to get the level
- 7
level = Level.toLevel(level);
- 7
if (level) {
- 4
this.__level = level;
}
}
},
pattern:function (patt) {
- 20
if (base.isString(patt)) {
- 20
this.__pattern = patt;
}
},
name:function (name) {
- 25
if (base.isString(name)) {
- 25
this.__name = name;
}
}
},
/**@ignore*/
getters:{
/**@ignore*/
level:function () {
- 106
return this.__level;
},
name:function () {
- 90
return this.__name;
},
pattern:function () {
- 3
return this.__pattern;
}
}
},
"static":{
/**@lends comb.logging.appenders.Appender*/
/**
* Register an appender so it can be used with {@link comb.logging.PropertyConfigurator}
*
* @example
*
* var Appender = comb.logging.appenders.Appender;
* comb.define(Appender, {
* instance : {
* append : function(event){
* //log the message
* }
* }
* }).registerType("MyAppender").as(module);
*
* @param {String} type the identifier for your appender type.
* @return returns the Appender class for chaining.
*/
registerType:function (type) {
- 5
if (base.isString(type)) {
- 5
APPENDER_TYPES[type.toLowerCase()] = this;
}
- 5
return this;
},
/**
* Acts as a factory for appenders.
*
* @example
*
* var logging = comb.logging,
* Logger = logging.Logger,
* Appender = logging.appenders.Appender;
*
* var logger = comb.logging.Logger.getLogger("my.logger");
* logger.addAppender(Appender.createAppender("consoleAppender"));
*
* @param {String} type the type of appender to create.
* @param {Object} [options={}] additional options to pass to the appender.
* @return {comb.logging.appenders.Appender} an appender to add to a logger.
*/
createAppender:function (type, options) {
- 14
var caseType = type.toLowerCase();
- 14
if (caseType in APPENDER_TYPES) {
- 13
return new APPENDER_TYPES[caseType](options);
} else {
- 1
throw new Error(type + " appender is not registered!");
}
}
}
}).as(module);
logging/appenders/consoleAppender.js
|
Coverage100.00
SLOC37
LOC17
Missed0
|
- 1
var define = require("../../define.js").define, base = require("../../base"), string = base.string, style = string.style, format = string.format, Appender = require("./appender"), Level = require("../level");
/**
* @class Appends messages to the console.
*
* @name ConsoleAppender
* @augments comb.logging.appenders.Appender
* @memberOf comb.logging.appenders
*/
- 1
Appender.extend({
instance: {
constructor: function (options) {
- 7
options = options || {};
- 7
!options.name && (options.name = "consoleAppender");
- 7
this._super(arguments, [options]);
},
append: function (event) {
- 6
if (this._canAppend(event)) {
- 6
var message = format(this.__pattern, event);
- 6
var level = event.level;
- 6
if (Level.ERROR.equals(level) || Level.FATAL.equals(level)) {
- 2
console.log(style(message, "red"));
- 4
} else if (Level.WARN.equals(level)) {
- 1
console.log(style(message, "yellow"));
- 3
} else if (Level.DEBUG.equals(level)) {
- 1
console.log(style(message, "magenta"));
- 2
} else if (Level.TRACE.equals(level)) {
- 1
console.log(style(message, "cyan"));
} else {
- 1
console.log(message);
}
}
}
}
}).registerType("ConsoleAppender").as(module);
logging/appenders/fileAppender.js
|
Coverage100.00
SLOC86
LOC22
Missed0
|
- 1
var define = require("../../define.js").define,
base = require("../../base"),
promise = require("../../promise"),
string = base.string,
Promise = promise.Promise,
PromiseList = promise.PromiseList,
style = string.style,
format = string.format,
Appender = require("./appender"),
Level = require("../level"),
fs = require("fs");
/**
* @class Appends messages to a file.
*
* @example
* var fileAppender = new comb.logging.appenders.FileAppender({
* file : "/var/log/myLog.log"
* });
*
*
* @name FileAppender
* @augments comb.logging.appenders.Appender
* @memberOf comb.logging.appenders
*
* @param {Object} [options] options to assign to this Appender
* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender
* on a logger it must have a different name.
* @param {String} [options.pattern="[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}"]
* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>
* <ul>
* <li>timeStamp - the timestamp of the event being logged</li>
* <li>level - the {@link comb.logging.Level} of the event</li>
* <li>levelName - the name of the level being logged</li>
* <li>name - the name of the logger logging the event</li>
* <li>message - the message being logged</li>
* </ul>
* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender
* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger
* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the
* appenders level is lower than the logger is will not recieve any messages.</p>
*
* @param {String} [options.file="./log.log"] the file to log events to.
* @param {String} [options.encoding="utf8"] the encoding of the file.
* @param {Boolean} [options.overwrite=false] if true the log file is overwritten otherwise it is appended to.
* @ignoreCode
*/
- 1
Appender.extend({
instance: {
constructor: function (options) {
- 8
options = options || {};
- 8
!options.name && (options.name = "fileAppender");
- 8
this.__file = options.file || "./log.log";
- 8
this.__encoding = options.encoding || "utf8";
- 8
this.__overwrite = options.overwrite || false;
- 8
this.__writeStream = options.writeStream || fs.createWriteStream(this.__file, {
flags: this.__overwrite ? "w" : 'a',
encoding: this.__encoding
});
- 8
this._super([options]);
- 8
this.__pattern += "\n";
- 8
base.listenForExit(base.hitch(this, "__onExit"));
},
__onExit: function () {
- 14
var ret = new Promise();
- 14
var ws = this.__writeStream;
- 14
this.__writeStream = null;
- 14
ws.on("close", base.hitch(ret, "callback"));
- 14
ws.destroySoon();
- 14
return ret.promise();
},
append: function (event) {
- 15
var ws = this.__writeStream;
- 15
if (this._canAppend(event) && ws && ws.writable) {
- 15
var message = format(this.__pattern, event);
- 15
var level = event.level;
- 15
ws.write(message);
}
}
}
}).registerType("FileAppender").as(module);
logging/appenders/index.js
|
Coverage100.00
SLOC11
LOC5
Missed0
|
/**@ignore*/
- 1
exports.Appender = require("./appender");
/**@ignore*/
- 1
exports.ConsoleAppender = require("./consoleAppender");
/**@ignore*/
- 1
exports.FileAppender = require("./fileAppender");
/**@ignore*/
- 1
exports.JSONAppender = require("./jsonAppender");
/**@ignore*/
- 1
exports.RollingFileAppender = require("./rollingFileAppender");
logging/appenders/jsonAppender.js
|
Coverage100.00
SLOC85
LOC19
Missed0
|
- 1
var define = require("../../define.js").define,
base = require("../../base"),
string = base.string,
escape = base.regexp.escapeString,
FileAppender = require("./fileAppender"),
format = string.format,
Level = require("../level"),
fs = require("fs");
/**
* @class Appends messages to a file in JSON format. The messages are logged to an array in a JSON file
* <b>The file is always overwritten</b>
*
* @example
* //example log.json
* [
* {
* "timestamp" : "Wed Jun 08 2011 11:16:20 GMT-0500 (CDT)",
* "level" : "INFO",
* "name" : "comb",
* "message" : "INFO MESSAGE!!!!"
* }
* ]
*
*
* @name JSONAppender
* @augments comb.logging.appenders.FileAppender
* @memberOf comb.logging.appenders
*
* @param {Object} [options] options to assign to this Appender
* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender
* on a logger it must have a different name.
* @param {String} [options.pattern="{"timestamp" : "{timeStamp}", "level" : "{levelName}", "name" : "{name}", "message" : "{message}"}"]
* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>
* <ul>
* <li>timeStamp - the timestamp of the event being logged</li>
* <li>level - the {@link comb.logging.Level} of the event</li>
* <li>levelName - the name of the level being logged</li>
* <li>name - the name of the logger logging the event</li>
* <li>message - the message being logged</li>
* </ul>
* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender
* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger
* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the
* appenders level is lower than the logger is will not recieve any messages.</p>
*
* @param {String} [options.file="./log.json"] the file to log events to.
* @param {String} [options.encoding="utf8"] the encoding of the file.
*
* @ignoreCode
*/
- 1
FileAppender.extend({
instance:{
constructor:function (options) {
- 5
options = options || {};
- 5
this.name = options.name || "JSONAppender";
- 5
this.__count = 0;
- 5
this.__file = options.file || "./log.json";
- 5
this.__encoding = options.encoding || "utf8";
- 5
this.__writeStream = options.writeStream || fs.createWriteStream(this.__file, { flags:"w", encoding:this.__encoding});
- 5
this.__writeStream.write("[\n");
- 5
this.level = options.level;
//explicit overwrite of patter
- 5
this.__pattern = '{"timestamp" : "{timeStamp}", "level" : "{levelName}", "name" : "{name}", "message" : "{message}"}';
- 5
base.listenForExit(base.hitch(this, "__onExit"));
},
append:function (event) {
- 6
if (this._canAppend(event)) {
- 6
event.message = event.message.replace(/\n+/g, "\\n");
- 6
var message = (this.__count ? ",\n" : "\n") + format(this.__pattern, event);
- 6
this.__writeStream.write(message);
- 6
this.__count++;
}
},
__onExit:function () {
- 5
this.__writeStream.write("]");
- 5
this._super(arguments);
}
}
}).registerType("JSONAppender").as(module);
logging/config.js
|
Coverage100.00
SLOC193
LOC38
Missed0
|
- 1
var define = require("../define.js").define, base = require("../base"), fs = require('fs'), Appender = require("./appenders/appender.js");
- 1
var logging, Logger, Level, appenders;
- 1
var parseProperties = function (properties) {
- 4
for (var i in properties) {
- 4
var logger = Logger.getLogger(i);
- 4
var props = properties[i], level = props.level, appenderArr = props.appenders;
- 4
if (level) {
- 4
level = Level.toLevel(level);
- 4
if (level) {
- 4
logger.level = level;
}
}
- 4
if (appenderArr && base.isArray(appenderArr)) {
- 4
for (var j = appenderArr.length - 1; j >= 0; j--) {
- 14
var appenderProps = base.merge({}, appenderArr[j]), type = appenderProps.type;
- 14
appenderProps.type = null;
- 14
if (type) {
- 12
logger.addAppender(type, appenderProps);
}
}
}
}
};
/**
* @class default configurator for logging
*
* @name BasicConfigurator
* @memberOf comb.logging
* @ignoreCode
*
*/
- 1
var BasicConfigurator = (exports.BasicConfigurator = define(null, {
instance: {
/**@lends comb.logging.BasicConfigurator.prototype*/
constructor: function () {
- 6
if (!Logger) {
- 1
logging = require("./index").logging;
- 1
Logger = logging.Logger;
- 1
Level = logging.Level;
- 1
appenders = logging.appenders;
}
},
/**
* Configure logging.
*
* @param {comb.logging.Appender} [appender=null] appender to add to the root logger, by default a console logger is added.
*/
configure: function (appender) {
- 4
var rootLogger = Logger.getRootLogger();
- 4
rootLogger.removeAllAppenders();
- 4
if (base.isInstanceOf(appender, appenders.Appender)) {
- 2
rootLogger.addAppender(appender);
} else {
- 2
rootLogger.addAppender(new appenders.ConsoleAppender());
}
}
}
}));
/**
* @class Configures comb.Logger with the properties or properties contained within a file
*
* @example
*
* var propertyConfigurator = new comb.logging.PropertyConfigurator();
*
* propertyConfigurator.configure("/location/of/combLogger.json");
*
* //or
*
* var config = {
* "my.logger" : {
* level : "INFO",
* appenders : [
* {
* //default file appender
* type : "FileAppender",
* file : "/var/log/myApp.log",
* },
* {
* //default JSON appender
* type : "JSONAppender",
* file : "/var/log/myApp.JSON",
* },
* {
* type : "FileAppender",
* //override default patter
* pattern : "{[EEEE, MMMM dd, yyyy h:m a]timeStamp} {[5]level}"
* + " {[- 5]levelName} {[-20]name} : {message}",
* //location of my log file
* file : "/var/log/myApp-errors.log",
* //override name so it will get added to the log
* name : "errorFileAppender",
* //overwrite each time
* overwrite : true,
* //explicity set the appender to only accept errors
* level : "ERROR"
* },
* {
* type : "JSONAppender",
* file : "/var/log/myApp-error.json",
* //explicity set the appender to only accept errors
* level : "ERROR"
* }
* ]
* }
* //repeat for more loggers
*
* propertyConfigurator.configure(config);
* }
*
* @name PropertyConfigurator
* @augments comb.logging.BasicConfigurator
* @memberOf comb.logging
* @ignoreCode
*
*/
- 1
exports.PropertyConfigurator = define(BasicConfigurator, {
instance: {
/**@lends comb.logging.PropertyConfigurator.prototype*/
/**
* Call to configure logging
*
* @example
*
* //Example configuration
* {
* "my.logger" : {
* level : "INFO",
* appenders : [
* {
* //default file appender
* type : "FileAppender",
* file : "/var/log/myApp.log",
* },
* {
* //default JSON appender
* type : "JSONAppender",
* file : "/var/log/myApp.JSON",
* },
* {
* type : "FileAppender",
* //override default patter
* pattern : "{[EEEE, MMMM dd, yyyy h:m a]timeStamp} {[5]level}"
* + " {[- 5]levelName} {[-20]name} : {message}",
* //location of my log file
* file : "/var/log/myApp-errors.log",
* //override name so it will get added to the log
* name : "errorFileAppender",
* //overwrite each time
* overwrite : true,
* //explicity set the appender to only accept errors
* level : "ERROR"
* },
* {
* type : "JSONAppender",
* file : "/var/log/myApp-error.json",
* //explicity set the appender to only accept errors
* level : "ERROR"
* }
* ]
* }
*
* @param {Object|String} properties Object containing configuration or string containing a file name with the configuration.
*/
configure: function (properties) {
- 6
var rootLogger = Logger.getRootLogger();
- 6
rootLogger.removeAllAppenders();
- 6
if (base.isHash(properties)) {
- 2
parseProperties(base.deepMerge({}, properties));
} else {
- 4
fs.readFile(properties, function (err, res) {
- 4
if (err) {
- 1
throw err;
} else {
- 3
try {
- 3
parseProperties(JSON.parse(res));
} catch (e) {
- 1
throw e;
}
}
});
}
}
}
});
logging/level.js
|
Coverage100.00
SLOC188
LOC33
Missed0
|
- 1
var define = require("../define.js").define, base = require("../base");
- 1
var LEVELS = {
ALL:-100000,
DEBUG:1,
TRACE:2,
INFO:3,
WARN:4,
ERROR:5,
FATAL:6,
OFF:100000
};
- 1
var LEVELS_REVERSE = {
"-100000":"ALL",
"1":"DEBUG",
"2":"TRACE",
"3":"INFO",
"4":"WARN",
"5":"ERROR",
"6":"FATAL",
"100000":"OFF"
};
/**
* @class Level class used to describe logging levels. The levels determine what types of events are logged to the appenders
* for example the if Level.ALL is used then all event will be logged, however if Level.INFO was used then <b>ONLY</b>
* INFO, WARN, ERROR, and FATAL events will be logged. To turn off logging for a logger use Level.OFF.
*
* <p><b>Not typically instantiated directly, but through staticly defined levels</b></p>
* @example
* //Levels in ascending order
* comb.logging.Level.ALL
* comb.logging.Level.DEBUG
* comb.logging.Level.TRACE
* comb.logging.Level.INFO
* comb.logging.Level.WARN
* comb.logging.Level.ERROR
* comb.logging.Level.FATAL
* comb.logging.Level.OFF
*
* //or
* Level.getLevel("INFO");
*
* @name Level
* @memberOf comb.logging
*
* @property {Number} level the numerical representation of this level.
* @property {String} name the name of level.
* @ignoreCode
*/
- 1
var Level = (exports = module.exports = define(null, {
instance:{
/**@lends comb.logging.Level.prototype*/
constructor:function (level, name) {
- 9
this.level = level;
- 9
this.name = name;
},
/**
* Determing if this level is >= another level
* @param {comb.logging.Level} level the level to test against
*
* @returns {Boolean} true if this is >= false otherwise.
*/
isGreaterOrEqualToo:function (level) {
- 366
var ret = false;
- 366
if (level && base.isNumber(level.level)) {
- 366
if (this.level >= level.level) {
- 223
ret = true;
}
}
- 366
return ret;
},
/**
* Determing if this level is equal to another level based off of the numerical rank.
*
* @param {comb.logging.Level} level the level to compare
*
* @returns {Boolean} true if this is equal to that false otherwise.
*/
equals:function (level) {
- 178
return level.level == this.level;
}
},
static:{
/**@lends comb.logging.Level*/
/**
* Converts a numerical or string representation of a level, if a default level is provided,
* then if a level cannot be determined then the default level is used.
*
* @param {Number|String|comb.logging.Level} level the level to try to convert
* @param {comb.logging.Level} [defaultLevel] default level to use if one cannot be determined,
*
* @returns {comb.logging.Level|null} returns a level if one can be determined null otherwise.
*/
toLevel:function (level, defaultLevel) {
- 229
var ret = null;
- 229
var args = base.argsToArray(arguments);
- 229
if (args.length === 1) {
- 227
var level = args[0];
- 227
if (base.isNumber(level)) {
- 11
var strLevel = LEVELS_REVERSE[level];
- 11
ret = Level[strLevel];
- 216
} else if (base.isString(level)) {
- 66
ret = Level[level.toUpperCase()];
} else {
- 150
ret = level;
}
} else {
- 2
ret = (Level.toLevel(args[0]) || args[1]);
}
- 229
return ret;
},
/**
* Adds a new level to the Level object.
*
* @example
*
* logger = Logger.getLogger("my.logger");
*
* //create the custom level
* Level.addLevel("custom_Level", 20);
*
* //now set the level on a logger
* logger.level = Level.CUSTOM_LEVEL;
*
* @param {string} label the label of the level, <b>Note:</b> the label will be coverted to uppercase.
* @param {number} level the level of the level
*
* @return {undefined|comb.logging.Level} the level that was created.
*
*/
addLevel:function (label, level) {
- 1
var ret;
- 1
if (base.isString(label) && base.isNumber(level)) {
- 1
label = label.toUpperCase();
- 1
LEVELS_REVERSE[level] = label;
- 1
LEVELS[label] = level;
- 1
ret = (this[label] = new Level(level, label));
}
- 1
return ret;
},
/**
* Level to allow logging of all events.
*/
ALL:null,
/**
* Logs only events debug or greater.
*/
DEBUG:null,
/**
* Like debug but provides a finer level of detail
*/
TRACE:null,
/**
* Only info, or error related events
*/
INFO:null,
/**
* Only warn or error related events
*/
WARN:null,
/**
* Error or fatal events
*/
ERROR:null,
/**
* Only fatal events
*/
FATAL:null,
/**
* No events will be logged.
*/
OFF:null
}
}));
- 1
for (var i in LEVELS_REVERSE) {
- 8
Level[LEVELS_REVERSE[i]] = new Level(parseInt(i, 10), LEVELS_REVERSE[i]);
}
plugins/Broadcaster.js
|
Coverage100.00
SLOC113
LOC26
Missed0
|
- 1
var func = require("../base/functions"),
define = require("../define").define;
- 1
var Broadcaster = define(null, {
instance : {
/** @lends comb.plugins.Broadcaster.prototype */
/**
* Plugin to allow a class to easily broadcast events
*
* @example
*
* var Mammal = define(comb.plugins.Broadcaster, {
* instance : {
*
* constructor: function(options) {
* options = options || {};
* this._super(arguments);
* this._type = options.type || "mammal";
* },
*
* speak : function() {
* var str = "A mammal of type " + this._type + " sounds like";
* this.broadcast("speak", str);
* this.onSpeak(str);
* return str;
* },
*
* onSpeak : function(){}
* }
* });
*
*
* var m = new Mammal({color : "gold"});
* m.listen("speak", function(str){
* //called back from the broadcast event
* console.log(str);
* });
* m.speak();
*
* @constructs
*/
constructor : function() {
- 2
this.__listeners = {};
},
/**
* Broadcasts an event from an object
*
* @param name the name of the event to broadcast
* @param {Object|String|Function|Date|Number} [args] variable number of arguments to pass to listeners, can be anything
*/
broadcast : function(topic, args) {
- 2
var args = Array.prototype.slice.call(arguments, 0), topic = args.shift();
- 2
if (topic && topic in this.__listeners) {
- 2
var list = this.__listeners[topic], i = list.length - 1;
- 2
while (i >= 0) {
- 2
list[i--].cb.apply(this, args);
}
}
},
/**
* Listens to a broadcasted event
* Simimlar to {@link comb.listen}
*
* @param {String} topic the topic to listen to
* @param {Function} callback the function to callback on event publish
*
* @returns {Array} handle to disconnect a topic
*/
listen : function(topic, callback) {
- 3
if (!func.isFunction(callback)) throw new Error("callback must be a function");
- 3
var handle = {
topic : topic,
cb : callback
};
- 3
var list = this.__listeners[topic];
- 3
if (!list) {
- 2
list = (this.__listeners[topic] = [handle]);
- 2
handle.pos = 0;
} else {
- 1
handle.pos = list.push(handle);
}
- 3
return handle;
},
/**
* Disconnects a listener
* Similar to {@link comb.unListen}
*
* @param handle disconnect a handle returned from Broadcaster.listen
*/
unListen : function(handle) {
- 1
if (handle) {
- 1
var topic = handle.topic;
- 1
if (topic in this.__listeners) {
- 1
var listeners = this.__listeners, list = listeners[topic];
- 1
if (list) {
- 1
for (var i = list.length - 1; i >= 0; i--) {
- 1
if (list[i] == handle) {
- 1
list.splice(i, 1);
- 1
break;
}
}
}
}
}
}
}
});
- 1
exports = module.exports = Broadcaster;
plugins/index.js
|
Coverage100.00
SLOC6
LOC2
Missed0
|
- 1
var comb = exports;
/**@namespace plugins for classes using {@link comb.define}*/
- 1
comb.plugins = {
Broadcaster : require("./Broadcaster"),
Middleware : require("./Middleware")
};