@via-profit/ability 3.6.5 → 3.7.1

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.cjs CHANGED
@@ -32,6 +32,8 @@ function brand$3(code) {
32
32
  }
33
33
  const AbilityCondition = {
34
34
  equals: brand$3('='),
35
+ defined: brand$3('defined'),
36
+ not_defined: brand$3('not_defined'),
35
37
  not_equals: brand$3('<>'),
36
38
  greater_than: brand$3('>'),
37
39
  less_than: brand$3('<'),
@@ -64,6 +66,8 @@ function fromLiteral(literal) {
64
66
  length_equals: AbilityCondition.length_equals,
65
67
  always: AbilityCondition.always,
66
68
  never: AbilityCondition.never,
69
+ defined: AbilityCondition.defined,
70
+ not_defined: AbilityCondition.not_defined,
67
71
  };
68
72
  const value = map[literal];
69
73
  if (!value) {
@@ -104,6 +108,10 @@ function toLiteral(cond) {
104
108
  return 'always';
105
109
  case AbilityCondition.never:
106
110
  return 'never';
111
+ case AbilityCondition.defined:
112
+ return 'defined';
113
+ case AbilityCondition.not_defined:
114
+ return 'not_defined';
107
115
  default:
108
116
  return 'never';
109
117
  }
@@ -126,15 +134,6 @@ const AbilityMatch = {
126
134
  disabled: brand$2('disabled'),
127
135
  };
128
136
 
129
- const colors = {
130
- reset: '\x1b[0m',
131
- green: '\x1b[32m',
132
- red: '\x1b[31m',
133
- blue: '\x1b[34m',
134
- yellow: '\x1b[33m',
135
- white: '\x1b[37m',
136
- gray: '\x1b[90m',
137
- };
138
137
  class AbilityExplain {
139
138
  type;
140
139
  children;
@@ -150,27 +149,36 @@ class AbilityExplain {
150
149
  }
151
150
  toString(indentPrefix = '', isLast = true) {
152
151
  const isMatch = this.match === AbilityMatch.match;
153
- const mark = isMatch ? `${colors.green}✓${colors.reset}` : `${colors.red}✗${colors.reset}`;
152
+ const isMismatch = this.match === AbilityMatch.mismatch;
153
+ const isPending = this.match === AbilityMatch.pending;
154
+ // const isDisabled = this.match === AbilityMatch.disabled;
155
+ const mark = isMatch
156
+ ? `<match ✓>`
157
+ : isMismatch
158
+ ? `<mismatch ✗>`
159
+ : isPending
160
+ ? `<pending …>`
161
+ : `<disabled ⊘>`;
154
162
  let label;
155
163
  switch (this.type) {
156
164
  case 'policy':
157
- label = `${colors.blue}POLICY${colors.reset}`;
165
+ label = `POLICY`;
158
166
  break;
159
167
  case 'ruleSet':
160
- label = `${colors.yellow}RULESET${colors.reset}`;
168
+ label = `RULESET`;
161
169
  break;
162
170
  default:
163
- label = `${colors.white}RULE${colors.reset}`;
171
+ label = `RULE`;
164
172
  }
165
173
  const branch = indentPrefix.length === 0
166
174
  ? ''
167
175
  : isLast
168
- ? `${colors.gray}└─${colors.reset} `
169
- : `${colors.gray}├─${colors.reset} `;
176
+ ? `└─ `
177
+ : `├─ `;
170
178
  let out = `${indentPrefix}${branch}${label} ${this.name} — ${mark}`;
171
179
  if (this.debugInfo)
172
- out += ` ${colors.gray}(${this.debugInfo})${colors.reset}`;
173
- const nextIndent = indentPrefix + (isLast ? ' ' : `${colors.gray}│ ${colors.reset}`);
180
+ out += ` (${this.debugInfo})`;
181
+ const nextIndent = indentPrefix + (isLast ? ' ' : `│ `);
174
182
  this.children.forEach((child, idx) => {
175
183
  out += '\n' + child.toString(nextIndent, idx === this.children.length - 1);
176
184
  });
@@ -183,6 +191,7 @@ class AbilityExplainRule extends AbilityExplain {
183
191
  type: 'rule',
184
192
  match: rule.state,
185
193
  name: rule.name,
194
+ debugInfo: `${rule.subject} ${rule.condition} ${JSON.stringify(rule.resource)}`,
186
195
  });
187
196
  }
188
197
  }
@@ -221,11 +230,13 @@ class AbilityResult {
221
230
  * Useful for debugging, logging, or building UI tools that visualize permission logic.
222
231
  */
223
232
  explain() {
224
- return this.strategy.policies
233
+ const resMarker = this.strategy.isDenied() ? '== DENIED==' : '== ALLOWED ==';
234
+ const policiesExplain = this.strategy.policies
225
235
  .map(policy => {
226
236
  return new AbilityExplainPolicy(policy).toString();
227
237
  })
228
238
  .join('\n');
239
+ return `${resMarker}\n${policiesExplain}\n`;
229
240
  }
230
241
  decisive() {
231
242
  return this.strategy.decisivePolicy();
@@ -245,7 +256,17 @@ class AbilityResult {
245
256
  };
246
257
  }
247
258
 
259
+ function brand$1(code) {
260
+ return code;
261
+ }
262
+ const AbilityPolicyEffect = {
263
+ deny: brand$1('deny'),
264
+ permit: brand$1('permit'),
265
+ };
266
+
248
267
  class AbilityResolver {
268
+ onDeny;
269
+ onAllow;
249
270
  StrategyClass;
250
271
  policyEntries;
251
272
  constructor(
@@ -254,6 +275,8 @@ class AbilityResolver {
254
275
  */
255
276
  policyOrListOfPolicies, strategy, options = {}) {
256
277
  const policies = this.toArray(policyOrListOfPolicies);
278
+ this.onDeny = options.onDeny;
279
+ this.onAllow = options.onAllow;
257
280
  const filtered = options.tags
258
281
  ? policies.filter(p => p.tags.some(tag => options.tags.includes(tag)))
259
282
  : policies;
@@ -291,11 +314,19 @@ class AbilityResolver {
291
314
  // 3. Use strategy
292
315
  const strategy = new this.StrategyClass(filteredPolicies);
293
316
  const effect = strategy.evaluate();
294
- return new AbilityResult(effect, strategy);
317
+ const result = new AbilityResult(effect, strategy);
318
+ if (effect === AbilityPolicyEffect.deny && this.onDeny) {
319
+ this.onDeny(result);
320
+ }
321
+ if (effect === AbilityPolicyEffect.permit && this.onAllow) {
322
+ this.onAllow(result);
323
+ }
324
+ return result;
295
325
  }
296
- enforce(permission, resource, environment) {
326
+ enforce(permission, resource, environment, options) {
297
327
  const result = this.resolve(permission, resource, environment);
298
328
  if (result.isDenied()) {
329
+ options?.onDeny && options?.onDeny(result);
299
330
  throw new AbilityError(`Permission denied`);
300
331
  }
301
332
  }
@@ -416,7 +447,7 @@ class AbilityTypeGenerator {
416
447
  environmentStructure[action] = {};
417
448
  }
418
449
  const existingEnvType = environmentStructure[action][envPath];
419
- const targetType = ruleType; // или 'unknown', если хочешь жёстко
450
+ const targetType = ruleType;
420
451
  if (existingEnvType && existingEnvType !== targetType) {
421
452
  environmentStructure[action][envPath] = `${existingEnvType} | ${targetType}`;
422
453
  }
@@ -1004,14 +1035,6 @@ class AbilityPolicy {
1004
1035
  }
1005
1036
  }
1006
1037
 
1007
- function brand$1(code) {
1008
- return code;
1009
- }
1010
- const AbilityPolicyEffect = {
1011
- deny: brand$1('deny'),
1012
- permit: brand$1('permit'),
1013
- };
1014
-
1015
1038
  /**
1016
1039
  * Represents a rule that defines a condition to be checked against a subject and resource.
1017
1040
  */
@@ -1063,6 +1086,8 @@ class AbilityRule {
1063
1086
  static valueLen = (v) => this.isString(v) || Array.isArray(v) ? v.length : null;
1064
1087
  static operatorHandlers = {
1065
1088
  [toLiteral(AbilityCondition.always)]: () => true,
1089
+ [toLiteral(AbilityCondition.defined)]: (a) => typeof a !== 'undefined',
1090
+ [toLiteral(AbilityCondition.not_defined)]: (a) => typeof a === 'undefined',
1066
1091
  [toLiteral(AbilityCondition.never)]: () => false,
1067
1092
  [toLiteral(AbilityCondition.equals)]: (a, b) => a === b,
1068
1093
  [toLiteral(AbilityCondition.not_equals)]: (a, b) => a !== b,
@@ -1602,6 +1627,7 @@ const TokenTypes = {
1602
1627
  NULL: brand('NULL'),
1603
1628
  EQ_NULL: brand('EQ_NULL'),
1604
1629
  NOT_EQ_NULL: brand('NOT_EQ_NULL'),
1630
+ DEFINED: brand('DEFINED'),
1605
1631
  NOT_EQ: brand('NOT_EQ'),
1606
1632
  LEN_GT: brand('LEN_GT'),
1607
1633
  LEN_LT: brand('LEN_LT'),
@@ -1652,9 +1678,11 @@ class AbilityDSLLexer {
1652
1678
  'true',
1653
1679
  'false',
1654
1680
  'null',
1681
+ 'defined',
1655
1682
  'contains',
1656
1683
  'includes',
1657
1684
  'length',
1685
+ 'len',
1658
1686
  'has',
1659
1687
  'in',
1660
1688
  'gt',
@@ -1868,11 +1896,11 @@ class AbilityDSLLexer {
1868
1896
  const startLine = this.line;
1869
1897
  const startColumn = this.column;
1870
1898
  const start = this.pos;
1871
- // Первый сегмент
1899
+ // First segment
1872
1900
  while (!this.isAtEnd() && /[a-zA-Z0-9_*]/.test(this.peek())) {
1873
1901
  this.advance();
1874
1902
  }
1875
- // Сегменты через точку
1903
+ // dots segments
1876
1904
  while (!this.isAtEnd() && this.peek() === '.') {
1877
1905
  this.advance(); // dot
1878
1906
  if (!/[a-zA-Z_*]/.test(this.peek())) {
@@ -1889,7 +1917,7 @@ class AbilityDSLLexer {
1889
1917
  if (word === 'never') {
1890
1918
  return new AbilityDSLToken(TokenTypes.NEVER, word, startLine, startColumn);
1891
1919
  }
1892
- // Если есть точка — это путь (identifier или permission)
1920
+ // (identifier or permission)
1893
1921
  if (word.includes('.')) {
1894
1922
  const last = this.tokens[this.tokens.length - 1];
1895
1923
  if (last?.type === TokenTypes.EFFECT) {
@@ -1899,16 +1927,13 @@ class AbilityDSLLexer {
1899
1927
  }
1900
1928
  return new AbilityDSLToken(TokenTypes.IDENTIFIER, word, startLine, startColumn);
1901
1929
  }
1902
- // Ключевые слова
1903
1930
  if (this.keywords.has(word)) {
1904
- // Эффекты
1905
1931
  if (word === 'permit' || word === 'allow') {
1906
1932
  return new AbilityDSLToken(TokenTypes.EFFECT, 'permit', startLine, startColumn);
1907
1933
  }
1908
1934
  if (word === 'deny' || word === 'forbidden') {
1909
1935
  return new AbilityDSLToken(TokenTypes.EFFECT, 'deny', startLine, startColumn);
1910
1936
  }
1911
- // Групповые ключевые слова
1912
1937
  if (word === 'all') {
1913
1938
  return new AbilityDSLToken(TokenTypes.ALL, word, startLine, startColumn);
1914
1939
  }
@@ -1921,13 +1946,15 @@ class AbilityDSLLexer {
1921
1946
  if (word === 'if') {
1922
1947
  return new AbilityDSLToken(TokenTypes.IF, word, startLine, startColumn);
1923
1948
  }
1924
- // Булевы и null
1925
1949
  if (word === 'true' || word === 'false') {
1926
1950
  return new AbilityDSLToken(TokenTypes.BOOLEAN, word, startLine, startColumn);
1927
1951
  }
1928
1952
  if (word === 'null') {
1929
1953
  return new AbilityDSLToken(TokenTypes.NULL, word, startLine, startColumn);
1930
1954
  }
1955
+ if (word === 'defined') {
1956
+ return new AbilityDSLToken(TokenTypes.DEFINED, word, startLine, startColumn);
1957
+ }
1931
1958
  if (word === 'except') {
1932
1959
  return new AbilityDSLToken(TokenTypes.EXCEPT, word, startLine, startColumn);
1933
1960
  }
@@ -2079,7 +2106,8 @@ class AbilityDSLTokenStream {
2079
2106
  if (this.eof()) {
2080
2107
  return false;
2081
2108
  }
2082
- return this.peek().type === type;
2109
+ const p = this.peek().type;
2110
+ return p === type;
2083
2111
  }
2084
2112
  match(type) {
2085
2113
  if (this.check(type)) {
@@ -2515,6 +2543,7 @@ class AbilityDSLParser {
2515
2543
  const operatorConsumesValue = operator !== TokenTypes.EQ_NULL &&
2516
2544
  operator !== TokenTypes.NOT_EQ_NULL &&
2517
2545
  operator !== TokenTypes.NULL &&
2546
+ operator !== TokenTypes.DEFINED &&
2518
2547
  operator !== TokenTypes.ALWAYS &&
2519
2548
  operator !== TokenTypes.NEVER;
2520
2549
  if (operatorConsumesValue) {
@@ -2567,42 +2596,46 @@ class AbilityDSLParser {
2567
2596
  this.stream.reset();
2568
2597
  // "length equals"
2569
2598
  this.stream.mark();
2570
- if (this.matchWord('length') && this.matchWord('equals')) {
2599
+ if ((this.matchWord('length') || this.matchWord('len')) && this.matchWord('equals')) {
2571
2600
  this.stream.commit();
2572
2601
  return { condition: AbilityCondition.length_equals, operator: TokenTypes.LEN_EQ };
2573
2602
  }
2574
2603
  this.stream.reset();
2575
2604
  // "length ="
2576
2605
  this.stream.mark();
2577
- if (this.matchWord('length') && this.matchSymbol('=')) {
2606
+ if ((this.matchWord('length') || this.matchWord('len')) && this.matchSymbol('=')) {
2578
2607
  this.stream.commit();
2579
2608
  return { condition: AbilityCondition.length_equals, operator: TokenTypes.LEN_EQ };
2580
2609
  }
2581
2610
  this.stream.reset();
2582
2611
  // "length greater than"
2583
2612
  this.stream.mark();
2584
- if (this.matchWord('length') && this.matchWord('greater') && this.matchWord('than')) {
2613
+ if ((this.matchWord('length') || this.matchWord('len')) &&
2614
+ this.matchWord('greater') &&
2615
+ this.matchWord('than')) {
2585
2616
  this.stream.commit();
2586
2617
  return { condition: AbilityCondition.length_greater_than, operator: TokenTypes.LEN_GT };
2587
2618
  }
2588
2619
  this.stream.reset();
2589
2620
  // "length >"
2590
2621
  this.stream.mark();
2591
- if (this.matchWord('length') && this.matchSymbol('>')) {
2622
+ if ((this.matchWord('length') || this.matchWord('len')) && this.matchSymbol('>')) {
2592
2623
  this.stream.commit();
2593
2624
  return { condition: AbilityCondition.length_greater_than, operator: TokenTypes.LEN_GT };
2594
2625
  }
2595
2626
  this.stream.reset();
2596
2627
  // "length less than"
2597
2628
  this.stream.mark();
2598
- if (this.matchWord('length') && this.matchWord('less') && this.matchWord('than')) {
2629
+ if ((this.matchWord('length') || this.matchWord('len')) &&
2630
+ this.matchWord('less') &&
2631
+ this.matchWord('than')) {
2599
2632
  this.stream.commit();
2600
2633
  return { condition: AbilityCondition.length_less_than, operator: TokenTypes.LEN_LT };
2601
2634
  }
2602
2635
  this.stream.reset();
2603
2636
  // "length <"
2604
2637
  this.stream.mark();
2605
- if (this.matchWord('length') && this.matchSymbol('<')) {
2638
+ if ((this.matchWord('length') || this.matchWord('len')) && this.matchSymbol('<')) {
2606
2639
  this.stream.commit();
2607
2640
  return { condition: AbilityCondition.length_less_than, operator: TokenTypes.LEN_LT };
2608
2641
  }
@@ -2730,6 +2763,20 @@ class AbilityDSLParser {
2730
2763
  }
2731
2764
  }
2732
2765
  this.stream.reset();
2766
+ // is defined
2767
+ this.stream.mark();
2768
+ if (this.matchWord('is') && this.matchWord('defined')) {
2769
+ this.stream.commit();
2770
+ return { condition: AbilityCondition.defined, operator: TokenTypes.DEFINED };
2771
+ }
2772
+ this.stream.reset();
2773
+ // is not defined
2774
+ this.stream.mark();
2775
+ if (this.matchWord('is') && this.matchWord('not') && this.matchWord('defined')) {
2776
+ this.stream.commit();
2777
+ return { condition: AbilityCondition.not_defined, operator: TokenTypes.DEFINED };
2778
+ }
2779
+ this.stream.reset();
2733
2780
  // Single token (symbol or keyword)
2734
2781
  const token = this.stream.peek();
2735
2782
  if (token.type !== TokenTypes.SYMBOL &&
@@ -2801,7 +2848,8 @@ class AbilityDSLParser {
2801
2848
  if ((token.type === TokenTypes.KEYWORD ||
2802
2849
  token.type === TokenTypes.IDENTIFIER ||
2803
2850
  token.type === TokenTypes.ALWAYS ||
2804
- token.type === TokenTypes.NEVER) &&
2851
+ token.type === TokenTypes.NEVER ||
2852
+ token.type === TokenTypes.DEFINED) &&
2805
2853
  token.value === word) {
2806
2854
  this.stream.next();
2807
2855
  return true;
@@ -2839,6 +2887,11 @@ class AbilityDSLParser {
2839
2887
  this.stream.syntaxError(`Unexpected ${token.type} in value position`, token);
2840
2888
  }
2841
2889
  this.stream.next();
2890
+ // if (token.type === TokenTypes.IDENTIFIER) {
2891
+ // this.stream.next();
2892
+ //
2893
+ // return this.parseValue();
2894
+ // }
2842
2895
  // CHECK THIS SWITCH COMPARE
2843
2896
  switch (token.type) {
2844
2897
  case TokenTypes.STRING:
@@ -2849,8 +2902,10 @@ class AbilityDSLParser {
2849
2902
  return token.value === 'true';
2850
2903
  case TokenTypes.NULL:
2851
2904
  return null;
2905
+ case TokenTypes.DEFINED:
2906
+ return typeof token.value !== 'undefined';
2852
2907
  case TokenTypes.IDENTIFIER:
2853
- return token.value;
2908
+ return null;
2854
2909
  default: {
2855
2910
  this.stream.syntaxError(`Unexpected value token "${token.value}"`, token, [
2856
2911
  TokenTypes.KEYWORD,
package/dist/index.d.ts CHANGED
@@ -7,13 +7,15 @@ declare const AbilityCompare: {
7
7
  readonly and: AbilityCompareType;
8
8
  };
9
9
 
10
- type AbilityConditionCode = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in' | 'contains' | 'not contains' | 'length greater than' | 'length less than' | 'length equals' | 'always' | 'never';
11
- type AbilityConditionLiteral = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'in' | 'not_in' | 'greater_than' | 'less_than' | 'less_or_equal' | 'greater_or_equal' | 'length_greater_than' | 'length_less_than' | 'length_equals' | 'always' | 'never';
10
+ type AbilityConditionCode = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in' | 'contains' | 'not contains' | 'length greater than' | 'length less than' | 'length equals' | 'always' | 'never' | 'defined' | 'not_defined';
11
+ type AbilityConditionLiteral = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'in' | 'not_in' | 'greater_than' | 'less_than' | 'less_or_equal' | 'greater_or_equal' | 'length_greater_than' | 'length_less_than' | 'length_equals' | 'always' | 'never' | 'defined' | 'not_defined';
12
12
  type AbilityConditionType = AbilityConditionCode & {
13
13
  __brand: 'AbilityCondition';
14
14
  };
15
15
  declare const AbilityCondition: {
16
16
  readonly equals: AbilityConditionType;
17
+ readonly defined: AbilityConditionType;
18
+ readonly not_defined: AbilityConditionType;
17
19
  readonly not_equals: AbilityConditionType;
18
20
  readonly greater_than: AbilityConditionType;
19
21
  readonly less_than: AbilityConditionType;
@@ -438,7 +440,7 @@ declare abstract class AbilityStrategy<Resource extends ResourceObject = Record<
438
440
 
439
441
  declare class AbilityResult<R extends ResourceObject = Record<string, unknown>, E extends EnvironmentObject = Record<string, unknown>> {
440
442
  protected readonly effect: AbilityPolicyEffectType;
441
- protected readonly strategy: AbilityStrategy<R, E>;
443
+ readonly strategy: AbilityStrategy<R, E>;
442
444
  constructor(effect: AbilityPolicyEffectType, strategy: AbilityStrategy<R, E>);
443
445
  /**
444
446
  * Returns a list of explanations for each policy involved in the ability evaluation.
@@ -455,13 +457,23 @@ declare class AbilityResult<R extends ResourceObject = Record<string, unknown>,
455
457
 
456
458
  interface AbilityResolverOptions<TTags extends string> {
457
459
  tags?: readonly TTags[];
460
+ readonly onDeny?: EnforceOnDeny;
461
+ readonly onAllow?: EnforceOnAllow;
458
462
  }
459
463
  type ExtractResources<P> = P extends AbilityPolicy<infer R, any, any> ? R : never;
460
464
  type ExtractEnvironment<P> = P extends AbilityPolicy<any, infer E, any> ? E : never;
461
465
  type ExtractPermission<R> = R extends AbilityResolver<infer P, any, any> ? keyof ExtractResources<P> & string : never;
462
466
  type ExtractResourceByPermission<P, Perm extends string> = P extends AbilityPolicy<infer R, any, any> ? (Perm extends keyof R ? R[Perm] : never) : never;
463
467
  type ExtractEnvironmentByPermission<P, Perm extends string> = P extends AbilityPolicy<any, infer E, any> ? (Perm extends keyof E ? E[Perm] : never) : never;
468
+ type EnforceOptions<R extends ResourceObject = Record<string, unknown>, E extends EnvironmentObject = Record<string, unknown>> = {
469
+ readonly onDeny?: EnforceOnDeny<R, E>;
470
+ readonly onAllow?: EnforceOnDeny<R, E>;
471
+ };
472
+ type EnforceOnDeny<R extends ResourceObject = Record<string, unknown>, E extends EnvironmentObject = Record<string, unknown>> = (result: AbilityResult<R, E>) => void;
473
+ type EnforceOnAllow<R extends ResourceObject = Record<string, unknown>, E extends EnvironmentObject = Record<string, unknown>> = (result: AbilityResult<R, E>) => void;
464
474
  declare class AbilityResolver<P extends AbilityPolicy<any, any, any>, S extends AbilityStrategy<P extends AbilityPolicy<infer R, infer E, any> ? R : never, P extends AbilityPolicy<any, infer E, any> ? E : never>, TTags extends string = P extends AbilityPolicy<any, any, infer T> ? T : never> {
475
+ private readonly onDeny?;
476
+ private readonly onAllow?;
465
477
  private readonly StrategyClass;
466
478
  private readonly policyEntries;
467
479
  constructor(
@@ -477,7 +489,7 @@ declare class AbilityResolver<P extends AbilityPolicy<any, any, any>, S extends
477
489
  * @param environment
478
490
  */
479
491
  resolve<Permission extends keyof ExtractResources<P> & string>(permission: Permission, resource: ExtractResourceByPermission<P, Permission>, environment?: ExtractEnvironmentByPermission<P, Permission>): AbilityResult<ExtractResourceByPermission<P, Permission>, ExtractEnvironment<P>>;
480
- enforce<Permission extends keyof ExtractResources<P> & string>(permission: Permission, resource: ExtractResourceByPermission<P, Permission>, environment?: ExtractEnvironmentByPermission<P, Permission>): void | never;
492
+ enforce<Permission extends keyof ExtractResources<P> & string>(permission: Permission, resource: ExtractResourceByPermission<P, Permission>, environment?: ExtractEnvironmentByPermission<P, Permission>, options?: EnforceOptions): void | never;
481
493
  /**
482
494
  * @deprecated - will be removed
483
495
  *
@@ -590,7 +602,7 @@ declare class AbilityDSLParser<R extends ResourceObject = Record<string, unknown
590
602
  private isStartOfAlias;
591
603
  }
592
604
 
593
- type TokenTypeCode = 'EFFECT' | 'IF' | 'PERMISSION' | 'IDENTIFIER' | 'COLON' | 'COMMA' | 'DOT' | 'LBRACKET' | 'RBRACKET' | 'ALL' | 'ANY' | 'OF' | 'EOF' | 'COMMENT' | 'EQ' | 'CONTAINS' | 'IN' | 'NOT_IN' | 'NOT_CONTAINS' | 'GT' | 'GTE' | 'LT' | 'LTE' | 'NULL' | 'EQ_NULL' | 'NOT_EQ_NULL' | 'NOT_EQ' | 'LEN_GT' | 'LEN_LT' | 'LEN_EQ' | 'ALWAYS' | 'NEVER' | 'EXCEPT' | 'ANNOTATION' | 'STRING' | 'NUMBER' | 'BOOLEAN' | 'SYMBOL' | 'KEYWORD' | 'ALIAS' | 'UNKNOWN';
605
+ type TokenTypeCode = 'EFFECT' | 'IF' | 'PERMISSION' | 'IDENTIFIER' | 'COLON' | 'COMMA' | 'DOT' | 'LBRACKET' | 'RBRACKET' | 'ALL' | 'ANY' | 'OF' | 'EOF' | 'COMMENT' | 'EQ' | 'CONTAINS' | 'IN' | 'NOT_IN' | 'NOT_CONTAINS' | 'GT' | 'GTE' | 'LT' | 'LTE' | 'NULL' | 'EQ_NULL' | 'NOT_EQ_NULL' | 'DEFINED' | 'NOT_EQ' | 'LEN_GT' | 'LEN_LT' | 'LEN_EQ' | 'ALWAYS' | 'NEVER' | 'EXCEPT' | 'ANNOTATION' | 'STRING' | 'NUMBER' | 'BOOLEAN' | 'SYMBOL' | 'KEYWORD' | 'ALIAS' | 'UNKNOWN';
594
606
  type TokenType = TokenTypeCode & {
595
607
  __brand: 'TokenType';
596
608
  };
@@ -621,6 +633,7 @@ declare const TokenTypes: {
621
633
  readonly NULL: TokenType;
622
634
  readonly EQ_NULL: TokenType;
623
635
  readonly NOT_EQ_NULL: TokenType;
636
+ readonly DEFINED: TokenType;
624
637
  readonly NOT_EQ: TokenType;
625
638
  readonly LEN_GT: TokenType;
626
639
  readonly LEN_LT: TokenType;
@@ -858,4 +871,4 @@ declare class PriorityStrategy<R extends ResourceObject, E extends EnvironmentOb
858
871
  }
859
872
 
860
873
  export { AbilityCompare, AbilityCondition, AbilityDSLLexer, AbilityDSLParser, AbilityDSLToken, AbilityError, AbilityExplain, AbilityExplainPolicy, AbilityExplainRule, AbilityExplainRuleSet, AbilityJSONParser, AbilityMatch, AbilityParserError, AbilityPolicy, AbilityPolicyEffect, AbilityResolver, AbilityResult, AbilityRule, AbilityRuleSet, AbilityStrategy, AbilityTypeGenerator, AllMustPermitStrategy, AnyPermitStrategy, DenyOverridesStrategy, FirstMatchStrategy, OnlyOneApplicableStrategy, PermitOverridesStrategy, PriorityStrategy, SequentialLastMatchStrategy, TokenTypes, ability, fromLiteral, isConditionEqual, isConditionNotEqual, toLiteral };
861
- export type { AbilityCompareType, AbilityConditionCode, AbilityConditionLiteral, AbilityConditionType, AbilityExplainConfig, AbilityExplainType, AbilityMatchType, AbilityPolicyConfig, AbilityPolicyConstructorProps, AbilityPolicyEffectType, AbilityResolverOptions, AbilityRuleConfig, AbilityRuleConstructorProps, AbilityRuleSetConfig, AbilityRuleSetConstructorProps, EnvironmentObject, ExtractEnvironment, ExtractEnvironmentByPermission, ExtractPermission, ExtractResourceByPermission, ExtractResources, NestedDict, Primitive, ResourceObject, ResourcesMap, TokenType, TokenTypeCode };
874
+ export type { AbilityCompareType, AbilityConditionCode, AbilityConditionLiteral, AbilityConditionType, AbilityExplainConfig, AbilityExplainType, AbilityMatchType, AbilityPolicyConfig, AbilityPolicyConstructorProps, AbilityPolicyEffectType, AbilityResolverOptions, AbilityRuleConfig, AbilityRuleConstructorProps, AbilityRuleSetConfig, AbilityRuleSetConstructorProps, EnforceOnAllow, EnforceOnDeny, EnforceOptions, EnvironmentObject, ExtractEnvironment, ExtractEnvironmentByPermission, ExtractPermission, ExtractResourceByPermission, ExtractResources, NestedDict, Primitive, ResourceObject, ResourcesMap, TokenType, TokenTypeCode };