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

@casl/ability

Package Overview
Dependencies
Maintainers
1
Versions
88
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@casl/ability - npm Package Compare versions

Comparing version
5.1.0-next.10
to
5.1.0-next.11
+80
-0
CHANGELOG.md

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

# [5.1.0-next.11](https://github.com/stalniy/casl/compare/@casl/ability@5.1.0-next.10...@casl/ability@5.1.0-next.11) (2020-10-17)
### Bug Fixes
* **README:** removes explanation duplicated from intro guide ([6315aa7](https://github.com/stalniy/casl/commit/6315aa7eea681d76bda947a7d5353da39c48e005))
### Code Refactoring
* **ruleIndex:** `detectSubjectType` option is now responsible only for detecting subject type from objects [skip release] ([ebeaadc](https://github.com/stalniy/casl/commit/ebeaadc0974a3e1697b34b3d85d2510d65b73dbb))
### BREAKING CHANGES
* **ruleIndex:** string and class (or function constructor) are the only possible subject types for now. `detectSubjectType` is now responsible only for detecting subject type from object
**Before**
When providing subject type it was important to handle cases when passed in argument is a string or function. As an alternative it was possible to call built-in `detectSubjectType` which could catch this cases:
```js
import { Ability } from '@casl/ability';
const ability = new Ability([], {
detectSubjectType(object) {
if (object && typeof object === 'object') {
return object.__typename;
}
return detectSubjectType(object);
});
```
**After**
There is no need to handle subject type values in `detectSubjectType` function anymore. It's now handled internally:
```js
import { Ability } from '@casl/ability';
const ability = new Ability([], {
detectSubjectType: object => object.__typename
});
```
Also it's important to note that if you want it's no longer possible to use classes and strings as subject types interchangably together as it was before. Now, if you want to use classes, you should use them everywhere:
**Before**
```js
import { defineAbility } from '@casl/ability';
class Post {}
const ability = defineAbility((can) => {
can('read', Post);
can('update', 'Post');
});
ability.can('read', 'Post') // true
ability.can('read', Post) // true
ability.can('update', Post) // true
```
**After**
```js
import { defineAbility } from '@casl/ability';
class Post {}
const ability = defineAbility((can) => {
can('read', Post);
can('update', 'Post');
});
ability.can('read', 'Post') // false, 'Post' and Post are considered different now
ability.can('read', Post) // true
ability.can('update', Post) // false
```
# [5.1.0-next.10](https://github.com/stalniy/casl/compare/@casl/ability@5.1.0-next.9...@casl/ability@5.1.0-next.10) (2020-10-17)

@@ -7,0 +87,0 @@

+1
-1

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

{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteItem(this: Set<string>, item: string) {\n this.delete(item);\n}\n\nfunction addItem(this: Set<string>, item: string) {\n this.add(item);\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {}\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const subjectType = ability.detectSubjectType(subject);\n const uniqueFields = ability.possibleRulesFor(action, subjectType)\n .reduceRight((fields, rule) => {\n if (!rule.matchesConditions(subject)) {\n return fields;\n }\n\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteItem : addItem;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, new Set<string>());\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","getRuleFields","deleteItem","item","delete","addItem","add","permittedFieldsOf","subject","options","fieldsFrom","detectSubjectType","uniqueFields","possibleRulesFor","reduceRight","matchesConditions","names","toggle","forEach","Set","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"wDAEO,SAASA,EAAaC,UACpBC,MAAMC,QAAQF,GAASA,EAAQ,CAACA,GAGlC,SAASG,EAAUC,EAAmBC,EAAcL,OACrDM,EAAMF,MACNG,EAAUF,MAEa,IAAvBA,EAAKG,QAAQ,KAAa,KACtBC,EAAOJ,EAAKK,MAAM,KAExBH,EAAUE,EAAKE,MACfL,EAAMG,EAAKG,QAAO,SAACC,EAAKC,GACtBD,EAAIC,GAAQD,EAAIC,IAAS,UAClBD,EAAIC,KACVV,GAGLE,EAAIC,GAAWP,ECNV,SAASe,EACdC,EACAC,EACAC,EACAC,OAEMC,EAAsBC,OAAOC,OAAO,UACpCC,EAAQP,EAAQQ,SAASP,EAAQC,OAElC,IAAIO,EAAI,EAAGA,EAAIF,EAAMG,OAAQD,IAAK,KAC/BE,EAAOJ,EAAME,OACbG,EAAKD,EAAKE,SAAW,OAAS,UAE/BF,EAAKG,cACJH,EAAKE,mBAEF,QACET,EAAMQ,UACNR,MAEJ,CACLA,EAAMQ,GAAMR,EAAMQ,IAAO,GACzBR,EAAMQ,GAAKG,KAAKZ,EAAQQ,YAIrBP,EAAMY,IAAMZ,EAAQ,KAG7B,SAASa,EAAUN,OACZA,EAAKO,UACF,IAAIC,uBAAuBC,KAAKC,UAAUV,gFAE3CA,EAAKO,IAGP,SAASI,EACdtB,EACAC,EACAC,OAEME,EAAQL,EAAaC,EAASC,EAAQC,EAAae,MAE3C,OAAVb,SACK,SAGJA,EAAMmB,YACFnB,EAAMY,IAAMQ,EAAQpB,EAAMY,KAAOS,EAAS,OAG/CrB,EAAMY,IACRZ,EAAMmB,KAAKR,KAAKS,EAAQpB,EAAMY,aAGzBS,EAASrB,EAAMmB,MAGjB,SAASG,EACd1B,EACAC,EACAC,UAEOF,EAAQQ,SAASP,EAAQC,GAC7BN,QAAO,SAAC+B,EAAQhB,MACXA,EAAKE,WAAaF,EAAKG,kBAClBa,SAGFtB,OAAOZ,KAAKkB,EAAKG,YAAYlB,QAAO,SAACgC,EAAQC,OAC5C7C,EAAQ2B,EAAKG,WAAYe,OAE1B7C,GAAUA,EAAc8C,cAAgBzB,OAC3ClB,EAAUyC,EAAQC,EAAW7C,UAGxB4C,IACND,KACF,IAGP,IAAMI,EAAgB,SAAhBA,EAAiBpB,UAA6BA,EAAKiB,QAQzD,SAASI,EAA8BC,QAChCC,OAAOD,GAGd,SAASE,EAA2BF,QAC7BG,IAAIH,GAGJ,SAASI,EACdrC,EACAC,EACAqC,EACAC,eAAAA,EAAAA,EAAqC,OAE/BC,EAAaD,EAAQC,YAAcT,MACnC7B,EAAcF,EAAQyC,kBAAkBH,OACxCI,EAAe1C,EAAQ2C,iBAAiB1C,EAAQC,GACnD0C,aAAY,SAAChB,EAAQjB,OACfA,EAAKkC,kBAAkBP,UACnBV,MAGHkB,EAAQN,EAAW7B,MAErBmC,EAAO,KACHC,EAASpC,EAAKE,SAAWmB,EAAaG,EAC5CW,EAAME,QAAQD,EAAQnB,UAGjBA,IACN,IAAIqB,YAEFhE,MAAMiE,KAAKR,GAGpB,IAAMS,EAAc,SAAdA,EAAenE,UAA6BC,MAAMC,QAAQF,GAASA,EAAMoE,KAAK,KAAOpE,GAWpF,SAASqE,EACd9C,EACA+C,UAEO/C,EAAMgD,KAAI,SAAC5C,OACV6C,EAA0B,CAC9BL,EAAaxC,EAAaV,QAAWU,EAAa8C,SAC3B,oBAAhBH,EACHvE,EAAU4B,EAAK2B,SAASiB,IAAID,GAAaF,KAAK,KAC9CD,EAAYxC,EAAK2B,SACrB3B,EAAKG,YAAc,EACnBH,EAAKE,SAAW,EAAI,EACpBF,EAAKiB,OAASuB,EAAYxC,EAAKiB,QAAU,EACzCjB,EAAK+C,QAAU,WAGTF,EAAWA,EAAW9C,OAAS,GAAI8C,EAAW7D,aAE/C6D,KAMJ,SAASG,EACdpD,EACAqD,UAEOrD,EAAMgD,KAAI,gBAAEtD,OAAQqC,OAASxB,OAAYD,OAAUe,OAAQ8B,WAC1DG,EAAWvB,EAAQ5C,MAAM,SACzBiB,EAAO,CACXE,WAAYA,EACZZ,OAAQA,EAAOP,MAAM,KACrB4C,QAAkC,oBAAlBsB,EACZC,EAASN,IAAIK,GACbC,MAGF/C,EACFH,EAAKG,WAAaA,KAGhBc,EACFjB,EAAKiB,OAASA,EAAOlC,MAAM,QAGzBgE,EACF/C,EAAK+C,OAASA,SAGT/C"}
{"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { Condition, buildAnd, buildOr } from '@ucast/mongo2js';\nimport { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport { AnyObject, SubjectType, ExtractSubjectType } from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery<T = object> {\n $or?: T[]\n $and?: T[]\n}\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n convert: RuleToQueryConverter<T>\n): AbilityQuery | null {\n const query: AbilityQuery = Object.create(null);\n const rules = ability.rulesFor(action, subjectType);\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nfunction ruleToAST(rule: RuleOf<AnyAbility>): Condition {\n if (!rule.ast) {\n throw new Error(`Ability rule \"${JSON.stringify(rule)}\" does not have \"ast\" property. So, cannot be used to generate AST`);\n }\n return rule.ast;\n}\n\nexport function rulesToAST<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): Condition | null {\n const query = rulesToQuery(ability, action, subjectType, ruleToAST) as AbilityQuery<Condition>;\n\n if (query === null) {\n return null;\n }\n\n if (!query.$and) {\n return query.$or ? buildOr(query.$or) : buildAnd([]);\n }\n\n if (query.$or) {\n query.$and.push(buildOr(query.$or));\n }\n\n return buildAnd(query.$and);\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n action: Parameters<T['rulesFor']>[0],\n subjectType: ExtractSubjectType<Parameters<T['rulesFor']>[1]>,\n): AnyObject {\n return ability.rulesFor(action, subjectType)\n .reduce((values, rule) => {\n if (rule.inverted || !rule.conditions) {\n return values;\n }\n\n return Object.keys(rule.conditions).reduce((fields, fieldName) => {\n const value = rule.conditions![fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteItem(this: Set<string>, item: string) {\n this.delete(item);\n}\n\nfunction addItem(this: Set<string>, item: string) {\n this.add(item);\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {}\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const subjectType = ability.detectSubjectType(subject);\n const uniqueFields = ability.possibleRulesFor(action, subjectType)\n .reduceRight((fields, rule) => {\n if (!rule.matchesConditions(subject)) {\n return fields;\n }\n\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteItem : addItem;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, new Set<string>());\n\n return Array.from(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || ''\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","action","subjectType","convert","query","Object","create","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","ruleToAST","ast","Error","JSON","stringify","rulesToAST","$and","buildOr","buildAnd","rulesToFields","values","fields","fieldName","constructor","getRuleFields","deleteItem","item","delete","addItem","add","permittedFieldsOf","subject","options","fieldsFrom","detectSubjectType","uniqueFields","possibleRulesFor","reduceRight","matchesConditions","names","toggle","forEach","Set","from","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"wDAEO,SAASA,EAAaC,UACpBC,MAAMC,QAAQF,GAASA,EAAQ,CAACA,GAGlC,SAASG,EAAUC,EAAmBC,EAAcL,OACrDM,EAAMF,MACNG,EAAUF,MAEa,IAAvBA,EAAKG,QAAQ,KAAa,KACtBC,EAAOJ,EAAKK,MAAM,KAExBH,EAAUE,EAAKE,MACfL,EAAMG,EAAKG,QAAO,SAACC,EAAKC,GACtBD,EAAIC,GAAQD,EAAIC,IAAS,UAClBD,EAAIC,KACVV,GAGLE,EAAIC,GAAWP,ECNV,SAASe,EACdC,EACAC,EACAC,EACAC,OAEMC,EAAsBC,OAAOC,OAAO,UACpCC,EAAQP,EAAQQ,SAASP,EAAQC,OAElC,IAAIO,EAAI,EAAGA,EAAIF,EAAMG,OAAQD,IAAK,KAC/BE,EAAOJ,EAAME,OACbG,EAAKD,EAAKE,SAAW,OAAS,UAE/BF,EAAKG,cACJH,EAAKE,mBAEF,QACET,EAAMQ,UACNR,MAEJ,CACLA,EAAMQ,GAAMR,EAAMQ,IAAO,GACzBR,EAAMQ,GAAKG,KAAKZ,EAAQQ,YAIrBP,EAAMY,IAAMZ,EAAQ,KAG7B,SAASa,EAAUN,OACZA,EAAKO,UACF,IAAIC,uBAAuBC,KAAKC,UAAUV,gFAE3CA,EAAKO,IAGP,SAASI,EACdtB,EACAC,EACAC,OAEME,EAAQL,EAAaC,EAASC,EAAQC,EAAae,MAE3C,OAAVb,SACK,SAGJA,EAAMmB,YACFnB,EAAMY,IAAMQ,EAAQpB,EAAMY,KAAOS,EAAS,OAG/CrB,EAAMY,IACRZ,EAAMmB,KAAKR,KAAKS,EAAQpB,EAAMY,aAGzBS,EAASrB,EAAMmB,MAGjB,SAASG,EACd1B,EACAC,EACAC,UAEOF,EAAQQ,SAASP,EAAQC,GAC7BN,QAAO,SAAC+B,EAAQhB,MACXA,EAAKE,WAAaF,EAAKG,kBAClBa,SAGFtB,OAAOZ,KAAKkB,EAAKG,YAAYlB,QAAO,SAACgC,EAAQC,OAC5C7C,EAAQ2B,EAAKG,WAAYe,OAE1B7C,GAAUA,EAAc8C,cAAgBzB,OAC3ClB,EAAUyC,EAAQC,EAAW7C,UAGxB4C,IACND,KACF,IAGP,IAAMI,EAAgB,SAAhBA,EAAiBpB,UAA6BA,EAAKiB,QAQzD,SAASI,EAA8BC,QAChCC,OAAOD,GAGd,SAASE,EAA2BF,QAC7BG,IAAIH,GAGJ,SAASI,EACdrC,EACAC,EACAqC,EACAC,eAAAA,EAAAA,EAAqC,OAE/BC,EAAaD,EAAQC,YAAcT,MACnC7B,EAAcF,EAAQyC,kBAAkBH,OACxCI,EAAe1C,EAAQ2C,iBAAiB1C,EAAQC,GACnD0C,aAAY,SAAChB,EAAQjB,OACfA,EAAKkC,kBAAkBP,UACnBV,MAGHkB,EAAQN,EAAW7B,MAErBmC,EAAO,KACHC,EAASpC,EAAKE,SAAWmB,EAAaG,EAC5CW,EAAME,QAAQD,EAAQnB,UAGjBA,IACN,IAAIqB,YAEFhE,MAAMiE,KAAKR,GAGpB,IAAMS,EAAc,SAAdA,EAAenE,UAA6BC,MAAMC,QAAQF,GAASA,EAAMoE,KAAK,KAAOpE,GAWpF,SAASqE,EACd9C,EACA+C,UAEO/C,EAAMgD,KAAI,SAAC5C,OACV6C,EAA0B,CAC9BL,EAAaxC,EAAaV,QAAWU,EAAa8C,SAC3B,oBAAhBH,EACHvE,EAAU4B,EAAK2B,SAASiB,IAAID,GAAaF,KAAK,KAC9CD,EAAYxC,EAAK2B,SACrB3B,EAAKG,YAAc,EACnBH,EAAKE,SAAW,EAAI,EACpBF,EAAKiB,OAASuB,EAAYxC,EAAKiB,QAAU,EACzCjB,EAAK+C,QAAU,WAGTF,EAAWA,EAAW9C,OAAS,GAAI8C,EAAW7D,aAE/C6D,KAMJ,SAASG,EACdpD,EACAqD,UAEOrD,EAAMgD,KAAI,gBAAEtD,OAAQqC,OAASxB,OAAYD,OAAUe,OAAQ8B,WAC1DG,EAAWvB,EAAQ5C,MAAM,SACzBiB,EAAO,CACXE,WAAYA,EACZZ,OAAQA,EAAOP,MAAM,KACrB4C,QAAkC,oBAAlBsB,EACZC,EAASN,IAAIK,GACbC,MAGF/C,EACFH,EAAKG,WAAaA,KAGhBc,EACFjB,EAAKiB,OAASA,EAAOlC,MAAM,QAGzBgE,EACF/C,EAAK+C,OAASA,SAGT/C"}

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

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

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

{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport 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 } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || typeof object === 'string' || typeof object === 'function') {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Normalize<A>[1]): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n readonly detectSubjectType!: Exclude<RuleIndexOptions<A, Conditions>['detectSubjectType'], undefined>;\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 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): Rule<A, Conditions>[] {\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const rules = (this as any).rulesFor(action, this.detectSubjectType(subject), field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = this.ability.detectSubjectType(args[1]);\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","detectSubjectType","subject","Type","constructor","modelName","name","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","matchesConditions","this","_lazyMatchConditions","matchesField","field","_lazyMatchField","ast","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","_this","delete","payload","current","PureAbility","can","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","_PureAbility","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}
{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","matchesConditions","this","_lazyMatchConditions","matchesField","field","_lazyMatchField","ast","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","_this","delete","payload","current","PureAbility","can","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","_PureAbility","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"o+BAEO,SAASA,EAAaC,UACpBC,MAAMC,QAAQF,GAASA,EAAQ,CAACA,GAoBzC,IAAMG,EAAa,sBACZ,SAASC,EAGdC,EAASC,MACLA,MACGA,EAAOC,eAAeJ,GACzBK,OAAOC,eAAeH,EAAQH,EAAY,CAAEH,MAAOK,SAC9C,GAAIA,IAASC,EAAOH,SACnB,IAAIO,+CAA+CL,sCAAwCC,EAAOH,WAIrGG,EAGF,IAAMK,EAAgB,SAAhBA,EAAiBX,OACtBK,SAAcL,QACJ,WAATK,GAA8B,aAATA,GAG9B,IAAMO,EAAsB,SAAtBA,EAAuBZ,UAAwBA,EAAMa,WAAab,EAAMc,MACvE,IAAMC,EAAqB,SAArBA,EAAsBf,SACT,kBAAVA,EAAqBA,EAAQY,EAAoBZ,IAG1D,SAASgB,EAAkBC,OAC3BA,QACI,SAGLA,EAAQV,eAAeJ,UACjBc,EAAgBd,UAGnBS,EAAoBK,EAAQC,aAG9B,SAASC,EAAcC,EAAsBC,OAC9CC,EAAUvB,EAAUsB,OACpBE,EAAI,QAEDA,EAAID,EAAQE,OAAQ,KACnBC,EAASH,EAAQC,QAEnBH,EAASb,eAAekB,GAC1BH,EAAUA,EAAQI,OAAON,EAASK,WAI/BH,EAGT,SAASK,EAAeP,MAClBA,EAASQ,aACL,IAAIlB,MAAM,+DAGlBF,OAAOqB,KAAKT,GAAUU,SAAQ,SAACC,OACvBC,EAAWD,IAAUX,EAASW,IAC/B9B,MAAMC,QAAQkB,EAASW,OACY,IAApCX,EAASW,GAAOE,QAAQF,KAAwD,IAAvCX,EAASW,GAAOE,QAAQ,cAGjED,QACI,IAAItB,4CAA4CqB,SAAYX,EAASW,OAK1E,SAASG,EAAoBd,MACL,eAAzBe,QAAQC,IAAIC,SACdV,EAAeP,UAGV,SAACK,UAA8BN,EAAcC,EAAUK,IAGhE,SAASa,EAAeC,EAAWC,EAAaC,OACzC,IAAIlB,EAAIkB,EAAOlB,EAAIiB,EAAOhB,OAAQD,IACrCgB,EAAKG,KAAKF,EAAOjB,IAId,SAASoB,EACdC,EACAC,OAEKD,IAAUA,EAAMpB,cACZqB,GAAgB,OAGpBA,IAAiBA,EAAarB,cAC1BoB,GAAS,OAGdrB,EAAI,MACJuB,EAAI,MACFC,EAAc,SAEbxB,EAAIqB,EAAMpB,QAAUsB,EAAID,EAAarB,UACtCoB,EAAMrB,GAAGyB,SAAWH,EAAaC,GAAGE,SAAU,CAChDD,EAAOL,KAAKE,EAAMrB,IAClBA,QACK,CACLwB,EAAOL,KAAKG,EAAaC,IACzBA,IAIJR,EAAYS,EAAQH,EAAOrB,GAC3Be,EAAYS,EAAQF,EAAcC,UAE3BC,EAGF,SAASE,EAAmBC,EAAgBC,EAAQC,OACrDpD,EAAQkD,EAAIG,IAAIF,OAEfnD,EAAO,CACVA,EAAQoD,IACRF,EAAII,IAAIH,EAAKnD,UAGRA,EAGF,IAAMuD,EAAW,SAAXA,EAAeC,UAASA,GCxIrC,SAASC,EAAiCC,EAAyBC,MAC7D1D,MAAMC,QAAQwD,EAAKE,UAAYF,EAAKE,OAAOpC,aACvC,IAAId,MAAM,wEAGdgD,EAAKE,SAAWD,EAAQE,mBACpB,IAAInD,MAAM,mFAGdgD,EAAKI,aAAeH,EAAQI,wBACxB,IAAIrD,MAAM,6FAWPsD,wBAaTN,EACAC,EACAX,eAAAA,EAAAA,EAAmB,OAdbiB,cACAC,SAeNT,EAASC,EAAMC,QAEVlC,OAASkC,EAAQQ,cAAcT,EAAKjC,aACpCR,QAAUyC,EAAKzC,aACfmD,WAAaV,EAAKU,cAClBN,WAAaJ,EAAKI,gBAClBO,OAASX,EAAKW,YACdT,OAASF,EAAKE,OAAS7D,EAAU2D,EAAKE,aAAUU,OAChDtB,SAAWA,OACXuB,EAAWZ,sBAuBlBa,kBAAA,WAAkBlE,OACXmE,KAAKX,kBACD,SAGJxD,GAAUK,EAAcL,UACnBmE,KAAKL,gBAGRK,KAAKC,EAAsBpE,MAGpCqE,aAAA,WAAaC,OACNH,KAAKb,cACD,SAGJgB,SACKH,KAAKL,gBAGRK,KAAKI,EAAiBD,yDAxCzBH,KAAKX,aAAeW,KAAKR,OACtBA,EAAmBQ,KAAKF,EAASR,kBAAmBU,KAAKX,mBAGzDW,KAAKR,+CAIRQ,KAAKb,SAAWa,KAAKP,OAClBA,EAAcO,KAAKF,EAASV,aAAcY,KAAKb,eAG/Ca,KAAKP,uCAILO,KAAKC,EAAuBD,KAAKC,EAAqBI,SAAMR,kBC3EhE,IAAMS,EAAa,SAAbA,EAAiB/E,EAAUgF,OAChCC,EAAO,CAAEjF,MAAAA,EAAOgF,KAAAA,EAAME,KAAM,SAE9BF,EACFA,EAAKE,KAAOD,SAGPA,GAGF,IAAME,EAAa,SAAbA,EAAcF,MACrBA,EAAKC,KACPD,EAAKC,KAAKF,KAAOC,EAAKD,QAGpBC,EAAKD,KACPC,EAAKD,KAAKE,KAAOD,EAAKC,KAGxBD,EAAKC,KAAOD,EAAKD,KAAO,MCwC1B,IAAMI,EAAqB,SAArBA,UAA4B,CAChCC,MAAO,GACPtC,OAAQ,QAEV,IAAMuC,EAAsB,SAAtBA,WAA4B,IAAIC,KACtC,IAAMC,GAAU,SAAVA,EAAWC,EAAY/B,OACtB+B,EAAMC,GAAqBhC,EAAKE,OACnC6B,EAAMC,EAAoB,UAejBC,yBAWTN,EACA1B,eADA0B,EAAAA,EAAsC,eACtC1B,EAAAA,EAA2C,QAXrC+B,EAA6B,WAC7BE,EAAwB,IAAIL,SAY7BM,EAAe,CAClB9B,kBAAmBJ,EAAQI,kBAC3BF,aAAcF,EAAQE,aACtBM,cAAeR,EAAQQ,eAAiBZ,QAErCuC,EAAqBnC,EAAQ3C,mBAAqBA,OAClD+E,EAASV,OACTW,EAAgBvB,KAAKwB,EAAeZ,uBAO3CrE,kBAAA,WAAkBV,UACTK,EAAcL,GACjBA,EACAmE,KAAKqB,EAAmBxF,MAG9B4F,OAAA,WAAOb,OACCc,EAAQ,CACZd,MAAAA,EACAe,QAAS3B,KACTjC,OAAQiC,WAGL4B,EAAM,SAAUF,QAChBJ,EAASV,OACTW,EAAgBvB,KAAKwB,EAAeZ,QACpCgB,EAAM,UAAWF,UAEf1B,QAGDwB,EAAR,WAAuBK,OACfC,EAAyC,IAAIhB,QAE9C,IAAIhE,EAAI+E,EAAS9E,OAAS,EAAGD,GAAK,EAAGA,IAAK,KACvCyB,EAAWsD,EAAS9E,OAASD,EAAI,MACjCmC,EAAO,IAAIM,EAAKsC,EAAS/E,GAAIkD,KAAKoB,EAAc7C,OAChD1B,EAAUvB,EAAU2D,EAAKjC,YACzB+E,EAAWzG,EAAU2D,EAAKzC,SAAW,OAC3CuE,GAAQf,KAAMf,OAET,IAAI+C,EAAI,EAAGA,EAAID,EAAShF,OAAQiF,IAAK,KAClCC,EAAezD,EAAasD,EAAcC,EAASC,GAAInB,OAExD,IAAIxC,EAAI,EAAGA,EAAIxB,EAAQE,OAAQsB,IAClCG,EAAayD,EAAcpF,EAAQwB,GAAIsC,GAAoBC,MAAM3C,KAAKgB,WAKrE6C,KAITI,iBAAA,WAAiBlF,EAAgBmF,eAAAA,EAAAA,EAA2B,UACrDjG,EAAciG,SACX,IAAIlG,MAAM,kGAGZgG,EAAezD,EAAawB,KAAKuB,EAAeY,EAAatB,OAC7DuB,EAAc5D,EAAayD,EAAcjF,EAAQ2D,MAEnDyB,EAAY9D,cACP8D,EAAYxB,UAGfyB,EAAyB,WAAXrF,GAAuBiF,EAAaK,IAAI,UACxDL,EAAarD,IAAI,UAAWgC,WAC5Bf,MACAe,EAAQ1C,EAAiBkE,EAAYxB,MAAOyB,MAE5B,QAAhBF,EACFvB,EAAQ1C,EAAiB0C,EAAQZ,KAAakC,iBAAiBlF,EAAQ,QAGzEoF,EAAYxB,MAAQA,EACpBwB,EAAY9D,OAAS,YAEdsC,KAIT2B,SAAA,WAASvF,EAAgBmF,EAA2BhC,OAC5CS,EAAgCZ,KAAakC,iBAAiBlF,EAAQmF,MAExEhC,GAA0B,kBAAVA,QACZ,IAAIlE,MAAM,qJAGb+D,KAAKiB,SACDL,SAGFA,EAAM4B,QAAO,SAAAvD,UAAQA,EAAKiB,aAAaC,SAGhDsC,GAAA,WACEf,EACAgB,kBAEMC,EAAO3C,KAAKmB,EAAQvC,IAAI8C,IAAU,SAClClB,EAAOF,EAAWoC,EAASC,QAC5BxB,EAAQtC,IAAI6C,EAAOlB,UAEjB,eACAA,EAAKC,OAASD,EAAKD,MAAQqC,EAAKzB,EAAQvC,IAAI8C,KAAWlB,EAC1DoC,EAAKzB,EAAQ0B,OAAOnB,QAEpBhB,EAAWF,OAKToB,EAAR,WAA+CvF,EAASyG,OAClDC,EAAU/C,KAAKmB,EAAQvC,IAAIvC,IAAS,WACrB,OAAZ0G,EAAkB,KACjBxC,EAAOwC,EAAQxC,KACrBwC,EAAQxH,MAAMuH,GACdC,EAAUxC,8CA/GLP,KAAKsB,sBCvGH0B,4FAIXC,IAAA,iBACQhE,EAAOe,KAAKkD,8CACTjE,IAASA,EAAKU,YAIzBuD,gBAAA,WAAgBlG,EAAgBR,EAAmB2D,OAC3CgC,EAAcnC,KAAKzD,kBAAkBC,OACrCoE,EAASZ,KAAauC,SAASvF,EAAQmF,EAAahC,OAErD,IAAIrD,EAAI,EAAGC,EAAS6D,EAAM7D,OAAQD,EAAIC,EAAQD,OAC7C8D,EAAM9D,GAAGiD,kBAAkBvD,UACtBoE,EAAM9D,UAIV,QAGTqG,OAAA,oBACUnD,KAAKiD,qCArBP/B,ICwBV,IAAMkC,GAAsB,CAC1BC,IAAAA,EACAC,IAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,KAAAA,EACAC,MAAAA,EACAC,OAAAA,EACAC,SAAAA,EACAC,WAAAA,EACAC,QAAAA,GAEF,IAAMC,GAAsB,CAC1BC,GAAAA,EACAC,GAAAA,EACAC,GAAAA,EACAC,IAAAA,EACAC,GAAAA,EACAC,IAAAA,EACAC,GAAIC,EACJC,IAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,MAAAA,EACAC,UAAAA,EACAC,OAAAA,EACAC,IAAAA,OAeWC,GAA0B,SAA1BA,EAA2BC,EAAcC,EAAcnG,UAAYoG,OACzElC,GAAwBgC,QACxBjB,GAAwBkB,GAC7BnG,QAGWqG,GAAoBD,EAAclC,GAAqBe,ICrFpE,IAAMqB,GAAuB,uBAC7B,IAAMC,GAAa,aACnB,IAAMC,GAAe,MACrB,IAAMC,GAAa,MAEnB,SAASC,GAAoBC,EAAe7E,EAAe8E,OACnDC,EAA2B,MAAdD,EAAO,IAA2B,MAAbD,EAAM,IAA0C,MAA5BA,EAAMA,EAAM9I,OAAS,GAC7E,IACA,QACEiJ,GAAmC,IAAzBH,EAAMrI,QAAQ,MAAe,OAAS,QAChDyI,EAAUJ,EAAMK,QAAQP,GAAY,QACvCO,QAAQR,GAAcM,EAAUD,UAE5B/E,EAAQ6E,EAAM9I,SAAW+I,EAAO/I,aAAekJ,OAAcA,EAGtE,SAASE,GAAaN,EAAe7E,EAAe8E,MACpC,MAAVD,IAAwC,MAAtBC,EAAO9E,EAAQ,IAAoC,MAAtB8E,EAAO9E,EAAQ,WACzD6E,aAGGA,EAGd,SAASO,GAAcjH,OACfkH,EAAWlH,EAAOV,KAAI,SAAA0B,UAASA,EAClC+F,QAAQV,GAAsBW,IAC9BD,QAAQT,GAAYG,WACjBK,EAAUI,EAAStJ,OAAS,QAAUsJ,EAASC,KAAK,SAAUD,EAAS,UAEtE,IAAIE,WAAWN,WAGXO,GAAoC,SAApCA,EAAqCrH,OAC5C8G,SAEG,SAAC9F,MACiB,qBAAZ8F,EACTA,EAAU9G,EAAOsH,OAAM,SAAAC,UAAyB,IAApBA,EAAElJ,QAAQ,QAClC,KACA4I,GAAcjH,UAGD,OAAZ8G,GACwB,IAA3B9G,EAAO3B,QAAQ2C,GACf8F,EAAQU,KAAKxG,SCrCRyG,iCAIChG,EAAiC1B,eAAjC0B,EAAAA,EAA6B,eAAI1B,EAAAA,EAAgC,UAC3E2H,YAAMjG,KACJtB,kBAAmBiG,GACnBnG,aAAcoH,IACXtH,oBALC8D,QCCJ8D,yBAGQ7H,QACL8H,EAAQ9H,sBAGf+H,QAAA,WAAQpH,QACDmH,EAAMnH,OAASA,SACbI,sBA8CEiH,yBAOCC,QAHLtG,MAAwB,QAIxBuG,EAAeD,MACdE,EAAOpH,KACboH,EAAKnE,IAAMmE,EAAKnE,IAAIoE,KAAKD,GACzBA,EAAKjE,OAASiE,EAAKjE,OAAOkE,KAAKD,GAC/BA,EAAKE,MAAQF,EAAKE,MAAMD,KAAKD,uBAY/BnE,IAAA,WACEjG,EACAR,EACA+K,EACAlI,OAEMJ,EAAO,CAAEjC,OAAAA,MAEXR,EAAS,CACXyC,EAAKzC,QAAUA,KAEXhB,MAAMC,QAAQ8L,IAAqD,kBAAvBA,EAC9CtI,EAAKE,OAASoI,OACT,GAAkC,qBAAvBA,EAChBtI,EAAKI,WAAakI,KAGM,qBAAflI,EACTJ,EAAKI,WAAaA,OAIjBuB,MAAM3C,KAAKgB,UAET,IAAI6H,GAAY7H,MAYzBkE,OAAA,WACEnG,EACAR,EACA+K,EACAlI,OAEMmI,EAAWxH,KAAaiD,IAAIjG,EAAQR,EAAS+K,EAAoBlI,GACvEmI,EAAQT,EAAMpH,SAAW,YAClB6H,KAGTF,MAAA,WAAMpI,UACG,IAAIc,KAAKmH,EAAanH,KAAKY,MAAO1B,gBAetC,SAASuI,GAEdC,EAAsCxI,OAChCsI,EAAU,IAAIP,GAAeL,QAC7Be,EAASD,EAAOF,EAAQvE,IAAKuE,EAAQrE,WAEvCwE,GAAiC,oBAAhBA,EAAOC,YACnBD,EAAOC,MAAK,kBAAMJ,EAAQF,MAAMpI,aAGlCsI,EAAQF,MAAMpI,OChKV2I,GAA0C,SAA1CA,EAA0CC,4BAA4BA,EAAM9K,gBAAe8K,EAAM3F,iBAE9G,IAAM4F,GAAc,SAASC,EAAoBC,QAC1CA,QAAUA,GAGjBF,GAAYG,UAAYnM,OAAOoM,OAAOlM,MAAMiM,eAE/BE,wBASJC,kBAAP,WAAyBC,QAClBC,EAA8C,kBAAhBD,EAA2B,kBAAMA,GAAcA,KAG7EE,KAAP,WAAkC7G,UACzB,IAAI3B,KAAK2B,eAGEA,uBACZ,YAdDxB,eAeAwB,QAAUA,KAEwB,oBAA5B1F,MAAMwM,kBAAkC,GAC5CpM,KAAO,iBACZJ,MAAMwM,uBAAwB7F,EAAKnG,0CAIvCiM,WAAA,WAAWT,QACJA,QAAUA,SACRjI,QAGT2I,eAAA,uBACQ1J,UAAY0C,SAAQuB,sCAEtBjE,IAASA,EAAKU,qBAIb3C,oDACAR,qDACA2F,YAAc7F,EAAmB0D,KAAK2B,QAAQpF,iEAC9C4D,kDAECP,EAASX,EAAOA,EAAKW,OAAS,QAE/BqI,QAAUjI,KAAKiI,SAAWrI,GAAWI,KAAKvD,YAAoB8L,EAAqBvI,YAClFA,gBA/CgD+H,IAA7CK,GAOJG,EAAuBV"}

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

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

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

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

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

{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport 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 } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || typeof object === 'string' || typeof object === 'function') {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Normalize<A>[1]): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n readonly detectSubjectType!: Exclude<RuleIndexOptions<A, Conditions>['detectSubjectType'], undefined>;\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 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): Rule<A, Conditions>[] {\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const rules = (this as any).rulesFor(action, this.detectSubjectType(subject), field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = this.ability.detectSubjectType(args[1]);\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","detectSubjectType","subject","Type","constructor","modelName","name","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","this","_lazyMatchConditions","ast","matchesConditions","matchesField","field","_lazyMatchField","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"uGAEO,SAASA,EAAaC,UACpBC,MAAMC,QAAQF,GAASA,EAAQ,CAACA,GAoBzC,MAAMG,EAAa,sBACZ,SAASC,EAGdC,EAASC,MACLA,MACGA,EAAOC,eAAeJ,GACzBK,OAAOC,eAAeH,EAAQH,EAAY,CAAEH,MAAOK,SAC9C,GAAIA,IAASC,EAAOH,SACnB,IAAIO,MAAO,yCAAwCL,qCAAwCC,EAAOH,aAIrGG,EAGF,SAASK,EAAqCC,OAC9CA,QACI,SAGc,kBAAZA,SACFA,KAGLA,EAAQL,eAAeJ,UACjBS,EAAgBT,SAGpBU,EAA0B,oBAAZD,EAAyBA,EAAUA,EAAQE,mBACvDD,EAAsBE,WAAaF,EAAKG,KAG3C,SAASC,EAAcC,EAAsBC,OAC9CC,EAAUrB,EAAUoB,OACpBE,EAAI,QAEDA,EAAID,EAAQE,OAAQ,OACnBC,EAASH,EAAQC,QAEnBH,EAASX,eAAegB,GAC1BH,EAAUA,EAAQI,OAAON,EAASK,WAI/BH,EAGT,SAASK,EAAeP,MAClBA,EAASQ,aACL,IAAIhB,MAAM,+DAGlBF,OAAOmB,KAAKT,GAAUU,QAASC,UACvBC,EAAWD,IAAUX,EAASW,IAC/B5B,MAAMC,QAAQgB,EAASW,OACY,IAApCX,EAASW,GAAOE,QAAQF,KAAwD,IAAvCX,EAASW,GAAOE,QAAQ,cAGjED,QACI,IAAIpB,MAAO,sCAAqCmB,QAAYX,EAASW,QAK1E,SAASG,EAAoBd,MACL,eAAzBe,QAAQC,IAAIC,SACdV,EAAeP,UAGTK,GAA8BN,EAAcC,EAAUK,GAGhE,SAASa,EAAeC,EAAWC,EAAaC,OACzC,IAAIlB,EAAIkB,EAAOlB,EAAIiB,EAAOhB,OAAQD,IACrCgB,EAAKG,KAAKF,EAAOjB,IAId,SAASoB,EACdC,EACAC,OAEKD,IAAUA,EAAMpB,cACZqB,GAAgB,OAGpBA,IAAiBA,EAAarB,cAC1BoB,GAAS,OAGdrB,EAAI,MACJuB,EAAI,QACFC,EAAc,SAEbxB,EAAIqB,EAAMpB,QAAUsB,EAAID,EAAarB,UACtCoB,EAAMrB,GAAGyB,SAAWH,EAAaC,GAAGE,SAAU,CAChDD,EAAOL,KAAKE,EAAMrB,IAClBA,QACK,CACLwB,EAAOL,KAAKG,EAAaC,IACzBA,IAIJR,EAAYS,EAAQH,EAAOrB,GAC3Be,EAAYS,EAAQF,EAAcC,UAE3BC,EAGF,SAASE,EAAmBC,EAAgBC,EAAQC,OACrDlD,EAAQgD,EAAIG,IAAIF,OAEfjD,EAAO,CACVA,EAAQkD,IACRF,EAAII,IAAIH,EAAKjD,UAGRA,EAGF,MAAMqD,EAAeC,GAASA,ECnIrC,SAASC,EAAiCC,EAAyBC,MAC7DxD,MAAMC,QAAQsD,EAAKE,UAAYF,EAAKE,OAAOpC,aACvC,IAAIZ,MAAM,wEAGd8C,EAAKE,SAAWD,EAAQE,mBACpB,IAAIjD,MAAM,mFAGd8C,EAAKI,aAAeH,EAAQI,wBACxB,IAAInD,MAAM,yFAWb,MAAMoD,EAYXhD,YACE0C,EACAC,EACAX,EAAmB,QAdbiB,cACAC,SAeNT,EAASC,EAAMC,QAEVlC,OAASkC,EAAQQ,cAAcT,EAAKjC,aACpCX,QAAU4C,EAAK5C,aACfsD,WAAaV,EAAKU,cAClBN,WAAaJ,EAAKI,gBAClBO,OAASX,EAAKW,YACdT,OAASF,EAAKE,OAAS3D,EAAUyD,EAAKE,aAAUU,OAChDtB,SAAWA,OACXuB,EAAWZ,aAIZa,KAAKV,aAAeU,KAAKP,OACtBA,EAAmBO,KAAKD,EAASR,kBAAmBS,KAAKV,mBAGzDU,KAAKP,aAIRO,KAAKZ,SAAWY,KAAKN,OAClBA,EAAcM,KAAKD,EAASV,aAAcW,KAAKZ,eAG/CY,KAAKN,mBAILM,KAAKC,EAAuBD,KAAKC,EAAqBC,SAAMJ,EAGrEK,kBAAkBnE,OACXgE,KAAKV,kBACD,SAGJtD,GAA4B,kBAAXA,GAAyC,oBAAXA,SAC1CgE,KAAKJ,gBAGRI,KAAKC,EAAsBjE,GAGpCoE,aAAaC,OACNL,KAAKZ,cACD,SAGJiB,SACKL,KAAKJ,gBAGRI,KAAKM,EAAiBD,ICnG1B,MAAME,EAAa,CAAI7E,EAAU8E,WAChCC,EAAO,CAAE/E,MAAAA,EAAO8E,KAAAA,EAAME,KAAM,SAE9BF,EACFA,EAAKE,KAAOD,SAGPA,GAGF,MAAME,EAAcF,OACrBA,EAAKC,KACPD,EAAKC,KAAKF,KAAOC,EAAKD,QAGpBC,EAAKD,KACPC,EAAKD,KAAKE,KAAOD,EAAKC,KAGxBD,EAAKC,KAAOD,EAAKD,KAAO,MCwC1B,MAAMI,EAAqB,MACzBC,MAAO,GACPtC,OAAQ,QAEV,MAAMuC,EAAsB,IAAM,IAAIC,IACtC,MAAMC,EAAU,CAACC,EAAY/B,SACtB+B,EAAMC,GAAqBhC,EAAKE,OACnC6B,EAAMC,EAAoB,MAevB,MAAMC,EAUX3E,YACEqE,EAAsC,GACtC1B,EAA2C,SAXrC+B,EAA6B,WAC7BE,EAAwB,IAAIL,SAY7BM,EAAe,CAClB9B,kBAAmBJ,EAAQI,kBAC3BF,aAAcF,EAAQE,aACtBM,cAAeR,EAAQQ,eAAiBZ,QAErC1C,kBAAoB8C,EAAQ9C,mBAAqBA,OACjDiF,EAAST,OACTU,EAAgBvB,KAAKwB,EAAeX,sBAIlCb,KAAKsB,EAGdG,OAAOZ,SACCa,EAAQ,CACZb,MAAAA,EACAc,QAAS3B,KACThC,OAAQgC,WAGL4B,EAAM,SAAUF,QAChBJ,EAAST,OACTU,EAAgBvB,KAAKwB,EAAeX,QACpCe,EAAM,UAAWF,UAEf1B,KAGDwB,EAAeK,SACfC,EAAyC,IAAIf,QAE9C,IAAIhE,EAAI8E,EAAS7E,OAAS,EAAGD,GAAK,EAAGA,IAAK,OACvCyB,EAAWqD,EAAS7E,OAASD,EAAI,QACjCmC,EAAO,IAAIM,EAAKqC,EAAS9E,GAAIiD,KAAKqB,EAAc7C,SAChD1B,EAAUrB,EAAUyD,EAAKjC,cACzB8E,EAAWtG,EAAUyD,EAAK5C,SAAW,OAC3C0E,EAAQhB,KAAMd,OAET,IAAI8C,EAAI,EAAGA,EAAID,EAAS/E,OAAQgF,IAAK,OAClCC,EAAexD,EAAaqD,EAAcC,EAASC,GAAIlB,OAExD,IAAIxC,EAAI,EAAGA,EAAIxB,EAAQE,OAAQsB,IAClCG,EAAawD,EAAcnF,EAAQwB,GAAIsC,GAAoBC,MAAM3C,KAAKgB,WAKrE4C,EAITI,iBAAiBjF,EAAgBkF,SACzBF,EAAexD,EAAauB,KAAKuB,EAAeY,EAAarB,SAC7DsB,EAAc3D,EAAawD,EAAchF,EAAQ2D,MAEnDwB,EAAY7D,cACP6D,EAAYvB,YAGfwB,EAAyB,WAAXpF,GAAuBgF,EAAaK,IAAI,UACxDL,EAAapD,IAAI,UAAWgC,WAC5Bf,MACAe,EAAQ1C,EAAiBiE,EAAYvB,MAAOwB,MAE5B,QAAhBF,EACFtB,EAAQ1C,EAAiB0C,EAAQb,KAAakC,iBAAiBjF,EAAQ,QAGzEmF,EAAYvB,MAAQA,EACpBuB,EAAY7D,OAAS,YAEdsC,EAIT0B,SAAStF,EAAgBkF,EAA2B9B,SAC5CQ,EAAgCb,KAAakC,iBAAiBjF,EAAQkF,MAExE9B,GAA0B,kBAAVA,QACZ,IAAIjE,MAAM,qJAGb4D,KAAKkB,SACDL,SAGFA,EAAM2B,OAAOtD,GAAQA,EAAKkB,aAAaC,IAGhDoC,GACEf,EACAgB,SAEMC,EAAO3C,KAAKoB,EAAQvC,IAAI6C,IAAU,WAClCjB,EAAOF,EAAWmC,EAASC,QAC5BvB,EAAQtC,IAAI4C,EAAOjB,SAEjB,SACAA,EAAKC,OAASD,EAAKD,MAAQR,KAAKoB,EAAQvC,IAAI6C,KAAWjB,OACrDW,EAAQwB,OAAOlB,QAEpBf,EAAWF,IAKTmB,EAAuClF,EAASmG,OAClDC,EAAU9C,KAAKoB,EAAQvC,IAAInC,IAAS,WACrB,OAAZoG,EAAkB,OACjBtC,EAAOsC,EAAQtC,KACrBsC,EAAQpH,MAAMmH,GACdC,EAAUtC,IC5MT,MAAMuC,UAGH5B,EACR6B,OAAOC,SACC/D,EAAOc,KAAKkD,mBAAmBD,WAC5B/D,IAASA,EAAKU,SAIzBsD,gBAAgBjG,EAAgBX,EAAmB+D,SAC3CQ,EAASb,KAAauC,SAAStF,EAAQ+C,KAAK3D,kBAAkBC,GAAU+D,OAEzE,IAAItD,EAAI,EAAGC,EAAS6D,EAAM7D,OAAQD,EAAIC,EAAQD,OAC7C8D,EAAM9D,GAAGoD,kBAAkB7D,UACtBuE,EAAM9D,UAIV,KAGToG,UAAUF,UACAjD,KAAKgD,OAAOC,ICIxB,MAAMG,EAAsB,KAC1BC,UACAC,UACAC,WACAC,WACAC,WACAC,WACAC,WACAC,YACAC,aACAC,eACAC,kBACAC,sBACAC,qBACAC,WAEF,MAAMC,EAAsB,IAC1BC,QACAC,QACAC,SACAC,SACAC,SACAC,MACAC,GAAIC,aACJC,UACAC,WACAC,aACAC,kBACAC,mBACAC,aACAC,aAeWC,EAA0B,CAACC,EAAcC,EAAclG,IAAYmG,iCACzElC,EAAwBgC,oBACxBjB,EAAwBkB,GAC7BlG,SAGWoG,EAAoBD,gBAAclC,EAAqBe,GCrFpE,MAAMqB,EAAuB,uBAC7B,MAAMC,EAAa,aACnB,MAAMC,EAAe,MACrB,MAAMC,EAAa,MAEnB,SAASC,EAAoBC,EAAe5E,EAAe6E,SACnDC,EAA2B,MAAdD,EAAO,IAA2B,MAAbD,EAAM,IAA0C,MAA5BA,EAAMA,EAAM7I,OAAS,GAC7E,IACA,UACEgJ,GAAmC,IAAzBH,EAAMpI,QAAQ,MAAe,OAAS,UAChDwI,EAAUJ,EAAMK,QAAQP,EAAY,QACvCO,QAAQR,EAAcM,EAAUD,UAE5B9E,EAAQ4E,EAAM7I,SAAW8I,EAAO9I,OAAU,MAAKiJ,MAAcA,EAGtE,SAASE,EAAaN,EAAe5E,EAAe6E,MACpC,MAAVD,IAAwC,MAAtBC,EAAO7E,EAAQ,IAAoC,MAAtB6E,EAAO7E,EAAQ,WACzD4E,QAGD,KAAIA,IAGd,SAASO,EAAchH,SACfiH,EAAWjH,EAAOV,IAAI2B,GAASA,EAClC6F,QAAQV,EAAsBW,GAC9BD,QAAQT,EAAYG,UACjBK,EAAUI,EAASrJ,OAAS,EAAK,MAAKqJ,EAASC,KAAK,QAAUD,EAAS,UAEtE,IAAIE,OAAQ,IAAGN,YAGXO,EAAqCpH,QAC5C6G,SAEI5F,OACiB,qBAAZ4F,EACTA,EAAU7G,EAAOqH,MAAMC,IAAyB,IAApBA,EAAEjJ,QAAQ,MAClC,KACA2I,EAAchH,UAGD,OAAZ6G,GACwB,IAA3B7G,EAAO3B,QAAQ4C,GACf4F,EAAQU,KAAKtG,KCrCd,MAAMuG,UAGH7D,EACRvG,YAAYqE,EAA6B,GAAI1B,EAAgC,UACrE0B,iBACJtB,kBAAmBgG,EACnBlG,aAAcmH,GACXrH,KCJT,MAAM0H,EAGJrK,YAAY0C,QACL4H,EAAQ5H,EAGf6H,QAAQlH,QACDiH,EAAMjH,OAASA,SACbG,MA8CJ,MAAMgH,EAOXxK,YAAYyK,QAHLpG,MAAwB,QAIxBqG,EAAeD,QACdE,EAAOnH,KACbmH,EAAKnE,IAAMmE,EAAKnE,IAAIoE,KAAKD,GACzBA,EAAKhE,OAASgE,EAAKhE,OAAOiE,KAAKD,GAC/BA,EAAKE,MAAQF,EAAKE,MAAMD,KAAKD,GAY/BnE,IACE/F,EACAX,EACAgL,EACAhI,SAEMJ,EAAO,CAAEjC,OAAAA,MAEXX,EAAS,CACX4C,EAAK5C,QAAUA,KAEXX,MAAMC,QAAQ0L,IAAqD,kBAAvBA,EAC9CpI,EAAKE,OAASkI,OACT,GAAkC,qBAAvBA,EAChBpI,EAAKI,WAAagI,KAGM,qBAAfhI,EACTJ,EAAKI,WAAaA,OAIjBuB,MAAM3C,KAAKgB,UAET,IAAI2H,EAAY3H,GAYzBiE,OACElG,EACAX,EACAgL,EACAhI,SAEMiI,EAAWvH,KAAagD,IAAI/F,EAAQX,EAASgL,EAAoBhI,GACvEiI,EAAQT,EAAMlH,SAAW,YAClB2H,EAGTF,MAAMlI,UACG,IAAIa,KAAKkH,EAAalH,KAAKa,MAAO1B,IAetC,SAASqI,EAEdC,EAAsCtI,SAChCoI,EAAU,IAAIP,EAAeJ,SAC7Bc,EAASD,EAAOF,EAAQvE,IAAKuE,EAAQpE,WAEvCuE,GAAiC,oBAAhBA,EAAOC,YACnBD,EAAOC,KAAK,IAAMJ,EAAQF,MAAMlI,WAGlCoI,EAAQF,MAAMlI,SCjKVyI,EAA0CC,GAAU,mBAAkBA,EAAM5K,eAAe4K,EAAM1F,eAE9G,MAAM2F,EAAc,SAASC,EAAoBC,QAC1CA,QAAUA,GAGjBF,EAAYG,UAAY/L,OAAOgM,OAAO9L,MAAM6L,WAErC,MAAME,UAA6CL,2BAS/BM,QAClBC,EAA8C,kBAAhBD,EAA2B,IAAMA,EAAcA,cAGlDzG,UACzB,IAAI3B,KAAK2B,GAGVnF,YAAYmF,SACZ,SAdDtB,kBAeAsB,QAAUA,KAEwB,oBAA5BvF,MAAMkM,kBAAkC,MAC5C5L,KAAO,iBACZN,MAAMkM,kBAAkBtI,KAAMA,KAAKxD,cAIvC+L,WAAWP,QACJA,QAAUA,SACRhI,KAGTwI,kBAAkBvF,SACV/D,EAAOc,KAAK2B,QAAQuB,mBAAmBD,MAEzC/D,IAASA,EAAKU,qBAIb3C,OAASgG,EAAK,QACd3G,QAAU2G,EAAK,QACfd,YAAcnC,KAAK2B,QAAQtF,kBAAkB4G,EAAK,SAClD5C,MAAQ4C,EAAK,SAEZpD,EAASX,EAAOA,EAAKW,OAAS,QAE/BmI,QAAUhI,KAAKgI,SAAWnI,GAAWG,KAAKxD,YAAoB6L,EAAqBrI,YAClFA,MA/CGmI,EAOJE,EAAuBT"}
{"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","this","_lazyMatchConditions","ast","matchesConditions","matchesField","field","_lazyMatchField","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}

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

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

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

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

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

{"version":3,"file":"index.mjs","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport 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 } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || typeof object === 'string' || typeof object === 'function') {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Normalize<A>[1]): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n readonly detectSubjectType!: Exclude<RuleIndexOptions<A, Conditions>['detectSubjectType'], undefined>;\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 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): Rule<A, Conditions>[] {\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const rules = (this as any).rulesFor(action, this.detectSubjectType(subject), field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = this.ability.detectSubjectType(args[1]);\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","detectSubjectType","subject","Type","constructor","modelName","name","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","this","_lazyMatchConditions","ast","matchesConditions","matchesField","field","_lazyMatchField","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"gVAEO,SAASA,EAAaC,UACpBC,MAAMC,QAAQF,GAASA,EAAQ,CAACA,GAoBzC,MAAMG,EAAa,sBACZ,SAASC,EAGdC,EAASC,MACLA,MACGA,EAAOC,eAAeJ,GACzBK,OAAOC,eAAeH,EAAQH,EAAY,CAAEH,MAAOK,SAC9C,GAAIA,IAASC,EAAOH,SACnB,IAAIO,MAAO,yCAAwCL,qCAAwCC,EAAOH,aAIrGG,EAGF,SAASK,EAAqCC,OAC9CA,QACI,SAGc,kBAAZA,SACFA,KAGLA,EAAQL,eAAeJ,UACjBS,EAAgBT,SAGpBU,EAA0B,oBAAZD,EAAyBA,EAAUA,EAAQE,mBACvDD,EAAsBE,WAAaF,EAAKG,KAG3C,SAASC,EAAcC,EAAsBC,OAC9CC,EAAUrB,EAAUoB,OACpBE,EAAI,QAEDA,EAAID,EAAQE,OAAQ,OACnBC,EAASH,EAAQC,QAEnBH,EAASX,eAAegB,GAC1BH,EAAUA,EAAQI,OAAON,EAASK,WAI/BH,EAGT,SAASK,EAAeP,MAClBA,EAASQ,aACL,IAAIhB,MAAM,+DAGlBF,OAAOmB,KAAKT,GAAUU,QAASC,UACvBC,EAAWD,IAAUX,EAASW,IAC/B5B,MAAMC,QAAQgB,EAASW,OACY,IAApCX,EAASW,GAAOE,QAAQF,KAAwD,IAAvCX,EAASW,GAAOE,QAAQ,cAGjED,QACI,IAAIpB,MAAO,sCAAqCmB,QAAYX,EAASW,QAK1E,SAASG,EAAoBd,MACL,eAAzBe,QAAQC,IAAIC,SACdV,EAAeP,UAGTK,GAA8BN,EAAcC,EAAUK,GAGhE,SAASa,EAAeC,EAAWC,EAAaC,OACzC,IAAIlB,EAAIkB,EAAOlB,EAAIiB,EAAOhB,OAAQD,IACrCgB,EAAKG,KAAKF,EAAOjB,IAId,SAASoB,EACdC,EACAC,OAEKD,IAAUA,EAAMpB,cACZqB,GAAgB,OAGpBA,IAAiBA,EAAarB,cAC1BoB,GAAS,OAGdrB,EAAI,MACJuB,EAAI,QACFC,EAAc,SAEbxB,EAAIqB,EAAMpB,QAAUsB,EAAID,EAAarB,UACtCoB,EAAMrB,GAAGyB,SAAWH,EAAaC,GAAGE,SAAU,CAChDD,EAAOL,KAAKE,EAAMrB,IAClBA,QACK,CACLwB,EAAOL,KAAKG,EAAaC,IACzBA,IAIJR,EAAYS,EAAQH,EAAOrB,GAC3Be,EAAYS,EAAQF,EAAcC,UAE3BC,EAGF,SAASE,EAAmBC,EAAgBC,EAAQC,OACrDlD,EAAQgD,EAAIG,IAAIF,OAEfjD,EAAO,CACVA,EAAQkD,IACRF,EAAII,IAAIH,EAAKjD,UAGRA,EAGF,MAAMqD,EAAeC,GAASA,ECnIrC,SAASC,EAAiCC,EAAyBC,MAC7DxD,MAAMC,QAAQsD,EAAKE,UAAYF,EAAKE,OAAOpC,aACvC,IAAIZ,MAAM,wEAGd8C,EAAKE,SAAWD,EAAQE,mBACpB,IAAIjD,MAAM,mFAGd8C,EAAKI,aAAeH,EAAQI,wBACxB,IAAInD,MAAM,yFAWb,MAAMoD,EAYXhD,YACE0C,EACAC,EACAX,EAAmB,QAdbiB,cACAC,SAeNT,EAASC,EAAMC,QAEVlC,OAASkC,EAAQQ,cAAcT,EAAKjC,aACpCX,QAAU4C,EAAK5C,aACfsD,WAAaV,EAAKU,cAClBN,WAAaJ,EAAKI,gBAClBO,OAASX,EAAKW,YACdT,OAASF,EAAKE,OAAS3D,EAAUyD,EAAKE,aAAUU,OAChDtB,SAAWA,OACXuB,EAAWZ,aAIZa,KAAKV,aAAeU,KAAKP,OACtBA,EAAmBO,KAAKD,EAASR,kBAAmBS,KAAKV,mBAGzDU,KAAKP,aAIRO,KAAKZ,SAAWY,KAAKN,OAClBA,EAAcM,KAAKD,EAASV,aAAcW,KAAKZ,eAG/CY,KAAKN,mBAILM,KAAKC,EAAuBD,KAAKC,EAAqBC,SAAMJ,EAGrEK,kBAAkBnE,OACXgE,KAAKV,kBACD,SAGJtD,GAA4B,kBAAXA,GAAyC,oBAAXA,SAC1CgE,KAAKJ,gBAGRI,KAAKC,EAAsBjE,GAGpCoE,aAAaC,OACNL,KAAKZ,cACD,SAGJiB,SACKL,KAAKJ,gBAGRI,KAAKM,EAAiBD,ICnG1B,MAAME,EAAa,CAAI7E,EAAU8E,WAChCC,EAAO,CAAE/E,MAAAA,EAAO8E,KAAAA,EAAME,KAAM,SAE9BF,EACFA,EAAKE,KAAOD,SAGPA,GAGF,MAAME,EAAcF,OACrBA,EAAKC,KACPD,EAAKC,KAAKF,KAAOC,EAAKD,QAGpBC,EAAKD,KACPC,EAAKD,KAAKE,KAAOD,EAAKC,KAGxBD,EAAKC,KAAOD,EAAKD,KAAO,MCwC1B,MAAMI,EAAqB,MACzBC,MAAO,GACPtC,OAAQ,QAEV,MAAMuC,EAAsB,IAAM,IAAIC,IACtC,MAAMC,EAAU,CAACC,EAAY/B,SACtB+B,EAAMC,GAAqBhC,EAAKE,OACnC6B,EAAMC,EAAoB,MAevB,MAAMC,EAUX3E,YACEqE,EAAsC,GACtC1B,EAA2C,SAXrC+B,EAA6B,WAC7BE,EAAwB,IAAIL,SAY7BM,EAAe,CAClB9B,kBAAmBJ,EAAQI,kBAC3BF,aAAcF,EAAQE,aACtBM,cAAeR,EAAQQ,eAAiBZ,QAErC1C,kBAAoB8C,EAAQ9C,mBAAqBA,OACjDiF,EAAST,OACTU,EAAgBvB,KAAKwB,EAAeX,sBAIlCb,KAAKsB,EAGdG,OAAOZ,SACCa,EAAQ,CACZb,MAAAA,EACAc,QAAS3B,KACThC,OAAQgC,WAGL4B,EAAM,SAAUF,QAChBJ,EAAST,OACTU,EAAgBvB,KAAKwB,EAAeX,QACpCe,EAAM,UAAWF,UAEf1B,KAGDwB,EAAeK,SACfC,EAAyC,IAAIf,QAE9C,IAAIhE,EAAI8E,EAAS7E,OAAS,EAAGD,GAAK,EAAGA,IAAK,OACvCyB,EAAWqD,EAAS7E,OAASD,EAAI,QACjCmC,EAAO,IAAIM,EAAKqC,EAAS9E,GAAIiD,KAAKqB,EAAc7C,SAChD1B,EAAUrB,EAAUyD,EAAKjC,cACzB8E,EAAWtG,EAAUyD,EAAK5C,SAAW,OAC3C0E,EAAQhB,KAAMd,OAET,IAAI8C,EAAI,EAAGA,EAAID,EAAS/E,OAAQgF,IAAK,OAClCC,EAAexD,EAAaqD,EAAcC,EAASC,GAAIlB,OAExD,IAAIxC,EAAI,EAAGA,EAAIxB,EAAQE,OAAQsB,IAClCG,EAAawD,EAAcnF,EAAQwB,GAAIsC,GAAoBC,MAAM3C,KAAKgB,WAKrE4C,EAITI,iBAAiBjF,EAAgBkF,SACzBF,EAAexD,EAAauB,KAAKuB,EAAeY,EAAarB,SAC7DsB,EAAc3D,EAAawD,EAAchF,EAAQ2D,MAEnDwB,EAAY7D,cACP6D,EAAYvB,YAGfwB,EAAyB,WAAXpF,GAAuBgF,EAAaK,IAAI,UACxDL,EAAapD,IAAI,UAAWgC,WAC5Bf,MACAe,EAAQ1C,EAAiBiE,EAAYvB,MAAOwB,MAE5B,QAAhBF,EACFtB,EAAQ1C,EAAiB0C,EAAQb,KAAakC,iBAAiBjF,EAAQ,QAGzEmF,EAAYvB,MAAQA,EACpBuB,EAAY7D,OAAS,YAEdsC,EAIT0B,SAAStF,EAAgBkF,EAA2B9B,SAC5CQ,EAAgCb,KAAakC,iBAAiBjF,EAAQkF,MAExE9B,GAA0B,kBAAVA,QACZ,IAAIjE,MAAM,qJAGb4D,KAAKkB,SACDL,SAGFA,EAAM2B,OAAOtD,GAAQA,EAAKkB,aAAaC,IAGhDoC,GACEf,EACAgB,SAEMC,EAAO3C,KAAKoB,EAAQvC,IAAI6C,IAAU,WAClCjB,EAAOF,EAAWmC,EAASC,QAC5BvB,EAAQtC,IAAI4C,EAAOjB,SAEjB,SACAA,EAAKC,OAASD,EAAKD,MAAQR,KAAKoB,EAAQvC,IAAI6C,KAAWjB,OACrDW,EAAQwB,OAAOlB,QAEpBf,EAAWF,IAKTmB,EAAuClF,EAASmG,OAClDC,EAAU9C,KAAKoB,EAAQvC,IAAInC,IAAS,WACrB,OAAZoG,EAAkB,OACjBtC,EAAOsC,EAAQtC,KACrBsC,EAAQpH,MAAMmH,GACdC,EAAUtC,IC5MT,MAAMuC,UAGH5B,EACR6B,OAAOC,SACC/D,EAAOc,KAAKkD,mBAAmBD,WAC5B/D,IAASA,EAAKU,SAIzBsD,gBAAgBjG,EAAgBX,EAAmB+D,SAC3CQ,EAASb,KAAauC,SAAStF,EAAQ+C,KAAK3D,kBAAkBC,GAAU+D,OAEzE,IAAItD,EAAI,EAAGC,EAAS6D,EAAM7D,OAAQD,EAAIC,EAAQD,OAC7C8D,EAAM9D,GAAGoD,kBAAkB7D,UACtBuE,EAAM9D,UAIV,KAGToG,UAAUF,UACAjD,KAAKgD,OAAOC,ICIxB,MAAMG,EAAsB,CAC1BC,IAAAA,EACAC,IAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,KAAAA,EACAC,MAAAA,EACAC,OAAAA,EACAC,SAAAA,EACAC,WAAAA,EACAC,QAAAA,GAEF,MAAMC,EAAsB,CAC1BC,GAAAA,EACAC,GAAAA,EACAC,GAAAA,EACAC,IAAAA,EACAC,GAAAA,EACAC,IAAAA,EACAC,GAAIC,EACJC,IAAAA,EACAC,IAAAA,EACAC,KAAAA,EACAC,MAAAA,EACAC,UAAAA,EACAC,OAAAA,EACAC,IAAAA,SAeWC,EAA0B,CAACC,EAAcC,EAAclG,IAAYmG,mBACzElC,EAAwBgC,oBACxBjB,EAAwBkB,GAC7BlG,SAGWoG,EAAoBD,EAAclC,EAAqBe,GCrFpE,MAAMqB,EAAuB,uBAC7B,MAAMC,GAAa,aACnB,MAAMC,GAAe,MACrB,MAAMC,GAAa,MAEnB,SAASC,GAAoBC,EAAe5E,EAAe6E,SACnDC,EAA2B,MAAdD,EAAO,IAA2B,MAAbD,EAAM,IAA0C,MAA5BA,EAAMA,EAAM7I,OAAS,GAC7E,IACA,UACEgJ,GAAmC,IAAzBH,EAAMpI,QAAQ,MAAe,OAAS,UAChDwI,EAAUJ,EAAMK,QAAQP,GAAY,QACvCO,QAAQR,GAAcM,EAAUD,UAE5B9E,EAAQ4E,EAAM7I,SAAW8I,EAAO9I,OAAU,MAAKiJ,MAAcA,EAGtE,SAASE,GAAaN,EAAe5E,EAAe6E,MACpC,MAAVD,IAAwC,MAAtBC,EAAO7E,EAAQ,IAAoC,MAAtB6E,EAAO7E,EAAQ,WACzD4E,QAGD,KAAIA,IAGd,SAASO,GAAchH,SACfiH,EAAWjH,EAAOV,IAAI2B,GAASA,EAClC6F,QAAQV,EAAsBW,IAC9BD,QAAQT,GAAYG,WACjBK,EAAUI,EAASrJ,OAAS,EAAK,MAAKqJ,EAASC,KAAK,QAAUD,EAAS,UAEtE,IAAIE,OAAQ,IAAGN,YAGXO,GAAqCpH,QAC5C6G,SAEI5F,OACiB,qBAAZ4F,EACTA,EAAU7G,EAAOqH,MAAMC,IAAyB,IAApBA,EAAEjJ,QAAQ,MAClC,KACA2I,GAAchH,UAGD,OAAZ6G,GACwB,IAA3B7G,EAAO3B,QAAQ4C,GACf4F,EAAQU,KAAKtG,KCrCd,MAAMuG,WAGH7D,EACRvG,YAAYqE,EAA6B,GAAI1B,EAAgC,UACrE0B,iBACJtB,kBAAmBgG,EACnBlG,aAAcmH,IACXrH,KCJT,MAAM0H,GAGJrK,YAAY0C,QACL4H,EAAQ5H,EAGf6H,QAAQlH,QACDiH,EAAMjH,OAASA,SACbG,MA8CJ,MAAMgH,GAOXxK,YAAYyK,QAHLpG,MAAwB,QAIxBqG,EAAeD,QACdE,EAAOnH,KACbmH,EAAKnE,IAAMmE,EAAKnE,IAAIoE,KAAKD,GACzBA,EAAKhE,OAASgE,EAAKhE,OAAOiE,KAAKD,GAC/BA,EAAKE,MAAQF,EAAKE,MAAMD,KAAKD,GAY/BnE,IACE/F,EACAX,EACAgL,EACAhI,SAEMJ,EAAO,CAAEjC,OAAAA,MAEXX,EAAS,CACX4C,EAAK5C,QAAUA,KAEXX,MAAMC,QAAQ0L,IAAqD,kBAAvBA,EAC9CpI,EAAKE,OAASkI,OACT,GAAkC,qBAAvBA,EAChBpI,EAAKI,WAAagI,KAGM,qBAAfhI,EACTJ,EAAKI,WAAaA,OAIjBuB,MAAM3C,KAAKgB,UAET,IAAI2H,GAAY3H,GAYzBiE,OACElG,EACAX,EACAgL,EACAhI,SAEMiI,EAAWvH,KAAagD,IAAI/F,EAAQX,EAASgL,EAAoBhI,GACvEiI,EAAQT,EAAMlH,SAAW,YAClB2H,EAGTF,MAAMlI,UACG,IAAIa,KAAKkH,EAAalH,KAAKa,MAAO1B,IAetC,SAASqI,GAEdC,EAAsCtI,SAChCoI,EAAU,IAAIP,GAAeJ,UAC7Bc,EAASD,EAAOF,EAAQvE,IAAKuE,EAAQpE,WAEvCuE,GAAiC,oBAAhBA,EAAOC,YACnBD,EAAOC,KAAK,IAAMJ,EAAQF,MAAMlI,WAGlCoI,EAAQF,MAAMlI,SCjKVyI,GAA0CC,GAAU,mBAAkBA,EAAM5K,eAAe4K,EAAM1F,eAE9G,MAAM2F,GAAc,SAASC,EAAoBC,QAC1CA,QAAUA,GAGjBF,GAAYG,UAAY/L,OAAOgM,OAAO9L,MAAM6L,WAErC,MAAME,WAA6CL,4BAS/BM,QAClBC,EAA8C,kBAAhBD,EAA2B,IAAMA,EAAcA,cAGlDzG,UACzB,IAAI3B,KAAK2B,GAGVnF,YAAYmF,SACZ,SAdDtB,kBAeAsB,QAAUA,KAEwB,oBAA5BvF,MAAMkM,kBAAkC,MAC5C5L,KAAO,iBACZN,MAAMkM,kBAAkBtI,KAAMA,KAAKxD,cAIvC+L,WAAWP,QACJA,QAAUA,SACRhI,KAGTwI,kBAAkBvF,SACV/D,EAAOc,KAAK2B,QAAQuB,mBAAmBD,MAEzC/D,IAASA,EAAKU,qBAIb3C,OAASgG,EAAK,QACd3G,QAAU2G,EAAK,QACfd,YAAcnC,KAAK2B,QAAQtF,kBAAkB4G,EAAK,SAClD5C,MAAQ4C,EAAK,SAEZpD,EAASX,EAAOA,EAAKW,OAAS,QAE/BmI,QAAUhI,KAAKgI,SAAWnI,GAAWG,KAAKxD,YAAoB6L,EAAqBrI,YAClFA,MA/CGmI,GAOJE,EAAuBT"}
{"version":3,"file":"index.mjs","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/structures/LinkedItem.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectType, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport const isSubjectType = (value: unknown): value is SubjectType => {\n const type = typeof value;\n return type === 'string' || type === 'function';\n};\n\nconst getSubjectClassName = (value: SubjectClass) => value.modelName || value.name;\nexport const getSubjectTypeName = (value: SubjectType) => {\n return typeof value === 'string' ? value : getSubjectClassName(value);\n};\n\nexport function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string {\n if (!subject) {\n return 'all';\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n return getSubjectClassName(subject.constructor as SubjectClass);\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n\nfunction copyArrayTo<T>(dest: T[], target: T[], start: number) {\n for (let i = start; i < target.length; i++) {\n dest.push(target[i]);\n }\n}\n\nexport function mergePrioritized<T extends { priority: number }>(\n array?: T[],\n anotherArray?: T[]\n): T[] {\n if (!array || !array.length) {\n return anotherArray || [];\n }\n\n if (!anotherArray || !anotherArray.length) {\n return array || [];\n }\n\n let i = 0;\n let j = 0;\n const merged: T[] = [];\n\n while (i < array.length && j < anotherArray.length) {\n if (array[i].priority < anotherArray[j].priority) {\n merged.push(array[i]);\n i++;\n } else {\n merged.push(anotherArray[j]);\n j++;\n }\n }\n\n copyArrayTo(merged, array, i);\n copyArrayTo(merged, anotherArray, j);\n\n return merged;\n}\n\nexport function getOrDefault<K, V>(map: Map<K, V>, key: K, defaultValue: () => V) {\n let value = map.get(key);\n\n if (!value) {\n value = defaultValue();\n map.set(key, value);\n }\n\n return value;\n}\n\nexport const identity = <T>(x: T) => x;\n","import { wrapArray, isSubjectType } from './utils';\nimport {\n MatchConditions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n} from './types';\nimport { RawRule, RawRuleFrom } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nfunction validate<A extends Abilities, C>(rule: RawRuleFrom<A, C>, options: RuleOptions<A, C>) {\n if (Array.isArray(rule.fields) && !rule.fields.length) {\n throw new Error('`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa');\n }\n\n if (rule.fields && !options.fieldMatcher) {\n throw new Error('You need to pass \"fieldMatcher\" option in order to restrict access by fields');\n }\n\n if (rule.conditions && !options.conditionsMatcher) {\n throw new Error('You need to pass \"conditionsMatcher\" option in order to restrict access by conditions');\n }\n}\n\ntype ResolveAction<T> = (action: T | T[]) => T | T[];\nexport interface RuleOptions<A extends Abilities, Conditions> {\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction: ResolveAction<Normalize<A>[0]>\n}\n\nexport class Rule<A extends Abilities, C> {\n private _matchConditions: MatchConditions | undefined;\n private _matchField: MatchField<string> | undefined;\n private readonly _options!: RuleOptions<A, C>;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n public readonly priority!: number;\n\n constructor(\n rule: RawRule<ToAbilityTypes<A>, C>,\n options: RuleOptions<A, C>,\n priority: number = 0\n ) {\n validate(rule, options);\n\n this.action = options.resolveAction(rule.action);\n this.subject = rule.subject!;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = rule.fields ? wrapArray(rule.fields) : undefined;\n this.priority = priority;\n this._options = options;\n }\n\n private get _lazyMatchConditions() {\n if (this.conditions && !this._matchConditions) {\n this._matchConditions = this._options.conditionsMatcher!(this.conditions);\n }\n\n return this._matchConditions;\n }\n\n private get _lazyMatchField() {\n if (this.fields && !this._matchField) {\n this._matchField = this._options.fieldMatcher!(this.fields);\n }\n\n return this._matchField;\n }\n\n get ast() {\n return this._lazyMatchConditions ? this._lazyMatchConditions.ast : undefined;\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this.conditions) {\n return true;\n }\n\n if (!object || isSubjectType(object)) {\n return !this.inverted;\n }\n\n return this._lazyMatchConditions!(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this.fields) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._lazyMatchField!(field);\n }\n}\n","export interface LinkedItem<T> {\n next: LinkedItem<T> | null\n prev: LinkedItem<T> | null\n readonly value: T\n}\n\nexport const linkedItem = <T>(value: T, prev: LinkedItem<T>['prev']) => {\n const item = { value, prev, next: null };\n\n if (prev) {\n prev.next = item;\n }\n\n return item;\n};\n\nexport const unlinkItem = (item: LinkedItem<any>) => {\n if (item.next) {\n item.next.prev = item.prev;\n }\n\n if (item.prev) {\n item.prev.next = item.next;\n }\n\n item.next = item.prev = null; // eslint-disable-line\n};\n","import { Rule, RuleOptions } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n Abilities,\n Normalize,\n SubjectType,\n AbilityParameters,\n AbilityTuple,\n ExtractSubjectType\n} from './types';\nimport { wrapArray, detectSubjectType, mergePrioritized, getOrDefault, identity, isSubjectType } from './utils';\nimport { LinkedItem, linkedItem, unlinkItem } from './structures/LinkedItem';\n\nexport interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {\n detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string\n}\n\ndeclare const $abilities: unique symbol;\ndeclare const $conditions: unique symbol;\ninterface WithGenerics {\n [$abilities]: any\n [$conditions]: any\n}\nexport type Public<T extends WithGenerics> = { [K in keyof T]: T[K] };\nexport type Generics<T extends WithGenerics> = {\n abilities: T[typeof $abilities],\n conditions: T[typeof $conditions]\n};\n\nexport type RuleOf<T extends WithGenerics> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends WithGenerics> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends WithGenerics> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\ninterface AbilityEvent<T extends WithGenerics> {\n target: T\n /** @deprecated use \"target\" property instead */\n ability: T\n}\n\nexport interface UpdateEvent<T extends WithGenerics> extends AbilityEvent<T> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<\n T extends WithGenerics,\n K extends keyof EventsMap<T> = keyof EventsMap<T>\n> = Map<K, LinkedItem<EventHandler<EventsMap<T>[K]>> | null>;\n\ninterface EventsMap<T extends WithGenerics> {\n update: UpdateEvent<T>\n updated: UpdateEvent<T>\n}\n\ntype IndexTree<A extends Abilities, C> = Map<SubjectType, Map<string, {\n rules: Rule<A, C>[],\n merged: boolean\n}>>;\n\nexport type Unsubscribe = () => void;\n\nconst defaultActionEntry = () => ({\n rules: [] as unknown as Rule<any, any>[],\n merged: false\n});\nconst defaultSubjectEntry = () => new Map<string, ReturnType<typeof defaultActionEntry>>();\nconst analyze = (index: any, rule: Rule<any, any>) => {\n if (!index._hasPerFieldRules && rule.fields) {\n index._hasPerFieldRules = true;\n }\n};\n\ntype AbilitySubjectTypeParameters<T extends Abilities, IncludeField extends boolean = true> =\n AbilityParameters<\n T,\n T extends AbilityTuple\n ? IncludeField extends true\n ? (action: T[0], subject: ExtractSubjectType<T[1]>, field?: string) => 0\n : (action: T[0], subject: ExtractSubjectType<T[1]>) => 0\n : never,\n (action: Extract<T, string>) => 0\n >;\n\nexport class RuleIndex<A extends Abilities, Conditions> {\n private _hasPerFieldRules: boolean = false;\n private _events: Events<this> = new Map();\n private _indexedRules!: IndexTree<A, Conditions>;\n private _rules!: RawRuleFrom<A, Conditions>[];\n private readonly _ruleOptions!: RuleOptions<A, Conditions>;\n private readonly _detectSubjectType!: Required<RuleIndexOptions<A, Conditions>>['detectSubjectType'];\n readonly [$abilities]!: A;\n readonly [$conditions]!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {}\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n this._detectSubjectType = options.detectSubjectType || detectSubjectType;\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n }\n\n get rules() {\n return this._rules;\n }\n\n detectSubjectType(object?: Normalize<A>[1]) {\n return isSubjectType(object)\n ? object\n : this._detectSubjectType(object as Exclude<Normalize<A>[1], SubjectType>);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): Public<this> {\n const event = {\n rules,\n ability: this,\n target: this\n } as unknown as UpdateEvent<this>;\n\n this._emit('update', event);\n this._rules = rules;\n this._indexedRules = this._buildIndexFor(rules);\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(rawRules: RawRuleFrom<A, Conditions>[]) {\n const indexedRules: IndexTree<A, Conditions> = new Map();\n\n for (let i = rawRules.length - 1; i >= 0; i--) {\n const priority = rawRules.length - i - 1;\n const rule = new Rule(rawRules[i], this._ruleOptions, priority);\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject || 'all');\n analyze(this, rule);\n\n for (let k = 0; k < subjects.length; k++) {\n const subjectRules = getOrDefault(indexedRules, subjects[k], defaultSubjectEntry);\n\n for (let j = 0; j < actions.length; j++) {\n getOrDefault(subjectRules, actions[j], defaultActionEntry).rules.push(rule);\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: AbilitySubjectTypeParameters<A, false>): Rule<A, Conditions>[]\n possibleRulesFor(action: string, subjectType: SubjectType = 'all'): Rule<A, Conditions>[] {\n if (!isSubjectType(subjectType)) {\n throw new Error('\"possibleRulesFor\" accepts only subject types (i.e., string or class) as the 2nd parameter');\n }\n\n const subjectRules = getOrDefault(this._indexedRules, subjectType, defaultSubjectEntry);\n const actionRules = getOrDefault(subjectRules, action, defaultActionEntry);\n\n if (actionRules.merged) {\n return actionRules.rules;\n }\n\n const manageRules = action !== 'manage' && subjectRules.has('manage')\n ? subjectRules.get('manage')!.rules\n : undefined;\n let rules = mergePrioritized(actionRules.rules, manageRules);\n\n if (subjectType !== 'all') {\n rules = mergePrioritized(rules, (this as any).possibleRulesFor(action, 'all'));\n }\n\n actionRules.rules = rules;\n actionRules.merged = true;\n\n return rules;\n }\n\n rulesFor(...args: AbilitySubjectTypeParameters<A>): Rule<A, Conditions>[]\n rulesFor(action: string, subjectType?: SubjectType, field?: string): Rule<A, Conditions>[] {\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subjectType);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this>>(\n event: T,\n handler: EventHandler<EventsMap<Public<this>>[T]>\n ): Unsubscribe {\n const head = this._events.get(event) || null;\n const item = linkedItem(handler, head);\n this._events.set(event, item);\n\n return () => {\n if (!item.next && !item.prev && this._events.get(event) === item) {\n this._events.delete(event);\n } else {\n unlinkItem(item);\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this>>(name: T, payload: EventsMap<this>[T]) {\n let current = this._events.get(name) || null;\n while (current !== null) {\n const prev = current.prev;\n current.value(payload);\n current = prev;\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, Public } from './RuleIndex';\nimport { Abilities, CanParameters, Subject } from './types';\nimport { Rule } from './Rule';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = Public<PureAbility<any, any>>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (...args: any[]) => T;\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown\n> extends RuleIndex<A, Conditions> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>): Rule<A, Conditions> | null\n relevantRuleFor(action: string, subject?: Subject, field?: string): Rule<A, Conditions> | null {\n const subjectType = this.detectSubjectType(subject);\n const rules = (this as any).rulesFor(action, subjectType, field);\n\n for (let i = 0, length = rules.length; i < length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n $eq,\n eq,\n $ne,\n ne,\n $lt,\n lt,\n $lte,\n lte,\n $gt,\n gt,\n $gte,\n gte,\n $in,\n within,\n $nin,\n nin,\n $all,\n all,\n $size,\n size,\n $regex,\n $options,\n regex,\n $elemMatch,\n elemMatch,\n $exists,\n exists,\n and,\n createFactory,\n BuildMongoQuery,\n DefaultOperators,\n} from '@ucast/mongo2js';\nimport { ConditionsMatcher, AnyObject } from '../types';\nimport { Container, GenericFactory } from '../hkt';\n\nconst defaultInstructions = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $options,\n $elemMatch,\n $exists,\n};\nconst defaultInterpreters = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n in: within,\n nin,\n all,\n size,\n regex,\n elemMatch,\n exists,\n and,\n};\n\ninterface MongoQueryFactory extends GenericFactory {\n produce: MongoQuery<this[0]>\n}\n\ntype MergeUnion<T extends {}, Keys extends keyof T = keyof T> = { [K in Keys]: T[K] };\nexport type MongoQuery<T = AnyObject> = BuildMongoQuery<MergeUnion<T>, {\n toplevel: {},\n field: Pick<DefaultOperators<MergeUnion<T>>['field'], keyof typeof defaultInstructions>\n}> & Container<MongoQueryFactory>;\n\ntype MongoQueryMatcherFactory =\n (...args: Partial<Parameters<typeof createFactory>>) => ConditionsMatcher<MongoQuery>;\nexport const buildMongoQueryMatcher = ((instructions, interpreters, options) => createFactory(\n { ...defaultInstructions, ...instructions },\n { ...defaultInterpreters, ...interpreters },\n options\n)) as MongoQueryMatcherFactory;\n\nexport const mongoQueryMatcher = createFactory(defaultInstructions, defaultInterpreters);\nexport type {\n MongoQueryFieldOperators,\n MongoQueryTopLevelOperators,\n MongoQueryOperators,\n} from '@ucast/mongo2js';\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { Public } from './RuleIndex';\nimport { RawRuleFrom } from './RawRule';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { fieldPatternMatcher } from './matchers/field';\n\n/**\n * @deprecated use `createMongoAbility` function instead\n */\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery = MongoQuery\n> extends PureAbility<A, C> {\n constructor(rules: RawRuleFrom<A, C>[] = [], options: AbilityOptions<A, C> = {}) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Public<Ability<any, MongoQuery>>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n TaggedInterface,\n Normalize,\n SubjectClass,\n AnyObject,\n} from './types';\nimport { ProduceGeneric } from './hkt';\n\nclass RuleBuilder<T extends AnyAbility> {\n public _rule!: RawRuleOf<T>;\n\n constructor(rule: RawRuleOf<T>) {\n this._rule = rule;\n }\n\n because(reason: string): this {\n this._rule.reason = reason;\n return this;\n }\n}\n\ntype ExtractWithDefault<T, U, D = never> = T extends U ? T : D;\ntype InstanceOf<T extends AnyAbility, S extends SubjectType> = S extends SubjectClass\n ? InstanceType<S>\n : ExtractWithDefault<Normalize<Generics<T>['abilities']>[1], TaggedInterface<Extract<S, string>>, AnyObject>;\ntype ConditionsOf<T extends AnyAbility, I extends {}> =\n ProduceGeneric<Generics<T>['conditions'], I>;\ntype ActionFrom<T extends AbilityTuple, S extends SubjectType> = T extends any\n ? S extends T[1] ? T[0] : never\n : never;\ntype ActionOf<T extends AnyAbility, S extends SubjectType> = ActionFrom<Generics<T>['abilities'], S>;\ntype SubjectTypeOf<T extends AnyAbility> = E<Normalize<Generics<T>['abilities']>[1]>;\n\ntype SimpleCanParams<T extends AnyAbility> = Parameters<(\n action: Generics<T>['abilities'] | Generics<T>['abilities'][]\n) => 0>;\ntype BuilderCanParameters<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\n\ntype BuilderCanParametersWithFields<\n S extends SubjectType,\n I extends InstanceOf<T, S>,\n F extends string,\n T extends AnyAbility\n> = Generics<T>['abilities'] extends AbilityTuple\n ? Parameters<(\n action: ActionOf<T, S> | ActionOf<T, S>[],\n subject: S | S[],\n fields?: F | F[],\n conditions?: ConditionsOf<T, I>\n ) => 0>\n : SimpleCanParams<T>;\ntype Keys<T> = string & keyof T;\n\nexport class AbilityBuilder<\n U extends AbilityClass<AnyAbility>,\n T extends InstanceType<U> = InstanceType<U>\n> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: U;\n\n constructor(AbilityType: U) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n can<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions']\n ): RuleBuilder<T> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot<\n I extends InstanceOf<T, S>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParameters<S, I, T>): RuleBuilder<T>\n cannot<\n I extends InstanceOf<T, S>,\n F extends string = Keys<I>,\n S extends SubjectTypeOf<T> = SubjectTypeOf<T>\n >(...args: BuilderCanParametersWithFields<S, I, F | Keys<I>, T>): RuleBuilder<T>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<T> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder._rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>) {\n return new this._AbilityType(this.rules, options) as T;\n }\n}\n\ntype DSL<T extends AnyAbility, R> = (\n can: AbilityBuilder<AbilityClass<T>>['can'],\n cannot: AbilityBuilder<AbilityClass<T>>['cannot']\n) => R;\n\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, Promise<void>>, options?: AbilityOptionsOf<T>): Promise<T>;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void>, options?: AbilityOptionsOf<T>): T;\nexport function defineAbility<\n T extends AnyMongoAbility\n>(define: DSL<T, void | Promise<void>>, options?: AbilityOptionsOf<T>): T | Promise<T> {\n const builder = new AbilityBuilder(Ability as unknown as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n if (result && typeof result.then === 'function') {\n return result.then(() => builder.build(options));\n }\n\n return builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\nimport { getSubjectTypeName } from './utils';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability!: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<T extends AnyAbility>(ability: T) {\n return new this(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = getSubjectTypeName(this.ability.detectSubjectType(args[1]));\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","isSubjectType","getSubjectClassName","modelName","name","getSubjectTypeName","detectSubjectType","subject","constructor","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","createAliasResolver","process","env","NODE_ENV","copyArrayTo","dest","target","start","push","mergePrioritized","array","anotherArray","j","merged","priority","getOrDefault","map","key","defaultValue","get","set","identity","x","validate","rule","options","fields","fieldMatcher","conditions","conditionsMatcher","Rule","_matchConditions","_matchField","resolveAction","inverted","reason","undefined","_options","this","_lazyMatchConditions","ast","matchesConditions","matchesField","field","_lazyMatchField","linkedItem","prev","item","next","unlinkItem","defaultActionEntry","rules","defaultSubjectEntry","Map","analyze","index","_hasPerFieldRules","RuleIndex","_events","_ruleOptions","_detectSubjectType","_rules","_indexedRules","_buildIndexFor","update","event","ability","_emit","rawRules","indexedRules","subjects","k","subjectRules","possibleRulesFor","subjectType","actionRules","manageRules","has","rulesFor","filter","on","handler","head","delete","payload","current","PureAbility","can","args","relevantRuleFor","cannot","defaultInstructions","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$options","$elemMatch","$exists","defaultInterpreters","eq","ne","lt","lte","gt","gte","in","within","nin","all","size","regex","elemMatch","exists","and","buildMongoQueryMatcher","instructions","interpreters","createFactory","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","_rule","because","AbilityBuilder","AbilityType","_AbilityType","self","bind","build","conditionsOrFields","builder","defineAbility","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","create","ForbiddenError","messageOrFn","_defaultErrorMessage","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"}

@@ -6,3 +6,3 @@ import { Rule, RuleOptions } from './Rule';

export interface RuleIndexOptions<A extends Abilities, C> extends Partial<RuleOptions<A, C>> {
detectSubjectType?(subject?: Normalize<A>[1]): string;
detectSubjectType?(subject?: Exclude<Normalize<A>[1], SubjectType>): string;
}

@@ -47,3 +47,3 @@ declare const $abilities: unique symbol;

private readonly _ruleOptions;
readonly detectSubjectType: Exclude<RuleIndexOptions<A, Conditions>['detectSubjectType'], undefined>;
private readonly _detectSubjectType;
readonly [$abilities]: A;

@@ -53,2 +53,3 @@ readonly [$conditions]: Conditions;

get rules(): (import("./types").ToAbilityTypes<A> extends import("./types").AbilityTupleType<string, SubjectType> ? import("./RawRule").SubjectRawRule<(import("./types").AbilityTupleType<string, SubjectType> & import("./types").ToAbilityTypes<A>)[0], (import("./types").AbilityTupleType<string, SubjectType> & import("./types").ToAbilityTypes<A>)[1], Conditions> : import("./RawRule").ClaimRawRule<Extract<import("./types").ToAbilityTypes<A>, string>>)[];
detectSubjectType(object?: Normalize<A>[1]): SubjectType;
update(rules: RawRuleFrom<A, Conditions>[]): Public<this>;

@@ -55,0 +56,0 @@ private _buildIndexFor;

@@ -1,6 +0,8 @@

import { AnyObject, Subject, ForcedSubject, AliasesMap } from './types';
import { AnyObject, Subject, SubjectType, ForcedSubject, AliasesMap } from './types';
export declare function wrapArray<T>(value: T[] | T): T[];
export declare function setByPath(object: AnyObject, path: string, value: unknown): void;
export declare function setSubjectType<T extends string, U extends Record<PropertyKey, any>>(type: T, object: U): U & ForcedSubject<T>;
export declare function detectSubjectType<T extends Subject>(subject?: T): string;
export declare const isSubjectType: (value: unknown) => value is SubjectType;
export declare const getSubjectTypeName: (value: SubjectType) => string;
export declare function detectSubjectType(subject?: Exclude<Subject, SubjectType>): string;
export declare function expandActions(aliasMap: AliasesMap, rawActions: string | string[]): string[];

@@ -7,0 +9,0 @@ export declare function createAliasResolver(aliasMap: AliasesMap): (action: string | string[]) => string[];

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

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

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

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

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

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

@@ -19,15 +19,2 @@ # [CASL Ability](https://stalniy.github.io/casl/) [![@casl/ability NPM version](https://badge.fury.io/js/%40casl%2Fability.svg)](https://badge.fury.io/js/%40casl%2Fability) [![](https://img.shields.io/npm/dm/%40casl%2Fability.svg)](https://www.npmjs.com/package/%40casl%2Fability) [![CASL Documentation](https://img.shields.io/badge/documentation-available-brightgreen.svg)](https://stalniy.github.io/casl/) [![CASL Join the chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/stalniy-casl/casl)

CASL operates on the abilities level, that is what a user can actually do in the application. An ability itself depends on the 4 parameters (last 3 are optional):
1. User Action\
Describes what user can actually do in the app. User action is a word (usually a verb) which depends on the business logic (e.g., `prolong`, `read`). Very often it will be a list of words from CRUD - `create`, `read`, `update` and `delete`.
2. Subject\
The subject or subject type which you want to check user action on. Usually this is a business (or domain) entity name (e.g., `Subscription`, `BlogPost`, `User`).
3. Conditions\
An object or function which restricts user action only to matched subjects. This is useful when you need to give a permission on resources created by a user (e.g., to allow user to update and delete own `BlogPost`)
4. Fields\
Can be used to restrict user action only to matched subject's fields (e.g., to allow moderator to update `hidden` field of `BlogPost` but not update `description` or `title`)
Using CASL you can describe abilities using regular and inverted rules. Let's see how
**Note**: all the examples below are written in ES6 using ES modules but CASL also has a sophisticated support for TypeScript, read [CASL TypeScript support][typescript-support] for details.

@@ -67,4 +54,2 @@

**Note**: you can use class instead of string as a subject type (e.g., `can('read', BlogPost)`)
And yes, `Ability` class allow you to use some MongoDB operators to define conditions. Don't worry if you don't know MongoDB, it's not required and explained in details in [Defining Abilities][define-abilities]

@@ -93,4 +78,2 @@

**Note**: you can use class instead of string as a subject type (e.g., `ability.can('read', BlogPost)`)
Of course, you are not restricted to use only class instances in order to check permissions on objects. See [Introduction][intro] for the detailed explanation.

@@ -97,0 +80,0 @@