happn-3
Version:
pub/sub api as a service using primus and mongo & redis or nedb, can work as cluster, single process or embedded using nedb
218 lines (179 loc) • 6.7 kB
JavaScript
var Promise = require("bluebird"),
fastClone = require("fast-clone"),
ms = require("ms"),
happnUtils = require("./shared"),
fs = require("fs-extra"),
LRU = require("lru-cache");
module.exports = UtilsService;
function UtilsService() {
this.regexCaches = {};
}
UtilsService.prototype.clone = function(obj, circular) {
if (!obj) return obj;
if (typeof obj === "string") return obj.toString();
if (!circular) return happnUtils.clone(obj);
else return fastClone(obj); //does not exist for browser
};
UtilsService.prototype.ensureRegexCache = ensureRegexCache;
UtilsService.prototype.wildcardMatch = wildcardMatch;
UtilsService.prototype.checkPath = happnUtils.checkPath;
UtilsService.prototype.removeLast = happnUtils.removeLast;
UtilsService.prototype.computeiv = happnUtils.computeiv;
UtilsService.prototype.asyncCallback = happnUtils.asyncCallback;
UtilsService.prototype.escapeRegex = happnUtils.escapeRegex;
UtilsService.prototype.wrapImmediate = happnUtils.wrapImmediate;
function ensureRegexCache(cacheKey, cacheSize, cacheAsObject) {
cacheKey = cacheKey || "default";
if (cacheAsObject && cacheKey === "default")
throw new Error("The default regex cache must be of type LRU");
if (!this.regexCaches[cacheKey]) {
if (cacheAsObject)
this.regexCaches[cacheKey] = {
length: 0,
data: {},
has: function(key) {
return this.data[key] != null;
},
get: function(key) {
return this.data[key];
},
set: function(key, data) {
this.data[key] = data;
this.length = Object.keys(this.data).length;
}
};
else {
this.regexCaches[cacheKey] = new LRU({
max: cacheSize || 10000,
maxAge: 0
});
}
}
return this.regexCaches[cacheKey];
}
function wildcardMatch(pattern, matchTo, cacheKey, cacheSize, cacheAsObject) {
const preparedOrMatched = happnUtils.wildcardPreliminaryMatch(pattern, matchTo);
if (typeof preparedOrMatched === "boolean") return preparedOrMatched; //we have a match result, return it
const cache = this.ensureRegexCache(cacheKey, cacheSize, cacheAsObject);
if (!cache.has(preparedOrMatched))
cache.set(preparedOrMatched, happnUtils.makeRe(preparedOrMatched));
const regex = cache.get(preparedOrMatched);
regex.lastIndex = 0;
return regex.test(matchTo);
}
UtilsService.prototype.wildcardMatchMultiple = function(patterns, matchTo, cacheKey, cacheSize) {
for (var patternIndex in patterns)
if ((this.wildcardMatch(patterns[patternIndex], matchTo), cacheKey, cacheSize)) return true;
return false;
};
UtilsService.prototype.replacePrefix = function(str, prefix, rep) {
if (rep == null) rep = "";
if (str && prefix && str.indexOf(prefix) === 0)
return rep + str.substring(prefix.length, str.length);
return str;
};
UtilsService.prototype.replaceSuffix = function(str, suffix, rep) {
if (rep == null) rep = "";
if (str && suffix && str.substring(str.length - suffix.length, str.length) === suffix)
return str.substring(0, str.length - suffix.length) + rep;
return str;
};
UtilsService.prototype.isNumeric = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
UtilsService.prototype.toMilliseconds = function(input) {
if (!input || input === Infinity) return input;
if (this.isNumeric(input)) return input;
else return ms(input);
};
UtilsService.prototype.hrtimeDiffInMilliseconds = function(previousTime) {
// Return the difference between 2 hrtimes in milliseconds
// with appropriate decimal fraction from the nano portion
// eg. 0.001763 milliseconds or 1000.030201 milliseconds
var diff = process.hrtime(previousTime);
return diff[0] * 1000 + diff[1] / 1000000;
};
UtilsService.prototype.stringContainsAny = function(str, segments, caseInSensitive) {
var containsAny = false;
segments.every(function(segment) {
var compareSegment = segment;
var compareStr = str;
if (caseInSensitive) {
compareSegment = segment.toUpperCase();
compareStr = str.toUpperCase();
}
if (compareStr.indexOf(compareSegment) > -1) {
containsAny = true;
return false;
} else return true;
});
return containsAny;
};
UtilsService.prototype.stringifyError = function(err) {
var plainError = {};
Object.getOwnPropertyNames(err).forEach(function(key) {
plainError[key] = err[key];
});
return JSON.stringify(plainError);
};
UtilsService.prototype.getFirstMatchingProperty = function(properties, obj) {
var checkProperties = [];
properties.map(function(propertyName) {
checkProperties.push(propertyName.toLowerCase());
});
for (var propertyName in obj)
if (checkProperties.indexOf(propertyName.toLowerCase()) > -1) return obj[propertyName];
return null;
};
UtilsService.prototype.mergeObjects = function(obj1, obj2, opts) {
var _this = this;
if (!opts) opts = {};
var newObj = {};
var getProp = function(obj, propertyName) {
if (!opts.clone) return obj[propertyName];
return _this.clone(obj[propertyName]);
};
for (var propertyName1 in obj1) {
newObj[propertyName1] = getProp(obj1, propertyName1);
}
for (var propertyName2 in obj2) {
if (newObj[propertyName2] && !opts.overwrite) continue;
newObj[propertyName2] = getProp(obj2, propertyName2);
}
return newObj;
};
UtilsService.prototype.promisify = function(originalFunction, opts) {
return function() {
var args = Array.prototype.slice.call(arguments);
var _this = this;
if (opts && opts.unshift) args.unshift(opts.unshift);
// No promisify if last passed arg is function (ie callback)
if (typeof args[args.length - 1] === "function") {
return originalFunction.apply(this, args);
}
return new Promise(function(resolve, reject) {
// push false callback into arguments
args.push(function(error, result, more) {
if (error) return reject(error);
if (more) {
var args = Array.prototype.slice.call(arguments);
args.shift(); // toss undefined error
return resolve(args); // resolve array of args passed to callback
}
return resolve(result);
});
try {
return originalFunction.apply(_this, args);
} catch (error) {
return reject(error);
}
});
};
};
UtilsService.prototype.fileExists = function(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
return false;
}
};