UNPKG

dev-charper-project

Version:
169 lines 6.12 kB
"use strict"; 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