"use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@ucast/mongo2js");function e(t){return Array.isArray(t)?t:[t]}const s=Object.hasOwn||Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);const i="__caslSubjectType__";function r(t,e){if(e)if(!s(e,i))Object.defineProperty(e,i,{value:t});else if(t!==e[i])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${e[i]}`);return e}const n=t=>{const e=typeof t;return"string"===e||"function"===e};const o=t=>t.modelName||t.name;const c=t=>"string"===typeof t?t:o(t);function u(t){if(s(t,i))return t[i];return o(t.constructor)}function h(t,i,r){let n=e(i);let o=0;while(ot.concat(e);function f(t,e){if(e in t)throw new Error(`Cannot use "${e}" as an alias because it's reserved action.`);const s=Object.keys(t);const i=(t,s)=>{const i=l(t,s);if(i)throw new Error(`Detected cycle ${i} -> ${t.join(", ")}`);const r="string"===typeof s&&s===e||-1!==t.indexOf(e)||Array.isArray(s)&&-1!==s.indexOf(e);if(r)throw new Error(`Cannot make an alias to "${e}" because this is reserved action`);return t.concat(s)};for(let e=0;eh(t,e,a)}function p(t,e,s){for(let i=s;it;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 x{constructor(t,s,i=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.origin=t;this.fields=t.fields?e(t.fields):void 0;this.priority=i;this.t=s}i(){if(this.conditions&&!this.o)this.o=this.t.conditionsMatcher(this.conditions);return this.o}get ast(){const t=this.i();return t?t.ast:void 0}matchesConditions(t){if(!this.conditions)return true;if(!t||n(t))return!this.inverted;const e=this.i();return e(t)}matchesField(t){if(!this.fields)return true;if(!t)return!this.inverted;if(this.fields&&!this.u)this.u=this.t.fieldMatcher(this.fields);return this.u(t)}}function $(t,e){const s={value:t,prev:e,next:null};if(e)e.next=s;return s}function A(t){if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null}const M=t=>({value:t.value,prev:t.prev,next:t.next});const j=()=>({rules:[],merged:false});const E=()=>new Map;class v{constructor(t=[],e={}){this.h=false;this.l={conditionsMatcher:e.conditionsMatcher,fieldMatcher:e.fieldMatcher,resolveAction:e.resolveAction||w};this.p=e.anyAction||"manage";this.g=e.anySubjectType||"all";this.$=e.detectSubjectType||u;this.A=t;this.M=this.j(t)}get rules(){return this.A}detectSubjectType(t){if(n(t))return t;if(!t)return this.g;return this.$(t)}update(t){const e={rules:t,ability:this,target:this};this.v("update",e);this.A=t;this.M=this.j(t);this.v("updated",e);return this}j(t){const s=new Map;for(let i=t.length-1;i>=0;i--){const r=t.length-i-1;const n=new x(t[i],this.l,r);const o=e(n.action);const c=e(n.subject||this.g);if(!this.h&&n.fields)this.h=true;for(let t=0;tt.matchesField(s)))}actionsFor(t){if(!n(t))throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter');const e=new Set;const s=this.M.get(t);if(s)Array.from(s.keys()).forEach((t=>e.add(t)));const i=t!==this.g?this.M.get(this.g):void 0;if(i)Array.from(i.keys()).forEach((t=>e.add(t)));return Array.from(e)}on(t,e){this.m=this.m||new Map;const s=this.m;const i=s.get(t)||null;const r=$(e,i);s.set(t,r);return()=>{const e=s.get(t);if(!r.next&&!r.prev&&e===r)s.delete(t);else if(r===e)s.set(t,r.prev);A(r)}}v(t,e){if(!this.m)return;let s=this.m.get(t)||null;while(null!==s){const t=s.prev?M(s.prev):null;s.value(e);s=t}}}class PureAbility extends v{can(t,e,s){const i=this.relevantRuleFor(t,e,s);return!!i&&!i.inverted}relevantRuleFor(t,e,s){const i=this.detectSubjectType(e);const r=this.rulesFor(t,i,s);for(let t=0,s=r.length;tt.createFactory(Object.assign({},m,e),Object.assign({},_,s),i);const O=t.createFactory(m,_);const C=/[-/\\^$+?.()|[\]{}]/g;const R=/\.?\*+\.?/g;const P=/\*+/;const S=/\./g;function T(t,e,s){const i="*"===s[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const r=-1===t.indexOf("**")?"[^.]":".";const n=t.replace(S,"\\$&").replace(P,r+i);return e+t.length===s.length?`(?:${n})?`:n}function q(t,e,s){if("."===t&&("*"===s[e-1]||"*"===s[e+1]))return t;return`\\${t}`}function B(t){const e=t.map((t=>t.replace(C,q).replace(R,T)));const s=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${s}$`)}const z=t=>{let e;return s=>{if("undefined"===typeof e)e=t.every((t=>-1===t.indexOf("*")))?null:B(t);return null===e?-1!==t.indexOf(s):e.test(s)}};class Ability extends PureAbility{constructor(t=[],e={}){super(t,Object.assign({conditionsMatcher:O,fieldMatcher:z},e))}}function createMongoAbility(t=[],e={}){return new PureAbility(t,Object.assign({conditionsMatcher:O,fieldMatcher:z},e))}function isAbilityClass(t){return"function"===typeof t.prototype.possibleRulesFor}class D{constructor(t){this._=t}because(t){this._.reason=t;return this}}class AbilityBuilder{constructor(t){this.rules=[];this.F=t;this.can=(t,e,s,i)=>this.O(t,e,s,i,false);this.cannot=(t,e,s,i)=>this.O(t,e,s,i,true);this.build=t=>isAbilityClass(this.F)?new this.F(this.rules,t):this.F(this.rules,t)}O(t,e,s,i,r){const n={action:t};if(r)n.inverted=r;if(e){n.subject=e;if(Array.isArray(s)||"string"===typeof s)n.fields=s;else if("undefined"!==typeof s)n.conditions=s;if("undefined"!==typeof i)n.conditions=i}this.rules.push(n);return new D(n)}}function defineAbility(t,e){const s=new AbilityBuilder(createMongoAbility);const i=t(s.can,s.cannot);if(i&&"function"===typeof i.then)return i.then((()=>s.build(e)));return s.build(e)}const Y=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const k=function t(e){this.message=e};k.prototype=Object.create(Error.prototype);class ForbiddenError extends k{static setDefaultMessage(t){this.C="string"===typeof t?()=>t:t}static from(t){return new this(t)}constructor(t){super("");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,e,s){const i=this.unlessCan(t,e,s);if(i)throw i}unlessCan(t,e,s){const i=this.ability.relevantRuleFor(t,e,s);if(i&&!i.inverted)return;this.action=t;this.subject=e;this.subjectType=c(this.ability.detectSubjectType(e));this.field=s;const r=i?i.reason:"";this.message=this.message||r||this.constructor.C(this);return this}}ForbiddenError.C=Y;var I=Object.freeze({__proto__:null});exports.Ability=Ability;exports.AbilityBuilder=AbilityBuilder;exports.ForbiddenError=ForbiddenError;exports.PureAbility=PureAbility;exports.buildMongoQueryMatcher=F;exports.createAliasResolver=d;exports.createMongoAbility=createMongoAbility;exports.defineAbility=defineAbility;exports.detectSubjectType=u;exports.fieldPatternMatcher=z;exports.getDefaultErrorMessage=Y;exports.hkt=I;exports.mongoQueryMatcher=O;exports.subject=r;exports.wrapArray=e; //# sourceMappingURL=index.js.map