{"version":3,"file":"index.mjs","names":[],"sources":["../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/Ability.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/createMongoAbility.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { wrapArray, isSubjectType } from './utils';\nimport {\n  MatchConditions,\n  MatchField,\n  Abilities,\n  ToAbilityTypes,\n  Normalize,\n  ConditionsMatcher,\n  FieldMatcher,\n} from './types';\nimport type { RawRule, RawRuleFrom } from './RawRule';\nimport type { Condition } from '@ucast/mongo2js';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate(rule: RawRuleFrom<Abilities, any>, options: RuleOptions<any>) {\n  if (Array.isArray(rule.fields) && !rule.fields.length) {\n    throw new Error('The `rawRule.fields` array cannot be empty. https://bit.ly/390miLa');\n  }\n\n  if (rule.fields && !options.fieldMatcher) {\n    throw new Error('Cannot restrict access by fields without a \"fieldMatcher\" option');\n  }\n\n  if (rule.conditions && !options.conditionsMatcher) {\n    throw new Error('Cannot restrict access by conditions without a \"conditionsMatcher\" option.' +\n      ' Please, provide a \"conditionsMatcher\" function to your Ability class or use \"createMongoAbility\" instead.');\n  }\n}\n\nexport interface RuleOptions<Conditions> {\n  conditionsMatcher?: ConditionsMatcher<Conditions>\n  fieldMatcher?: FieldMatcher\n  resolveAction(action: string | string[]): string | string[]\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<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 origin!: RawRule<ToAbilityTypes<A>, C>;\n  public readonly priority!: number;\n\n  constructor(\n    rule: RawRule<ToAbilityTypes<A>, C>,\n    options: RuleOptions<C>,\n    priority = 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.origin = rule;\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      if (!this.inverted) return true;\n      const matches = this._conditionsMatcher();\n      if (!matches) return false;\n      return matches.matchesAll === true || !!matches.ast && isMatchesAll(matches.ast);\n    }\n\n    const matches = this._conditionsMatcher();\n    return matches ? matches(object as Record<string, unknown>) : false;\n  }\n\n  matchesField(field: string | undefined): boolean {\n    if (!this.fields) {\n      return true;\n    }\n\n    if (!field) {\n      // if there is no field (i.e., checking whether user has access to at least one field on subject)\n      // we ignore inverted rules because they disallow to do an action on it, so we are continue looking for regular rule\n      return !this.inverted;\n    }\n\n    if (!this._matchField) {\n      this._matchField = this._options.fieldMatcher!(this.fields);\n    }\n\n    return this._matchField ? this._matchField(field) : false;\n  }\n}\n\nfunction isMatchesAll(ast: Condition): boolean {\n  return (ast.operator === 'and' || ast.operator === 'AND') &&\n    Array.isArray(ast.value) &&\n    ast.value.length === 0;\n}\n","export interface LinkedItem<T> {\n  next: LinkedItem<T> | null\n  prev: LinkedItem<T> | null\n  readonly value: T\n}\n\nexport function 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 function 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;\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, DETECT_SUBJECT_TYPE_STRATEGY, filterWithLazyAllocation } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<C>> {\n  detectSubjectType?(\n    subject: Exclude<Normalize<A>[1], SubjectType>\n  ): ExtractSubjectType<Normalize<A>[1]>;\n  anyAction?: string;\n  anySubjectType?: string;\n}\n\nexport declare const ɵabilities: unique symbol;\nexport declare 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 interface 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}\n/**\n * @deprecated `on`/`emit` properly infer type without this type\n * TODO(major): delete\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<EventsMap<T>[K]> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n  update(event: UpdateEvent<T>): void\n  updated(event: UpdateEvent<T>): void\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>>();\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 = false;\n  private _events?: Events<this>;\n  private _indexedRules: IndexTree<A, Conditions> = new Map();\n  private _rules: RawRuleFrom<A, Conditions>[];\n  private readonly _ruleOptions: RuleOptions<Conditions>;\n  private _detectSubjectType: this['detectSubjectType'];\n  private readonly _anyAction: string;\n  private readonly _anySubjectType: string;\n  private readonly _hasCustomSubjectTypeDetection: boolean;\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._anyAction = options.anyAction || 'manage';\n    this._anySubjectType = options.anySubjectType || 'all';\n    this._rules = rules;\n    this._hasCustomSubjectTypeDetection = !!options.detectSubjectType;\n    this._detectSubjectType = options.detectSubjectType || (detectSubjectType as this['detectSubjectType']);\n    this._indexAndAnalyzeRules(rules);\n  }\n\n  get rules() {\n    return this._rules;\n  }\n\n  detectSubjectType(object?: Normalize<A>[1]): ExtractSubjectType<Normalize<A>[1]> {\n    if (isSubjectType(object)) return object as ExtractSubjectType<Normalize<A>[1]>;\n    if (!object) return this._anySubjectType as ExtractSubjectType<Normalize<A>[1]>;\n    return 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._hasPerFieldRules = false;\n    this._rules = rules;\n    this._indexAndAnalyzeRules(rules);\n    this._emit('updated', event);\n\n    return this;\n  }\n\n  private _indexAndAnalyzeRules(rawRules: RawRuleFrom<A, Conditions>[]) {\n    const indexedRules: IndexTree<A, Conditions> = new Map();\n    let typeOfSubjectType: string | undefined;\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      if (!this._hasPerFieldRules && rule.fields) this._hasPerFieldRules = true;\n\n      for (let k = 0; k < subjects.length; k++) {\n        const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n        if (typeOfSubjectType === undefined) {\n          typeOfSubjectType = typeof subjects[k];\n        }\n        if (typeof subjects[k] !== typeOfSubjectType && typeOfSubjectType !== 'mixed') {\n          typeOfSubjectType = 'mixed';\n        }\n\n        for (let j = 0; j < actions.length; j++) {\n          getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n        }\n      }\n    }\n\n    this._indexedRules = indexedRules;\n    if (typeOfSubjectType !== 'mixed' && !this._hasCustomSubjectTypeDetection) {\n      const detectSubjectType = DETECT_SUBJECT_TYPE_STRATEGY[typeOfSubjectType as 'function' | 'string'] || DETECT_SUBJECT_TYPE_STRATEGY.string;\n      this._detectSubjectType = detectSubjectType as this['detectSubjectType'];\n    }\n  }\n\n  possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): readonly Rule<A, Conditions>[];\n  possibleRulesFor(\n    action: string,\n    subjectType: SubjectType = this._anySubjectType\n  ): readonly 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 = this._indexedRules.get(subjectType);\n    const actionRules = subjectRules?.get(action);\n\n    if (actionRules?.merged) {\n      return actionRules.rules;\n    }\n\n    const anyActionRules = action !== this._anyAction && !!subjectRules?.has(this._anyAction)\n      ? Object.freeze(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    if (actionRules) {\n      actionRules.rules = Object.freeze(rules) as Rule<A, Conditions>[];\n      actionRules.merged = true;\n    }\n\n    return rules;\n  }\n\n  rulesFor(...args: AbilitySubjectTypeParameters<A>): readonly Rule<A, Conditions>[];\n  rulesFor(\n    action: string,\n    subjectType?: SubjectType,\n    field?: string\n  ): readonly 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://casl.js.org/v6/en/api/casl-ability#can-of-ability for details');\n    }\n\n    if (!this._hasPerFieldRules) {\n      return rules;\n    }\n\n    return filterWithLazyAllocation(rules, rule => rule.matchesField(field));\n  }\n\n  actionsFor(subjectType: ExtractSubjectType<Normalize<A>[1]>): string[] {\n    if (!isSubjectType(subjectType)) {\n      throw new Error('\"actionsFor\" accepts only subject types (i.e., string or class) as a parameter');\n    }\n\n    const actions = new Set<string>();\n\n    const subjectRules = this._indexedRules.get(subjectType);\n    if (subjectRules) {\n      Array.from(subjectRules.keys()).forEach(action => actions.add(action));\n    }\n\n    const anySubjectTypeRules = subjectType !== this._anySubjectType\n      ? this._indexedRules.get(this._anySubjectType)\n      : undefined;\n    if (anySubjectTypeRules) {\n      Array.from(anySubjectTypeRules.keys()).forEach(action => actions.add(action));\n    }\n\n    return Array.from(actions);\n  }\n\n  on<T extends keyof EventsMap<this>>(\n    event: T,\n    handler: EventsMap<Public<this>>[T]\n  ): Unsubscribe {\n    this._events = this._events || new Map();\n    const events = this._events;\n    const tail = events.get(event) || null;\n    const item = linkedItem(handler, tail);\n    events.set(event, item);\n\n    return () => {\n      const currentTail = events.get(event);\n\n      if (!item.next && !item.prev && currentTail === item) {\n        events.delete(event);\n      } else if (item === currentTail) {\n        events.set(event, item.prev);\n      }\n\n      unlinkItem(item);\n    };\n  }\n\n  private _emit<T extends keyof EventsMap<this>>(\n    name: T,\n    payload: Parameters<EventsMap<this>[T]>[0]\n  ) {\n    if (!this._events) return;\n\n    let current = this._events.get(name) || null;\n    const handlers: ((payload: Parameters<EventsMap<this>[T]>[0]) => void)[] = [];\n\n    // We collect handlers in an array first to avoid issues if a handler\n    // unsubscribes itself (or others) during emission, which would mutate the linked list.\n    // Using an array here is faster than cloning linked list nodes.\n    while (current !== null) {\n      handlers.push(current.value);\n      current = current.prev;\n    }\n\n    for (let i = 0; i < handlers.length; i++) {\n      handlers[i](payload);\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<A extends Abilities, Conditions>\n  extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility extends Public<Ability<any, any>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends RuleIndexOptionsOf<T> {}\n\nexport type AbilityClass<T extends AnyAbility> = new (\n  rules?: RawRuleOf<T>[],\n  options?: AbilityOptionsOf<T>\n) => T;\n\nexport type CreateAbility<T extends AnyAbility> = (\n  rules?: RawRuleOf<T>[],\n  options?: AbilityOptionsOf<T>\n) => T;\n\nexport class Ability<\n  A extends Abilities = AbilityTuple,\n  Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n  can(...args: CanParameters<A>): boolean;\n  can(action: string, subject?: Subject, field?: string): boolean {\n    const rule = (this as PrimitiveAbility).relevantRuleFor(action, subject, field);\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  cannot(action: string, subject?: Subject, field?: string): boolean {\n    return !(this as PrimitiveAbility).can(action, subject, field);\n  }\n}\n\n/**\n * helper interface that helps to emit js methods that have static parameters\n */\ninterface PrimitiveAbility<A extends Abilities = AbilityTuple, Conditions = unknown> {\n  can(action: string, subject?: Subject, field?: string): boolean;\n  relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null\n}\n","import {\n  $all,\n  $elemMatch,\n  $eq,\n  $exists,\n  $gt,\n  $gte,\n  $in,\n  $lt,\n  $lte,\n  $ne,\n  $nin,\n  $options,\n  $regex,\n  $size,\n  all,\n  and,\n  BuildMongoQuery,\n  createFactory,\n  DefaultOperators,\n  elemMatch,\n  eq,\n  exists,\n  gt,\n  gte,\n  lt,\n  lte,\n  ne,\n  nin,\n  regex,\n  size,\n  within\n} from '@ucast/mongo2js';\nimport { Container, GenericFactory } from '../hkt';\nimport { AnyObject, ConditionsMatcher } from '../types';\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, 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, MongoQueryOperators, MongoQueryTopLevelOperators\n} from '@ucast/mongo2js';\n\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 { Ability, AbilityOptions, AbilityOptionsOf } from './Ability';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\nimport { Public, RawRuleOf } from './RuleIndex';\n\nexport interface AnyMongoAbility extends Public<Ability<any, MongoQuery>> {}\nexport interface MongoAbility<\n  A extends AbilityTuple = AbilityTuple,\n  C extends MongoQuery = MongoQuery\n> extends Ability<A, C> {}\n\n/**\n * Creates Ability with MongoDB conditions matcher\n */\nexport function createMongoAbility<\n  T extends AnyMongoAbility = MongoAbility\n>(rules?: RawRuleOf<T>[], options?: AbilityOptionsOf<T>): T;\nexport function createMongoAbility<\n  A extends AbilityTuple = AbilityTuple,\n  C extends MongoQuery = MongoQuery\n>(rules?: RawRuleFrom<A, C>[], options?: AbilityOptions<A, C>): MongoAbility<A, C>;\nexport function createMongoAbility(rules: any[] = [], options = {}): AnyMongoAbility {\n  return new Ability(rules, {\n    conditionsMatcher: mongoQueryMatcher,\n    fieldMatcher: fieldPatternMatcher,\n    ...options,\n  });\n}\n","import { type AnyMongoAbility, createMongoAbility, type MongoAbility } from './createMongoAbility';\nimport type { ProduceGeneric } from './hkt';\nimport type { AbilityOptionsOf, AnyAbility } from './Ability';\nimport type { Generics, RawRuleOf } from './RuleIndex';\nimport type {\n  AbilityTuple, AnyClass, AnyObject, ExtractSubjectType as E, Normalize, SubjectType,\n  TaggedInterface\n} from './types';\n\nfunction isAbilityClass(factory: AbilityFactory<any>): factory is AnyClass {\n  return factory.prototype !== undefined && typeof factory.prototype.possibleRulesFor === 'function';\n}\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 AbilityFactory<T extends AnyAbility> = AnyClass<T> | ((rules?: any[], options?: any) => T);\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends AnyClass<infer R>\n  ? R\n  : S extends (...args: any[]) => infer O\n    ? O\n    : S extends string\n      ? Exclude<Normalize<Generics<T>['abilities']>[1], SubjectType> extends TaggedInterface<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 Extract<T[1], SubjectType> ? 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\ntype AddRule<T extends AnyAbility> = {\n  <\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  <\n    I extends InstanceOf<T, S>,\n    S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n  >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>;\n};\n\nexport class AbilityBuilder<T extends AnyAbility> {\n  public rules: RawRuleOf<T>[] = [];\n  private readonly _createAbility: AbilityFactory<T>;\n  public can: AddRule<T>;\n  public cannot: AddRule<T>;\n  public build: (options?: AbilityOptionsOf<T>) => T;\n\n  constructor(AbilityType: AbilityFactory<T>) {\n    this._createAbility = AbilityType;\n\n    this.can = (\n      action: string | string[],\n      subject?: SubjectType | SubjectType[],\n      conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n      conditions?: Generics<T>['conditions']\n    ) => this._addRule(action, subject, conditionsOrFields, conditions, false);\n    this.cannot = (\n      action: string | string[],\n      subject?: SubjectType | SubjectType[],\n      conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n      conditions?: Generics<T>['conditions']\n    ) => this._addRule(action, subject, conditionsOrFields, conditions, true);\n\n    this.build = options => (isAbilityClass(this._createAbility)\n      ? new this._createAbility(this.rules, options)\n      : this._createAbility(this.rules, options));\n  }\n\n  private _addRule(\n    action: string | string[],\n    subject?: SubjectType | SubjectType[],\n    conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n    conditions?: Generics<T>['conditions'],\n    inverted?: boolean\n  ): RuleBuilder<T> {\n    const rule = { action } as RawRuleOf<T>;\n\n    if (inverted) rule.inverted = inverted;\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    return new RuleBuilder(rule);\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 = MongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n  T extends AnyMongoAbility = MongoAbility\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<T>(createMongoAbility);\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 type { AnyAbility } from './Ability';\nimport type { Normalize, Subject } from './types';\nimport type { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\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: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`\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): ForbiddenError<U> {\n    return new this<U>(ability);\n  }\n\n  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): this {\n    this.message = message;\n    return this;\n  }\n\n  throwUnlessCan(...args: Parameters<T['can']>): void;\n  throwUnlessCan(action: string, subject?: Subject, field?: string): void {\n    const error = (this as any).unlessCan(action, subject, field);\n    if (error) throw error;\n  }\n\n  unlessCan(...args: Parameters<T['can']>): this | undefined;\n  unlessCan(action: string, subject?: Subject, field?: string): this | undefined {\n    const rule = this.ability.relevantRuleFor(action, subject, field);\n\n    if (rule && !rule.inverted) {\n      return;\n    }\n\n    this.action = action;\n    this.subject = subject;\n    this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(subject));\n    this.field = field;\n\n    const reason = rule ? rule.reason : '';\n    this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n    return this;\n  }\n}\n"],"mappings":"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"}