@swaggerexpert/arazzo-criterion 1.0.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.
Files changed (37) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +406 -0
  4. package/SECURITY.md +15 -0
  5. package/cjs/apg-lite.cjs +1223 -0
  6. package/cjs/errors/ArazzoCriterionError.cjs +46 -0
  7. package/cjs/errors/ArazzoCriterionEvaluateError.cjs +10 -0
  8. package/cjs/errors/ArazzoCriterionParseError.cjs +10 -0
  9. package/cjs/evaluate/index.cjs +139 -0
  10. package/cjs/grammar.cjs +1111 -0
  11. package/cjs/index.cjs +83 -0
  12. package/cjs/parse/callbacks/cst.cjs +30 -0
  13. package/cjs/parse/index.cjs +42 -0
  14. package/cjs/parse/trace/Expectations.cjs +12 -0
  15. package/cjs/parse/trace/Trace.cjs +37 -0
  16. package/cjs/parse/translators/ASTTranslator/index.cjs +17 -0
  17. package/cjs/parse/translators/ASTTranslator/transformers.cjs +203 -0
  18. package/cjs/parse/translators/CSTTranslator.cjs +49 -0
  19. package/cjs/parse/translators/XMLTranslator.cjs +14 -0
  20. package/cjs/test/index.cjs +20 -0
  21. package/es/errors/ArazzoCriterionError.mjs +40 -0
  22. package/es/errors/ArazzoCriterionEvaluateError.mjs +3 -0
  23. package/es/errors/ArazzoCriterionParseError.mjs +3 -0
  24. package/es/evaluate/index.mjs +132 -0
  25. package/es/grammar.mjs +1105 -0
  26. package/es/index.mjs +11 -0
  27. package/es/parse/callbacks/cst.mjs +24 -0
  28. package/es/parse/index.mjs +35 -0
  29. package/es/parse/trace/Expectations.mjs +6 -0
  30. package/es/parse/trace/Trace.mjs +30 -0
  31. package/es/parse/translators/ASTTranslator/index.mjs +9 -0
  32. package/es/parse/translators/ASTTranslator/transformers.mjs +195 -0
  33. package/es/parse/translators/CSTTranslator.mjs +42 -0
  34. package/es/parse/translators/XMLTranslator.mjs +7 -0
  35. package/es/test/index.mjs +13 -0
  36. package/package.json +95 -0
  37. package/types/index.d.ts +283 -0
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ class ArazzoCriterionError extends Error {
8
+ constructor(message, options = undefined) {
9
+ super(message, options);
10
+ this.name = this.constructor.name;
11
+ if (typeof message === 'string') {
12
+ this.message = message;
13
+ }
14
+ if (typeof Error.captureStackTrace === 'function') {
15
+ Error.captureStackTrace(this, this.constructor);
16
+ } else {
17
+ this.stack = new Error(message).stack;
18
+ }
19
+
20
+ /**
21
+ * This needs to stay here until our minimum supported version of Node.js is >= 16.9.0.
22
+ * Node.js is >= 16.9.0 supports error causes natively.
23
+ */
24
+ if (options != null && typeof options === 'object' && Object.hasOwn(options, 'cause') && !('cause' in this)) {
25
+ const {
26
+ cause
27
+ } = options;
28
+ this.cause = cause;
29
+ if (cause instanceof Error && 'stack' in cause) {
30
+ this.stack = `${this.stack}\nCAUSE: ${cause.stack}`;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Allows to assign arbitrary properties to the error object.
36
+ */
37
+ if (options != null && typeof options === 'object') {
38
+ const {
39
+ cause,
40
+ ...causelessOptions
41
+ } = options;
42
+ Object.assign(this, causelessOptions);
43
+ }
44
+ }
45
+ }
46
+ var _default = exports.default = ArazzoCriterionError;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ArazzoCriterionError = _interopRequireDefault(require("./ArazzoCriterionError.cjs"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ class ArazzoCriterionEvaluateError extends _ArazzoCriterionError.default {}
10
+ var _default = exports.default = ArazzoCriterionEvaluateError;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ArazzoCriterionError = _interopRequireDefault(require("./ArazzoCriterionError.cjs"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ class ArazzoCriterionParseError extends _ArazzoCriterionError.default {}
10
+ var _default = exports.default = ArazzoCriterionParseError;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _index = _interopRequireDefault(require("../parse/index.cjs"));
8
+ var _ArazzoCriterionEvaluateError = _interopRequireDefault(require("../errors/ArazzoCriterionEvaluateError.cjs"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ /**
11
+ * Evaluate a "simple" Arazzo criterion condition.
12
+ *
13
+ * Runtime expression values are supplied by the caller through `resolve`, which
14
+ * receives the runtime expression string and its parsed sub-AST, and returns the
15
+ * concrete value.
16
+ *
17
+ * @example
18
+ * evaluate('$statusCode == 200', {
19
+ * resolve: (expression, ast) => (expression === '$statusCode' ? 200 : undefined),
20
+ * }); // => true
21
+ */
22
+ const evaluate = (condition, {
23
+ resolve
24
+ } = {}) => {
25
+ if (typeof condition !== 'string') {
26
+ throw new TypeError('Criterion condition must be a string');
27
+ }
28
+ if (typeof resolve !== 'function') {
29
+ throw new TypeError('evaluate requires a "resolve" function in options');
30
+ }
31
+ const {
32
+ result,
33
+ tree
34
+ } = (0, _index.default)(condition);
35
+ if (!result.success) {
36
+ throw new _ArazzoCriterionEvaluateError.default('Invalid criterion condition', {
37
+ condition
38
+ });
39
+ }
40
+ return toBoolean(evaluateNode(tree, resolve));
41
+ };
42
+ const evaluateNode = (node, resolve) => {
43
+ switch (node.type) {
44
+ case 'LogicalExpression':
45
+ return evaluateLogical(node, resolve);
46
+ case 'UnaryExpression':
47
+ return !toBoolean(evaluateNode(node.argument, resolve));
48
+ case 'BinaryExpression':
49
+ return evaluateComparison(node, resolve);
50
+ case 'Literal':
51
+ return node.value;
52
+ case 'RuntimeExpression':
53
+ return resolve(node.text, node.expression);
54
+ case 'RuntimeExpressionNavigation':
55
+ return evaluateNavigation(node, resolve);
56
+ default:
57
+ throw new _ArazzoCriterionEvaluateError.default(`Unknown AST node type: ${node.type}`);
58
+ }
59
+ };
60
+ const evaluateLogical = (node, resolve) => {
61
+ if (node.operator === '&&') {
62
+ return toBoolean(evaluateNode(node.left, resolve)) && toBoolean(evaluateNode(node.right, resolve));
63
+ }
64
+ // '||'
65
+ return toBoolean(evaluateNode(node.left, resolve)) || toBoolean(evaluateNode(node.right, resolve));
66
+ };
67
+ const evaluateNavigation = (node, resolve) => {
68
+ let value = resolve(node.expression.text, node.expression.expression);
69
+ for (const step of node.navigation) {
70
+ if (value == null) return undefined;
71
+ value = step.type === 'MemberAccess' ? value[step.name] : value[step.value];
72
+ }
73
+ return value;
74
+ };
75
+ const evaluateComparison = (node, resolve) => {
76
+ const left = evaluateNode(node.left, resolve);
77
+ const right = evaluateNode(node.right, resolve);
78
+ switch (node.operator) {
79
+ case '==':
80
+ return looseEquals(left, right);
81
+ case '!=':
82
+ return !looseEquals(left, right);
83
+ case '<':
84
+ case '<=':
85
+ case '>':
86
+ case '>=':
87
+ return relational(node.operator, left, right);
88
+ default:
89
+ throw new _ArazzoCriterionEvaluateError.default(`Unknown comparison operator: ${node.operator}`);
90
+ }
91
+ };
92
+
93
+ // null equals only itself; comparing null to any other value is false.
94
+ const looseEquals = (a, b) => {
95
+ const aNull = a === null || a === undefined;
96
+ const bNull = b === null || b === undefined;
97
+ if (aNull || bNull) return aNull && bNull;
98
+
99
+ // string comparisons MUST be case insensitive
100
+ if (typeof a === 'string' && typeof b === 'string') {
101
+ return a.toLowerCase() === b.toLowerCase();
102
+ }
103
+
104
+ // numeric strings SHOULD be coerced to numbers when compared with a number
105
+ if (typeof a === 'number' && typeof b === 'string' && isNumeric(b)) return a === Number(b);
106
+ if (typeof b === 'number' && typeof a === 'string' && isNumeric(a)) return Number(a) === b;
107
+ return a === b;
108
+ };
109
+ const relational = (operator, a, b) => {
110
+ // comparing null/undefined with a relational operator is always false
111
+ if (a === null || a === undefined || b === null || b === undefined) return false;
112
+ let left = a;
113
+ let right = b;
114
+
115
+ // numeric coercion of numeric strings under numeric operators
116
+ if (typeof left === 'number' && typeof right === 'string' && isNumeric(right)) right = Number(right);else if (typeof right === 'number' && typeof left === 'string' && isNumeric(left)) left = Number(left);else if (typeof left === 'string' && typeof right === 'string') {
117
+ // case-insensitive string ordering
118
+ left = left.toLowerCase();
119
+ right = right.toLowerCase();
120
+ }
121
+ switch (operator) {
122
+ case '<':
123
+ return left < right;
124
+ case '<=':
125
+ return left <= right;
126
+ case '>':
127
+ return left > right;
128
+ case '>=':
129
+ return left >= right;
130
+ default:
131
+ return false;
132
+ }
133
+ };
134
+ const isNumeric = str => str.trim() !== '' && Number.isFinite(Number(str));
135
+
136
+ // A condition passes (truthy) when it evaluates to a truthy value; it fails (falsy)
137
+ // on false, null, or a missing (undefined) value.
138
+ const toBoolean = value => Boolean(value);
139
+ var _default = exports.default = evaluate;