@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.
- package/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +406 -0
- package/SECURITY.md +15 -0
- package/cjs/apg-lite.cjs +1223 -0
- package/cjs/errors/ArazzoCriterionError.cjs +46 -0
- package/cjs/errors/ArazzoCriterionEvaluateError.cjs +10 -0
- package/cjs/errors/ArazzoCriterionParseError.cjs +10 -0
- package/cjs/evaluate/index.cjs +139 -0
- package/cjs/grammar.cjs +1111 -0
- package/cjs/index.cjs +83 -0
- package/cjs/parse/callbacks/cst.cjs +30 -0
- package/cjs/parse/index.cjs +42 -0
- package/cjs/parse/trace/Expectations.cjs +12 -0
- package/cjs/parse/trace/Trace.cjs +37 -0
- package/cjs/parse/translators/ASTTranslator/index.cjs +17 -0
- package/cjs/parse/translators/ASTTranslator/transformers.cjs +203 -0
- package/cjs/parse/translators/CSTTranslator.cjs +49 -0
- package/cjs/parse/translators/XMLTranslator.cjs +14 -0
- package/cjs/test/index.cjs +20 -0
- package/es/errors/ArazzoCriterionError.mjs +40 -0
- package/es/errors/ArazzoCriterionEvaluateError.mjs +3 -0
- package/es/errors/ArazzoCriterionParseError.mjs +3 -0
- package/es/evaluate/index.mjs +132 -0
- package/es/grammar.mjs +1105 -0
- package/es/index.mjs +11 -0
- package/es/parse/callbacks/cst.mjs +24 -0
- package/es/parse/index.mjs +35 -0
- package/es/parse/trace/Expectations.mjs +6 -0
- package/es/parse/trace/Trace.mjs +30 -0
- package/es/parse/translators/ASTTranslator/index.mjs +9 -0
- package/es/parse/translators/ASTTranslator/transformers.mjs +195 -0
- package/es/parse/translators/CSTTranslator.mjs +42 -0
- package/es/parse/translators/XMLTranslator.mjs +7 -0
- package/es/test/index.mjs +13 -0
- package/package.json +95 -0
- 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;
|