import{createFactory as t,$eq as e,$ne as i,$lt as s,$lte as n,$gt as r,$gte as o,$in as c,$nin as u,$all as h,$size as l,$regex as a,$options as f,$elemMatch as d,$exists as p,eq as b,ne as y,lt as w,lte as g,gt as $,gte as m,within as E,nin as A,all as j,size as v,regex as x,elemMatch as M,exists as _,and as F}from"@ucast/mongo2js";function O(t){return Array.isArray(t)?t:[t]}const C="__caslSubjectType__";function R(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}const T=t=>{const e=typeof t;return"string"===e||"function"===e};const B=t=>t.modelName||t.name;const P=t=>"string"===typeof t?t:B(t);function S(t){if(t.hasOwnProperty(C))return t[C];return B(t.constructor)}function q(t,e,i){let s=O(e);let n=0;while(nt.concat(e);function Y(t,e){if(e in t)throw new Error(`Cannot use "${e}" as an alias because it's reserved action.`);const i=Object.keys(t);const s=(t,i)=>{const s=z(t,i);if(s)throw new Error(`Detected cycle ${s} -> ${t.join(", ")}`);const n="string"===typeof i&&i===e||-1!==t.indexOf(e)||Array.isArray(i)&&-1!==i.indexOf(e);if(n)throw new Error(`Cannot make an alias to "${e}" because this is reserved action`);return t.concat(i)};for(let e=0;eq(t,e,D)}function I(t,e,i){for(let s=i;st;function H(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 J{constructor(t,e,i=0){H(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=i;this.t=e}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||T(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 K(t,e){const i={value:t,prev:e,next:null};if(e)e.next=i;return i}function N(t){if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null}const Q=t=>({value:t.value,prev:t.prev,next:t.next});const V=()=>({rules:[],merged:false});const W=()=>new Map;const X=(t,e)=>{if(!t.h&&e.fields)t.h=true};class Z{constructor(t=[],e={}){this.h=false;this.l=new Map;this.p={conditionsMatcher:e.conditionsMatcher,fieldMatcher:e.fieldMatcher,resolveAction:e.resolveAction||G};this.g=e.anyAction||"manage";this.$=e.anySubjectType||"all";this.m=e.detectSubjectType||S;this.A=t;this.j=this.v(t)}get rules(){return this.A}detectSubjectType(t){if(T(t))return t;if(!t)return this.$;return this.m(t)}update(t){const e={rules:t,ability:this,target:this};this.M("update",e);this.A=t;this.j=this.v(t);this.M("updated",e);return this}v(t){const e=new Map;for(let i=t.length-1;i>=0;i--){const s=t.length-i-1;const n=new J(t[i],this.p,s);const r=O(n.action);const o=O(n.subject||this.$);X(this,n);for(let t=0;tt.matchesField(i)))}on(t,e){const i=this.l.get(t)||null;const s=K(e,i);this.l.set(t,s);return()=>{const e=this.l.get(t);if(!s.next&&!s.prev&&e===s)this.l.delete(t);else if(s===e)this.l.set(t,s.prev);N(s)}}M(t,e){let i=this.l.get(t)||null;while(null!==i){const t=i.prev?Q(i.prev):null;i.value(e);i=t}}}class PureAbility extends Z{can(...t){const e=this.relevantRuleFor(...t);return!!e&&!e.inverted}relevantRuleFor(t,e,i){const s=this.detectSubjectType(e);const n=this.rulesFor(t,s,i);for(let t=0,i=n.length;tt(Object.assign({},tt,e),Object.assign({},et,i),s);const st=t(tt,et);const nt=/[-/\\^$+?.()|[\]{}]/g;const rt=/\.?\*+\.?/g;const ot=/\*+/;const ct=/\./g;function ut(t,e,i){const s="*"===i[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const n=-1===t.indexOf("**")?"[^.]":".";const r=t.replace(ct,"\\$&").replace(ot,n+s);return e+t.length===i.length?`(?:${r})?`:r}function ht(t,e,i){if("."===t&&("*"===i[e-1]||"*"===i[e+1]))return t;return`\\${t}`}function lt(t){const e=t.map((t=>t.replace(nt,ht).replace(rt,ut)));const i=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${i}$`)}const at=t=>{let e;return i=>{if("undefined"===typeof e)e=t.every((t=>-1===t.indexOf("*")))?null:lt(t);return null===e?-1!==t.indexOf(i):e.test(i)}};class Ability extends PureAbility{constructor(t=[],e={}){super(t,Object.assign({conditionsMatcher:st,fieldMatcher:at},e))}}class ft{constructor(t){this._=t}because(t){this._.reason=t;return this}}class AbilityBuilder{constructor(t){this.rules=[];this.F=t;this.can=this.can.bind(this);this.cannot=this.cannot.bind(this);this.build=this.build.bind(this)}can(t,e,i,s){const n={action:t};if(e){n.subject=e;if(Array.isArray(i)||"string"===typeof i)n.fields=i;else if("undefined"!==typeof i)n.conditions=i;if("undefined"!==typeof s)n.conditions=s}this.rules.push(n);return new ft(n)}cannot(t,e,i,s){const n=this.can(t,e,i,s);n._.inverted=true;return n}build(t){return new this.F(this.rules,t)}}function defineAbility(t,e){const i=new AbilityBuilder(Ability);const s=t(i.can,i.cannot);if(s&&"function"===typeof s.then)return s.then((()=>i.build(e)));return i.build(e)}const dt=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const pt=function t(e){this.message=e};pt.prototype=Object.create(Error.prototype);class ForbiddenError extends pt{static setDefaultMessage(t){this.O="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){const e=this.ability.relevantRuleFor(...t);if(e&&!e.inverted)return;this.action=t[0];this.subject=t[1];this.subjectType=P(this.ability.detectSubjectType(t[1]));this.field=t[2];const i=e?e.reason:"";this.message=this.message||i||this.constructor.O(this);throw this}}ForbiddenError.O=dt;var bt=Object.freeze({__proto__:null});export{Ability,AbilityBuilder,ForbiddenError,PureAbility,it as buildMongoQueryMatcher,k as createAliasResolver,defineAbility,S as detectSubjectType,at as fieldPatternMatcher,dt as getDefaultErrorMessage,bt as hkt,st as mongoQueryMatcher,R as subject,O as wrapArray}; //# sourceMappingURL=index.mjs.map