{"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, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray(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\n>(type: T, object: U): U & ForcedSubject {\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;\n}\n\nexport function detectSubjectType(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 = (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\nfunction copyArrayTo(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(\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(map: Map, 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","import { wrapArray } 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 = Normalize>;\n\nfunction validate(rule: RawRuleFrom, options: RuleOptions) {\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 = (action: T | T[]) => T | T[];\nexport interface RuleOptions {\n conditionsMatcher?: ConditionsMatcher\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction[0]>\n}\n\nexport class Rule {\n private __matchConditions: MatchConditions | undefined;\n private __matchField: MatchField | undefined;\n private readonly _options!: RuleOptions;\n public readonly action!: Tuple[0] | Tuple[0][];\n public readonly subject!: Tuple[1] | Tuple[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, C>,\n options: RuleOptions,\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 _matchConditions() {\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 _matchField() {\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._matchConditions ? this._matchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize[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","export class LinkedItem {\n public next: LinkedItem | null = null;\n\n constructor(\n public readonly value: T,\n public prev: LinkedItem | null = null\n ) {\n if (prev) {\n prev.next = this;\n }\n }\n\n destroy() {\n const { next, prev } = this;\n\n if (next) {\n next.prev = prev;\n }\n\n if (prev) {\n prev.next = next;\n }\n\n this.next = this.prev = null; // eslint-disable-line\n }\n}\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport { CanParameters, Abilities, Normalize, Subject, SubjectType } from './types';\nimport { wrapArray, detectSubjectType, identity, mergePrioritized, getOrDefault } from './utils';\nimport { LinkedItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions extends Partial> {\n detectSubjectType?(subject?: Normalize[1]): 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 = { [K in keyof T]: T[K] };\nexport type Generics = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf =\n Rule['abilities'], Generics['conditions']>;\nexport type RawRuleOf =\n RawRuleFrom['abilities'], Generics['conditions']>;\n\nexport type RuleIndexOptionsOf =\n RuleIndexOptions['abilities'], Generics['conditions']>;\n\nexport interface UpdateEvent {\n rules: RawRuleOf[]\n}\nexport type EventHandler = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n Event extends {} = {},\n K extends keyof EventsMap = keyof EventsMap\n> = Map[K]>> | null,\n destroy: Array | null,\n emits: boolean\n}>;\n\ninterface EventsMap {\n update: UpdateEvent & Event\n updated: UpdateEvent & Event\n}\n\ntype IndexTree = Map[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map>();\nconst defaultEventEntry = () => ({ emits: false, last: null, destroy: null });\n\nexport class RuleIndex {\n private _hasPerFieldRules: boolean = false;\n private _events: Events = new Map();\n private _indexedRules!: IndexTree;\n private _rules!: RawRuleFrom[];\n private readonly _ruleOptions!: RuleOptions;\n readonly detectSubjectType!: Exclude['detectSubjectType'], undefined>;\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom[] = [],\n options: RuleIndexOptions = {}\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 update(rules: RawRuleFrom[]): Public {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent & BaseEvent;\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[]) {\n const indexedRules: IndexTree = 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);\n this._analyze(rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectType = this.detectSubjectType(subjects[k]);\n const subjectRules = getOrDefault(indexedRules, subjectType, 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 private _analyze(rule: Rule) {\n if (!this._hasPerFieldRules && rule.fields) {\n this._hasPerFieldRules = true;\n }\n }\n\n possibleRulesFor(...[action, subject]: CanParameters) {\n const subjectType = this.detectSubjectType(subject);\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: CanParameters): Rule[]\n rulesFor(action: string, subject?: Subject, field?: string): Rule[] {\n const rules: Rule[] = (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>(\n event: T,\n handler: EventHandler[T]>\n ): Unsubscribe {\n const details = getOrDefault(this._events, event, defaultEventEntry);\n const item = new LinkedItem(handler, details.last);\n details.last = item;\n const destroy = () => {\n if (details.emits) {\n details.destroy = details.destroy || [];\n details.destroy.push(destroy);\n return;\n }\n\n if (!item.next && !item.prev && details.last === item) {\n details.last = null;\n } else {\n item.destroy();\n }\n };\n\n return destroy;\n }\n\n private _emit>(\n name: T,\n payload: EventsMap[T]\n ) {\n const details = this._events.get(name);\n\n if (!details) {\n return;\n }\n\n try {\n details.emits = true;\n let item = details.last;\n while (item !== null) {\n item.value(payload);\n item = item.prev;\n }\n } finally {\n details.emits = false;\n if (details.destroy) {\n details.destroy.forEach(destroy => destroy());\n }\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters } from './types';\n\nexport type AbilityOptions = RuleIndexOptions;\nexport type AnyAbility = Public>;\nexport type AbilityOptionsOf = RuleIndexOptionsOf;\nexport type AbilityClass = new (...args: any[]) => T;\n\ninterface AbilityEvent {\n /** @deprecated use \"target\" property instead */\n ability: this['target']\n target: PureAbility\n}\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex> {\n can(...args: CanParameters): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters) {\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): 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 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};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery\n}\n\ntype MergeUnion = { [K in Keys]: T[K] };\nexport type MongoQuery = BuildMongoQuery, {\n toplevel: {},\n field: Pick>['field'], keyof typeof defaultInstructions>\n}> & Container;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial>) => ConditionsMatcher;\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.join('').indexOf('*') === -1\n ? null\n : createPattern(fields);\n }\n\n if (pattern === null || field.indexOf('*') !== -1) {\n return fields.indexOf(field) !== -1;\n }\n\n return pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\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 = MongoQuery\n> extends PureAbility {\n constructor(rules?: RawRuleFrom[], options?: AbilityOptions) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public>;\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 {\n public _rule!: RawRuleOf;\n\n constructor(rule: RawRuleOf) {\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 extends U ? T : D;\ntype InstanceOf = S extends SubjectClass\n ? InstanceType\n : ExtractWithDefault['abilities']>[1], TaggedInterface>, AnyObject>;\ntype ConditionsOf =\n ProduceGeneric['conditions'], I>;\ntype ActionFrom = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf = ActionFrom['abilities'], S>;\ntype SubjectTypeOf = E['abilities']>[1]>;\n\ntype SimpleCanParams = Parameters<(\n action: Generics['abilities'] | Generics['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf,\n T extends AnyAbility\n> = Generics['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf | ActionOf[],\n subject: S | S[],\n conditions?: ConditionsOf\n ) => 0>\n : SimpleCanParams;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf,\n F extends string,\n T extends AnyAbility\n> = Generics['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf | ActionOf[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf\n ) => 0>\n : SimpleCanParams;\ntype Keys = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass,\n T extends InstanceType = InstanceType\n> {\n public rules: RawRuleOf[] = [];\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,\n S extends SubjectTypeOf = SubjectTypeOf\n >(...args: BuilderCanParameters): RuleBuilder\n can<\n I extends InstanceOf,\n F extends string = Keys,\n S extends SubjectTypeOf = SubjectTypeOf\n >(...args: BuilderCanParametersWithFields, T>): RuleBuilder\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics['conditions'],\n conditions?: Generics['conditions']\n ): RuleBuilder {\n const rule = { action } as RawRuleOf;\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,\n S extends SubjectTypeOf = SubjectTypeOf\n >(...args: BuilderCanParameters): RuleBuilder\n cannot<\n I extends InstanceOf,\n F extends string = Keys,\n S extends SubjectTypeOf = SubjectTypeOf\n >(...args: BuilderCanParametersWithFields, T>): RuleBuilder\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics['conditions'],\n conditions?: Generics['conditions'],\n ): RuleBuilder {\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) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL = (\n can: AbilityBuilder>['can'],\n cannot: AbilityBuilder>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL>, options?: AbilityOptionsOf): Promise;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL, options?: AbilityOptionsOf): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL>, options?: AbilityOptionsOf): T | Promise {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass);\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';\n\nexport type GetErrorMessage = (error: ForbiddenError) => 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 extends NativeError {\n public readonly ability!: T;\n public action!: Normalize['abilities']>[0];\n public subject!: Generics['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(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) {\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","Error","Object","defineProperty","detectSubjectType","subject","Type","constructor","modelName","name","identity","x","createAliasResolver","aliasMap","process","env","NODE_ENV","manage","keys","forEach","alias","indexOf","assertAliasMap","action","rawActions","actions","i","length","concat","expandActions","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","Rule","rule","options","__matchConditions","__matchField","fields","fieldMatcher","conditions","conditionsMatcher","validate","resolveAction","inverted","reason","undefined","_options","this","_matchConditions","ast","matchesConditions","matchesField","field","_matchField","LinkedItem","prev","next","destroy","defaultActionEntry","rules","defaultSubjectEntry","Map","defaultEventEntry","emits","last","PureAbility","_hasPerFieldRules","_events","_ruleOptions","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","_analyze","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","details","item","payload","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","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","index","string","quantifier","matcher","pattern","replace","escapeRegexp","fieldPatternMatcher","join","patterns","RegExp","createPattern","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}