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
169 lines (141 loc) • 5.15 kB
JavaScript
module.exports = {
/*
Shared between the browser client and the server and nodejs client
*/
prepareWildPath: function(path) {
//strips out duplicate sequential wildcards, ie simon***bishop -> simon*bishop
return path.replace(/(.)\1+/g, "*");
},
makeRe: function(pattern) {
return new RegExp("^" + this.escapeRegex(pattern).replace(/\\\*/g, ".*") + "$", "i");
},
escapeRegex: function(str) {
if (typeof str !== "string") throw new TypeError("Expected a string");
return str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
},
wildcardPreliminaryMatch: function(pattern, matchTo) {
if (pattern.indexOf("*") === -1) return pattern === matchTo;
const preparedPattern = pattern.replace(/(.)\1+/g, "*"); //strip out *** ****** and replace with *
if (preparedPattern === "*") return true;
return preparedPattern;
},
wildcardMatch: function(pattern, matchTo) {
const preparedOrMatched = this.wildcardPreliminaryMatch(pattern, matchTo);
if (typeof preparedOrMatched === "boolean") return preparedOrMatched; //we have a match result, return it
//try a starts with reject
const initialSegment = preparedOrMatched.split("*").pop();
if (initialSegment.length > 0 && matchTo.indexOf(initialSegment) === -1) return false;
return this.makeRe(preparedOrMatched).test(matchTo);
},
whilst: function(test, iterator, cb) {
cb = cb || noop;
if (!test()) return cb(null);
var _this = this;
_this.__attempts = 0;
var next = function(err, args) {
_this.__attempts++;
if (err) return cb(err, _this.__attempts);
if (test.apply(this, args)) return iterator(_this.__attempts, next);
cb.apply(null, [null].concat(args, _this.__attempts));
}.bind(_this);
iterator(_this.__attempts, next);
},
//taken from https://github.com/alessioalex/tiny-each-async
async: function(arr, parallelLimit, iteratorFn, cb) {
var pending = 0;
var index = 0;
var lastIndex = arr.length - 1;
var called = false;
var limit;
var callback;
var iterate;
if (typeof parallelLimit === "number") {
limit = parallelLimit;
iterate = iteratorFn;
callback = cb || function noop() {};
} else {
iterate = parallelLimit;
callback = iteratorFn || function noop() {};
limit = arr.length;
}
if (!arr.length) {
return callback();
}
var iteratorLength = iterate.length;
var shouldCallNextIterator = function shouldCallNextIterator() {
return !called && pending < limit && index < lastIndex;
};
var iteratorCallback = function iteratorCallback(err) {
if (called) {
return;
}
pending--;
if (err || (index === lastIndex && !pending)) {
called = true;
callback(err);
} else if (shouldCallNextIterator()) {
processIterator(++index);
}
};
var processIterator = function processIterator() {
pending++;
var args =
iteratorLength === 2
? [arr[index], iteratorCallback]
: [arr[index], index, iteratorCallback];
iterate.apply(null, args);
if (shouldCallNextIterator()) {
processIterator(++index);
}
};
processIterator();
},
clone: function(obj) {
return JSON.parse(JSON.stringify(obj));
},
checkPath: function(path, action) {
if (action === "set" && path.indexOf("*") > -1)
throw new Error(
"Bad path, if the action is 'set' the path cannot contain the * wildcard character"
);
if (path.match(/^[a-zA-Z0-9/(){}+=&:%@._*\-\s]+$/) == null)
throw new Error(
"Bad path, can only contain characters a-z A-Z 0-9 / & + = : @ % * ( ) _ -, ie: factory1@I&J(western-cape)/plant1:conveyer_2/stats=true/capacity=10%/*"
);
},
computeiv: function(secret) {
if (typeof secret !== "string")
throw new Error("secret must be a string and cannot be null or undefined");
if (secret.length !== 32) throw new Error("secret must be 32 chars long");
var iv = "";
for (let x = 0; x < 32; x = x + 2) iv += secret[x];
return iv;
},
removeLast: function(str, last) {
if (
!str || //null undefined or empty
!str.substring || //not a string
!last || //last is null undefined or empty
str[str.length - 1] !== last
)
//string doesnt end with specified last character
return str;
return str.substring(0, str.length - 1);
},
asyncCallback: function() {
var fn = arguments[0].bind.apply(arguments[0], Array.from(arguments));
if (setImmediate) return setImmediate(fn);
setTimeout(fn, 0);
},
wrapImmediate: function(fn, timeout) {
return function() {
if (timeout) return setTimeout(fn.bind(this), timeout, ...arguments);
if (setImmediate) {
setImmediate(fn.bind(this), ...arguments);
return;
}
setTimeout(fn.bind(this), ...arguments);
};
}
};
function noop() {}