@via-profit/ability 3.1.1 → 3.3.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,184 +87,27 @@ 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
- class AbilityParser {
339
- /**
340
- * Sets a value in a nested object structure based on a dot/bracket notation path.
341
- * @param object - The target object to modify.
342
- * @param path - The path to the property in dot/bracket notation.
343
- * @param value - The value to set at the specified path.
344
- */
345
- static setValueDotValue(object, path, value) {
346
- if (!path || path.trim().length === 0) {
347
- throw new AbilityError_1.AbilityParserError(`Invalid path provided on a [${path}]`);
348
- }
349
- const way = path.replace(/\[/g, '.').replace(/]/g, '').split('.');
350
- const last = way.pop();
351
- if (!last) {
352
- throw new AbilityError_1.AbilityParserError(`Invalid path provided on a [${path}]`);
353
- }
354
- const lastObj = way.reduce((acc, key, index, array) => {
355
- const currentValue = acc[key];
356
- const nextKey = array[index + 1];
357
- const shouldBeArray = nextKey !== undefined && isFinite(Number(nextKey));
358
- if (currentValue === undefined || currentValue === null) {
359
- // Create missing property
360
- const newValue = shouldBeArray ? [] : {};
361
- acc[key] = newValue;
362
- return newValue;
363
- }
364
- if (typeof currentValue !== 'object') {
365
- throw new AbilityError_1.AbilityParserError(`Cannot set property '${key}' on non-object value at path: ${path}`);
366
- }
367
- return currentValue;
368
- }, object);
369
- const existingValue = lastObj[last];
370
- if (existingValue !== undefined &&
371
- typeof existingValue === 'object' &&
372
- existingValue !== null &&
373
- !Array.isArray(existingValue)) {
374
- throw new AbilityError_1.AbilityParserError(`Cannot set primitive value on existing object at path: ${path}`);
375
- }
376
- lastObj[last] = value;
97
+ class AbilityTypeGenerator {
98
+ policies;
99
+ constructor(policies) {
100
+ this.policies = policies;
377
101
  }
378
102
  /**
379
103
  * Generates TypeScript type definitions based on the provided policies.
380
- * @param policies - An array of AbilityPolicy instances.
381
104
  * @returns A generated type definitions.
382
105
  */
383
- static generateTypeDefs(policies) {
106
+ generateTypeDefs() {
384
107
  // Structure to store types: { [action]: { [subjectPath]: type } }
385
108
  const typeStructure = {};
386
109
  // Iterate through all policies
387
- policies.forEach(policy => {
110
+ this.policies.forEach(policy => {
388
111
  const action = policy.permission;
389
112
  // Initialize object for action if it doesn't exist
390
113
  if (!typeStructure[action]) {
@@ -416,22 +139,22 @@ class AbilityParser {
416
139
  * @param rule - The rule to analyze
417
140
  * @returns TypeScript type as string
418
141
  */
419
- static determineTypeFromRule(rule) {
142
+ determineTypeFromRule(rule) {
420
143
  // 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)) {
144
+ if (rule.condition.isEqual(AbilityCondition.greater_than) ||
145
+ rule.condition.isEqual(AbilityCondition.less_than) ||
146
+ rule.condition.isEqual(AbilityCondition.greater_or_equal) ||
147
+ rule.condition.isEqual(AbilityCondition.less_or_equal)) {
425
148
  return 'number';
426
149
  }
427
150
  // Array operations
428
- if (rule.condition.isEqual(AbilityCondition_1.default.in) ||
429
- rule.condition.isEqual(AbilityCondition_1.default.not_in)) {
151
+ if (rule.condition.isEqual(AbilityCondition.in) ||
152
+ rule.condition.isEqual(AbilityCondition.not_in)) {
430
153
  return this.getArrayType(rule.resource);
431
154
  }
432
155
  // Equality/Inequality operations
433
- if (rule.condition.isEqual(AbilityCondition_1.default.equals) ||
434
- rule.condition.isEqual(AbilityCondition_1.default.not_equals)) {
156
+ if (rule.condition.isEqual(AbilityCondition.equals) ||
157
+ rule.condition.isEqual(AbilityCondition.not_equals)) {
435
158
  return this.getPrimitiveType(rule.resource);
436
159
  }
437
160
  return 'any';
@@ -441,7 +164,7 @@ class AbilityParser {
441
164
  * @param resource - The resource value to analyze
442
165
  * @returns TypeScript array type as string
443
166
  */
444
- static getArrayType(resource) {
167
+ getArrayType(resource) {
445
168
  if (Array.isArray(resource)) {
446
169
  if (resource.length === 0)
447
170
  return 'any[]';
@@ -450,18 +173,18 @@ class AbilityParser {
450
173
  const elementType = elementTypes.size === 1
451
174
  ? Array.from(elementTypes)[0]
452
175
  : `(${Array.from(elementTypes).join(' | ')})`;
453
- return `${elementType}[]`;
176
+ return `readonly ${elementType}[]`;
454
177
  }
455
178
  // If resource is not an array but condition is in/not_in,
456
179
  // it expects an array of such elements
457
- return `${this.getPrimitiveType(resource)}[]`;
180
+ return `readonly ${this.getPrimitiveType(resource)}[]`;
458
181
  }
459
182
  /**
460
183
  * Gets primitive TypeScript type for a value
461
184
  * @param value - The value to analyze
462
185
  * @returns TypeScript primitive type as string
463
186
  */
464
- static getPrimitiveType(value) {
187
+ getPrimitiveType(value) {
465
188
  if (value === null)
466
189
  return 'null';
467
190
  if (value === undefined)
@@ -488,7 +211,7 @@ class AbilityParser {
488
211
  * @param flatStructure - Flat structure with dot notation paths
489
212
  * @returns Nested object structure
490
213
  */
491
- static buildNestedStructure(flatStructure) {
214
+ buildNestedStructure(flatStructure) {
492
215
  const result = {};
493
216
  Object.entries(flatStructure).forEach(([action, paths]) => {
494
217
  result[action] = {};
@@ -520,10 +243,9 @@ class AbilityParser {
520
243
  * @param structure - Nested type structure
521
244
  * @returns Formatted TypeScript type definition string
522
245
  */
523
- static formatTypeDefinitions(structure) {
246
+ formatTypeDefinitions(structure) {
524
247
  let output = '// Automatically generated by via-profit/ability\n';
525
248
  output += '// Do not edit manually\n';
526
- output += '\n/* eslint-disable */\n\n';
527
249
  output += 'export type Resources = {\n';
528
250
  // Sort actions for stable output
529
251
  const sortedActions = Object.keys(structure).sort();
@@ -541,7 +263,7 @@ class AbilityParser {
541
263
  * @param indent - Current indentation level
542
264
  * @returns Formatted string
543
265
  */
544
- static formatNestedObject(obj, indent) {
266
+ formatNestedObject(obj, indent) {
545
267
  const spaces = ' '.repeat(indent);
546
268
  let output = '';
547
269
  // Sort keys for stable output
@@ -562,29 +284,60 @@ class AbilityParser {
562
284
  return output;
563
285
  }
564
286
  }
565
- exports.AbilityParser = AbilityParser;
566
- exports["default"] = AbilityParser;
567
-
568
-
569
- /***/ }),
570
-
571
- /***/ 278:
572
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
573
287
 
288
+ class AbilityExplain {
289
+ type;
290
+ children;
291
+ name;
292
+ match;
293
+ constructor(config, children = []) {
294
+ this.type = config.type;
295
+ this.children = children;
296
+ this.name = config.name;
297
+ this.match = config.match;
298
+ }
299
+ toString(indent = 0) {
300
+ const pad = ' '.repeat(indent);
301
+ const mark = this.match.code === AbilityMatch.match.code ? '✓' : '✗';
302
+ let out = `${pad}${mark} ${this.type} «${this.name}» is ${this.match.code}`;
303
+ this.children.forEach(child => {
304
+ out += '\n' + child.toString(indent + 1);
305
+ });
306
+ return out;
307
+ }
308
+ }
309
+ class AbilityExplainRule extends AbilityExplain {
310
+ constructor(rule) {
311
+ super({
312
+ type: 'rule',
313
+ match: rule.state,
314
+ name: rule.name,
315
+ });
316
+ }
317
+ }
318
+ class AbilityExplainRuleSet extends AbilityExplain {
319
+ constructor(ruleSet) {
320
+ const children = ruleSet.rules.map(rule => new AbilityExplainRule(rule));
321
+ super({
322
+ type: 'ruleSet',
323
+ match: ruleSet.state,
324
+ name: ruleSet.name,
325
+ }, children);
326
+ }
327
+ }
328
+ class AbilityExplainPolicy extends AbilityExplain {
329
+ constructor(policy) {
330
+ const children = policy.ruleSet.map(ruleSet => new AbilityExplainRuleSet(ruleSet));
331
+ super({
332
+ type: 'policy',
333
+ name: policy.name,
334
+ match: policy.matchState,
335
+ }, children);
336
+ }
337
+ }
574
338
 
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
339
  class AbilityPolicy {
587
- matchState = AbilityMatch_1.default.pending;
340
+ matchState = AbilityMatch.pending;
588
341
  /**
589
342
  * List of rules
590
343
  */
@@ -599,7 +352,7 @@ class AbilityPolicy {
599
352
  * rules will be returns «permit» status and for the «or» - if\
600
353
  * one of the rules returns as «permit»
601
354
  */
602
- compareMethod = AbilityCompare_1.default.and;
355
+ compareMethod = AbilityCompare.and;
603
356
  /**
604
357
  * Policy name
605
358
  */
@@ -614,7 +367,7 @@ class AbilityPolicy {
614
367
  */
615
368
  permission;
616
369
  constructor(params) {
617
- const { name, id, permission, effect, compareMethod = AbilityCompare_1.default.and } = params;
370
+ const { name, id, permission, effect, compareMethod = AbilityCompare.and } = params;
618
371
  this.name = name;
619
372
  this.id = id;
620
373
  this.permission = permission;
@@ -645,7 +398,7 @@ class AbilityPolicy {
645
398
  * @param environment - The user environment object
646
399
  */
647
400
  async check(resource, environment) {
648
- this.matchState = AbilityMatch_1.default.mismatch;
401
+ this.matchState = AbilityMatch.mismatch;
649
402
  if (!this.ruleSet.length) {
650
403
  return this.matchState;
651
404
  }
@@ -653,94 +406,104 @@ class AbilityPolicy {
653
406
  for (const ruleSet of this.ruleSet) {
654
407
  const state = await ruleSet.check(resource, environment);
655
408
  rulesetCheckStates.push(state);
656
- if (AbilityCompare_1.default.and.isEqual(this.compareMethod) && AbilityMatch_1.default.mismatch.isEqual(state)) {
409
+ if (AbilityCompare.and.isEqual(this.compareMethod) && AbilityMatch.mismatch.isEqual(state)) {
657
410
  return this.matchState; // mismatch
658
411
  }
659
- if (AbilityCompare_1.default.or.isEqual(this.compareMethod) && AbilityMatch_1.default.match.isEqual(state)) {
660
- this.matchState = AbilityMatch_1.default.match;
412
+ if (AbilityCompare.or.isEqual(this.compareMethod) && AbilityMatch.match.isEqual(state)) {
413
+ this.matchState = AbilityMatch.match;
661
414
  return this.matchState;
662
415
  }
663
416
  }
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;
417
+ if (AbilityCompare.and.isEqual(this.compareMethod)) {
418
+ if (rulesetCheckStates.every(s => AbilityMatch.match.isEqual(s))) {
419
+ this.matchState = AbilityMatch.match;
667
420
  }
668
421
  }
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;
422
+ if (AbilityCompare.or.isEqual(this.compareMethod)) {
423
+ if (rulesetCheckStates.some(s => AbilityMatch.match.isEqual(s))) {
424
+ this.matchState = AbilityMatch.match;
672
425
  }
673
426
  }
674
427
  return this.matchState;
675
428
  }
676
429
  explain() {
677
- if (this.matchState === AbilityMatch_1.default.pending) {
678
- throw new AbilityError_1.AbilityError('First, run the check method, then explain');
430
+ if (this.matchState === AbilityMatch.pending) {
431
+ throw new AbilityError('First, run the check method, then explain');
432
+ }
433
+ return new AbilityExplainPolicy(this);
434
+ }
435
+ copyWith(props) {
436
+ const policy = new AbilityPolicy({
437
+ id: props.id ?? this.id,
438
+ name: props.name ?? this.name,
439
+ permission: props.permission ?? this.permission,
440
+ effect: props.effect ?? this.effect,
441
+ compareMethod: props.compareMethod ?? this.compareMethod,
442
+ });
443
+ const nextRuleSet = props.ruleSet ?? this.ruleSet;
444
+ for (const rule of nextRuleSet) {
445
+ policy.addRuleSet(rule);
679
446
  }
680
- return new AbilityExplain_1.AbilityExplainPolicy(this);
447
+ return policy;
681
448
  }
449
+ }
450
+
451
+ class AbilityPolicyEffect extends AbilityCode {
452
+ static deny = new AbilityPolicyEffect('deny');
453
+ static permit = new AbilityPolicyEffect('permit');
454
+ }
455
+
456
+ class AbilityResult {
682
457
  /**
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
458
+ * Already checked policies (after call the policy.check())
686
459
  */
687
- static fromJSONAll(configs) {
688
- return AbilityJSONParser_1.AbilityJSONParser.parse(configs);
460
+ policies;
461
+ constructor(policies) {
462
+ this.policies = policies;
689
463
  }
690
464
  /**
691
- * Parse the config JSON format to Policy class instance
465
+ * Returns a list of explanations for each policy involved in the ability evaluation.
466
+ * Each item describes how a specific policy contributed to the final permission result.
467
+ *
468
+ * Useful for debugging, logging, or building UI tools that visualize permission logic.
692
469
  */
693
- static fromJSON(config) {
694
- return AbilityJSONParser_1.AbilityJSONParser.parsePolicy(config);
470
+ explain() {
471
+ return this.policies.map(policy => {
472
+ return new AbilityExplainPolicy(policy);
473
+ });
695
474
  }
696
- static fromDSL(dsl) {
697
- return new AbilityDSLParser_1.AbilityDSLParser(dsl).parse()[0];
475
+ getLastMatchedPolicy() {
476
+ for (let i = this.policies.length - 1; i >= 0; i--) {
477
+ if (this.policies[i].matchState.isEqual(AbilityMatch.match)) {
478
+ return this.policies[i];
479
+ }
480
+ }
481
+ return null;
698
482
  }
699
- toJSON() {
700
- return AbilityJSONParser_1.AbilityJSONParser.toJSON([this])[0];
483
+ isAllowed() {
484
+ const effect = this.getLastEffectOfMatchedPolicy();
485
+ return effect?.isEqual(AbilityPolicyEffect.permit) ?? false;
701
486
  }
702
- toString() {
703
- return JSON.stringify(this.toJSON());
487
+ isDenied() {
488
+ const effect = this.getLastEffectOfMatchedPolicy();
489
+ return effect?.isEqual(AbilityPolicyEffect.deny) ?? true;
490
+ }
491
+ /**
492
+ * Get the last effect of the policy
493
+ *
494
+ * @returns {AbilityPolicyEffect | null}
495
+ */
496
+ getLastEffectOfMatchedPolicy() {
497
+ for (let i = this.policies.length - 1; i >= 0; i--) {
498
+ const p = this.policies[i];
499
+ if (p.matchState.isEqual(AbilityMatch.match)) {
500
+ return p.effect;
501
+ }
502
+ }
503
+ return null;
704
504
  }
705
505
  }
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
506
 
730
- /***/ }),
731
-
732
- /***/ 634:
733
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
734
-
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
507
  class AbilityResolver {
745
508
  policies;
746
509
  cache;
@@ -775,20 +538,24 @@ class AbilityResolver {
775
538
  }
776
539
  }
777
540
  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.`);
541
+ if (policyMatchState === AbilityMatch.pending) {
542
+ 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
543
  }
781
544
  if (this.cache) {
782
545
  await this.cache.set(cacheKey, policyMatchState);
783
546
  }
784
547
  }
785
- return new AbilityResult_1.AbilityResult(filteredPolicies);
548
+ return new AbilityResult(filteredPolicies);
786
549
  }
787
550
  async enforce(permission, resource, environment) {
788
551
  const result = await this.resolve(permission, resource, environment);
789
552
  if (result.isDenied()) {
790
- const policyName = result.getLastMatchedPolicy()?.name?.toString() || 'unknown';
791
- throw new AbilityError_1.AbilityError(`Permission denied by policy "${policyName}"`);
553
+ const lastPolicy = result.getLastMatchedPolicy();
554
+ if (lastPolicy) {
555
+ throw new AbilityError(`Permission denied by policy "${lastPolicy.name.toString()}"`);
556
+ }
557
+ // No policy matched → implicit deny
558
+ throw new AbilityError(`Permission denied: no matching policy found (implicit deny)`);
792
559
  }
793
560
  }
794
561
  /**
@@ -817,91 +584,7 @@ class AbilityResolver {
817
584
  await this.cache?.clear();
818
585
  }
819
586
  }
820
- exports.AbilityResolver = AbilityResolver;
821
- exports["default"] = AbilityResolver;
822
-
823
-
824
- /***/ }),
825
-
826
- /***/ 941:
827
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
828
-
829
-
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
587
 
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
588
  /**
906
589
  * Represents a rule that defines a condition to be checked against a subject and resource.
907
590
  */
@@ -917,7 +600,7 @@ class AbilityRule {
917
600
  condition;
918
601
  name;
919
602
  id;
920
- state = AbilityMatch_1.default.pending;
603
+ state = AbilityMatch.pending;
921
604
  /**
922
605
  * Creates an instance of AbilityRule.
923
606
  * @param {string} params.id - The unique identifier of the rule.
@@ -945,39 +628,39 @@ class AbilityRule {
945
628
  const [subjectValue, resourceValue] = this.extractValues(resource, environment);
946
629
  const isValue = (v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null;
947
630
  // equals
948
- if (AbilityCondition_1.default.equals.isEqual(this.condition)) {
631
+ if (AbilityCondition.equals.isEqual(this.condition)) {
949
632
  is = subjectValue === resourceValue;
950
633
  }
951
634
  // not equals
952
- if (AbilityCondition_1.default.not_equals.isEqual(this.condition)) {
635
+ if (AbilityCondition.not_equals.isEqual(this.condition)) {
953
636
  is = subjectValue !== resourceValue;
954
637
  }
955
638
  // less than
956
- if (AbilityCondition_1.default.less_than.isEqual(this.condition)) {
639
+ if (AbilityCondition.less_than.isEqual(this.condition)) {
957
640
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
958
641
  is = subjectValue < resourceValue;
959
642
  }
960
643
  }
961
644
  // less or equal
962
- if (AbilityCondition_1.default.less_or_equal.isEqual(this.condition)) {
645
+ if (AbilityCondition.less_or_equal.isEqual(this.condition)) {
963
646
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
964
647
  is = subjectValue <= resourceValue;
965
648
  }
966
649
  }
967
650
  // more than
968
- if (AbilityCondition_1.default.greater_than.isEqual(this.condition)) {
651
+ if (AbilityCondition.greater_than.isEqual(this.condition)) {
969
652
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
970
653
  is = subjectValue > resourceValue;
971
654
  }
972
655
  }
973
656
  // more or equal
974
- if (AbilityCondition_1.default.greater_or_equal.isEqual(this.condition)) {
657
+ if (AbilityCondition.greater_or_equal.isEqual(this.condition)) {
975
658
  if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
976
659
  is = subjectValue >= resourceValue;
977
660
  }
978
661
  }
979
662
  // in
980
- if (AbilityCondition_1.default.in.isEqual(this.condition)) {
663
+ if (AbilityCondition.in.isEqual(this.condition)) {
981
664
  // value in array
982
665
  if (isValue(subjectValue) && Array.isArray(resourceValue)) {
983
666
  is = resourceValue.includes(subjectValue);
@@ -988,7 +671,7 @@ class AbilityRule {
988
671
  }
989
672
  }
990
673
  // not in
991
- if (AbilityCondition_1.default.not_in.isEqual(this.condition)) {
674
+ if (AbilityCondition.not_in.isEqual(this.condition)) {
992
675
  if (isValue(subjectValue) && Array.isArray(resourceValue)) {
993
676
  is = !resourceValue.includes(subjectValue);
994
677
  }
@@ -997,7 +680,7 @@ class AbilityRule {
997
680
  }
998
681
  }
999
682
  // contains
1000
- if (AbilityCondition_1.default.contains.isEqual(this.condition)) {
683
+ if (AbilityCondition.contains.isEqual(this.condition)) {
1001
684
  // array contains value
1002
685
  if (Array.isArray(subjectValue) && isValue(resourceValue)) {
1003
686
  is = subjectValue.includes(resourceValue);
@@ -1008,7 +691,7 @@ class AbilityRule {
1008
691
  }
1009
692
  }
1010
693
  // not contains
1011
- if (AbilityCondition_1.default.not_contains.isEqual(this.condition)) {
694
+ if (AbilityCondition.not_contains.isEqual(this.condition)) {
1012
695
  if (Array.isArray(subjectValue) && isValue(resourceValue)) {
1013
696
  is = !subjectValue.includes(resourceValue);
1014
697
  }
@@ -1017,7 +700,7 @@ class AbilityRule {
1017
700
  }
1018
701
  }
1019
702
  // length equals
1020
- if (AbilityCondition_1.default.length_equals.isEqual(this.condition)) {
703
+ if (AbilityCondition.length_equals.isEqual(this.condition)) {
1021
704
  // foo.bar == n
1022
705
  if (isValue(subjectValue) && typeof resourceValue === 'number') {
1023
706
  is = String(subjectValue).length === resourceValue;
@@ -1036,7 +719,7 @@ class AbilityRule {
1036
719
  }
1037
720
  }
1038
721
  // length greater than
1039
- if (AbilityCondition_1.default.length_greater_than.isEqual(this.condition)) {
722
+ if (AbilityCondition.length_greater_than.isEqual(this.condition)) {
1040
723
  // foo.bar > n
1041
724
  if (isValue(subjectValue) && typeof resourceValue === 'number') {
1042
725
  is = String(subjectValue).length > resourceValue;
@@ -1055,7 +738,7 @@ class AbilityRule {
1055
738
  }
1056
739
  }
1057
740
  // length greater than
1058
- if (AbilityCondition_1.default.length_less_than.isEqual(this.condition)) {
741
+ if (AbilityCondition.length_less_than.isEqual(this.condition)) {
1059
742
  // foo.bar < n
1060
743
  if (isValue(subjectValue) && typeof resourceValue === 'number') {
1061
744
  is = String(subjectValue).length < resourceValue;
@@ -1073,7 +756,7 @@ class AbilityRule {
1073
756
  is = subjectValue.length < resourceValue.length;
1074
757
  }
1075
758
  }
1076
- this.state = is ? AbilityMatch_1.default.match : AbilityMatch_1.default.mismatch;
759
+ this.state = is ? AbilityMatch.match : AbilityMatch.mismatch;
1077
760
  return this.state;
1078
761
  }
1079
762
  /**
@@ -1149,107 +832,96 @@ class AbilityRule {
1149
832
  toString() {
1150
833
  return `AbilityRule: ${this.name} condition: ${this.condition.code} subject: "${this.subject?.toString()}" resource: "${this.resource?.toString()}"`;
1151
834
  }
1152
- static fromJSON(config) {
1153
- return AbilityJSONParser_1.AbilityJSONParser.parseRule(config);
835
+ copyWith(props) {
836
+ return new AbilityRule({
837
+ id: props.id ?? this.id,
838
+ name: props.name ?? this.name,
839
+ subject: props.subject ?? this.subject,
840
+ resource: props.resource ?? this.resource,
841
+ condition: props.condition ?? this.condition,
842
+ });
1154
843
  }
1155
844
  static equals(subject, resource) {
1156
845
  return new AbilityRule({
1157
- condition: AbilityCondition_1.default.equals,
846
+ condition: AbilityCondition.equals,
1158
847
  subject,
1159
848
  resource,
1160
849
  });
1161
850
  }
1162
851
  static notEquals(subject, resource) {
1163
852
  return new AbilityRule({
1164
- condition: AbilityCondition_1.default.not_equals,
853
+ condition: AbilityCondition.not_equals,
1165
854
  subject,
1166
855
  resource,
1167
856
  });
1168
857
  }
1169
858
  static contains(subject, resource) {
1170
859
  return new AbilityRule({
1171
- condition: AbilityCondition_1.default.contains,
860
+ condition: AbilityCondition.contains,
1172
861
  subject,
1173
862
  resource,
1174
863
  });
1175
864
  }
1176
865
  static notContains(subject, resource) {
1177
866
  return new AbilityRule({
1178
- condition: AbilityCondition_1.default.not_contains,
867
+ condition: AbilityCondition.not_contains,
1179
868
  subject,
1180
869
  resource,
1181
870
  });
1182
871
  }
1183
872
  static notIn(subject, resource) {
1184
873
  return new AbilityRule({
1185
- condition: AbilityCondition_1.default.not_in,
874
+ condition: AbilityCondition.not_in,
1186
875
  subject,
1187
876
  resource,
1188
877
  });
1189
878
  }
1190
879
  static in(subject, resource) {
1191
880
  return new AbilityRule({
1192
- condition: AbilityCondition_1.default.in,
881
+ condition: AbilityCondition.in,
1193
882
  subject,
1194
883
  resource,
1195
884
  });
1196
885
  }
1197
886
  static notEqual(subject, resource) {
1198
887
  return new AbilityRule({
1199
- condition: AbilityCondition_1.default.not_equals,
888
+ condition: AbilityCondition.not_equals,
1200
889
  subject,
1201
890
  resource,
1202
891
  });
1203
892
  }
1204
893
  static lessThan(subject, resource) {
1205
894
  return new AbilityRule({
1206
- condition: AbilityCondition_1.default.less_than,
895
+ condition: AbilityCondition.less_than,
1207
896
  subject,
1208
897
  resource,
1209
898
  });
1210
899
  }
1211
900
  static lessOrEqual(subject, resource) {
1212
901
  return new AbilityRule({
1213
- condition: AbilityCondition_1.default.less_or_equal,
902
+ condition: AbilityCondition.less_or_equal,
1214
903
  subject,
1215
904
  resource,
1216
905
  });
1217
906
  }
1218
907
  static moreThan(subject, resource) {
1219
908
  return new AbilityRule({
1220
- condition: AbilityCondition_1.default.greater_than,
909
+ condition: AbilityCondition.greater_than,
1221
910
  subject,
1222
911
  resource,
1223
912
  });
1224
913
  }
1225
914
  static moreOrEqual(subject, resource) {
1226
915
  return new AbilityRule({
1227
- condition: AbilityCondition_1.default.greater_or_equal,
916
+ condition: AbilityCondition.greater_or_equal,
1228
917
  subject,
1229
918
  resource,
1230
919
  });
1231
920
  }
1232
921
  }
1233
- exports.AbilityRule = AbilityRule;
1234
- exports["default"] = AbilityRule;
1235
-
1236
-
1237
- /***/ }),
1238
922
 
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
923
  class AbilityRuleSet {
1252
- state = AbilityMatch_1.default.pending;
924
+ state = AbilityMatch.pending;
1253
925
  /**
1254
926
  * List of rules
1255
927
  */
@@ -1260,7 +932,7 @@ class AbilityRuleSet {
1260
932
  * rules will be returns «permit» status and for the «or» - if\
1261
933
  * one of the rules returns as «permit»
1262
934
  */
1263
- compareMethod = AbilityCompare_1.default.and;
935
+ compareMethod = AbilityCompare.and;
1264
936
  /**
1265
937
  * Group name
1266
938
  */
@@ -1284,7 +956,7 @@ class AbilityRuleSet {
1284
956
  return this;
1285
957
  }
1286
958
  async check(resources, environment) {
1287
- this.state = AbilityMatch_1.default.mismatch;
959
+ this.state = AbilityMatch.mismatch;
1288
960
  if (!this.rules.length) {
1289
961
  return this.state;
1290
962
  }
@@ -1292,22 +964,22 @@ class AbilityRuleSet {
1292
964
  for (const rule of this.rules) {
1293
965
  const state = await rule.check(resources, environment);
1294
966
  ruleCheckStates.push(state);
1295
- if (AbilityCompare_1.default.and.isEqual(this.compareMethod) && AbilityMatch_1.default.mismatch.isEqual(state)) {
967
+ if (AbilityCompare.and.isEqual(this.compareMethod) && AbilityMatch.mismatch.isEqual(state)) {
1296
968
  return this.state; // mismatch
1297
969
  }
1298
- if (AbilityCompare_1.default.or.isEqual(this.compareMethod) && AbilityMatch_1.default.match.isEqual(state)) {
1299
- this.state = AbilityMatch_1.default.match;
970
+ if (AbilityCompare.or.isEqual(this.compareMethod) && AbilityMatch.match.isEqual(state)) {
971
+ this.state = AbilityMatch.match;
1300
972
  return this.state;
1301
973
  }
1302
974
  }
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;
975
+ if (AbilityCompare.and.isEqual(this.compareMethod)) {
976
+ if (ruleCheckStates.every(s => AbilityMatch.match.isEqual(s))) {
977
+ this.state = AbilityMatch.match;
1306
978
  }
1307
979
  }
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;
980
+ if (AbilityCompare.or.isEqual(this.compareMethod)) {
981
+ if (ruleCheckStates.some(s => AbilityMatch.match.isEqual(s))) {
982
+ this.state = AbilityMatch.match;
1311
983
  }
1312
984
  }
1313
985
  return this.state;
@@ -1315,78 +987,247 @@ class AbilityRuleSet {
1315
987
  toString() {
1316
988
  return `AbilityRuleSet: ${this.name} compareMethod: ${this.compareMethod.code}, rules: ${this.rules.map(rule => rule.toString()).join('\n')}`;
1317
989
  }
1318
- /**
1319
- * Parse the config JSON format to Group class instance
1320
- */
1321
- static fromJSON(config) {
1322
- return AbilityJSONParser_1.AbilityJSONParser.parseRuleSet(config);
990
+ copyWith(props) {
991
+ const next = new AbilityRuleSet({
992
+ id: props.id ?? this.id,
993
+ name: props.name ?? this.name,
994
+ compareMethod: props.compareMethod ?? this.compareMethod,
995
+ });
996
+ const nextRules = props.rules ?? this.rules;
997
+ for (const rule of nextRules) {
998
+ next.addRule(rule);
999
+ }
1000
+ return next;
1323
1001
  }
1324
1002
  static and(rules) {
1325
1003
  return new AbilityRuleSet({
1326
- compareMethod: AbilityCompare_1.default.and,
1004
+ compareMethod: AbilityCompare.and,
1327
1005
  }).addRules(rules);
1328
1006
  }
1329
1007
  static or(rules) {
1330
1008
  return new AbilityRuleSet({
1331
- compareMethod: AbilityCompare_1.default.or,
1009
+ compareMethod: AbilityCompare.or,
1332
1010
  }).addRules(rules);
1333
1011
  }
1334
1012
  }
1335
- exports.AbilityRuleSet = AbilityRuleSet;
1336
- exports["default"] = AbilityRuleSet;
1337
-
1338
-
1339
- /***/ }),
1340
-
1341
- /***/ 156:
1342
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
1343
-
1344
1013
 
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
- /***/ }),
1014
+ class AbilityInMemoryCache {
1015
+ store = new Map();
1016
+ async get(key) {
1017
+ const entry = this.store.get(key);
1018
+ if (!entry)
1019
+ return undefined;
1020
+ if (Date.now() > entry.expires) {
1021
+ this.store.delete(key);
1022
+ return undefined;
1023
+ }
1024
+ return entry.value;
1025
+ }
1026
+ async set(key, value, ttlSeconds = 60) {
1027
+ this.store.set(key, {
1028
+ value,
1029
+ expires: Date.now() + ttlSeconds * 1000,
1030
+ });
1031
+ }
1032
+ serialize(input) {
1033
+ return this.fastHash(this.stableStringify(input));
1034
+ }
1035
+ async delete(key) {
1036
+ this.store.delete(key);
1037
+ }
1038
+ async clear() {
1039
+ this.store.clear();
1040
+ }
1041
+ async deleteByPrefix(prefix) {
1042
+ for (const key of this.store.keys()) {
1043
+ if (key.startsWith(prefix)) {
1044
+ this.store.delete(key);
1045
+ }
1046
+ }
1047
+ }
1048
+ fastHash(str) {
1049
+ let hash = 5381;
1050
+ for (let i = 0; i < str.length; i++) {
1051
+ hash = (hash * 33) ^ str.charCodeAt(i);
1052
+ }
1053
+ return (hash >>> 0).toString(36);
1054
+ }
1055
+ stableStringify(obj) {
1056
+ if (obj === null)
1057
+ return 'null';
1058
+ const type = typeof obj;
1059
+ if (type === 'string')
1060
+ return JSON.stringify(obj);
1061
+ if (type === 'number' || type === 'boolean')
1062
+ return String(obj);
1063
+ if (type === 'undefined')
1064
+ return 'undefined';
1065
+ if (Array.isArray(obj)) {
1066
+ let out = '[';
1067
+ for (let i = 0; i < obj.length; i++) {
1068
+ if (i > 0)
1069
+ out += ',';
1070
+ out += this.stableStringify(obj[i]);
1071
+ }
1072
+ return out + ']';
1073
+ }
1074
+ const keys = Object.keys(obj);
1075
+ keys.sort();
1076
+ let out = '{';
1077
+ for (let i = 0; i < keys.length; i++) {
1078
+ const k = keys[i];
1079
+ if (i > 0)
1080
+ out += ',';
1081
+ out += k + ':' + this.stableStringify(obj[k]);
1082
+ }
1083
+ return out + '}';
1084
+ }
1085
+ }
1382
1086
 
1383
- /***/ 10:
1384
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1087
+ class AbilityJSONParser {
1088
+ /**
1089
+ * Parses an array of policy configurations into an array of AbilityPolicy instances.
1090
+ * @param configs - Array of policy configurations
1091
+ * @returns Array of AbilityPolicy instances
1092
+ */
1093
+ static parse(configs) {
1094
+ return configs.map(config => AbilityJSONParser.parsePolicy(config));
1095
+ }
1096
+ static parsePolicy(config) {
1097
+ const { id, name, ruleSet, compareMethod, permission, effect } = config;
1098
+ // Create the empty policy
1099
+ const policy = new AbilityPolicy({
1100
+ name,
1101
+ id,
1102
+ permission: permission,
1103
+ effect: new AbilityPolicyEffect(effect),
1104
+ });
1105
+ policy.compareMethod = new AbilityCompare(compareMethod);
1106
+ ruleSet.forEach(ruleSetConfig => {
1107
+ policy.addRuleSet(AbilityJSONParser.parseRuleSet(ruleSetConfig));
1108
+ });
1109
+ return policy;
1110
+ }
1111
+ static parseRule(config) {
1112
+ const { id, name, subject, resource, condition } = config;
1113
+ return new AbilityRule({
1114
+ id,
1115
+ name,
1116
+ subject,
1117
+ resource,
1118
+ condition: new AbilityCondition(condition),
1119
+ });
1120
+ }
1121
+ /**
1122
+ * Parse the config JSON format to Group class instance
1123
+ */
1124
+ static parseRuleSet(config) {
1125
+ const { id, name, rules, compareMethod } = config;
1126
+ const ruleSet = new AbilityRuleSet({
1127
+ compareMethod: new AbilityCompare(compareMethod),
1128
+ name,
1129
+ id,
1130
+ });
1131
+ // Adding rules if exists
1132
+ if (rules && rules.length > 0) {
1133
+ const abilityRules = rules.map(ruleConfig => AbilityJSONParser.parseRule(ruleConfig));
1134
+ ruleSet.addRules(abilityRules);
1135
+ }
1136
+ return ruleSet;
1137
+ }
1138
+ static ruleToJSON(rule) {
1139
+ return {
1140
+ id: rule.id,
1141
+ name: rule.name,
1142
+ subject: rule.subject,
1143
+ resource: rule.resource,
1144
+ condition: rule.condition.code,
1145
+ };
1146
+ }
1147
+ static ruleSetToJSON(ruleSet) {
1148
+ return {
1149
+ id: ruleSet.id.toString(),
1150
+ name: ruleSet.name.toString(),
1151
+ compareMethod: ruleSet.compareMethod.code.toString(),
1152
+ rules: ruleSet.rules.map(rule => AbilityJSONParser.ruleToJSON(rule)),
1153
+ };
1154
+ }
1155
+ static policyToJSON(policy) {
1156
+ return {
1157
+ id: policy.id.toString(),
1158
+ name: policy.name.toString(),
1159
+ compareMethod: policy.compareMethod.code.toString(),
1160
+ ruleSet: policy.ruleSet.map(ruleSet => AbilityJSONParser.ruleSetToJSON(ruleSet)),
1161
+ permission: policy.permission,
1162
+ effect: policy.effect.code,
1163
+ };
1164
+ }
1165
+ static toJSON(policies) {
1166
+ return policies.map(policy => AbilityJSONParser.policyToJSON(policy));
1167
+ }
1168
+ }
1385
1169
 
1170
+ /**
1171
+ * Represents a single token produced by the Ability DSL lexer.
1172
+ * Each token carries a type (e.g., EFFECT, IDENTIFIER, STRING) and its raw string value.
1173
+ */
1174
+ class AbilityDSLToken extends AbilityCode {
1175
+ /** The literal text of the token as it appeared in the input (e.g., "permit", "user.roles", "admin"). */
1176
+ value = '';
1177
+ /** The line number in DSL */
1178
+ line = 1;
1179
+ /** The column in dsl */
1180
+ column = 1;
1181
+ constructor(type, value, line, column) {
1182
+ super(type);
1183
+ this.value = value;
1184
+ this.line = line;
1185
+ this.column = column;
1186
+ }
1187
+ /**
1188
+ * Returns a human-readable representation of the token, useful for debugging.
1189
+ * Example output: "AbilityDSLToken([EFFECT] permit"
1190
+ */
1191
+ toString() {
1192
+ return `AbilityDSLToken([${this.code}] "${this.value}" at ${this.line}:${this.column})`;
1193
+ }
1194
+ static EFFECT = 'EFFECT';
1195
+ static IF = 'IF';
1196
+ static PERMISSION = 'PERMISSION';
1197
+ static IDENTIFIER = 'IDENTIFIER';
1198
+ static COLON = 'COLON';
1199
+ static COMMA = 'COMMA';
1200
+ static DOT = 'DOT';
1201
+ static LBRACKET = 'LBRACKET';
1202
+ static RBRACKET = 'RBRACKET';
1203
+ static ALL = 'ALL';
1204
+ static ANY = 'ANY';
1205
+ static OF = 'OF';
1206
+ static EOF = 'EOF';
1207
+ static COMMENT = 'COMMENT';
1208
+ static EQ = 'EQ';
1209
+ static CONTAINS = 'CONTAINS';
1210
+ static IN = 'IN';
1211
+ static NOT_IN = 'NOT_IN';
1212
+ static NOT_CONTAINS = 'NOT_CONTAINS';
1213
+ static GT = 'GT';
1214
+ static GTE = 'GTE';
1215
+ static LT = 'LT';
1216
+ static LTE = 'LTE';
1217
+ static NULL = 'NULL';
1218
+ static EQ_NULL = 'EQ_NULL';
1219
+ static NOT_EQ_NULL = 'NOT_EQ_NULL';
1220
+ static LEN_GT = 'LEN_GT';
1221
+ static LEN_LT = 'LEN_LT';
1222
+ static LEN_EQ = 'LEN_EQ';
1223
+ static NOT_EQ = 'NOT_EQ';
1224
+ static STRING = 'STRING';
1225
+ static NUMBER = 'NUMBER';
1226
+ static BOOLEAN = 'BOOLEAN';
1227
+ static SYMBOL = 'SYMBOL';
1228
+ static KEYWORD = 'KEYWORD';
1229
+ }
1386
1230
 
1387
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1388
- exports.AbilityDSLLexer = void 0;
1389
- const AbilityDSLToken_1 = __webpack_require__(325);
1390
1231
  class AbilityDSLLexer {
1391
1232
  input;
1392
1233
  pos = 0;
@@ -1454,7 +1295,7 @@ class AbilityDSLLexer {
1454
1295
  }
1455
1296
  throw new Error(`Unexpected character '${char}' at ${this.line}:${this.column}`);
1456
1297
  }
1457
- this.tokens.push(new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.EOF, '', this.line, this.column));
1298
+ this.tokens.push(new AbilityDSLToken(AbilityDSLToken.EOF, '', this.line, this.column));
1458
1299
  return this.tokens;
1459
1300
  }
1460
1301
  readComment() {
@@ -1465,7 +1306,7 @@ class AbilityDSLLexer {
1465
1306
  while (!this.isAtEnd() && !this.isNewline()) {
1466
1307
  value += this.advance();
1467
1308
  }
1468
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.COMMENT, value.trim(), startLine, startColumn);
1309
+ return new AbilityDSLToken(AbilityDSLToken.COMMENT, value.trim(), startLine, startColumn);
1469
1310
  }
1470
1311
  readString() {
1471
1312
  const startLine = this.line;
@@ -1485,7 +1326,7 @@ class AbilityDSLLexer {
1485
1326
  continue;
1486
1327
  }
1487
1328
  if (char === quote) {
1488
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.STRING, value, startLine, startColumn);
1329
+ return new AbilityDSLToken(AbilityDSLToken.STRING, value, startLine, startColumn);
1489
1330
  }
1490
1331
  value += char;
1491
1332
  }
@@ -1499,7 +1340,7 @@ class AbilityDSLLexer {
1499
1340
  this.advance();
1500
1341
  }
1501
1342
  const value = this.input.slice(start, this.pos);
1502
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.NUMBER, value, startLine, startColumn);
1343
+ return new AbilityDSLToken(AbilityDSLToken.NUMBER, value, startLine, startColumn);
1503
1344
  }
1504
1345
  readSymbol() {
1505
1346
  const startLine = this.line;
@@ -1507,41 +1348,41 @@ class AbilityDSLLexer {
1507
1348
  const char = this.advance();
1508
1349
  switch (char) {
1509
1350
  case '.':
1510
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.DOT, char, startLine, startColumn);
1351
+ return new AbilityDSLToken(AbilityDSLToken.DOT, char, startLine, startColumn);
1511
1352
  case ':':
1512
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.COLON, char, startLine, startColumn);
1353
+ return new AbilityDSLToken(AbilityDSLToken.COLON, char, startLine, startColumn);
1513
1354
  case ',':
1514
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.COMMA, char, startLine, startColumn);
1355
+ return new AbilityDSLToken(AbilityDSLToken.COMMA, char, startLine, startColumn);
1515
1356
  case '[':
1516
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.LBRACKET, char, startLine, startColumn);
1357
+ return new AbilityDSLToken(AbilityDSLToken.LBRACKET, char, startLine, startColumn);
1517
1358
  case ']':
1518
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.RBRACKET, char, startLine, startColumn);
1359
+ return new AbilityDSLToken(AbilityDSLToken.RBRACKET, char, startLine, startColumn);
1519
1360
  case '>':
1520
1361
  if (this.peek() === '=') {
1521
1362
  this.advance();
1522
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '>=', startLine, startColumn);
1363
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '>=', startLine, startColumn);
1523
1364
  }
1524
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '>', startLine, startColumn);
1365
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '>', startLine, startColumn);
1525
1366
  case '<':
1526
1367
  if (this.peek() === '=') {
1527
1368
  this.advance();
1528
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '<=', startLine, startColumn);
1369
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '<=', startLine, startColumn);
1529
1370
  }
1530
1371
  if (this.peek() === '>') {
1531
1372
  this.advance();
1532
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '<>', startLine, startColumn);
1373
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '<>', startLine, startColumn);
1533
1374
  }
1534
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '<', startLine, startColumn);
1375
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '<', startLine, startColumn);
1535
1376
  case '=':
1536
1377
  if (this.peek() === '=') {
1537
1378
  this.advance();
1538
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '==', startLine, startColumn);
1379
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '==', startLine, startColumn);
1539
1380
  }
1540
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '=', startLine, startColumn);
1381
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '=', startLine, startColumn);
1541
1382
  case '!':
1542
1383
  if (this.peek() === '=') {
1543
1384
  this.advance();
1544
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.SYMBOL, '!=', startLine, startColumn);
1385
+ return new AbilityDSLToken(AbilityDSLToken.SYMBOL, '!=', startLine, startColumn);
1545
1386
  }
1546
1387
  throw new Error(`Unexpected symbol '!' at ${this.line}:${this.column}`);
1547
1388
  default:
@@ -1570,52 +1411,52 @@ class AbilityDSLLexer {
1570
1411
  // Если есть точка — это путь (identifier или permission)
1571
1412
  if (word.includes('.')) {
1572
1413
  const last = this.tokens[this.tokens.length - 1];
1573
- if (last?.code === AbilityDSLToken_1.AbilityDSLToken.EFFECT) {
1414
+ if (last?.code === AbilityDSLToken.EFFECT) {
1574
1415
  if (word.startsWith('permission.')) {
1575
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1416
+ return new AbilityDSLToken(AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1576
1417
  }
1577
1418
  }
1578
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1419
+ return new AbilityDSLToken(AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1579
1420
  }
1580
1421
  // Ключевые слова
1581
1422
  if (this.keywords.has(word)) {
1582
1423
  // Эффекты
1583
1424
  if (word === 'permit' || word === 'allow') {
1584
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.EFFECT, 'permit', startLine, startColumn);
1425
+ return new AbilityDSLToken(AbilityDSLToken.EFFECT, 'permit', startLine, startColumn);
1585
1426
  }
1586
1427
  if (word === 'deny' || word === 'forbidden') {
1587
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.EFFECT, 'deny', startLine, startColumn);
1428
+ return new AbilityDSLToken(AbilityDSLToken.EFFECT, 'deny', startLine, startColumn);
1588
1429
  }
1589
1430
  // Групповые ключевые слова
1590
1431
  if (word === 'all') {
1591
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.ALL, word, startLine, startColumn);
1432
+ return new AbilityDSLToken(AbilityDSLToken.ALL, word, startLine, startColumn);
1592
1433
  }
1593
1434
  if (word === 'any') {
1594
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.ANY, word, startLine, startColumn);
1435
+ return new AbilityDSLToken(AbilityDSLToken.ANY, word, startLine, startColumn);
1595
1436
  }
1596
1437
  if (word === 'of') {
1597
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.OF, word, startLine, startColumn);
1438
+ return new AbilityDSLToken(AbilityDSLToken.OF, word, startLine, startColumn);
1598
1439
  }
1599
1440
  if (word === 'if') {
1600
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.IF, word, startLine, startColumn);
1441
+ return new AbilityDSLToken(AbilityDSLToken.IF, word, startLine, startColumn);
1601
1442
  }
1602
1443
  // Булевы и null
1603
1444
  if (word === 'true' || word === 'false') {
1604
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.BOOLEAN, word, startLine, startColumn);
1445
+ return new AbilityDSLToken(AbilityDSLToken.BOOLEAN, word, startLine, startColumn);
1605
1446
  }
1606
1447
  if (word === 'null') {
1607
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.NULL, word, startLine, startColumn);
1448
+ return new AbilityDSLToken(AbilityDSLToken.NULL, word, startLine, startColumn);
1608
1449
  }
1609
1450
  // Остальные ключевые слова (contains, in, equals, greater, less, not, is, or, than, equal)
1610
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.KEYWORD, word, startLine, startColumn);
1451
+ return new AbilityDSLToken(AbilityDSLToken.KEYWORD, word, startLine, startColumn);
1611
1452
  }
1612
1453
  // Если после EFFECT и нет точки — действие (например, "create")
1613
1454
  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);
1455
+ if (lastToken?.code === AbilityDSLToken.EFFECT) {
1456
+ return new AbilityDSLToken(AbilityDSLToken.PERMISSION, word, startLine, startColumn);
1616
1457
  }
1617
1458
  // Обычный идентификатор
1618
- return new AbilityDSLToken_1.AbilityDSLToken(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1459
+ return new AbilityDSLToken(AbilityDSLToken.IDENTIFIER, word, startLine, startColumn);
1619
1460
  }
1620
1461
  skipWhitespace() {
1621
1462
  while (!this.isAtEnd() && /\s/.test(this.peek())) {
@@ -1648,33 +1489,73 @@ class AbilityDSLLexer {
1648
1489
  }
1649
1490
  return ch;
1650
1491
  }
1651
- isAtEnd() {
1652
- return this.pos >= this.input.length;
1492
+ isAtEnd() {
1493
+ return this.pos >= this.input.length;
1494
+ }
1495
+ }
1496
+
1497
+ class AbilityDSLSyntaxError extends Error {
1498
+ line;
1499
+ column;
1500
+ context;
1501
+ details;
1502
+ _formattedMessage;
1503
+ _originalStack;
1504
+ constructor(line, column, context, // строка DSL + ^ + соседние строки
1505
+ details) {
1506
+ super(details.split('\n')[0]); // message = только первая строка
1507
+ this.line = line;
1508
+ this.column = column;
1509
+ this.context = context;
1510
+ this.details = details;
1511
+ this.name = 'AbilityDSLSyntaxError';
1512
+ if (Error.captureStackTrace) {
1513
+ Error.captureStackTrace(this, AbilityDSLSyntaxError);
1514
+ }
1515
+ this._originalStack = this.stack;
1516
+ this._formattedMessage = this.formatMessage();
1517
+ Object.defineProperty(this, 'stack', {
1518
+ get: () => this._formattedMessage,
1519
+ configurable: true,
1520
+ });
1521
+ }
1522
+ static supportsColor() {
1523
+ return typeof process !== 'undefined' && process.stdout?.isTTY;
1524
+ }
1525
+ formatMessage() {
1526
+ const useColor = AbilityDSLSyntaxError.supportsColor();
1527
+ const BOLD = useColor ? '\x1b[1m' : '';
1528
+ const RED = useColor ? '\x1b[31m' : '';
1529
+ const ORANGE = useColor ? '\x1b[33;1m' : '';
1530
+ const GRAY = useColor ? '\x1b[90m' : '';
1531
+ const RESET = useColor ? '\x1b[0m' : '';
1532
+ const lines = this.context.split('\n');
1533
+ // Find line with ^
1534
+ const pointerIndex = lines.findIndex(l => l.includes('^') || l.includes('~'));
1535
+ const commentIndex = lines.findIndex(l => l.trim().includes('#'));
1536
+ const formattedLines = lines.map((line, idx) => {
1537
+ if (idx === pointerIndex - 1) {
1538
+ // Error line
1539
+ return `${BOLD}${ORANGE}${line}${RESET}`;
1540
+ }
1541
+ if (idx === pointerIndex) {
1542
+ // Error with ~~~~~
1543
+ return `${RED}${line}${RESET}`;
1544
+ }
1545
+ // Comments # ...
1546
+ if (idx === commentIndex) {
1547
+ return `${GRAY}${line}${RESET}`;
1548
+ }
1549
+ return line;
1550
+ });
1551
+ const contextBlock = formattedLines.join('\n');
1552
+ return `${BOLD}${RED}${this.name}: ${this.details}${RESET}\n\n` + contextBlock;
1553
+ }
1554
+ toString() {
1555
+ return this._formattedMessage;
1653
1556
  }
1654
1557
  }
1655
- exports.AbilityDSLLexer = AbilityDSLLexer;
1656
-
1657
1558
 
1658
- /***/ }),
1659
-
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
1559
  /**
1679
1560
  * Parser for the Ability DSL.
1680
1561
  *
@@ -1708,7 +1589,7 @@ class AbilityDSLParser {
1708
1589
  */
1709
1590
  parse() {
1710
1591
  // Tokenize the entire DSL string.
1711
- this.tokens = new AbilityDSLLexer_1.AbilityDSLLexer(this.dsl).tokenize();
1592
+ this.tokens = new AbilityDSLLexer(this.dsl).tokenize();
1712
1593
  this.pos = 0;
1713
1594
  const policies = [];
1714
1595
  // Keep parsing until we've consumed all tokens.
@@ -1736,29 +1617,29 @@ class AbilityDSLParser {
1736
1617
  this.consumeLeadingComments();
1737
1618
  const meta = this.takeAnnotations();
1738
1619
  // Effect: "permit" or "deny"
1739
- const effectToken = this.consume(AbilityDSLToken_1.AbilityDSLToken.EFFECT, 'Expected effect');
1620
+ const effectToken = this.consume(AbilityDSLToken.EFFECT, 'Expected effect');
1740
1621
  const effect = effectToken.value;
1741
1622
  // Permission: e.g. "order.update"
1742
- const permissionToken = this.consume(AbilityDSLToken_1.AbilityDSLToken.PERMISSION, 'Expected permission');
1623
+ const permissionToken = this.consume(AbilityDSLToken.PERMISSION, 'Expected permission');
1743
1624
  const permission = permissionToken.value;
1744
1625
  if (!permission.startsWith('permission.')) {
1745
1626
  return this.syntaxError(`Unexpected token. The permission key, must be starts with prefix \`permission.\`, but got \`${permission}\`.\nDid you mean \`permission.${permission}\`?`, permissionToken);
1746
1627
  }
1747
1628
  // "if" keyword
1748
- this.consume(AbilityDSLToken_1.AbilityDSLToken.IF, 'Expected "if"');
1629
+ this.consume(AbilityDSLToken.IF, 'Expected "if"');
1749
1630
  // 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;
1631
+ const compareToken = this.consumeOneOf([AbilityDSLToken.ALL, AbilityDSLToken.ANY], 'Expected "all" or "any"');
1632
+ const compareMethod = compareToken.code === AbilityDSLToken.ALL ? AbilityCompare.and : AbilityCompare.or;
1752
1633
  // Colon after the group keyword
1753
- this.consume(AbilityDSLToken_1.AbilityDSLToken.COLON, 'Expected ":"');
1634
+ this.consume(AbilityDSLToken.COLON, 'Expected ":"');
1754
1635
  // Parse the list of rule sets (each "all of:" or "any of:" block)
1755
1636
  const ruleSets = this.parseRuleSets(compareMethod);
1756
1637
  // Construct the policy instance.
1757
- return new AbilityPolicy_1.default({
1638
+ return new AbilityPolicy({
1758
1639
  id: `${effect}:${permission}:${Math.random()}`,
1759
1640
  name: meta.name ?? `${effect} ${permission}`,
1760
1641
  permission: permission.replace(/^permission\./, ''),
1761
- effect: effect === 'permit' ? AbilityPolicyEffect_1.default.permit : AbilityPolicyEffect_1.default.deny,
1642
+ effect: effect === 'permit' ? AbilityPolicyEffect.permit : AbilityPolicyEffect.deny,
1762
1643
  compareMethod,
1763
1644
  }).addRuleSets(ruleSets);
1764
1645
  }
@@ -1779,7 +1660,7 @@ class AbilityDSLParser {
1779
1660
  }
1780
1661
  // Иначе — implicit group (all-of по умолчанию)
1781
1662
  const meta = this.takeAnnotations();
1782
- const group = new AbilityRuleSet_1.default({
1663
+ const group = new AbilityRuleSet({
1783
1664
  compareMethod: policyCompareMethod,
1784
1665
  name: meta.name,
1785
1666
  });
@@ -1789,7 +1670,7 @@ class AbilityDSLParser {
1789
1670
  if (this.isStartOfGroup() || this.isStartOfPolicy()) {
1790
1671
  break;
1791
1672
  }
1792
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER)) {
1673
+ if (this.check(AbilityDSLToken.IDENTIFIER)) {
1793
1674
  group.addRule(this.parseRule());
1794
1675
  }
1795
1676
  else {
@@ -1806,19 +1687,19 @@ class AbilityDSLParser {
1806
1687
  parseGroup() {
1807
1688
  this.consumeLeadingComments();
1808
1689
  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)) {
1690
+ const compareToken = this.consumeOneOf([AbilityDSLToken.ALL, AbilityDSLToken.ANY], 'Expected "all" or "any"');
1691
+ const compareMethod = compareToken.code === AbilityDSLToken.ALL ? AbilityCompare.and : AbilityCompare.or;
1692
+ if (this.check(AbilityDSLToken.OF)) {
1812
1693
  this.advance();
1813
1694
  }
1814
- this.consume(AbilityDSLToken_1.AbilityDSLToken.COLON, 'Expected ":"');
1815
- const group = new AbilityRuleSet_1.default({ compareMethod, name: meta.name });
1695
+ this.consume(AbilityDSLToken.COLON, 'Expected ":"');
1696
+ const group = new AbilityRuleSet({ compareMethod, name: meta.name });
1816
1697
  while (!this.isAtEnd()) {
1817
1698
  this.consumeLeadingComments();
1818
1699
  if (this.isStartOfGroup() || this.isStartOfPolicy()) {
1819
1700
  break;
1820
1701
  }
1821
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER)) {
1702
+ if (this.check(AbilityDSLToken.IDENTIFIER)) {
1822
1703
  group.addRule(this.parseRule());
1823
1704
  }
1824
1705
  else {
@@ -1836,19 +1717,19 @@ class AbilityDSLParser {
1836
1717
  parseRule() {
1837
1718
  this.consumeLeadingComments();
1838
1719
  const meta = this.takeAnnotations();
1839
- if (!this.check(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER)) {
1720
+ if (!this.check(AbilityDSLToken.IDENTIFIER)) {
1840
1721
  this.syntaxError(`Expected identifier, got ${this.peek().code}`, this.peek());
1841
1722
  }
1842
1723
  // Subject (e.g., "user.roles")
1843
- const subject = this.consume(AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER, 'Expected field').value;
1724
+ const subject = this.consume(AbilityDSLToken.IDENTIFIER, 'Expected field').value;
1844
1725
  // Operator (e.g., "contains", "equals", "is not null")
1845
1726
  const { condition, operator } = this.parseConditionOperator();
1846
1727
  let resource;
1847
1728
  let beforePos = this.pos;
1848
1729
  // 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) {
1730
+ if (operator === AbilityDSLToken.EQ_NULL ||
1731
+ operator === AbilityDSLToken.NOT_EQ_NULL ||
1732
+ operator === AbilityDSLToken.NULL) {
1852
1733
  resource = null;
1853
1734
  }
1854
1735
  else {
@@ -1860,11 +1741,11 @@ class AbilityDSLParser {
1860
1741
  this.consumeLeadingComments();
1861
1742
  const resourceToken = this.tokens[beforePos];
1862
1743
  if (typeof resource === 'string' &&
1863
- resourceToken.code === AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER &&
1744
+ resourceToken.code === AbilityDSLToken.IDENTIFIER &&
1864
1745
  !resourceToken.value.includes('.')) {
1865
- this.syntaxError(`Expected comparison operator or value, got \`${resource}\``, this.tokens[beforePos], [AbilityDSLToken_1.AbilityDSLToken.KEYWORD]);
1746
+ this.syntaxError(`Expected comparison operator or value, got \`${resource}\``, this.tokens[beforePos], [AbilityDSLToken.KEYWORD]);
1866
1747
  }
1867
- return new AbilityRule_1.default({
1748
+ return new AbilityRule({
1868
1749
  subject,
1869
1750
  resource,
1870
1751
  condition,
@@ -1882,32 +1763,32 @@ class AbilityDSLParser {
1882
1763
  const savedPos = this.pos;
1883
1764
  // "length equals"
1884
1765
  if (this.matchWord('length') && this.matchWord('equals')) {
1885
- return { condition: AbilityCondition_1.default.length_equals, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_EQ };
1766
+ return { condition: AbilityCondition.length_equals, operator: AbilityDSLToken.LEN_EQ };
1886
1767
  }
1887
1768
  this.pos = savedPos;
1888
1769
  // "length ="
1889
1770
  if (this.matchWord('length') && this.matchSymbol('=')) {
1890
- return { condition: AbilityCondition_1.default.length_equals, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_EQ };
1771
+ return { condition: AbilityCondition.length_equals, operator: AbilityDSLToken.LEN_EQ };
1891
1772
  }
1892
1773
  this.pos = savedPos;
1893
1774
  // "length greater than"
1894
1775
  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 };
1776
+ return { condition: AbilityCondition.length_greater_than, operator: AbilityDSLToken.LEN_GT };
1896
1777
  }
1897
1778
  this.pos = savedPos;
1898
1779
  // "length >"
1899
1780
  if (this.matchWord('length') && this.matchSymbol('>')) {
1900
- return { condition: AbilityCondition_1.default.length_greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_GT };
1781
+ return { condition: AbilityCondition.length_greater_than, operator: AbilityDSLToken.LEN_GT };
1901
1782
  }
1902
1783
  this.pos = savedPos;
1903
1784
  // "length less than"
1904
1785
  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 };
1786
+ return { condition: AbilityCondition.length_less_than, operator: AbilityDSLToken.LEN_LT };
1906
1787
  }
1907
1788
  this.pos = savedPos;
1908
1789
  // "length <"
1909
1790
  if (this.matchWord('length') && this.matchSymbol('<')) {
1910
- return { condition: AbilityCondition_1.default.length_less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LEN_LT };
1791
+ return { condition: AbilityCondition.length_less_than, operator: AbilityDSLToken.LEN_LT };
1911
1792
  }
1912
1793
  this.pos = savedPos;
1913
1794
  // "greater than or equal"
@@ -1915,12 +1796,12 @@ class AbilityDSLParser {
1915
1796
  this.matchWord('than') &&
1916
1797
  this.matchWord('or') &&
1917
1798
  this.matchWord('equal')) {
1918
- return { condition: AbilityCondition_1.default.greater_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.GTE };
1799
+ return { condition: AbilityCondition.greater_or_equal, operator: AbilityDSLToken.GTE };
1919
1800
  }
1920
1801
  this.pos = savedPos;
1921
1802
  // greater than
1922
1803
  if (this.matchWord('greater') && this.matchWord('than')) {
1923
- return { condition: AbilityCondition_1.default.greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.GT };
1804
+ return { condition: AbilityCondition.greater_than, operator: AbilityDSLToken.GT };
1924
1805
  }
1925
1806
  this.pos = savedPos;
1926
1807
  // less than or equal
@@ -1928,143 +1809,141 @@ class AbilityDSLParser {
1928
1809
  this.matchWord('than') &&
1929
1810
  this.matchWord('or') &&
1930
1811
  this.matchWord('equal')) {
1931
- return { condition: AbilityCondition_1.default.less_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.LTE };
1812
+ return { condition: AbilityCondition.less_or_equal, operator: AbilityDSLToken.LTE };
1932
1813
  }
1933
1814
  this.pos = savedPos;
1934
1815
  // less than
1935
1816
  if (this.matchWord('less') && this.matchWord('than')) {
1936
- return { condition: AbilityCondition_1.default.less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LT };
1817
+ return { condition: AbilityCondition.less_than, operator: AbilityDSLToken.LT };
1937
1818
  }
1938
1819
  this.pos = savedPos;
1939
1820
  // "not contains"
1940
1821
  if (this.matchWord('not') && this.matchWord('contains')) {
1941
1822
  return {
1942
- condition: AbilityCondition_1.default.not_contains,
1943
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_CONTAINS,
1823
+ condition: AbilityCondition.not_contains,
1824
+ operator: AbilityDSLToken.NOT_CONTAINS,
1944
1825
  };
1945
1826
  }
1946
1827
  this.pos = savedPos;
1947
1828
  // "not includes"
1948
1829
  if (this.matchWord('not') && this.matchWord('includes')) {
1949
1830
  return {
1950
- condition: AbilityCondition_1.default.not_contains,
1951
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_CONTAINS,
1831
+ condition: AbilityCondition.not_contains,
1832
+ operator: AbilityDSLToken.NOT_CONTAINS,
1952
1833
  };
1953
1834
  }
1954
1835
  this.pos = savedPos;
1955
1836
  // "not includes"
1956
1837
  if (this.matchWord('not') && this.matchWord('has')) {
1957
1838
  return {
1958
- condition: AbilityCondition_1.default.not_contains,
1959
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_CONTAINS,
1839
+ condition: AbilityCondition.not_contains,
1840
+ operator: AbilityDSLToken.NOT_CONTAINS,
1960
1841
  };
1961
1842
  }
1962
1843
  this.pos = savedPos;
1963
1844
  // "is equals"
1964
1845
  if (this.matchWord('is') && this.matchWord('equals')) {
1965
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1846
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
1966
1847
  }
1967
1848
  this.pos = savedPos;
1968
1849
  // not equal
1969
1850
  if (this.matchWord('not') && this.matchWord('equals')) {
1970
- return { condition: AbilityCondition_1.default.not_equals, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ };
1851
+ return { condition: AbilityCondition.not_equals, operator: AbilityDSLToken.NOT_EQ };
1971
1852
  }
1972
1853
  this.pos = savedPos;
1973
1854
  // is not equals
1974
1855
  if (this.matchWord('is') && this.matchWord('not') && this.matchWord('equals')) {
1975
- return { condition: AbilityCondition_1.default.not_equals, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ };
1856
+ return { condition: AbilityCondition.not_equals, operator: AbilityDSLToken.NOT_EQ };
1976
1857
  }
1977
1858
  this.pos = savedPos;
1978
1859
  // is in
1979
1860
  if (this.matchWord('is') && this.matchWord('in')) {
1980
- return { condition: AbilityCondition_1.default.in, operator: AbilityDSLToken_1.AbilityDSLToken.IN };
1861
+ return { condition: AbilityCondition.in, operator: AbilityDSLToken.IN };
1981
1862
  }
1982
1863
  this.pos = savedPos;
1983
1864
  // not in
1984
1865
  if (this.matchWord('not') && this.matchWord('in')) {
1985
- return { condition: AbilityCondition_1.default.not_in, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_IN };
1866
+ return { condition: AbilityCondition.not_in, operator: AbilityDSLToken.NOT_IN };
1986
1867
  }
1987
1868
  this.pos = savedPos;
1988
1869
  // is not null
1989
1870
  if (this.matchWord('is') && this.matchWord('not')) {
1990
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.NULL)) {
1871
+ if (this.check(AbilityDSLToken.NULL)) {
1991
1872
  this.advance();
1992
1873
  return {
1993
- condition: AbilityCondition_1.default.not_equals,
1994
- operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ_NULL,
1874
+ condition: AbilityCondition.not_equals,
1875
+ operator: AbilityDSLToken.NOT_EQ_NULL,
1995
1876
  };
1996
1877
  }
1997
1878
  }
1998
1879
  this.pos = savedPos;
1999
1880
  // is null
2000
1881
  if (this.matchWord('is') && this.matchWord('null')) {
2001
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.NULL)) {
1882
+ if (this.check(AbilityDSLToken.NULL)) {
2002
1883
  this.advance();
2003
1884
  return {
2004
- condition: AbilityCondition_1.default.equals,
2005
- operator: AbilityDSLToken_1.AbilityDSLToken.EQ_NULL,
1885
+ condition: AbilityCondition.equals,
1886
+ operator: AbilityDSLToken.EQ_NULL,
2006
1887
  };
2007
1888
  }
2008
1889
  }
2009
1890
  this.pos = savedPos;
2010
1891
  // Single token (symbol or keyword)
2011
1892
  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) {
1893
+ if (token.code !== AbilityDSLToken.SYMBOL &&
1894
+ token.code !== AbilityDSLToken.KEYWORD &&
1895
+ token.code !== AbilityDSLToken.NULL) {
2015
1896
  this.syntaxError(`Expected comparison operator, got \`${token.value}\``, token, [
2016
- AbilityDSLToken_1.AbilityDSLToken.SYMBOL,
2017
- AbilityDSLToken_1.AbilityDSLToken.KEYWORD,
2018
- AbilityDSLToken_1.AbilityDSLToken.NULL,
1897
+ AbilityDSLToken.SYMBOL,
1898
+ AbilityDSLToken.KEYWORD,
1899
+ AbilityDSLToken.NULL,
2019
1900
  ]);
2020
1901
  }
2021
1902
  this.advance();
2022
1903
  switch (token.code) {
2023
- case AbilityDSLToken_1.AbilityDSLToken.SYMBOL:
1904
+ case AbilityDSLToken.SYMBOL:
2024
1905
  if (token.value === '=' || token.value === '==')
2025
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1906
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
2026
1907
  if (token.value === '!=' || token.value === '<>')
2027
- return { condition: AbilityCondition_1.default.not_equals, operator: AbilityDSLToken_1.AbilityDSLToken.NOT_EQ };
1908
+ return { condition: AbilityCondition.not_equals, operator: AbilityDSLToken.NOT_EQ };
2028
1909
  if (token.value === '>')
2029
- return { condition: AbilityCondition_1.default.greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.GT };
1910
+ return { condition: AbilityCondition.greater_than, operator: AbilityDSLToken.GT };
2030
1911
  if (token.value === '<')
2031
- return { condition: AbilityCondition_1.default.less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LT };
1912
+ return { condition: AbilityCondition.less_than, operator: AbilityDSLToken.LT };
2032
1913
  if (token.value === '>=')
2033
- return { condition: AbilityCondition_1.default.greater_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.GTE };
1914
+ return { condition: AbilityCondition.greater_or_equal, operator: AbilityDSLToken.GTE };
2034
1915
  if (token.value === '<=')
2035
- return { condition: AbilityCondition_1.default.less_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.LTE };
1916
+ return { condition: AbilityCondition.less_or_equal, operator: AbilityDSLToken.LTE };
2036
1917
  break;
2037
- case AbilityDSLToken_1.AbilityDSLToken.KEYWORD:
1918
+ case AbilityDSLToken.KEYWORD:
2038
1919
  if (token.value === 'contains' || token.value === 'includes' || token.value === 'has')
2039
- return { condition: AbilityCondition_1.default.contains, operator: AbilityDSLToken_1.AbilityDSLToken.CONTAINS };
1920
+ return { condition: AbilityCondition.contains, operator: AbilityDSLToken.CONTAINS };
2040
1921
  if (token.value === 'in')
2041
- return { condition: AbilityCondition_1.default.in, operator: AbilityDSLToken_1.AbilityDSLToken.IN };
1922
+ return { condition: AbilityCondition.in, operator: AbilityDSLToken.IN };
2042
1923
  if (token.value === 'equals')
2043
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1924
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
2044
1925
  if (token.value === 'gte') {
2045
- return { condition: AbilityCondition_1.default.greater_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.GTE };
1926
+ return { condition: AbilityCondition.greater_or_equal, operator: AbilityDSLToken.GTE };
2046
1927
  }
2047
1928
  if (token.value === 'greater' || token.value === 'gt') {
2048
1929
  // If we come here, it means "greater" without "than" – treat as '>'
2049
- return { condition: AbilityCondition_1.default.greater_than, operator: AbilityDSLToken_1.AbilityDSLToken.GT };
1930
+ return { condition: AbilityCondition.greater_than, operator: AbilityDSLToken.GT };
2050
1931
  }
2051
1932
  if (token.value === 'less' || token.value === 'lt') {
2052
- return { condition: AbilityCondition_1.default.less_than, operator: AbilityDSLToken_1.AbilityDSLToken.LT };
1933
+ return { condition: AbilityCondition.less_than, operator: AbilityDSLToken.LT };
2053
1934
  }
2054
1935
  if (token.value === 'lte') {
2055
- return { condition: AbilityCondition_1.default.less_or_equal, operator: AbilityDSLToken_1.AbilityDSLToken.LTE };
1936
+ return { condition: AbilityCondition.less_or_equal, operator: AbilityDSLToken.LTE };
2056
1937
  }
2057
1938
  if (token.value === 'is') {
2058
1939
  // "is" alone -> equals
2059
- return { condition: AbilityCondition_1.default.equals, operator: AbilityDSLToken_1.AbilityDSLToken.EQ };
1940
+ return { condition: AbilityCondition.equals, operator: AbilityDSLToken.EQ };
2060
1941
  }
2061
1942
  break;
2062
- default:
2063
- break;
2064
1943
  }
2065
1944
  return this.syntaxError(`Unexpected operator token \`${token.value}\``, token, [
2066
- AbilityDSLToken_1.AbilityDSLToken.SYMBOL,
2067
- AbilityDSLToken_1.AbilityDSLToken.KEYWORD,
1945
+ AbilityDSLToken.SYMBOL,
1946
+ AbilityDSLToken.KEYWORD,
2068
1947
  ]);
2069
1948
  }
2070
1949
  /**
@@ -2077,7 +1956,7 @@ class AbilityDSLParser {
2077
1956
  return false;
2078
1957
  }
2079
1958
  const token = this.peek();
2080
- if ((token.code === AbilityDSLToken_1.AbilityDSLToken.KEYWORD || token.code === AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER) &&
1959
+ if ((token.code === AbilityDSLToken.KEYWORD || token.code === AbilityDSLToken.IDENTIFIER) &&
2081
1960
  token.value === word) {
2082
1961
  this.advance();
2083
1962
  return true;
@@ -2088,7 +1967,7 @@ class AbilityDSLParser {
2088
1967
  if (this.isAtEnd())
2089
1968
  return false;
2090
1969
  const token = this.peek();
2091
- if (token.code === AbilityDSLToken_1.AbilityDSLToken.SYMBOL && token.value === symbol) {
1970
+ if (token.code === AbilityDSLToken.SYMBOL && token.value === symbol) {
2092
1971
  this.advance();
2093
1972
  return true;
2094
1973
  }
@@ -2103,32 +1982,32 @@ class AbilityDSLParser {
2103
1982
  */
2104
1983
  parseValue() {
2105
1984
  // Arrays start with a left bracket
2106
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.LBRACKET)) {
1985
+ if (this.check(AbilityDSLToken.LBRACKET)) {
2107
1986
  this.advance();
2108
1987
  return this.parseArray();
2109
1988
  }
2110
1989
  // Ensure we are not about to read a structural token as a value.
2111
1990
  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) {
1991
+ if (token.code === AbilityDSLToken.ALL ||
1992
+ token.code === AbilityDSLToken.ANY ||
1993
+ token.code === AbilityDSLToken.EFFECT) {
2115
1994
  this.syntaxError(`Unexpected ${token.code} in value position`, token);
2116
1995
  }
2117
1996
  this.advance();
2118
1997
  // CHECK THIS SWITCH COMPARE
2119
1998
  switch (token.code) {
2120
- case AbilityDSLToken_1.AbilityDSLToken.STRING:
1999
+ case AbilityDSLToken.STRING:
2121
2000
  return token.value;
2122
- case AbilityDSLToken_1.AbilityDSLToken.NUMBER:
2001
+ case AbilityDSLToken.NUMBER:
2123
2002
  return Number(token.value);
2124
- case AbilityDSLToken_1.AbilityDSLToken.BOOLEAN:
2003
+ case AbilityDSLToken.BOOLEAN:
2125
2004
  return token.value === 'true';
2126
- case AbilityDSLToken_1.AbilityDSLToken.NULL:
2005
+ case AbilityDSLToken.NULL:
2127
2006
  return null;
2128
- case AbilityDSLToken_1.AbilityDSLToken.IDENTIFIER:
2007
+ case AbilityDSLToken.IDENTIFIER:
2129
2008
  return token.value;
2130
2009
  default: {
2131
- this.syntaxError(`Unexpected value token "${token.value}"`, token ?? this.tokens[this.tokens.length - 1], [AbilityDSLToken_1.AbilityDSLToken.KEYWORD]);
2010
+ this.syntaxError(`Unexpected value token "${token.value}"`, token ?? this.tokens[this.tokens.length - 1], [AbilityDSLToken.KEYWORD]);
2132
2011
  }
2133
2012
  }
2134
2013
  }
@@ -2139,11 +2018,11 @@ class AbilityDSLParser {
2139
2018
  parseArray() {
2140
2019
  const arr = [];
2141
2020
  // Handle empty array
2142
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.RBRACKET)) {
2021
+ if (this.check(AbilityDSLToken.RBRACKET)) {
2143
2022
  this.advance();
2144
2023
  return arr;
2145
2024
  }
2146
- while (!this.isAtEnd() && !this.check(AbilityDSLToken_1.AbilityDSLToken.RBRACKET)) {
2025
+ while (!this.isAtEnd() && !this.check(AbilityDSLToken.RBRACKET)) {
2147
2026
  const value = this.parseValue();
2148
2027
  // Flatten nested arrays if they appear (though grammar doesn't currently allow nesting).
2149
2028
  if (Array.isArray(value)) {
@@ -2159,18 +2038,18 @@ class AbilityDSLParser {
2159
2038
  this.syntaxError('Unexpected null in array', this.peek());
2160
2039
  }
2161
2040
  // Optional comma between elements
2162
- if (this.check(AbilityDSLToken_1.AbilityDSLToken.COMMA)) {
2041
+ if (this.check(AbilityDSLToken.COMMA)) {
2163
2042
  this.advance();
2164
2043
  }
2165
2044
  }
2166
- this.consume(AbilityDSLToken_1.AbilityDSLToken.RBRACKET, 'Expected "]"');
2045
+ this.consume(AbilityDSLToken.RBRACKET, 'Expected "]"');
2167
2046
  return arr;
2168
2047
  }
2169
2048
  // -------------------------------------------------------------------------
2170
2049
  // #region Annotations and comments
2171
2050
  // -------------------------------------------------------------------------
2172
2051
  consumeLeadingComments() {
2173
- while (this.check(AbilityDSLToken_1.AbilityDSLToken.COMMENT)) {
2052
+ while (this.check(AbilityDSLToken.COMMENT)) {
2174
2053
  const token = this.advance();
2175
2054
  this.processCommentToken(token);
2176
2055
  }
@@ -2220,7 +2099,7 @@ class AbilityDSLParser {
2220
2099
  const detailsMsg = `${details}\nDetails: Unexpected value token \`${actual}\``;
2221
2100
  finalDetails = suggestion ? `${detailsMsg} Did you mean \`${suggestion}\`?` : detailsMsg;
2222
2101
  }
2223
- throw new AbilityDSLSyntaxError_1.AbilityDSLSyntaxError(token.line, token.column, context + '\n', finalDetails);
2102
+ throw new AbilityDSLSyntaxError(token.line, token.column, context + '\n', finalDetails);
2224
2103
  }
2225
2104
  getLine(lineNumber) {
2226
2105
  return this.dsl.split(/\r?\n/)[lineNumber - 1] ?? '';
@@ -2269,7 +2148,7 @@ class AbilityDSLParser {
2269
2148
  }
2270
2149
  }
2271
2150
  const expected = types.map(t => t).join(', ');
2272
- const actual = token ? token.value : AbilityDSLToken_1.AbilityDSLToken.EOF;
2151
+ const actual = token ? token.value : AbilityDSLToken.EOF;
2273
2152
  const suggestion = this.suggest(actual, types);
2274
2153
  const details = `${message}\nDetails: Unexpected token \`${actual}\`, expected one of: ${expected}.`;
2275
2154
  const finalMsg = suggestion ? `${details} Did you mean \`${suggestion}\`?` : details;
@@ -2281,7 +2160,7 @@ class AbilityDSLParser {
2281
2160
  return this.advance();
2282
2161
  }
2283
2162
  const expected = type;
2284
- const actual = token ? token.value : AbilityDSLToken_1.AbilityDSLToken.EOF;
2163
+ const actual = token ? token.value : AbilityDSLToken.EOF;
2285
2164
  const suggestion = this.suggest(actual, [type]);
2286
2165
  const details = `${message}\nDetails: Unexpected token \`${actual}\`, expected "${expected}".`;
2287
2166
  const finalMsg = suggestion ? `${details} Did you mean \`${suggestion}\`?` : details;
@@ -2293,10 +2172,10 @@ class AbilityDSLParser {
2293
2172
  return this.peek().code === type;
2294
2173
  }
2295
2174
  isStartOfPolicy() {
2296
- return this.check(AbilityDSLToken_1.AbilityDSLToken.EFFECT);
2175
+ return this.check(AbilityDSLToken.EFFECT);
2297
2176
  }
2298
2177
  isStartOfGroup() {
2299
- return this.check(AbilityDSLToken_1.AbilityDSLToken.ALL) || this.check(AbilityDSLToken_1.AbilityDSLToken.ANY);
2178
+ return this.check(AbilityDSLToken.ALL) || this.check(AbilityDSLToken.ANY);
2300
2179
  }
2301
2180
  advance() {
2302
2181
  return this.tokens[this.pos++];
@@ -2305,296 +2184,29 @@ class AbilityDSLParser {
2305
2184
  return this.tokens[this.pos];
2306
2185
  }
2307
2186
  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;
2187
+ return this.peek().code === AbilityDSLToken.EOF;
2381
2188
  }
2382
2189
  }
2383
- exports.AbilityDSLSyntaxError = AbilityDSLSyntaxError;
2384
-
2385
-
2386
- /***/ }),
2387
-
2388
- /***/ 325:
2389
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
2390
2190
 
2391
-
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
- }
2191
+ exports.AbilityCode = AbilityCode;
2192
+ exports.AbilityCompare = AbilityCompare;
2193
+ exports.AbilityCondition = AbilityCondition;
2194
+ exports.AbilityDSLLexer = AbilityDSLLexer;
2195
+ exports.AbilityDSLParser = AbilityDSLParser;
2458
2196
  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
- }
2197
+ exports.AbilityError = AbilityError;
2198
+ exports.AbilityExplain = AbilityExplain;
2199
+ exports.AbilityExplainPolicy = AbilityExplainPolicy;
2200
+ exports.AbilityExplainRule = AbilityExplainRule;
2201
+ exports.AbilityExplainRuleSet = AbilityExplainRuleSet;
2202
+ exports.AbilityInMemoryCache = AbilityInMemoryCache;
2560
2203
  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
- ;
2204
+ exports.AbilityMatch = AbilityMatch;
2205
+ exports.AbilityParserError = AbilityParserError;
2206
+ exports.AbilityPolicy = AbilityPolicy;
2207
+ exports.AbilityPolicyEffect = AbilityPolicyEffect;
2208
+ exports.AbilityResolver = AbilityResolver;
2209
+ exports.AbilityResult = AbilityResult;
2210
+ exports.AbilityRule = AbilityRule;
2211
+ exports.AbilityRuleSet = AbilityRuleSet;
2212
+ exports.AbilityTypeGenerator = AbilityTypeGenerator;