@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.
Files changed (146) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/package.json +3 -2
  3. package/src/index.d.ts +1 -0
  4. package/src/index.js +1 -0
  5. package/src/index.js.map +1 -1
  6. package/src/lib/bpm/bpm-root-options.d.ts +13 -0
  7. package/src/lib/bpm/bpm-root-options.js.map +1 -1
  8. package/src/lib/bpm/bpm-root.module.d.ts +12 -0
  9. package/src/lib/bpm/bpm-root.module.js +5 -0
  10. package/src/lib/bpm/bpm-root.module.js.map +1 -1
  11. package/src/lib/condition/adapters/cel-legacy.adapter.d.ts +62 -0
  12. package/src/lib/condition/adapters/cel-legacy.adapter.js +141 -0
  13. package/src/lib/condition/adapters/cel-legacy.adapter.js.map +1 -0
  14. package/src/lib/condition/adapters/cel-v2.adapter.d.ts +76 -0
  15. package/src/lib/condition/adapters/cel-v2.adapter.js +371 -0
  16. package/src/lib/condition/adapters/cel-v2.adapter.js.map +1 -0
  17. package/src/lib/condition/condition.service.d.ts +90 -5
  18. package/src/lib/condition/condition.service.js +287 -71
  19. package/src/lib/condition/condition.service.js.map +1 -1
  20. package/src/lib/condition/expression-ast.d.ts +176 -0
  21. package/src/lib/condition/expression-ast.js +1254 -0
  22. package/src/lib/condition/expression-ast.js.map +1 -0
  23. package/src/lib/condition/expression-budget.d.ts +44 -0
  24. package/src/lib/condition/expression-budget.js +61 -0
  25. package/src/lib/condition/expression-budget.js.map +1 -0
  26. package/src/lib/condition/expression-dialect.d.ts +29 -0
  27. package/src/lib/condition/expression-dialect.js +44 -0
  28. package/src/lib/condition/expression-dialect.js.map +1 -0
  29. package/src/lib/condition/expression-differential.corpus.d.ts +34 -0
  30. package/src/lib/condition/expression-differential.corpus.js +995 -0
  31. package/src/lib/condition/expression-differential.corpus.js.map +1 -0
  32. package/src/lib/condition/expression-differential.d.ts +33 -0
  33. package/src/lib/condition/expression-differential.js +48 -0
  34. package/src/lib/condition/expression-differential.js.map +1 -0
  35. package/src/lib/condition/expression-engine-failure.d.ts +15 -0
  36. package/src/lib/condition/expression-engine-failure.js +22 -0
  37. package/src/lib/condition/expression-engine-failure.js.map +1 -0
  38. package/src/lib/condition/expression-errors.d.ts +40 -0
  39. package/src/lib/condition/expression-errors.js +105 -0
  40. package/src/lib/condition/expression-errors.js.map +1 -0
  41. package/src/lib/condition/expression-function-invocation.d.ts +50 -0
  42. package/src/lib/condition/expression-function-invocation.js +290 -0
  43. package/src/lib/condition/expression-function-invocation.js.map +1 -0
  44. package/src/lib/condition/expression-result.walker.d.ts +18 -0
  45. package/src/lib/condition/expression-result.walker.js +152 -0
  46. package/src/lib/condition/expression-result.walker.js.map +1 -0
  47. package/src/lib/condition/expression-runtime.d.ts +70 -0
  48. package/src/lib/condition/expression-runtime.js +134 -0
  49. package/src/lib/condition/expression-runtime.js.map +1 -0
  50. package/src/lib/condition/index.d.ts +4 -0
  51. package/src/lib/condition/index.js +8 -0
  52. package/src/lib/condition/index.js.map +1 -1
  53. package/src/lib/delegation/delegation-rule.entity.d.ts +7 -0
  54. package/src/lib/delegation/delegation-rule.entity.js +10 -0
  55. package/src/lib/delegation/delegation-rule.entity.js.map +1 -1
  56. package/src/lib/delegation/delegation.service.d.ts +7 -1
  57. package/src/lib/delegation/delegation.service.js +22 -5
  58. package/src/lib/delegation/delegation.service.js.map +1 -1
  59. package/src/lib/delegation/dto/delegation-rule.input.d.ts +2 -0
  60. package/src/lib/delegation/dto/delegation-rule.input.js +10 -0
  61. package/src/lib/delegation/dto/delegation-rule.input.js.map +1 -1
  62. package/src/lib/expression-function/expression-function.built-ins.d.ts +9 -0
  63. package/src/lib/expression-function/expression-function.built-ins.js +117 -0
  64. package/src/lib/expression-function/expression-function.built-ins.js.map +1 -0
  65. package/src/lib/expression-function/expression-function.module.d.ts +19 -0
  66. package/src/lib/expression-function/expression-function.module.js +34 -0
  67. package/src/lib/expression-function/expression-function.module.js.map +1 -0
  68. package/src/lib/expression-function/expression-function.provider.d.ts +17 -0
  69. package/src/lib/expression-function/expression-function.provider.js +39 -0
  70. package/src/lib/expression-function/expression-function.provider.js.map +1 -0
  71. package/src/lib/expression-function/expression-function.registry.d.ts +36 -0
  72. package/src/lib/expression-function/expression-function.registry.js +231 -0
  73. package/src/lib/expression-function/expression-function.registry.js.map +1 -0
  74. package/src/lib/expression-function/expression-function.types.d.ts +30 -0
  75. package/src/lib/expression-function/expression-function.types.js +8 -0
  76. package/src/lib/expression-function/expression-function.types.js.map +1 -0
  77. package/src/lib/expression-function/index.d.ts +5 -0
  78. package/src/lib/expression-function/index.js +9 -0
  79. package/src/lib/expression-function/index.js.map +1 -0
  80. package/src/lib/form/form-schema.validator.js +53 -6
  81. package/src/lib/form/form-schema.validator.js.map +1 -1
  82. package/src/lib/form-data-source/form-data-source-value-resolver.service.d.ts +12 -1
  83. package/src/lib/form-data-source/form-data-source-value-resolver.service.js +45 -26
  84. package/src/lib/form-data-source/form-data-source-value-resolver.service.js.map +1 -1
  85. package/src/lib/form-data-source/form-data-source.expression.d.ts +95 -0
  86. package/src/lib/form-data-source/form-data-source.expression.js +267 -0
  87. package/src/lib/form-data-source/form-data-source.expression.js.map +1 -0
  88. package/src/lib/form-data-source/form-data-source.module.js +4 -0
  89. package/src/lib/form-data-source/form-data-source.module.js.map +1 -1
  90. package/src/lib/form-data-source/form-data-source.service.d.ts +22 -3
  91. package/src/lib/form-data-source/form-data-source.service.js +78 -18
  92. package/src/lib/form-data-source/form-data-source.service.js.map +1 -1
  93. package/src/lib/form-data-source/form-data-source.validation.d.ts +47 -4
  94. package/src/lib/form-data-source/form-data-source.validation.js +151 -23
  95. package/src/lib/form-data-source/form-data-source.validation.js.map +1 -1
  96. package/src/lib/migrations/0000000030000-delegation-scope-condition-dialect.d.ts +22 -0
  97. package/src/lib/migrations/0000000030000-delegation-scope-condition-dialect.js +76 -0
  98. package/src/lib/migrations/0000000030000-delegation-scope-condition-dialect.js.map +1 -0
  99. package/src/lib/migrations/index.d.ts +1 -0
  100. package/src/lib/migrations/index.js +3 -0
  101. package/src/lib/migrations/index.js.map +1 -1
  102. package/src/lib/notification/notification.service.d.ts +1 -1
  103. package/src/lib/notification/notification.service.js +7 -3
  104. package/src/lib/notification/notification.service.js.map +1 -1
  105. package/src/lib/template/dto/expression-designer.dto.d.ts +107 -0
  106. package/src/lib/template/dto/expression-designer.dto.js +415 -0
  107. package/src/lib/template/dto/expression-designer.dto.js.map +1 -0
  108. package/src/lib/template/expression-designer.queries.d.ts +16 -0
  109. package/src/lib/template/expression-designer.queries.js +66 -0
  110. package/src/lib/template/expression-designer.queries.js.map +1 -0
  111. package/src/lib/template/expression-designer.service.d.ts +72 -0
  112. package/src/lib/template/expression-designer.service.js +543 -0
  113. package/src/lib/template/expression-designer.service.js.map +1 -0
  114. package/src/lib/template/index.d.ts +2 -0
  115. package/src/lib/template/index.js +2 -0
  116. package/src/lib/template/index.js.map +1 -1
  117. package/src/lib/template/template.module.js +4 -0
  118. package/src/lib/template/template.module.js.map +1 -1
  119. package/src/lib/template/template.service.d.ts +37 -1
  120. package/src/lib/template/template.service.js +317 -29
  121. package/src/lib/template/template.service.js.map +1 -1
  122. package/src/lib/template/workflow-definition.validator.d.ts +7 -0
  123. package/src/lib/template/workflow-definition.validator.js +26 -2
  124. package/src/lib/template/workflow-definition.validator.js.map +1 -1
  125. package/src/lib/workflow-engine/time-budget.d.ts +13 -0
  126. package/src/lib/workflow-engine/time-budget.js +58 -0
  127. package/src/lib/workflow-engine/time-budget.js.map +1 -0
  128. package/src/lib/workflow-engine/workflow-engine.service.d.ts +24 -0
  129. package/src/lib/workflow-engine/workflow-engine.service.js +240 -65
  130. package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
  131. package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js +4 -0
  132. package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js.map +1 -1
  133. package/src/lib/workflow-webhook/workflow-webhook-delivery.service.d.ts +3 -1
  134. package/src/lib/workflow-webhook/workflow-webhook-delivery.service.js +11 -2
  135. package/src/lib/workflow-webhook/workflow-webhook-delivery.service.js.map +1 -1
  136. package/src/lib/workflow-webhook/workflow-webhook-enqueue.d.ts +8 -1
  137. package/src/lib/workflow-webhook/workflow-webhook-enqueue.js +70 -27
  138. package/src/lib/workflow-webhook/workflow-webhook-enqueue.js.map +1 -1
  139. package/src/lib/workflow-webhook/workflow-webhook-expression.d.ts +57 -0
  140. package/src/lib/workflow-webhook/workflow-webhook-expression.js +123 -0
  141. package/src/lib/workflow-webhook/workflow-webhook-expression.js.map +1 -0
  142. package/src/lib/workflow-webhook/workflow-webhook.module.js +4 -0
  143. package/src/lib/workflow-webhook/workflow-webhook.module.js.map +1 -1
  144. package/src/lib/workflow-webhook/workflow-webhook.validator.d.ts +7 -0
  145. package/src/lib/workflow-webhook/workflow-webhook.validator.js +29 -6
  146. package/src/lib/workflow-webhook/workflow-webhook.validator.js.map +1 -1
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.callsUnavailableFunction = exports.isRegistryFunctionName = exports.readExpressionFunctionTable = exports.createExpressionFunctionInvoker = exports.runWithExpressionFunctionFrame = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const bpm_core_shared_1 = require("@rytass/bpm-core-shared");
6
+ const expression_function_registry_1 = require("../expression-function/expression-function.registry");
7
+ const expression_engine_failure_1 = require("./expression-engine-failure");
8
+ const expression_result_walker_1 = require("./expression-result.walker");
9
+ /*
10
+ * The one place a function an expression calls is run (ADR 22 §3.5). Both
11
+ * engine adapters register the wrappers built here, so the two dialects share
12
+ * one set of rules:
13
+ *
14
+ * - arguments become fresh deep-frozen JSON copies (the walker), so a handler
15
+ * can never reach `formData`; writing to one throws `TypeError` in strict mode;
16
+ * - an argument that does not fit the declared parameter type is
17
+ * `EXPRESSION_TYPE_ERROR`, as the engine reports an overload mismatch;
18
+ * - a handler that throws, returns a thenable, or returns something that is
19
+ * not JSON or not its `returnType` is `EXPRESSION_FUNCTION_FAILED`, and its
20
+ * message is never kept: only the function name and the code are logged;
21
+ * - the handler runs inside the evaluation, so its time is charged to the
22
+ * expression budget and a handler that does not finish is interrupted
23
+ * (`EXPRESSION_BUDGET_EXCEEDED`, the interrupt skips every catch here).
24
+ */
25
+ const logger = new common_1.Logger('ExpressionFunction');
26
+ let activeFrame = null;
27
+ /**
28
+ * Runs one engine evaluation and fails it with `EXPRESSION_FUNCTION_FAILED`
29
+ * when any function it called failed, even if the engine absorbed that error.
30
+ */
31
+ const runWithExpressionFunctionFrame = (work) => {
32
+ const previous = activeFrame;
33
+ // Mutable on purpose: the wrappers below flag it while the engine runs.
34
+ const frame = { failed: false };
35
+ activeFrame = frame;
36
+ try {
37
+ const result = work();
38
+ if (frame.failed) {
39
+ throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_FUNCTION_FAILED');
40
+ }
41
+ return result;
42
+ }
43
+ catch (error) {
44
+ if (frame.failed) {
45
+ throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_FUNCTION_FAILED');
46
+ }
47
+ throw error;
48
+ }
49
+ finally {
50
+ activeFrame = previous;
51
+ }
52
+ };
53
+ exports.runWithExpressionFunctionFrame = runWithExpressionFunctionFrame;
54
+ const failFunction = (name, reason) => {
55
+ if (activeFrame !== null) {
56
+ activeFrame.failed = true;
57
+ }
58
+ // The name is the host's validated identifier and the reason a fixed word;
59
+ // neither the handler's message nor any argument is ever written.
60
+ logger.warn(`function=${name} code=EXPRESSION_FUNCTION_FAILED reason=${reason}`);
61
+ throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_FUNCTION_FAILED');
62
+ };
63
+ const refuseArgument = () => {
64
+ throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_TYPE_ERROR');
65
+ };
66
+ const isPlainMap = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
67
+ /** Whether a JSON value is of a declared type. `dyn` accepts any JSON value. */
68
+ const isOfType = (value, type) => {
69
+ switch (type) {
70
+ case 'bool':
71
+ return typeof value === 'boolean';
72
+ case 'double':
73
+ return typeof value === 'number';
74
+ case 'dyn':
75
+ return true;
76
+ case 'int':
77
+ return typeof value === 'number' && Number.isInteger(value);
78
+ case 'list':
79
+ return Array.isArray(value);
80
+ case 'map':
81
+ return isPlainMap(value);
82
+ case 'null':
83
+ return value === null;
84
+ case 'string':
85
+ return typeof value === 'string';
86
+ default:
87
+ return false;
88
+ }
89
+ };
90
+ /**
91
+ * One argument as the handler sees it: a fresh deep-frozen JSON copy (cel-v2
92
+ * `int`s become JS numbers). A value that is not JSON — cel-v2 bytes, a
93
+ * timestamp, a value beyond the result limits — is a type error at the call.
94
+ */
95
+ const readArgument = (name, raw, type) => {
96
+ let value;
97
+ try {
98
+ value = (0, expression_result_walker_1.normalizeExpressionResult)(raw, name, expression_result_walker_1.DEFAULT_EXPRESSION_RESULT_LIMITS);
99
+ }
100
+ catch {
101
+ return refuseArgument();
102
+ }
103
+ return isOfType(value, type) ? value : refuseArgument();
104
+ };
105
+ const isThenable = (value) => (typeof value === 'object' || typeof value === 'function') &&
106
+ value !== null &&
107
+ typeof value.then === 'function';
108
+ const ignoreRejection = () => undefined;
109
+ /**
110
+ * Marks a native promise's rejection as handled, so a rejection nobody awaits
111
+ * does not become an unhandled rejection in the host process.
112
+ *
113
+ * Only a real promise is touched, and through the intrinsic
114
+ * `Promise.prototype.then`: its brand check throws for anything else before
115
+ * any host code runs, and an own `then` the host put on a promise is never
116
+ * called. A foreign thenable is deliberately not adopted — `Promise.resolve`
117
+ * would call its `then` in a later microtask, after the evaluation and outside
118
+ * the budget, where it could block the event loop for as long as it likes.
119
+ * Whatever does run here (a promise subclass's species constructor) runs now,
120
+ * inside the evaluation and its budget.
121
+ */
122
+ const silenceNativeRejection = (value) => {
123
+ try {
124
+ Reflect.apply(Promise.prototype.then, value, [undefined, ignoreRejection]);
125
+ }
126
+ catch {
127
+ // Not a native promise, or a subclass that refused: nothing to silence.
128
+ }
129
+ };
130
+ /**
131
+ * What the engine gets back: the checked JSON result, with a declared `int`
132
+ * turned into a `bigint` for cel-v2, whose `int` is a `bigint` (a JS number
133
+ * there is a `double`, and `int` results would silently compare unequal).
134
+ */
135
+ const toEngineValue = (value, returnType, dialect) => dialect === 'cel-v2' && returnType === 'int' && typeof value === 'number'
136
+ ? BigInt(value)
137
+ : value;
138
+ /**
139
+ * Wraps a registered function for one dialect's engine. The wrapper is what
140
+ * the engine calls; the handler only ever sees checked, frozen arguments.
141
+ */
142
+ const createExpressionFunctionInvoker = (fn, dialect) => (...rawArgs) => {
143
+ // cel-v2 enforces arity through the registered signature; cel-legacy
144
+ // passes whatever was written.
145
+ if (rawArgs.length !== fn.parameters.length) {
146
+ return refuseArgument();
147
+ }
148
+ const args = rawArgs.map((raw, index) => readArgument(fn.name, raw, fn.parameters[index].type));
149
+ let raw;
150
+ let thenable;
151
+ try {
152
+ raw = Reflect.apply(fn.handler, undefined, args);
153
+ // Inside the `try`: reading `then` can run a host getter.
154
+ thenable = isThenable(raw);
155
+ }
156
+ catch {
157
+ // Whatever the handler threw — a `TypeError` from writing to a frozen
158
+ // argument, a host error, even an `ExpressionRuntimeError` that would
159
+ // otherwise pass through with its own label and code — becomes one code.
160
+ return failFunction(fn.name, 'threw');
161
+ }
162
+ if (thenable) {
163
+ // Nobody will await it; without a handler a later rejection would be an
164
+ // unhandled rejection in the host process.
165
+ silenceNativeRejection(raw);
166
+ return failFunction(fn.name, 'thenable');
167
+ }
168
+ let value;
169
+ try {
170
+ value = (0, expression_result_walker_1.normalizeExpressionResult)(raw, fn.name, expression_result_walker_1.DEFAULT_EXPRESSION_RESULT_LIMITS);
171
+ }
172
+ catch {
173
+ return failFunction(fn.name, 'invalid-result');
174
+ }
175
+ return isOfType(value, fn.returnType)
176
+ ? toEngineValue(value, fn.returnType, dialect)
177
+ : failFunction(fn.name, 'return-type');
178
+ };
179
+ exports.createExpressionFunctionInvoker = createExpressionFunctionInvoker;
180
+ const tables = new WeakMap();
181
+ /** Thrown inside the table read when the registry answered out of shape. */
182
+ class RegistryShapeError extends Error {
183
+ }
184
+ const VALUE_TYPES = new Set(expression_function_registry_1.BPM_EXPRESSION_VALUE_TYPES);
185
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
186
+ const refuseShape = () => {
187
+ throw new RegistryShapeError();
188
+ };
189
+ const readValueType = (value) => typeof value === 'string' && VALUE_TYPES.has(value)
190
+ ? value
191
+ : refuseShape();
192
+ /**
193
+ * A frozen copy of what `get` returned for `name`, or a shape refusal. The
194
+ * copy is what the wrappers read, so a registry that changes the object it
195
+ * returned later changes nothing here.
196
+ */
197
+ const readRegisteredFunction = (candidate, name) => {
198
+ if (!isRecord(candidate) || candidate.name !== name) {
199
+ return refuseShape();
200
+ }
201
+ const { description, handler, label, parameters, returnType } = candidate;
202
+ if (typeof handler !== 'function' || !Array.isArray(parameters)) {
203
+ return refuseShape();
204
+ }
205
+ return Object.freeze({
206
+ description: typeof description === 'string' ? description : '',
207
+ handler: handler,
208
+ label: typeof label === 'string' ? label : name,
209
+ name,
210
+ parameters: Object.freeze(parameters.map((parameter) => isRecord(parameter) && typeof parameter.name === 'string'
211
+ ? Object.freeze({
212
+ name: parameter.name,
213
+ type: readValueType(parameter.type),
214
+ })
215
+ : refuseShape())),
216
+ returnType: readValueType(returnType),
217
+ });
218
+ };
219
+ const failRegistry = (reason) => {
220
+ logger.warn(`code=EXPRESSION_FUNCTION_FAILED reason=${reason}`);
221
+ throw new expression_engine_failure_1.ExpressionEngineFailure('EXPRESSION_FUNCTION_FAILED');
222
+ };
223
+ const readListedNames = (listed) => {
224
+ if (!Array.isArray(listed)) {
225
+ return refuseShape();
226
+ }
227
+ const names = listed.map((descriptor) => isRecord(descriptor) &&
228
+ typeof descriptor.name === 'string' &&
229
+ (0, exports.isRegistryFunctionName)(descriptor.name)
230
+ ? descriptor.name
231
+ : refuseShape());
232
+ // A name listed twice would register two overloads of one signature.
233
+ return new Set(names).size === names.length ? names : refuseShape();
234
+ };
235
+ /**
236
+ * Reads every function a registry lists, through `get`, once per registry.
237
+ *
238
+ * The registry is host code (a host may provide its own under
239
+ * `BPM_EXPRESSION_FUNCTION_REGISTRY`). If `list` or `get` throws, or answers
240
+ * out of shape — not a list, a name that is not a function name or is listed
241
+ * twice, `null` for a listed name, an object without a handler or with an
242
+ * unknown type — the evaluation fails with `EXPRESSION_FUNCTION_FAILED`. The
243
+ * host's message is never kept: only a fixed reason is logged. A failure is
244
+ * not cached, so the next evaluation asks the registry again.
245
+ */
246
+ const readExpressionFunctionTable = (registry) => {
247
+ const cached = tables.get(registry);
248
+ if (cached) {
249
+ return cached;
250
+ }
251
+ let functions;
252
+ try {
253
+ functions = Object.freeze(readListedNames(registry.list()).map((name) => readRegisteredFunction(registry.get(name), name)));
254
+ }
255
+ catch (error) {
256
+ return failRegistry(error instanceof RegistryShapeError ? 'registry-shape' : 'registry-threw');
257
+ }
258
+ const table = Object.freeze({
259
+ functions,
260
+ names: new Set(functions.map((fn) => fn.name)),
261
+ });
262
+ tables.set(registry, table);
263
+ return table;
264
+ };
265
+ exports.readExpressionFunctionTable = readExpressionFunctionTable;
266
+ const BUILT_IN_NAMES = new Set(bpm_core_shared_1.BPM_BUILT_IN_EXPRESSION_FUNCTION_NAMES);
267
+ /**
268
+ * Whether a called name is one a registry decides: shaped like a host function
269
+ * (`…_vN`) or one of the nine built-ins. The engine's own functions (`size`,
270
+ * `int`, `matches`, …) never are, and neither is any other unknown name, which
271
+ * keeps the engine's own error (`EXPRESSION_TYPE_ERROR`) at evaluation and is
272
+ * refused outright by the publish lint (docs/24 §2.1, 2026-11-07).
273
+ *
274
+ * The publish lint, the rollback check and {@link callsUnavailableFunction}
275
+ * all read this one rule.
276
+ */
277
+ const isRegistryFunctionName = (name) => BUILT_IN_NAMES.has(name) || bpm_core_shared_1.BPM_EXPRESSION_FUNCTION_NAME_PATTERN.test(name);
278
+ exports.isRegistryFunctionName = isRegistryFunctionName;
279
+ /**
280
+ * Whether an expression calls a function the registry does not have — a host
281
+ * function withdrawn after the version was published, or a built-in a custom
282
+ * registry left out. Only names {@link isRegistryFunctionName} accepts count:
283
+ * any other unknown name keeps the engine's own error, as before functions
284
+ * existed. The caller fails the evaluation with `EXPRESSION_FUNCTION_FAILED`
285
+ * before the engine runs, so the outcome does not depend on which branch the
286
+ * engine would have reached.
287
+ */
288
+ const callsUnavailableFunction = (calledNames, table) => calledNames.some((name) => (0, exports.isRegistryFunctionName)(name) && !table.names.has(name));
289
+ exports.callsUnavailableFunction = callsUnavailableFunction;
290
+ //# sourceMappingURL=expression-function-invocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression-function-invocation.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/condition/expression-function-invocation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
2
+ readonly [key: string]: JsonValue;
3
+ };
4
+ export interface ExpressionResultLimits {
5
+ readonly maxDepth: number;
6
+ readonly maxNodes: number;
7
+ /** Upper bound on the size the value would have as JSON, estimated while walking. */
8
+ readonly maxBytes: number;
9
+ }
10
+ export declare const DEFAULT_EXPRESSION_RESULT_LIMITS: ExpressionResultLimits;
11
+ /**
12
+ * Turns whatever an engine returned into a fresh, deep-frozen JSON value, or
13
+ * throws `EXPRESSION_INVALID_RESULT`. Functions, promises, class instances,
14
+ * `undefined`, non-finite numbers and out-of-range integers are all refused. The
15
+ * size is estimated while walking, not with `JSON.stringify`, so a huge shared
16
+ * string cannot cost much before it is refused.
17
+ */
18
+ export declare const normalizeExpressionResult: (raw: unknown, label: string, limits?: ExpressionResultLimits) => JsonValue;
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeExpressionResult = exports.DEFAULT_EXPRESSION_RESULT_LIMITS = void 0;
4
+ const expression_errors_1 = require("./expression-errors");
5
+ exports.DEFAULT_EXPRESSION_RESULT_LIMITS = {
6
+ maxBytes: 64 * 1024,
7
+ maxDepth: 32,
8
+ maxNodes: 10_000,
9
+ };
10
+ // Writing these as object keys would let a result reach a prototype when a
11
+ // consumer merges it. Rejected at any depth where they are own keys of the
12
+ // value the engine returned. What reaches the walker depends on the engine
13
+ // (verified on both real engines 2026-11-07; differential corpus P43–P45):
14
+ // - cel-legacy (cel-js 0.8.2) builds a map literal by assignment, so
15
+ // `{"constructor": 1}` arrives with that own key and is refused here, and
16
+ // `{"__proto__": {...}}` swaps the prototype and is refused by
17
+ // `isPlainObject`.
18
+ // - cel-v2 (@marcbachmann/cel-js 8.0.0) drops all three keys while building
19
+ // the map, so `{"constructor": 1}` arrives as `{}` and nothing is refused:
20
+ // no pollution, but the key is lost silently instead of failing closed.
21
+ // Refusing it needs the AST, which is P2's (docs/24 §2.5).
22
+ const FORBIDDEN_KEYS = new Set([
23
+ '__proto__',
24
+ 'constructor',
25
+ 'prototype',
26
+ ]);
27
+ const NUMBER_BYTES = 24;
28
+ const LITERAL_BYTES = 5;
29
+ const KEY_OVERHEAD_BYTES = 4;
30
+ /**
31
+ * A map the walker may copy: its prototype is `Object.prototype` or `null`, and
32
+ * it is neither `Object.prototype` itself nor an array. `Object.prototype` has a `null`
33
+ * prototype, so without the second check an engine that handed back the shared
34
+ * prototype would have it accepted as an empty map.
35
+ */
36
+ const isPlainObject = (value) => {
37
+ // An array whose prototype was swapped for Object.prototype is still an
38
+ // array exotic object; it is refused, not copied as a map of indexes.
39
+ if (value === Object.prototype || Array.isArray(value)) {
40
+ return false;
41
+ }
42
+ const prototype = Object.getPrototypeOf(value);
43
+ return prototype === Object.prototype || prototype === null;
44
+ };
45
+ /**
46
+ * A list the walker may copy: a real array whose prototype is
47
+ * `Array.prototype`. `Array.isArray` alone also accepts `Array.prototype`
48
+ * itself, arrays from another realm and arrays whose prototype was replaced.
49
+ */
50
+ const isPlainArray = (value) => Array.isArray(value) &&
51
+ value !== Array.prototype &&
52
+ Object.getPrototypeOf(value) === Array.prototype;
53
+ /**
54
+ * Reads an own property without running code. An accessor is refused rather
55
+ * than called: a getter would run outside the time budget, and what it returns
56
+ * could differ from one read to the next.
57
+ */
58
+ const readDataProperty = (value, key, refuse) => {
59
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
60
+ return descriptor && 'value' in descriptor ? descriptor.value : refuse();
61
+ };
62
+ /**
63
+ * Turns whatever an engine returned into a fresh, deep-frozen JSON value, or
64
+ * throws `EXPRESSION_INVALID_RESULT`. Functions, promises, class instances,
65
+ * `undefined`, non-finite numbers and out-of-range integers are all refused. The
66
+ * size is estimated while walking, not with `JSON.stringify`, so a huge shared
67
+ * string cannot cost much before it is refused.
68
+ */
69
+ const normalizeExpressionResult = (raw, label, limits = exports.DEFAULT_EXPRESSION_RESULT_LIMITS) => {
70
+ // Mutable on purpose: one ledger spans the whole walk, and returning the
71
+ // counts from every recursive call would make the walker harder to read.
72
+ const ledger = { bytes: 0, nodes: 0 };
73
+ const refuse = () => {
74
+ throw new expression_errors_1.ExpressionRuntimeError('EXPRESSION_INVALID_RESULT', label);
75
+ };
76
+ const charge = (bytes) => {
77
+ ledger.bytes += bytes;
78
+ if (ledger.bytes > limits.maxBytes) {
79
+ refuse();
80
+ }
81
+ };
82
+ const walk = (value, depth) => {
83
+ if (depth > limits.maxDepth) {
84
+ refuse();
85
+ }
86
+ ledger.nodes += 1;
87
+ if (ledger.nodes > limits.maxNodes) {
88
+ refuse();
89
+ }
90
+ if (value === null) {
91
+ charge(LITERAL_BYTES);
92
+ return null;
93
+ }
94
+ if (typeof value === 'boolean') {
95
+ charge(LITERAL_BYTES);
96
+ return value;
97
+ }
98
+ if (typeof value === 'number') {
99
+ // Every double beyond 2^53 is an integer, so this is exactly the out-of-
100
+ // safe-range case. cel-legacy returns numbers, not bigints, so this is the
101
+ // branch that actually sees an oversized integer result.
102
+ if (!Number.isFinite(value) ||
103
+ Math.abs(value) > Number.MAX_SAFE_INTEGER) {
104
+ refuse();
105
+ }
106
+ charge(NUMBER_BYTES);
107
+ return value;
108
+ }
109
+ if (typeof value === 'bigint') {
110
+ if (value > BigInt(Number.MAX_SAFE_INTEGER) ||
111
+ value < BigInt(Number.MIN_SAFE_INTEGER)) {
112
+ refuse();
113
+ }
114
+ charge(NUMBER_BYTES);
115
+ return Number(value);
116
+ }
117
+ if (typeof value === 'string') {
118
+ // UTF-8 never takes fewer bytes than UTF-16 code units, so a string longer
119
+ // than the whole allowance is refused before its bytes are counted.
120
+ if (value.length > limits.maxBytes - ledger.bytes) {
121
+ refuse();
122
+ }
123
+ charge(Buffer.byteLength(value, 'utf8'));
124
+ return value;
125
+ }
126
+ if (typeof value === 'object' && isPlainArray(value)) {
127
+ const list = value;
128
+ // Indexes are read as data properties, so a getter on an index (or a hole
129
+ // that would read through to the prototype) is refused, not run.
130
+ return Object.freeze(Array.from({ length: list.length }, (_item, index) => walk(readDataProperty(list, String(index), refuse), depth + 1)));
131
+ }
132
+ if (typeof value === 'object' && value !== null && isPlainObject(value)) {
133
+ // Symbol keys cannot be written as JSON; a value that carries one is not
134
+ // the plain map it looks like.
135
+ if (Object.getOwnPropertySymbols(value).length > 0) {
136
+ refuse();
137
+ }
138
+ const entries = Object.keys(value).map((key) => {
139
+ if (FORBIDDEN_KEYS.has(key)) {
140
+ refuse();
141
+ }
142
+ charge(Buffer.byteLength(key, 'utf8') + KEY_OVERHEAD_BYTES);
143
+ return [key, walk(readDataProperty(value, key, refuse), depth + 1)];
144
+ });
145
+ return Object.freeze(Object.fromEntries(entries));
146
+ }
147
+ return refuse();
148
+ };
149
+ return walk(raw, 0);
150
+ };
151
+ exports.normalizeExpressionResult = normalizeExpressionResult;
152
+ //# sourceMappingURL=expression-result.walker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression-result.walker.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/condition/expression-result.walker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { ExpressionBudget } from './expression-budget';
2
+ import { type JsonValue } from './expression-result.walker';
3
+ import type { BPMExpressionFunctionRegistry } from '../expression-function/expression-function.types';
4
+ import { type ExpressionDialect } from './expression-dialect';
5
+ /** An engine's compiled form of one expression. `native` is never read outside its adapter. */
6
+ export interface ExpressionHandle {
7
+ readonly native: unknown;
8
+ }
9
+ /**
10
+ * One engine behind the runtime. `compile` runs before any budget starts and
11
+ * returns `null` when the expression does not parse. `evaluate` runs inside the
12
+ * budget and may throw whatever the engine throws; the runtime maps it.
13
+ */
14
+ export interface ExpressionEngineAdapter {
15
+ compile(expression: string): ExpressionHandle | null;
16
+ evaluate(handle: ExpressionHandle, roots: Readonly<Record<string, unknown>>): unknown;
17
+ }
18
+ export interface ExpressionEvalRequest {
19
+ readonly expression: string;
20
+ /** Names the use point in errors and logs. Must never contain a context value. */
21
+ readonly label: string;
22
+ /** Only the roots the use point allows. */
23
+ readonly roots: Readonly<Record<string, unknown>>;
24
+ readonly budget: ExpressionBudget;
25
+ /**
26
+ * The engine to evaluate with: the dialect of the definition or rule the
27
+ * expression belongs to. Absent means `cel-legacy` (ADR 22 §3.3).
28
+ */
29
+ readonly dialect?: ExpressionDialect;
30
+ }
31
+ /**
32
+ * The single place where an expression is compiled and evaluated (ADR 22 §3.2).
33
+ * Every caller goes through here: nothing reaches an engine directly.
34
+ *
35
+ * Order: compile (outside any budget, so an interrupt cannot land in module
36
+ * loading), check the budget, evaluate under `runWithinTimeBudget`, normalize
37
+ * the result, and map any failure to an {@link ExpressionRuntimeError}.
38
+ *
39
+ * A timeout raises `EXPRESSION_BUDGET_EXCEEDED`. It never returns `false`: an
40
+ * expression that did not finish is not the same as one that is false.
41
+ */
42
+ export declare class ExpressionRuntime {
43
+ private readonly legacyAdapter;
44
+ private readonly v2Adapter;
45
+ /**
46
+ * Without arguments the runtime calls the nine built-in functions only
47
+ * (ADR 22 §3.5); use {@link ExpressionRuntime.withFunctions} for a host's.
48
+ */
49
+ constructor(legacyAdapter?: ExpressionEngineAdapter, v2Adapter?: ExpressionEngineAdapter);
50
+ /**
51
+ * The runtime for a function registry: both dialects call the functions it
52
+ * lists, through the same argument, result and failure rules. One runtime
53
+ * per registry, cached, so every caller shares its compiled environments.
54
+ * The built-ins-only registry gets the default adapters.
55
+ */
56
+ static withFunctions(registry: BPMExpressionFunctionRegistry): ExpressionRuntime;
57
+ /**
58
+ * Compiles with the dialect's engine. This is also what loads that engine,
59
+ * so callers that compile before starting a budget never have an interrupt
60
+ * land inside module loading.
61
+ */
62
+ compile(expression: string, label: string, dialect?: ExpressionDialect): ExpressionHandle;
63
+ evaluate(request: ExpressionEvalRequest): JsonValue;
64
+ private readAdapter;
65
+ /**
66
+ * Logs only the label, the dialect, the code and the elapsed time. The message, the key
67
+ * name and the expression are not logged: they can carry case data.
68
+ */
69
+ private logFailure;
70
+ }