@magda/typescript-common 2.0.0-alpha.0 → 2.0.0-alpha.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.
Files changed (37) hide show
  1. package/dist/OpaCompileResponseParser.d.ts +115 -4
  2. package/dist/OpaCompileResponseParser.js +233 -19
  3. package/dist/OpaCompileResponseParser.js.map +1 -1
  4. package/dist/SQLUtils.js +1 -1
  5. package/dist/SQLUtils.js.map +1 -1
  6. package/dist/authorization-api/authMiddleware.d.ts +7 -6
  7. package/dist/authorization-api/authMiddleware.js +54 -45
  8. package/dist/authorization-api/authMiddleware.js.map +1 -1
  9. package/dist/authorization-api/model.d.ts +1 -1
  10. package/dist/generated/registry/api.d.ts +11 -0
  11. package/dist/generated/registry/api.js +57 -0
  12. package/dist/generated/registry/api.js.map +1 -1
  13. package/dist/getStorageUrl.d.ts +34 -0
  14. package/dist/getStorageUrl.js +138 -0
  15. package/dist/getStorageUrl.js.map +1 -0
  16. package/dist/handleServerError.d.ts +2 -0
  17. package/dist/handleServerError.js +17 -0
  18. package/dist/handleServerError.js.map +1 -0
  19. package/dist/opa/AspectQuery.js +3 -0
  20. package/dist/opa/AspectQuery.js.map +1 -1
  21. package/dist/opa/AuthDecision.js +1 -1
  22. package/dist/opa/AuthDecision.js.map +1 -1
  23. package/dist/opa/AuthDecisionQueryClient.js +8 -5
  24. package/dist/opa/AuthDecisionQueryClient.js.map +1 -1
  25. package/dist/registry/RegistryClient.d.ts +1 -0
  26. package/dist/registry/RegistryClient.js +14 -0
  27. package/dist/registry/RegistryClient.js.map +1 -1
  28. package/dist/test/getStorageUrl.spec.d.ts +1 -0
  29. package/dist/test/getStorageUrl.spec.js +95 -0
  30. package/dist/test/getStorageUrl.spec.js.map +1 -0
  31. package/dist/test/sampleAuthDecisions/datasetPermissionWithOrgUnitConstraint.json +2 -2
  32. package/dist/test/sampleAuthDecisions/extraLargeResponse.json +2519 -0
  33. package/dist/test/sampleOpaResponses/datasetPermissionWithOrgUnitConstraint.json +2 -2
  34. package/dist/test/sampleOpaResponses/extraLargeResponse.json +104869 -0
  35. package/dist/test/testOpaCompileResponseParser.spec.js +19 -2
  36. package/dist/test/testOpaCompileResponseParser.spec.js.map +1 -1
  37. package/package.json +6 -4
@@ -53,6 +53,17 @@ export declare class RegoRule {
53
53
  * @memberof RegoRule
54
54
  */
55
55
  value: RegoValue;
56
+ /**
57
+ * Whether the rule contains any expressions that has any resolvable references.
58
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
59
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
60
+ * i.e. evaluate() method should return immediately.
61
+ * This will speed up evaluation process.
62
+ *
63
+ * @type {boolean}
64
+ * @memberof RegoRule
65
+ */
66
+ hasNoResolvableRef: boolean;
56
67
  /**
57
68
  * All Rego expressions in this rule's rule body. @see RegoExp
58
69
  *
@@ -86,6 +97,24 @@ export declare class RegoRule {
86
97
  */
87
98
  private parser;
88
99
  constructor(options: RegoRuleOptions);
100
+ /**
101
+ * OPA PE result might contain duplicate expressions.
102
+ * https://github.com/open-policy-agent/opa/issues/4516
103
+ * This method will remove those duplication by simply string comparison.
104
+ *
105
+ * @return {*}
106
+ * @memberof RegoRule
107
+ */
108
+ removeDuplicateExpressions(): void;
109
+ /**
110
+ * Test whether the rule is an "impossible" rule.
111
+ * If so, the rule should be simply discarded.
112
+ * See: https://github.com/open-policy-agent/opa/issues/4516
113
+ *
114
+ * @return {*} {boolean}
115
+ * @memberof RegoRule
116
+ */
117
+ isImpossible(): boolean;
89
118
  clone(options?: Partial<RegoRuleOptions>): RegoRule;
90
119
  /**
91
120
  * Re-evaluate this rule
@@ -117,12 +146,26 @@ export declare class RegoRule {
117
146
  fullName: string;
118
147
  name: string;
119
148
  expressions: ({
149
+ negated: boolean;
150
+ terms: {
151
+ type: string;
152
+ value: RegoTermValue;
153
+ }[];
154
+ index?: undefined;
155
+ } | {
120
156
  negated: boolean;
121
157
  index: number;
122
158
  terms: {
123
159
  type: string;
124
160
  value: RegoTermValue;
125
161
  }[];
162
+ } | {
163
+ terms: {
164
+ type: string;
165
+ value: RegoTermValue;
166
+ }[];
167
+ negated?: undefined;
168
+ index?: undefined;
126
169
  } | {
127
170
  index: number;
128
171
  terms: {
@@ -193,6 +236,17 @@ export declare class RegoTerm {
193
236
  type: string;
194
237
  value: RegoTermValue;
195
238
  private parser;
239
+ /**
240
+ * Whether the expression contains any resolvable references.
241
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
242
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
243
+ * i.e. evaluate() method should return immediately.
244
+ * This will speed up evaluation process.
245
+ *
246
+ * @type {boolean}
247
+ * @memberof RegoTerm
248
+ */
249
+ hasNoResolvableRef: boolean;
196
250
  constructor(type: string, value: RegoTermValue, parser: OpaCompileResponseParser);
197
251
  clone(): RegoTerm;
198
252
  /**
@@ -201,7 +255,7 @@ export declare class RegoTerm {
201
255
  * @returns
202
256
  * @memberof RegoTerm
203
257
  */
204
- asString(): number | Object;
258
+ asString(): string;
205
259
  /**
206
260
  * If it's a reference term. A operator is an Reference term as well
207
261
  *
@@ -317,6 +371,17 @@ export declare class RegoExp {
317
371
  * @memberof RegoExp
318
372
  */
319
373
  terms: RegoTerm[];
374
+ /**
375
+ * Whether the expression contains any resolvable references.
376
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
377
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
378
+ * i.e. evaluate() method should return immediately.
379
+ * This will speed up evaluation process.
380
+ *
381
+ * @type {boolean}
382
+ * @memberof RegoExp
383
+ */
384
+ hasNoResolvableRef: boolean;
320
385
  /**
321
386
  * Whether this expression is a negative expression
322
387
  * i.e. it's final evaluation result should be `false` if result is `true`
@@ -355,7 +420,15 @@ export declare class RegoExp {
355
420
  * @returns
356
421
  * @memberof RegoExp
357
422
  */
358
- termsAsString(): (number | Object)[];
423
+ termsAsString(): string;
424
+ /**
425
+ * Print concise format expression string presentation.
426
+ * Can be used for debugging
427
+ *
428
+ * @return {*}
429
+ * @memberof RegoExp
430
+ */
431
+ asString(): string;
359
432
  /**
360
433
  * Output human readable string
361
434
  *
@@ -404,13 +477,27 @@ export declare class RegoExp {
404
477
  * @memberof RegoExp
405
478
  */
406
479
  evaluate(): this;
407
- toData(index?: number): {
480
+ toData(index?: number, ignoreIndex?: boolean, ignoreNegated?: boolean): {
481
+ negated: boolean;
482
+ terms: {
483
+ type: string;
484
+ value: RegoTermValue;
485
+ }[];
486
+ index?: undefined;
487
+ } | {
408
488
  negated: boolean;
409
489
  index: number;
410
490
  terms: {
411
491
  type: string;
412
492
  value: RegoTermValue;
413
493
  }[];
494
+ } | {
495
+ terms: {
496
+ type: string;
497
+ value: RegoTermValue;
498
+ }[];
499
+ negated?: undefined;
500
+ index?: undefined;
414
501
  } | {
415
502
  index: number;
416
503
  terms: {
@@ -419,7 +506,7 @@ export declare class RegoExp {
419
506
  }[];
420
507
  negated?: undefined;
421
508
  };
422
- toJSON(index?: number): string;
509
+ toJSON(index?: number, ignoreIndex?: boolean, ignoreNegated?: boolean): string;
423
510
  toConciseData(): {
424
511
  negated: boolean;
425
512
  operator: string;
@@ -440,6 +527,17 @@ export declare class RegoExp {
440
527
  */
441
528
  export declare class RegoRef {
442
529
  parts: RegoRefPart[];
530
+ /**
531
+ * Whether the expression contains any resolvable references.
532
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
533
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
534
+ * i.e. evaluate() method should return immediately.
535
+ * This will speed up evaluation process.
536
+ *
537
+ * @type {boolean}
538
+ * @memberof RegoRef
539
+ */
540
+ hasNoResolvableRef: boolean;
443
541
  constructor(parts: RegoRefPart[]);
444
542
  clone(): RegoRef;
445
543
  toData(): {
@@ -475,6 +573,17 @@ export declare class RegoRuleSet {
475
573
  value?: any;
476
574
  isCompleteEvaluated: boolean;
477
575
  parser: OpaCompileResponseParser;
576
+ /**
577
+ * Whether the ruleSet contains any rules that has any resolvable references.
578
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
579
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
580
+ * i.e. evaluate() method should return immediately.
581
+ * This will speed up evaluation process.
582
+ *
583
+ * @type {boolean}
584
+ * @memberof RegoRuleSet
585
+ */
586
+ hasNoResolvableRef: boolean;
478
587
  constructor(parser: OpaCompileResponseParser, rules: RegoRule[], fullName?: string, name?: string);
479
588
  evaluate(): RegoRuleSet;
480
589
  isResolvable(): boolean;
@@ -546,6 +655,7 @@ export default class OpaCompileResponseParser {
546
655
  * @memberof OpaCompileResponseParser
547
656
  */
548
657
  readonly pseudoQueryRuleName: string;
658
+ private ruleDuplicationCheckCache;
549
659
  private setQueryRuleResult;
550
660
  /**
551
661
  * Parse OPA result Response
@@ -555,6 +665,7 @@ export default class OpaCompileResponseParser {
555
665
  * @memberof OpaCompileResponseParser
556
666
  */
557
667
  parse(json: any): RegoRule[];
668
+ addRule(rule: RegoRule): void;
558
669
  isRefResolvable(fullName: string): boolean;
559
670
  getRefValue(fullName: string): any;
560
671
  private resolveAllRuleSets;
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
2
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
15
  };
@@ -19,6 +30,18 @@ const lodash_1 = __importDefault(require("lodash"));
19
30
  */
20
31
  class RegoRule {
21
32
  constructor(options) {
33
+ var _a;
34
+ /**
35
+ * Whether the rule contains any expressions that has any resolvable references.
36
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
37
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
38
+ * i.e. evaluate() method should return immediately.
39
+ * This will speed up evaluation process.
40
+ *
41
+ * @type {boolean}
42
+ * @memberof RegoRule
43
+ */
44
+ this.hasNoResolvableRef = false;
22
45
  this.isCompleteEvaluated = false;
23
46
  this.name = lodash_1.default.isString(options.name) ? options.name : "";
24
47
  this.fullName = lodash_1.default.isString(options.fullName) ? options.fullName : "";
@@ -42,8 +65,69 @@ class RegoRule {
42
65
  if (!(this.parser instanceof OpaCompileResponseParser)) {
43
66
  throw new Error("Require parser parameter to create a RegoRule");
44
67
  }
68
+ this.removeDuplicateExpressions();
69
+ if (((_a = this.expressions) === null || _a === void 0 ? void 0 : _a.length) &&
70
+ this.expressions.findIndex((exp) => !exp.hasNoResolvableRef) === -1) {
71
+ this.hasNoResolvableRef = true;
72
+ }
45
73
  this.evaluate();
46
74
  }
75
+ /**
76
+ * OPA PE result might contain duplicate expressions.
77
+ * https://github.com/open-policy-agent/opa/issues/4516
78
+ * This method will remove those duplication by simply string comparison.
79
+ *
80
+ * @return {*}
81
+ * @memberof RegoRule
82
+ */
83
+ removeDuplicateExpressions() {
84
+ var _a;
85
+ if (!((_a = this === null || this === void 0 ? void 0 : this.expressions) === null || _a === void 0 ? void 0 : _a.length)) {
86
+ return;
87
+ }
88
+ const expSet = new Set();
89
+ this.expressions = this.expressions.filter((exp) => {
90
+ const orgSetLength = expSet.size;
91
+ // exp.toJSON() is faster than exp.toConciseJSON()
92
+ expSet.add(exp.toJSON(0, true));
93
+ return expSet.size > orgSetLength;
94
+ });
95
+ }
96
+ /**
97
+ * Test whether the rule is an "impossible" rule.
98
+ * If so, the rule should be simply discarded.
99
+ * See: https://github.com/open-policy-agent/opa/issues/4516
100
+ *
101
+ * @return {*} {boolean}
102
+ * @memberof RegoRule
103
+ */
104
+ isImpossible() {
105
+ var _a;
106
+ if (!((_a = this === null || this === void 0 ? void 0 : this.expressions) === null || _a === void 0 ? void 0 : _a.length)) {
107
+ return false;
108
+ }
109
+ const nonNegatedExpSet = new Set();
110
+ const negatedExps = this.expressions.filter((exp) => {
111
+ if (exp.isNegated) {
112
+ return true;
113
+ }
114
+ else {
115
+ // add non negated exp content to set
116
+ // exp.toJSON() is faster than exp.toConciseJSON()
117
+ nonNegatedExpSet.add(exp.toJSON(0, true));
118
+ return false;
119
+ }
120
+ });
121
+ if (!negatedExps.length) {
122
+ return false;
123
+ }
124
+ for (const exp of negatedExps) {
125
+ if (nonNegatedExpSet.has(exp.toJSON(0, true, true))) {
126
+ return true;
127
+ }
128
+ }
129
+ return false;
130
+ }
47
131
  clone(options = {}) {
48
132
  const regoRule = new RegoRule(Object.assign({ name: this.name, fullName: this.fullName, isDefault: this.isDefault, value: this.value, isCompleteEvaluated: this.isCompleteEvaluated, expressions: this.expressions.map((e) => e.clone()), parser: this.parser }, options));
49
133
  regoRule.isMatched = this.isMatched;
@@ -58,6 +142,9 @@ class RegoRule {
58
142
  */
59
143
  evaluate() {
60
144
  var _a;
145
+ if (this.hasNoResolvableRef) {
146
+ return this;
147
+ }
61
148
  if (this.isCompleteEvaluated) {
62
149
  return this;
63
150
  }
@@ -223,9 +310,23 @@ exports.RegoOperators = {
223
310
  */
224
311
  class RegoTerm {
225
312
  constructor(type, value, parser) {
313
+ /**
314
+ * Whether the expression contains any resolvable references.
315
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
316
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
317
+ * i.e. evaluate() method should return immediately.
318
+ * This will speed up evaluation process.
319
+ *
320
+ * @type {boolean}
321
+ * @memberof RegoTerm
322
+ */
323
+ this.hasNoResolvableRef = false;
226
324
  this.type = type;
227
325
  this.value = value;
228
326
  this.parser = parser;
327
+ if (this.value instanceof RegoRef && this.value.hasNoResolvableRef) {
328
+ this.hasNoResolvableRef = true;
329
+ }
229
330
  }
230
331
  clone() {
231
332
  return new RegoTerm(this.type, this.value, this.parser);
@@ -240,7 +341,7 @@ class RegoTerm {
240
341
  if (this.value instanceof RegoRef)
241
342
  return this.value.fullRefString();
242
343
  else
243
- return this.value;
344
+ return JSON.stringify(this.value);
244
345
  }
245
346
  /**
246
347
  * If it's a reference term. A operator is an Reference term as well
@@ -376,6 +477,9 @@ class RegoTerm {
376
477
  * @memberof RegoTerm
377
478
  */
378
479
  getValue() {
480
+ if (this.hasNoResolvableRef) {
481
+ return undefined;
482
+ }
379
483
  if (!this.isRef()) {
380
484
  return this.value;
381
485
  }
@@ -399,6 +503,9 @@ class RegoTerm {
399
503
  * @memberof RegoTerm
400
504
  */
401
505
  isValueResolvable() {
506
+ if (this.hasNoResolvableRef) {
507
+ return false;
508
+ }
402
509
  if (!this.isRef()) {
403
510
  return true;
404
511
  }
@@ -461,6 +568,18 @@ exports.RegoTerm = RegoTerm;
461
568
  */
462
569
  class RegoExp {
463
570
  constructor(terms, isNegated = false, isCompleteEvaluated = false, value = null, parser) {
571
+ var _a;
572
+ /**
573
+ * Whether the expression contains any resolvable references.
574
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
575
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
576
+ * i.e. evaluate() method should return immediately.
577
+ * This will speed up evaluation process.
578
+ *
579
+ * @type {boolean}
580
+ * @memberof RegoExp
581
+ */
582
+ this.hasNoResolvableRef = false;
464
583
  /**
465
584
  * If it's complete evaluated
466
585
  *
@@ -480,6 +599,10 @@ class RegoExp {
480
599
  this.isCompleteEvaluated = isCompleteEvaluated;
481
600
  this.value = value;
482
601
  this.parser = parser;
602
+ if (((_a = this === null || this === void 0 ? void 0 : this.terms) === null || _a === void 0 ? void 0 : _a.length) &&
603
+ this.terms.findIndex((item) => !item.hasNoResolvableRef) === -1) {
604
+ this.hasNoResolvableRef = true;
605
+ }
483
606
  }
484
607
  clone() {
485
608
  const regoExp = new RegoExp(this.terms.map((t) => t.clone()), this.isNegated, this.isCompleteEvaluated, this.value, this.parser);
@@ -492,7 +615,22 @@ class RegoExp {
492
615
  * @memberof RegoExp
493
616
  */
494
617
  termsAsString() {
495
- return this.terms.map((t) => t.asString());
618
+ return this.terms.map((t) => t.asString()).join(" ");
619
+ }
620
+ /**
621
+ * Print concise format expression string presentation.
622
+ * Can be used for debugging
623
+ *
624
+ * @return {*}
625
+ * @memberof RegoExp
626
+ */
627
+ asString() {
628
+ if (this.isNegated) {
629
+ return "NOT " + this.termsAsString();
630
+ }
631
+ else {
632
+ return this.termsAsString();
633
+ }
496
634
  }
497
635
  /**
498
636
  * Output human readable string
@@ -631,6 +769,9 @@ class RegoExp {
631
769
  * @memberof RegoExp
632
770
  */
633
771
  evaluate() {
772
+ if (this.hasNoResolvableRef) {
773
+ return this;
774
+ }
634
775
  if (this.isCompleteEvaluated) {
635
776
  return this;
636
777
  }
@@ -696,24 +837,39 @@ class RegoExp {
696
837
  throw new Error(`Invalid ${this.terms.length} terms rego expression: ${this.termsAsString()}`);
697
838
  }
698
839
  }
699
- toData(index = 0) {
840
+ toData(index = 0, ignoreIndex = false, ignoreNegated = false) {
700
841
  const terms = this.terms.map((term) => term.toData());
701
- if (this.isNegated) {
702
- return {
703
- negated: true,
704
- index,
705
- terms
706
- };
842
+ if (this.isNegated && !ignoreNegated) {
843
+ if (ignoreIndex) {
844
+ return {
845
+ negated: true,
846
+ terms
847
+ };
848
+ }
849
+ else {
850
+ return {
851
+ negated: true,
852
+ index,
853
+ terms
854
+ };
855
+ }
707
856
  }
708
857
  else {
709
- return {
710
- index,
711
- terms
712
- };
858
+ if (ignoreIndex) {
859
+ return {
860
+ terms
861
+ };
862
+ }
863
+ else {
864
+ return {
865
+ index,
866
+ terms
867
+ };
868
+ }
713
869
  }
714
870
  }
715
- toJSON(index = 0) {
716
- return JSON.stringify(this.toData(index));
871
+ toJSON(index = 0, ignoreIndex = false, ignoreNegated = false) {
872
+ return JSON.stringify(this.toData(index, ignoreIndex, ignoreNegated));
717
873
  }
718
874
  toConciseData() {
719
875
  let data;
@@ -768,7 +924,25 @@ exports.RegoExp = RegoExp;
768
924
  */
769
925
  class RegoRef {
770
926
  constructor(parts) {
927
+ var _a;
928
+ /**
929
+ * Whether the expression contains any resolvable references.
930
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
931
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
932
+ * i.e. evaluate() method should return immediately.
933
+ * This will speed up evaluation process.
934
+ *
935
+ * @type {boolean}
936
+ * @memberof RegoRef
937
+ */
938
+ this.hasNoResolvableRef = false;
771
939
  this.parts = parts;
940
+ if (
941
+ // `input.` ref should be considered not resolvable in partial evaluate context.
942
+ (this.parts.length && ((_a = this.parts[0]) === null || _a === void 0 ? void 0 : _a.value) === "input") ||
943
+ this.isOperator()) {
944
+ this.hasNoResolvableRef = true;
945
+ }
772
946
  }
773
947
  clone() {
774
948
  return new RegoRef(this.parts.map((p) => (Object.assign({}, p))));
@@ -893,6 +1067,17 @@ class RegoRuleSet {
893
1067
  this.rules = [];
894
1068
  this.defaultRule = null;
895
1069
  this.isCompleteEvaluated = false;
1070
+ /**
1071
+ * Whether the ruleSet contains any rules that has any resolvable references.
1072
+ * reference start with `input.` should be considered as non-resolvable in context of partial evaluation.
1073
+ * When this field is set to `true`, we should not attempt to evaluate this expression.
1074
+ * i.e. evaluate() method should return immediately.
1075
+ * This will speed up evaluation process.
1076
+ *
1077
+ * @type {boolean}
1078
+ * @memberof RegoRuleSet
1079
+ */
1080
+ this.hasNoResolvableRef = false;
896
1081
  this.parser = parser;
897
1082
  if (rules === null || rules === void 0 ? void 0 : rules.length) {
898
1083
  const defaultRuleIdx = rules.findIndex((r) => r.isDefault);
@@ -913,10 +1098,17 @@ class RegoRuleSet {
913
1098
  else if ((_b = rules === null || rules === void 0 ? void 0 : rules[0]) === null || _b === void 0 ? void 0 : _b.name) {
914
1099
  this.name = rules[0].name;
915
1100
  }
1101
+ if (this.rules.length &&
1102
+ this.rules.findIndex((r) => !r.hasNoResolvableRef) === -1) {
1103
+ this.hasNoResolvableRef = true;
1104
+ }
916
1105
  this.evaluate();
917
1106
  }
918
1107
  evaluate() {
919
1108
  var _a;
1109
+ if (this.hasNoResolvableRef) {
1110
+ return this;
1111
+ }
920
1112
  if (this.isCompleteEvaluated) {
921
1113
  return this;
922
1114
  }
@@ -1113,6 +1305,7 @@ class OpaCompileResponseParser {
1113
1305
  * @memberof OpaCompileResponseParser
1114
1306
  */
1115
1307
  this.pseudoQueryRuleName = RegoRule.randomRuleName("default_rule_");
1308
+ this.ruleDuplicationCheckCache = {};
1116
1309
  }
1117
1310
  setQueryRuleResult(val) {
1118
1311
  this.completeRuleResults[this.pseudoQueryRuleName] = {
@@ -1173,8 +1366,9 @@ class OpaCompileResponseParser {
1173
1366
  value: true,
1174
1367
  parser: this
1175
1368
  });
1176
- this.originalRules.push(rule);
1177
- this.rules.push(rule);
1369
+ // this.originalRules.push(rule);
1370
+ // this.rules.push(rule);
1371
+ this.addRule(rule);
1178
1372
  });
1179
1373
  }
1180
1374
  const packages = this.data.support;
@@ -1188,15 +1382,35 @@ class OpaCompileResponseParser {
1188
1382
  const rules = p.rules;
1189
1383
  rules.forEach((r) => {
1190
1384
  const regoRule = RegoRule.parseFromData(r, packageName, this);
1191
- this.originalRules.push(regoRule);
1192
- this.rules.push(regoRule);
1385
+ //this.originalRules.push(regoRule);
1386
+ //this.rules.push(regoRule);
1387
+ this.addRule(regoRule);
1193
1388
  });
1194
1389
  });
1195
1390
  }
1391
+ this.ruleDuplicationCheckCache = {};
1196
1392
  lodash_1.default.uniq(this.rules.map((r) => r.fullName)).forEach((fullName) => (this.ruleSets[fullName] = new RegoRuleSet(this, this.rules.filter((r) => r.fullName === fullName), fullName)));
1197
1393
  this.resolveAllRuleSets();
1198
1394
  return this.rules;
1199
1395
  }
1396
+ addRule(rule) {
1397
+ this.originalRules.push(rule);
1398
+ if (rule.isImpossible()) {
1399
+ return;
1400
+ }
1401
+ if (!this.ruleDuplicationCheckCache[rule.fullName]) {
1402
+ this.ruleDuplicationCheckCache[rule.fullName] = new Set();
1403
+ }
1404
+ const setData = this.ruleDuplicationCheckCache[rule.fullName];
1405
+ const _a = rule.toData(), { name, fullName } = _a, ruleData = __rest(_a, ["name", "fullName"]);
1406
+ const jsonData = JSON.stringify(ruleData);
1407
+ const size = setData.size;
1408
+ setData.add(jsonData);
1409
+ if (size === setData.size) {
1410
+ return;
1411
+ }
1412
+ this.rules.push(rule);
1413
+ }
1200
1414
  isRefResolvable(fullName) {
1201
1415
  if (this.completeRuleResults[fullName]) {
1202
1416
  return true;