guard-bit
Version:
Utility to split opportunities by the account level (free\pro\enterprise\etc.) for frontend and node
175 lines (159 loc) • 5.34 kB
JavaScript
(function (root, factory) {
'use strict';
/* istanbul ignore next */
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
/* global module */
module.exports = factory();
} else {
root.Guard = factory();
}
}(this, function () {
'use strict';
return function (initConfig) {
var level = 0;
var config;
var listeners = [];
var isRequesting = false;
var requestQueue = [];
var _ = {
isFunction: function (value) {
return typeof value == 'function';
},
isArray: function (value) {
return Array.isArray(value);
},
isRegExp: function (value) {
return value instanceof RegExp;
}
};
function checkAccess(requestRule) {
if (!requestRule) {
return level > 0;
}
return (function () {
for (var i = 0; i <= level; i++) {
var rules = config[i].allowed;
for (var j = 0; j < rules.length; j++) {
if (rules[j].test(requestRule)) {
return true;
}
}
}
return false;
}());
}
function reqThenCallback(feature, callback) {
return function () {
var args = arguments;
if (checkAccess(feature)) {
setTimeout(function () {
callback.apply(null, args);
}, 0);
return;
}
requestQueue.push(callback);
if (isRequesting) {
return;
}
isRequesting = true;
if (config[level].request) {
config[level].request(requestHandler);
}
function requestHandler(err) {
isRequesting = false;
if (err) {
requestQueue = [];
return;
}
guard.setLevel(level + 1);
while (requestQueue.length) {
var nextRequest = requestQueue.shift();
if (feature != null) {
guard(feature, nextRequest).apply(null, args);
} else {
guard(nextRequest).apply(null, args);
}
}
}
};
}
var guard = function guard() {
if (arguments.length === 0) {
return checkAccess();
}
if (arguments.length === 1) {
if (_.isFunction(arguments[0])) {
return reqThenCallback(null, arguments[0]);
} else {
return checkAccess(arguments[0]);
}
}
if (!_.isFunction(arguments[1])) {
throw new TypeError();
}
return reqThenCallback(arguments[0], arguments[1]);
};
guard.request = function (callback) {
if (callback && !_.isFunction(callback)) {
throw new TypeError();
}
if (!callback) {
callback = function () {};
}
return reqThenCallback(null, callback)();
};
guard.setup = function (newConfig) {
if (_.isFunction(newConfig)) {
config = [{
allowed: [],
request: newConfig
}, {
allowed: [/.*/]
}];
} else if (_.isArray(newConfig)) {
config = newConfig.map(function (val) {
return {
allowed: val.allowed.map(function (rule) {
if (_.isRegExp(rule)) {
return rule;
}
var ruleNorm = '^' + rule.replace('*', '.*') + '$';
return new RegExp(ruleNorm);
}),
request: val.request
};
});
} else {
config = [{
allowed: []
}, {
allowed: [/.*/]
}];
}
return config;
};
guard.setLevel = function (newLevel) {
level = newLevel;
listeners.forEach(function (listener) {
listener(newLevel);
});
};
guard.getLevel = function () {
return level;
};
guard.listen = function (listener) {
listeners.push(listener);
return function () {
var i = listeners.indexOf(listener);
if (i !== -1) {
listeners.splice(i, 1);
}
listener = null;
};
};
guard.setup(initConfig);
return guard;
};
}));