{"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(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 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): string {\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\ntype AliasMerge = (actions: string[], action: string | string[]) => string[];\nfunction expandActions(aliasMap: AliasesMap, rawActions: string | string[], merge: AliasMerge) {\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 = merge(actions, aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction findDuplicate(actions: string[], actionToFind: string | string[]) {\n if (typeof actionToFind === 'string' && actions.indexOf(actionToFind) !== -1) {\n return actionToFind;\n }\n\n for (let i = 0; i < actionToFind.length; i++) {\n if (actions.indexOf(actionToFind[i]) !== -1) return actionToFind[i];\n }\n\n return null;\n}\n\nconst defaultAliasMerge: AliasMerge = (actions, action) => actions.concat(action);\nfunction validateForCycles(aliasMap: AliasesMap, reservedAction: string) {\n if (reservedAction in aliasMap) {\n throw new Error(`Cannot use \"${reservedAction}\" as an alias because it's reserved action.`);\n }\n\n const keys = Object.keys(aliasMap);\n const mergeAliasesAndDetectCycles: AliasMerge = (actions, action) => {\n const duplicate = findDuplicate(actions, action);\n if (duplicate) throw new Error(`Detected cycle ${duplicate} -> ${actions.join(', ')}`);\n\n const isUsingReservedAction = typeof action === 'string' && action === reservedAction\n || actions.indexOf(reservedAction) !== -1\n || Array.isArray(action) && action.indexOf(reservedAction) !== -1;\n if (isUsingReservedAction) throw new Error(`Cannot make an alias to \"${reservedAction}\" because this is reserved action`);\n\n return actions.concat(action);\n };\n\n for (let i = 0; i < keys.length; i++) {\n expandActions(aliasMap, keys[i], mergeAliasesAndDetectCycles);\n }\n}\n\nexport type AliasResolverOptions = { skipValidate?: boolean; anyAction?: string };\nexport function createAliasResolver(aliasMap: AliasesMap, options?: AliasResolverOptions) {\n if (!options || options.skipValidate !== false) {\n validateForCycles(aliasMap, options && options.anyAction || 'manage');\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action, defaultAliasMerge);\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\nexport const identity = (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 = 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\nexport interface RuleOptions {\n conditionsMatcher?: ConditionsMatcher\n fieldMatcher?: FieldMatcher\n resolveAction(action: string | string[]): string | string[]\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 _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[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 Record);\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 {\n next: LinkedItem | null\n prev: LinkedItem | null\n readonly value: T\n}\n\nexport function linkedItem(value: T, prev: LinkedItem['prev']) {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n}\n\nexport function unlinkItem(item: LinkedItem) {\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\nexport const cloneLinkedItem = >(item: T): T => ({\n value: item.value,\n prev: item.prev,\n next: item.next,\n} as T);\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, cloneLinkedItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions extends Partial> {\n detectSubjectType?(\n subject: Exclude[1], SubjectType>\n ): ExtractSubjectType[1]>;\n anyAction?: string;\n anySubjectType?: 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 interface 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\ninterface AbilityEvent {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent extends AbilityEvent {\n rules: RawRuleOf[]\n}\n/**\n * @deprecated `on`/`emit` properly infer type without this type\n * TODO(major): delete\n */\nexport type EventHandler = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap = keyof EventsMap\n> = Map[K]> | null>;\n\ninterface EventsMap {\n update(event: UpdateEvent): void\n updated(event: UpdateEvent): void\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 analyze = (index: any, rule: Rule) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType) => 0\n : never,\n (action: Extract) => 0\n >;\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 private readonly _detectSubjectType!: Required>['detectSubjectType'];\n private readonly _anyAction: string;\n private readonly _anySubjectType: string;\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._anyAction = options.anyAction || 'manage';\n this._anySubjectType = options.anySubjectType || 'all';\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[1]): ExtractSubjectType[1]> {\n if (isSubjectType(object)) return object;\n if (!object) return this._anySubjectType;\n return this._detectSubjectType(object as Exclude[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom[]): Public {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent;\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 || this._anySubjectType);\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): Rule[]\n possibleRulesFor(\n action: string,\n subjectType: SubjectType = this._anySubjectType\n ): Rule[] {\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 anyActionRules = action !== this._anyAction && subjectRules.has(this._anyAction)\n ? subjectRules.get(this._anyAction)!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, anyActionRules);\n\n if (subjectType !== this._anySubjectType) {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, this._anySubjectType));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters): Rule[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule[] {\n const rules: Rule[] = (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>(\n event: T,\n handler: EventsMap>[T]\n ): Unsubscribe {\n const tail = this._events.get(event) || null;\n const item = linkedItem(handler, tail);\n this._events.set(event, item);\n\n return () => {\n const currentTail = this._events.get(event);\n\n if (!item.next && !item.prev && currentTail === item) {\n this._events.delete(event);\n } else if (item === currentTail) {\n this._events.set(event, item.prev);\n }\n\n unlinkItem(item);\n };\n }\n\n private _emit>(\n name: T,\n payload: Parameters[T]>[0]\n ) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev ? cloneLinkedItem(current.prev) : null;\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 interface AbilityOptions\n extends RuleIndexOptions {}\nexport interface AnyAbility extends Public> {}\nexport interface AbilityOptionsOf extends RuleIndexOptionsOf {}\nexport type AbilityClass = new (\n rules?: RawRuleOf[],\n options?: AbilityOptionsOf\n) => T;\n\nexport class PureAbility<\n A extends Abilities = AbilityTuple,\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): Rule | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule | 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): 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\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.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 { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\nimport { Public } from './RuleIndex';\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 interface AnyMongoAbility extends 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 AnyObject,\n AnyClass,\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 InstanceOf = S extends AnyClass\n ? R\n : S extends string\n ? Exclude['abilities']>[1], SubjectType> extends TaggedInterface\n ? Extract['abilities']>[1], TaggedInterface>\n : AnyObject\n : never;\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 public rules: RawRuleOf[] = [];\n private _AbilityType!: AnyClass;\n\n constructor(AbilityType: AnyClass) {\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,\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);\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';\nimport { getSubjectTypeName } from './utils';\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: U) {\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 = 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","merge","actions","i","length","action","findDuplicate","actionToFind","indexOf","defaultAliasMerge","concat","validateForCycles","reservedAction","keys","mergeAliasesAndDetectCycles","duplicate","join","isUsingReservedAction","createAliasResolver","options","skipValidate","anyAction","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","fields","fieldMatcher","conditions","conditionsMatcher","Rule","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matches","ast","matchesConditions","matchesField","field","_matchField","linkedItem","prev","item","next","unlinkItem","cloneLinkedItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_anyAction","_anySubjectType","anySubjectType","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","anyActionRules","has","rulesFor","filter","on","handler","tail","currentTail","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","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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"}