@via-profit/ability 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,105 +1,5 @@
1
- /******/ (() => { // webpackBootstrap
2
- /******/ "use strict";
3
- /******/ var __webpack_modules__ = ({
1
+ 'use strict';
4
2
 
5
- /***/ 6:
6
- /***/ ((__unused_webpack_module, exports) => {
7
-
8
-
9
- Object.defineProperty(exports, "__esModule", ({ value: true }));
10
-
11
-
12
- /***/ }),
13
-
14
- /***/ 829:
15
- /***/ ((__unused_webpack_module, exports) => {
16
-
17
-
18
- Object.defineProperty(exports, "__esModule", ({ value: true }));
19
- exports.AbilityInMemoryCache = void 0;
20
- class AbilityInMemoryCache {
21
- store = new Map();
22
- async get(key) {
23
- const entry = this.store.get(key);
24
- if (!entry)
25
- return undefined;
26
- if (Date.now() > entry.expires) {
27
- this.store.delete(key);
28
- return undefined;
29
- }
30
- return entry.value;
31
- }
32
- async set(key, value, ttlSeconds = 60) {
33
- this.store.set(key, {
34
- value,
35
- expires: Date.now() + ttlSeconds * 1000,
36
- });
37
- }
38
- serialize(input) {
39
- return this.fastHash(this.stableStringify(input));
40
- }
41
- async delete(key) {
42
- this.store.delete(key);
43
- }
44
- async clear() {
45
- this.store.clear();
46
- }
47
- async deleteByPrefix(prefix) {
48
- for (const key of this.store.keys()) {
49
- if (key.startsWith(prefix)) {
50
- this.store.delete(key);
51
- }
52
- }
53
- }
54
- fastHash(str) {
55
- let hash = 5381;
56
- for (let i = 0; i < str.length; i++) {
57
- hash = (hash * 33) ^ str.charCodeAt(i);
58
- }
59
- return (hash >>> 0).toString(36);
60
- }
61
- stableStringify(obj) {
62
- if (obj === null)
63
- return 'null';
64
- const type = typeof obj;
65
- if (type === 'string')
66
- return JSON.stringify(obj);
67
- if (type === 'number' || type === 'boolean')
68
- return String(obj);
69
- if (type === 'undefined')
70
- return 'undefined';
71
- if (Array.isArray(obj)) {
72
- let out = '[';
73
- for (let i = 0; i < obj.length; i++) {
74
- if (i > 0)
75
- out += ',';
76
- out += this.stableStringify(obj[i]);
77
- }
78
- return out + ']';
79
- }
80
- const keys = Object.keys(obj);
81
- keys.sort();
82
- let out = '{';
83
- for (let i = 0; i < keys.length; i++) {
84
- const k = keys[i];
85
- if (i > 0)
86
- out += ',';
87
- out += k + ':' + this.stableStringify(obj[k]);
88
- }
89
- return out + '}';
90
- }
91
- }
92
- exports.AbilityInMemoryCache = AbilityInMemoryCache;
93
-
94
-
95
- /***/ }),
96
-
97
- /***/ 301:
98
- /***/ ((__unused_webpack_module, exports) => {
99
-
100
-
101
- Object.defineProperty(exports, "__esModule", ({ value: true }));
102
- exports.AbilityCode = void 0;
103
3
  class AbilityCode {
104
4
  _code;
105
5
  constructor(code) {
@@ -115,44 +15,24 @@ class AbilityCode {
115
15
  return !this.isEqual(compareWith);
116
16
  }
117
17
  }
118
- exports.AbilityCode = AbilityCode;
119
- exports["default"] = AbilityCode;
120
-
121
-
122
- /***/ }),
123
18
 
124
- /***/ 413:
125
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
126
-
127
-
128
- var __importDefault = (this && this.__importDefault) || function (mod) {
129
- return (mod && mod.__esModule) ? mod : { "default": mod };
130
- };
131
- Object.defineProperty(exports, "__esModule", ({ value: true }));
132
- exports.AbilityCompare = void 0;
133
- const AbilityCode_1 = __importDefault(__webpack_require__(301));
134
- class AbilityCompare extends AbilityCode_1.default {
19
+ class AbilityCompare extends AbilityCode {
135
20
  static and = new AbilityCompare('and');
136
21
  static or = new AbilityCompare('or');
137
22
  }
138
- exports.AbilityCompare = AbilityCompare;
139
- exports["default"] = AbilityCompare;
140
-
141
-
142
- /***/ }),
143
-
144
- /***/ 167:
145
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
146
23
 
24
+ class AbilityError extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ }
28
+ }
29
+ class AbilityParserError extends Error {
30
+ constructor(message) {
31
+ super(message);
32
+ }
33
+ }
147
34
 
148
- var __importDefault = (this && this.__importDefault) || function (mod) {
149
- return (mod && mod.__esModule) ? mod : { "default": mod };
150
- };
151
- Object.defineProperty(exports, "__esModule", ({ value: true }));
152
- exports.AbilityCondition = void 0;
153
- const AbilityCode_1 = __importDefault(__webpack_require__(301));
154
- const AbilityError_1 = __webpack_require__(216);
155
- class AbilityCondition extends AbilityCode_1.default {
35
+ class AbilityCondition extends AbilityCode {
156
36
  static equals = new AbilityCondition('=');
157
37
  static not_equals = new AbilityCondition('<>');
158
38
  static greater_than = new AbilityCondition('>');
@@ -193,7 +73,7 @@ class AbilityCondition extends AbilityCode_1.default {
193
73
  case 'length_equals':
194
74
  return this.length_equals;
195
75
  default:
196
- throw new AbilityError_1.AbilityParserError(`Literal ${literal} does not found in AbilityCondition class`);
76
+ throw new AbilityParserError(`Literal ${literal} does not found in AbilityCondition class`);
197
77
  }
198
78
  }
199
79
  get literal() {
@@ -207,134 +87,13 @@ class AbilityCondition extends AbilityCode_1.default {
207
87
  return literal;
208
88
  }
209
89
  }
210
- exports.AbilityCondition = AbilityCondition;
211
- exports["default"] = AbilityCondition;
212
-
213
-
214
- /***/ }),
215
-
216
- /***/ 216:
217
- /***/ ((__unused_webpack_module, exports) => {
218
-
219
-
220
- Object.defineProperty(exports, "__esModule", ({ value: true }));
221
- exports.AbilityParserError = exports.AbilityError = void 0;
222
- class AbilityError extends Error {
223
- constructor(message) {
224
- super(message);
225
- }
226
- }
227
- exports.AbilityError = AbilityError;
228
- class AbilityParserError extends Error {
229
- constructor(message) {
230
- super(message);
231
- }
232
- }
233
- exports.AbilityParserError = AbilityParserError;
234
-
235
-
236
- /***/ }),
237
-
238
- /***/ 221:
239
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
240
-
241
-
242
- var __importDefault = (this && this.__importDefault) || function (mod) {
243
- return (mod && mod.__esModule) ? mod : { "default": mod };
244
- };
245
- Object.defineProperty(exports, "__esModule", ({ value: true }));
246
- exports.AbilityExplainPolicy = exports.AbilityExplainRuleSet = exports.AbilityExplainRule = exports.AbilityExplain = void 0;
247
- const AbilityMatch_1 = __importDefault(__webpack_require__(247));
248
- class AbilityExplain {
249
- type;
250
- children;
251
- name;
252
- match;
253
- constructor(config, children = []) {
254
- this.type = config.type;
255
- this.children = children;
256
- this.name = config.name;
257
- this.match = config.match;
258
- }
259
- toString(indent = 0) {
260
- const pad = ' '.repeat(indent);
261
- const mark = this.match.code === AbilityMatch_1.default.match.code ? '✓' : '✗';
262
- let out = `${pad}${mark} ${this.type} «${this.name}» is ${this.match.code}`;
263
- this.children.forEach(child => {
264
- out += '\n' + child.toString(indent + 1);
265
- });
266
- return out;
267
- }
268
- }
269
- exports.AbilityExplain = AbilityExplain;
270
- class AbilityExplainRule extends AbilityExplain {
271
- constructor(rule) {
272
- super({
273
- type: 'rule',
274
- match: rule.state,
275
- name: rule.name,
276
- });
277
- }
278
- }
279
- exports.AbilityExplainRule = AbilityExplainRule;
280
- class AbilityExplainRuleSet extends AbilityExplain {
281
- constructor(ruleSet) {
282
- const children = ruleSet.rules.map(rule => new AbilityExplainRule(rule));
283
- super({
284
- type: 'ruleSet',
285
- match: ruleSet.state,
286
- name: ruleSet.name,
287
- }, children);
288
- }
289
- }
290
- exports.AbilityExplainRuleSet = AbilityExplainRuleSet;
291
- class AbilityExplainPolicy extends AbilityExplain {
292
- constructor(policy) {
293
- const children = policy.ruleSet.map(ruleSet => new AbilityExplainRuleSet(ruleSet));
294
- super({
295
- type: 'policy',
296
- name: policy.name,
297
- match: policy.matchState,
298
- }, children);
299
- }
300
- }
301
- exports.AbilityExplainPolicy = AbilityExplainPolicy;
302
-
303
-
304
- /***/ }),
305
-
306
- /***/ 247:
307
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
308
-
309
90
 
310
- var __importDefault = (this && this.__importDefault) || function (mod) {
311
- return (mod && mod.__esModule) ? mod : { "default": mod };
312
- };
313
- Object.defineProperty(exports, "__esModule", ({ value: true }));
314
- exports.AbilityMatch = void 0;
315
- const AbilityCode_1 = __importDefault(__webpack_require__(301));
316
- class AbilityMatch extends AbilityCode_1.default {
91
+ class AbilityMatch extends AbilityCode {
317
92
  static pending = new AbilityMatch('pending');
318
93
  static match = new AbilityMatch('match');
319
94
  static mismatch = new AbilityMatch('mismatch');
320
95
  }
321
- exports.AbilityMatch = AbilityMatch;
322
- exports["default"] = AbilityMatch;
323
-
324
-
325
- /***/ }),
326
-
327
- /***/ 147:
328
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
329
96
 
330
-
331
- var __importDefault = (this && this.__importDefault) || function (mod) {
332
- return (mod && mod.__esModule) ? mod : { "default": mod };
333
- };
334
- Object.defineProperty(exports, "__esModule", ({ value: true }));
335
- exports.AbilityParser = void 0;
336
- const AbilityError_1 = __webpack_require__(216);
337
- const AbilityCondition_1 = __importDefault(__webpack_require__(167));
338
97
  class AbilityParser {
339
98
  /**
340
99
  * Sets a value in a nested object structure based on a dot/bracket notation path.
@@ -344,12 +103,12 @@ class AbilityParser {
344
103
  */
345
104
  static setValueDotValue(object, path, value) {
346
105
  if (!path || path.trim().length === 0) {
347
- throw new AbilityError_1.AbilityParserError(`Invalid path provided on a [${path}]`);
106
+ throw new AbilityParserError(`Invalid path provided on a [${path}]`);
348
107
  }
349
108
  const way = path.replace(/\[/g, '.').replace(/]/g, '').split('.');
350
109
  const last = way.pop();
351
110
  if (!last) {
352
- throw new AbilityError_1.AbilityParserError(`Invalid path provided on a [${path}]`);
111
+ throw new AbilityParserError(`Invalid path provided on a [${path}]`);
353
112
  }
354
113
  const lastObj = way.reduce((acc, key, index, array) => {
355
114
  const currentValue = acc[key];
@@ -362,7 +121,7 @@ class AbilityParser {
362
121
  return newValue;
363
122
  }
364
123
  if (typeof currentValue !== 'object') {
365
- throw new AbilityError_1.AbilityParserError(`Cannot set property '${key}' on non-object value at path: ${path}`);
124
+ throw new AbilityParserError(`Cannot set property '${key}' on non-object value at path: ${path}`);
366
125
  }
367
126
  return currentValue;
368
127
  }, object);
@@ -371,7 +130,7 @@ class AbilityParser {
371
130
  typeof existingValue === 'object' &&
372
131
  existingValue !== null &&
373
132
  !Array.isArray(existingValue)) {
374
- throw new AbilityError_1.AbilityParserError(`Cannot set primitive value on existing object at path: ${path}`);
133
+ throw new AbilityParserError(`Cannot set primitive value on existing object at path: ${path}`);
375
134
  }
376
135
  lastObj[last] = value;
377
136
  }
@@ -418,20 +177,20 @@ class AbilityParser {
418
177
  */
419
178
  static determineTypeFromRule(rule) {
420
179
  // Numeric comparisons - always number
421
- if (rule.condition.isEqual(AbilityCondition_1.default.greater_than) ||
422
- rule.condition.isEqual(AbilityCondition_1.default.less_than) ||
423
- rule.condition.isEqual(AbilityCondition_1.default.greater_or_equal) ||
424
- rule.condition.isEqual(AbilityCondition_1.default.less_or_equal)) {
180
+ if (rule.condition.isEqual(AbilityCondition.greater_than) ||
181
+ rule.condition.isEqual(AbilityCondition.less_than) ||
182
+ rule.condition.isEqual(AbilityCondition.greater_or_equal) ||
183
+ rule.condition.isEqual(AbilityCondition.less_or_equal)) {
425
184
  return 'number';
426
185
  }
427
186
  // Array operations
428
- if (rule.condition.isEqual(AbilityCondition_1.default.in) ||
429
- rule.condition.isEqual(AbilityCondition_1.default.not_in)) {
187
+ if (rule.condition.isEqual(AbilityCondition.in) ||
188
+ rule.condition.isEqual(AbilityCondition.not_in)) {
430
189
  return this.getArrayType(rule.resource);
431
190
  }
432
191
  // Equality/Inequality operations
433
- if (rule.condition.isEqual(AbilityCondition_1.default.equals) ||
434
- rule.condition.isEqual(AbilityCondition_1.default.not_equals)) {
192
+ if (rule.condition.isEqual(AbilityCondition.equals) ||
193
+ rule.condition.isEqual(AbilityCondition.not_equals)) {
435
194
  return this.getPrimitiveType(rule.resource);
436
195
  }
437
196
  return 'any';
@@ -562,29 +321,60 @@ class AbilityParser {
562
321
  return output;
563
322
  }
564
323
  }
565
- exports.AbilityParser = AbilityParser;
566
- exports["default"] = AbilityParser;
567
-
568
-
569
- /***/ }),
570
-
571
- /***/ 278:
572
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
573
324
 
325
+ class AbilityExplain {
326
+ type;
327
+ children;
328
+ name;
329
+ match;
330
+ constructor(config, children = []) {
331
+ this.type = config.type;
332
+ this.children = children;
333
+ this.name = config.name;
334
+ this.match = config.match;
335
+ }
336
+ toString(indent = 0) {
337
+ const pad = ' '.repeat(indent);
338
+ const mark = this.match.code === AbilityMatch.match.code ? '✓' : '✗';
339
+ let out = `${pad}${mark} ${this.type} «${this.name}» is ${this.match.code}`;
340
+ this.children.forEach(child => {
341
+ out += '\n' + child.toString(indent + 1);
342
+ });
343
+ return out;
344
+ }
345
+ }
346
+ class AbilityExplainRule extends AbilityExplain {
347
+ constructor(rule) {
348
+ super({
349
+ type: 'rule',
350
+ match: rule.state,
351
+ name: rule.name,
352
+ });
353
+ }
354
+ }
355
+ class AbilityExplainRuleSet extends AbilityExplain {
356
+ constructor(ruleSet) {
357
+ const children = ruleSet.rules.map(rule => new AbilityExplainRule(rule));
358
+ super({
359
+ type: 'ruleSet',
360
+ match: ruleSet.state,
361
+ name: ruleSet.name,
362
+ }, children);
363
+ }
364
+ }
365
+ class AbilityExplainPolicy extends AbilityExplain {
366
+ constructor(policy) {
367
+ const children = policy.ruleSet.map(ruleSet => new AbilityExplainRuleSet(ruleSet));
368
+ super({
369
+ type: 'policy',
370
+ name: policy.name,
371
+ match: policy.matchState,
372
+ }, children);
373
+ }
374
+ }
574
375
 
575
- var __importDefault = (this && this.__importDefault) || function (mod) {
576
- return (mod && mod.__esModule) ? mod : { "default": mod };
577
- };
578
- Object.defineProperty(exports, "__esModule", ({ value: true }));
579
- exports.AbilityPolicy = void 0;
580
- const AbilityMatch_1 = __importDefault(__webpack_require__(247));
581
- const AbilityCompare_1 = __importDefault(__webpack_require__(413));
582
- const AbilityExplain_1 = __webpack_require__(221);
583
- const AbilityError_1 = __webpack_require__(216);
584
- const AbilityJSONParser_1 = __webpack_require__(909);
585
- const AbilityDSLParser_1 = __webpack_require__(577);
586
376
  class AbilityPolicy {
587
- matchState = AbilityMatch_1.default.pending;
377
+ matchState = AbilityMatch.pending;
588
378
  /**
589
379
  * List of rules
590
380
  */
@@ -599,7 +389,7 @@ class AbilityPolicy {
599
389
  * rules will be returns «permit» status and for the «or» - if\
600
390
  * one of the rules returns as «permit»
601
391
  */
602
- compareMethod = AbilityCompare_1.default.and;
392
+ compareMethod = AbilityCompare.and;
603
393
  /**
604
394
  * Policy name
605
395
  */
@@ -614,7 +404,7 @@ class AbilityPolicy {
614
404
  */
615
405
  permission;
616
406
  constructor(params) {
617
- const { name, id, permission, effect, compareMethod = AbilityCompare_1.default.and } = params;
407
+ const { name, id, permission, effect, compareMethod = AbilityCompare.and } = params;
618
408
  this.name = name;
619
409
  this.id = id;
620
410
  this.permission = permission;
@@ -645,7 +435,7 @@ class AbilityPolicy {
645
435
  * @param environment - The user environment object
646
436
  */
647
437
  async check(resource, environment) {
648
- this.matchState = AbilityMatch_1.default.mismatch;
438
+ this.matchState = AbilityMatch.mismatch;
649
439
  if (!this.ruleSet.length) {
650
440
  return this.matchState;
651
441
  }
@@ -653,94 +443,104 @@ class AbilityPolicy {
653
443
  for (const ruleSet of this.ruleSet) {
654
444
  const state = await ruleSet.check(resource, environment);
655
445
  rulesetCheckStates.push(state);
656
- if (AbilityCompare_1.default.and.isEqual(this.compareMethod) && AbilityMatch_1.default.mismatch.isEqual(state)) {
446
+ if (AbilityCompare.and.isEqual(this.compareMethod) && AbilityMatch.mismatch.isEqual(state)) {
657
447
  return this.matchState; // mismatch
658
448
  }
659
- if (AbilityCompare_1.default.or.isEqual(this.compareMethod) && AbilityMatch_1.default.match.isEqual(state)) {
660
- this.matchState = AbilityMatch_1.default.match;
449
+ if (AbilityCompare.or.isEqual(this.compareMethod) && AbilityMatch.match.isEqual(state)) {
450
+ this.matchState = AbilityMatch.match;
661
451
  return this.matchState;
662
452
  }
663
453
  }
664
- if (AbilityCompare_1.default.and.isEqual(this.compareMethod)) {
665
- if (rulesetCheckStates.every(s => AbilityMatch_1.default.match.isEqual(s))) {
666
- this.matchState = AbilityMatch_1.default.match;
454
+ if (AbilityCompare.and.isEqual(this.compareMethod)) {
455
+ if (rulesetCheckStates.every(s => AbilityMatch.match.isEqual(s))) {
456
+ this.matchState = AbilityMatch.match;
667
457
  }
668
458
  }
669
- if (AbilityCompare_1.default.or.isEqual(this.compareMethod)) {
670
- if (rulesetCheckStates.some(s => AbilityMatch_1.default.match.isEqual(s))) {
671
- this.matchState = AbilityMatch_1.default.match;
459
+ if (AbilityCompare.or.isEqual(this.compareMethod)) {
460
+ if (rulesetCheckStates.some(s => AbilityMatch.match.isEqual(s))) {
461
+ this.matchState = AbilityMatch.match;
672
462
  }
673
463
  }
674
464
  return this.matchState;
675
465
  }
676
466
  explain() {
677
- if (this.matchState === AbilityMatch_1.default.pending) {
678
- throw new AbilityError_1.AbilityError('First, run the check method, then explain');
467
+ if (this.matchState === AbilityMatch.pending) {
468
+ throw new AbilityError('First, run the check method, then explain');
469
+ }
470
+ return new AbilityExplainPolicy(this);
471
+ }
472
+ copyWith(props) {
473
+ const policy = new AbilityPolicy({
474
+ id: props.id ?? this.id,
475
+ name: props.name ?? this.name,
476
+ permission: props.permission ?? this.permission,
477
+ effect: props.effect ?? this.effect,
478
+ compareMethod: props.compareMethod ?? this.compareMethod,
479
+ });
480
+ const nextRuleSet = props.ruleSet ?? this.ruleSet;
481
+ for (const rule of nextRuleSet) {
482
+ policy.addRuleSet(rule);
679
483
  }
680
- return new AbilityExplain_1.AbilityExplainPolicy(this);
484
+ return policy;
681
485
  }
486
+ }
487
+
488
+ class AbilityPolicyEffect extends AbilityCode {
489
+ static deny = new AbilityPolicyEffect('deny');
490
+ static permit = new AbilityPolicyEffect('permit');
491
+ }
492
+
493
+ class AbilityResult {
682
494
  /**
683
- * Parses an array of policy configurations into an array of AbilityPolicy instances.
684
- * @param configs - Array of policy configurations
685
- * @returns Array of AbilityPolicy instances
495
+ * Already checked policies (after call the policy.check())
686
496
  */
687
- static fromJSONAll(configs) {
688
- return AbilityJSONParser_1.AbilityJSONParser.parse(configs);
689
- }
497
+ policies;
498
+ constructor(policies) {
499
+ this.policies = policies;
500
+ }
690
501
  /**
691
- * Parse the config JSON format to Policy class instance
502
+ * Returns a list of explanations for each policy involved in the ability evaluation.
503
+ * Each item describes how a specific policy contributed to the final permission result.
504
+ *
505
+ * Useful for debugging, logging, or building UI tools that visualize permission logic.
692
506
  */
693
- static fromJSON(config) {
694
- return AbilityJSONParser_1.AbilityJSONParser.parsePolicy(config);
507
+ explain() {
508
+ return this.policies.map(policy => {
509
+ return new AbilityExplainPolicy(policy);
510
+ });
695
511
  }
696
- static fromDSL(dsl) {
697
- return new AbilityDSLParser_1.AbilityDSLParser(dsl).parse()[0];
512
+ getLastMatchedPolicy() {
513
+ for (let i = this.policies.length - 1; i >= 0; i--) {
514
+ if (this.policies[i].matchState.isEqual(AbilityMatch.match)) {
515
+ return this.policies[i];
516
+ }
517
+ }
518
+ return null;
698
519
  }
699
- toJSON() {
700
- return AbilityJSONParser_1.AbilityJSONParser.toJSON([this])[0];
520
+ isAllowed() {
521
+ const effect = this.getLastEffectOfMatchedPolicy();
522
+ return effect?.isEqual(AbilityPolicyEffect.permit) ?? false;
701
523
  }
702
- toString() {
703
- return JSON.stringify(this.toJSON());
524
+ isDenied() {
525
+ const effect = this.getLastEffectOfMatchedPolicy();
526
+ return effect?.isEqual(AbilityPolicyEffect.deny) ?? true;
527
+ }
528
+ /**
529
+ * Get the last effect of the policy
530
+ *
531
+ * @returns {AbilityPolicyEffect | null}
532
+ */
533
+ getLastEffectOfMatchedPolicy() {
534
+ for (let i = this.policies.length - 1; i >= 0; i--) {
535
+ const p = this.policies[i];
536
+ if (p.matchState.isEqual(AbilityMatch.match)) {
537
+ return p.effect;
538
+ }
539
+ }
540
+ return null;
704
541
  }
705
542
  }
706
- exports.AbilityPolicy = AbilityPolicy;
707
- exports["default"] = AbilityPolicy;
708
-
709
-
710
- /***/ }),
711
-
712
- /***/ 179:
713
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
714
-
715
-
716
- var __importDefault = (this && this.__importDefault) || function (mod) {
717
- return (mod && mod.__esModule) ? mod : { "default": mod };
718
- };
719
- Object.defineProperty(exports, "__esModule", ({ value: true }));
720
- exports.AbilityPolicyEffect = void 0;
721
- const AbilityCode_1 = __importDefault(__webpack_require__(301));
722
- class AbilityPolicyEffect extends AbilityCode_1.default {
723
- static deny = new AbilityPolicyEffect('deny');
724
- static permit = new AbilityPolicyEffect('permit');
725
- }
726
- exports.AbilityPolicyEffect = AbilityPolicyEffect;
727
- exports["default"] = AbilityPolicyEffect;
728
-
729
-
730
- /***/ }),
731
-
732
- /***/ 634:
733
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
734
543
 
735
-
736
- var __importDefault = (this && this.__importDefault) || function (mod) {
737
- return (mod && mod.__esModule) ? mod : { "default": mod };
738
- };
739
- Object.defineProperty(exports, "__esModule", ({ value: true }));
740
- exports.AbilityResolver = void 0;
741
- const AbilityError_1 = __webpack_require__(216);
742
- const AbilityResult_1 = __webpack_require__(941);
743
- const AbilityMatch_1 = __importDefault(__webpack_require__(247));
744
544
  class AbilityResolver {
745
545
  policies;
746
546
  cache;
@@ -775,20 +575,20 @@ class AbilityResolver {
775
575
  }
776
576
  }
777
577
  const policyMatchState = await policy.check(resource, environment);
778
- if (policyMatchState === AbilityMatch_1.default.pending) {
779
- throw new AbilityError_1.AbilityError(`The policy "${policy.name}" is still in a pending state. Make sure to call "check" to evaluate the policy before resolving permissions.`);
578
+ if (policyMatchState === AbilityMatch.pending) {
579
+ throw new AbilityError(`The policy "${policy.name}" is still in a pending state. Make sure to call "check" to evaluate the policy before resolving permissions.`);
780
580
  }
781
581
  if (this.cache) {
782
582
  await this.cache.set(cacheKey, policyMatchState);
783
583
  }
784
584
  }
785
- return new AbilityResult_1.AbilityResult(filteredPolicies);
585
+ return new AbilityResult(filteredPolicies);
786
586
  }
787
587
  async enforce(permission, resource, environment) {
788
588
  const result = await this.resolve(permission, resource, environment);
789
589
  if (result.isDenied()) {
790
590
  const policyName = result.getLastMatchedPolicy()?.name?.toString() || 'unknown';
791
- throw new AbilityError_1.AbilityError(`Permission denied by policy "${policyName}"`);
591
+ throw new AbilityError(`Permission denied by policy "${policyName}"`);
792
592
  }
793
593
  }
794
594
  /**
@@ -817,91 +617,7 @@ class AbilityResolver {
817
617
  await this.cache?.clear();
818
618
  }
819
619
  }
820
- exports.AbilityResolver = AbilityResolver;
821
- exports["default"] = AbilityResolver;
822
-
823
-
824
- /***/ }),
825
-
826
- /***/ 941:
827
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
828
-
829
620
 
830
- var __importDefault = (this && this.__importDefault) || function (mod) {
831
- return (mod && mod.__esModule) ? mod : { "default": mod };
832
- };
833
- Object.defineProperty(exports, "__esModule", ({ value: true }));
834
- exports.AbilityResult = void 0;
835
- const AbilityExplain_1 = __webpack_require__(221);
836
- const AbilityMatch_1 = __importDefault(__webpack_require__(247));
837
- const AbilityPolicyEffect_1 = __importDefault(__webpack_require__(179));
838
- class AbilityResult {
839
- /**
840
- * Already checked policies (after call the policy.check())
841
- */
842
- policies;
843
- constructor(policies) {
844
- this.policies = policies;
845
- }
846
- /**
847
- * Returns a list of explanations for each policy involved in the ability evaluation.
848
- * Each item describes how a specific policy contributed to the final permission result.
849
- *
850
- * Useful for debugging, logging, or building UI tools that visualize permission logic.
851
- */
852
- explain() {
853
- return this.policies.map(policy => {
854
- return new AbilityExplain_1.AbilityExplainPolicy(policy);
855
- });
856
- }
857
- getLastMatchedPolicy() {
858
- for (let i = this.policies.length - 1; i >= 0; i--) {
859
- if (this.policies[i].matchState.isEqual(AbilityMatch_1.default.match)) {
860
- return this.policies[i];
861
- }
862
- }
863
- return null;
864
- }
865
- isAllowed() {
866
- const effect = this.getLastEffectOfMatchedPolicy();
867
- return effect?.isEqual(AbilityPolicyEffect_1.default.permit) ?? false;
868
- }
869
- isDenied() {
870
- const effect = this.getLastEffectOfMatchedPolicy();
871
- return effect?.isEqual(AbilityPolicyEffect_1.default.deny) ?? true;
872
- }
873
- /**
874
- * Get the last effect of the policy
875
- *
876
- * @returns {AbilityPolicyEffect | null}
877
- */
878
- getLastEffectOfMatchedPolicy() {
879
- for (let i = this.policies.length - 1; i >= 0; i--) {
880
- const p = this.policies[i];
881
- if (p.matchState.isEqual(AbilityMatch_1.default.match)) {
882
- return p.effect;
883
- }
884
- }
885
- return null;
886
- }
887
- }
888
- exports.AbilityResult = AbilityResult;
889
-
890
-
891
- /***/ }),
892
-
893
- /***/ 306:
894
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
895
-
896
-
897
- var __importDefault = (this && this.__importDefault) || function (mod) {
898
- return (mod && mod.__esModule) ? mod : { "default": mod };
899
- };
900
- Object.defineProperty(exports, "__esModule", ({ value: true }));
901
- exports.AbilityRule = void 0;
902
- const AbilityMatch_1 = __importDefault(__webpack_require__(247));
903
- const AbilityCondition_1 = __importDefault(__webpack_require__(167));
904
- const AbilityJSONParser_1 = __webpack_require__(909);
905
621
  /**
906
622
  * Represents a rule that defines a condition to be checked against a subject and resource.
907
623
  */
@@ -917,7 +633,7 @@ class AbilityRule {
917
633
  condition;
918
634
  name;
919
635
  id;
920
- state = AbilityMatch_1.default.pending;
636
+ state = AbilityMatch.pending;
921
637
  /**
922
638
  * Creates an instance of AbilityRule.
923
639
  * @param {string} params.id - The unique identifier of the rule.
@@ -945,39 +661,39 @@ class AbilityRule {
945
661
  const [subjectValue, resourceValue] = this.extractValues(resource, environment);
946
662
  const isValue = (v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null;
947
663
  // equals
948
- if (AbilityCondition_1.default.equals.isEqual(this.condition)) {
664
+ if (AbilityCondition.equals.isEqual(this.condition)) {
949
665
  is = subjectValue === resourceValue;
950
666
  }
951
667
  // not equals
952
- if (AbilityCondition_1.default.not_equals.isEqual(this.condition)) {
668
+ if (AbilityCondition.not_equals.isEqual(this.condition)) {
953
669
  is = subjectValue !== resourceValue;
954
670
  }
955
671
  // less than
956
- if (AbilityCondition_1.default.less_than.isEqual(this.condition)) {
672
+ if (AbilityCondition.less_than.isEqual(this.condition)) {
957
673
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
958
674
  is = subjectValue < resourceValue;
959
675
  }
960
676
  }
961
677
  // less or equal
962
- if (AbilityCondition_1.default.less_or_equal.isEqual(this.condition)) {
678
+ if (AbilityCondition.less_or_equal.isEqual(this.condition)) {
963
679
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
964
680
  is = subjectValue <= resourceValue;
965
681
  }
966
682
  }
967
683
  // more than
968
- if (AbilityCondition_1.default.greater_than.isEqual(this.condition)) {
684
+ if (AbilityCondition.greater_than.isEqual(this.condition)) {
969
685
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
970
686
  is = subjectValue > resourceValue;
971
687
  }
972
688
  }
973
689
  // more or equal
974
- if (AbilityCondition_1.default.greater_or_equal.isEqual(this.condition)) {
690
+ if (AbilityCondition.greater_or_equal.isEqual(this.condition)) {
975
691
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
976
692
  is = subjectValue >= resourceValue;
977
693
  }
978
694
  }
979
695
  // in
980
- if (AbilityCondition_1.default.in.isEqual(this.condition)) {
696
+ if (AbilityCondition.in.isEqual(this.condition)) {
981
697
  // value in array
982
698
  if (isValue(subjectValue) && Array.isArray(resourceValue)) {
983
699
  is = resourceValue.includes(subjectValue);
@@ -988,7 +704,7 @@ class AbilityRule {
988
704
  }
989
705
  }
990
706
  // not in
991
- if (AbilityCondition_1.default.not_in.isEqual(this.condition)) {
707
+ if (AbilityCondition.not_in.isEqual(this.condition)) {
992
708
  if (isValue(subjectValue) && Array.isArray(resourceValue)) {
993
709
  is = !resourceValue.includes(subjectValue);
994
710
  }
@@ -997,7 +713,7 @@ class AbilityRule {
997
713
  }
998
714
  }
999
715
  // contains
1000
- if (AbilityCondition_1.default.contains.isEqual(this.condition)) {
716
+ if (AbilityCondition.contains.isEqual(this.condition)) {
1001
717
  // array contains value
1002
718
  if (Array.isArray(subjectValue) && isValue(resourceValue)) {
1003
719
  is = subjectValue.includes(resourceValue);
@@ -1008,7 +724,7 @@ class AbilityRule {
1008
724
  }
1009
725
  }
1010
726
  // not contains
1011
- if (AbilityCondition_1.default.not_contains.isEqual(this.condition)) {
727
+ if (AbilityCondition.not_contains.isEqual(this.condition)) {
1012
728
  if (Array.isArray(subjectValue) && isValue(resourceValue)) {
1013
729
  is = !subjectValue.includes(resourceValue);
1014
730
  }
@@ -1017,7 +733,7 @@ class AbilityRule {
1017
733
  }
1018
734
  }
1019
735
  // length equals
1020
- if (AbilityCondition_1.default.length_equals.isEqual(this.condition)) {
736
+ if (AbilityCondition.length_equals.isEqual(this.condition)) {
1021
737
  // foo.bar == n
1022
738
  if (isValue(subjectValue) && typeof resourceValue === 'number') {
1023
739
  is = String(subjectValue).length === resourceValue;
@@ -1036,7 +752,7 @@ class AbilityRule {
1036
752
  }
1037
753
  }
1038
754
  // length greater than
1039
- if (AbilityCondition_1.default.length_greater_than.isEqual(this.condition)) {
755
+ if (AbilityCondition.length_greater_than.isEqual(this.condition)) {
1040
756
  // foo.bar > n
1041
757
  if (isValue(subjectValue) && typeof resourceValue === 'number') {
1042
758
  is = String(subjectValue).length > resourceValue;
@@ -1055,7 +771,7 @@ class AbilityRule {
1055
771
  }
1056
772
  }
1057
773
  // length greater than
1058
- if (AbilityCondition_1.default.length_less_than.isEqual(this.condition)) {
774
+ if (AbilityCondition.length_less_than.isEqual(this.condition)) {
1059
775
  // foo.bar < n
1060
776
  if (isValue(subjectValue) && typeof resourceValue === 'number') {
1061
777
  is = String(subjectValue).length < resourceValue;
@@ -1073,7 +789,7 @@ class AbilityRule {
1073
789
  is = subjectValue.length < resourceValue.length;
1074
790
  }
1075
791
  }
1076
- this.state = is ? AbilityMatch_1.default.match : AbilityMatch_1.default.mismatch;
792
+ this.state = is ? AbilityMatch.match : AbilityMatch.mismatch;
1077
793
  return this.state;
1078
794
  }
1079
795
  /**
@@ -1149,107 +865,96 @@ class AbilityRule {
1149
865
  toString() {
1150
866
  return `AbilityRule: ${this.name} condition: ${this.condition.code} subject: "${this.subject?.toString()}" resource: "${this.resource?.toString()}"`;
1151
867
  }
1152
- static fromJSON(config) {
1153
- return AbilityJSONParser_1.AbilityJSONParser.parseRule(config);
868
+ copyWith(props) {
869
+ return new AbilityRule({
870
+ id: props.id ?? this.id,
871
+ name: props.name ?? this.name,
872
+ subject: props.subject ?? this.subject,
873
+ resource: props.resource ?? this.resource,
874
+ condition: props.condition ?? this.condition,
875
+ });
1154
876
  }
1155
877
  static equals(subject, resource) {
1156
878
  return new AbilityRule({
1157
- condition: AbilityCondition_1.default.equals,
879
+ condition: AbilityCondition.equals,
1158
880
  subject,
1159
881
  resource,
1160
882
  });
1161
883
  }
1162
884
  static notEquals(subject, resource) {
1163
885
  return new AbilityRule({
1164
- condition: AbilityCondition_1.default.not_equals,
886
+ condition: AbilityCondition.not_equals,
1165
887
  subject,
1166
888
  resource,
1167
889
  });
1168
890
  }
1169
891
  static contains(subject, resource) {
1170
892
  return new AbilityRule({
1171
- condition: AbilityCondition_1.default.contains,
893
+ condition: AbilityCondition.contains,
1172
894
  subject,
1173
895
  resource,
1174
896
  });
1175
897
  }
1176
898
  static notContains(subject, resource) {
1177
899
  return new AbilityRule({
1178
- condition: AbilityCondition_1.default.not_contains,
900
+ condition: AbilityCondition.not_contains,
1179
901
  subject,
1180
902
  resource,
1181
903
  });
1182
904
  }
1183
905
  static notIn(subject, resource) {
1184
906
  return new AbilityRule({
1185
- condition: AbilityCondition_1.default.not_in,
907
+ condition: AbilityCondition.not_in,
1186
908
  subject,
1187
909
  resource,
1188
910
  });
1189
911
  }
1190
912
  static in(subject, resource) {
1191
913
  return new AbilityRule({
1192
- condition: AbilityCondition_1.default.in,
914
+ condition: AbilityCondition.in,
1193
915
  subject,
1194
916
  resource,
1195
917
  });
1196
918
  }
1197
919
  static notEqual(subject, resource) {
1198
920
  return new AbilityRule({
1199
- condition: AbilityCondition_1.default.not_equals,
921
+ condition: AbilityCondition.not_equals,
1200
922
  subject,
1201
923
  resource,
1202
924
  });
1203
925
  }
1204
926
  static lessThan(subject, resource) {
1205
927
  return new AbilityRule({
1206
- condition: AbilityCondition_1.default.less_than,
928
+ condition: AbilityCondition.less_than,
1207
929
  subject,
1208
930
  resource,
1209
931
  });
1210
932
  }
1211
933
  static lessOrEqual(subject, resource) {
1212
934
  return new AbilityRule({
1213
- condition: AbilityCondition_1.default.less_or_equal,
935
+ condition: AbilityCondition.less_or_equal,
1214
936
  subject,
1215
937
  resource,
1216
938
  });
1217
939
  }
1218
940
  static moreThan(subject, resource) {
1219
941
  return new AbilityRule({
1220
- condition: AbilityCondition_1.default.greater_than,
942
+ condition: AbilityCondition.greater_than,
1221
943
  subject,
1222
944
  resource,
1223
945
  });
1224
946
  }
1225
947
  static moreOrEqual(subject, resource) {
1226
948
  return new AbilityRule({
1227
- condition: AbilityCondition_1.default.greater_or_equal,
949
+ condition: AbilityCondition.greater_or_equal,
1228
950
  subject,
1229
951
  resource,
1230
952
  });
1231
953
  }
1232
954
  }
1233
- exports.AbilityRule = AbilityRule;
1234
- exports["default"] = AbilityRule;
1235
-
1236
-
1237
- /***/ }),
1238
955
 
1239
- /***/ 56:
1240
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
1241
-
1242
-
1243
- var __importDefault = (this && this.__importDefault) || function (mod) {
1244
- return (mod && mod.__esModule) ? mod : { "default": mod };
1245
- };
1246
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1247
- exports.AbilityRuleSet = void 0;
1248
- const AbilityCompare_1 = __importDefault(__webpack_require__(413));
1249
- const AbilityMatch_1 = __importDefault(__webpack_require__(247));
1250
- const AbilityJSONParser_1 = __webpack_require__(909);
1251
956
  class AbilityRuleSet {
1252
- state = AbilityMatch_1.default.pending;
957
+ state = AbilityMatch.pending;
1253
958
  /**
1254
959
  * List of rules
1255
960
  */
@@ -1260,7 +965,7 @@ class AbilityRuleSet {
1260
965
  * rules will be returns «permit» status and for the «or» - if\
1261
966
  * one of the rules returns as «permit»
1262
967
  */
1263
- compareMethod = AbilityCompare_1.default.and;
968
+ compareMethod = AbilityCompare.and;
1264
969
  /**
1265
970
  * Group name
1266
971
  */
@@ -1284,7 +989,7 @@ class AbilityRuleSet {
1284
989
  return this;
1285
990
  }
1286
991
  async check(resources, environment) {
1287
- this.state = AbilityMatch_1.default.mismatch;
992
+ this.state = AbilityMatch.mismatch;
1288
993
  if (!this.rules.length) {
1289
994
  return this.state;
1290
995
  }
@@ -1292,22 +997,22 @@ class AbilityRuleSet {
1292
997
  for (const rule of this.rules) {
1293
998
  const state = await rule.check(resources, environment);
1294
999
  ruleCheckStates.push(state);
1295
- if (AbilityCompare_1.default.and.isEqual(this.compareMethod) && AbilityMatch_1.default.mismatch.isEqual(state)) {
1000
+ if (AbilityCompare.and.isEqual(this.compareMethod) && AbilityMatch.mismatch.isEqual(state)) {
1296
1001
  return this.state; // mismatch
1297
1002
  }
1298
- if (AbilityCompare_1.default.or.isEqual(this.compareMethod) && AbilityMatch_1.default.match.isEqual(state)) {
1299
- this.state = AbilityMatch_1.default.match;
1003
+ if (AbilityCompare.or.isEqual(this.compareMethod) && AbilityMatch.match.isEqual(state)) {
1004
+ this.state = AbilityMatch.match;
1300
1005
  return this.state;
1301
1006
  }
1302
1007
  }
1303
- if (AbilityCompare_1.default.and.isEqual(this.compareMethod)) {
1304
- if (ruleCheckStates.every(s => AbilityMatch_1.default.match.isEqual(s))) {
1305
- this.state = AbilityMatch_1.default.match;
1008
+ if (AbilityCompare.and.isEqual(this.compareMethod)) {
1009
+ if (ruleCheckStates.every(s => AbilityMatch.match.isEqual(s))) {
1010
+ this.state = AbilityMatch.match;
1306
1011
  }
1307
1012
  }
1308
- if (AbilityCompare_1.default.or.isEqual(this.compareMethod)) {
1309
- if (ruleCheckStates.some(s => AbilityMatch_1.default.match.isEqual(s))) {
1310
- this.state = AbilityMatch_1.default.match;
1013
+ if (AbilityCompare.or.isEqual(this.compareMethod)) {
1014
+ if (ruleCheckStates.some(s => AbilityMatch.match.isEqual(s))) {
1015
+ this.state = AbilityMatch.match;
1311
1016
  }
1312
1017
  }
1313
1018
  return this.state;
@@ -1315,78 +1020,247 @@ class AbilityRuleSet {
1315
1020
  toString() {
1316
1021
  return `AbilityRuleSet: ${this.name} compareMethod: ${this.compareMethod.code}, rules: ${this.rules.map(rule => rule.toString()).join('\n')}`;
1317
1022
  }
1318
- /**
1319
- * Parse the config JSON format to Group class instance
1320
- */
1321
- static fromJSON(config) {
1322
- return AbilityJSONParser_1.AbilityJSONParser.parseRuleSet(config);
1023
+ copyWith(props) {
1024
+ const next = new AbilityRuleSet({
1025
+ id: props.id ?? this.id,
1026
+ name: props.name ?? this.name,
1027
+ compareMethod: props.compareMethod ?? this.compareMethod,
1028
+ });
1029
+ const nextRules = props.rules ?? this.rules;
1030
+ for (const rule of nextRules) {
1031
+ next.addRule(rule);
1032
+ }
1033
+ return next;
1323
1034
  }
1324
1035
  static and(rules) {
1325
1036
  return new AbilityRuleSet({
1326
- compareMethod: AbilityCompare_1.default.and,
1037
+ compareMethod: AbilityCompare.and,
1327
1038
  }).addRules(rules);
1328
1039
  }
1329
1040
  static or(rules) {
1330
1041
  return new AbilityRuleSet({
1331
- compareMethod: AbilityCompare_1.default.or,
1042
+ compareMethod: AbilityCompare.or,
1332
1043
  }).addRules(rules);
1333
1044
  }
1334
1045
  }
1335
- exports.AbilityRuleSet = AbilityRuleSet;
1336
- exports["default"] = AbilityRuleSet;
1337
-
1338
1046
 
1339
- /***/ }),
1340
-
1341
- /***/ 156:
1342
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
1343
-
1344
-
1345
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
1346
- if (k2 === undefined) k2 = k;
1347
- var desc = Object.getOwnPropertyDescriptor(m, k);
1348
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1349
- desc = { enumerable: true, get: function() { return m[k]; } };
1350
- }
1351
- Object.defineProperty(o, k2, desc);
1352
- }) : (function(o, m, k, k2) {
1353
- if (k2 === undefined) k2 = k;
1354
- o[k2] = m[k];
1355
- }));
1356
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
1357
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
1358
- };
1359
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1360
- __exportStar(__webpack_require__(301), exports);
1361
- __exportStar(__webpack_require__(413), exports);
1362
- __exportStar(__webpack_require__(167), exports);
1363
- __exportStar(__webpack_require__(216), exports);
1364
- __exportStar(__webpack_require__(247), exports);
1365
- __exportStar(__webpack_require__(147), exports);
1366
- __exportStar(__webpack_require__(278), exports);
1367
- __exportStar(__webpack_require__(179), exports);
1368
- __exportStar(__webpack_require__(634), exports);
1369
- __exportStar(__webpack_require__(306), exports);
1370
- __exportStar(__webpack_require__(56), exports);
1371
- __exportStar(__webpack_require__(221), exports);
1372
- __exportStar(__webpack_require__(941), exports);
1373
- __exportStar(__webpack_require__(6), exports);
1374
- __exportStar(__webpack_require__(829), exports);
1375
- __exportStar(__webpack_require__(909), exports);
1376
- __exportStar(__webpack_require__(577), exports);
1377
- __exportStar(__webpack_require__(10), exports);
1378
- __exportStar(__webpack_require__(325), exports);
1379
-
1380
-
1381
- /***/ }),
1047
+ class AbilityInMemoryCache {
1048
+ store = new Map();
1049
+ async get(key) {
1050
+ const entry = this.store.get(key);
1051
+ if (!entry)
1052
+ return undefined;
1053
+ if (Date.now() > entry.expires) {
1054
+ this.store.delete(key);
1055
+ return undefined;
1056
+ }
1057
+ return entry.value;
1058
+ }
1059
+ async set(key, value, ttlSeconds = 60) {
1060
+ this.store.set(key, {
1061
+ value,
1062
+ expires: Date.now() + ttlSeconds * 1000,
1063
+ });
1064
+ }
1065
+ serialize(input) {
1066
+ return this.fastHash(this.stableStringify(input));
1067
+ }
1068
+ async delete(key) {
1069
+ this.store.delete(key);
1070
+ }
1071
+ async clear() {
1072
+ this.store.clear();
1073
+ }
1074
+ async deleteByPrefix(prefix) {
1075
+ for (const key of this.store.keys()) {
1076
+ if (key.startsWith(prefix)) {
1077
+ this.store.delete(key);
1078
+ }
1079
+ }
1080
+ }
1081
+ fastHash(str) {
1082
+ let hash = 5381;
1083
+ for (let i = 0; i < str.length; i++) {
1084
+ hash = (hash * 33) ^ str.charCodeAt(i);
1085
+ }
1086
+ return (hash >>> 0).toString(36);
1087
+ }
1088
+ stableStringify(obj) {
1089
+ if (obj === null)
1090
+ return 'null';
1091
+ const type = typeof obj;
1092
+ if (type === 'string')
1093
+ return JSON.stringify(obj);
1094
+ if (type === 'number' || type === 'boolean')
1095
+ return String(obj);
1096
+ if (type === 'undefined')
1097
+ return 'undefined';
1098
+ if (Array.isArray(obj)) {
1099
+ let out = '[';
1100
+ for (let i = 0; i < obj.length; i++) {
1101
+ if (i > 0)
1102
+ out += ',';
1103
+ out += this.stableStringify(obj[i]);
1104
+ }
1105
+ return out + ']';
1106
+ }
1107
+ const keys = Object.keys(obj);
1108
+ keys.sort();
1109
+ let out = '{';
1110
+ for (let i = 0; i < keys.length; i++) {
1111
+ const k = keys[i];
1112
+ if (i > 0)
1113
+ out += ',';
1114
+ out += k + ':' + this.stableStringify(obj[k]);
1115
+ }
1116
+ return out + '}';
1117
+ }
1118
+ }
1382
1119
 
1383
- /***/ 10:
1384
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1120
+ class AbilityJSONParser {
1121
+ /**
1122
+ * Parses an array of policy configurations into an array of AbilityPolicy instances.
1123
+ * @param configs - Array of policy configurations
1124
+ * @returns Array of AbilityPolicy instances
1125
+ */
1126
+ static parse(configs) {
1127
+ return configs.map(config => AbilityJSONParser.parsePolicy(config));
1128
+ }
1129
+ static parsePolicy(config) {
1130
+ const { id, name, ruleSet, compareMethod, permission, effect } = config;
1131
+ // Create the empty policy
1132
+ const policy = new AbilityPolicy({
1133
+ name,
1134
+ id,
1135
+ permission: permission,
1136
+ effect: new AbilityPolicyEffect(effect),
1137
+ });
1138
+ policy.compareMethod = new AbilityCompare(compareMethod);
1139
+ ruleSet.forEach(ruleSetConfig => {
1140
+ policy.addRuleSet(AbilityJSONParser.parseRuleSet(ruleSetConfig));
1141
+ });
1142
+ return policy;
1143
+ }
1144
+ static parseRule(config) {
1145
+ const { id, name, subject, resource, condition } = config;
1146
+ return new AbilityRule({
1147
+ id,
1148
+ name,
1149
+ subject,
1150
+ resource,
1151
+ condition: new AbilityCondition(condition),
1152
+ });
1153
+ }
1154
+ /**
1155
+ * Parse the config JSON format to Group class instance
1156
+ */
1157
+ static parseRuleSet(config) {
1158
+ const { id, name, rules, compareMethod } = config;
1159
+ const ruleSet = new AbilityRuleSet({
1160
+ compareMethod: new AbilityCompare(compareMethod),
1161
+ name,
1162
+ id,
1163
+ });
1164
+ // Adding rules if exists
1165
+ if (rules && rules.length > 0) {
1166
+ const abilityRules = rules.map(ruleConfig => AbilityJSONParser.parseRule(ruleConfig));
1167
+ ruleSet.addRules(abilityRules);
1168
+ }
1169
+ return ruleSet;
1170
+ }
1171
+ static ruleToJSON(rule) {
1172
+ return {
1173
+ id: rule.id,
1174
+ name: rule.name,
1175
+ subject: rule.subject,
1176
+ resource: rule.resource,
1177
+ condition: rule.condition.code,
1178
+ };
1179
+ }
1180
+ static ruleSetToJSON(ruleSet) {
1181
+ return {
1182
+ id: ruleSet.id.toString(),
1183
+ name: ruleSet.name.toString(),
1184
+ compareMethod: ruleSet.compareMethod.code.toString(),
1185
+ rules: ruleSet.rules.map(rule => AbilityJSONParser.ruleToJSON(rule)),
1186
+ };
1187
+ }
1188
+ static policyToJSON(policy) {
1189
+ return {
1190
+ id: policy.id.toString(),
1191
+ name: policy.name.toString(),
1192
+ compareMethod: policy.compareMethod.code.toString(),
1193
+ ruleSet: policy.ruleSet.map(ruleSet => AbilityJSONParser.ruleSetToJSON(ruleSet)),
1194
+ permission: policy.permission,
1195
+ effect: policy.effect.code,
1196
+ };
1197
+ }
1198
+ static toJSON(policies) {
1199
+ return policies.map(policy => AbilityJSONParser.policyToJSON(policy));
1200
+ }
1201
+ }
1385
1202
 
1203
+ /**
1204
+ * Represents a single token produced by the Ability DSL lexer.
1205
+ * Each token carries a type (e.g., EFFECT, IDENTIFIER, STRING) and its raw string value.
1206
+ */
1207
+ class AbilityDSLToken extends AbilityCode {
1208
+ /** The literal text of the token as it appeared in the input (e.g., "permit", "user.roles", "admin"). */
1209
+ value = '';
1210
+ /** The line number in DSL */
1211
+ line = 1;
1212
+ /** The column in dsl */
1213
+ column = 1;
1214
+ constructor(type, value, line, column) {
1215
+ super(type);
1216
+ this.value = value;
1217
+ this.line = line;
1218
+ this.column = column;
1219
+ }
1220
+ /**
1221
+ * Returns a human-readable representation of the token, useful for debugging.
1222
+ * Example output: "AbilityDSLToken([EFFECT] permit"
1223
+ */
1224
+ toString() {
1225
+ return `AbilityDSLToken([${this.code}] "${this.value}" at ${this.line}:${this.column})`;
1226
+ }
1227
+ static EFFECT = 'EFFECT';
1228
+ static IF = 'IF';
1229
+ static PERMISSION = 'PERMISSION';
1230
+ static IDENTIFIER = 'IDENTIFIER';
1231
+ static COLON = 'COLON';
1232
+ static COMMA = 'COMMA';
1233
+ static DOT = 'DOT';
1234
+ static LBRACKET = 'LBRACKET';
1235
+ static RBRACKET = 'RBRACKET';
1236
+ static ALL = 'ALL';
1237
+ static ANY = 'ANY';
1238
+ static OF = 'OF';
1239
+ static EOF = 'EOF';
1240
+ static COMMENT = 'COMMENT';
1241
+ static EQ = 'EQ';
1242
+ static CONTAINS = 'CONTAINS';
1243
+ static IN = 'IN';
1244
+ static NOT_IN = 'NOT_IN';
1245
+ static NOT_CONTAINS = 'NOT_CONTAINS';
1246
+ static GT = 'GT';
1247
+ static GTE = 'GTE';
1248
+ static LT = 'LT';
1249
+ static LTE = 'LTE';
1250
+ static NULL = 'NULL';
1251
+ static EQ_NULL = 'EQ_NULL';
1252
+ static NOT_EQ_NULL = 'NOT_EQ_NULL';
1253
+ static LEN_GT = 'LEN_GT';
1254
+ static LEN_LT = 'LEN_LT';
1255
+ static LEN_EQ = 'LEN_EQ';
1256
+ static NOT_EQ = 'NOT_EQ';
1257
+ static STRING = 'STRING';
1258
+ static NUMBER = 'NUMBER';
1259
+ static BOOLEAN = 'BOOLEAN';
1260
+ static SYMBOL = 'SYMBOL';
1261
+ static KEYWORD = 'KEYWORD';
1262
+ }
1386
1263
 
1387
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1388
- exports.AbilityDSLLexer = void 0;
1389
- const AbilityDSLToken_1 = __webpack_require__(325);
1390
1264
  class AbilityDSLLexer {
1391
1265
  input;
1392
1266
  pos = 0;
@@ -1454,7 +1328,7 @@ class AbilityDSLLexer {
1454
1328
  }
1455
1329
  throw new Error(`Unexpected character '${char}' at ${this.line}:${this.column}`);
1456
1330
  }
1457
- this.tokens.push(new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.EOF, '', this.line, this.column));
1331
+ this.tokens.push(new AbilityDSLToken(AbilityDSLToken.EOF, '', this.line, this.column));
1458
1332
  return this.tokens;
1459
1333
  }
1460
1334
  readComment() {
@@ -1465,7 +1339,7 @@ class AbilityDSLLexer {
1465
1339
  while (!this.isAtEnd() && !this.isNewline()) {
1466
1340
  value += this.advance();
1467
1341
  }
1468
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.COMMENT, value.trim(), startLine, startColumn);
1342
+ return new AbilityDSLToken(AbilityDSLToken.COMMENT, value.trim(), startLine, startColumn);
1469
1343
  }
1470
1344
  readString() {
1471
1345
  const startLine = this.line;
@@ -1485,7 +1359,7 @@ class AbilityDSLLexer {
1485
1359
  continue;
1486
1360
  }
1487
1361
  if (char === quote) {
1488
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.STRING, value, startLine, startColumn);
1362
+ return new AbilityDSLToken(AbilityDSLToken.STRING, value, startLine, startColumn);
1489
1363
  }
1490
1364
  value += char;
1491
1365
  }
@@ -1499,7 +1373,7 @@ class AbilityDSLLexer {
1499
1373
  this.advance();
1500
1374
  }
1501
1375
  const value = this.input.slice(start, this.pos);
1502
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.NUMBER, value, startLine, startColumn);
1376
+ return new AbilityDSLToken(AbilityDSLToken.NUMBER, value, startLine, startColumn);
1503
1377
  }
1504
1378
  readSymbol() {
1505
1379
  const startLine = this.line;
@@ -1507,41 +1381,41 @@ class AbilityDSLLexer {
1507
1381
  const char = this.advance();
1508
1382
  switch (char) {
1509
1383
  case '.':
1510
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.DOT, char, startLine, startColumn);
1384
+ return new AbilityDSLToken(AbilityDSLToken.DOT, char, startLine, startColumn);
1511
1385
  case ':':
1512
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.COLON, char, startLine, startColumn);
1386
+ return new AbilityDSLToken(AbilityDSLToken.COLON, char, startLine, startColumn);
1513
1387
  case ',':
1514
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.COMMA, char, startLine, startColumn);
1388
+ return new AbilityDSLToken(AbilityDSLToken.COMMA, char, startLine, startColumn);
1515
1389
  case '[':
1516
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.LBRACKET, char, startLine, startColumn);
1390
+ return new AbilityDSLToken(AbilityDSLToken.LBRACKET, char, startLine, startColumn);
1517
1391
  case ']':
1518
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.RBRACKET, char, startLine, startColumn);
1392
+ return new AbilityDSLToken(AbilityDSLToken.RBRACKET, char, startLine, startColumn);
1519
1393
  case '>':
1520
1394
  if (this.peek() === '=') {
1521
1395
  this.advance();
1522
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '>=', startLine, startColumn);
1396
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '>=', startLine, startColumn);
1523
1397
  }
1524
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '>', startLine, startColumn);
1398
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '>', startLine, startColumn);
1525
1399
  case '<':
1526
1400
  if (this.peek() === '=') {
1527
1401
  this.advance();
1528
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '<=', startLine, startColumn);
1402
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '<=', startLine, startColumn);
1529
1403
  }
1530
1404
  if (this.peek() === '>') {
1531
1405
  this.advance();
1532
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '<>', startLine, startColumn);
1406
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '<>', startLine, startColumn);
1533
1407
  }
1534
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '<', startLine, startColumn);
1408
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '<', startLine, startColumn);
1535
1409
  case '=':
1536
1410
  if (this.peek() === '=') {
1537
1411
  this.advance();
1538
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '==', startLine, startColumn);
1412
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '==', startLine, startColumn);
1539
1413
  }
1540
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '=', startLine, startColumn);
1414
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '=', startLine, startColumn);
1541
1415
  case '!':
1542
1416
  if (this.peek() === '=') {
1543
1417
  this.advance();
1544
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '!=', startLine, startColumn);
1418
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '!=', startLine, startColumn);
1545
1419
  }
1546
1420
  throw new Error(`Unexpected symbol '!' at ${this.line}:${this.column}`);
1547
1421
  default:
@@ -1570,52 +1444,52 @@ class AbilityDSLLexer {
1570
1444
  // Если есть точка — это путь (identifier или permission)
1571
1445
  if (word.includes('.')) {
1572
1446
  const last = this.tokens[this.tokens.length - 1];
1573
- if (last?.code === AbilityDSLToken_1.AbilityDSLToken.EFFECT) {
1447
+ if (last?.code === AbilityDSLToken.EFFECT) {
1574
1448
  if (word.startsWith('permission.')) {
1575
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1449
+ return new AbilityDSLToken(AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1576
1450
  }
1577
1451
  }
1578
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1452
+ return new AbilityDSLToken(AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1579
1453
  }
1580
1454
  // Ключевые слова
1581
1455
  if (this.keywords.has(word)) {
1582
1456
  // Эффекты
1583
1457
  if (word === 'permit' || word === 'allow') {
1584
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.EFFECT, 'permit', startLine, startColumn);
1458
+ return new AbilityDSLToken(AbilityDSLToken.EFFECT, 'permit', startLine, startColumn);
1585
1459
  }
1586
1460
  if (word === 'deny' || word === 'forbidden') {
1587
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.EFFECT, 'deny', startLine, startColumn);
1461
+ return new AbilityDSLToken(AbilityDSLToken.EFFECT, 'deny', startLine, startColumn);
1588
1462
  }
1589
1463
  // Групповые ключевые слова
1590
1464
  if (word === 'all') {
1591
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.ALL, word, startLine, startColumn);
1465
+ return new AbilityDSLToken(AbilityDSLToken.ALL, word, startLine, startColumn);
1592
1466
  }
1593
1467
  if (word === 'any') {
1594
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.ANY, word, startLine, startColumn);
1468
+ return new AbilityDSLToken(AbilityDSLToken.ANY, word, startLine, startColumn);
1595
1469
  }
1596
1470
  if (word === 'of') {
1597
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.OF, word, startLine, startColumn);
1471
+ return new AbilityDSLToken(AbilityDSLToken.OF, word, startLine, startColumn);
1598
1472
  }
1599
1473
  if (word === 'if') {
1600
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.IF, word, startLine, startColumn);
1474
+ return new AbilityDSLToken(AbilityDSLToken.IF, word, startLine, startColumn);
1601
1475
  }
1602
1476
  // Булевы и null
1603
1477
  if (word === 'true' || word === 'false') {
1604
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.BOOLEAN, word, startLine, startColumn);
1478
+ return new AbilityDSLToken(AbilityDSLToken.BOOLEAN, word, startLine, startColumn);
1605
1479
  }
1606
1480
  if (word === 'null') {
1607
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.NULL, word, startLine, startColumn);
1481
+ return new AbilityDSLToken(AbilityDSLToken.NULL, word, startLine, startColumn);
1608
1482
  }
1609
1483
  // Остальные ключевые слова (contains, in, equals, greater, less, not, is, or, than, equal)
1610
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.KEYWORD, word, startLine, startColumn);
1484
+ return new AbilityDSLToken(AbilityDSLToken.KEYWORD, word, startLine, startColumn);
1611
1485
  }
1612
1486
  // Если после EFFECT и нет точки — действие (например, "create")
1613
1487
  const lastToken = this.tokens[this.tokens.length - 1];
1614
- if (lastToken?.code === AbilityDSLToken_1.AbilityDSLToken.EFFECT) {
1615
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1488
+ if (lastToken?.code === AbilityDSLToken.EFFECT) {
1489
+ return new AbilityDSLToken(AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1616
1490
  }
1617
1491
  // Обычный идентификатор
1618
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1492
+ return new AbilityDSLToken(AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1619
1493
  }
1620
1494
  skipWhitespace() {
1621
1495
  while (!this.isAtEnd() && /\s/.test(this.peek())) {
@@ -1648,33 +1522,73 @@ class AbilityDSLLexer {
1648
1522
  }
1649
1523
  return ch;
1650
1524
  }
1651
- isAtEnd() {
1652
- return this.pos >= this.input.length;
1525
+ isAtEnd() {
1526
+ return this.pos >= this.input.length;
1527
+ }
1528
+ }
1529
+
1530
+ class AbilityDSLSyntaxError extends Error {
1531
+ line;
1532
+ column;
1533
+ context;
1534
+ details;
1535
+ _formattedMessage;
1536
+ _originalStack;
1537
+ constructor(line, column, context, // строка DSL + ^ + соседние строки
1538
+ details) {
1539
+ super(details.split('\n')[0]); // message = только первая строка
1540
+ this.line = line;
1541
+ this.column = column;
1542
+ this.context = context;
1543
+ this.details = details;
1544
+ this.name = 'AbilityDSLSyntaxError';
1545
+ if (Error.captureStackTrace) {
1546
+ Error.captureStackTrace(this, AbilityDSLSyntaxError);
1547
+ }
1548
+ this._originalStack = this.stack;
1549
+ this._formattedMessage = this.formatMessage();
1550
+ Object.defineProperty(this, 'stack', {
1551
+ get: () => this._formattedMessage,
1552
+ configurable: true,
1553
+ });
1554
+ }
1555
+ static supportsColor() {
1556
+ return typeof process !== 'undefined' && process.stdout?.isTTY;
1557
+ }
1558
+ formatMessage() {
1559
+ const useColor = AbilityDSLSyntaxError.supportsColor();
1560
+ const BOLD = useColor ? '\x1b[1m' : '';
1561
+ const RED = useColor ? '\x1b[31m' : '';
1562
+ const ORANGE = useColor ? '\x1b[33;1m' : '';
1563
+ const GRAY = useColor ? '\x1b[90m' : '';
1564
+ const RESET = useColor ? '\x1b[0m' : '';
1565
+ const lines = this.context.split('\n');
1566
+ // Find line with ^
1567
+ const pointerIndex = lines.findIndex(l => l.includes('^') || l.includes('~'));
1568
+ const commentIndex = lines.findIndex(l => l.trim().includes('#'));
1569
+ const formattedLines = lines.map((line, idx) => {
1570
+ if (idx === pointerIndex - 1) {
1571
+ // Error line
1572
+ return `${BOLD}${ORANGE}${line}${RESET}`;
1573
+ }
1574
+ if (idx === pointerIndex) {
1575
+ // Error with ~~~~~
1576
+ return `${RED}${line}${RESET}`;
1577
+ }
1578
+ // Comments # ...
1579
+ if (idx === commentIndex) {
1580
+ return `${GRAY}${line}${RESET}`;
1581
+ }
1582
+ return line;
1583
+ });
1584
+ const contextBlock = formattedLines.join('\n');
1585
+ return `${BOLD}${RED}${this.name}: ${this.details}${RESET}\n\n` + contextBlock;
1586
+ }
1587
+ toString() {
1588
+ return this._formattedMessage;
1653
1589
  }
1654
1590
  }
1655
- exports.AbilityDSLLexer = AbilityDSLLexer;
1656
-
1657
-
1658
- /***/ }),
1659
1591
 
1660
- /***/ 577:
1661
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
1662
-
1663
-
1664
- var __importDefault = (this && this.__importDefault) || function (mod) {
1665
- return (mod && mod.__esModule) ? mod : { "default": mod };
1666
- };
1667
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1668
- exports.AbilityDSLParser = void 0;
1669
- const AbilityCompare_1 = __importDefault(__webpack_require__(413));
1670
- const AbilityCondition_1 = __importDefault(__webpack_require__(167));
1671
- const AbilityPolicy_1 = __importDefault(__webpack_require__(278));
1672
- const AbilityPolicyEffect_1 = __importDefault(__webpack_require__(179));
1673
- const AbilityRule_1 = __importDefault(__webpack_require__(306));
1674
- const AbilityRuleSet_1 = __importDefault(__webpack_require__(56));
1675
- const AbilityDSLLexer_1 = __webpack_require__(10);
1676
- const AbilityDSLToken_1 = __webpack_require__(325);
1677
- const AbilityDSLSyntaxError_1 = __webpack_require__(883);
1678
1592
  /**
1679
1593
  * Parser for the Ability DSL.
1680
1594
  *
@@ -1708,7 +1622,7 @@ class AbilityDSLParser {
1708
1622
  */
1709
1623
  parse() {
1710
1624
  // Tokenize the entire DSL string.
1711
- this.tokens = new AbilityDSLLexer_1.AbilityDSLLexer(this.dsl).tokenize();
1625
+ this.tokens = new AbilityDSLLexer(this.dsl).tokenize();
1712
1626
  this.pos = 0;
1713
1627
  const policies = [];
1714
1628
  // Keep parsing until we've consumed all tokens.
@@ -1736,29 +1650,29 @@ class AbilityDSLParser {
1736
1650
  this.consumeLeadingComments();
1737
1651
  const meta = this.takeAnnotations();
1738
1652
  // Effect: "permit" or "deny"
1739
- const effectToken = this.consume(AbilityDSLToken_1.AbilityDSLToken.EFFECT, 'Expected effect');
1653
+ const effectToken = this.consume(AbilityDSLToken.EFFECT, 'Expected effect');
1740
1654
  const effect = effectToken.value;
1741
1655
  // Permission: e.g. "order.update"
1742
- const permissionToken = this.consume(AbilityDSLToken_1.AbilityDSLToken.PERMISSION, 'Expected permission');
1656
+ const permissionToken = this.consume(AbilityDSLToken.PERMISSION, 'Expected permission');
1743
1657
  const permission = permissionToken.value;
1744
1658
  if (!permission.startsWith('permission.')) {
1745
1659
  return this.syntaxError(`Unexpected token. The permission key, must be starts with prefix \`permission.\`, but got \`${permission}\`.\nDid you mean \`permission.${permission}\`?`, permissionToken);
1746
1660
  }
1747
1661
  // "if" keyword
1748
- this.consume(AbilityDSLToken_1.AbilityDSLToken.IF, 'Expected "if"');
1662
+ this.consume(AbilityDSLToken.IF, 'Expected "if"');
1749
1663
  // Group selector: "all" or "any" – determines how the top‑level rule sets are combined.
1750
- const compareToken = this.consumeOneOf([AbilityDSLToken_1.AbilityDSLToken.ALL, AbilityDSLToken_1.AbilityDSLToken.ANY], 'Expected "all" or "any"');
1751
- const compareMethod = compareToken.code === AbilityDSLToken_1.AbilityDSLToken.ALL ? AbilityCompare_1.default.and : AbilityCompare_1.default.or;
1664
+ const compareToken = this.consumeOneOf([AbilityDSLToken.ALL, AbilityDSLToken.ANY], 'Expected "all" or "any"');
1665
+ const compareMethod = compareToken.code === AbilityDSLToken.ALL ? AbilityCompare.and : AbilityCompare.or;
1752
1666
  // Colon after the group keyword
1753
- this.consume(AbilityDSLToken_1.AbilityDSLToken.COLON, 'Expected ":"');
1667
+ this.consume(AbilityDSLToken.COLON, 'Expected ":"');
1754
1668
  // Parse the list of rule sets (each "all of:" or "any of:" block)
1755
1669
  const ruleSets = this.parseRuleSets(compareMethod);
1756
1670
  // Construct the policy instance.
1757
- return new AbilityPolicy_1.default({
1671
+ return new AbilityPolicy({
1758
1672
  id: `${effect}:${permission}:${Math.random()}`,
1759
1673
  name: meta.name ?? `${effect} ${permission}`,
1760
1674
  permission: permission.replace(/^permission\./, ''),
1761
- effect: effect === 'permit' ? AbilityPolicyEffect_1.default.permit : AbilityPolicyEffect_1.default.deny,
1675
+ effect: effect === 'permit' ? AbilityPolicyEffect.permit : AbilityPolicyEffect.deny,
1762
1676
  compareMethod,
1763
1677
  }).addRuleSets(ruleSets);
1764
1678
  }
@@ -1779,7 +1693,7 @@ class AbilityDSLParser {
1779
1693
  }
1780
1694
  // Иначе — implicit group (all-of по умолчанию)
1781
1695
  const meta = this.takeAnnotations();
1782
- const group = new AbilityRuleSet_1.default({
1696
+ const group = new AbilityRuleSet({
1783
1697
  compareMethod: policyCompareMethod,
1784
1698
  name: meta.name,
1785
1699
  });
@@ -1789,7 +1703,7 @@ class AbilityDSLParser {
1789
1703
  if (this.isStartOfGroup() || this.isStartOfPolicy()) {
1790
1704
  break;
1791
1705
  }
1792
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER)) {
1706
+ if (this.check(AbilityDSLToken.IDENTIFIER)) {
1793
1707
  group.addRule(this.parseRule());
1794
1708
  }
1795
1709
  else {
@@ -1806,19 +1720,19 @@ class AbilityDSLParser {
1806
1720
  parseGroup() {
1807
1721
  this.consumeLeadingComments();
1808
1722
  const meta = this.takeAnnotations();
1809
- const compareToken = this.consumeOneOf([AbilityDSLToken_1.AbilityDSLToken.ALL, AbilityDSLToken_1.AbilityDSLToken.ANY], 'Expected "all" or "any"');
1810
- const compareMethod = compareToken.code === AbilityDSLToken_1.AbilityDSLToken.ALL ? AbilityCompare_1.default.and : AbilityCompare_1.default.or;
1811
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.OF)) {
1723
+ const compareToken = this.consumeOneOf([AbilityDSLToken.ALL, AbilityDSLToken.ANY], 'Expected "all" or "any"');
1724
+ const compareMethod = compareToken.code === AbilityDSLToken.ALL ? AbilityCompare.and : AbilityCompare.or;
1725
+ if (this.check(AbilityDSLToken.OF)) {
1812
1726
  this.advance();
1813
1727
  }
1814
- this.consume(AbilityDSLToken_1.AbilityDSLToken.COLON, 'Expected ":"');
1815
- const group = new AbilityRuleSet_1.default({ compareMethod, name: meta.name });
1728
+ this.consume(AbilityDSLToken.COLON, 'Expected ":"');
1729
+ const group = new AbilityRuleSet({ compareMethod, name: meta.name });
1816
1730
  while (!this.isAtEnd()) {
1817
1731
  this.consumeLeadingComments();
1818
1732
  if (this.isStartOfGroup() || this.isStartOfPolicy()) {
1819
1733
  break;
1820
1734
  }
1821
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER)) {
1735
+ if (this.check(AbilityDSLToken.IDENTIFIER)) {
1822
1736
  group.addRule(this.parseRule());
1823
1737
  }
1824
1738
  else {
@@ -1836,19 +1750,19 @@ class AbilityDSLParser {
1836
1750
  parseRule() {
1837
1751
  this.consumeLeadingComments();
1838
1752
  const meta = this.takeAnnotations();
1839
- if (!this.check(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER)) {
1753
+ if (!this.check(AbilityDSLToken.IDENTIFIER)) {
1840
1754
  this.syntaxError(`Expected identifier, got ${this.peek().code}`, this.peek());
1841
1755
  }
1842
1756
  // Subject (e.g., "user.roles")
1843
- const subject = this.consume(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER, 'Expected field').value;
1757
+ const subject = this.consume(AbilityDSLToken.IDENTIFIER, 'Expected field').value;
1844
1758
  // Operator (e.g., "contains", "equals", "is not null")
1845
1759
  const { condition, operator } = this.parseConditionOperator();
1846
1760
  let resource;
1847
1761
  let beforePos = this.pos;
1848
1762
  // Special operators that don't consume a value token.
1849
- if (operator === AbilityDSLToken_1.AbilityDSLToken.EQ_NULL ||
1850
- operator === AbilityDSLToken_1.AbilityDSLToken.NOT_EQ_NULL ||
1851
- operator === AbilityDSLToken_1.AbilityDSLToken.NULL) {
1763
+ if (operator === AbilityDSLToken.EQ_NULL ||
1764
+ operator === AbilityDSLToken.NOT_EQ_NULL ||
1765
+ operator === AbilityDSLToken.NULL) {
1852
1766
  resource = null;
1853
1767
  }
1854
1768
  else {
@@ -1860,11 +1774,11 @@ class AbilityDSLParser {
1860
1774
  this.consumeLeadingComments();
1861
1775
  const resourceToken = this.tokens[beforePos];
1862
1776
  if (typeof resource === 'string' &&
1863
- resourceToken.code === AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER &&
1777
+ resourceToken.code === AbilityDSLToken.IDENTIFIER &&
1864
1778
  !resourceToken.value.includes('.')) {
1865
- this.syntaxError(`Expected comparison operator or value, got \`${resource}\``, this.tokens[beforePos], [AbilityDSLToken_1.AbilityDSLToken.KEYWORD]);
1779
+ this.syntaxError(`Expected comparison operator or value, got \`${resource}\``, this.tokens[beforePos], [AbilityDSLToken.KEYWORD]);
1866
1780
  }
1867
- return new AbilityRule_1.default({
1781
+ return new AbilityRule({
1868
1782
  subject,
1869
1783
  resource,
1870
1784
  condition,
@@ -1882,32 +1796,32 @@ class AbilityDSLParser {
1882
1796
  const savedPos = this.pos;
1883
1797
  // "length equals"
1884
1798
  if (this.matchWord('length') && this.matchWord('equals')) {
1885
- return { condition: AbilityCondition_1.default.length_equals, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_EQ };
1799
+ return { condition: AbilityCondition.length_equals, operator: AbilityDSLToken.LEN_EQ };
1886
1800
  }
1887
1801
  this.pos = savedPos;
1888
1802
  // "length ="
1889
1803
  if (this.matchWord('length') && this.matchSymbol('=')) {
1890
- return { condition: AbilityCondition_1.default.length_equals, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_EQ };
1804
+ return { condition: AbilityCondition.length_equals, operator: AbilityDSLToken.LEN_EQ };
1891
1805
  }
1892
1806
  this.pos = savedPos;
1893
1807
  // "length greater than"
1894
1808
  if (this.matchWord('length') && this.matchWord('greater') && this.matchWord('than')) {
1895
- return { condition: AbilityCondition_1.default.length_greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_GT };
1809
+ return { condition: AbilityCondition.length_greater_than, operator: AbilityDSLToken.LEN_GT };
1896
1810
  }
1897
1811
  this.pos = savedPos;
1898
1812
  // "length >"
1899
1813
  if (this.matchWord('length') && this.matchSymbol('>')) {
1900
- return { condition: AbilityCondition_1.default.length_greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_GT };
1814
+ return { condition: AbilityCondition.length_greater_than, operator: AbilityDSLToken.LEN_GT };
1901
1815
  }
1902
1816
  this.pos = savedPos;
1903
1817
  // "length less than"
1904
1818
  if (this.matchWord('length') && this.matchWord('less') && this.matchWord('than')) {
1905
- return { condition: AbilityCondition_1.default.length_less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_LT };
1819
+ return { condition: AbilityCondition.length_less_than, operator: AbilityDSLToken.LEN_LT };
1906
1820
  }
1907
1821
  this.pos = savedPos;
1908
1822
  // "length <"
1909
1823
  if (this.matchWord('length') && this.matchSymbol('<')) {
1910
- return { condition: AbilityCondition_1.default.length_less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_LT };
1824
+ return { condition: AbilityCondition.length_less_than, operator: AbilityDSLToken.LEN_LT };
1911
1825
  }
1912
1826
  this.pos = savedPos;
1913
1827
  // "greater than or equal"
@@ -1915,12 +1829,12 @@ class AbilityDSLParser {
1915
1829
  this.matchWord('than') &&
1916
1830
  this.matchWord('or') &&
1917
1831
  this.matchWord('equal')) {
1918
- return { condition: AbilityCondition_1.default.greater_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.GTE };
1832
+ return { condition: AbilityCondition.greater_or_equal, operator: AbilityDSLToken.GTE };
1919
1833
  }
1920
1834
  this.pos = savedPos;
1921
1835
  // greater than
1922
1836
  if (this.matchWord('greater') && this.matchWord('than')) {
1923
- return { condition: AbilityCondition_1.default.greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.GT };
1837
+ return { condition: AbilityCondition.greater_than, operator: AbilityDSLToken.GT };
1924
1838
  }
1925
1839
  this.pos = savedPos;
1926
1840
  // less than or equal
@@ -1928,143 +1842,141 @@ class AbilityDSLParser {
1928
1842
  this.matchWord('than') &&
1929
1843
  this.matchWord('or') &&
1930
1844
  this.matchWord('equal')) {
1931
- return { condition: AbilityCondition_1.default.less_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.LTE };
1845
+ return { condition: AbilityCondition.less_or_equal, operator: AbilityDSLToken.LTE };
1932
1846
  }
1933
1847
  this.pos = savedPos;
1934
1848
  // less than
1935
1849
  if (this.matchWord('less') && this.matchWord('than')) {
1936
- return { condition: AbilityCondition_1.default.less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LT };
1850
+ return { condition: AbilityCondition.less_than, operator: AbilityDSLToken.LT };
1937
1851
  }
1938
1852
  this.pos = savedPos;
1939
1853
  // "not contains"
1940
1854
  if (this.matchWord('not') && this.matchWord('contains')) {
1941
1855
  return {
1942
- condition: AbilityCondition_1.default.not_contains,
1943
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_CONTAINS,
1856
+ condition: AbilityCondition.not_contains,
1857
+ operator: AbilityDSLToken.NOT_CONTAINS,
1944
1858
  };
1945
1859
  }
1946
1860
  this.pos = savedPos;
1947
1861
  // "not includes"
1948
1862
  if (this.matchWord('not') && this.matchWord('includes')) {
1949
1863
  return {
1950
- condition: AbilityCondition_1.default.not_contains,
1951
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_CONTAINS,
1864
+ condition: AbilityCondition.not_contains,
1865
+ operator: AbilityDSLToken.NOT_CONTAINS,
1952
1866
  };
1953
1867
  }
1954
1868
  this.pos = savedPos;
1955
1869
  // "not includes"
1956
1870
  if (this.matchWord('not') && this.matchWord('has')) {
1957
1871
  return {
1958
- condition: AbilityCondition_1.default.not_contains,
1959
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_CONTAINS,
1872
+ condition: AbilityCondition.not_contains,
1873
+ operator: AbilityDSLToken.NOT_CONTAINS,
1960
1874
  };
1961
1875
  }
1962
1876
  this.pos = savedPos;
1963
1877
  // "is equals"
1964
1878
  if (this.matchWord('is') && this.matchWord('equals')) {
1965
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1879
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
1966
1880
  }
1967
1881
  this.pos = savedPos;
1968
1882
  // not equal
1969
1883
  if (this.matchWord('not') && this.matchWord('equals')) {
1970
- return { condition: AbilityCondition_1.default.not_equals, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ };
1884
+ return { condition: AbilityCondition.not_equals, operator: AbilityDSLToken.NOT_EQ };
1971
1885
  }
1972
1886
  this.pos = savedPos;
1973
1887
  // is not equals
1974
1888
  if (this.matchWord('is') && this.matchWord('not') && this.matchWord('equals')) {
1975
- return { condition: AbilityCondition_1.default.not_equals, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ };
1889
+ return { condition: AbilityCondition.not_equals, operator: AbilityDSLToken.NOT_EQ };
1976
1890
  }
1977
1891
  this.pos = savedPos;
1978
1892
  // is in
1979
1893
  if (this.matchWord('is') && this.matchWord('in')) {
1980
- return { condition: AbilityCondition_1.default.in, operator: AbilityDSLToken_1.AbilityDSLToken.IN };
1894
+ return { condition: AbilityCondition.in, operator: AbilityDSLToken.IN };
1981
1895
  }
1982
1896
  this.pos = savedPos;
1983
1897
  // not in
1984
1898
  if (this.matchWord('not') && this.matchWord('in')) {
1985
- return { condition: AbilityCondition_1.default.not_in, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_IN };
1899
+ return { condition: AbilityCondition.not_in, operator: AbilityDSLToken.NOT_IN };
1986
1900
  }
1987
1901
  this.pos = savedPos;
1988
1902
  // is not null
1989
1903
  if (this.matchWord('is') && this.matchWord('not')) {
1990
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.NULL)) {
1904
+ if (this.check(AbilityDSLToken.NULL)) {
1991
1905
  this.advance();
1992
1906
  return {
1993
- condition: AbilityCondition_1.default.not_equals,
1994
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ_NULL,
1907
+ condition: AbilityCondition.not_equals,
1908
+ operator: AbilityDSLToken.NOT_EQ_NULL,
1995
1909
  };
1996
1910
  }
1997
1911
  }
1998
1912
  this.pos = savedPos;
1999
1913
  // is null
2000
1914
  if (this.matchWord('is') && this.matchWord('null')) {
2001
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.NULL)) {
1915
+ if (this.check(AbilityDSLToken.NULL)) {
2002
1916
  this.advance();
2003
1917
  return {
2004
- condition: AbilityCondition_1.default.equals,
2005
- operator: AbilityDSLToken_1.AbilityDSLToken.EQ_NULL,
1918
+ condition: AbilityCondition.equals,
1919
+ operator: AbilityDSLToken.EQ_NULL,
2006
1920
  };
2007
1921
  }
2008
1922
  }
2009
1923
  this.pos = savedPos;
2010
1924
  // Single token (symbol or keyword)
2011
1925
  const token = this.peek();
2012
- if (token.code !== AbilityDSLToken_1.AbilityDSLToken.SYMBOL &&
2013
- token.code !== AbilityDSLToken_1.AbilityDSLToken.KEYWORD &&
2014
- token.code !== AbilityDSLToken_1.AbilityDSLToken.NULL) {
1926
+ if (token.code !== AbilityDSLToken.SYMBOL &&
1927
+ token.code !== AbilityDSLToken.KEYWORD &&
1928
+ token.code !== AbilityDSLToken.NULL) {
2015
1929
  this.syntaxError(`Expected comparison operator, got \`${token.value}\``, token, [
2016
- AbilityDSLToken_1.AbilityDSLToken.SYMBOL,
2017
- AbilityDSLToken_1.AbilityDSLToken.KEYWORD,
2018
- AbilityDSLToken_1.AbilityDSLToken.NULL,
1930
+ AbilityDSLToken.SYMBOL,
1931
+ AbilityDSLToken.KEYWORD,
1932
+ AbilityDSLToken.NULL,
2019
1933
  ]);
2020
1934
  }
2021
1935
  this.advance();
2022
1936
  switch (token.code) {
2023
- case AbilityDSLToken_1.AbilityDSLToken.SYMBOL:
1937
+ case AbilityDSLToken.SYMBOL:
2024
1938
  if (token.value === '=' || token.value === '==')
2025
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1939
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
2026
1940
  if (token.value === '!=' || token.value === '<>')
2027
- return { condition: AbilityCondition_1.default.not_equals, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ };
1941
+ return { condition: AbilityCondition.not_equals, operator: AbilityDSLToken.NOT_EQ };
2028
1942
  if (token.value === '>')
2029
- return { condition: AbilityCondition_1.default.greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.GT };
1943
+ return { condition: AbilityCondition.greater_than, operator: AbilityDSLToken.GT };
2030
1944
  if (token.value === '<')
2031
- return { condition: AbilityCondition_1.default.less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LT };
1945
+ return { condition: AbilityCondition.less_than, operator: AbilityDSLToken.LT };
2032
1946
  if (token.value === '>=')
2033
- return { condition: AbilityCondition_1.default.greater_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.GTE };
1947
+ return { condition: AbilityCondition.greater_or_equal, operator: AbilityDSLToken.GTE };
2034
1948
  if (token.value === '<=')
2035
- return { condition: AbilityCondition_1.default.less_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.LTE };
1949
+ return { condition: AbilityCondition.less_or_equal, operator: AbilityDSLToken.LTE };
2036
1950
  break;
2037
- case AbilityDSLToken_1.AbilityDSLToken.KEYWORD:
1951
+ case AbilityDSLToken.KEYWORD:
2038
1952
  if (token.value === 'contains' || token.value === 'includes' || token.value === 'has')
2039
- return { condition: AbilityCondition_1.default.contains, operator: AbilityDSLToken_1.AbilityDSLToken.CONTAINS };
1953
+ return { condition: AbilityCondition.contains, operator: AbilityDSLToken.CONTAINS };
2040
1954
  if (token.value === 'in')
2041
- return { condition: AbilityCondition_1.default.in, operator: AbilityDSLToken_1.AbilityDSLToken.IN };
1955
+ return { condition: AbilityCondition.in, operator: AbilityDSLToken.IN };
2042
1956
  if (token.value === 'equals')
2043
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1957
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
2044
1958
  if (token.value === 'gte') {
2045
- return { condition: AbilityCondition_1.default.greater_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.GTE };
1959
+ return { condition: AbilityCondition.greater_or_equal, operator: AbilityDSLToken.GTE };
2046
1960
  }
2047
1961
  if (token.value === 'greater' || token.value === 'gt') {
2048
1962
  // If we come here, it means "greater" without "than" – treat as '>'
2049
- return { condition: AbilityCondition_1.default.greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.GT };
1963
+ return { condition: AbilityCondition.greater_than, operator: AbilityDSLToken.GT };
2050
1964
  }
2051
1965
  if (token.value === 'less' || token.value === 'lt') {
2052
- return { condition: AbilityCondition_1.default.less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LT };
1966
+ return { condition: AbilityCondition.less_than, operator: AbilityDSLToken.LT };
2053
1967
  }
2054
1968
  if (token.value === 'lte') {
2055
- return { condition: AbilityCondition_1.default.less_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.LTE };
1969
+ return { condition: AbilityCondition.less_or_equal, operator: AbilityDSLToken.LTE };
2056
1970
  }
2057
1971
  if (token.value === 'is') {
2058
1972
  // "is" alone -> equals
2059
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1973
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
2060
1974
  }
2061
1975
  break;
2062
- default:
2063
- break;
2064
1976
  }
2065
1977
  return this.syntaxError(`Unexpected operator token \`${token.value}\``, token, [
2066
- AbilityDSLToken_1.AbilityDSLToken.SYMBOL,
2067
- AbilityDSLToken_1.AbilityDSLToken.KEYWORD,
1978
+ AbilityDSLToken.SYMBOL,
1979
+ AbilityDSLToken.KEYWORD,
2068
1980
  ]);
2069
1981
  }
2070
1982
  /**
@@ -2077,7 +1989,7 @@ class AbilityDSLParser {
2077
1989
  return false;
2078
1990
  }
2079
1991
  const token = this.peek();
2080
- if ((token.code === AbilityDSLToken_1.AbilityDSLToken.KEYWORD || token.code === AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER) &&
1992
+ if ((token.code === AbilityDSLToken.KEYWORD || token.code === AbilityDSLToken.IDENTIFIER) &&
2081
1993
  token.value === word) {
2082
1994
  this.advance();
2083
1995
  return true;
@@ -2088,7 +2000,7 @@ class AbilityDSLParser {
2088
2000
  if (this.isAtEnd())
2089
2001
  return false;
2090
2002
  const token = this.peek();
2091
- if (token.code === AbilityDSLToken_1.AbilityDSLToken.SYMBOL && token.value === symbol) {
2003
+ if (token.code === AbilityDSLToken.SYMBOL && token.value === symbol) {
2092
2004
  this.advance();
2093
2005
  return true;
2094
2006
  }
@@ -2103,32 +2015,32 @@ class AbilityDSLParser {
2103
2015
  */
2104
2016
  parseValue() {
2105
2017
  // Arrays start with a left bracket
2106
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.LBRACKET)) {
2018
+ if (this.check(AbilityDSLToken.LBRACKET)) {
2107
2019
  this.advance();
2108
2020
  return this.parseArray();
2109
2021
  }
2110
2022
  // Ensure we are not about to read a structural token as a value.
2111
2023
  const token = this.peek();
2112
- if (token.code === AbilityDSLToken_1.AbilityDSLToken.ALL ||
2113
- token.code === AbilityDSLToken_1.AbilityDSLToken.ANY ||
2114
- token.code === AbilityDSLToken_1.AbilityDSLToken.EFFECT) {
2024
+ if (token.code === AbilityDSLToken.ALL ||
2025
+ token.code === AbilityDSLToken.ANY ||
2026
+ token.code === AbilityDSLToken.EFFECT) {
2115
2027
  this.syntaxError(`Unexpected ${token.code} in value position`, token);
2116
2028
  }
2117
2029
  this.advance();
2118
2030
  // CHECK THIS SWITCH COMPARE
2119
2031
  switch (token.code) {
2120
- case AbilityDSLToken_1.AbilityDSLToken.STRING:
2032
+ case AbilityDSLToken.STRING:
2121
2033
  return token.value;
2122
- case AbilityDSLToken_1.AbilityDSLToken.NUMBER:
2034
+ case AbilityDSLToken.NUMBER:
2123
2035
  return Number(token.value);
2124
- case AbilityDSLToken_1.AbilityDSLToken.BOOLEAN:
2036
+ case AbilityDSLToken.BOOLEAN:
2125
2037
  return token.value === 'true';
2126
- case AbilityDSLToken_1.AbilityDSLToken.NULL:
2038
+ case AbilityDSLToken.NULL:
2127
2039
  return null;
2128
- case AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER:
2040
+ case AbilityDSLToken.IDENTIFIER:
2129
2041
  return token.value;
2130
2042
  default: {
2131
- this.syntaxError(`Unexpected value token "${token.value}"`, token ?? this.tokens[this.tokens.length - 1], [AbilityDSLToken_1.AbilityDSLToken.KEYWORD]);
2043
+ this.syntaxError(`Unexpected value token "${token.value}"`, token ?? this.tokens[this.tokens.length - 1], [AbilityDSLToken.KEYWORD]);
2132
2044
  }
2133
2045
  }
2134
2046
  }
@@ -2139,11 +2051,11 @@ class AbilityDSLParser {
2139
2051
  parseArray() {
2140
2052
  const arr = [];
2141
2053
  // Handle empty array
2142
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.RBRACKET)) {
2054
+ if (this.check(AbilityDSLToken.RBRACKET)) {
2143
2055
  this.advance();
2144
2056
  return arr;
2145
2057
  }
2146
- while (!this.isAtEnd() && !this.check(AbilityDSLToken_1.AbilityDSLToken.RBRACKET)) {
2058
+ while (!this.isAtEnd() && !this.check(AbilityDSLToken.RBRACKET)) {
2147
2059
  const value = this.parseValue();
2148
2060
  // Flatten nested arrays if they appear (though grammar doesn't currently allow nesting).
2149
2061
  if (Array.isArray(value)) {
@@ -2159,18 +2071,18 @@ class AbilityDSLParser {
2159
2071
  this.syntaxError('Unexpected null in array', this.peek());
2160
2072
  }
2161
2073
  // Optional comma between elements
2162
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.COMMA)) {
2074
+ if (this.check(AbilityDSLToken.COMMA)) {
2163
2075
  this.advance();
2164
2076
  }
2165
2077
  }
2166
- this.consume(AbilityDSLToken_1.AbilityDSLToken.RBRACKET, 'Expected "]"');
2078
+ this.consume(AbilityDSLToken.RBRACKET, 'Expected "]"');
2167
2079
  return arr;
2168
2080
  }
2169
2081
  // -------------------------------------------------------------------------
2170
2082
  // #region Annotations and comments
2171
2083
  // -------------------------------------------------------------------------
2172
2084
  consumeLeadingComments() {
2173
- while (this.check(AbilityDSLToken_1.AbilityDSLToken.COMMENT)) {
2085
+ while (this.check(AbilityDSLToken.COMMENT)) {
2174
2086
  const token = this.advance();
2175
2087
  this.processCommentToken(token);
2176
2088
  }
@@ -2220,7 +2132,7 @@ class AbilityDSLParser {
2220
2132
  const detailsMsg = `${details}\nDetails: Unexpected value token \`${actual}\``;
2221
2133
  finalDetails = suggestion ? `${detailsMsg} Did you mean \`${suggestion}\`?` : detailsMsg;
2222
2134
  }
2223
- throw new AbilityDSLSyntaxError_1.AbilityDSLSyntaxError(token.line, token.column, context + '\n', finalDetails);
2135
+ throw new AbilityDSLSyntaxError(token.line, token.column, context + '\n', finalDetails);
2224
2136
  }
2225
2137
  getLine(lineNumber) {
2226
2138
  return this.dsl.split(/\r?\n/)[lineNumber - 1] ?? '';
@@ -2269,7 +2181,7 @@ class AbilityDSLParser {
2269
2181
  }
2270
2182
  }
2271
2183
  const expected = types.map(t => t).join(', ');
2272
- const actual = token ? token.value : AbilityDSLToken_1.AbilityDSLToken.EOF;
2184
+ const actual = token ? token.value : AbilityDSLToken.EOF;
2273
2185
  const suggestion = this.suggest(actual, types);
2274
2186
  const details = `${message}\nDetails: Unexpected token \`${actual}\`, expected one of: ${expected}.`;
2275
2187
  const finalMsg = suggestion ? `${details} Did you mean \`${suggestion}\`?` : details;
@@ -2281,7 +2193,7 @@ class AbilityDSLParser {
2281
2193
  return this.advance();
2282
2194
  }
2283
2195
  const expected = type;
2284
- const actual = token ? token.value : AbilityDSLToken_1.AbilityDSLToken.EOF;
2196
+ const actual = token ? token.value : AbilityDSLToken.EOF;
2285
2197
  const suggestion = this.suggest(actual, [type]);
2286
2198
  const details = `${message}\nDetails: Unexpected token \`${actual}\`, expected "${expected}".`;
2287
2199
  const finalMsg = suggestion ? `${details} Did you mean \`${suggestion}\`?` : details;
@@ -2293,10 +2205,10 @@ class AbilityDSLParser {
2293
2205
  return this.peek().code === type;
2294
2206
  }
2295
2207
  isStartOfPolicy() {
2296
- return this.check(AbilityDSLToken_1.AbilityDSLToken.EFFECT);
2208
+ return this.check(AbilityDSLToken.EFFECT);
2297
2209
  }
2298
2210
  isStartOfGroup() {
2299
- return this.check(AbilityDSLToken_1.AbilityDSLToken.ALL) || this.check(AbilityDSLToken_1.AbilityDSLToken.ANY);
2211
+ return this.check(AbilityDSLToken.ALL) || this.check(AbilityDSLToken.ANY);
2300
2212
  }
2301
2213
  advance() {
2302
2214
  return this.tokens[this.pos++];
@@ -2305,296 +2217,29 @@ class AbilityDSLParser {
2305
2217
  return this.tokens[this.pos];
2306
2218
  }
2307
2219
  isAtEnd() {
2308
- return this.peek().code === AbilityDSLToken_1.AbilityDSLToken.EOF;
2309
- }
2310
- }
2311
- exports.AbilityDSLParser = AbilityDSLParser;
2312
-
2313
-
2314
- /***/ }),
2315
-
2316
- /***/ 883:
2317
- /***/ ((__unused_webpack_module, exports) => {
2318
-
2319
-
2320
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2321
- exports.AbilityDSLSyntaxError = void 0;
2322
- class AbilityDSLSyntaxError extends Error {
2323
- line;
2324
- column;
2325
- context;
2326
- details;
2327
- _formattedMessage;
2328
- _originalStack;
2329
- constructor(line, column, context, // строка DSL + ^ + соседние строки
2330
- details) {
2331
- super(details.split('\n')[0]); // message = только первая строка
2332
- this.line = line;
2333
- this.column = column;
2334
- this.context = context;
2335
- this.details = details;
2336
- this.name = 'AbilityDSLSyntaxError';
2337
- if (Error.captureStackTrace) {
2338
- Error.captureStackTrace(this, AbilityDSLSyntaxError);
2339
- }
2340
- this._originalStack = this.stack;
2341
- this._formattedMessage = this.formatMessage();
2342
- Object.defineProperty(this, 'stack', {
2343
- get: () => this._formattedMessage,
2344
- configurable: true,
2345
- });
2346
- }
2347
- static supportsColor() {
2348
- return typeof process !== 'undefined' && process.stdout?.isTTY;
2349
- }
2350
- formatMessage() {
2351
- const useColor = AbilityDSLSyntaxError.supportsColor();
2352
- const BOLD = useColor ? '\x1b[1m' : '';
2353
- const RED = useColor ? '\x1b[31m' : '';
2354
- const ORANGE = useColor ? '\x1b[33;1m' : '';
2355
- const GRAY = useColor ? '\x1b[90m' : '';
2356
- const RESET = useColor ? '\x1b[0m' : '';
2357
- const lines = this.context.split('\n');
2358
- // Find line with ^
2359
- const pointerIndex = lines.findIndex(l => l.includes('^') || l.includes('~'));
2360
- const commentIndex = lines.findIndex(l => l.trim().includes('#'));
2361
- const formattedLines = lines.map((line, idx) => {
2362
- if (idx === pointerIndex - 1) {
2363
- // Error line
2364
- return `${BOLD}${ORANGE}${line}${RESET}`;
2365
- }
2366
- if (idx === pointerIndex) {
2367
- // Error with ~~~~~
2368
- return `${RED}${line}${RESET}`;
2369
- }
2370
- // Comments # ...
2371
- if (idx === commentIndex) {
2372
- return `${GRAY}${line}${RESET}`;
2373
- }
2374
- return line;
2375
- });
2376
- const contextBlock = formattedLines.join('\n');
2377
- return `${BOLD}${RED}${this.name}: ${this.details}${RESET}\n\n` + contextBlock;
2378
- }
2379
- toString() {
2380
- return this._formattedMessage;
2220
+ return this.peek().code === AbilityDSLToken.EOF;
2381
2221
  }
2382
2222
  }
2383
- exports.AbilityDSLSyntaxError = AbilityDSLSyntaxError;
2384
-
2385
-
2386
- /***/ }),
2387
-
2388
- /***/ 325:
2389
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
2390
-
2391
2223
 
2392
- var __importDefault = (this && this.__importDefault) || function (mod) {
2393
- return (mod && mod.__esModule) ? mod : { "default": mod };
2394
- };
2395
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2396
- exports.AbilityDSLToken = void 0;
2397
- const AbilityCode_1 = __importDefault(__webpack_require__(301));
2398
- /**
2399
- * Represents a single token produced by the Ability DSL lexer.
2400
- * Each token carries a type (e.g., EFFECT, IDENTIFIER, STRING) and its raw string value.
2401
- */
2402
- class AbilityDSLToken extends AbilityCode_1.default {
2403
- /** The literal text of the token as it appeared in the input (e.g., "permit", "user.roles", "admin"). */
2404
- value = '';
2405
- /** The line number in DSL */
2406
- line = 1;
2407
- /** The column in dsl */
2408
- column = 1;
2409
- constructor(type, value, line, column) {
2410
- super(type);
2411
- this.value = value;
2412
- this.line = line;
2413
- this.column = column;
2414
- }
2415
- /**
2416
- * Returns a human-readable representation of the token, useful for debugging.
2417
- * Example output: "AbilityDSLToken([EFFECT] permit"
2418
- */
2419
- toString() {
2420
- return `AbilityDSLToken([${this.code}] "${this.value}" at ${this.line}:${this.column})`;
2421
- }
2422
- static EFFECT = 'EFFECT';
2423
- static IF = 'IF';
2424
- static PERMISSION = 'PERMISSION';
2425
- static IDENTIFIER = 'IDENTIFIER';
2426
- static COLON = 'COLON';
2427
- static COMMA = 'COMMA';
2428
- static DOT = 'DOT';
2429
- static LBRACKET = 'LBRACKET';
2430
- static RBRACKET = 'RBRACKET';
2431
- static ALL = 'ALL';
2432
- static ANY = 'ANY';
2433
- static OF = 'OF';
2434
- static EOF = 'EOF';
2435
- static COMMENT = 'COMMENT';
2436
- static EQ = 'EQ';
2437
- static CONTAINS = 'CONTAINS';
2438
- static IN = 'IN';
2439
- static NOT_IN = 'NOT_IN';
2440
- static NOT_CONTAINS = 'NOT_CONTAINS';
2441
- static GT = 'GT';
2442
- static GTE = 'GTE';
2443
- static LT = 'LT';
2444
- static LTE = 'LTE';
2445
- static NULL = 'NULL';
2446
- static EQ_NULL = 'EQ_NULL';
2447
- static NOT_EQ_NULL = 'NOT_EQ_NULL';
2448
- static LEN_GT = 'LEN_GT';
2449
- static LEN_LT = 'LEN_LT';
2450
- static LEN_EQ = 'LEN_EQ';
2451
- static NOT_EQ = 'NOT_EQ';
2452
- static STRING = 'STRING';
2453
- static NUMBER = 'NUMBER';
2454
- static BOOLEAN = 'BOOLEAN';
2455
- static SYMBOL = 'SYMBOL';
2456
- static KEYWORD = 'KEYWORD';
2457
- }
2224
+ exports.AbilityCode = AbilityCode;
2225
+ exports.AbilityCompare = AbilityCompare;
2226
+ exports.AbilityCondition = AbilityCondition;
2227
+ exports.AbilityDSLLexer = AbilityDSLLexer;
2228
+ exports.AbilityDSLParser = AbilityDSLParser;
2458
2229
  exports.AbilityDSLToken = AbilityDSLToken;
2459
-
2460
-
2461
- /***/ }),
2462
-
2463
- /***/ 909:
2464
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
2465
-
2466
-
2467
- var __importDefault = (this && this.__importDefault) || function (mod) {
2468
- return (mod && mod.__esModule) ? mod : { "default": mod };
2469
- };
2470
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2471
- exports.AbilityJSONParser = void 0;
2472
- const AbilityCondition_1 = __importDefault(__webpack_require__(167));
2473
- const AbilityRule_1 = __webpack_require__(306);
2474
- const AbilityRuleSet_1 = __webpack_require__(56);
2475
- const AbilityCompare_1 = __importDefault(__webpack_require__(413));
2476
- const AbilityPolicyEffect_1 = __importDefault(__webpack_require__(179));
2477
- const AbilityPolicy_1 = __webpack_require__(278);
2478
- class AbilityJSONParser {
2479
- /**
2480
- * Parses an array of policy configurations into an array of AbilityPolicy instances.
2481
- * @param configs - Array of policy configurations
2482
- * @returns Array of AbilityPolicy instances
2483
- */
2484
- static parse(configs) {
2485
- return configs.map(config => AbilityJSONParser.parsePolicy(config));
2486
- }
2487
- static parsePolicy(config) {
2488
- const { id, name, ruleSet, compareMethod, permission, effect } = config;
2489
- // Create the empty policy
2490
- const policy = new AbilityPolicy_1.AbilityPolicy({
2491
- name,
2492
- id,
2493
- permission: permission,
2494
- effect: new AbilityPolicyEffect_1.default(effect),
2495
- });
2496
- policy.compareMethod = new AbilityCompare_1.default(compareMethod);
2497
- ruleSet.forEach(ruleSetConfig => {
2498
- policy.addRuleSet(AbilityRuleSet_1.AbilityRuleSet.fromJSON(ruleSetConfig));
2499
- });
2500
- return policy;
2501
- }
2502
- static parseRule(config) {
2503
- const { id, name, subject, resource, condition } = config;
2504
- return new AbilityRule_1.AbilityRule({
2505
- id,
2506
- name,
2507
- subject,
2508
- resource,
2509
- condition: new AbilityCondition_1.default(condition),
2510
- });
2511
- }
2512
- /**
2513
- * Parse the config JSON format to Group class instance
2514
- */
2515
- static parseRuleSet(config) {
2516
- const { id, name, rules, compareMethod } = config;
2517
- const ruleSet = new AbilityRuleSet_1.AbilityRuleSet({
2518
- compareMethod: new AbilityCompare_1.default(compareMethod),
2519
- name,
2520
- id,
2521
- });
2522
- // Adding rules if exists
2523
- if (rules && rules.length > 0) {
2524
- const abilityRules = rules.map(ruleConfig => AbilityRule_1.AbilityRule.fromJSON(ruleConfig));
2525
- ruleSet.addRules(abilityRules);
2526
- }
2527
- return ruleSet;
2528
- }
2529
- static ruleToJSON(rule) {
2530
- return {
2531
- id: rule.id,
2532
- name: rule.name,
2533
- subject: rule.subject,
2534
- resource: rule.resource,
2535
- condition: rule.condition.code,
2536
- };
2537
- }
2538
- static ruleSetToJSON(ruleSet) {
2539
- return {
2540
- id: ruleSet.id.toString(),
2541
- name: ruleSet.name.toString(),
2542
- compareMethod: ruleSet.compareMethod.code.toString(),
2543
- rules: ruleSet.rules.map(rule => AbilityJSONParser.ruleToJSON(rule)),
2544
- };
2545
- }
2546
- static policyToJSON(policy) {
2547
- return {
2548
- id: policy.id.toString(),
2549
- name: policy.name.toString(),
2550
- compareMethod: policy.compareMethod.code.toString(),
2551
- ruleSet: policy.ruleSet.map(ruleSet => AbilityJSONParser.ruleSetToJSON(ruleSet)),
2552
- permission: policy.permission,
2553
- effect: policy.effect.code,
2554
- };
2555
- }
2556
- static toJSON(policies) {
2557
- return policies.map(policy => AbilityJSONParser.policyToJSON(policy));
2558
- }
2559
- }
2230
+ exports.AbilityError = AbilityError;
2231
+ exports.AbilityExplain = AbilityExplain;
2232
+ exports.AbilityExplainPolicy = AbilityExplainPolicy;
2233
+ exports.AbilityExplainRule = AbilityExplainRule;
2234
+ exports.AbilityExplainRuleSet = AbilityExplainRuleSet;
2235
+ exports.AbilityInMemoryCache = AbilityInMemoryCache;
2560
2236
  exports.AbilityJSONParser = AbilityJSONParser;
2561
-
2562
-
2563
- /***/ })
2564
-
2565
- /******/ });
2566
- /************************************************************************/
2567
- /******/ // The module cache
2568
- /******/ var __webpack_module_cache__ = {};
2569
- /******/
2570
- /******/ // The require function
2571
- /******/ function __webpack_require__(moduleId) {
2572
- /******/ // Check if module is in cache
2573
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
2574
- /******/ if (cachedModule !== undefined) {
2575
- /******/ return cachedModule.exports;
2576
- /******/ }
2577
- /******/ // Create a new module (and put it into the cache)
2578
- /******/ var module = __webpack_module_cache__[moduleId] = {
2579
- /******/ // no module.id needed
2580
- /******/ // no module.loaded needed
2581
- /******/ exports: {}
2582
- /******/ };
2583
- /******/
2584
- /******/ // Execute the module function
2585
- /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
2586
- /******/
2587
- /******/ // Return the exports of the module
2588
- /******/ return module.exports;
2589
- /******/ }
2590
- /******/
2591
- /************************************************************************/
2592
- /******/
2593
- /******/ // startup
2594
- /******/ // Load entry module and return exports
2595
- /******/ // This entry module is referenced by other modules so it can't be inlined
2596
- /******/ var __webpack_exports__ = __webpack_require__(156);
2597
- /******/ module.exports = __webpack_exports__;
2598
- /******/
2599
- /******/ })()
2600
- ;
2237
+ exports.AbilityMatch = AbilityMatch;
2238
+ exports.AbilityParser = AbilityParser;
2239
+ exports.AbilityParserError = AbilityParserError;
2240
+ exports.AbilityPolicy = AbilityPolicy;
2241
+ exports.AbilityPolicyEffect = AbilityPolicyEffect;
2242
+ exports.AbilityResolver = AbilityResolver;
2243
+ exports.AbilityResult = AbilityResult;
2244
+ exports.AbilityRule = AbilityRule;
2245
+ exports.AbilityRuleSet = AbilityRuleSet;