@rytass/bpm-core-nestjs-module 0.19.0 → 0.20.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/CHANGELOG.md +36 -0
- package/package.json +3 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/bpm/bpm-root-options.d.ts +13 -0
- package/src/lib/bpm/bpm-root-options.js.map +1 -1
- package/src/lib/bpm/bpm-root.module.d.ts +12 -0
- package/src/lib/bpm/bpm-root.module.js +5 -0
- package/src/lib/bpm/bpm-root.module.js.map +1 -1
- package/src/lib/condition/adapters/cel-legacy.adapter.d.ts +62 -0
- package/src/lib/condition/adapters/cel-legacy.adapter.js +141 -0
- package/src/lib/condition/adapters/cel-legacy.adapter.js.map +1 -0
- package/src/lib/condition/adapters/cel-v2.adapter.d.ts +76 -0
- package/src/lib/condition/adapters/cel-v2.adapter.js +371 -0
- package/src/lib/condition/adapters/cel-v2.adapter.js.map +1 -0
- package/src/lib/condition/condition.service.d.ts +90 -5
- package/src/lib/condition/condition.service.js +287 -71
- package/src/lib/condition/condition.service.js.map +1 -1
- package/src/lib/condition/expression-ast.d.ts +176 -0
- package/src/lib/condition/expression-ast.js +1254 -0
- package/src/lib/condition/expression-ast.js.map +1 -0
- package/src/lib/condition/expression-budget.d.ts +44 -0
- package/src/lib/condition/expression-budget.js +61 -0
- package/src/lib/condition/expression-budget.js.map +1 -0
- package/src/lib/condition/expression-dialect.d.ts +29 -0
- package/src/lib/condition/expression-dialect.js +44 -0
- package/src/lib/condition/expression-dialect.js.map +1 -0
- package/src/lib/condition/expression-differential.corpus.d.ts +34 -0
- package/src/lib/condition/expression-differential.corpus.js +995 -0
- package/src/lib/condition/expression-differential.corpus.js.map +1 -0
- package/src/lib/condition/expression-differential.d.ts +33 -0
- package/src/lib/condition/expression-differential.js +48 -0
- package/src/lib/condition/expression-differential.js.map +1 -0
- package/src/lib/condition/expression-engine-failure.d.ts +15 -0
- package/src/lib/condition/expression-engine-failure.js +22 -0
- package/src/lib/condition/expression-engine-failure.js.map +1 -0
- package/src/lib/condition/expression-errors.d.ts +40 -0
- package/src/lib/condition/expression-errors.js +105 -0
- package/src/lib/condition/expression-errors.js.map +1 -0
- package/src/lib/condition/expression-function-invocation.d.ts +50 -0
- package/src/lib/condition/expression-function-invocation.js +290 -0
- package/src/lib/condition/expression-function-invocation.js.map +1 -0
- package/src/lib/condition/expression-result.walker.d.ts +18 -0
- package/src/lib/condition/expression-result.walker.js +152 -0
- package/src/lib/condition/expression-result.walker.js.map +1 -0
- package/src/lib/condition/expression-runtime.d.ts +70 -0
- package/src/lib/condition/expression-runtime.js +134 -0
- package/src/lib/condition/expression-runtime.js.map +1 -0
- package/src/lib/condition/index.d.ts +4 -0
- package/src/lib/condition/index.js +8 -0
- package/src/lib/condition/index.js.map +1 -1
- package/src/lib/delegation/delegation-rule.entity.d.ts +7 -0
- package/src/lib/delegation/delegation-rule.entity.js +10 -0
- package/src/lib/delegation/delegation-rule.entity.js.map +1 -1
- package/src/lib/delegation/delegation.service.d.ts +7 -1
- package/src/lib/delegation/delegation.service.js +22 -5
- package/src/lib/delegation/delegation.service.js.map +1 -1
- package/src/lib/delegation/dto/delegation-rule.input.d.ts +2 -0
- package/src/lib/delegation/dto/delegation-rule.input.js +10 -0
- package/src/lib/delegation/dto/delegation-rule.input.js.map +1 -1
- package/src/lib/expression-function/expression-function.built-ins.d.ts +9 -0
- package/src/lib/expression-function/expression-function.built-ins.js +117 -0
- package/src/lib/expression-function/expression-function.built-ins.js.map +1 -0
- package/src/lib/expression-function/expression-function.module.d.ts +19 -0
- package/src/lib/expression-function/expression-function.module.js +34 -0
- package/src/lib/expression-function/expression-function.module.js.map +1 -0
- package/src/lib/expression-function/expression-function.provider.d.ts +17 -0
- package/src/lib/expression-function/expression-function.provider.js +39 -0
- package/src/lib/expression-function/expression-function.provider.js.map +1 -0
- package/src/lib/expression-function/expression-function.registry.d.ts +36 -0
- package/src/lib/expression-function/expression-function.registry.js +231 -0
- package/src/lib/expression-function/expression-function.registry.js.map +1 -0
- package/src/lib/expression-function/expression-function.types.d.ts +30 -0
- package/src/lib/expression-function/expression-function.types.js +8 -0
- package/src/lib/expression-function/expression-function.types.js.map +1 -0
- package/src/lib/expression-function/index.d.ts +5 -0
- package/src/lib/expression-function/index.js +9 -0
- package/src/lib/expression-function/index.js.map +1 -0
- package/src/lib/form/form-schema.validator.js +53 -6
- package/src/lib/form/form-schema.validator.js.map +1 -1
- package/src/lib/form-data-source/form-data-source-value-resolver.service.d.ts +12 -1
- package/src/lib/form-data-source/form-data-source-value-resolver.service.js +45 -26
- package/src/lib/form-data-source/form-data-source-value-resolver.service.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.expression.d.ts +95 -0
- package/src/lib/form-data-source/form-data-source.expression.js +267 -0
- package/src/lib/form-data-source/form-data-source.expression.js.map +1 -0
- package/src/lib/form-data-source/form-data-source.module.js +4 -0
- package/src/lib/form-data-source/form-data-source.module.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.service.d.ts +22 -3
- package/src/lib/form-data-source/form-data-source.service.js +78 -18
- package/src/lib/form-data-source/form-data-source.service.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.validation.d.ts +47 -4
- package/src/lib/form-data-source/form-data-source.validation.js +151 -23
- package/src/lib/form-data-source/form-data-source.validation.js.map +1 -1
- package/src/lib/migrations/0000000030000-delegation-scope-condition-dialect.d.ts +22 -0
- package/src/lib/migrations/0000000030000-delegation-scope-condition-dialect.js +76 -0
- package/src/lib/migrations/0000000030000-delegation-scope-condition-dialect.js.map +1 -0
- package/src/lib/migrations/index.d.ts +1 -0
- package/src/lib/migrations/index.js +3 -0
- package/src/lib/migrations/index.js.map +1 -1
- package/src/lib/notification/notification.service.d.ts +1 -1
- package/src/lib/notification/notification.service.js +7 -3
- package/src/lib/notification/notification.service.js.map +1 -1
- package/src/lib/template/dto/expression-designer.dto.d.ts +107 -0
- package/src/lib/template/dto/expression-designer.dto.js +415 -0
- package/src/lib/template/dto/expression-designer.dto.js.map +1 -0
- package/src/lib/template/expression-designer.queries.d.ts +16 -0
- package/src/lib/template/expression-designer.queries.js +66 -0
- package/src/lib/template/expression-designer.queries.js.map +1 -0
- package/src/lib/template/expression-designer.service.d.ts +72 -0
- package/src/lib/template/expression-designer.service.js +543 -0
- package/src/lib/template/expression-designer.service.js.map +1 -0
- package/src/lib/template/index.d.ts +2 -0
- package/src/lib/template/index.js +2 -0
- package/src/lib/template/index.js.map +1 -1
- package/src/lib/template/template.module.js +4 -0
- package/src/lib/template/template.module.js.map +1 -1
- package/src/lib/template/template.service.d.ts +37 -1
- package/src/lib/template/template.service.js +317 -29
- package/src/lib/template/template.service.js.map +1 -1
- package/src/lib/template/workflow-definition.validator.d.ts +7 -0
- package/src/lib/template/workflow-definition.validator.js +26 -2
- package/src/lib/template/workflow-definition.validator.js.map +1 -1
- package/src/lib/workflow-engine/time-budget.d.ts +13 -0
- package/src/lib/workflow-engine/time-budget.js +58 -0
- package/src/lib/workflow-engine/time-budget.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.service.d.ts +24 -0
- package/src/lib/workflow-engine/workflow-engine.service.js +240 -65
- package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
- package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js +4 -0
- package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js.map +1 -1
- package/src/lib/workflow-webhook/workflow-webhook-delivery.service.d.ts +3 -1
- package/src/lib/workflow-webhook/workflow-webhook-delivery.service.js +11 -2
- package/src/lib/workflow-webhook/workflow-webhook-delivery.service.js.map +1 -1
- package/src/lib/workflow-webhook/workflow-webhook-enqueue.d.ts +8 -1
- package/src/lib/workflow-webhook/workflow-webhook-enqueue.js +70 -27
- package/src/lib/workflow-webhook/workflow-webhook-enqueue.js.map +1 -1
- package/src/lib/workflow-webhook/workflow-webhook-expression.d.ts +57 -0
- package/src/lib/workflow-webhook/workflow-webhook-expression.js +123 -0
- package/src/lib/workflow-webhook/workflow-webhook-expression.js.map +1 -0
- package/src/lib/workflow-webhook/workflow-webhook.module.js +4 -0
- package/src/lib/workflow-webhook/workflow-webhook.module.js.map +1 -1
- package/src/lib/workflow-webhook/workflow-webhook.validator.d.ts +7 -0
- package/src/lib/workflow-webhook/workflow-webhook.validator.js +29 -6
- package/src/lib/workflow-webhook/workflow-webhook.validator.js.map +1 -1
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.celV2Adapter = exports.createCelV2Adapter = exports.CEL_V2_LIMITS = void 0;
|
|
4
|
+
exports.loadCelV2Environment = loadCelV2Environment;
|
|
5
|
+
exports.findCelV2ArgumentTypeMismatch = findCelV2ArgumentTypeMismatch;
|
|
6
|
+
exports.parseCelV2 = parseCelV2;
|
|
7
|
+
exports.classifyCelV2Error = classifyCelV2Error;
|
|
8
|
+
const expression_function_registry_1 = require("../../expression-function/expression-function.registry");
|
|
9
|
+
const expression_engine_failure_1 = require("../expression-engine-failure");
|
|
10
|
+
const expression_function_invocation_1 = require("../expression-function-invocation");
|
|
11
|
+
/**
|
|
12
|
+
* Parse-time structure limits (ADR 22 §3.4, docs/24 §2.7). They are applied by
|
|
13
|
+
* the engine while parsing, so an over-large expression never reaches the
|
|
14
|
+
* budget. Comprehension nesting is not an engine limit; P2 checks it on the AST.
|
|
15
|
+
*/
|
|
16
|
+
exports.CEL_V2_LIMITS = {
|
|
17
|
+
maxAstNodes: 200,
|
|
18
|
+
maxDepth: 32,
|
|
19
|
+
};
|
|
20
|
+
const MIXED_ARITHMETIC_OPERATORS = ['+', '-', '*', '/', '%'];
|
|
21
|
+
/**
|
|
22
|
+
* A CEL `int` (a `bigint`) or `double` (a `number`) as a JS number. An int
|
|
23
|
+
* outside the safe range cannot become a double without silently changing,
|
|
24
|
+
* so it is refused (docs/24 §2.1: out of safe range is `EXPRESSION_INVALID_RESULT`).
|
|
25
|
+
*/
|
|
26
|
+
const toDouble = (value) => {
|
|
27
|
+
if (typeof value === 'number') {
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
if (typeof value === 'bigint' &&
|
|
31
|
+
value <= BigInt(Number.MAX_SAFE_INTEGER) &&
|
|
32
|
+
value >= BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
33
|
+
return Number(value);
|
|
34
|
+
}
|
|
35
|
+
throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_INVALID_RESULT');
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The mixed `int`/`double` arithmetic cel-legacy gives for free (it only has
|
|
39
|
+
* JS numbers) and cel-v2 refuses with `no such overload`. Form values arrive as
|
|
40
|
+
* JS numbers, which cel-v2 types as `double`, while integer literals are `int`,
|
|
41
|
+
* so without these `form.amount * 2` fails (ADR 22 §3.3). The result is a
|
|
42
|
+
* `double`, as in cel-legacy.
|
|
43
|
+
*
|
|
44
|
+
* A zero divisor throws `EXPRESSION_TYPE_ERROR` (docs/24 §2.1) instead of
|
|
45
|
+
* returning `Infinity`/`NaN`, which a comparison would quietly turn into a
|
|
46
|
+
* routing decision.
|
|
47
|
+
*/
|
|
48
|
+
const MIXED_ARITHMETIC = {
|
|
49
|
+
'%': (left, right) => left % right,
|
|
50
|
+
'*': (left, right) => left * right,
|
|
51
|
+
'+': (left, right) => left + right,
|
|
52
|
+
'-': (left, right) => left - right,
|
|
53
|
+
'/': (left, right) => left / right,
|
|
54
|
+
};
|
|
55
|
+
const runMixedArithmetic = (operator, left, right) => {
|
|
56
|
+
const leftNumber = toDouble(left);
|
|
57
|
+
const rightNumber = toDouble(right);
|
|
58
|
+
if ((operator === '/' || operator === '%') && rightNumber === 0) {
|
|
59
|
+
throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_TYPE_ERROR');
|
|
60
|
+
}
|
|
61
|
+
return MIXED_ARITHMETIC[operator](leftNumber, rightNumber);
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* `int == double`, exact: the int is compared as a `bigint`, so a large int is
|
|
65
|
+
* never rounded into equality with a nearby double. Registering it also gives
|
|
66
|
+
* the reverse order and `!=` (the engine derives them).
|
|
67
|
+
*/
|
|
68
|
+
const isIntEqualToDouble = (left, right) => {
|
|
69
|
+
const [int, double] = typeof left === 'bigint' ? [left, right] : [right, left];
|
|
70
|
+
return (typeof int === 'bigint' &&
|
|
71
|
+
typeof double === 'number' &&
|
|
72
|
+
Number.isInteger(double) &&
|
|
73
|
+
BigInt(double) === int);
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Options that make cel-v2 read a BPM context the way cel-legacy did:
|
|
77
|
+
* undeclared roots are `dyn` (the roots are checked by the runtime's
|
|
78
|
+
* allowlist, not by declaration), and list and map literals may mix value
|
|
79
|
+
* types (`{"a": "x", "b": 2}`, which cel-legacy refuses).
|
|
80
|
+
*/
|
|
81
|
+
const ENVIRONMENT_OPTIONS = {
|
|
82
|
+
homogeneousAggregateLiterals: false,
|
|
83
|
+
limits: exports.CEL_V2_LIMITS,
|
|
84
|
+
unlistedVariablesAreDyn: true,
|
|
85
|
+
};
|
|
86
|
+
const createEnvironment = (module) => {
|
|
87
|
+
const environment = new module.Environment(ENVIRONMENT_OPTIONS);
|
|
88
|
+
MIXED_ARITHMETIC_OPERATORS.forEach((operator) => {
|
|
89
|
+
environment.registerOperator(`double ${operator} int: double`, (left, right) => runMixedArithmetic(operator, left, right));
|
|
90
|
+
environment.registerOperator(`int ${operator} double: double`, (left, right) => runMixedArithmetic(operator, left, right));
|
|
91
|
+
});
|
|
92
|
+
// `in` is deliberately not registered for mixed lists: an `int in
|
|
93
|
+
// list<double>` overload makes the engine's own `V in list<V>` ambiguous for
|
|
94
|
+
// `dyn` values, and `form.qty in [1, 2.5]` then fails at evaluation.
|
|
95
|
+
environment.registerOperator('int == double', isIntEqualToDouble);
|
|
96
|
+
return environment;
|
|
97
|
+
};
|
|
98
|
+
let celV2BaseEnvironment = null;
|
|
99
|
+
/**
|
|
100
|
+
* Loads `@marcbachmann/cel-js` on first use, like `loadCelEngine` does for
|
|
101
|
+
* cel-legacy, and for the same reasons: a host that never evaluates a cel-v2
|
|
102
|
+
* expression never resolves the package, and the ESM-only package is loaded
|
|
103
|
+
* with `require` so every caller stays synchronous (Node >=20.19 / >=22.12).
|
|
104
|
+
*
|
|
105
|
+
* This is the environment every function environment is cloned from: options,
|
|
106
|
+
* limits and the mixed-number operators, no functions. Cloning freezes it, so
|
|
107
|
+
* it is complete before the first clone.
|
|
108
|
+
*/
|
|
109
|
+
const loadCelV2BaseEnvironment = () => {
|
|
110
|
+
if (celV2BaseEnvironment === null) {
|
|
111
|
+
let module;
|
|
112
|
+
try {
|
|
113
|
+
module = require('@marcbachmann/cel-js');
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (typeof error === 'object' &&
|
|
117
|
+
error !== null &&
|
|
118
|
+
error.code === 'ERR_REQUIRE_ESM') {
|
|
119
|
+
throw new Error(`[@rytass/bpm-core-nestjs-module] This Node version cannot require the ESM-only '@marcbachmann/cel-js'. BPM needs Node >=20.19 or >=22.12 to evaluate cel-v2 expressions. Original error: ${error instanceof Error ? error.message : String(error)}`);
|
|
120
|
+
}
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
celV2BaseEnvironment = createEnvironment(module);
|
|
124
|
+
}
|
|
125
|
+
return celV2BaseEnvironment;
|
|
126
|
+
};
|
|
127
|
+
/*
|
|
128
|
+
* How a declared type is written in a cel-v2 signature. Numbers are `dyn`:
|
|
129
|
+
* cel-v2 tells an `int` literal (`1000`) from a `double` (a form value, which
|
|
130
|
+
* is a JS number), so a `double` parameter would refuse `f_v1(1000)` and an
|
|
131
|
+
* `int` one would refuse `f_v1(form.qty)`. The wrapper checks the number
|
|
132
|
+
* against the declared type instead. Every other type is enforced by the
|
|
133
|
+
* engine's overload resolution, which reports a mismatch as a type error.
|
|
134
|
+
*/
|
|
135
|
+
const toSignatureParameterType = (type) => type === 'double' || type === 'int' ? 'dyn' : type;
|
|
136
|
+
const toSignature = (fn) => `${fn.name}(${fn.parameters
|
|
137
|
+
.map((parameter) => toSignatureParameterType(parameter.type))
|
|
138
|
+
.join(', ')}): ${fn.returnType}`;
|
|
139
|
+
const celV2Environments = new WeakMap();
|
|
140
|
+
/**
|
|
141
|
+
* The declared parameter types of every function registered on a function
|
|
142
|
+
* environment, by name. Kept beside the environment because numbers are
|
|
143
|
+
* registered as `dyn` (see `toSignatureParameterType`), so the engine's own
|
|
144
|
+
* check cannot tell a `string` argument handed to a `double` parameter.
|
|
145
|
+
*/
|
|
146
|
+
const celV2FunctionParameters = new WeakMap();
|
|
147
|
+
/**
|
|
148
|
+
* The cel-v2 environment for a registry: the base environment plus every
|
|
149
|
+
* function the registry lists (the nine built-ins and the host's), built once
|
|
150
|
+
* per registry and cached. Without a registry it is the built-ins-only one.
|
|
151
|
+
*
|
|
152
|
+
* Every function is registered as a global call (`round(x)`), never as a
|
|
153
|
+
* method. The name `trim` therefore sits beside cel-v2's own `string.trim()`
|
|
154
|
+
* method without replacing it; no other built-in name exists in cel-v2.
|
|
155
|
+
*
|
|
156
|
+
* The returned environment is frozen: registering on it throws. For a
|
|
157
|
+
* type check with declared variables (P2's `env.check()`), `clone()` it and
|
|
158
|
+
* register the variables on the clone.
|
|
159
|
+
*/
|
|
160
|
+
function loadCelV2Environment(registry = expression_function_registry_1.BUILT_IN_EXPRESSION_FUNCTION_REGISTRY) {
|
|
161
|
+
const cached = celV2Environments.get(registry);
|
|
162
|
+
if (cached) {
|
|
163
|
+
return cached;
|
|
164
|
+
}
|
|
165
|
+
const environment = loadCelV2BaseEnvironment().clone();
|
|
166
|
+
const { functions } = (0, expression_function_invocation_1.readExpressionFunctionTable)(registry);
|
|
167
|
+
functions.forEach((fn) => {
|
|
168
|
+
environment.registerFunction(toSignature(fn), (0, expression_function_invocation_1.createExpressionFunctionInvoker)(fn, 'cel-v2'));
|
|
169
|
+
});
|
|
170
|
+
// Cloning stops the parent from registering more (documented engine
|
|
171
|
+
// behaviour), so the shared environment cannot be changed by a caller.
|
|
172
|
+
environment.clone();
|
|
173
|
+
celV2FunctionParameters.set(environment, new Map(functions.map((fn) => [
|
|
174
|
+
fn.name,
|
|
175
|
+
fn.parameters.map((parameter) => parameter.type),
|
|
176
|
+
])));
|
|
177
|
+
celV2Environments.set(registry, environment);
|
|
178
|
+
return environment;
|
|
179
|
+
}
|
|
180
|
+
const isAstNode = (value) => typeof value === 'object' &&
|
|
181
|
+
value !== null &&
|
|
182
|
+
typeof value.op === 'string';
|
|
183
|
+
const NUMERIC_CHECKED_TYPES = new Set([
|
|
184
|
+
'double',
|
|
185
|
+
'int',
|
|
186
|
+
'uint',
|
|
187
|
+
]);
|
|
188
|
+
/*
|
|
189
|
+
* The checked types (their base, `list<string>` is `list`) a parameter of
|
|
190
|
+
* each declared type accepts. `dyn` is accepted everywhere: a value the check
|
|
191
|
+
* cannot type is decided at evaluation, as before. A `double` parameter takes
|
|
192
|
+
* an `int` and an `int` one a `double` (a form number is a `double` even when
|
|
193
|
+
* it is whole); the wrapper decides those at evaluation.
|
|
194
|
+
*/
|
|
195
|
+
const isCheckedTypeAccepted = (checkedType, parameterType) => {
|
|
196
|
+
if (checkedType === 'dyn' || parameterType === 'dyn') {
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
switch (parameterType) {
|
|
200
|
+
case 'double':
|
|
201
|
+
case 'int':
|
|
202
|
+
return NUMERIC_CHECKED_TYPES.has(checkedType);
|
|
203
|
+
case 'null':
|
|
204
|
+
return checkedType === 'null';
|
|
205
|
+
default:
|
|
206
|
+
return checkedType === parameterType;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const readCheckedBaseType = (node) => {
|
|
210
|
+
const checked = node
|
|
211
|
+
?.checkedType;
|
|
212
|
+
const name = typeof checked === 'object' && checked !== null
|
|
213
|
+
? checked.name
|
|
214
|
+
: undefined;
|
|
215
|
+
return typeof name === 'string' ? name.split('<')[0].trim() : null;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* The first global call to a registered function whose argument the type
|
|
219
|
+
* check typed as something the declared parameter refuses (ADR 22 §3.5): a
|
|
220
|
+
* text field handed to a `double` parameter, say. Only meaningful on the AST
|
|
221
|
+
* of an expression `check()` accepted, parsed in a clone of
|
|
222
|
+
* `loadCelV2Environment(...)`'s environment (`environment` is that
|
|
223
|
+
* environment, not the clone); an argument without a checked type, or a
|
|
224
|
+
* function the environment does not know, is skipped.
|
|
225
|
+
*
|
|
226
|
+
* The engine checks every other parameter type itself through the
|
|
227
|
+
* signature; numbers are registered as `dyn` there, which is what this
|
|
228
|
+
* closes for the publish lint.
|
|
229
|
+
*
|
|
230
|
+
* `readArgumentType`, when given, may name the type to compare instead of
|
|
231
|
+
* the checked one (a base type, `null` to keep the checked one): the lint
|
|
232
|
+
* passes the schema type of a field it had to check as `dyn`, so that
|
|
233
|
+
* `form.title != null && f(form.title)` is compared as the text it is.
|
|
234
|
+
*/
|
|
235
|
+
function findCelV2ArgumentTypeMismatch(ast, environment, readArgumentType = () => null) {
|
|
236
|
+
const parameters = celV2FunctionParameters.get(environment);
|
|
237
|
+
if (!parameters) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
const visit = (node) => {
|
|
241
|
+
if (Array.isArray(node)) {
|
|
242
|
+
return node.reduce((found, child) => found ?? visit(child), null);
|
|
243
|
+
}
|
|
244
|
+
if (!isAstNode(node)) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const args = node.args;
|
|
248
|
+
if (node.op === 'call' &&
|
|
249
|
+
Array.isArray(args) &&
|
|
250
|
+
typeof args[0] === 'string' &&
|
|
251
|
+
Array.isArray(args[1])) {
|
|
252
|
+
const declared = parameters.get(args[0]);
|
|
253
|
+
const callArguments = args[1];
|
|
254
|
+
const mismatchIndex = declared && declared.length === callArguments.length
|
|
255
|
+
? callArguments.findIndex((argument, index) => {
|
|
256
|
+
const checkedType = readArgumentType(argument) ?? readCheckedBaseType(argument);
|
|
257
|
+
return (checkedType !== null &&
|
|
258
|
+
!isCheckedTypeAccepted(checkedType, declared[index]));
|
|
259
|
+
})
|
|
260
|
+
: -1;
|
|
261
|
+
if (declared && mismatchIndex >= 0) {
|
|
262
|
+
return {
|
|
263
|
+
argument: callArguments[mismatchIndex],
|
|
264
|
+
functionName: args[0],
|
|
265
|
+
parameterType: declared[mismatchIndex],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return visit(args);
|
|
270
|
+
};
|
|
271
|
+
return visit(ast);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Parses with cel-v2. Returns `null` when the expression does not parse or
|
|
275
|
+
* breaks a structure limit. The engine is loaded outside the `try`: a failure
|
|
276
|
+
* to load it is a configuration error, not a bad expression.
|
|
277
|
+
*
|
|
278
|
+
* Parsing does not check that a called function exists; evaluation does.
|
|
279
|
+
*/
|
|
280
|
+
function parseCelV2(expression, registry = expression_function_registry_1.BUILT_IN_EXPRESSION_FUNCTION_REGISTRY) {
|
|
281
|
+
const environment = loadCelV2Environment(registry);
|
|
282
|
+
try {
|
|
283
|
+
return { native: environment.parse(expression) };
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Names of the global functions an expression calls (`call` nodes; methods are
|
|
291
|
+
* `rcall` and never host functions). A small walk of the engine's AST, only
|
|
292
|
+
* for the evaluation-time check; the publish lint reads references through
|
|
293
|
+
* P2's AST module.
|
|
294
|
+
*/
|
|
295
|
+
const readCalledFunctionNames = (node) => {
|
|
296
|
+
if (Array.isArray(node)) {
|
|
297
|
+
return node.flatMap(readCalledFunctionNames);
|
|
298
|
+
}
|
|
299
|
+
if (!isAstNode(node)) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
const args = node.args;
|
|
303
|
+
const own = node.op === 'call' && Array.isArray(args) && typeof args[0] === 'string'
|
|
304
|
+
? [args[0]]
|
|
305
|
+
: [];
|
|
306
|
+
return [...own, ...readCalledFunctionNames(args)];
|
|
307
|
+
};
|
|
308
|
+
const isCelError = (error) => error instanceof Error &&
|
|
309
|
+
(error.name === 'EvaluationError' ||
|
|
310
|
+
error.name === 'TypeError' ||
|
|
311
|
+
error.name === 'ParseError') &&
|
|
312
|
+
typeof error.code === 'string' &&
|
|
313
|
+
typeof error.summary === 'string';
|
|
314
|
+
/*
|
|
315
|
+
* The only engine summaries a key name is read from. Anchored at both ends;
|
|
316
|
+
* the candidate is checked against the expression before anyone sees it.
|
|
317
|
+
* `No such key: index out of bounds, ...` does not match, by design.
|
|
318
|
+
*/
|
|
319
|
+
const KEY_NAME_PATTERNS = [
|
|
320
|
+
/^No such key: ([A-Za-z_][A-Za-z0-9_]*)$/u,
|
|
321
|
+
/^Unknown variable: ([A-Za-z_][A-Za-z0-9_]*)$/u,
|
|
322
|
+
];
|
|
323
|
+
const readKeyNameCandidate = (summary) => KEY_NAME_PATTERNS.reduce((found, pattern) => found ?? pattern.exec(summary)?.[1] ?? null, null);
|
|
324
|
+
const CEL_V2_CODE_MAP = {
|
|
325
|
+
index_out_of_bounds: 'EXPRESSION_MISSING_KEY',
|
|
326
|
+
index_out_of_range: 'EXPRESSION_MISSING_KEY',
|
|
327
|
+
no_such_key: 'EXPRESSION_MISSING_KEY',
|
|
328
|
+
numeric_overflow: 'EXPRESSION_INVALID_RESULT',
|
|
329
|
+
unknown_variable: 'EXPRESSION_MISSING_KEY',
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Maps an error cel-v2 threw to a classified failure, by its `code` only. Any
|
|
333
|
+
* code not listed is a type or evaluation error. Errors that are not cel-v2's
|
|
334
|
+
* (an operator handler's own failure, a stack overflow) pass through unchanged
|
|
335
|
+
* and are classified by the runtime.
|
|
336
|
+
*/
|
|
337
|
+
function classifyCelV2Error(error) {
|
|
338
|
+
if (!isCelError(error)) {
|
|
339
|
+
return error;
|
|
340
|
+
}
|
|
341
|
+
const code = CEL_V2_CODE_MAP[error.code] ?? 'EXPRESSION_TYPE_ERROR';
|
|
342
|
+
return new expression_engine_failure_1.ExpressionEngineFailure(code, code === 'EXPRESSION_MISSING_KEY'
|
|
343
|
+
? readKeyNameCandidate(error.summary)
|
|
344
|
+
: null);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The cel-v2 adapter for a registry. A host function the registry no longer
|
|
348
|
+
* has (withdrawn after publishing) fails the evaluation with
|
|
349
|
+
* `EXPRESSION_FUNCTION_FAILED` before the engine runs, wherever the call sits.
|
|
350
|
+
*/
|
|
351
|
+
const createCelV2Adapter = (registry) => ({
|
|
352
|
+
compile: (expression) => parseCelV2(expression, registry),
|
|
353
|
+
evaluate: (handle, roots) => {
|
|
354
|
+
const parsed = handle.native;
|
|
355
|
+
if ((0, expression_function_invocation_1.callsUnavailableFunction)(readCalledFunctionNames(parsed.ast), (0, expression_function_invocation_1.readExpressionFunctionTable)(registry))) {
|
|
356
|
+
throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_FUNCTION_FAILED');
|
|
357
|
+
}
|
|
358
|
+
return (0, expression_function_invocation_1.runWithExpressionFunctionFrame)(() => {
|
|
359
|
+
try {
|
|
360
|
+
return parsed({ ...roots });
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
throw classifyCelV2Error(error);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
exports.createCelV2Adapter = createCelV2Adapter;
|
|
369
|
+
/** The built-ins-only adapter, used wherever no registry was handed in. */
|
|
370
|
+
exports.celV2Adapter = (0, exports.createCelV2Adapter)(expression_function_registry_1.BUILT_IN_EXPRESSION_FUNCTION_REGISTRY);
|
|
371
|
+
//# sourceMappingURL=cel-v2.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cel-v2.adapter.js","sourceRoot":"","sources":["../../../../../../../libs/bpm-core/src/lib/condition/adapters/cel-v2.adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,101 @@
|
|
|
1
|
+
import { OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import { ExpressionLintIssue } from '@rytass/bpm-core-shared';
|
|
3
|
+
import { ExpressionBudget } from './expression-budget';
|
|
4
|
+
import { JsonValue } from './expression-result.walker';
|
|
5
|
+
import { type BPMExpressionFunctionRegistry } from '../expression-function/expression-function.types';
|
|
6
|
+
import { ExpressionDialect } from './expression-dialect';
|
|
7
|
+
import { ExpressionLintContext } from './expression-ast';
|
|
1
8
|
interface ConditionExpression {
|
|
2
9
|
readonly expression: string | null | undefined;
|
|
3
10
|
readonly label: string;
|
|
4
11
|
}
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Lint options. Everything beyond `dialect` and `maxExpressionLength` is the
|
|
14
|
+
* cel-v2 lint context (`ExpressionLintContext`): the use point, the bound
|
|
15
|
+
* form, the function registry and the field a `SET_FORM_FIELD` writes.
|
|
16
|
+
* cel-legacy reads only the roots from it (docs/24 §1: the old dialect's lint
|
|
17
|
+
* does not change).
|
|
18
|
+
*/
|
|
19
|
+
export interface ConditionLintOptions extends ExpressionLintContext {
|
|
20
|
+
/**
|
|
21
|
+
* The engine whose parser decides syntax. Absent means `cel-legacy`; one
|
|
22
|
+
* this version does not know is reported as `EXPRESSION_SYNTAX_ERROR`.
|
|
23
|
+
*/
|
|
24
|
+
readonly dialect?: ExpressionDialect;
|
|
7
25
|
readonly maxExpressionLength?: number;
|
|
8
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for one evaluation. Both fields are optional: without them a
|
|
29
|
+
* evaluation uses the operation's budget if it runs inside one
|
|
30
|
+
* (see `runExpressionOperation`), or a fresh single-expression budget.
|
|
31
|
+
*/
|
|
32
|
+
export interface ExpressionCallOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Roots the expression may read. Checked at evaluation time, so a dry run
|
|
35
|
+
* cannot read a root that the published definition would be refused for.
|
|
36
|
+
*/
|
|
37
|
+
readonly allowedRootIdentifiers?: readonly string[];
|
|
38
|
+
readonly budget?: ExpressionBudget;
|
|
39
|
+
/**
|
|
40
|
+
* The dialect of the definition or rule the expression belongs to. Absent
|
|
41
|
+
* means `cel-legacy`, which is what every expression saved before the
|
|
42
|
+
* dialect existed was written for (ADR 22 §3.3). One this version does not
|
|
43
|
+
* know is refused as `EXPRESSION_SYNTAX_ERROR`.
|
|
44
|
+
*/
|
|
45
|
+
readonly dialect?: ExpressionDialect;
|
|
46
|
+
}
|
|
9
47
|
export type CelEvaluationContext = Readonly<Record<string, unknown>>;
|
|
10
|
-
|
|
48
|
+
/** How long each dialect's warm-up took, in milliseconds; `null` if it failed. */
|
|
49
|
+
export type ExpressionWarmUpResult = Readonly<Record<ExpressionDialect, number | null>>;
|
|
50
|
+
export declare class ConditionService implements OnApplicationBootstrap {
|
|
51
|
+
private readonly logger;
|
|
52
|
+
private readonly functionRegistry;
|
|
53
|
+
private readonly runtime;
|
|
54
|
+
/**
|
|
55
|
+
* Evaluates and lints with the expression function registry
|
|
56
|
+
* (`BPM_EXPRESSION_FUNCTION_REGISTRY`, ADR 22 §3.5): both dialects call its
|
|
57
|
+
* functions and the cel-v2 lint checks against it. The injection is
|
|
58
|
+
* optional and `ConditionService` is also built with `new` in hosts and
|
|
59
|
+
* tests, so `new ConditionService()` still works: only the nine built-ins.
|
|
60
|
+
*/
|
|
61
|
+
constructor(functionRegistry?: BPMExpressionFunctionRegistry | null);
|
|
62
|
+
/**
|
|
63
|
+
* Warms both engines at boot so the first case does not pay for it (Phase 23
|
|
64
|
+
* P3 live finding: the first evaluation after a restart took about 90 ms of
|
|
65
|
+
* its 100 ms budget, against about 1 ms warm).
|
|
66
|
+
*
|
|
67
|
+
* A warm-up that succeeded for any dialect writes one `log` line with each
|
|
68
|
+
* dialect's time (a failed one reads `failed` and has already warned with
|
|
69
|
+
* `EXPRESSION_WARM_UP_FAILED`), so a deployment can see it ran. The line
|
|
70
|
+
* holds only fixed words and milliseconds: no expression, no data. It is
|
|
71
|
+
* written here, not in `warmUp()`, so calling `warmUp()` stays silent.
|
|
72
|
+
*/
|
|
73
|
+
onApplicationBootstrap(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Loads each dialect's engine and this registry's environment, then parses,
|
|
76
|
+
* lints and evaluates one expression per dialect under a generous budget of
|
|
77
|
+
* its own, so module loading, the cel-v2 environment clone and the `vm`
|
|
78
|
+
* context are paid here. Never throws: a dialect that fails (a host
|
|
79
|
+
* registry that cannot be read, say) is logged with a fixed code and left
|
|
80
|
+
* cold, and the evaluations it serves fail closed as before.
|
|
81
|
+
*/
|
|
82
|
+
warmUp(): ExpressionWarmUpResult;
|
|
83
|
+
/**
|
|
84
|
+
* Loads the dialect's engine and builds this registry's function
|
|
85
|
+
* environment now, outside any budget. Callers that are about to start a
|
|
86
|
+
* budgeted run (the dry run) call this first so an interrupt cannot land
|
|
87
|
+
* halfway through module loading or function registration.
|
|
88
|
+
*/
|
|
89
|
+
prepareEngine(dialect?: ExpressionDialect): void;
|
|
11
90
|
lintExpressions(expressions: readonly ConditionExpression[], options?: ConditionLintOptions): readonly string[];
|
|
91
|
+
/**
|
|
92
|
+
* The lint as structured findings, warnings included (docs/24 §2.2): what
|
|
93
|
+
* the designer's preview and the publish lint read. `lintExpression` is the
|
|
94
|
+
* error half of it, as the lines publish has always returned.
|
|
95
|
+
*/
|
|
96
|
+
lintExpressionIssues(expression: string | null | undefined, label: string, options?: ConditionLintOptions): readonly ExpressionLintIssue[];
|
|
12
97
|
lintExpression(expression: string | null | undefined, label: string, options?: ConditionLintOptions): readonly string[];
|
|
13
|
-
evaluateBoolean(expression: string | null | undefined, context: CelEvaluationContext, label: string): boolean;
|
|
14
|
-
evaluateValue(expression: string, context: CelEvaluationContext, label: string):
|
|
98
|
+
evaluateBoolean(expression: string | null | undefined, context: CelEvaluationContext, label: string, options?: ExpressionCallOptions): boolean;
|
|
99
|
+
evaluateValue(expression: string, context: CelEvaluationContext, label: string, options?: ExpressionCallOptions): JsonValue;
|
|
15
100
|
}
|
|
16
101
|
export {};
|