dev-charper-project
Version:
169 lines • 6.12 kB
JavaScript
;
exports.__esModule = true;
exports.Able = void 0;
var Able;
(function (Able) {
/**
* Resolve a set of abilities with a group definition, returning a set of
* abilities based on all abilities and references to groups in `abilities`.
*
* Unlike `.resolve`, this function does not apply or resolve values.
*
* ```ts
* const definition = { foo: ["bar"] };
* const abilities = ["foo", "bam"];
* Able.flatten(definition, abilities);
* // ["foo", "bam", "bar"]
* ```
*
* @param definition
* @param abilities
*/
function flatten(definition, abilities) {
abilities = abilities.slice();
for (var _i = 0, abilities_1 = abilities; _i < abilities_1.length; _i++) {
var ability = abilities_1[_i];
var members = arr(definition[ability]);
for (var _a = 0, members_1 = members; _a < members_1.length; _a++) {
var member = members_1[_a];
if (!abilities.includes(member)) {
abilities.push(member);
}
}
}
return abilities;
}
Able.flatten = flatten;
/**
* Extract values from a resolved set of abilities and return the values as a
* map with the remaining abilities.
*
* Example:
*
* ```ts
* const abilities = ["foo", "bam", "?foo=1", "?x[]=3"];
* Able.extractValues(abilities);
* // [ { foo: '1', x: [ '3' ] }, [ 'foo', 'bam' ] ]
* ```
*
* @param abilities
*/
function extractValues(abilities) {
var values = {};
var remainder = [];
for (var _i = 0, abilities_2 = abilities; _i < abilities_2.length; _i++) {
var ability = abilities_2[_i];
if (ability[0] === "?") {
var _a = ability.substr(1).split("=", 2), key = _a[0], value = _a[1];
if (key[key.length - 2] === "[" && key[key.length - 1] === "]") {
var arrKey = key.substr(0, key.length - 2);
if (!(values[arrKey] instanceof Array)) {
values[arrKey] = [];
}
if (typeof value !== "undefined") {
values[arrKey].push(value);
}
}
else {
values[key] = typeof value === "undefined" ? "" : value;
}
}
else {
remainder.push(ability);
}
}
return [values, remainder];
}
Able.extractValues = extractValues;
/**
* Replacing template abilities with a given set of values applied. Template
* abilities with missing values are removed.
*
* Example:
*
* ```ts
* const abilities = ["article:{articleId}:read", "post:{postId}:read"]
* const values = { articleId: ["1", "2"] }
* Able.applyValues(abilities, values);
* // [ 'article:1:read', 'article:2:read' ]
* ```
*
* @param abilities
* @param values
*/
function applyValues(abilities, values) {
var REGEX = /\{([^}]+)\}/g;
return abilities.reduce(function (outerAbilitiesAcc, ability) {
var match = ability.match(REGEX);
if (!match) {
return outerAbilitiesAcc.concat([ability]);
}
return outerAbilitiesAcc.concat(match
.map(function (k) { return k.substr(1, k.length - 2); })
.reduce(function (abilitiesAcc, k) {
return abilitiesAcc.reduce(function (acc, innerAbility) {
return acc.concat(arr(values[k]).map(function (v) { return innerAbility.replace("{".concat(k, "}"), v); }));
}, []);
}, [ability]));
}, []);
}
Able.applyValues = applyValues;
/**
* Flatten abilities, and extract and apply embedded values.
*
* ```ts
* const definition = { writer: ["article:{articleId}:write"] };
* const abilities = ["writer", "?articleId[]=4"];
* Able.resolve(definition, abilities);
* // [ 'writer', 'article:4:write' ]
* ```
*
* @param definition
* @param abilities
*/
function resolve(definition, abilities) {
var flattened = Able.flatten(definition, abilities);
var _a = Able.extractValues(flattened), extractedValues = _a[0], extractedAbilities = _a[1];
return Able.applyValues(extractedAbilities, extractedValues);
}
Able.resolve = resolve;
/**
* Compare a set of resolved abilities with a set of required abilities, and
* return all abilities in `requiredAbilities` missing in `abilities`. Returns
* an empty array if `abilities` contains all abilities from
* `requiredAbilities`.
* @param abilities
* @param requiredAbilities
*/
function getMissingAbilities(abilities, requiredAbilities) {
return requiredAbilities.filter(function (ability) { return !abilities.includes(ability); });
}
Able.getMissingAbilities = getMissingAbilities;
/**
* Similar to `getMissingAbilities`, but returns `true` if there are no
* missing abilities. In effect, this function returns whether the user has
* access to something that requires a set of abilities. Only returns `true`
* if `appliedAbilities` include all abilities in `requiredAbilities`.
* @param appliedAbilities
* @param requiredAbilities
*/
function canAccess(appliedAbilities, requiredAbilities) {
return this.getMissingAbilities(appliedAbilities, requiredAbilities).length === 0;
}
Able.canAccess = canAccess;
})(Able = exports.Able || (exports.Able = {}));
function arr(valueOrValues) {
if (valueOrValues === "") {
return [""];
}
else if (typeof valueOrValues === "undefined" || valueOrValues === null) {
return [];
}
else if (typeof valueOrValues === "string") {
return [valueOrValues];
}
else {
return valueOrValues;
}
}
//# sourceMappingURL=Able.js.map