@casl/ability
Advanced tools
+7
-0
@@ -5,2 +5,9 @@ # Change Log | ||
| ## [5.2.1](https://github.com/stalniy/casl/compare/@casl/ability@5.2.0...@casl/ability@5.2.1) (2021-01-23) | ||
| ### Bug Fixes | ||
| * **ability:** removes generic parameters from `AnyAbility` type ([5566ac8](https://github.com/stalniy/casl/commit/5566ac863aa4cb477d96da1fb83d414fade1e48f)) | ||
| # [5.2.0](https://github.com/stalniy/casl/compare/@casl/ability@5.1.2...@casl/ability@5.2.0) (2021-01-22) | ||
@@ -7,0 +14,0 @@ |
@@ -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 _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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility<A extends Abilities = any, Conditions = any>\n extends Public<PureAbility<A, Conditions>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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, AnyAbility } from './PureAbility';\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 interface AnyMongoAbility extends AnyAbility<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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matchesConditions","matches","matchesField","field","_matchField","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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"} | ||
| {"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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility extends Public<PureAbility<any, any>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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 { 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<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 interface AnyMongoAbility extends 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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matchesConditions","matches","matchesField","field","_matchField","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,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 _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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility<A extends Abilities = any, Conditions = any>\n extends Public<PureAbility<A, Conditions>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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, AnyAbility } from './PureAbility';\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 interface AnyMongoAbility extends AnyAbility<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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matches","ast","matchesConditions","matchesField","field","_matchField","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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"} | ||
| {"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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility extends Public<PureAbility<any, any>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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 { 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<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 interface AnyMongoAbility extends 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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matches","ast","matchesConditions","matchesField","field","_matchField","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,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 _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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility<A extends Abilities = any, Conditions = any>\n extends Public<PureAbility<A, Conditions>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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, AnyAbility } from './PureAbility';\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 interface AnyMongoAbility extends AnyAbility<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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matches","ast","matchesConditions","matchesField","field","_matchField","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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"} | ||
| {"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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility extends Public<PureAbility<any, any>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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 { 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<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 interface AnyMongoAbility extends 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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matches","ast","matchesConditions","matchesField","field","_matchField","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,9 +0,10 @@ | ||
| import { PureAbility, AbilityOptions, AnyAbility } from './PureAbility'; | ||
| import { PureAbility, AbilityOptions } from './PureAbility'; | ||
| import { RawRuleFrom } from './RawRule'; | ||
| import { AbilityTuple } from './types'; | ||
| import { MongoQuery } from './matchers/conditions'; | ||
| import { Public } from './RuleIndex'; | ||
| export declare class Ability<A extends AbilityTuple = AbilityTuple, C extends MongoQuery = MongoQuery> extends PureAbility<A, C> { | ||
| constructor(rules?: RawRuleFrom<A, C>[], options?: AbilityOptions<A, C>); | ||
| } | ||
| export interface AnyMongoAbility extends AnyAbility<any, MongoQuery> { | ||
| export interface AnyMongoAbility extends Public<Ability<any, MongoQuery>> { | ||
| } |
@@ -19,6 +19,3 @@ import { createFactory, BuildMongoQuery, DefaultOperators } from '@ucast/mongo2js'; | ||
| [x: string]: any; | ||
| } & import("@ucast/mongo2js").MongoQueryTopLevelOperators<any>), import("@ucast/mongo2js").ParsingContext<import("@ucast/mongo2js").FieldParsingContext & { | ||
| query: {}; | ||
| hasOperators<T>(value: unknown): value is T; | ||
| }>>; | ||
| } & import("@ucast/mongo2js").MongoQueryTopLevelOperators<any>), import("@ucast/mongo2js").FieldParsingContext>; | ||
| $exists: import("@ucast/mongo2js").FieldInstruction<boolean, import("@ucast/mongo2js").FieldParsingContext>; | ||
@@ -25,0 +22,0 @@ }; |
@@ -6,3 +6,3 @@ import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public, RawRuleOf } from './RuleIndex'; | ||
| } | ||
| export interface AnyAbility<A extends Abilities = any, Conditions = any> extends Public<PureAbility<A, Conditions>> { | ||
| export interface AnyAbility extends Public<PureAbility<any, any>> { | ||
| } | ||
@@ -9,0 +9,0 @@ export interface AbilityOptionsOf<T extends AnyAbility> extends RuleIndexOptionsOf<T> { |
@@ -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 _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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility<A extends Abilities = any, Conditions = any>\n extends Public<PureAbility<A, Conditions>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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, AnyAbility } from './PureAbility';\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 interface AnyMongoAbility extends AnyAbility<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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matchesConditions","matches","matchesField","field","_matchField","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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"} | ||
| {"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?(\n subject: Exclude<Normalize<A>[1], SubjectType>\n ): ExtractSubjectType<Normalize<A>[1]>\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 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}\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]): ExtractSubjectType<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 interface AbilityOptions<A extends Abilities, Conditions>\n extends RuleIndexOptions<A, Conditions> {}\nexport interface AnyAbility extends Public<PureAbility<any, any>> {}\nexport interface AbilityOptionsOf<T extends AnyAbility> extends 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 { 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<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 interface AnyMongoAbility extends 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","resolveAction","inverted","reason","undefined","_options","_conditionsMatcher","this","_matchConditions","matchesConditions","matches","matchesField","field","_matchField","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
-1
| { | ||
| "name": "@casl/ability", | ||
| "version": "5.2.0", | ||
| "version": "5.2.1", | ||
| "description": "CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access", | ||
@@ -5,0 +5,0 @@ "funding": "https://github.com/stalniy/casl/blob/master/BACKERS.md", |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
345332
0.02%560
-0.36%