You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@casl/ability

Package Overview
Dependencies
Maintainers
1
Versions
88
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@casl/ability - npm Package Compare versions

Comparing version
5.1.0-next.11
to
5.1.0-next.12
+122
dist/es6/extra.js
function wrapArray(value) {
return Array.isArray(value) ? value : [value];
}
function setByPath(object, path, value) {
let ref = object;
let lastKey = path;
if (path.indexOf('.') !== -1) {
const keys = path.split('.');
lastKey = keys.pop();
ref = keys.reduce((res, prop) => {
res[prop] = res[prop] || {};
return res[prop];
}, object);
}
ref[lastKey] = value;
}
function rulesToQuery(ability, ...args) {
const [action, subject, convert] = args;
const query = {};
const rules = ability.rulesFor(action, subject);
for (let i = 0; i < rules.length; i++) {
const rule = rules[i];
const op = rule.inverted ? '$and' : '$or';
if (!rule.conditions) {
if (rule.inverted) {
break;
} else {
delete query[op];
return query;
}
} else {
query[op] = query[op] || [];
query[op].push(convert(rule));
}
}
return query.$or ? query : null;
}
function rulesToFields(ability, ...[action, subject]) {
return ability.rulesFor(action, subject).filter(rule => !rule.inverted && rule.conditions).reduce((values, rule) => {
const conditions = rule.conditions;
return Object.keys(conditions).reduce((fields, fieldName) => {
const value = conditions[fieldName];
if (!value || value.constructor !== Object) {
setByPath(fields, fieldName, value);
}
return fields;
}, values);
}, {});
}
const getRuleFields = rule => rule.fields;
function deleteKey(key) {
delete this[key];
}
function setKey(key) {
this[key] = true;
}
function permittedFieldsOf(ability, action, subject, options = {}) {
const fieldsFrom = options.fieldsFrom || getRuleFields;
const uniqueFields = ability.possibleRulesFor(action, subject).filter(rule => rule.matchesConditions(subject)).reverse().reduce((fields, rule) => {
const names = fieldsFrom(rule);
if (names) {
const toggle = rule.inverted ? deleteKey : setKey;
names.forEach(toggle, fields);
}
return fields;
}, {});
return Object.keys(uniqueFields);
}
const joinIfArray = value => Array.isArray(value) ? value.join(',') : value;
function packRules(rules, packSubject) {
return rules.map(rule => {
// eslint-disable-line
const packedRule = [joinIfArray(rule.action || rule.actions), typeof packSubject === 'function' ? wrapArray(rule.subject).map(packSubject).join(',') : joinIfArray(rule.subject), rule.conditions || 0, rule.inverted ? 1 : 0, rule.fields ? joinIfArray(rule.fields) : 0, rule.reason || ''];
while (!packedRule[packedRule.length - 1]) packedRule.pop();
return packedRule;
});
}
function unpackRules(rules, unpackSubject) {
return rules.map(([action, subject, conditions, inverted, fields, reason]) => {
const subjects = subject.split(',');
const rule = {
inverted: !!inverted,
action: action.split(','),
subject: typeof unpackSubject === 'function' ? subjects.map(unpackSubject) : subjects
};
if (conditions) {
rule.conditions = conditions;
}
if (fields) {
rule.fields = fields.split(',');
}
if (reason) {
rule.reason = reason;
}
return rule;
});
}
export { packRules, permittedFieldsOf, rulesToFields, rulesToQuery, unpackRules };
//# sourceMappingURL=extra.js.map
{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>,\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport const identity = <T>(x: T) => x;\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n","import { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf, Generics } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport {\n AbilityParameters,\n AnyObject,\n SubjectType,\n AbilityTuple,\n CanParameters,\n Abilities,\n} from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery {\n $or?: object[]\n $and?: object[]\n}\n\ntype RulesToQueryRestArgs<T extends Abilities, ConvertRule> = AbilityParameters<\nT,\nT extends AbilityTuple\n ? (action: T[0], subject: T[1], convert: ConvertRule) => 0\n : never,\n(action: never, subject: never, convert: ConvertRule) => 0\n>;\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n ...args: RulesToQueryRestArgs<Generics<T>['abilities'], RuleToQueryConverter<T>>\n): AbilityQuery | null {\n const [action, subject, convert] = args;\n const query: AbilityQuery = {};\n const rules = ability.rulesFor(action, subject) as RuleOf<T>[];\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n ...[action, subject]: CanParameters<Generics<T>['abilities'], false>\n): AnyObject {\n return ability.rulesFor(action, subject)\n .filter(rule => !rule.inverted && rule.conditions)\n .reduce((values, rule) => {\n const conditions = rule.conditions!;\n\n return Object.keys(conditions).reduce((fields, fieldName) => {\n const value = conditions[fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteKey(this: Record<string, any>, key: string) {\n delete this[key];\n}\n\nfunction setKey(this: Record<string, any>, key: string) {\n this[key] = true;\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {},\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const uniqueFields = ability.possibleRulesFor(action, subject)\n .filter(rule => rule.matchesConditions(subject))\n .reverse()\n .reduce((fields, rule) => {\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteKey : setKey;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, {} as Record<string, true>);\n\n return Object.keys(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>,\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || '',\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>,\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects,\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","args","action","subject","convert","query","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","rulesToFields","filter","values","Object","fields","fieldName","constructor","getRuleFields","deleteKey","key","setKey","permittedFieldsOf","options","fieldsFrom","uniqueFields","possibleRulesFor","matchesConditions","reverse","names","toggle","forEach","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}
import { createQueryTester, $eq, $ne, $lt, $lte, $gt, $gte, $in, $nin, $all, $size, $regex, $elemMatch, $exists } from 'sift';
function wrapArray(value) {
return Array.isArray(value) ? value : [value];
}
const TYPE_FIELD = '__caslSubjectType__';
function setSubjectType(type, object) {
if (object) {
if (!object.hasOwnProperty(TYPE_FIELD)) {
Object.defineProperty(object, TYPE_FIELD, {
value: type
});
} else if (type !== object[TYPE_FIELD]) {
throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);
}
}
return object;
}
function detectSubjectType(subject) {
if (!subject) {
return 'all';
}
if (typeof subject === 'string') {
return subject;
}
if (subject.hasOwnProperty(TYPE_FIELD)) {
return subject[TYPE_FIELD];
}
const Type = typeof subject === 'function' ? subject : subject.constructor;
return Type.modelName || Type.name;
}
function expandActions(aliasMap, rawActions) {
let actions = wrapArray(rawActions);
let i = 0;
while (i < actions.length) {
const action = actions[i++];
if (aliasMap.hasOwnProperty(action)) {
actions = actions.concat(aliasMap[action]);
}
}
return actions;
}
function assertAliasMap(aliasMap) {
if (aliasMap.manage) {
throw new Error('Cannot add alias for "manage" action because it is reserved');
}
Object.keys(aliasMap).forEach(alias => {
const hasError = alias === aliasMap[alias] || Array.isArray(aliasMap[alias]) && (aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1);
if (hasError) {
throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);
}
});
}
const identity = x => x;
function createAliasResolver(aliasMap) {
if (process.env.NODE_ENV !== 'production') {
assertAliasMap(aliasMap);
}
return action => expandActions(aliasMap, action);
}
class Rule {
constructor(rule, options) {
this._matchConditions = void 0;
this._matchField = void 0;
this.action = options.resolveAction(rule.actions || rule.action);
this.subject = rule.subject;
this.inverted = !!rule.inverted;
this.conditions = rule.conditions;
this.reason = rule.reason;
this.fields = !rule.fields || rule.fields.length === 0 ? undefined : wrapArray(rule.fields);
if ('actions' in rule) {
// eslint-disable-next-line
console.warn('Rule `actions` field is deprecated. Use `action` field instead');
}
if (this.conditions && options.conditionsMatcher) {
this._matchConditions = options.conditionsMatcher(this.conditions);
}
if (this.fields && options.fieldMatcher) {
this._matchField = options.fieldMatcher(this.fields);
}
}
matchesConditions(object) {
if (!this._matchConditions) {
return true;
}
if (!object || typeof object === 'string' || typeof object === 'function') {
return !this.inverted;
}
return this._matchConditions(object);
}
matchesField(field) {
if (!this._matchField) {
return true;
}
if (!field) {
return !this.inverted;
}
return this._matchField(field);
}
}
class RulesAnalyzer {
constructor(hasRules) {
this._isAllInverted = void 0;
this._hasPerFieldRules = false;
this._hasRuleWithEmptyFields = false;
this._isAllInverted = hasRules;
this._analyze = this._analyze.bind(this);
}
_analyze({
fields,
inverted
}) {
this._isAllInverted = this._isAllInverted && !!inverted;
if (!this._hasRuleWithEmptyFields && Array.isArray(fields) && !fields.length) {
this._hasRuleWithEmptyFields = true;
}
if (!this._hasPerFieldRules && fields && fields.length) {
this._hasPerFieldRules = true;
}
}
_validate(ruleOptions) {
if (this._isAllInverted) {
// eslint-disable-next-line
console.warn('Make sure your ability has direct rules, not only inverted ones. Otherwise `ability.can` will always return `false`.');
}
if (this._hasRuleWithEmptyFields) {
// eslint-disable-next-line
console.warn('[error in next major version]: There are rules with `fields` property being an empty array. This results in the same as not passing fields at all. Make sure to remove empty array or pass fields.');
}
if (this._hasPerFieldRules && !ruleOptions.fieldMatcher) {
throw new Error('Field level restrictions are ignored because "fieldMatcher" option is not specified. Did you unintentionally used PureAbility instead of Ability?');
}
}
}
class RuleIndex {
constructor(rules = [], options = {}) {
this._hasPerFieldRules = false;
this._mergedRules = Object.create(null);
this._events = Object.create(null);
this._indexedRules = Object.create(null);
this._rules = [];
this._ruleOptions = {
conditionsMatcher: options.conditionsMatcher,
fieldMatcher: options.fieldMatcher,
resolveAction: options.resolveAction || identity
};
Object.defineProperty(this, 'detectSubjectType', {
value: options.detectSubjectType || options.subjectName || detectSubjectType
});
Object.defineProperty(this, 'rules', {
get: () => this._rules
});
this.update(rules);
}
update(rules) {
const event = {
rules,
ability: this,
target: this
};
this._emit('update', event);
this._mergedRules = Object.create(null);
const analyser = new RulesAnalyzer(rules.length > 0);
const indexedRules = this._buildIndexFor(rules, analyser._analyze);
analyser._validate(this._ruleOptions);
this._indexedRules = indexedRules;
this._rules = rules;
this._hasPerFieldRules = analyser._hasPerFieldRules;
this._emit('updated', event);
return this;
}
_buildIndexFor(rawRules, iterator = identity) {
const indexedRules = Object.create(null);
for (let i = 0; i < rawRules.length; i++) {
iterator(rawRules[i], i);
const rule = new Rule(rawRules[i], this._ruleOptions);
const priority = rawRules.length - i - 1;
const actions = wrapArray(rule.action);
const subjects = wrapArray(rule.subject);
for (let k = 0; k < subjects.length; k++) {
const subject = this.detectSubjectType(subjects[k]);
indexedRules[subject] = indexedRules[subject] || Object.create(null);
for (let j = 0; j < actions.length; j++) {
const action = actions[j];
indexedRules[subject][action] = indexedRules[subject][action] || Object.create(null);
indexedRules[subject][action][priority] = rule;
}
}
}
return indexedRules;
}
possibleRulesFor(...args) {
const [action, subject] = args;
const subjectName = this.detectSubjectType(subject);
const mergedRules = this._mergedRules;
const key = `${subjectName}_${action}`;
if (!mergedRules[key]) {
mergedRules[key] = this._mergeRulesFor(action, subjectName);
}
return mergedRules[key];
}
_mergeRulesFor(action, subjectName) {
const subjects = subjectName === 'all' ? [subjectName] : [subjectName, 'all'];
const mergedRules = subjects.reduce((rules, subjectType) => {
const subjectRules = this._indexedRules[subjectType];
if (!subjectRules) {
return rules;
}
return Object.assign(rules, subjectRules[action], subjectRules.manage);
}, []); // TODO: think whether there is a better way to prioritize rules
// or convert sparse array to regular one
return mergedRules.filter(Boolean);
}
rulesFor(...args) {
const [action, subject, field] = args;
const rules = this.possibleRulesFor(action, subject);
if (field && typeof field !== 'string') {
throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');
}
if (!this._hasPerFieldRules) {
return rules;
}
return rules.filter(rule => rule.matchesField(field));
}
on(event, handler) {
const events = this._events;
let isAttached = true;
if (!events[event]) {
events[event] = [];
}
events[event].push(handler);
return () => {
if (isAttached) {
const index = events[event].indexOf(handler);
events[event].splice(index, 1);
isAttached = false;
}
};
}
_emit(eventName, event) {
const handlers = this._events[eventName];
if (handlers) {
handlers.slice(0).forEach(handler => handler(event));
}
}
}
class PureAbility extends RuleIndex {
can(...args) {
const rule = this.relevantRuleFor(...args);
return !!rule && !rule.inverted;
}
relevantRuleFor(...args) {
const rules = this.rulesFor(...args);
const subject = args[1];
for (let i = 0; i < rules.length; i++) {
if (rules[i].matchesConditions(subject)) {
return rules[i];
}
}
return null;
}
cannot(...args) {
return !this.can(...args);
}
}
const defaultOperations = {
$eq,
$ne,
$lt,
$lte,
$gt,
$gte,
$in,
$nin,
$all,
$size,
$regex,
$elemMatch,
$exists
};
function buildMongoQueryMatcher(operations) {
const options = {
operations: Object.assign({}, defaultOperations, operations)
};
return conditions => createQueryTester(conditions, options);
}
const mongoQueryMatcher = buildMongoQueryMatcher({});
const REGEXP_SPECIAL_CHARS = /[-/\\^$+?.()|[\]{}]/g;
const REGEXP_ANY = /\.?\*+\.?/g;
const REGEXP_STARS = /\*+/;
const REGEXP_DOT = /\./g;
function detectRegexpPattern(match, index, string) {
const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.' ? '+' : '*';
const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';
const pattern = match.replace(REGEXP_DOT, '\\$&').replace(REGEXP_STARS, matcher + quantifier);
return index + match.length === string.length ? `(?:${pattern})?` : pattern;
}
function escapeRegexp(match, index, string) {
if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {
return match;
}
return `\\${match}`;
}
function createPattern(fields) {
const patterns = fields.map(field => field.replace(REGEXP_SPECIAL_CHARS, escapeRegexp).replace(REGEXP_ANY, detectRegexpPattern));
const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];
return new RegExp(`^${pattern}$`);
}
const fieldPatternMatcher = fields => {
let pattern;
return field => {
if (typeof pattern === 'undefined') {
pattern = fields.every(f => f.indexOf('*') === -1) ? null : createPattern(fields);
}
return pattern === null ? fields.indexOf(field) !== -1 : pattern.test(field);
};
};
class Ability extends PureAbility {
constructor(rules, options) {
super(rules, Object.assign({
conditionsMatcher: mongoQueryMatcher,
fieldMatcher: fieldPatternMatcher
}, options));
}
}
class RuleBuilder {
constructor(rule) {
this.rule = rule;
}
because(reason) {
this.rule.reason = reason;
return this;
}
}
class AbilityBuilder {
constructor(AbilityType = PureAbility) {
this.rules = [];
this._AbilityType = AbilityType;
const self = this;
self.can = self.can.bind(self);
self.cannot = self.cannot.bind(self);
self.build = self.build.bind(self);
}
can(action, subject, conditionsOrFields, conditions) {
const rule = {
action
};
if (subject) {
rule.subject = subject;
if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {
rule.fields = conditionsOrFields;
} else if (typeof conditionsOrFields !== 'undefined') {
rule.conditions = conditionsOrFields;
}
if (typeof conditions !== 'undefined') {
rule.conditions = conditions;
}
}
this.rules.push(rule);
return new RuleBuilder(rule);
}
cannot(action, subject, conditionsOrFields, conditions) {
const builder = this.can(action, subject, conditionsOrFields, conditions);
builder.rule.inverted = true;
return builder;
}
build(options) {
return new this._AbilityType(this.rules, options);
}
}
function defineAbility(params, dsl) {
let options;
let define;
if (typeof params === 'function') {
define = params;
options = {};
} else if (typeof dsl === 'function') {
options = params;
define = dsl;
} else {
throw new Error('`defineAbility` expects to receive either options and dsl function or only dsl function');
}
const builder = new AbilityBuilder(Ability);
const result = define(builder.can, builder.cannot);
return result && typeof result.then === 'function' ? result.then(() => builder.build(options)) : builder.build(options);
}
const getDefaultErrorMessage = error => `Cannot execute "${error.action}" on "${error.subjectType}"`;
const NativeError = function NError(message) {
this.message = message;
};
NativeError.prototype = Object.create(Error.prototype);
class ForbiddenError extends NativeError {
static setDefaultMessage(messageOrFn) {
this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;
}
static from(ability) {
return new this(ability);
}
constructor(ability) {
super('');
this.ability = void 0;
this.field = void 0;
this.ability = ability;
if (typeof Error.captureStackTrace === 'function') {
this.name = 'ForbiddenError';
Error.captureStackTrace(this, this.constructor);
}
}
setMessage(message) {
this.message = message;
return this;
}
throwUnlessCan(...args) {
const rule = this.ability.relevantRuleFor(...args);
if (rule && !rule.inverted) {
return;
}
this.action = args[0];
this.subject = args[1];
this.subjectType = this.ability.detectSubjectType(args[1]);
this.field = args[2];
const reason = rule ? rule.reason : ''; // eslint-disable-next-line no-underscore-dangle
this.message = this.message || reason || this.constructor._defaultErrorMessage(this);
throw this; // eslint-disable-line
}
}
ForbiddenError._defaultErrorMessage = getDefaultErrorMessage;
export { Ability, AbilityBuilder, ForbiddenError, PureAbility, buildMongoQueryMatcher, createAliasResolver, defineAbility, detectSubjectType, fieldPatternMatcher, getDefaultErrorMessage, mongoQueryMatcher, setSubjectType as subject, wrapArray };
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/RulesAnalyzer.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>,\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport const identity = <T>(x: T) => x;\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n","import { wrapArray } from './utils';\nimport {\n MatchConditions,\n RuleOptions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n} from './types';\nimport { RawRule } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nexport class Rule<A extends Abilities, C> {\n private readonly _matchConditions: MatchConditions | undefined;\n private readonly _matchField: MatchField<string> | undefined;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n\n constructor(rule: RawRule<ToAbilityTypes<A>, C>, options: RuleOptions<A, C>) {\n this.action = options.resolveAction((rule as any).actions || (rule as any).action);\n this.subject = rule.subject;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = !rule.fields || rule.fields.length === 0\n ? undefined\n : wrapArray(rule.fields);\n\n if ('actions' in rule) {\n // eslint-disable-next-line\n console.warn('Rule `actions` field is deprecated. Use `action` field instead');\n }\n\n if (this.conditions && options.conditionsMatcher) {\n this._matchConditions = options.conditionsMatcher(this.conditions);\n }\n\n if (this.fields && options.fieldMatcher) {\n this._matchField = options.fieldMatcher(this.fields);\n }\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this._matchConditions) {\n return true;\n }\n\n if (!object || typeof object === 'string' || typeof object === 'function') {\n return !this.inverted;\n }\n\n return this._matchConditions(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this._matchField) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._matchField(field);\n }\n}\n","import { RawRuleFrom } from './RawRule';\nimport { Abilities, RuleOptions } from './types';\n\nexport default class RulesAnalyzer<A extends Abilities, C> {\n public _isAllInverted: boolean;\n public _hasPerFieldRules: boolean = false;\n public _hasRuleWithEmptyFields: boolean = false;\n\n constructor(hasRules: boolean) {\n this._isAllInverted = hasRules;\n this._analyze = this._analyze.bind(this);\n }\n\n _analyze({ fields, inverted }: RawRuleFrom<A, C>) {\n this._isAllInverted = this._isAllInverted && !!inverted;\n\n if (!this._hasRuleWithEmptyFields && Array.isArray(fields) && !fields.length) {\n this._hasRuleWithEmptyFields = true;\n }\n\n if (!this._hasPerFieldRules && fields && fields.length) {\n this._hasPerFieldRules = true;\n }\n }\n\n _validate(ruleOptions: RuleOptions<A, C>) {\n if (this._isAllInverted) {\n // eslint-disable-next-line\n console.warn('Make sure your ability has direct rules, not only inverted ones. Otherwise `ability.can` will always return `false`.');\n }\n\n if (this._hasRuleWithEmptyFields) {\n // eslint-disable-next-line\n console.warn('[error in next major version]: There are rules with `fields` property being an empty array. This results in the same as not passing fields at all. Make sure to remove empty array or pass fields.');\n }\n\n if (this._hasPerFieldRules && !ruleOptions.fieldMatcher) {\n throw new Error('Field level restrictions are ignored because \"fieldMatcher\" option is not specified. Did you unintentionally used PureAbility instead of Ability?');\n }\n }\n}\n","import { Rule } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n DetectSubjectType,\n ResolveAction,\n CanParameters,\n Abilities,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n RuleOptions,\n} from './types';\nimport { wrapArray, detectSubjectType, identity } from './utils';\nimport RulesAnalyzer from './RulesAnalyzer';\n\ntype AnyRuleIndex = RuleIndex<any, any, any>;\n\nexport interface RuleIndexOptions<A extends Abilities, Conditions> {\n /** @deprecated use \"detectSubjectType\" option instead */\n subjectName?: this['detectSubjectType']\n detectSubjectType?: DetectSubjectType<Normalize<A>[1]>\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction?: ResolveAction<Normalize<A>[0]>\n}\n\nexport type Generics<T extends AnyRuleIndex> = T extends AnyRuleIndex\n ? { abilities: T['za'], conditions: T['zc'] }\n : never;\n\nexport type RuleOf<T extends AnyRuleIndex> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends AnyRuleIndex> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends AnyRuleIndex> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport interface UpdateEvent<T extends AnyRuleIndex> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<T extends AnyRuleIndex, Event extends {} = {}> = {\n [K in keyof EventsMap<T, Event>]: EventHandler<EventsMap<T, Event>[K]>[]\n};\n\ninterface EventsMap<T extends AnyRuleIndex, Event extends {} = {}> {\n update: UpdateEvent<T> & Event\n updated: UpdateEvent<T> & Event\n}\n\ninterface IndexTree<A extends Abilities, C> {\n [subject: string]: {\n [action: string]: {\n [priority: number]: Rule<A, C>\n }\n }\n}\n\ntype RuleIterator<A extends Abilities, C> = (rule: RawRuleFrom<A, C>, index: number) => void;\n\nexport type Unsubscribe = () => void;\n\nexport class RuleIndex<A extends Abilities, Conditions, BaseEvent extends {} = {}> {\n private _hasPerFieldRules: boolean = false;\n private _mergedRules: Record<string, Rule<A, Conditions>[]> = Object.create(null);\n private _events: Events<this, BaseEvent> = Object.create(null);\n private _indexedRules: IndexTree<A, Conditions> = Object.create(null);\n private _rules: this['rules'] = [];\n readonly rules!: RawRuleFrom<A, Conditions>[];\n readonly _ruleOptions!: RuleOptions<A, Conditions>;\n readonly detectSubjectType!: DetectSubjectType<Normalize<A>[1]>;\n /** @private hacky property to track Abilities type */\n readonly za!: A;\n /** @private hacky property to track Conditions type */\n readonly zc!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {},\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n Object.defineProperty(this, 'detectSubjectType', {\n value: options.detectSubjectType || options.subjectName || detectSubjectType,\n });\n Object.defineProperty(this, 'rules', { get: () => this._rules });\n this.update(rules);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): this {\n const event = {\n rules,\n ability: this,\n target: this,\n } as unknown as UpdateEvent<this> & BaseEvent;\n\n this._emit('update', event);\n this._mergedRules = Object.create(null);\n\n const analyser = new RulesAnalyzer<A, Conditions>(rules.length > 0);\n const indexedRules = this._buildIndexFor(rules, analyser._analyze);\n\n analyser._validate(this._ruleOptions);\n this._indexedRules = indexedRules;\n this._rules = rules;\n this._hasPerFieldRules = analyser._hasPerFieldRules;\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(\n rawRules: RawRuleFrom<A, Conditions>[],\n iterator: RuleIterator<A, Conditions> = identity,\n ) {\n const indexedRules: IndexTree<A, Conditions> = Object.create(null);\n\n for (let i = 0; i < rawRules.length; i++) {\n iterator(rawRules[i], i);\n const rule = new Rule(rawRules[i], this._ruleOptions);\n const priority = rawRules.length - i - 1;\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject);\n\n for (let k = 0; k < subjects.length; k++) {\n const subject = this.detectSubjectType(subjects[k]);\n indexedRules[subject] = indexedRules[subject] || Object.create(null);\n\n for (let j = 0; j < actions.length; j++) {\n const action = actions[j];\n indexedRules[subject][action] = indexedRules[subject][action] || Object.create(null);\n indexedRules[subject][action][priority] = rule;\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: CanParameters<A, false>) {\n const [action, subject] = args;\n const subjectName = this.detectSubjectType(subject);\n const mergedRules = this._mergedRules;\n const key = `${subjectName}_${action}`;\n\n if (!mergedRules[key]) {\n mergedRules[key] = this._mergeRulesFor(action, subjectName);\n }\n\n return mergedRules[key];\n }\n\n private _mergeRulesFor(action: string, subjectName: string) {\n const subjects = subjectName === 'all' ? [subjectName] : [subjectName, 'all'];\n const mergedRules = subjects.reduce((rules, subjectType) => {\n const subjectRules = this._indexedRules[subjectType];\n\n if (!subjectRules) {\n return rules;\n }\n\n return Object.assign(rules, subjectRules[action], subjectRules.manage);\n }, []);\n\n // TODO: think whether there is a better way to prioritize rules\n // or convert sparse array to regular one\n return mergedRules.filter(Boolean);\n }\n\n rulesFor(...args: CanParameters<A>) {\n const [action, subject, field] = args;\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subject);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this, BaseEvent>>(\n event: T,\n handler: EventHandler<EventsMap<this, BaseEvent>[T]>,\n ): Unsubscribe {\n const events = this._events;\n let isAttached = true;\n\n if (!events[event]) {\n events[event] = [];\n }\n\n events[event].push(handler);\n\n return () => {\n if (isAttached) {\n const index = events[event].indexOf(handler);\n events[event].splice(index, 1);\n isAttached = false;\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this, BaseEvent>>(\n eventName: T,\n event: EventsMap<this, BaseEvent>[T],\n ) {\n const handlers = this._events[eventName];\n\n if (handlers) {\n handlers.slice(0).forEach(handler => handler(event));\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, RawRuleOf } from './RuleIndex';\nimport { Abilities, CanParameters } from './types';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = PureAbility<any, any>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (\n rules?: RawRuleOf<T>[],\n options?: AbilityOptionsOf<T>\n) => T;\n\ninterface AbilityEvent<A extends Abilities = Abilities, Conditions = unknown> {\n /** @deprecated use \"target\" property instead */\n ability: this['target']\n target: PureAbility<A, Conditions>\n}\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown,\n> extends RuleIndex<A, Conditions, AbilityEvent<A, Conditions>> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>) {\n const rules = this.rulesFor(...args);\n const subject = args[1];\n\n for (let i = 0; i < rules.length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n createQueryTester as sift,\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $elemMatch,\n $exists,\n} from 'sift';\nimport { ConditionsMatcher as Matcher } from '../types';\n\nconst defaultOperations = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $elemMatch,\n $exists,\n};\n\ntype RegExpOptions<T> = { $regex: T, $options?: string };\ntype Primitive = Record<PropertyKey, any> | string | number | null | boolean | undefined;\nexport type MongoQueryOperators = {\n $eq?: any,\n $ne?: any,\n $lt?: string | number | Date,\n $lte?: string | number | Date,\n $gt?: string | number | Date,\n $gte?: string | number | Date,\n $in?: any[],\n $nin?: any[],\n $all?: any[],\n /** checks by array length */\n $size?: number,\n $regex?: RegExp | RegExpOptions<string> | RegExpOptions<RegExp>,\n /** checks the shape of array item */\n $elemMatch?: {\n [k in Exclude<keyof MongoQueryOperators, '$elemMatch'>]?: MongoQueryOperators[k]\n },\n /** checks that property exists */\n $exists?: boolean\n};\n\nexport type MongoQuery<AdditionalOperators = never> =\n Record<PropertyKey, MongoQueryOperators | Primitive | AdditionalOperators>;\nexport function buildMongoQueryMatcher<T extends object>(\n operations: Record<keyof T, any>,\n): Matcher<MongoQuery | T> {\n const options = { operations: { ...defaultOperations, ...operations } };\n return conditions => sift(conditions as any, options);\n}\nexport const mongoQueryMatcher = buildMongoQueryMatcher({});\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { RawRuleFrom } from './RawRule';\nimport { fieldPatternMatcher } from './matchers/field';\n\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery<any> = MongoQuery,\n> extends PureAbility<A, C> {\n constructor(rules?: RawRuleFrom<A, C>[], options?: AbilityOptions<A, C>) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Ability<any, MongoQuery>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass, PureAbility } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n AbilityTypes,\n ToAbilityTypes,\n AbilityParameters,\n} from './types';\nimport { RawRule } from './RawRule';\n\nclass RuleBuilder<T extends RawRule<any, any>> {\n public rule!: T;\n\n constructor(rule: T) {\n this.rule = rule;\n }\n\n because(reason: string): this {\n this.rule.reason = reason;\n return this;\n }\n}\n\ntype CanFunction<T extends AbilityTypes, C, WithFields = true> = T extends AbilityTuple\n ? WithFields extends true\n // eslint-disable-next-line max-len\n ? (action: T[0] | T[0][], subject: E<T[1]> | E<T[1]>[], fields?: string | string[], conditions?: C) => 0\n : (action: T[0] | T[0][], subject: E<T[1]> | E<T[1]>[], conditions?: C) => 0\n : never;\n\nexport type BuilderCanParameters<T extends AnyAbility, WithFields extends boolean = false> =\n AbilityParameters<\n Generics<T>['abilities'],\n CanFunction<ToAbilityTypes<Generics<T>['abilities']>, Generics<T>['conditions'], WithFields>,\n (action: Generics<T>['abilities'] | Generics<T>['abilities'][]) => 0\n >;\n\nexport class AbilityBuilder<T extends AnyAbility = PureAbility> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: AbilityClass<T>;\n\n constructor(AbilityType: AbilityClass<T> = PureAbility as AbilityClass<T>) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can(...args: BuilderCanParameters<T>): RuleBuilder<RawRuleOf<T>>\n can(...args: BuilderCanParameters<T, true>): RuleBuilder<RawRuleOf<T>>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<RawRuleOf<T>> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot(...args: BuilderCanParameters<T>): RuleBuilder<RawRuleOf<T>>\n cannot(...args: BuilderCanParameters<T, true>): RuleBuilder<RawRuleOf<T>>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<RawRuleOf<T>> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder.rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>): T {\n return new this._AbilityType(this.rules, options);\n }\n}\n\ntype AsyncDSL<T extends AnyMongoAbility> = (\n can: AbilityBuilder<T>['can'],\n cannot: AbilityBuilder<T>['cannot']\n) => Promise<void>;\ntype DSL<T extends AnyMongoAbility> = (...args: Parameters<AsyncDSL<T>>) => void;\n\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n dsl: AsyncDSL<T>\n): Promise<T>;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n params: AbilityOptionsOf<T>,\n dsl: AsyncDSL<T>\n): Promise<T>;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n dsl: DSL<T>\n): T;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n params: AbilityOptionsOf<T>,\n dsl: DSL<T>\n): T;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n params: AbilityOptionsOf<T> | DSL<T> | AsyncDSL<T>,\n dsl?: DSL<T> | AsyncDSL<T>,\n): T | Promise<T> {\n let options: AbilityOptionsOf<T>;\n let define: DSL<T> | AsyncDSL<T>;\n\n if (typeof params === 'function') {\n define = params;\n options = {};\n } else if (typeof dsl === 'function') {\n options = params;\n define = dsl;\n } else {\n throw new Error('`defineAbility` expects to receive either options and dsl function or only dsl function');\n }\n\n const builder = new AbilityBuilder<T>(Ability as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n return result && typeof result.then === 'function'\n ? result.then(() => builder.build(options))\n : builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<U extends AnyAbility>(ability: U) {\n return new this<U>(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = this.ability.detectSubjectType(args[1]);\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","detectSubjectType","subject","Type","constructor","modelName","name","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","identity","x","createAliasResolver","process","env","NODE_ENV","Rule","rule","options","_matchConditions","_matchField","resolveAction","inverted","conditions","reason","fields","undefined","console","warn","conditionsMatcher","fieldMatcher","matchesConditions","matchesField","field","RulesAnalyzer","hasRules","_isAllInverted","_hasPerFieldRules","_hasRuleWithEmptyFields","_analyze","bind","_validate","ruleOptions","RuleIndex","rules","_mergedRules","create","_events","_indexedRules","_rules","_ruleOptions","subjectName","get","update","event","ability","target","_emit","analyser","indexedRules","_buildIndexFor","rawRules","iterator","priority","subjects","k","j","possibleRulesFor","args","mergedRules","key","_mergeRulesFor","reduce","subjectType","subjectRules","assign","filter","Boolean","rulesFor","on","handler","events","isAttached","push","index","splice","eventName","handlers","slice","PureAbility","can","relevantRuleFor","cannot","defaultOperations","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$elemMatch","$exists","buildMongoQueryMatcher","operations","sift","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","map","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","because","AbilityBuilder","AbilityType","_AbilityType","self","build","conditionsOrFields","builder","defineAbility","params","dsl","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}
+57
-2

@@ -5,2 +5,57 @@ # Change Log

# [5.1.0-next.12](https://github.com/stalniy/casl/compare/@casl/ability@5.1.0-next.11...@casl/ability@5.1.0-next.12) (2020-11-18)
### Bug Fixes
* **ability:** replaces getters with functions to ensure terser properly minifies them ([386ecb6](https://github.com/stalniy/casl/commit/386ecb6df79aa466f10e3e2eccea4d3771c97ad4))
* **extra:** makes `permittedFieldsOf` to iterate from the end of array ([81e6409](https://github.com/stalniy/casl/commit/81e64096eb780762e117dae05cfa7cafad801aa3))
### Code Refactoring
* **extra:** makes `fieldsFrom` option to be mandatory for `permittedFieldsOf` [skip release] ([df29b0d](https://github.com/stalniy/casl/commit/df29b0d7364ab1964d4d7b3b98212615beaa4952))
* **types:** restricts which utility types are exported by library ([e98618f](https://github.com/stalniy/casl/commit/e98618f34d0a29358644b6c11ce87398ffeb2437))
### Reverts
* **builder:** reverts back `AbilityBuilder` generic parameter ([aa7b45f](https://github.com/stalniy/casl/commit/aa7b45f69c4fc7b603b8b5be3e9982d370d3398a))
### BREAKING CHANGES
* **types:** types `AliasesMap`, `TaggedInterface`, `AbilityTupleType`, `ToAbilityTypes`, `AnyObject` are no longer exported by the library
* **extra:** makes `fieldsFrom` option to be mandatory for `permittedFieldsO
f`. This reduces confusion around why `permittedFieldsOf` returns empty array when user can manage entity fields. So, now this logic is just explicit and clear
**Before**
```js
import { defineAbility } from '@casl/ability';
import { permittedFieldsOf } from '@casl/ability/extra';
const ability = defineAbility((can) => {
can('read', 'Article');
});
const fields = permittedFieldsOf(ability, 'read', 'Article'); // []
```
**After**
```js
import { defineAbility } from '@casl/ability';
import { permittedFieldsOf } from '@casl/ability/extra';
const ability = defineAbility((can) => {
can('read', 'Article');
});
const ARTICLE_FIELDS = ['id', 'title', 'description'];
const fields = permittedFieldsOf(ability, 'read', 'Article', {
fieldsFrom: rule => rule.fields || ARTICLE_FIELDS
}); // ['id', 'title', 'description']
```
# [5.1.0-next.11](https://github.com/stalniy/casl/compare/@casl/ability@5.1.0-next.10...@casl/ability@5.1.0-next.11) (2020-10-17)

@@ -52,3 +107,3 @@

Also it's important to note that if you want it's no longer possible to use classes and strings as subject types interchangably together as it was before. Now, if you want to use classes, you should use them everywhere:
Also it's important to note that it's no longer possible to use classes and strings as subject types interchangeably together as it was before. Now, if you want to use classes, you should use them everywhere:

@@ -205,3 +260,3 @@ **Before**

* **builder:** changes main generic parameter to be a class instead of instance and makes `defineAbility` to accept options as the 2nd argument.
* **builder:** changes main generic parameter restriction to accept any class and makes `defineAbility` to accept options as the 2nd argument.

@@ -208,0 +263,0 @@ **Before**

+1
-1

@@ -1,2 +0,2 @@

import{buildOr as r,buildAnd as n}from"@ucast/mongo2js";function t(r){return Array.isArray(r)?r:[r]}function e(r,n,t){var e=r;var u=n;if(-1!==n.indexOf(".")){var i=n.split(".");u=i.pop();e=i.reduce((function(r,n){r[n]=r[n]||{};return r[n]}),r)}e[u]=t}function u(r,n,t,e){var u=Object.create(null);var i=r.rulesFor(n,t);for(var f=0;f<i.length;f++){var o=i[f];var a=o.inverted?"$and":"$or";if(!o.conditions)if(o.inverted)break;else{delete u[a];return u}else{u[a]=u[a]||[];u[a].push(e(o))}}return u.$or?u:null}function i(r){if(!r.ast)throw new Error('Ability rule "'+JSON.stringify(r)+'" does not have "ast" property. So, cannot be used to generate AST');return r.ast}function f(t,e,f){var o=u(t,e,f,i);if(null===o)return null;if(!o.$and)return o.$or?r(o.$or):n([]);if(o.$or)o.$and.push(r(o.$or));return n(o.$and)}function o(r,n,t){return r.rulesFor(n,t).reduce((function(r,n){if(n.inverted||!n.conditions)return r;return Object.keys(n.conditions).reduce((function(r,t){var u=n.conditions[t];if(!u||u.constructor!==Object)e(r,t,u);return r}),r)}),{})}var a=function r(n){return n.fields};function c(r){this.delete(r)}function v(r){this.add(r)}function l(r,n,t,e){if(void 0===e)e={};var u=e.fieldsFrom||a;var i=r.detectSubjectType(t);var f=r.possibleRulesFor(n,i).reduceRight((function(r,n){if(!n.matchesConditions(t))return r;var e=u(n);if(e){var i=n.inverted?c:v;e.forEach(i,r)}return r}),new Set);return Array.from(f)}var s=function r(n){return Array.isArray(n)?n.join(","):n};function b(r,n){return r.map((function(r){var e=[s(r.action||r.actions),"function"===typeof n?t(r.subject).map(n).join(","):s(r.subject),r.conditions||0,r.inverted?1:0,r.fields?s(r.fields):0,r.reason||""];while(!e[e.length-1])e.pop();return e}))}function y(r,n){return r.map((function(r){var t=r[0],e=r[1],u=r[2],i=r[3],f=r[4],o=r[5];var a=e.split(",");var c={inverted:!!i,action:t.split(","),subject:"function"===typeof n?a.map(n):a};if(u)c.conditions=u;if(f)c.fields=f.split(",");if(o)c.reason=o;return c}))}export{b as packRules,l as permittedFieldsOf,f as rulesToAST,o as rulesToFields,u as rulesToQuery,y as unpackRules};
import{buildOr as r,buildAnd as n}from"@ucast/mongo2js";function t(r){return Array.isArray(r)?r:[r]}function e(r,n,t){var e=r;var u=n;if(-1!==n.indexOf(".")){var i=n.split(".");u=i.pop();e=i.reduce((function(r,n){r[n]=r[n]||{};return r[n]}),r)}e[u]=t}function u(r,n,t,e){var u=Object.create(null);var i=r.rulesFor(n,t);for(var o=0;o<i.length;o++){var a=i[o];var f=a.inverted?"$and":"$or";if(!a.conditions)if(a.inverted)break;else{delete u[f];return u}else{u[f]=u[f]||[];u[f].push(e(a))}}return u.$or?u:null}function i(r){if(!r.ast)throw new Error('Ability rule "'+JSON.stringify(r)+'" does not have "ast" property. So, cannot be used to generate AST');return r.ast}function o(t,e,o){var a=u(t,e,o,i);if(null===a)return null;if(!a.$and)return a.$or?r(a.$or):n([]);if(a.$or)a.$and.push(r(a.$or));return n(a.$and)}function a(r,n,t){return r.rulesFor(n,t).reduce((function(r,n){if(n.inverted||!n.conditions)return r;return Object.keys(n.conditions).reduce((function(r,t){var u=n.conditions[t];if(!u||u.constructor!==Object)e(r,t,u);return r}),r)}),{})}function f(r,n,t,e){var u=r.detectSubjectType(t);var i=r.possibleRulesFor(n,u);var o=new Set;var a=o.delete.bind(o);var f=o.add.bind(o);var v=i.length;while(v--){var c=i[v];if(c.matchesConditions(t)){var l=c.inverted?a:f;e.fieldsFrom(c).forEach(l)}}return Array.from(o)}var v=function r(n){return Array.isArray(n)?n.join(","):n};function c(r,n){return r.map((function(r){var e=[v(r.action||r.actions),"function"===typeof n?t(r.subject).map(n).join(","):v(r.subject),r.conditions||0,r.inverted?1:0,r.fields?v(r.fields):0,r.reason||""];while(!e[e.length-1])e.pop();return e}))}function l(r,n){return r.map((function(r){var t=r[0],e=r[1],u=r[2],i=r[3],o=r[4],a=r[5];var f=e.split(",");var v={inverted:!!i,action:t.split(","),subject:"function"===typeof n?f.map(n):f};if(u)v.conditions=u;if(o)v.fields=o.split(",");if(a)v.reason=a;return v}))}export{c as packRules,f as permittedFieldsOf,o as rulesToAST,a as rulesToFields,u as rulesToQuery,l as unpackRules};
//# sourceMappingURL=extra.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteItem(this: Set<string>, item: string) {\n this.delete(item);\n}\n\nfunction addItem(this: Set<string>, item: string) {\n this.add(item);\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {}\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const subjectType = ability.detectSubjectType(subject);\n const uniqueFields = ability.possibleRulesFor(action, subjectType)\n .reduceRight((fields, rule) => {\n if (!rule.matchesConditions(subject)) {\n return fields;\n }\n\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteItem : addItem;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, new Set<string>());\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","getRuleFields","deleteItem","item","delete","addItem","add","permittedFieldsOf","subject","options","fieldsFrom","detectSubjectType","uniqueFields","possibleRulesFor","reduceRight","matchesConditions","names","toggle","forEach","Set","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}
{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[];\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom: GetRuleFields<RuleOf<T>>\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T>\n): string[] {\n const subjectType = ability.detectSubjectType(subject);\n const rules = ability.possibleRulesFor(action, subjectType);\n const uniqueFields = new Set<string>();\n const deleteItem = uniqueFields.delete.bind(uniqueFields);\n const addItem = uniqueFields.add.bind(uniqueFields);\n let i = rules.length;\n\n while (i--) {\n const rule = rules[i];\n if (rule.matchesConditions(subject)) {\n const toggle = rule.inverted ? deleteItem : addItem;\n options.fieldsFrom(rule).forEach(toggle);\n }\n }\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","permittedFieldsOf","subject","options","detectSubjectType","possibleRulesFor","uniqueFields","Set","deleteItem","delete","bind","addItem","add","matchesConditions","toggle","fieldsFrom","forEach","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}

@@ -1,2 +0,2 @@

import{createFactory as t,$eq as r,$ne as n,$lt as i,$lte as e,$gt as u,$gte as o,$in as a,$nin as s,$all as f,$size as c,$regex as h,$options as v,$elemMatch as l,$exists as d,eq as p,ne as y,lt as w,lte as g,gt as b,gte as $,within as m,nin as E,all as j,size as M,regex as x,elemMatch as O,exists as A,and as _}from"@ucast/mongo2js";function k(t,r){for(var n=0;n<r.length;n++){var i=r[n];i.enumerable=i.enumerable||false;i.configurable=true;if("value"in i)i.writable=true;Object.defineProperty(t,i.key,i)}}function z(t,r,n){if(r)k(t.prototype,r);if(n)k(t,n);return t}function R(){R=Object.assign||function(t){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i))t[i]=n[i]}return t};return R.apply(this,arguments)}function C(t,r){t.prototype=Object.create(r.prototype);t.prototype.constructor=t;t.__proto__=r}function F(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function T(t){return Array.isArray(t)?t:[t]}var q="__caslSubjectType__";function S(t,r){if(r)if(!r.hasOwnProperty(q))Object.defineProperty(r,q,{value:t});else if(t!==r[q])throw new Error("Trying to cast object to subject type "+t+" but previously it was casted to "+r[q]);return r}var Y=function t(r){var n=typeof r;return"string"===n||"function"===n};var L=function t(r){return r.modelName||r.name};var B=function t(r){return"string"===typeof r?r:L(r)};function D(t){if(!t)return"all";if(t.hasOwnProperty(q))return t[q];return L(t.constructor)}function G(t,r){var n=T(r);var i=0;while(i<n.length){var e=n[i++];if(t.hasOwnProperty(e))n=n.concat(t[e])}return n}function H(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach((function(r){var n=r===t[r]||Array.isArray(t[r])&&(-1!==t[r].indexOf(r)||-1!==t[r].indexOf("manage"));if(n)throw new Error("Attempt to alias action to itself: "+r+" -> "+t[r])}))}function I(t){if("production"!==process.env.NODE_ENV)H(t);return function(r){return G(t,r)}}function J(t,r,n){for(var i=n;i<r.length;i++)t.push(r[i])}function K(t,r){if(!t||!t.length)return r||[];if(!r||!r.length)return t||[];var n=0;var i=0;var e=[];while(n<t.length&&i<r.length)if(t[n].priority<r[i].priority){e.push(t[n]);n++}else{e.push(r[i]);i++}J(e,t,n);J(e,r,i);return e}function N(t,r,n){var i=t.get(r);if(!i){i=n();t.set(r,i)}return i}var P=function t(r){return r};function Q(t,r){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!r.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!r.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}var U=function(){function t(t,r,n){if(void 0===n)n=0;this.t=void 0;this.i=void 0;Q(t,r);this.action=r.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?T(t.fields):void 0;this.priority=n;this.u=r}var r=t.prototype;r.matchesConditions=function t(r){if(!this.conditions)return true;if(!r||Y(r))return!this.inverted;return this.o(r)};r.matchesField=function t(r){if(!this.fields)return true;if(!r)return!this.inverted;return this.s(r)};z(t,[{key:"_lazyMatchConditions",get:function t(){if(this.conditions&&!this.t)this.t=this.u.conditionsMatcher(this.conditions);return this.t}},{key:"_lazyMatchField",get:function t(){if(this.fields&&!this.i)this.i=this.u.fieldMatcher(this.fields);return this.i}},{key:"ast",get:function t(){return this.o?this.o.ast:void 0}}]);return t}();var V=function t(r,n){var i={value:r,prev:n,next:null};if(n)n.next=i;return i};var W=function t(r){if(r.next)r.next.prev=r.prev;if(r.prev)r.prev.next=r.next;r.next=r.prev=null};var X=function t(){return{rules:[],merged:false}};var Z=function t(){return new Map};var tt=function t(r,n){if(!r.h&&n.fields)r.h=true};var rt=function(){function t(t,r){if(void 0===t)t=[];if(void 0===r)r={};this.h=false;this.v=new Map;this.l={conditionsMatcher:r.conditionsMatcher,fieldMatcher:r.fieldMatcher,resolveAction:r.resolveAction||P};this.p=r.detectSubjectType||D;this.g=t;this.$=this.m(t)}var r=t.prototype;r.detectSubjectType=function t(r){return Y(r)?r:this.p(r)};r.update=function t(r){var n={rules:r,ability:this,target:this};this.j("update",n);this.g=r;this.$=this.m(r);this.j("updated",n);return this};r.m=function t(r){var n=new Map;for(var i=r.length-1;i>=0;i--){var e=r.length-i-1;var u=new U(r[i],this.l,e);var o=T(u.action);var a=T(u.subject||"all");tt(this,u);for(var s=0;s<a.length;s++){var f=N(n,a[s],Z);for(var c=0;c<o.length;c++)N(f,o[c],X).rules.push(u)}}return n};r.possibleRulesFor=function t(r,n){if(void 0===n)n="all";if(!Y(n))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');var i=N(this.$,n,Z);var e=N(i,r,X);if(e.merged)return e.rules;var u="manage"!==r&&i.has("manage")?i.get("manage").rules:void 0;var o=K(e.rules,u);if("all"!==n)o=K(o,this.possibleRulesFor(r,"all"));e.rules=o;e.merged=true;return o};r.rulesFor=function t(r,n,i){var e=this.possibleRulesFor(r,n);if(i&&"string"!==typeof i)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return e;return e.filter((function(t){return t.matchesField(i)}))};r.on=function t(r,n){var i=this;var e=this.v.get(r)||null;var u=V(n,e);this.v.set(r,u);return function(){if(!u.next&&!u.prev&&i.v.get(r)===u)i.v.delete(r);else W(u)}};r.j=function t(r,n){var i=this.v.get(r)||null;while(null!==i){var e=i.prev;i.value(n);i=e}};z(t,[{key:"rules",get:function t(){return this.g}}]);return t}();var nt=function(t){C(r,t);function r(){return t.apply(this,arguments)||this}var n=r.prototype;n.can=function t(){var r=this.relevantRuleFor.apply(this,arguments);return!!r&&!r.inverted};n.relevantRuleFor=function t(r,n,i){var e=this.detectSubjectType(n);var u=this.rulesFor(r,e,i);for(var o=0,a=u.length;o<a;o++)if(u[o].matchesConditions(n))return u[o];return null};n.cannot=function t(){return!this.can.apply(this,arguments)};return r}(rt);var it={$eq:r,$ne:n,$lt:i,$lte:e,$gt:u,$gte:o,$in:a,$nin:s,$all:f,$size:c,$regex:h,$options:v,$elemMatch:l,$exists:d};var et={eq:p,ne:y,lt:w,lte:g,gt:b,gte:$,in:m,nin:E,all:j,size:M,regex:x,elemMatch:O,exists:A,and:_};var ut=function r(n,i,e){return t(R({},it,n),R({},et,i),e)};var ot=t(it,et);var at=/[-/\\^$+?.()|[\]{}]/g;var st=/\.?\*+\.?/g;var ft=/\*+/;var ct=/\./g;function ht(t,r,n){var i="*"===n[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";var e=-1===t.indexOf("**")?"[^.]":".";var u=t.replace(ct,"\\$&").replace(ft,e+i);return r+t.length===n.length?"(?:"+u+")?":u}function vt(t,r,n){if("."===t&&("*"===n[r-1]||"*"===n[r+1]))return t;return"\\"+t}function lt(t){var r=t.map((function(t){return t.replace(at,vt).replace(st,ht)}));var n=r.length>1?"(?:"+r.join("|")+")":r[0];return new RegExp("^"+n+"$")}var dt=function t(r){var n;return function(t){if("undefined"===typeof n)n=r.every((function(t){return-1===t.indexOf("*")}))?null:lt(r);return null===n?-1!==r.indexOf(t):n.test(t)}};var pt=function(t){C(r,t);function r(r,n){if(void 0===r)r=[];if(void 0===n)n={};return t.call(this,r,R({conditionsMatcher:ot,fieldMatcher:dt},n))||this}return r}(nt);var yt=function(){function t(t){this.M=t}var r=t.prototype;r.because=function t(r){this.M.reason=r;return this};return t}();var wt=function(){function t(t){this.rules=[];this.O=t;var r=this;r.can=r.can.bind(r);r.cannot=r.cannot.bind(r);r.build=r.build.bind(r)}var r=t.prototype;r.can=function t(r,n,i,e){var u={action:r};if(n){u.subject=n;if(Array.isArray(i)||"string"===typeof i)u.fields=i;else if("undefined"!==typeof i)u.conditions=i;if("undefined"!==typeof e)u.conditions=e}this.rules.push(u);return new yt(u)};r.cannot=function t(r,n,i,e){var u=this.can(r,n,i,e);u.M.inverted=true;return u};r.build=function t(r){return new this.O(this.rules,r)};return t}();function gt(t,r){var n=new wt(pt);var i=t(n.can,n.cannot);if(i&&"function"===typeof i.then)return i.then((function(){return n.build(r)}));return n.build(r)}var bt=function t(r){return'Cannot execute "'+r.action+'" on "'+r.subjectType+'"'};var $t=function t(r){this.message=r};$t.prototype=Object.create(Error.prototype);var mt=function(t){C(r,t);r.setDefaultMessage=function t(r){this.A="string"===typeof r?function(){return r}:r};r.from=function t(r){return new this(r)};function r(r){var n;n=t.call(this,"")||this;n.field=void 0;n.ability=r;if("function"===typeof Error.captureStackTrace){n.name="ForbiddenError";Error.captureStackTrace(F(n),n.constructor)}return n}var n=r.prototype;n.setMessage=function t(r){this.message=r;return this};n.throwUnlessCan=function t(){var r;var n=(r=this.ability).relevantRuleFor.apply(r,arguments);if(n&&!n.inverted)return;this.action=arguments.length<=0?void 0:arguments[0];this.subject=arguments.length<=1?void 0:arguments[1];this.subjectType=B(this.ability.detectSubjectType(arguments.length<=1?void 0:arguments[1]));this.field=arguments.length<=2?void 0:arguments[2];var i=n?n.reason:"";this.message=this.message||i||this.constructor.A(this);throw this};return r}($t);mt.A=bt;export{pt as Ability,wt as AbilityBuilder,mt as ForbiddenError,nt as PureAbility,ut as buildMongoQueryMatcher,I as createAliasResolver,gt as defineAbility,D as detectSubjectType,dt as fieldPatternMatcher,bt as getDefaultErrorMessage,ot as mongoQueryMatcher,S as subject,T as wrapArray};
import{createFactory as t,$eq as r,$ne as i,$lt as n,$lte as e,$gt as o,$gte as u,$in as s,$nin as a,$all as f,$size as c,$regex as h,$options as v,$elemMatch as l,$exists as d,eq as b,ne as y,lt as p,lte as w,gt as g,gte as E,within as A,nin as $,all as m,size as j,regex as M,elemMatch as x,exists as F,and as O}from"@ucast/mongo2js";function P(t,r){for(var i=0;i<r.length;i++){var n=r[i];n.enumerable=n.enumerable||false;n.configurable=true;if("value"in n)n.writable=true;Object.defineProperty(t,n.key,n)}}function R(t,r,i){if(r)P(t.prototype,r);if(i)P(t,i);return t}function _(){_=Object.assign||function(t){for(var r=1;r<arguments.length;r++){var i=arguments[r];for(var n in i)if(Object.prototype.hasOwnProperty.call(i,n))t[n]=i[n]}return t};return _.apply(this,arguments)}function B(t,r){t.prototype=Object.create(r.prototype);t.prototype.constructor=t;t.__proto__=r}function T(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function k(t){return Array.isArray(t)?t:[t]}var q="__caslSubjectType__";function z(t,r){if(r)if(!r.hasOwnProperty(q))Object.defineProperty(r,q,{value:t});else if(t!==r[q])throw new Error("Trying to cast object to subject type "+t+" but previously it was casted to "+r[q]);return r}var C=function t(r){var i=typeof r;return"string"===i||"function"===i};var S=function t(r){return r.modelName||r.name};var Y=function t(r){return"string"===typeof r?r:S(r)};function L(t){if(!t)return"all";if(t.hasOwnProperty(q))return t[q];return S(t.constructor)}function D(t,r){var i=k(r);var n=0;while(n<i.length){var e=i[n++];if(t.hasOwnProperty(e))i=i.concat(t[e])}return i}function G(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach((function(r){var i=r===t[r]||Array.isArray(t[r])&&(-1!==t[r].indexOf(r)||-1!==t[r].indexOf("manage"));if(i)throw new Error("Attempt to alias action to itself: "+r+" -> "+t[r])}))}function H(t){if("production"!==process.env.NODE_ENV)G(t);return function(r){return D(t,r)}}function I(t,r,i){for(var n=i;n<r.length;n++)t.push(r[n])}function J(t,r){if(!t||!t.length)return r||[];if(!r||!r.length)return t||[];var i=0;var n=0;var e=[];while(i<t.length&&n<r.length)if(t[i].priority<r[n].priority){e.push(t[i]);i++}else{e.push(r[n]);n++}I(e,t,i);I(e,r,n);return e}function K(t,r,i){var n=t.get(r);if(!n){n=i();t.set(r,n)}return n}var N=function t(r){return r};function Q(t,r){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!r.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!r.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}var U=function(){function t(t,r,i){if(void 0===i)i=0;this.t=void 0;this.i=void 0;Q(t,r);this.action=r.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?k(t.fields):void 0;this.priority=i;this.o=r}var r=t.prototype;r.u=function t(){if(this.conditions&&!this.t)this.t=this.o.conditionsMatcher(this.conditions);return this.t};r.matchesConditions=function t(r){if(!this.conditions)return true;if(!r||C(r))return!this.inverted;var i=this.u();return i(r)};r.matchesField=function t(r){if(!this.fields)return true;if(!r)return!this.inverted;if(this.fields&&!this.i)this.i=this.o.fieldMatcher(this.fields);return this.i(r)};R(t,[{key:"ast",get:function t(){var r=this.u();return r?r.ast:void 0}}]);return t}();var V=function t(r,i){var n={value:r,prev:i,next:null};if(i)i.next=n;return n};var W=function t(r){if(r.next)r.next.prev=r.prev;if(r.prev)r.prev.next=r.next;r.next=r.prev=null};var X=function t(){return{rules:[],merged:false}};var Z=function t(){return new Map};var tt=function t(r,i){if(!r.h&&i.fields)r.h=true};var rt=function(){function t(t,r){if(void 0===t)t=[];if(void 0===r)r={};this.h=false;this.v=new Map;this.l={conditionsMatcher:r.conditionsMatcher,fieldMatcher:r.fieldMatcher,resolveAction:r.resolveAction||N};this.p=r.detectSubjectType||L;this.g=t;this.A=this.$(t)}var r=t.prototype;r.detectSubjectType=function t(r){return C(r)?r:this.p(r)};r.update=function t(r){var i={rules:r,ability:this,target:this};this.m("update",i);this.g=r;this.A=this.$(r);this.m("updated",i);return this};r.$=function t(r){var i=new Map;for(var n=r.length-1;n>=0;n--){var e=r.length-n-1;var o=new U(r[n],this.l,e);var u=k(o.action);var s=k(o.subject||"all");tt(this,o);for(var a=0;a<s.length;a++){var f=K(i,s[a],Z);for(var c=0;c<u.length;c++)K(f,u[c],X).rules.push(o)}}return i};r.possibleRulesFor=function t(r,i){if(void 0===i)i="all";if(!C(i))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');var n=K(this.A,i,Z);var e=K(n,r,X);if(e.merged)return e.rules;var o="manage"!==r&&n.has("manage")?n.get("manage").rules:void 0;var u=J(e.rules,o);if("all"!==i)u=J(u,this.possibleRulesFor(r,"all"));e.rules=u;e.merged=true;return u};r.rulesFor=function t(r,i,n){var e=this.possibleRulesFor(r,i);if(n&&"string"!==typeof n)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return e;return e.filter((function(t){return t.matchesField(n)}))};r.on=function t(r,i){var n=this;var e=this.v.get(r)||null;var o=V(i,e);this.v.set(r,o);return function(){if(!o.next&&!o.prev&&n.v.get(r)===o)n.v.delete(r);else W(o)}};r.m=function t(r,i){var n=this.v.get(r)||null;while(null!==n){var e=n.prev;n.value(i);n=e}};R(t,[{key:"rules",get:function t(){return this.g}}]);return t}();var it=function(t){B(PureAbility,t);function PureAbility(){return t.apply(this,arguments)||this}var r=PureAbility.prototype;r.can=function t(){var r=this.relevantRuleFor.apply(this,arguments);return!!r&&!r.inverted};r.relevantRuleFor=function t(r,i,n){var e=this.detectSubjectType(i);var o=this.rulesFor(r,e,n);for(var u=0,s=o.length;u<s;u++)if(o[u].matchesConditions(i))return o[u];return null};r.cannot=function t(){return!this.can.apply(this,arguments)};return PureAbility}(rt);var nt={$eq:r,$ne:i,$lt:n,$lte:e,$gt:o,$gte:u,$in:s,$nin:a,$all:f,$size:c,$regex:h,$options:v,$elemMatch:l,$exists:d};var et={eq:b,ne:y,lt:p,lte:w,gt:g,gte:E,in:A,nin:$,all:m,size:j,regex:M,elemMatch:x,exists:F,and:O};var ot=function r(i,n,e){return t(_({},nt,i),_({},et,n),e)};var ut=t(nt,et);var st=/[-/\\^$+?.()|[\]{}]/g;var at=/\.?\*+\.?/g;var ft=/\*+/;var ct=/\./g;function ht(t,r,i){var n="*"===i[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";var e=-1===t.indexOf("**")?"[^.]":".";var o=t.replace(ct,"\\$&").replace(ft,e+n);return r+t.length===i.length?"(?:"+o+")?":o}function vt(t,r,i){if("."===t&&("*"===i[r-1]||"*"===i[r+1]))return t;return"\\"+t}function lt(t){var r=t.map((function(t){return t.replace(st,vt).replace(at,ht)}));var i=r.length>1?"(?:"+r.join("|")+")":r[0];return new RegExp("^"+i+"$")}var dt=function t(r){var i;return function(t){if("undefined"===typeof i)i=r.every((function(t){return-1===t.indexOf("*")}))?null:lt(r);return null===i?-1!==r.indexOf(t):i.test(t)}};var bt=function(t){B(Ability,t);function Ability(r,i){if(void 0===r)r=[];if(void 0===i)i={};return t.call(this,r,_({conditionsMatcher:ut,fieldMatcher:dt},i))||this}return Ability}(it);var yt=function(){function t(t){this.j=t}var r=t.prototype;r.because=function t(r){this.j.reason=r;return this};return t}();var pt=function(){function AbilityBuilder(t){this.rules=[];this.M=t;this.can=this.can.bind(this);this.cannot=this.cannot.bind(this);this.build=this.build.bind(this)}var t=AbilityBuilder.prototype;t.can=function t(r,i,n,e){var o={action:r};if(i){o.subject=i;if(Array.isArray(n)||"string"===typeof n)o.fields=n;else if("undefined"!==typeof n)o.conditions=n;if("undefined"!==typeof e)o.conditions=e}this.rules.push(o);return new yt(o)};t.cannot=function t(r,i,n,e){var o=this.can(r,i,n,e);o.j.inverted=true;return o};t.build=function t(r){return new this.M(this.rules,r)};return AbilityBuilder}();function defineAbility(t,r){var i=new pt(bt);var n=t(i.can,i.cannot);if(n&&"function"===typeof n.then)return n.then((function(){return i.build(r)}));return i.build(r)}var wt=function t(r){return'Cannot execute "'+r.action+'" on "'+r.subjectType+'"'};var gt=function t(r){this.message=r};gt.prototype=Object.create(Error.prototype);var Et=function(t){B(ForbiddenError,t);ForbiddenError.setDefaultMessage=function t(r){this.F="string"===typeof r?function(){return r}:r};ForbiddenError.from=function t(r){return new this(r)};function ForbiddenError(r){var i;i=t.call(this,"")||this;i.field=void 0;i.ability=r;if("function"===typeof Error.captureStackTrace){i.name="ForbiddenError";Error.captureStackTrace(T(i),i.constructor)}return i}var r=ForbiddenError.prototype;r.setMessage=function t(r){this.message=r;return this};r.throwUnlessCan=function t(){var r;var i=(r=this.ability).relevantRuleFor.apply(r,arguments);if(i&&!i.inverted)return;this.action=arguments.length<=0?void 0:arguments[0];this.subject=arguments.length<=1?void 0:arguments[1];this.subjectType=Y(this.ability.detectSubjectType(arguments.length<=1?void 0:arguments[1]));this.field=arguments.length<=2?void 0:arguments[2];var n=i?i.reason:"";this.message=this.message||n||this.constructor.F(this);throw this};return ForbiddenError}(gt);Et.F=wt;export{bt as Ability,pt as AbilityBuilder,Et as ForbiddenError,it as PureAbility,ot as buildMongoQueryMatcher,H as createAliasResolver,defineAbility,L as detectSubjectType,dt as fieldPatternMatcher,wt as getDefaultErrorMessage,ut as mongoQueryMatcher,z as subject,k as wrapArray};
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","matchesConditions","this","_lazyMatchConditions","matchesField","field","_lazyMatchField","ast","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","_this","delete","payload","current","PureAbility","can","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","_PureAbility","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}
{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private _conditionsMatcher() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions!;\n }\n\n get ast() {\n const matches = this._conditionsMatcher();\n return matches ? matches.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n const matches = this._conditionsMatcher();\n return matches(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public, RawRuleOf } from './RuleIndex';\nimport { Abilities, AbilityTuple, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (\n rules: RawRuleOf<T>[],\n options: AbilityOptionsOf<T>\n) => T;\n\nexport class PureAbility<\n A extends Abilities = AbilityTuple,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n AnyObject,\n AnyClass,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends AnyClass<infer R>\n ? R\n : S extends string\n ? Exclude<Normalize<Generics<T>['abilities']>[1], SubjectType> extends { kind: string }\n ? Extract<Normalize<Generics<T>['abilities']>[1], TaggedInterface<S>>\n : AnyObject\n : never;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<T extends AnyAbility> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: AnyClass<T>;\n\n constructor(AbilityType: AnyClass<T>) {\n this._AbilityType = AbilityType;\n this.can = this.can.bind(this as any);\n this.cannot = this.cannot.bind(this as any);\n this.build = this.build.bind(this as any);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options);\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<T>['can'],\n cannot: AbilityBuilder<T>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<U extends AnyAbility>(ability: U) {\n return new this<U>(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","matchesConditions","matches","matchesField","field","ast","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","_this","delete","payload","current","PureAbility","can","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","_PureAbility","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@ucast/mongo2js");function n(t){return Array.isArray(t)?t:[t]}function r(t,n,r){let e=t;let o=n;if(-1!==n.indexOf(".")){const r=n.split(".");o=r.pop();e=r.reduce((t,n)=>{t[n]=t[n]||{};return t[n]},t)}e[o]=r}function e(t,n,r,e){const o=Object.create(null);const u=t.rulesFor(n,r);for(let t=0;t<u.length;t++){const n=u[t];const r=n.inverted?"$and":"$or";if(!n.conditions)if(n.inverted)break;else{delete o[r];return o}else{o[r]=o[r]||[];o[r].push(e(n))}}return o.$or?o:null}function o(t){if(!t.ast)throw new Error(`Ability rule "${JSON.stringify(t)}" does not have "ast" property. So, cannot be used to generate AST`);return t.ast}function u(n,r,u){const c=e(n,r,u,o);if(null===c)return null;if(!c.$and)return c.$or?t.buildOr(c.$or):t.buildAnd([]);if(c.$or)c.$and.push(t.buildOr(c.$or));return t.buildAnd(c.$and)}function c(t,n,e){return t.rulesFor(n,e).reduce((t,n)=>{if(n.inverted||!n.conditions)return t;return Object.keys(n.conditions).reduce((t,e)=>{const o=n.conditions[e];if(!o||o.constructor!==Object)r(t,e,o);return t},t)},{})}const s=t=>t.fields;function i(t){this.delete(t)}function f(t){this.add(t)}function l(t,n,r,e={}){const o=e.fieldsFrom||s;const u=t.detectSubjectType(r);const c=t.possibleRulesFor(n,u).reduceRight((t,n)=>{if(!n.matchesConditions(r))return t;const e=o(n);if(e){const r=n.inverted?i:f;e.forEach(r,t)}return t},new Set);return Array.from(c)}const a=t=>Array.isArray(t)?t.join(","):t;function p(t,r){return t.map(t=>{const e=[a(t.action||t.actions),"function"===typeof r?n(t.subject).map(r).join(","):a(t.subject),t.conditions||0,t.inverted?1:0,t.fields?a(t.fields):0,t.reason||""];while(!e[e.length-1])e.pop();return e})}function b(t,n){return t.map(([t,r,e,o,u,c])=>{const s=r.split(",");const i={inverted:!!o,action:t.split(","),subject:"function"===typeof n?s.map(n):s};if(e)i.conditions=e;if(u)i.fields=u.split(",");if(c)i.reason=c;return i})}exports.packRules=p;exports.permittedFieldsOf=l;exports.rulesToAST=u;exports.rulesToFields=c;exports.rulesToQuery=e;exports.unpackRules=b;
"use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@ucast/mongo2js");function n(t){return Array.isArray(t)?t:[t]}function e(t,n,e){let r=t;let o=n;if(-1!==n.indexOf(".")){const e=n.split(".");o=e.pop();r=e.reduce(((t,n)=>{t[n]=t[n]||{};return t[n]}),t)}r[o]=e}function r(t,n,e,r){const o=Object.create(null);const u=t.rulesFor(n,e);for(let t=0;t<u.length;t++){const n=u[t];const e=n.inverted?"$and":"$or";if(!n.conditions)if(n.inverted)break;else{delete o[e];return o}else{o[e]=o[e]||[];o[e].push(r(n))}}return o.$or?o:null}function o(t){if(!t.ast)throw new Error(`Ability rule "${JSON.stringify(t)}" does not have "ast" property. So, cannot be used to generate AST`);return t.ast}function u(n,e,u){const c=r(n,e,u,o);if(null===c)return null;if(!c.$and)return c.$or?t.buildOr(c.$or):t.buildAnd([]);if(c.$or)c.$and.push(t.buildOr(c.$or));return t.buildAnd(c.$and)}function c(t,n,r){return t.rulesFor(n,r).reduce(((t,n)=>{if(n.inverted||!n.conditions)return t;return Object.keys(n.conditions).reduce(((t,r)=>{const o=n.conditions[r];if(!o||o.constructor!==Object)e(t,r,o);return t}),t)}),{})}function s(t,n,e,r){const o=t.detectSubjectType(e);const u=t.possibleRulesFor(n,o);const c=new Set;const s=c.delete.bind(c);const i=c.add.bind(c);let f=u.length;while(f--){const t=u[f];if(t.matchesConditions(e)){const n=t.inverted?s:i;r.fieldsFrom(t).forEach(n)}}return Array.from(c)}const i=t=>Array.isArray(t)?t.join(","):t;function f(t,e){return t.map((t=>{const r=[i(t.action||t.actions),"function"===typeof e?n(t.subject).map(e).join(","):i(t.subject),t.conditions||0,t.inverted?1:0,t.fields?i(t.fields):0,t.reason||""];while(!r[r.length-1])r.pop();return r}))}function l(t,n){return t.map((([t,e,r,o,u,c])=>{const s=e.split(",");const i={inverted:!!o,action:t.split(","),subject:"function"===typeof n?s.map(n):s};if(r)i.conditions=r;if(u)i.fields=u.split(",");if(c)i.reason=c;return i}))}exports.packRules=f;exports.permittedFieldsOf=s;exports.rulesToAST=u;exports.rulesToFields=c;exports.rulesToQuery=r;exports.unpackRules=l;
//# sourceMappingURL=extra.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteItem(this: Set<string>, item: string) {\n this.delete(item);\n}\n\nfunction addItem(this: Set<string>, item: string) {\n this.add(item);\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {}\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const subjectType = ability.detectSubjectType(subject);\n const uniqueFields = ability.possibleRulesFor(action, subjectType)\n .reduceRight((fields, rule) => {\n if (!rule.matchesConditions(subject)) {\n return fields;\n }\n\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteItem : addItem;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, new Set<string>());\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","getRuleFields","deleteItem","item","delete","addItem","add","permittedFieldsOf","subject","options","fieldsFrom","detectSubjectType","uniqueFields","possibleRulesFor","reduceRight","matchesConditions","names","toggle","forEach","Set","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}
{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[];\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom: GetRuleFields<RuleOf<T>>\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T>\n): string[] {\n const subjectType = ability.detectSubjectType(subject);\n const rules = ability.possibleRulesFor(action, subjectType);\n const uniqueFields = new Set<string>();\n const deleteItem = uniqueFields.delete.bind(uniqueFields);\n const addItem = uniqueFields.add.bind(uniqueFields);\n let i = rules.length;\n\n while (i--) {\n const rule = rules[i];\n if (rule.matchesConditions(subject)) {\n const toggle = rule.inverted ? deleteItem : addItem;\n options.fieldsFrom(rule).forEach(toggle);\n }\n }\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","permittedFieldsOf","subject","options","detectSubjectType","possibleRulesFor","uniqueFields","Set","deleteItem","delete","bind","addItem","add","matchesConditions","toggle","fieldsFrom","forEach","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@ucast/mongo2js");function e(t){return Array.isArray(t)?t:[t]}const s="__caslSubjectType__";function n(t,e){if(e)if(!e.hasOwnProperty(s))Object.defineProperty(e,s,{value:t});else if(t!==e[s])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${e[s]}`);return e}const r=t=>{const e=typeof t;return"string"===e||"function"===e};const i=t=>t.modelName||t.name;const o=t=>"string"===typeof t?t:i(t);function c(t){if(!t)return"all";if(t.hasOwnProperty(s))return t[s];return i(t.constructor)}function u(t,s){let n=e(s);let r=0;while(r<n.length){const e=n[r++];if(t.hasOwnProperty(e))n=n.concat(t[e])}return n}function h(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach(e=>{const s=e===t[e]||Array.isArray(t[e])&&(-1!==t[e].indexOf(e)||-1!==t[e].indexOf("manage"));if(s)throw new Error(`Attempt to alias action to itself: ${e} -> ${t[e]}`)})}function a(t){if("production"!==process.env.NODE_ENV)h(t);return e=>u(t,e)}function l(t,e,s){for(let n=s;n<e.length;n++)t.push(e[n])}function f(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let s=0;let n=0;const r=[];while(s<t.length&&n<e.length)if(t[s].priority<e[n].priority){r.push(t[s]);s++}else{r.push(e[n]);n++}l(r,t,s);l(r,e,n);return r}function p(t,e,s){let n=t.get(e);if(!n){n=s();t.set(e,n)}return n}const d=t=>t;function g(t,e){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!e.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!e.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}class w{constructor(t,s,n=0){this.t=void 0;this.s=void 0;g(t,s);this.action=s.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?e(t.fields):void 0;this.priority=n;this.i=s}get o(){if(this.conditions&&!this.t)this.t=this.i.conditionsMatcher(this.conditions);return this.t}get u(){if(this.fields&&!this.s)this.s=this.i.fieldMatcher(this.fields);return this.s}get ast(){return this.o?this.o.ast:void 0}matchesConditions(t){if(!this.conditions)return true;if(!t||r(t))return!this.inverted;return this.o(t)}matchesField(t){if(!this.fields)return true;if(!t)return!this.inverted;return this.u(t)}}const y=(t,e)=>{const s={value:t,prev:e,next:null};if(e)e.next=s;return s};const b=t=>{if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null};const $=()=>({rules:[],merged:false});const x=()=>new Map;const m=(t,e)=>{if(!t.h&&e.fields)t.h=true};class M{constructor(t=[],e={}){this.h=false;this.l=new Map;this.p={conditionsMatcher:e.conditionsMatcher,fieldMatcher:e.fieldMatcher,resolveAction:e.resolveAction||d};this.g=e.detectSubjectType||c;this.$=t;this.m=this.M(t)}get rules(){return this.$}detectSubjectType(t){return r(t)?t:this.g(t)}update(t){const e={rules:t,ability:this,target:this};this.v("update",e);this.$=t;this.m=this.M(t);this.v("updated",e);return this}M(t){const s=new Map;for(let n=t.length-1;n>=0;n--){const r=t.length-n-1;const i=new w(t[n],this.p,r);const o=e(i.action);const c=e(i.subject||"all");m(this,i);for(let t=0;t<c.length;t++){const e=p(s,c[t],x);for(let t=0;t<o.length;t++)p(e,o[t],$).rules.push(i)}}return s}possibleRulesFor(t,e="all"){if(!r(e))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');const s=p(this.m,e,x);const n=p(s,t,$);if(n.merged)return n.rules;const i="manage"!==t&&s.has("manage")?s.get("manage").rules:void 0;let o=f(n.rules,i);if("all"!==e)o=f(o,this.possibleRulesFor(t,"all"));n.rules=o;n.merged=true;return o}rulesFor(t,e,s){const n=this.possibleRulesFor(t,e);if(s&&"string"!==typeof s)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return n;return n.filter(t=>t.matchesField(s))}on(t,e){const s=this.l.get(t)||null;const n=y(e,s);this.l.set(t,n);return()=>{if(!n.next&&!n.prev&&this.l.get(t)===n)this.l.delete(t);else b(n)}}v(t,e){let s=this.l.get(t)||null;while(null!==s){const t=s.prev;s.value(e);s=t}}}class v extends M{can(...t){const e=this.relevantRuleFor(...t);return!!e&&!e.inverted}relevantRuleFor(t,e,s){const n=this.detectSubjectType(e);const r=this.rulesFor(t,n,s);for(let t=0,s=r.length;t<s;t++)if(r[t].matchesConditions(e))return r[t];return null}cannot(...t){return!this.can(...t)}}const j={$eq:t.$eq,$ne:t.$ne,$lt:t.$lt,$lte:t.$lte,$gt:t.$gt,$gte:t.$gte,$in:t.$in,$nin:t.$nin,$all:t.$all,$size:t.$size,$regex:t.$regex,$options:t.$options,$elemMatch:t.$elemMatch,$exists:t.$exists};const E={eq:t.eq,ne:t.ne,lt:t.lt,lte:t.lte,gt:t.gt,gte:t.gte,in:t.within,nin:t.nin,all:t.all,size:t.size,regex:t.regex,elemMatch:t.elemMatch,exists:t.exists,and:t.and};const _=(e,s,n)=>t.createFactory(Object.assign({},j,e),Object.assign({},E,s),n);const F=t.createFactory(j,E);const O=/[-/\\^$+?.()|[\]{}]/g;const A=/\.?\*+\.?/g;const C=/\*+/;const R=/\./g;function z(t,e,s){const n="*"===s[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const r=-1===t.indexOf("**")?"[^.]":".";const i=t.replace(R,"\\$&").replace(C,r+n);return e+t.length===s.length?`(?:${i})?`:i}function T(t,e,s){if("."===t&&("*"===s[e-1]||"*"===s[e+1]))return t;return`\\${t}`}function q(t){const e=t.map(t=>t.replace(O,T).replace(A,z));const s=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${s}$`)}const S=t=>{let e;return s=>{if("undefined"===typeof e)e=t.every(t=>-1===t.indexOf("*"))?null:q(t);return null===e?-1!==t.indexOf(s):e.test(s)}};class Y extends v{constructor(t=[],e={}){super(t,Object.assign({conditionsMatcher:F,fieldMatcher:S},e))}}class D{constructor(t){this.j=t}because(t){this.j.reason=t;return this}}class I{constructor(t){this.rules=[];this._=t;const e=this;e.can=e.can.bind(e);e.cannot=e.cannot.bind(e);e.build=e.build.bind(e)}can(t,e,s,n){const r={action:t};if(e){r.subject=e;if(Array.isArray(s)||"string"===typeof s)r.fields=s;else if("undefined"!==typeof s)r.conditions=s;if("undefined"!==typeof n)r.conditions=n}this.rules.push(r);return new D(r)}cannot(t,e,s,n){const r=this.can(t,e,s,n);r.j.inverted=true;return r}build(t){return new this._(this.rules,t)}}function L(t,e){const s=new I(Y);const n=t(s.can,s.cannot);if(n&&"function"===typeof n.then)return n.then(()=>s.build(e));return s.build(e)}const U=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const k=function t(e){this.message=e};k.prototype=Object.create(Error.prototype);class B extends k{static setDefaultMessage(t){this.F="string"===typeof t?()=>t:t}static from(t){return new this(t)}constructor(t){super("");this.field=void 0;this.ability=t;if("function"===typeof Error.captureStackTrace){this.name="ForbiddenError";Error.captureStackTrace(this,this.constructor)}}setMessage(t){this.message=t;return this}throwUnlessCan(...t){const e=this.ability.relevantRuleFor(...t);if(e&&!e.inverted)return;this.action=t[0];this.subject=t[1];this.subjectType=o(this.ability.detectSubjectType(t[1]));this.field=t[2];const s=e?e.reason:"";this.message=this.message||s||this.constructor.F(this);throw this}}B.F=U;exports.Ability=Y;exports.AbilityBuilder=I;exports.ForbiddenError=B;exports.PureAbility=v;exports.buildMongoQueryMatcher=_;exports.createAliasResolver=a;exports.defineAbility=L;exports.detectSubjectType=c;exports.fieldPatternMatcher=S;exports.getDefaultErrorMessage=U;exports.mongoQueryMatcher=F;exports.subject=n;exports.wrapArray=e;
"use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@ucast/mongo2js");function e(t){return Array.isArray(t)?t:[t]}const s="__caslSubjectType__";function i(t,e){if(e)if(!e.hasOwnProperty(s))Object.defineProperty(e,s,{value:t});else if(t!==e[s])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${e[s]}`);return e}const r=t=>{const e=typeof t;return"string"===e||"function"===e};const n=t=>t.modelName||t.name;const o=t=>"string"===typeof t?t:n(t);function c(t){if(!t)return"all";if(t.hasOwnProperty(s))return t[s];return n(t.constructor)}function u(t,s){let i=e(s);let r=0;while(r<i.length){const e=i[r++];if(t.hasOwnProperty(e))i=i.concat(t[e])}return i}function h(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach((e=>{const s=e===t[e]||Array.isArray(t[e])&&(-1!==t[e].indexOf(e)||-1!==t[e].indexOf("manage"));if(s)throw new Error(`Attempt to alias action to itself: ${e} -> ${t[e]}`)}))}function l(t){if("production"!==process.env.NODE_ENV)h(t);return e=>u(t,e)}function a(t,e,s){for(let i=s;i<e.length;i++)t.push(e[i])}function f(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let s=0;let i=0;const r=[];while(s<t.length&&i<e.length)if(t[s].priority<e[i].priority){r.push(t[s]);s++}else{r.push(e[i]);i++}a(r,t,s);a(r,e,i);return r}function d(t,e,s){let i=t.get(e);if(!i){i=s();t.set(e,i)}return i}const p=t=>t;function b(t,e){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!e.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!e.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}class y{constructor(t,s,i=0){this.t=void 0;this.i=void 0;b(t,s);this.action=s.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?e(t.fields):void 0;this.priority=i;this.o=s}u(){if(this.conditions&&!this.t)this.t=this.o.conditionsMatcher(this.conditions);return this.t}get ast(){const t=this.u();return t?t.ast:void 0}matchesConditions(t){if(!this.conditions)return true;if(!t||r(t))return!this.inverted;const e=this.u();return e(t)}matchesField(t){if(!this.fields)return true;if(!t)return!this.inverted;if(this.fields&&!this.i)this.i=this.o.fieldMatcher(this.fields);return this.i(t)}}const w=(t,e)=>{const s={value:t,prev:e,next:null};if(e)e.next=s;return s};const g=t=>{if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null};const $=()=>({rules:[],merged:false});const x=()=>new Map;const m=(t,e)=>{if(!t.h&&e.fields)t.h=true};class A{constructor(t=[],e={}){this.h=false;this.l=new Map;this.p={conditionsMatcher:e.conditionsMatcher,fieldMatcher:e.fieldMatcher,resolveAction:e.resolveAction||p};this.g=e.detectSubjectType||c;this.$=t;this.m=this.A(t)}get rules(){return this.$}detectSubjectType(t){return r(t)?t:this.g(t)}update(t){const e={rules:t,ability:this,target:this};this.v("update",e);this.$=t;this.m=this.A(t);this.v("updated",e);return this}A(t){const s=new Map;for(let i=t.length-1;i>=0;i--){const r=t.length-i-1;const n=new y(t[i],this.p,r);const o=e(n.action);const c=e(n.subject||"all");m(this,n);for(let t=0;t<c.length;t++){const e=d(s,c[t],x);for(let t=0;t<o.length;t++)d(e,o[t],$).rules.push(n)}}return s}possibleRulesFor(t,e="all"){if(!r(e))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');const s=d(this.m,e,x);const i=d(s,t,$);if(i.merged)return i.rules;const n="manage"!==t&&s.has("manage")?s.get("manage").rules:void 0;let o=f(i.rules,n);if("all"!==e)o=f(o,this.possibleRulesFor(t,"all"));i.rules=o;i.merged=true;return o}rulesFor(t,e,s){const i=this.possibleRulesFor(t,e);if(s&&"string"!==typeof s)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return i;return i.filter((t=>t.matchesField(s)))}on(t,e){const s=this.l.get(t)||null;const i=w(e,s);this.l.set(t,i);return()=>{if(!i.next&&!i.prev&&this.l.get(t)===i)this.l.delete(t);else g(i)}}v(t,e){let s=this.l.get(t)||null;while(null!==s){const t=s.prev;s.value(e);s=t}}}class PureAbility extends A{can(...t){const e=this.relevantRuleFor(...t);return!!e&&!e.inverted}relevantRuleFor(t,e,s){const i=this.detectSubjectType(e);const r=this.rulesFor(t,i,s);for(let t=0,s=r.length;t<s;t++)if(r[t].matchesConditions(e))return r[t];return null}cannot(...t){return!this.can(...t)}}const E={$eq:t.$eq,$ne:t.$ne,$lt:t.$lt,$lte:t.$lte,$gt:t.$gt,$gte:t.$gte,$in:t.$in,$nin:t.$nin,$all:t.$all,$size:t.$size,$regex:t.$regex,$options:t.$options,$elemMatch:t.$elemMatch,$exists:t.$exists};const v={eq:t.eq,ne:t.ne,lt:t.lt,lte:t.lte,gt:t.gt,gte:t.gte,in:t.within,nin:t.nin,all:t.all,size:t.size,regex:t.regex,elemMatch:t.elemMatch,exists:t.exists,and:t.and};const M=(e,s,i)=>t.createFactory(Object.assign({},E,e),Object.assign({},v,s),i);const j=t.createFactory(E,v);const F=/[-/\\^$+?.()|[\]{}]/g;const _=/\.?\*+\.?/g;const O=/\*+/;const R=/\./g;function C(t,e,s){const i="*"===s[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const r=-1===t.indexOf("**")?"[^.]":".";const n=t.replace(R,"\\$&").replace(O,r+i);return e+t.length===s.length?`(?:${n})?`:n}function T(t,e,s){if("."===t&&("*"===s[e-1]||"*"===s[e+1]))return t;return`\\${t}`}function q(t){const e=t.map((t=>t.replace(F,T).replace(_,C)));const s=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${s}$`)}const B=t=>{let e;return s=>{if("undefined"===typeof e)e=t.every((t=>-1===t.indexOf("*")))?null:q(t);return null===e?-1!==t.indexOf(s):e.test(s)}};class Ability extends PureAbility{constructor(t=[],e={}){super(t,Object.assign({conditionsMatcher:j,fieldMatcher:B},e))}}class P{constructor(t){this.M=t}because(t){this.M.reason=t;return this}}class AbilityBuilder{constructor(t){this.rules=[];this.j=t;this.can=this.can.bind(this);this.cannot=this.cannot.bind(this);this.build=this.build.bind(this)}can(t,e,s,i){const r={action:t};if(e){r.subject=e;if(Array.isArray(s)||"string"===typeof s)r.fields=s;else if("undefined"!==typeof s)r.conditions=s;if("undefined"!==typeof i)r.conditions=i}this.rules.push(r);return new P(r)}cannot(t,e,s,i){const r=this.can(t,e,s,i);r.M.inverted=true;return r}build(t){return new this.j(this.rules,t)}}function defineAbility(t,e){const s=new AbilityBuilder(Ability);const i=t(s.can,s.cannot);if(i&&"function"===typeof i.then)return i.then((()=>s.build(e)));return s.build(e)}const S=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const z=function t(e){this.message=e};z.prototype=Object.create(Error.prototype);class ForbiddenError extends z{static setDefaultMessage(t){this.F="string"===typeof t?()=>t:t}static from(t){return new this(t)}constructor(t){super("");this.field=void 0;this.ability=t;if("function"===typeof Error.captureStackTrace){this.name="ForbiddenError";Error.captureStackTrace(this,this.constructor)}}setMessage(t){this.message=t;return this}throwUnlessCan(...t){const e=this.ability.relevantRuleFor(...t);if(e&&!e.inverted)return;this.action=t[0];this.subject=t[1];this.subjectType=o(this.ability.detectSubjectType(t[1]));this.field=t[2];const s=e?e.reason:"";this.message=this.message||s||this.constructor.F(this);throw this}}ForbiddenError.F=S;exports.Ability=Ability;exports.AbilityBuilder=AbilityBuilder;exports.ForbiddenError=ForbiddenError;exports.PureAbility=PureAbility;exports.buildMongoQueryMatcher=M;exports.createAliasResolver=l;exports.defineAbility=defineAbility;exports.detectSubjectType=c;exports.fieldPatternMatcher=B;exports.getDefaultErrorMessage=S;exports.mongoQueryMatcher=j;exports.subject=i;exports.wrapArray=e;
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","this","_lazyMatchConditions","ast","matchesConditions","matchesField","field","_lazyMatchField","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"uGAEO,SAASA,EAAaC,UACpBC,MAAMC,QAAQF,GAASA,EAAQ,CAACA,GAoBzC,MAAMG,EAAa,sBACZ,SAASC,EAGdC,EAASC,MACLA,MACGA,EAAOC,eAAeJ,GACzBK,OAAOC,eAAeH,EAAQH,EAAY,CAAEH,MAAOK,SAC9C,GAAIA,IAASC,EAAOH,SACnB,IAAIO,MAAO,yCAAwCL,qCAAwCC,EAAOH,aAIrGG,EAGF,MAAMK,EAAiBX,UACtBK,SAAcL,QACJ,WAATK,GAA8B,aAATA,GAG9B,MAAMO,EAAuBZ,GAAwBA,EAAMa,WAAab,EAAMc,KACvE,MAAMC,EAAsBf,GACT,kBAAVA,EAAqBA,EAAQY,EAAoBZ,GAG1D,SAASgB,EAAkBC,OAC3BA,QACI,SAGLA,EAAQV,eAAeJ,UACjBc,EAAgBd,UAGnBS,EAAoBK,EAAQC,aAG9B,SAASC,EAAcC,EAAsBC,OAC9CC,EAAUvB,EAAUsB,OACpBE,EAAI,QAEDA,EAAID,EAAQE,OAAQ,OACnBC,EAASH,EAAQC,QAEnBH,EAASb,eAAekB,GAC1BH,EAAUA,EAAQI,OAAON,EAASK,WAI/BH,EAGT,SAASK,EAAeP,MAClBA,EAASQ,aACL,IAAIlB,MAAM,+DAGlBF,OAAOqB,KAAKT,GAAUU,QAASC,UACvBC,EAAWD,IAAUX,EAASW,IAC/B9B,MAAMC,QAAQkB,EAASW,OACY,IAApCX,EAASW,GAAOE,QAAQF,KAAwD,IAAvCX,EAASW,GAAOE,QAAQ,cAGjED,QACI,IAAItB,MAAO,sCAAqCqB,QAAYX,EAASW,QAK1E,SAASG,EAAoBd,MACL,eAAzBe,QAAQC,IAAIC,SACdV,EAAeP,UAGTK,GAA8BN,EAAcC,EAAUK,GAGhE,SAASa,EAAeC,EAAWC,EAAaC,OACzC,IAAIlB,EAAIkB,EAAOlB,EAAIiB,EAAOhB,OAAQD,IACrCgB,EAAKG,KAAKF,EAAOjB,IAId,SAASoB,EACdC,EACAC,OAEKD,IAAUA,EAAMpB,cACZqB,GAAgB,OAGpBA,IAAiBA,EAAarB,cAC1BoB,GAAS,OAGdrB,EAAI,MACJuB,EAAI,QACFC,EAAc,SAEbxB,EAAIqB,EAAMpB,QAAUsB,EAAID,EAAarB,UACtCoB,EAAMrB,GAAGyB,SAAWH,EAAaC,GAAGE,SAAU,CAChDD,EAAOL,KAAKE,EAAMrB,IAClBA,QACK,CACLwB,EAAOL,KAAKG,EAAaC,IACzBA,IAIJR,EAAYS,EAAQH,EAAOrB,GAC3Be,EAAYS,EAAQF,EAAcC,UAE3BC,EAGF,SAASE,EAAmBC,EAAgBC,EAAQC,OACrDpD,EAAQkD,EAAIG,IAAIF,OAEfnD,EAAO,CACVA,EAAQoD,IACRF,EAAII,IAAIH,EAAKnD,UAGRA,EAGF,MAAMuD,EAAeC,GAASA,ECxIrC,SAASC,EAAiCC,EAAyBC,MAC7D1D,MAAMC,QAAQwD,EAAKE,UAAYF,EAAKE,OAAOpC,aACvC,IAAId,MAAM,wEAGdgD,EAAKE,SAAWD,EAAQE,mBACpB,IAAInD,MAAM,mFAGdgD,EAAKI,aAAeH,EAAQI,wBACxB,IAAIrD,MAAM,yFAWb,MAAMsD,EAYX9C,YACEwC,EACAC,EACAX,EAAmB,QAdbiB,cACAC,SAeNT,EAASC,EAAMC,QAEVlC,OAASkC,EAAQQ,cAAcT,EAAKjC,aACpCR,QAAUyC,EAAKzC,aACfmD,WAAaV,EAAKU,cAClBN,WAAaJ,EAAKI,gBAClBO,OAASX,EAAKW,YACdT,OAASF,EAAKE,OAAS7D,EAAU2D,EAAKE,aAAUU,OAChDtB,SAAWA,OACXuB,EAAWZ,aAIZa,KAAKV,aAAeU,KAAKP,OACtBA,EAAmBO,KAAKD,EAASR,kBAAmBS,KAAKV,mBAGzDU,KAAKP,aAIRO,KAAKZ,SAAWY,KAAKN,OAClBA,EAAcM,KAAKD,EAASV,aAAcW,KAAKZ,eAG/CY,KAAKN,mBAILM,KAAKC,EAAuBD,KAAKC,EAAqBC,SAAMJ,EAGrEK,kBAAkBrE,OACXkE,KAAKV,kBACD,SAGJxD,GAAUK,EAAcL,UACnBkE,KAAKJ,gBAGRI,KAAKC,EAAsBnE,GAGpCsE,aAAaC,OACNL,KAAKZ,cACD,SAGJiB,SACKL,KAAKJ,gBAGRI,KAAKM,EAAiBD,ICnG1B,MAAME,EAAa,CAAI/E,EAAUgF,WAChCC,EAAO,CAAEjF,MAAAA,EAAOgF,KAAAA,EAAME,KAAM,SAE9BF,EACFA,EAAKE,KAAOD,SAGPA,GAGF,MAAME,EAAcF,OACrBA,EAAKC,KACPD,EAAKC,KAAKF,KAAOC,EAAKD,QAGpBC,EAAKD,KACPC,EAAKD,KAAKE,KAAOD,EAAKC,KAGxBD,EAAKC,KAAOD,EAAKD,KAAO,MCwC1B,MAAMI,EAAqB,MACzBC,MAAO,GACPtC,OAAQ,QAEV,MAAMuC,EAAsB,IAAM,IAAIC,IACtC,MAAMC,EAAU,CAACC,EAAY/B,SACtB+B,EAAMC,GAAqBhC,EAAKE,OACnC6B,EAAMC,EAAoB,MAevB,MAAMC,EAUXzE,YACEmE,EAAsC,GACtC1B,EAA2C,SAXrC+B,EAA6B,WAC7BE,EAAwB,IAAIL,SAY7BM,EAAe,CAClB9B,kBAAmBJ,EAAQI,kBAC3BF,aAAcF,EAAQE,aACtBM,cAAeR,EAAQQ,eAAiBZ,QAErCuC,EAAqBnC,EAAQ3C,mBAAqBA,OAClD+E,EAASV,OACTW,EAAgBxB,KAAKyB,EAAeZ,sBAIlCb,KAAKuB,EAGd/E,kBAAkBV,UACTK,EAAcL,GACjBA,EACAkE,KAAKsB,EAAmBxF,GAG9B4F,OAAOb,SACCc,EAAQ,CACZd,MAAAA,EACAe,QAAS5B,KACThC,OAAQgC,WAGL6B,EAAM,SAAUF,QAChBJ,EAASV,OACTW,EAAgBxB,KAAKyB,EAAeZ,QACpCgB,EAAM,UAAWF,UAEf3B,KAGDyB,EAAeK,SACfC,EAAyC,IAAIhB,QAE9C,IAAIhE,EAAI+E,EAAS9E,OAAS,EAAGD,GAAK,EAAGA,IAAK,OACvCyB,EAAWsD,EAAS9E,OAASD,EAAI,QACjCmC,EAAO,IAAIM,EAAKsC,EAAS/E,GAAIiD,KAAKqB,EAAc7C,SAChD1B,EAAUvB,EAAU2D,EAAKjC,cACzB+E,EAAWzG,EAAU2D,EAAKzC,SAAW,OAC3CuE,EAAQhB,KAAMd,OAET,IAAI+C,EAAI,EAAGA,EAAID,EAAShF,OAAQiF,IAAK,OAClCC,EAAezD,EAAasD,EAAcC,EAASC,GAAInB,OAExD,IAAIxC,EAAI,EAAGA,EAAIxB,EAAQE,OAAQsB,IAClCG,EAAayD,EAAcpF,EAAQwB,GAAIsC,GAAoBC,MAAM3C,KAAKgB,WAKrE6C,EAITI,iBAAiBlF,EAAgBmF,EAA2B,WACrDjG,EAAciG,SACX,IAAIlG,MAAM,oGAGZgG,EAAezD,EAAauB,KAAKwB,EAAeY,EAAatB,SAC7DuB,EAAc5D,EAAayD,EAAcjF,EAAQ2D,MAEnDyB,EAAY9D,cACP8D,EAAYxB,YAGfyB,EAAyB,WAAXrF,GAAuBiF,EAAaK,IAAI,UACxDL,EAAarD,IAAI,UAAWgC,WAC5Bf,MACAe,EAAQ1C,EAAiBkE,EAAYxB,MAAOyB,MAE5B,QAAhBF,EACFvB,EAAQ1C,EAAiB0C,EAAQb,KAAamC,iBAAiBlF,EAAQ,QAGzEoF,EAAYxB,MAAQA,EACpBwB,EAAY9D,OAAS,YAEdsC,EAIT2B,SAASvF,EAAgBmF,EAA2B/B,SAC5CQ,EAAgCb,KAAamC,iBAAiBlF,EAAQmF,MAExE/B,GAA0B,kBAAVA,QACZ,IAAInE,MAAM,qJAGb8D,KAAKkB,SACDL,SAGFA,EAAM4B,OAAOvD,GAAQA,EAAKkB,aAAaC,IAGhDqC,GACEf,EACAgB,SAEMC,EAAO5C,KAAKoB,EAAQvC,IAAI8C,IAAU,WAClClB,EAAOF,EAAWoC,EAASC,QAC5BxB,EAAQtC,IAAI6C,EAAOlB,SAEjB,SACAA,EAAKC,OAASD,EAAKD,MAAQR,KAAKoB,EAAQvC,IAAI8C,KAAWlB,OACrDW,EAAQyB,OAAOlB,QAEpBhB,EAAWF,IAKToB,EAAuCvF,EAASwG,OAClDC,EAAU/C,KAAKoB,EAAQvC,IAAIvC,IAAS,WACrB,OAAZyG,EAAkB,OACjBvC,EAAOuC,EAAQvC,KACrBuC,EAAQvH,MAAMsH,GACdC,EAAUvC,ICtNT,MAAMwC,UAGH7B,EACR8B,OAAOC,SACChE,EAAOc,KAAKmD,mBAAmBD,WAC5BhE,IAASA,EAAKU,SAIzBuD,gBAAgBlG,EAAgBR,EAAmB4D,SAC3C+B,EAAcpC,KAAKxD,kBAAkBC,SACrCoE,EAASb,KAAawC,SAASvF,EAAQmF,EAAa/B,OAErD,IAAItD,EAAI,EAAGC,EAAS6D,EAAM7D,OAAQD,EAAIC,EAAQD,OAC7C8D,EAAM9D,GAAGoD,kBAAkB1D,UACtBoE,EAAM9D,UAIV,KAGTqG,UAAUF,UACAlD,KAAKiD,OAAOC,ICGxB,MAAMG,EAAsB,KAC1BC,UACAC,UACAC,WACAC,WACAC,WACAC,WACAC,WACAC,YACAC,aACAC,eACAC,kBACAC,sBACAC,qBACAC,WAEF,MAAMC,EAAsB,IAC1BC,QACAC,QACAC,SACAC,SACAC,SACAC,MACAC,GAAIC,aACJC,UACAC,WACAC,aACAC,kBACAC,mBACAC,aACAC,aAeWC,EAA0B,CAACC,EAAcC,EAAcnG,IAAYoG,iCACzElC,EAAwBgC,oBACxBjB,EAAwBkB,GAC7BnG,SAGWqG,EAAoBD,gBAAclC,EAAqBe,GCrFpE,MAAMqB,EAAuB,uBAC7B,MAAMC,EAAa,aACnB,MAAMC,EAAe,MACrB,MAAMC,EAAa,MAEnB,SAASC,EAAoBC,EAAe7E,EAAe8E,SACnDC,EAA2B,MAAdD,EAAO,IAA2B,MAAbD,EAAM,IAA0C,MAA5BA,EAAMA,EAAM9I,OAAS,GAC7E,IACA,UACEiJ,GAAmC,IAAzBH,EAAMrI,QAAQ,MAAe,OAAS,UAChDyI,EAAUJ,EAAMK,QAAQP,EAAY,QACvCO,QAAQR,EAAcM,EAAUD,UAE5B/E,EAAQ6E,EAAM9I,SAAW+I,EAAO/I,OAAU,MAAKkJ,MAAcA,EAGtE,SAASE,EAAaN,EAAe7E,EAAe8E,MACpC,MAAVD,IAAwC,MAAtBC,EAAO9E,EAAQ,IAAoC,MAAtB8E,EAAO9E,EAAQ,WACzD6E,QAGD,KAAIA,IAGd,SAASO,EAAcjH,SACfkH,EAAWlH,EAAOV,IAAI2B,GAASA,EAClC8F,QAAQV,EAAsBW,GAC9BD,QAAQT,EAAYG,UACjBK,EAAUI,EAAStJ,OAAS,EAAK,MAAKsJ,EAASC,KAAK,QAAUD,EAAS,UAEtE,IAAIE,OAAQ,IAAGN,YAGXO,EAAqCrH,QAC5C8G,SAEI7F,OACiB,qBAAZ6F,EACTA,EAAU9G,EAAOsH,MAAMC,IAAyB,IAApBA,EAAElJ,QAAQ,MAClC,KACA4I,EAAcjH,UAGD,OAAZ8G,GACwB,IAA3B9G,EAAO3B,QAAQ4C,GACf6F,EAAQU,KAAKvG,KCrCd,MAAMwG,UAGH7D,EACRtG,YAAYmE,EAA6B,GAAI1B,EAAgC,UACrE0B,iBACJtB,kBAAmBiG,EACnBnG,aAAcoH,GACXtH,KCJT,MAAM2H,EAGJpK,YAAYwC,QACL6H,EAAQ7H,EAGf8H,QAAQnH,QACDkH,EAAMlH,OAASA,SACbG,MA8CJ,MAAMiH,EAOXvK,YAAYwK,QAHLrG,MAAwB,QAIxBsG,EAAeD,QACdE,EAAOpH,KACboH,EAAKnE,IAAMmE,EAAKnE,IAAIoE,KAAKD,GACzBA,EAAKhE,OAASgE,EAAKhE,OAAOiE,KAAKD,GAC/BA,EAAKE,MAAQF,EAAKE,MAAMD,KAAKD,GAY/BnE,IACEhG,EACAR,EACA8K,EACAjI,SAEMJ,EAAO,CAAEjC,OAAAA,MAEXR,EAAS,CACXyC,EAAKzC,QAAUA,KAEXhB,MAAMC,QAAQ6L,IAAqD,kBAAvBA,EAC9CrI,EAAKE,OAASmI,OACT,GAAkC,qBAAvBA,EAChBrI,EAAKI,WAAaiI,KAGM,qBAAfjI,EACTJ,EAAKI,WAAaA,OAIjBuB,MAAM3C,KAAKgB,UAET,IAAI4H,EAAY5H,GAYzBkE,OACEnG,EACAR,EACA8K,EACAjI,SAEMkI,EAAWxH,KAAaiD,IAAIhG,EAAQR,EAAS8K,EAAoBjI,GACvEkI,EAAQT,EAAMnH,SAAW,YAClB4H,EAGTF,MAAMnI,UACG,IAAIa,KAAKmH,EAAanH,KAAKa,MAAO1B,IAetC,SAASsI,EAEdC,EAAsCvI,SAChCqI,EAAU,IAAIP,EAAeJ,SAC7Bc,EAASD,EAAOF,EAAQvE,IAAKuE,EAAQpE,WAEvCuE,GAAiC,oBAAhBA,EAAOC,YACnBD,EAAOC,KAAK,IAAMJ,EAAQF,MAAMnI,WAGlCqI,EAAQF,MAAMnI,SChKV0I,EAA0CC,GAAU,mBAAkBA,EAAM7K,eAAe6K,EAAM1F,eAE9G,MAAM2F,EAAc,SAASC,EAAoBC,QAC1CA,QAAUA,GAGjBF,EAAYG,UAAYlM,OAAOmM,OAAOjM,MAAMgM,WAErC,MAAME,UAA6CL,2BAS/BM,QAClBC,EAA8C,kBAAhBD,EAA2B,IAAMA,EAAcA,cAGlDzG,UACzB,IAAI5B,KAAK4B,GAGVlF,YAAYkF,SACZ,SAdDvB,kBAeAuB,QAAUA,KAEwB,oBAA5B1F,MAAMqM,kBAAkC,MAC5CjM,KAAO,iBACZJ,MAAMqM,kBAAkBvI,KAAMA,KAAKtD,cAIvC8L,WAAWP,QACJA,QAAUA,SACRjI,KAGTyI,kBAAkBvF,SACVhE,EAAOc,KAAK4B,QAAQuB,mBAAmBD,MAEzChE,IAASA,EAAKU,qBAIb3C,OAASiG,EAAK,QACdzG,QAAUyG,EAAK,QACfd,YAAc7F,EAAmByD,KAAK4B,QAAQpF,kBAAkB0G,EAAK,UACrE7C,MAAQ6C,EAAK,SAEZrD,EAASX,EAAOA,EAAKW,OAAS,QAE/BoI,QAAUjI,KAAKiI,SAAWpI,GAAWG,KAAKtD,YAAoB4L,EAAqBtI,YAClFA,MA/CGoI,EAOJE,EAAuBT"}
{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private _conditionsMatcher() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions!;\n }\n\n get ast() {\n const matches = this._conditionsMatcher();\n return matches ? matches.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n const matches = this._conditionsMatcher();\n return matches(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public, RawRuleOf } from './RuleIndex';\nimport { Abilities, AbilityTuple, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (\n rules: RawRuleOf<T>[],\n options: AbilityOptionsOf<T>\n) => T;\n\nexport class PureAbility<\n A extends Abilities = AbilityTuple,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n AnyObject,\n AnyClass,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends AnyClass<infer R>\n ? R\n : S extends string\n ? Exclude<Normalize<Generics<T>['abilities']>[1], SubjectType> extends { kind: string }\n ? Extract<Normalize<Generics<T>['abilities']>[1], TaggedInterface<S>>\n : AnyObject\n : never;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<T extends AnyAbility> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: AnyClass<T>;\n\n constructor(AbilityType: AnyClass<T>) {\n this._AbilityType = AbilityType;\n this.can = this.can.bind(this as any);\n this.cannot = this.cannot.bind(this as any);\n this.build = this.build.bind(this as any);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options);\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<T>['can'],\n cannot: AbilityBuilder<T>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<U extends AnyAbility>(ability: U) {\n return new this<U>(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","matches","ast","matchesConditions","matchesField","field","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}

@@ -1,2 +0,2 @@

import{buildOr as n,buildAnd as t}from"@ucast/mongo2js";function r(n){return Array.isArray(n)?n:[n]}function e(n,t,r){let e=n;let o=t;if(-1!==t.indexOf(".")){const r=t.split(".");o=r.pop();e=r.reduce((n,t)=>{n[t]=n[t]||{};return n[t]},n)}e[o]=r}function o(n,t,r,e){const o=Object.create(null);const u=n.rulesFor(t,r);for(let n=0;n<u.length;n++){const t=u[n];const r=t.inverted?"$and":"$or";if(!t.conditions)if(t.inverted)break;else{delete o[r];return o}else{o[r]=o[r]||[];o[r].push(e(t))}}return o.$or?o:null}function u(n){if(!n.ast)throw new Error(`Ability rule "${JSON.stringify(n)}" does not have "ast" property. So, cannot be used to generate AST`);return n.ast}function c(r,e,c){const i=o(r,e,c,u);if(null===i)return null;if(!i.$and)return i.$or?n(i.$or):t([]);if(i.$or)i.$and.push(n(i.$or));return t(i.$and)}function i(n,t,r){return n.rulesFor(t,r).reduce((n,t)=>{if(t.inverted||!t.conditions)return n;return Object.keys(t.conditions).reduce((n,r)=>{const o=t.conditions[r];if(!o||o.constructor!==Object)e(n,r,o);return n},n)},{})}const f=n=>n.fields;function s(n){this.delete(n)}function l(n){this.add(n)}function a(n,t,r,e={}){const o=e.fieldsFrom||f;const u=n.detectSubjectType(r);const c=n.possibleRulesFor(t,u).reduceRight((n,t)=>{if(!t.matchesConditions(r))return n;const e=o(t);if(e){const r=t.inverted?s:l;e.forEach(r,n)}return n},new Set);return Array.from(c)}const b=n=>Array.isArray(n)?n.join(","):n;function y(n,t){return n.map(n=>{const e=[b(n.action||n.actions),"function"===typeof t?r(n.subject).map(t).join(","):b(n.subject),n.conditions||0,n.inverted?1:0,n.fields?b(n.fields):0,n.reason||""];while(!e[e.length-1])e.pop();return e})}function p(n,t){return n.map(([n,r,e,o,u,c])=>{const i=r.split(",");const f={inverted:!!o,action:n.split(","),subject:"function"===typeof t?i.map(t):i};if(e)f.conditions=e;if(u)f.fields=u.split(",");if(c)f.reason=c;return f})}export{y as packRules,a as permittedFieldsOf,c as rulesToAST,i as rulesToFields,o as rulesToQuery,p as unpackRules};
import{buildOr as n,buildAnd as t}from"@ucast/mongo2js";function r(n){return Array.isArray(n)?n:[n]}function e(n,t,r){let e=n;let o=t;if(-1!==t.indexOf(".")){const r=t.split(".");o=r.pop();e=r.reduce(((n,t)=>{n[t]=n[t]||{};return n[t]}),n)}e[o]=r}function o(n,t,r,e){const o=Object.create(null);const c=n.rulesFor(t,r);for(let n=0;n<c.length;n++){const t=c[n];const r=t.inverted?"$and":"$or";if(!t.conditions)if(t.inverted)break;else{delete o[r];return o}else{o[r]=o[r]||[];o[r].push(e(t))}}return o.$or?o:null}function c(n){if(!n.ast)throw new Error(`Ability rule "${JSON.stringify(n)}" does not have "ast" property. So, cannot be used to generate AST`);return n.ast}function u(r,e,u){const i=o(r,e,u,c);if(null===i)return null;if(!i.$and)return i.$or?n(i.$or):t([]);if(i.$or)i.$and.push(n(i.$or));return t(i.$and)}function i(n,t,r){return n.rulesFor(t,r).reduce(((n,t)=>{if(t.inverted||!t.conditions)return n;return Object.keys(t.conditions).reduce(((n,r)=>{const o=t.conditions[r];if(!o||o.constructor!==Object)e(n,r,o);return n}),n)}),{})}function f(n,t,r,e){const o=n.detectSubjectType(r);const c=n.possibleRulesFor(t,o);const u=new Set;const i=u.delete.bind(u);const f=u.add.bind(u);let s=c.length;while(s--){const n=c[s];if(n.matchesConditions(r)){const t=n.inverted?i:f;e.fieldsFrom(n).forEach(t)}}return Array.from(u)}const s=n=>Array.isArray(n)?n.join(","):n;function l(n,t){return n.map((n=>{const e=[s(n.action||n.actions),"function"===typeof t?r(n.subject).map(t).join(","):s(n.subject),n.conditions||0,n.inverted?1:0,n.fields?s(n.fields):0,n.reason||""];while(!e[e.length-1])e.pop();return e}))}function a(n,t){return n.map((([n,r,e,o,c,u])=>{const i=r.split(",");const f={inverted:!!o,action:n.split(","),subject:"function"===typeof t?i.map(t):i};if(e)f.conditions=e;if(c)f.fields=c.split(",");if(u)f.reason=u;return f}))}export{l as packRules,f as permittedFieldsOf,u as rulesToAST,i as rulesToFields,o as rulesToQuery,a as unpackRules};
//# sourceMappingURL=extra.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"extra.mjs","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteItem(this: Set<string>, item: string) {\n this.delete(item);\n}\n\nfunction addItem(this: Set<string>, item: string) {\n this.add(item);\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {}\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const subjectType = ability.detectSubjectType(subject);\n const uniqueFields = ability.possibleRulesFor(action, subjectType)\n .reduceRight((fields, rule) => {\n if (!rule.matchesConditions(subject)) {\n return fields;\n }\n\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteItem : addItem;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, new Set<string>());\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","getRuleFields","deleteItem","item","delete","addItem","add","permittedFieldsOf","subject","options","fieldsFrom","detectSubjectType","uniqueFields","possibleRulesFor","reduceRight","matchesConditions","names","toggle","forEach","Set","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}
{"version":3,"file":"extra.mjs","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[];\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom: GetRuleFields<RuleOf<T>>\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T>\n): string[] {\n const subjectType = ability.detectSubjectType(subject);\n const rules = ability.possibleRulesFor(action, subjectType);\n const uniqueFields = new Set<string>();\n const deleteItem = uniqueFields.delete.bind(uniqueFields);\n const addItem = uniqueFields.add.bind(uniqueFields);\n let i = rules.length;\n\n while (i--) {\n const rule = rules[i];\n if (rule.matchesConditions(subject)) {\n const toggle = rule.inverted ? deleteItem : addItem;\n options.fieldsFrom(rule).forEach(toggle);\n }\n }\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","permittedFieldsOf","subject","options","detectSubjectType","possibleRulesFor","uniqueFields","Set","deleteItem","delete","bind","addItem","add","matchesConditions","toggle","fieldsFrom","forEach","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}

@@ -1,2 +0,2 @@

import{createFactory as t,$eq as s,$ne as e,$lt as n,$lte as i,$gt as r,$gte as o,$in as c,$nin as u,$all as h,$size as a,$regex as l,$options as f,$elemMatch as d,$exists as p,eq as g,ne as w,lt as y,lte as b,gt as $,gte as m,within as M,nin as j,all as v,size as x,regex as E,elemMatch as F,exists as _,and as A}from"@ucast/mongo2js";function O(t){return Array.isArray(t)?t:[t]}const C="__caslSubjectType__";function R(t,s){if(s)if(!s.hasOwnProperty(C))Object.defineProperty(s,C,{value:t});else if(t!==s[C])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${s[C]}`);return s}const z=t=>{const s=typeof t;return"string"===s||"function"===s};const T=t=>t.modelName||t.name;const S=t=>"string"===typeof t?t:T(t);function q(t){if(!t)return"all";if(t.hasOwnProperty(C))return t[C];return T(t.constructor)}function Y(t,s){let e=O(s);let n=0;while(n<e.length){const s=e[n++];if(t.hasOwnProperty(s))e=e.concat(t[s])}return e}function D(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach(s=>{const e=s===t[s]||Array.isArray(t[s])&&(-1!==t[s].indexOf(s)||-1!==t[s].indexOf("manage"));if(e)throw new Error(`Attempt to alias action to itself: ${s} -> ${t[s]}`)})}function I(t){if("production"!==process.env.NODE_ENV)D(t);return s=>Y(t,s)}function L(t,s,e){for(let n=e;n<s.length;n++)t.push(s[n])}function U(t,s){if(!t||!t.length)return s||[];if(!s||!s.length)return t||[];let e=0;let n=0;const i=[];while(e<t.length&&n<s.length)if(t[e].priority<s[n].priority){i.push(t[e]);e++}else{i.push(s[n]);n++}L(i,t,e);L(i,s,n);return i}function k(t,s,e){let n=t.get(s);if(!n){n=e();t.set(s,n)}return n}const B=t=>t;function G(t,s){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!s.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!s.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}class H{constructor(t,s,e=0){this.t=void 0;this.s=void 0;G(t,s);this.action=s.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?O(t.fields):void 0;this.priority=e;this.i=s}get o(){if(this.conditions&&!this.t)this.t=this.i.conditionsMatcher(this.conditions);return this.t}get u(){if(this.fields&&!this.s)this.s=this.i.fieldMatcher(this.fields);return this.s}get ast(){return this.o?this.o.ast:void 0}matchesConditions(t){if(!this.conditions)return true;if(!t||z(t))return!this.inverted;return this.o(t)}matchesField(t){if(!this.fields)return true;if(!t)return!this.inverted;return this.u(t)}}const J=(t,s)=>{const e={value:t,prev:s,next:null};if(s)s.next=e;return e};const K=t=>{if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null};const N=()=>({rules:[],merged:false});const P=()=>new Map;const Q=(t,s)=>{if(!t.h&&s.fields)t.h=true};class V{constructor(t=[],s={}){this.h=false;this.l=new Map;this.p={conditionsMatcher:s.conditionsMatcher,fieldMatcher:s.fieldMatcher,resolveAction:s.resolveAction||B};this.g=s.detectSubjectType||q;this.$=t;this.m=this.M(t)}get rules(){return this.$}detectSubjectType(t){return z(t)?t:this.g(t)}update(t){const s={rules:t,ability:this,target:this};this.j("update",s);this.$=t;this.m=this.M(t);this.j("updated",s);return this}M(t){const s=new Map;for(let e=t.length-1;e>=0;e--){const n=t.length-e-1;const i=new H(t[e],this.p,n);const r=O(i.action);const o=O(i.subject||"all");Q(this,i);for(let t=0;t<o.length;t++){const e=k(s,o[t],P);for(let t=0;t<r.length;t++)k(e,r[t],N).rules.push(i)}}return s}possibleRulesFor(t,s="all"){if(!z(s))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');const e=k(this.m,s,P);const n=k(e,t,N);if(n.merged)return n.rules;const i="manage"!==t&&e.has("manage")?e.get("manage").rules:void 0;let r=U(n.rules,i);if("all"!==s)r=U(r,this.possibleRulesFor(t,"all"));n.rules=r;n.merged=true;return r}rulesFor(t,s,e){const n=this.possibleRulesFor(t,s);if(e&&"string"!==typeof e)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return n;return n.filter(t=>t.matchesField(e))}on(t,s){const e=this.l.get(t)||null;const n=J(s,e);this.l.set(t,n);return()=>{if(!n.next&&!n.prev&&this.l.get(t)===n)this.l.delete(t);else K(n)}}j(t,s){let e=this.l.get(t)||null;while(null!==e){const t=e.prev;e.value(s);e=t}}}class W extends V{can(...t){const s=this.relevantRuleFor(...t);return!!s&&!s.inverted}relevantRuleFor(t,s,e){const n=this.detectSubjectType(s);const i=this.rulesFor(t,n,e);for(let t=0,e=i.length;t<e;t++)if(i[t].matchesConditions(s))return i[t];return null}cannot(...t){return!this.can(...t)}}const X={$eq:s,$ne:e,$lt:n,$lte:i,$gt:r,$gte:o,$in:c,$nin:u,$all:h,$size:a,$regex:l,$options:f,$elemMatch:d,$exists:p};const Z={eq:g,ne:w,lt:y,lte:b,gt:$,gte:m,in:M,nin:j,all:v,size:x,regex:E,elemMatch:F,exists:_,and:A};const tt=(s,e,n)=>t(Object.assign({},X,s),Object.assign({},Z,e),n);const st=t(X,Z);const et=/[-/\\^$+?.()|[\]{}]/g;const nt=/\.?\*+\.?/g;const it=/\*+/;const rt=/\./g;function ot(t,s,e){const n="*"===e[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const i=-1===t.indexOf("**")?"[^.]":".";const r=t.replace(rt,"\\$&").replace(it,i+n);return s+t.length===e.length?`(?:${r})?`:r}function ct(t,s,e){if("."===t&&("*"===e[s-1]||"*"===e[s+1]))return t;return`\\${t}`}function ut(t){const s=t.map(t=>t.replace(et,ct).replace(nt,ot));const e=s.length>1?`(?:${s.join("|")})`:s[0];return new RegExp(`^${e}$`)}const ht=t=>{let s;return e=>{if("undefined"===typeof s)s=t.every(t=>-1===t.indexOf("*"))?null:ut(t);return null===s?-1!==t.indexOf(e):s.test(e)}};class at extends W{constructor(t=[],s={}){super(t,Object.assign({conditionsMatcher:st,fieldMatcher:ht},s))}}class lt{constructor(t){this.v=t}because(t){this.v.reason=t;return this}}class ft{constructor(t){this.rules=[];this.F=t;const s=this;s.can=s.can.bind(s);s.cannot=s.cannot.bind(s);s.build=s.build.bind(s)}can(t,s,e,n){const i={action:t};if(s){i.subject=s;if(Array.isArray(e)||"string"===typeof e)i.fields=e;else if("undefined"!==typeof e)i.conditions=e;if("undefined"!==typeof n)i.conditions=n}this.rules.push(i);return new lt(i)}cannot(t,s,e,n){const i=this.can(t,s,e,n);i.v.inverted=true;return i}build(t){return new this.F(this.rules,t)}}function dt(t,s){const e=new ft(at);const n=t(e.can,e.cannot);if(n&&"function"===typeof n.then)return n.then(()=>e.build(s));return e.build(s)}const pt=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const gt=function t(s){this.message=s};gt.prototype=Object.create(Error.prototype);class wt extends gt{static setDefaultMessage(t){this._="string"===typeof t?()=>t:t}static from(t){return new this(t)}constructor(t){super("");this.field=void 0;this.ability=t;if("function"===typeof Error.captureStackTrace){this.name="ForbiddenError";Error.captureStackTrace(this,this.constructor)}}setMessage(t){this.message=t;return this}throwUnlessCan(...t){const s=this.ability.relevantRuleFor(...t);if(s&&!s.inverted)return;this.action=t[0];this.subject=t[1];this.subjectType=S(this.ability.detectSubjectType(t[1]));this.field=t[2];const e=s?s.reason:"";this.message=this.message||e||this.constructor._(this);throw this}}wt._=pt;export{at as Ability,ft as AbilityBuilder,wt as ForbiddenError,W as PureAbility,tt as buildMongoQueryMatcher,I as createAliasResolver,dt as defineAbility,q as detectSubjectType,ht as fieldPatternMatcher,pt as getDefaultErrorMessage,st as mongoQueryMatcher,R as subject,O as wrapArray};
import{createFactory as t,$eq as i,$ne as e,$lt as s,$lte as n,$gt as r,$gte as o,$in as c,$nin as u,$all as h,$size as l,$regex as a,$options as f,$elemMatch as d,$exists as p,eq as b,ne as y,lt as w,lte as g,gt as $,gte as m,within as A,nin as E,all as M,size as j,regex as v,elemMatch as x,exists as F,and as _}from"@ucast/mongo2js";function O(t){return Array.isArray(t)?t:[t]}const R="__caslSubjectType__";function C(t,i){if(i)if(!i.hasOwnProperty(R))Object.defineProperty(i,R,{value:t});else if(t!==i[R])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${i[R]}`);return i}const T=t=>{const i=typeof t;return"string"===i||"function"===i};const B=t=>t.modelName||t.name;const P=t=>"string"===typeof t?t:B(t);function S(t){if(!t)return"all";if(t.hasOwnProperty(R))return t[R];return B(t.constructor)}function q(t,i){let e=O(i);let s=0;while(s<e.length){const i=e[s++];if(t.hasOwnProperty(i))e=e.concat(t[i])}return e}function z(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach((i=>{const e=i===t[i]||Array.isArray(t[i])&&(-1!==t[i].indexOf(i)||-1!==t[i].indexOf("manage"));if(e)throw new Error(`Attempt to alias action to itself: ${i} -> ${t[i]}`)}))}function Y(t){if("production"!==process.env.NODE_ENV)z(t);return i=>q(t,i)}function D(t,i,e){for(let s=e;s<i.length;s++)t.push(i[s])}function I(t,i){if(!t||!t.length)return i||[];if(!i||!i.length)return t||[];let e=0;let s=0;const n=[];while(e<t.length&&s<i.length)if(t[e].priority<i[s].priority){n.push(t[e]);e++}else{n.push(i[s]);s++}D(n,t,e);D(n,i,s);return n}function L(t,i,e){let s=t.get(i);if(!s){s=e();t.set(i,s)}return s}const U=t=>t;function k(t,i){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!i.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!i.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}class G{constructor(t,i,e=0){this.t=void 0;this.i=void 0;k(t,i);this.action=i.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?O(t.fields):void 0;this.priority=e;this.o=i}u(){if(this.conditions&&!this.t)this.t=this.o.conditionsMatcher(this.conditions);return this.t}get ast(){const t=this.u();return t?t.ast:void 0}matchesConditions(t){if(!this.conditions)return true;if(!t||T(t))return!this.inverted;const i=this.u();return i(t)}matchesField(t){if(!this.fields)return true;if(!t)return!this.inverted;if(this.fields&&!this.i)this.i=this.o.fieldMatcher(this.fields);return this.i(t)}}const H=(t,i)=>{const e={value:t,prev:i,next:null};if(i)i.next=e;return e};const J=t=>{if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null};const K=()=>({rules:[],merged:false});const N=()=>new Map;const Q=(t,i)=>{if(!t.h&&i.fields)t.h=true};class V{constructor(t=[],i={}){this.h=false;this.l=new Map;this.p={conditionsMatcher:i.conditionsMatcher,fieldMatcher:i.fieldMatcher,resolveAction:i.resolveAction||U};this.g=i.detectSubjectType||S;this.$=t;this.m=this.A(t)}get rules(){return this.$}detectSubjectType(t){return T(t)?t:this.g(t)}update(t){const i={rules:t,ability:this,target:this};this.M("update",i);this.$=t;this.m=this.A(t);this.M("updated",i);return this}A(t){const i=new Map;for(let e=t.length-1;e>=0;e--){const s=t.length-e-1;const n=new G(t[e],this.p,s);const r=O(n.action);const o=O(n.subject||"all");Q(this,n);for(let t=0;t<o.length;t++){const e=L(i,o[t],N);for(let t=0;t<r.length;t++)L(e,r[t],K).rules.push(n)}}return i}possibleRulesFor(t,i="all"){if(!T(i))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');const e=L(this.m,i,N);const s=L(e,t,K);if(s.merged)return s.rules;const n="manage"!==t&&e.has("manage")?e.get("manage").rules:void 0;let r=I(s.rules,n);if("all"!==i)r=I(r,this.possibleRulesFor(t,"all"));s.rules=r;s.merged=true;return r}rulesFor(t,i,e){const s=this.possibleRulesFor(t,i);if(e&&"string"!==typeof e)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return s;return s.filter((t=>t.matchesField(e)))}on(t,i){const e=this.l.get(t)||null;const s=H(i,e);this.l.set(t,s);return()=>{if(!s.next&&!s.prev&&this.l.get(t)===s)this.l.delete(t);else J(s)}}M(t,i){let e=this.l.get(t)||null;while(null!==e){const t=e.prev;e.value(i);e=t}}}class PureAbility extends V{can(...t){const i=this.relevantRuleFor(...t);return!!i&&!i.inverted}relevantRuleFor(t,i,e){const s=this.detectSubjectType(i);const n=this.rulesFor(t,s,e);for(let t=0,e=n.length;t<e;t++)if(n[t].matchesConditions(i))return n[t];return null}cannot(...t){return!this.can(...t)}}const W={$eq:i,$ne:e,$lt:s,$lte:n,$gt:r,$gte:o,$in:c,$nin:u,$all:h,$size:l,$regex:a,$options:f,$elemMatch:d,$exists:p};const X={eq:b,ne:y,lt:w,lte:g,gt:$,gte:m,in:A,nin:E,all:M,size:j,regex:v,elemMatch:x,exists:F,and:_};const Z=(i,e,s)=>t(Object.assign({},W,i),Object.assign({},X,e),s);const tt=t(W,X);const it=/[-/\\^$+?.()|[\]{}]/g;const et=/\.?\*+\.?/g;const st=/\*+/;const nt=/\./g;function rt(t,i,e){const s="*"===e[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const n=-1===t.indexOf("**")?"[^.]":".";const r=t.replace(nt,"\\$&").replace(st,n+s);return i+t.length===e.length?`(?:${r})?`:r}function ot(t,i,e){if("."===t&&("*"===e[i-1]||"*"===e[i+1]))return t;return`\\${t}`}function ct(t){const i=t.map((t=>t.replace(it,ot).replace(et,rt)));const e=i.length>1?`(?:${i.join("|")})`:i[0];return new RegExp(`^${e}$`)}const ut=t=>{let i;return e=>{if("undefined"===typeof i)i=t.every((t=>-1===t.indexOf("*")))?null:ct(t);return null===i?-1!==t.indexOf(e):i.test(e)}};class Ability extends PureAbility{constructor(t=[],i={}){super(t,Object.assign({conditionsMatcher:tt,fieldMatcher:ut},i))}}class ht{constructor(t){this.j=t}because(t){this.j.reason=t;return this}}class AbilityBuilder{constructor(t){this.rules=[];this.v=t;this.can=this.can.bind(this);this.cannot=this.cannot.bind(this);this.build=this.build.bind(this)}can(t,i,e,s){const n={action:t};if(i){n.subject=i;if(Array.isArray(e)||"string"===typeof e)n.fields=e;else if("undefined"!==typeof e)n.conditions=e;if("undefined"!==typeof s)n.conditions=s}this.rules.push(n);return new ht(n)}cannot(t,i,e,s){const n=this.can(t,i,e,s);n.j.inverted=true;return n}build(t){return new this.v(this.rules,t)}}function defineAbility(t,i){const e=new AbilityBuilder(Ability);const s=t(e.can,e.cannot);if(s&&"function"===typeof s.then)return s.then((()=>e.build(i)));return e.build(i)}const lt=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const at=function t(i){this.message=i};at.prototype=Object.create(Error.prototype);class ForbiddenError extends at{static setDefaultMessage(t){this.F="string"===typeof t?()=>t:t}static from(t){return new this(t)}constructor(t){super("");this.field=void 0;this.ability=t;if("function"===typeof Error.captureStackTrace){this.name="ForbiddenError";Error.captureStackTrace(this,this.constructor)}}setMessage(t){this.message=t;return this}throwUnlessCan(...t){const i=this.ability.relevantRuleFor(...t);if(i&&!i.inverted)return;this.action=t[0];this.subject=t[1];this.subjectType=P(this.ability.detectSubjectType(t[1]));this.field=t[2];const e=i?i.reason:"";this.message=this.message||e||this.constructor.F(this);throw this}}ForbiddenError.F=lt;export{Ability,AbilityBuilder,ForbiddenError,PureAbility,Z as buildMongoQueryMatcher,Y as createAliasResolver,defineAbility,S as detectSubjectType,ut as fieldPatternMatcher,lt as getDefaultErrorMessage,tt as mongoQueryMatcher,C as subject,O as wrapArray};
//# sourceMappingURL=index.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.mjs","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","this","_lazyMatchConditions","ast","matchesConditions","matchesField","field","_lazyMatchField","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}
{"version":3,"file":"index.mjs","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private _conditionsMatcher() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions!;\n }\n\n get ast() {\n const matches = this._conditionsMatcher();\n return matches ? matches.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n const matches = this._conditionsMatcher();\n return matches(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public, RawRuleOf } from './RuleIndex';\nimport { Abilities, AbilityTuple, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (\n rules: RawRuleOf<T>[],\n options: AbilityOptionsOf<T>\n) => T;\n\nexport class PureAbility<\n A extends Abilities = AbilityTuple,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n AnyObject,\n AnyClass,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends AnyClass<infer R>\n ? R\n : S extends string\n ? Exclude<Normalize<Generics<T>['abilities']>[1], SubjectType> extends { kind: string }\n ? Extract<Normalize<Generics<T>['abilities']>[1], TaggedInterface<S>>\n : AnyObject\n : never;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<T extends AnyAbility> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: AnyClass<T>;\n\n constructor(AbilityType: AnyClass<T>) {\n this._AbilityType = AbilityType;\n this.can = this.can.bind(this as any);\n this.cannot = this.cannot.bind(this as any);\n this.build = this.build.bind(this as any);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options);\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<T>['can'],\n cannot: AbilityBuilder<T>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<U extends AnyAbility>(ability: U) {\n return new this<U>(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","matches","ast","matchesConditions","matchesField","field","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}

@@ -6,5 +6,2 @@ import { PureAbility, AbilityOptions } from './PureAbility';

import { MongoQuery } from './matchers/conditions';
/**
* @deprecated use `createMongoAbility` function instead
*/
export declare class Ability<A extends AbilityTuple = AbilityTuple, C extends MongoQuery = MongoQuery> extends PureAbility<A, C> {

@@ -11,0 +8,0 @@ constructor(rules?: RawRuleFrom<A, C>[], options?: AbilityOptions<A, C>);

import { AnyMongoAbility } from './Ability';
import { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';
import { AnyAbility, AbilityOptionsOf } from './PureAbility';
import { RawRuleOf, Generics } from './RuleIndex';
import { ExtractSubjectType as E, AbilityTuple, SubjectType, TaggedInterface, Normalize, SubjectClass, AnyObject } from './types';
import { ExtractSubjectType as E, AbilityTuple, SubjectType, TaggedInterface, Normalize, AnyObject, AnyClass } from './types';
import { ProduceGeneric } from './hkt';

@@ -11,4 +11,5 @@ declare class RuleBuilder<T extends AnyAbility> {

}
declare type ExtractWithDefault<T, U, D = never> = T extends U ? T : D;
declare type InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass ? InstanceType<S> : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;
declare type InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends AnyClass<infer R> ? R : S extends string ? Exclude<Normalize<Generics<T>['abilities']>[1], SubjectType> extends {
kind: string;
} ? Extract<Normalize<Generics<T>['abilities']>[1], TaggedInterface<S>> : AnyObject : never;
declare type ConditionsOf<T extends AnyAbility, I extends {}> = ProduceGeneric<Generics<T>['conditions'], I>;

@@ -22,6 +23,6 @@ declare type ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any ? S extends T[1] ? T[0] : never : never;

declare type Keys<T> = string & keyof T;
export declare class AbilityBuilder<U extends AbilityClass<AnyAbility>, T extends InstanceType<U> = InstanceType<U>> {
export declare class AbilityBuilder<T extends AnyAbility> {
rules: RawRuleOf<T>[];
private _AbilityType;
constructor(AbilityType: U);
constructor(AbilityType: AnyClass<T>);
can<I extends InstanceOf<T, S>, S extends SubjectTypeOf<T> = SubjectTypeOf<T>>(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>;

@@ -33,5 +34,5 @@ can<I extends InstanceOf<T, S>, F extends string = Keys<I>, S extends SubjectTypeOf<T> = SubjectTypeOf<T>>(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>;

}
declare type DSL<T extends AnyAbility, R> = (can: AbilityBuilder<AbilityClass<T>>['can'], cannot: AbilityBuilder<AbilityClass<T>>['cannot']) => R;
declare type DSL<T extends AnyAbility, R> = (can: AbilityBuilder<T>['can'], cannot: AbilityBuilder<T>['cannot']) => R;
export declare function defineAbility<T extends AnyMongoAbility>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;
export declare function defineAbility<T extends AnyMongoAbility>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;
export {};

@@ -15,8 +15,33 @@ import { Condition } from '@ucast/mongo2js';

export declare function rulesToFields<T extends PureAbility<any, AnyObject>>(ability: T, action: Parameters<T['rulesFor']>[0], subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>): AnyObject;
export declare type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;
export declare type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[];
export interface PermittedFieldsOptions<T extends AnyAbility> {
fieldsFrom?: GetRuleFields<RuleOf<T>>;
fieldsFrom: GetRuleFields<RuleOf<T>>;
}
export declare function permittedFieldsOf<T extends AnyAbility>(ability: T, action: Parameters<T['can']>[0], subject: Parameters<T['can']>[1], options?: PermittedFieldsOptions<T>): string[];
export declare type PackRule<T extends RawRule<any, any>> = [string, string] | [string, string, T['conditions']] | [string, string, T['conditions'] | 0, 1] | [string, string, T['conditions'] | 0, 1 | 0, string] | [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];
export declare function permittedFieldsOf<T extends AnyAbility>(ability: T, action: Parameters<T['can']>[0], subject: Parameters<T['can']>[1], options: PermittedFieldsOptions<T>): string[];
export declare type PackRule<T extends RawRule<any, any>> = [
string,
string
] | [
string,
string,
T['conditions']
] | [
string,
string,
T['conditions'] | 0,
1
] | [
string,
string,
T['conditions'] | 0,
1 | 0,
string
] | [
string,
string,
T['conditions'] | 0,
1 | 0,
string | 0,
string
];
export declare type PackSubjectType<T extends SubjectType> = (type: T) => string;

@@ -23,0 +48,0 @@ export declare function packRules<T extends RawRule<any, any>>(rules: T[], packSubject?: PackSubjectType<T['subject']>): PackRule<T>[];

@@ -15,3 +15,3 @@ import { AnyAbility } from './PureAbility';

static setDefaultMessage(messageOrFn: string | GetErrorMessage): void;
static from<T extends AnyAbility>(ability: T): ForbiddenError<T>;
static from<U extends AnyAbility>(ability: U): ForbiddenError<U>;
private constructor();

@@ -18,0 +18,0 @@ setMessage(message: string): this;

@@ -6,7 +6,7 @@ export * from './Ability';

export * from './RawRule';
export * from './types';
export * from './hkt';
export * from './matchers/conditions';
export * from './matchers/field';
export type { SubjectClass, SubjectType, Subject, AbilityTuple, Abilities, Normalize, IfString, AbilityParameters, CanParameters, ExtractSubjectType, InferSubjects, ForcedSubject, MatchConditions, ConditionsMatcher, MatchField, FieldMatcher, } from './types';
export type { Generics, RuleOf, RawRuleOf, UpdateEvent, EventHandler, Unsubscribe } from './RuleIndex';
export { setSubjectType as subject, detectSubjectType, createAliasResolver, wrapArray } from './utils';

@@ -17,5 +17,5 @@ import { createFactory, BuildMongoQuery, DefaultOperators } from '@ucast/mongo2js';

$options: import("@ucast/mongo2js").FieldInstruction<unknown, import("@ucast/mongo2js").FieldParsingContext>;
$elemMatch: import("@ucast/mongo2js").FieldInstruction<({
$elemMatch: import("@ucast/mongo2js").FieldInstruction<import("@ucast/mongo2js").MongoQueryOperators<any> | ({
[x: string]: any;
} & import("@ucast/mongo2js").MongoQueryTopLevelOperators<any>) | (import("@ucast/mongo2js").MongoQueryFieldOperators<any> & import("@ucast/mongo2js").MongoQueryTopLevelOperators<any> & import("@ucast/mongo2js").MongoQueryTopLevelOperators<any>), import("@ucast/mongo2js").FieldParsingContext>;
} & import("@ucast/mongo2js").MongoQueryTopLevelOperators<any>), import("@ucast/mongo2js").FieldParsingContext>;
$exists: import("@ucast/mongo2js").FieldInstruction<boolean, import("@ucast/mongo2js").FieldParsingContext>;

@@ -22,0 +22,0 @@ };

@@ -1,3 +0,3 @@

import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';
import { Abilities, CanParameters } from './types';
import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public, RawRuleOf } from './RuleIndex';
import { Abilities, AbilityTuple, CanParameters } from './types';
import { Rule } from './Rule';

@@ -7,4 +7,4 @@ export declare type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;

export declare type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;
export declare type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;
export declare class PureAbility<A extends Abilities = Abilities, Conditions = unknown> extends RuleIndex<A, Conditions> {
export declare type AbilityClass<T extends AnyAbility> = new (rules: RawRuleOf<T>[], options: AbilityOptionsOf<T>) => T;
export declare class PureAbility<A extends Abilities = AbilityTuple, Conditions = unknown> extends RuleIndex<A, Conditions> {
can(...args: CanParameters<A>): boolean;

@@ -11,0 +11,0 @@ relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null;

@@ -22,4 +22,3 @@ import { Abilities, ToAbilityTypes, Normalize, ConditionsMatcher, FieldMatcher } from './types';

constructor(rule: RawRule<ToAbilityTypes<A>, C>, options: RuleOptions<A, C>, priority?: number);
private get _lazyMatchConditions();
private get _lazyMatchField();
private _conditionsMatcher;
get ast(): import("@ucast/mongo2js").Condition<unknown> | undefined;

@@ -26,0 +25,0 @@ matchesConditions(object: Normalize<A>[1] | undefined): boolean;

import type { Condition } from '@ucast/mongo2js';
import { Container, GenericFactory } from './hkt';
declare type Fn = (...args: any[]) => any;
declare type AnyClass<ReturnType = any> = new (...args: any[]) => ReturnType;
export declare type AnyClass<ReturnType = any> = new (...args: any[]) => ReturnType;
declare type AnyRecord = Record<PropertyKey, any>;

@@ -6,0 +6,0 @@ export declare type AnyObject = Record<PropertyKey, unknown>;

@@ -1,2 +0,2 @@

(function(n,r){"object"===typeof exports&&"undefined"!==typeof module?r(exports,require("@ucast/mongo2js")):"function"===typeof define&&define.amd?define(["exports","@ucast/mongo2js"],r):(n=n||self,r((n.casl=n.casl||{},n.casl.extra={}),n.ucast.mongo2js))})(this,(function(n,r){"use strict";function t(n){return Array.isArray(n)?n:[n]}function e(n,r,t){var e=n;var u=r;if(-1!==r.indexOf(".")){var i=r.split(".");u=i.pop();e=i.reduce((function(n,r){n[r]=n[r]||{};return n[r]}),n)}e[u]=t}function u(n,r,t,e){var u=Object.create(null);var i=n.rulesFor(r,t);for(var o=0;o<i.length;o++){var f=i[o];var c=f.inverted?"$and":"$or";if(!f.conditions)if(f.inverted)break;else{delete u[c];return u}else{u[c]=u[c]||[];u[c].push(e(f))}}return u.$or?u:null}function i(n){if(!n.ast)throw new Error('Ability rule "'+JSON.stringify(n)+'" does not have "ast" property. So, cannot be used to generate AST');return n.ast}function o(n,t,e){var o=u(n,t,e,i);if(null===o)return null;if(!o.$and)return o.$or?r.buildOr(o.$or):r.buildAnd([]);if(o.$or)o.$and.push(r.buildOr(o.$or));return r.buildAnd(o.$and)}function f(n,r,t){return n.rulesFor(r,t).reduce((function(n,r){if(r.inverted||!r.conditions)return n;return Object.keys(r.conditions).reduce((function(n,t){var u=r.conditions[t];if(!u||u.constructor!==Object)e(n,t,u);return n}),n)}),{})}var c=function n(r){return r.fields};function a(n){this.delete(n)}function v(n){this.add(n)}function s(n,r,t,e){if(void 0===e)e={};var u=e.fieldsFrom||c;var i=n.detectSubjectType(t);var o=n.possibleRulesFor(r,i).reduceRight((function(n,r){if(!r.matchesConditions(t))return n;var e=u(r);if(e){var i=r.inverted?a:v;e.forEach(i,n)}return n}),new Set);return Array.from(o)}var l=function n(r){return Array.isArray(r)?r.join(","):r};function d(n,r){return n.map((function(n){var e=[l(n.action||n.actions),"function"===typeof r?t(n.subject).map(r).join(","):l(n.subject),n.conditions||0,n.inverted?1:0,n.fields?l(n.fields):0,n.reason||""];while(!e[e.length-1])e.pop();return e}))}function p(n,r){return n.map((function(n){var t=n[0],e=n[1],u=n[2],i=n[3],o=n[4],f=n[5];var c=e.split(",");var a={inverted:!!i,action:t.split(","),subject:"function"===typeof r?c.map(r):c};if(u)a.conditions=u;if(o)a.fields=o.split(",");if(f)a.reason=f;return a}))}n.packRules=d;n.permittedFieldsOf=s;n.rulesToAST=o;n.rulesToFields=f;n.rulesToQuery=u;n.unpackRules=p;Object.defineProperty(n,"__esModule",{value:true})}));
(function(r,n){"object"===typeof exports&&"undefined"!==typeof module?n(exports,require("@ucast/mongo2js")):"function"===typeof define&&define.amd?define(["exports","@ucast/mongo2js"],n):(r="undefined"!==typeof globalThis?globalThis:r||self,n((r.casl=r.casl||{},r.casl.extra={}),r.ucast.mongo2js))})(this,(function(r,n){"use strict";function e(r){return Array.isArray(r)?r:[r]}function t(r,n,e){var t=r;var u=n;if(-1!==n.indexOf(".")){var i=n.split(".");u=i.pop();t=i.reduce((function(r,n){r[n]=r[n]||{};return r[n]}),r)}t[u]=e}function u(r,n,e,t){var u=Object.create(null);var i=r.rulesFor(n,e);for(var o=0;o<i.length;o++){var f=i[o];var a=f.inverted?"$and":"$or";if(!f.conditions)if(f.inverted)break;else{delete u[a];return u}else{u[a]=u[a]||[];u[a].push(t(f))}}return u.$or?u:null}function i(r){if(!r.ast)throw new Error('Ability rule "'+JSON.stringify(r)+'" does not have "ast" property. So, cannot be used to generate AST');return r.ast}function o(r,e,t){var o=u(r,e,t,i);if(null===o)return null;if(!o.$and)return o.$or?n.buildOr(o.$or):n.buildAnd([]);if(o.$or)o.$and.push(n.buildOr(o.$or));return n.buildAnd(o.$and)}function f(r,n,e){return r.rulesFor(n,e).reduce((function(r,n){if(n.inverted||!n.conditions)return r;return Object.keys(n.conditions).reduce((function(r,e){var u=n.conditions[e];if(!u||u.constructor!==Object)t(r,e,u);return r}),r)}),{})}function a(r,n,e,t){var u=r.detectSubjectType(e);var i=r.possibleRulesFor(n,u);var o=new Set;var f=o.delete.bind(o);var a=o.add.bind(o);var c=i.length;while(c--){var v=i[c];if(v.matchesConditions(e)){var l=v.inverted?f:a;t.fieldsFrom(v).forEach(l)}}return Array.from(o)}var c=function r(n){return Array.isArray(n)?n.join(","):n};function v(r,n){return r.map((function(r){var t=[c(r.action||r.actions),"function"===typeof n?e(r.subject).map(n).join(","):c(r.subject),r.conditions||0,r.inverted?1:0,r.fields?c(r.fields):0,r.reason||""];while(!t[t.length-1])t.pop();return t}))}function l(r,n){return r.map((function(r){var e=r[0],t=r[1],u=r[2],i=r[3],o=r[4],f=r[5];var a=t.split(",");var c={inverted:!!i,action:e.split(","),subject:"function"===typeof n?a.map(n):a};if(u)c.conditions=u;if(o)c.fields=o.split(",");if(f)c.reason=f;return c}))}r.packRules=v;r.permittedFieldsOf=a;r.rulesToAST=o;r.rulesToFields=f;r.rulesToQuery=u;r.unpackRules=l;Object.defineProperty(r,"__esModule",{value:true})}));
//# sourceMappingURL=extra.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteItem(this: Set<string>, item: string) {\n this.delete(item);\n}\n\nfunction addItem(this: Set<string>, item: string) {\n this.add(item);\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {}\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const subjectType = ability.detectSubjectType(subject);\n const uniqueFields = ability.possibleRulesFor(action, subjectType)\n .reduceRight((fields, rule) => {\n if (!rule.matchesConditions(subject)) {\n return fields;\n }\n\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteItem : addItem;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, new Set<string>());\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","getRuleFields","deleteItem","item","delete","addItem","add","permittedFieldsOf","subject","options","fieldsFrom","detectSubjectType","uniqueFields","possibleRulesFor","reduceRight","matchesConditions","names","toggle","forEach","Set","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}
{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[];\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom: GetRuleFields<RuleOf<T>>\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T>\n): string[] {\n const subjectType = ability.detectSubjectType(subject);\n const rules = ability.possibleRulesFor(action, subjectType);\n const uniqueFields = new Set<string>();\n const deleteItem = uniqueFields.delete.bind(uniqueFields);\n const addItem = uniqueFields.add.bind(uniqueFields);\n let i = rules.length;\n\n while (i--) {\n const rule = rules[i];\n if (rule.matchesConditions(subject)) {\n const toggle = rule.inverted ? deleteItem : addItem;\n options.fieldsFrom(rule).forEach(toggle);\n }\n }\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","permittedFieldsOf","subject","options","detectSubjectType","possibleRulesFor","uniqueFields","Set","deleteItem","delete","bind","addItem","add","matchesConditions","toggle","fieldsFrom","forEach","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"}

@@ -1,2 +0,2 @@

(function(t,r){"object"===typeof exports&&"undefined"!==typeof module?r(exports,require("@ucast/mongo2js")):"function"===typeof define&&define.amd?define(["exports","@ucast/mongo2js"],r):(t=t||self,r(t.casl={},t.ucast.mongo2js))})(this,(function(t,r){"use strict";function n(t,r){for(var n=0;n<r.length;n++){var i=r[n];i.enumerable=i.enumerable||false;i.configurable=true;if("value"in i)i.writable=true;Object.defineProperty(t,i.key,i)}}function i(t,r,i){if(r)n(t.prototype,r);if(i)n(t,i);return t}function e(){e=Object.assign||function(t){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i))t[i]=n[i]}return t};return e.apply(this,arguments)}function u(t,r){t.prototype=Object.create(r.prototype);t.prototype.constructor=t;t.__proto__=r}function o(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function s(t){return Array.isArray(t)?t:[t]}var a="__caslSubjectType__";function f(t,r){if(r)if(!r.hasOwnProperty(a))Object.defineProperty(r,a,{value:t});else if(t!==r[a])throw new Error("Trying to cast object to subject type "+t+" but previously it was casted to "+r[a]);return r}var c=function t(r){var n=typeof r;return"string"===n||"function"===n};var h=function t(r){return r.modelName||r.name};var v=function t(r){return"string"===typeof r?r:h(r)};function l(t){if(!t)return"all";if(t.hasOwnProperty(a))return t[a];return h(t.constructor)}function d(t,r){var n=s(r);var i=0;while(i<n.length){var e=n[i++];if(t.hasOwnProperty(e))n=n.concat(t[e])}return n}function p(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach((function(r){var n=r===t[r]||Array.isArray(t[r])&&(-1!==t[r].indexOf(r)||-1!==t[r].indexOf("manage"));if(n)throw new Error("Attempt to alias action to itself: "+r+" -> "+t[r])}))}function y(t){if("production"!==process.env.NODE_ENV)p(t);return function(r){return d(t,r)}}function w(t,r,n){for(var i=n;i<r.length;i++)t.push(r[i])}function g(t,r){if(!t||!t.length)return r||[];if(!r||!r.length)return t||[];var n=0;var i=0;var e=[];while(n<t.length&&i<r.length)if(t[n].priority<r[i].priority){e.push(t[n]);n++}else{e.push(r[i]);i++}w(e,t,n);w(e,r,i);return e}function b(t,r,n){var i=t.get(r);if(!i){i=n();t.set(r,i)}return i}var $=function t(r){return r};function m(t,r){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!r.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!r.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}var j=function(){function t(t,r,n){if(void 0===n)n=0;this.t=void 0;this.i=void 0;m(t,r);this.action=r.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?s(t.fields):void 0;this.priority=n;this.u=r}var r=t.prototype;r.matchesConditions=function t(r){if(!this.conditions)return true;if(!r||c(r))return!this.inverted;return this.o(r)};r.matchesField=function t(r){if(!this.fields)return true;if(!r)return!this.inverted;return this.s(r)};i(t,[{key:"_lazyMatchConditions",get:function t(){if(this.conditions&&!this.t)this.t=this.u.conditionsMatcher(this.conditions);return this.t}},{key:"_lazyMatchField",get:function t(){if(this.fields&&!this.i)this.i=this.u.fieldMatcher(this.fields);return this.i}},{key:"ast",get:function t(){return this.o?this.o.ast:void 0}}]);return t}();var E=function t(r,n){var i={value:r,prev:n,next:null};if(n)n.next=i;return i};var M=function t(r){if(r.next)r.next.prev=r.prev;if(r.prev)r.prev.next=r.next;r.next=r.prev=null};var x=function t(){return{rules:[],merged:false}};var O=function t(){return new Map};var _=function t(r,n){if(!r.h&&n.fields)r.h=true};var A=function(){function t(t,r){if(void 0===t)t=[];if(void 0===r)r={};this.h=false;this.v=new Map;this.l={conditionsMatcher:r.conditionsMatcher,fieldMatcher:r.fieldMatcher,resolveAction:r.resolveAction||$};this.p=r.detectSubjectType||l;this.g=t;this.$=this.m(t)}var r=t.prototype;r.detectSubjectType=function t(r){return c(r)?r:this.p(r)};r.update=function t(r){var n={rules:r,ability:this,target:this};this.j("update",n);this.g=r;this.$=this.m(r);this.j("updated",n);return this};r.m=function t(r){var n=new Map;for(var i=r.length-1;i>=0;i--){var e=r.length-i-1;var u=new j(r[i],this.l,e);var o=s(u.action);var a=s(u.subject||"all");_(this,u);for(var f=0;f<a.length;f++){var c=b(n,a[f],O);for(var h=0;h<o.length;h++)b(c,o[h],x).rules.push(u)}}return n};r.possibleRulesFor=function t(r,n){if(void 0===n)n="all";if(!c(n))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');var i=b(this.$,n,O);var e=b(i,r,x);if(e.merged)return e.rules;var u="manage"!==r&&i.has("manage")?i.get("manage").rules:void 0;var o=g(e.rules,u);if("all"!==n)o=g(o,this.possibleRulesFor(r,"all"));e.rules=o;e.merged=true;return o};r.rulesFor=function t(r,n,i){var e=this.possibleRulesFor(r,n);if(i&&"string"!==typeof i)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return e;return e.filter((function(t){return t.matchesField(i)}))};r.on=function t(r,n){var i=this;var e=this.v.get(r)||null;var u=E(n,e);this.v.set(r,u);return function(){if(!u.next&&!u.prev&&i.v.get(r)===u)i.v.delete(r);else M(u)}};r.j=function t(r,n){var i=this.v.get(r)||null;while(null!==i){var e=i.prev;i.value(n);i=e}};i(t,[{key:"rules",get:function t(){return this.g}}]);return t}();var k=function(t){u(r,t);function r(){return t.apply(this,arguments)||this}var n=r.prototype;n.can=function t(){var r=this.relevantRuleFor.apply(this,arguments);return!!r&&!r.inverted};n.relevantRuleFor=function t(r,n,i){var e=this.detectSubjectType(n);var u=this.rulesFor(r,e,i);for(var o=0,s=u.length;o<s;o++)if(u[o].matchesConditions(n))return u[o];return null};n.cannot=function t(){return!this.can.apply(this,arguments)};return r}(A);var z={$eq:r.$eq,$ne:r.$ne,$lt:r.$lt,$lte:r.$lte,$gt:r.$gt,$gte:r.$gte,$in:r.$in,$nin:r.$nin,$all:r.$all,$size:r.$size,$regex:r.$regex,$options:r.$options,$elemMatch:r.$elemMatch,$exists:r.$exists};var R={eq:r.eq,ne:r.ne,lt:r.lt,lte:r.lte,gt:r.gt,gte:r.gte,in:r.within,nin:r.nin,all:r.all,size:r.size,regex:r.regex,elemMatch:r.elemMatch,exists:r.exists,and:r.and};var q=function t(n,i,u){return r.createFactory(e({},z,n),e({},R,i),u)};var C=r.createFactory(z,R);var F=/[-/\\^$+?.()|[\]{}]/g;var T=/\.?\*+\.?/g;var S=/\*+/;var Y=/\./g;function L(t,r,n){var i="*"===n[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";var e=-1===t.indexOf("**")?"[^.]":".";var u=t.replace(Y,"\\$&").replace(S,e+i);return r+t.length===n.length?"(?:"+u+")?":u}function B(t,r,n){if("."===t&&("*"===n[r-1]||"*"===n[r+1]))return t;return"\\"+t}function D(t){var r=t.map((function(t){return t.replace(F,B).replace(T,L)}));var n=r.length>1?"(?:"+r.join("|")+")":r[0];return new RegExp("^"+n+"$")}var G=function t(r){var n;return function(t){if("undefined"===typeof n)n=r.every((function(t){return-1===t.indexOf("*")}))?null:D(r);return null===n?-1!==r.indexOf(t):n.test(t)}};var H=function(t){u(r,t);function r(r,n){if(void 0===r)r=[];if(void 0===n)n={};return t.call(this,r,e({conditionsMatcher:C,fieldMatcher:G},n))||this}return r}(k);var I=function(){function t(t){this.M=t}var r=t.prototype;r.because=function t(r){this.M.reason=r;return this};return t}();var J=function(){function t(t){this.rules=[];this.O=t;var r=this;r.can=r.can.bind(r);r.cannot=r.cannot.bind(r);r.build=r.build.bind(r)}var r=t.prototype;r.can=function t(r,n,i,e){var u={action:r};if(n){u.subject=n;if(Array.isArray(i)||"string"===typeof i)u.fields=i;else if("undefined"!==typeof i)u.conditions=i;if("undefined"!==typeof e)u.conditions=e}this.rules.push(u);return new I(u)};r.cannot=function t(r,n,i,e){var u=this.can(r,n,i,e);u.M.inverted=true;return u};r.build=function t(r){return new this.O(this.rules,r)};return t}();function K(t,r){var n=new J(H);var i=t(n.can,n.cannot);if(i&&"function"===typeof i.then)return i.then((function(){return n.build(r)}));return n.build(r)}var N=function t(r){return'Cannot execute "'+r.action+'" on "'+r.subjectType+'"'};var P=function t(r){this.message=r};P.prototype=Object.create(Error.prototype);var Q=function(t){u(r,t);r.setDefaultMessage=function t(r){this._="string"===typeof r?function(){return r}:r};r.from=function t(r){return new this(r)};function r(r){var n;n=t.call(this,"")||this;n.field=void 0;n.ability=r;if("function"===typeof Error.captureStackTrace){n.name="ForbiddenError";Error.captureStackTrace(o(n),n.constructor)}return n}var n=r.prototype;n.setMessage=function t(r){this.message=r;return this};n.throwUnlessCan=function t(){var r;var n=(r=this.ability).relevantRuleFor.apply(r,arguments);if(n&&!n.inverted)return;this.action=arguments.length<=0?void 0:arguments[0];this.subject=arguments.length<=1?void 0:arguments[1];this.subjectType=v(this.ability.detectSubjectType(arguments.length<=1?void 0:arguments[1]));this.field=arguments.length<=2?void 0:arguments[2];var i=n?n.reason:"";this.message=this.message||i||this.constructor._(this);throw this};return r}(P);Q._=N;t.Ability=H;t.AbilityBuilder=J;t.ForbiddenError=Q;t.PureAbility=k;t.buildMongoQueryMatcher=q;t.createAliasResolver=y;t.defineAbility=K;t.detectSubjectType=l;t.fieldPatternMatcher=G;t.getDefaultErrorMessage=N;t.mongoQueryMatcher=C;t.subject=f;t.wrapArray=s;Object.defineProperty(t,"__esModule",{value:true})}));
(function(t,r){"object"===typeof exports&&"undefined"!==typeof module?r(exports,require("@ucast/mongo2js")):"function"===typeof define&&define.amd?define(["exports","@ucast/mongo2js"],r):(t="undefined"!==typeof globalThis?globalThis:t||self,r(t.casl={},t.ucast.mongo2js))})(this,(function(t,r){"use strict";function i(t,r){for(var i=0;i<r.length;i++){var n=r[i];n.enumerable=n.enumerable||false;n.configurable=true;if("value"in n)n.writable=true;Object.defineProperty(t,n.key,n)}}function n(t,r,n){if(r)i(t.prototype,r);if(n)i(t,n);return t}function e(){e=Object.assign||function(t){for(var r=1;r<arguments.length;r++){var i=arguments[r];for(var n in i)if(Object.prototype.hasOwnProperty.call(i,n))t[n]=i[n]}return t};return e.apply(this,arguments)}function o(t,r){t.prototype=Object.create(r.prototype);t.prototype.constructor=t;t.__proto__=r}function u(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function s(t){return Array.isArray(t)?t:[t]}var f="__caslSubjectType__";function a(t,r){if(r)if(!r.hasOwnProperty(f))Object.defineProperty(r,f,{value:t});else if(t!==r[f])throw new Error("Trying to cast object to subject type "+t+" but previously it was casted to "+r[f]);return r}var c=function t(r){var i=typeof r;return"string"===i||"function"===i};var h=function t(r){return r.modelName||r.name};var v=function t(r){return"string"===typeof r?r:h(r)};function l(t){if(!t)return"all";if(t.hasOwnProperty(f))return t[f];return h(t.constructor)}function d(t,r){var i=s(r);var n=0;while(n<i.length){var e=i[n++];if(t.hasOwnProperty(e))i=i.concat(t[e])}return i}function b(t){if(t.manage)throw new Error('Cannot add alias for "manage" action because it is reserved');Object.keys(t).forEach((function(r){var i=r===t[r]||Array.isArray(t[r])&&(-1!==t[r].indexOf(r)||-1!==t[r].indexOf("manage"));if(i)throw new Error("Attempt to alias action to itself: "+r+" -> "+t[r])}))}function p(t){if("production"!==process.env.NODE_ENV)b(t);return function(r){return d(t,r)}}function y(t,r,i){for(var n=i;n<r.length;n++)t.push(r[n])}function w(t,r){if(!t||!t.length)return r||[];if(!r||!r.length)return t||[];var i=0;var n=0;var e=[];while(i<t.length&&n<r.length)if(t[i].priority<r[n].priority){e.push(t[i]);i++}else{e.push(r[n]);n++}y(e,t,i);y(e,r,n);return e}function g(t,r,i){var n=t.get(r);if(!n){n=i();t.set(r,n)}return n}var E=function t(r){return r};function A(t,r){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!r.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!r.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}var $=function(){function t(t,r,i){if(void 0===i)i=0;this.t=void 0;this.i=void 0;A(t,r);this.action=r.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.fields=t.fields?s(t.fields):void 0;this.priority=i;this.o=r}var r=t.prototype;r.u=function t(){if(this.conditions&&!this.t)this.t=this.o.conditionsMatcher(this.conditions);return this.t};r.matchesConditions=function t(r){if(!this.conditions)return true;if(!r||c(r))return!this.inverted;var i=this.u();return i(r)};r.matchesField=function t(r){if(!this.fields)return true;if(!r)return!this.inverted;if(this.fields&&!this.i)this.i=this.o.fieldMatcher(this.fields);return this.i(r)};n(t,[{key:"ast",get:function t(){var r=this.u();return r?r.ast:void 0}}]);return t}();var m=function t(r,i){var n={value:r,prev:i,next:null};if(i)i.next=n;return n};var j=function t(r){if(r.next)r.next.prev=r.prev;if(r.prev)r.prev.next=r.next;r.next=r.prev=null};var M=function t(){return{rules:[],merged:false}};var x=function t(){return new Map};var F=function t(r,i){if(!r.h&&i.fields)r.h=true};var O=function(){function t(t,r){if(void 0===t)t=[];if(void 0===r)r={};this.h=false;this.v=new Map;this.l={conditionsMatcher:r.conditionsMatcher,fieldMatcher:r.fieldMatcher,resolveAction:r.resolveAction||E};this.p=r.detectSubjectType||l;this.g=t;this.A=this.$(t)}var r=t.prototype;r.detectSubjectType=function t(r){return c(r)?r:this.p(r)};r.update=function t(r){var i={rules:r,ability:this,target:this};this.m("update",i);this.g=r;this.A=this.$(r);this.m("updated",i);return this};r.$=function t(r){var i=new Map;for(var n=r.length-1;n>=0;n--){var e=r.length-n-1;var o=new $(r[n],this.l,e);var u=s(o.action);var f=s(o.subject||"all");F(this,o);for(var a=0;a<f.length;a++){var c=g(i,f[a],x);for(var h=0;h<u.length;h++)g(c,u[h],M).rules.push(o)}}return i};r.possibleRulesFor=function t(r,i){if(void 0===i)i="all";if(!c(i))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');var n=g(this.A,i,x);var e=g(n,r,M);if(e.merged)return e.rules;var o="manage"!==r&&n.has("manage")?n.get("manage").rules:void 0;var u=w(e.rules,o);if("all"!==i)u=w(u,this.possibleRulesFor(r,"all"));e.rules=u;e.merged=true;return u};r.rulesFor=function t(r,i,n){var e=this.possibleRulesFor(r,i);if(n&&"string"!==typeof n)throw new Error("The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details");if(!this.h)return e;return e.filter((function(t){return t.matchesField(n)}))};r.on=function t(r,i){var n=this;var e=this.v.get(r)||null;var o=m(i,e);this.v.set(r,o);return function(){if(!o.next&&!o.prev&&n.v.get(r)===o)n.v.delete(r);else j(o)}};r.m=function t(r,i){var n=this.v.get(r)||null;while(null!==n){var e=n.prev;n.value(i);n=e}};n(t,[{key:"rules",get:function t(){return this.g}}]);return t}();var _=function(t){o(PureAbility,t);function PureAbility(){return t.apply(this,arguments)||this}var r=PureAbility.prototype;r.can=function t(){var r=this.relevantRuleFor.apply(this,arguments);return!!r&&!r.inverted};r.relevantRuleFor=function t(r,i,n){var e=this.detectSubjectType(i);var o=this.rulesFor(r,e,n);for(var u=0,s=o.length;u<s;u++)if(o[u].matchesConditions(i))return o[u];return null};r.cannot=function t(){return!this.can.apply(this,arguments)};return PureAbility}(O);var T={$eq:r.$eq,$ne:r.$ne,$lt:r.$lt,$lte:r.$lte,$gt:r.$gt,$gte:r.$gte,$in:r.$in,$nin:r.$nin,$all:r.$all,$size:r.$size,$regex:r.$regex,$options:r.$options,$elemMatch:r.$elemMatch,$exists:r.$exists};var P={eq:r.eq,ne:r.ne,lt:r.lt,lte:r.lte,gt:r.gt,gte:r.gte,in:r.within,nin:r.nin,all:r.all,size:r.size,regex:r.regex,elemMatch:r.elemMatch,exists:r.exists,and:r.and};var R=function t(i,n,o){return r.createFactory(e({},T,i),e({},P,n),o)};var q=r.createFactory(T,P);var B=/[-/\\^$+?.()|[\]{}]/g;var k=/\.?\*+\.?/g;var z=/\*+/;var C=/\./g;function S(t,r,i){var n="*"===i[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";var e=-1===t.indexOf("**")?"[^.]":".";var o=t.replace(C,"\\$&").replace(z,e+n);return r+t.length===i.length?"(?:"+o+")?":o}function Y(t,r,i){if("."===t&&("*"===i[r-1]||"*"===i[r+1]))return t;return"\\"+t}function L(t){var r=t.map((function(t){return t.replace(B,Y).replace(k,S)}));var i=r.length>1?"(?:"+r.join("|")+")":r[0];return new RegExp("^"+i+"$")}var D=function t(r){var i;return function(t){if("undefined"===typeof i)i=r.every((function(t){return-1===t.indexOf("*")}))?null:L(r);return null===i?-1!==r.indexOf(t):i.test(t)}};var G=function(t){o(Ability,t);function Ability(r,i){if(void 0===r)r=[];if(void 0===i)i={};return t.call(this,r,e({conditionsMatcher:q,fieldMatcher:D},i))||this}return Ability}(_);var H=function(){function t(t){this.j=t}var r=t.prototype;r.because=function t(r){this.j.reason=r;return this};return t}();var I=function(){function AbilityBuilder(t){this.rules=[];this.M=t;this.can=this.can.bind(this);this.cannot=this.cannot.bind(this);this.build=this.build.bind(this)}var t=AbilityBuilder.prototype;t.can=function t(r,i,n,e){var o={action:r};if(i){o.subject=i;if(Array.isArray(n)||"string"===typeof n)o.fields=n;else if("undefined"!==typeof n)o.conditions=n;if("undefined"!==typeof e)o.conditions=e}this.rules.push(o);return new H(o)};t.cannot=function t(r,i,n,e){var o=this.can(r,i,n,e);o.j.inverted=true;return o};t.build=function t(r){return new this.M(this.rules,r)};return AbilityBuilder}();function defineAbility(t,r){var i=new I(G);var n=t(i.can,i.cannot);if(n&&"function"===typeof n.then)return n.then((function(){return i.build(r)}));return i.build(r)}var J=function t(r){return'Cannot execute "'+r.action+'" on "'+r.subjectType+'"'};var K=function t(r){this.message=r};K.prototype=Object.create(Error.prototype);var N=function(t){o(ForbiddenError,t);ForbiddenError.setDefaultMessage=function t(r){this.F="string"===typeof r?function(){return r}:r};ForbiddenError.from=function t(r){return new this(r)};function ForbiddenError(r){var i;i=t.call(this,"")||this;i.field=void 0;i.ability=r;if("function"===typeof Error.captureStackTrace){i.name="ForbiddenError";Error.captureStackTrace(u(i),i.constructor)}return i}var r=ForbiddenError.prototype;r.setMessage=function t(r){this.message=r;return this};r.throwUnlessCan=function t(){var r;var i=(r=this.ability).relevantRuleFor.apply(r,arguments);if(i&&!i.inverted)return;this.action=arguments.length<=0?void 0:arguments[0];this.subject=arguments.length<=1?void 0:arguments[1];this.subjectType=v(this.ability.detectSubjectType(arguments.length<=1?void 0:arguments[1]));this.field=arguments.length<=2?void 0:arguments[2];var n=i?i.reason:"";this.message=this.message||n||this.constructor.F(this);throw this};return ForbiddenError}(K);N.F=J;t.Ability=G;t.AbilityBuilder=I;t.ForbiddenError=N;t.PureAbility=_;t.buildMongoQueryMatcher=R;t.createAliasResolver=p;t.defineAbility=defineAbility;t.detectSubjectType=l;t.fieldPatternMatcher=D;t.getDefaultErrorMessage=J;t.mongoQueryMatcher=q;t.subject=a;t.wrapArray=s;Object.defineProperty(t,"__esModule",{value:true})}));
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","matchesConditions","this","_lazyMatchConditions","matchesField","field","_lazyMatchField","ast","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","_this","delete","payload","current","PureAbility","can","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","_PureAbility","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}
{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private _conditionsMatcher() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions!;\n }\n\n get ast() {\n const matches = this._conditionsMatcher();\n return matches ? matches.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n const matches = this._conditionsMatcher();\n return matches(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public, RawRuleOf } from './RuleIndex';\nimport { Abilities, AbilityTuple, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (\n rules: RawRuleOf<T>[],\n options: AbilityOptionsOf<T>\n) => T;\n\nexport class PureAbility<\n A extends Abilities = AbilityTuple,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n AnyObject,\n AnyClass,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends AnyClass<infer R>\n ? R\n : S extends string\n ? Exclude<Normalize<Generics<T>['abilities']>[1], SubjectType> extends { kind: string }\n ? Extract<Normalize<Generics<T>['abilities']>[1], TaggedInterface<S>>\n : AnyObject\n : never;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<T extends AnyAbility> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: AnyClass<T>;\n\n constructor(AbilityType: AnyClass<T>) {\n this._AbilityType = AbilityType;\n this.can = this.can.bind(this as any);\n this.cannot = this.cannot.bind(this as any);\n this.build = this.build.bind(this as any);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options);\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<T>['can'],\n cannot: AbilityBuilder<T>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<U extends AnyAbility>(ability: U) {\n return new this<U>(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","matchesConditions","matches","matchesField","field","ast","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","_this","delete","payload","current","PureAbility","can","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","_PureAbility","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}
{
"name": "@casl/ability",
"version": "5.1.0-next.11",
"version": "5.1.0-next.12",
"description": "CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access",

@@ -33,7 +33,7 @@ "funding": "https://github.com/stalniy/casl/blob/master/BACKERS.md",

"build.extra": "rollup -c ../../rollup.config.js -i src/extra.ts -n casl.extra -g @ucast/mongo2js:ucast.mongo2js",
"build.types": "rm -rf dist/types/* && tsc && cp index.metadata.json dist/types",
"build.types": "rm -rf dist/types/* && tsc -p tsconfig.build.json && cp index.metadata.json dist/types",
"build": "npm run build.types && npm run build.core && npm run build.extra",
"lint": "eslint --ext .js,.ts src/ spec/",
"test": "NODE_ENV=test jest --config ../../tools/jest.config.js --env node",
"prerelease": "npm run lint && npm test && NODE_ENV=production npm run build",
"prerelease2": "npm run lint && npm test && NODE_ENV=production npm run build",
"release": "semantic-release -e ../../tools/semantic-release"

@@ -52,3 +52,3 @@ },

],
"author": "Sergii Stotskyi <sergiy.stotskiy@freaksidea.com>",
"author": "Sergii Stotskyi <sergiy.stotskiy@gmail.com>",
"license": "MIT",

@@ -70,5 +70,5 @@ "engines": {

"@semantic-release/npm": "^7.0.5",
"@types/jest": "^26.0.15",
"@types/node": "^14.0.5",
"@typescript-eslint/eslint-plugin": "3.10.1",
"babel-jest": "^26.0.0",
"@typescript-eslint/eslint-plugin": "4.5.0",
"chai": "^4.1.0",

@@ -78,4 +78,5 @@ "chai-spies": "^1.0.0",

"eslint-config-airbnb-base": "^14.1.0",
"eslint-config-airbnb-typescript": "^9.0.0",
"eslint-config-airbnb-typescript": "^12.0.0",
"eslint-plugin-import": "^2.20.2",
"expect-type": "^0.9.0",
"jest": "^26.0.0",

@@ -85,4 +86,5 @@ "rollup": "^2.10.9",

"rollup-plugin-terser": "^7.0.0",
"semantic-release": "17.1.1",
"typescript": "~3.8.0"
"semantic-release": "^17.1.1",
"ts-jest": "^26.4.4",
"typescript": "~4.0.3"
},

@@ -89,0 +91,0 @@ "files": [