@rytass/bpm-core-nestjs-module 0.19.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -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 +121 -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-condition-evaluator.js +12 -12
- package/src/lib/workflow-engine/workflow-condition-evaluator.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.service.d.ts +24 -0
- package/src/lib/workflow-engine/workflow-engine.service.js +311 -88
- package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
- package/src/lib/workflow-engine/workflow-form-value.d.ts +11 -0
- package/src/lib/workflow-engine/workflow-form-value.js +33 -0
- package/src/lib/workflow-engine/workflow-form-value.js.map +1 -0
- 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,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var ExpressionFunctionModule_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.ExpressionFunctionModule = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const expression_function_provider_1 = require("./expression-function.provider");
|
|
8
|
+
const expression_function_types_1 = require("./expression-function.types");
|
|
9
|
+
/**
|
|
10
|
+
* Publishes the expression function registry (ADR 22 §3.5) under
|
|
11
|
+
* `BPM_EXPRESSION_FUNCTION_REGISTRY`. Global, because every module that
|
|
12
|
+
* evaluates or lints an expression (`ConditionModule` consumers: templates,
|
|
13
|
+
* the workflow engine, delegation) reads the same registry.
|
|
14
|
+
*/
|
|
15
|
+
let ExpressionFunctionModule = ExpressionFunctionModule_1 = class ExpressionFunctionModule {
|
|
16
|
+
static forRoot(options = {}) {
|
|
17
|
+
return {
|
|
18
|
+
exports: [expression_function_types_1.BPM_EXPRESSION_FUNCTION_REGISTRY],
|
|
19
|
+
global: true,
|
|
20
|
+
imports: [...(options.imports ?? [])],
|
|
21
|
+
module: ExpressionFunctionModule_1,
|
|
22
|
+
providers: [
|
|
23
|
+
...(options.functionsProvider ? [options.functionsProvider] : []),
|
|
24
|
+
expression_function_provider_1.expressionFunctionRegistryProvider,
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
exports.ExpressionFunctionModule = ExpressionFunctionModule;
|
|
30
|
+
exports.ExpressionFunctionModule = ExpressionFunctionModule = ExpressionFunctionModule_1 = tslib_1.__decorate([
|
|
31
|
+
(0, common_1.Global)(),
|
|
32
|
+
(0, common_1.Module)({})
|
|
33
|
+
], ExpressionFunctionModule);
|
|
34
|
+
//# sourceMappingURL=expression-function.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-function.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/expression-function/expression-function.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAMwB;AACxB,iFAAoF;AACpF,2EAGqC;AAcrC;;;;;GAKG;AAGI,IAAM,wBAAwB,gCAA9B,MAAM,wBAAwB;IACnC,MAAM,CAAC,OAAO,CAAC,UAA2C,EAAE;QAC1D,OAAO;YACL,OAAO,EAAE,CAAC,4DAAgC,CAAC;YAC3C,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YACrC,MAAM,EAAE,0BAAwB;YAChC,SAAS,EAAE;gBACT,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjE,iEAAkC;aACnC;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAbY,4DAAwB;mCAAxB,wBAAwB;IAFpC,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,wBAAwB,CAapC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Provider } from '@nestjs/common';
|
|
2
|
+
import { BPMExpressionFunctionRegistry } from './expression-function.types';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the registry every BPM module injects under
|
|
5
|
+
* `BPM_EXPRESSION_FUNCTION_REGISTRY`: the nine built-ins plus the host
|
|
6
|
+
* functions from `BPMRootModule`'s `expressionFunctions` runtime option and
|
|
7
|
+
* from a `BPM_EXPRESSION_FUNCTIONS` provider, in that order. With neither, only
|
|
8
|
+
* the built-ins are available.
|
|
9
|
+
*
|
|
10
|
+
* Every function is validated here, so a bad name, an async handler or an
|
|
11
|
+
* unsupported type fails the host's boot — for `forRoot` and `forRootAsync`
|
|
12
|
+
* alike — instead of the first evaluation that would reach it.
|
|
13
|
+
*
|
|
14
|
+
* Both sources are injected optionally so the module also resolves on its own,
|
|
15
|
+
* outside `BPMRootModule`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const expressionFunctionRegistryProvider: Provider<BPMExpressionFunctionRegistry>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expressionFunctionRegistryProvider = void 0;
|
|
4
|
+
const bpm_root_options_1 = require("../bpm/bpm-root-options");
|
|
5
|
+
const expression_function_registry_1 = require("./expression-function.registry");
|
|
6
|
+
const expression_function_types_1 = require("./expression-function.types");
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the registry every BPM module injects under
|
|
9
|
+
* `BPM_EXPRESSION_FUNCTION_REGISTRY`: the nine built-ins plus the host
|
|
10
|
+
* functions from `BPMRootModule`'s `expressionFunctions` runtime option and
|
|
11
|
+
* from a `BPM_EXPRESSION_FUNCTIONS` provider, in that order. With neither, only
|
|
12
|
+
* the built-ins are available.
|
|
13
|
+
*
|
|
14
|
+
* Every function is validated here, so a bad name, an async handler or an
|
|
15
|
+
* unsupported type fails the host's boot — for `forRoot` and `forRootAsync`
|
|
16
|
+
* alike — instead of the first evaluation that would reach it.
|
|
17
|
+
*
|
|
18
|
+
* Both sources are injected optionally so the module also resolves on its own,
|
|
19
|
+
* outside `BPMRootModule`.
|
|
20
|
+
*/
|
|
21
|
+
exports.expressionFunctionRegistryProvider = {
|
|
22
|
+
inject: [
|
|
23
|
+
{ optional: true, token: bpm_root_options_1.BPM_ROOT_OPTIONS },
|
|
24
|
+
{ optional: true, token: expression_function_types_1.BPM_EXPRESSION_FUNCTIONS },
|
|
25
|
+
],
|
|
26
|
+
provide: expression_function_types_1.BPM_EXPRESSION_FUNCTION_REGISTRY,
|
|
27
|
+
useFactory: (rootOptions, hostFunctions) => {
|
|
28
|
+
const functions = [
|
|
29
|
+
...(rootOptions?.expressionFunctions ?? []),
|
|
30
|
+
...(hostFunctions ?? []),
|
|
31
|
+
];
|
|
32
|
+
// Without host functions every consumer shares the built-ins-only
|
|
33
|
+
// registry, and with it the default engine environments.
|
|
34
|
+
return functions.length === 0
|
|
35
|
+
? expression_function_registry_1.BUILT_IN_EXPRESSION_FUNCTION_REGISTRY
|
|
36
|
+
: new expression_function_registry_1.StaticBPMExpressionFunctionRegistry(functions);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=expression-function.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-function.provider.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/expression-function/expression-function.provider.ts"],"names":[],"mappings":";;;AACA,8DAGiC;AACjC,iFAGwC;AACxC,2EAKqC;AAErC;;;;;;;;;;;;;GAaG;AACU,QAAA,kCAAkC,GAC7C;IACE,MAAM,EAAE;QACN,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,mCAAgB,EAAE;QAC3C,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,oDAAwB,EAAE;KACpD;IACD,OAAO,EAAE,4DAAgC;IACzC,UAAU,EAAE,CACV,WAA8C,EAC9C,aAA2D,EAC5B,EAAE;QACjC,MAAM,SAAS,GAAG;YAChB,GAAG,CAAC,WAAW,EAAE,mBAAmB,IAAI,EAAE,CAAC;YAC3C,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;SACzB,CAAC;QAEF,kEAAkE;QAClE,yDAAyD;QACzD,OAAO,SAAS,CAAC,MAAM,KAAK,CAAC;YAC3B,CAAC,CAAC,oEAAqC;YACvC,CAAC,CAAC,IAAI,kEAAmC,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type BPMExpressionFunctionDescriptor, type BPMExpressionValueType } from '@rytass/bpm-core-shared';
|
|
2
|
+
import type { BPMExpressionFunction, BPMExpressionFunctionRegistry } from './expression-function.types';
|
|
3
|
+
/** Every value type a parameter or a result may declare (ADR 22 §3.5). */
|
|
4
|
+
export declare const BPM_EXPRESSION_VALUE_TYPES: readonly BPMExpressionValueType[];
|
|
5
|
+
/**
|
|
6
|
+
* Validates every host function (ADR 22 §3.5) and returns frozen copies:
|
|
7
|
+
* the name matches `BPM_EXPRESSION_FUNCTION_NAME_PATTERN` and is neither a
|
|
8
|
+
* built-in nor registered twice; the handler is a plain synchronous function;
|
|
9
|
+
* every parameter and the result declare a supported type.
|
|
10
|
+
*
|
|
11
|
+
* Throws a plain `Error` naming the function and the reason, so a host that
|
|
12
|
+
* registers a bad function does not boot.
|
|
13
|
+
*/
|
|
14
|
+
export declare const validateExpressionFunctions: (functions: readonly unknown[]) => readonly BPMExpressionFunction[];
|
|
15
|
+
/**
|
|
16
|
+
* A fixed set of functions: the nine built-ins plus the host functions given
|
|
17
|
+
* at construction, validated there. Lookups are by own key only, so a name
|
|
18
|
+
* such as `constructor` or `toString` is never found on a prototype.
|
|
19
|
+
*/
|
|
20
|
+
export declare class StaticBPMExpressionFunctionRegistry implements BPMExpressionFunctionRegistry {
|
|
21
|
+
private readonly functions;
|
|
22
|
+
private readonly descriptors;
|
|
23
|
+
constructor(hostFunctions?: readonly BPMExpressionFunction[]);
|
|
24
|
+
get(name: string): BPMExpressionFunction | null;
|
|
25
|
+
list(): readonly BPMExpressionFunctionDescriptor[];
|
|
26
|
+
assertPublishable(names: readonly string[]): readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/** Only the nine built-ins: what BPM uses when the host registers no function. */
|
|
29
|
+
export declare class EmptyBPMExpressionFunctionRegistry extends StaticBPMExpressionFunctionRegistry {
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The shared built-ins-only registry. Evaluation falls back to it wherever no
|
|
34
|
+
* registry was handed in, so the built-ins are always available.
|
|
35
|
+
*/
|
|
36
|
+
export declare const BUILT_IN_EXPRESSION_FUNCTION_REGISTRY: BPMExpressionFunctionRegistry;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BUILT_IN_EXPRESSION_FUNCTION_REGISTRY = exports.EmptyBPMExpressionFunctionRegistry = exports.StaticBPMExpressionFunctionRegistry = exports.validateExpressionFunctions = exports.BPM_EXPRESSION_VALUE_TYPES = void 0;
|
|
4
|
+
const node_util_1 = require("node:util");
|
|
5
|
+
const bpm_core_shared_1 = require("@rytass/bpm-core-shared");
|
|
6
|
+
const expression_function_built_ins_1 = require("./expression-function.built-ins");
|
|
7
|
+
/** Every value type a parameter or a result may declare (ADR 22 §3.5). */
|
|
8
|
+
exports.BPM_EXPRESSION_VALUE_TYPES = Object.freeze([
|
|
9
|
+
'bool',
|
|
10
|
+
'double',
|
|
11
|
+
'dyn',
|
|
12
|
+
'int',
|
|
13
|
+
'list',
|
|
14
|
+
'map',
|
|
15
|
+
'null',
|
|
16
|
+
'string',
|
|
17
|
+
]);
|
|
18
|
+
const VALUE_TYPES = new Set(exports.BPM_EXPRESSION_VALUE_TYPES);
|
|
19
|
+
const BUILT_IN_NAMES = new Set(bpm_core_shared_1.BPM_BUILT_IN_EXPRESSION_FUNCTION_NAMES);
|
|
20
|
+
const PARAMETER_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
21
|
+
/*
|
|
22
|
+
* cel-js 0.8.2 (cel-legacy) lexes `true`, `false` and `null` without a word
|
|
23
|
+
* boundary and ahead of identifiers, so `nullable_v1(1)` is read as `null`
|
|
24
|
+
* followed by `able_v1` — a syntax error. cel-v2 has no such problem, but a
|
|
25
|
+
* host function must work in both dialects, so the name is refused here.
|
|
26
|
+
* (`in` is lexed with a boundary; `inRange_v1` is fine.)
|
|
27
|
+
*/
|
|
28
|
+
const CEL_LEGACY_KEYWORD_PREFIX = /^(?:true|false|null)/u;
|
|
29
|
+
/*
|
|
30
|
+
* `async function`, `function*` and `async function*` all return something a
|
|
31
|
+
* synchronous evaluation cannot use.
|
|
32
|
+
*
|
|
33
|
+
* The primary check is the engine's own function kind (`util.types`): it is
|
|
34
|
+
* fixed when the function is created, so neither `Object.setPrototypeOf` nor
|
|
35
|
+
* an own `Symbol.toStringTag` changes it, and it holds across realms. It does
|
|
36
|
+
* not see through `bind`, so the prototype chain is checked too: every such
|
|
37
|
+
* function inherits from the intrinsic `AsyncFunction.prototype`,
|
|
38
|
+
* `GeneratorFunction.prototype` or `AsyncGeneratorFunction.prototype` of this
|
|
39
|
+
* realm, and a bound copy keeps that prototype. The tag is a last check for a
|
|
40
|
+
* bound handler from another realm.
|
|
41
|
+
*
|
|
42
|
+
* A bound copy whose prototype was also moved to `Function.prototype` and
|
|
43
|
+
* re-tagged still passes all three; such a handler returns a promise, which
|
|
44
|
+
* the call wrapper refuses as `EXPRESSION_FUNCTION_FAILED` (fail closed).
|
|
45
|
+
*/
|
|
46
|
+
const REFUSED_FUNCTION_PROTOTYPES = [
|
|
47
|
+
Object.getPrototypeOf(async () => undefined),
|
|
48
|
+
Object.getPrototypeOf(function* refusedGenerator() {
|
|
49
|
+
// Never called: only its prototype is read.
|
|
50
|
+
}),
|
|
51
|
+
Object.getPrototypeOf(async function* refusedAsyncGenerator() {
|
|
52
|
+
// Never called: only its prototype is read.
|
|
53
|
+
}),
|
|
54
|
+
// A build that compiled these down to plain functions would yield
|
|
55
|
+
// `Function.prototype`, which every handler inherits from: never compare to it.
|
|
56
|
+
].filter((prototype) => prototype !== Function.prototype);
|
|
57
|
+
const REFUSED_FUNCTION_TAGS = new Set([
|
|
58
|
+
'[object AsyncFunction]',
|
|
59
|
+
'[object AsyncGeneratorFunction]',
|
|
60
|
+
'[object GeneratorFunction]',
|
|
61
|
+
]);
|
|
62
|
+
const isAsyncOrGenerator = (handler) => node_util_1.types.isAsyncFunction(handler) ||
|
|
63
|
+
node_util_1.types.isGeneratorFunction(handler) ||
|
|
64
|
+
REFUSED_FUNCTION_PROTOTYPES.some((prototype) => Object.prototype.isPrototypeOf.call(prototype, handler)) ||
|
|
65
|
+
REFUSED_FUNCTION_TAGS.has(Object.prototype.toString.call(handler));
|
|
66
|
+
const PREFIX = '[@rytass/bpm-core-nestjs-module]';
|
|
67
|
+
const refuse = (name, reason) => {
|
|
68
|
+
throw new Error(`${PREFIX} Expression function "${name}" ${reason}.`);
|
|
69
|
+
};
|
|
70
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
71
|
+
const readDisplayName = (candidate, index) => isRecord(candidate) && typeof candidate.name === 'string'
|
|
72
|
+
? candidate.name
|
|
73
|
+
: `#${index}`;
|
|
74
|
+
const readParameter = (name, candidate, index) => {
|
|
75
|
+
if (!isRecord(candidate)) {
|
|
76
|
+
return refuse(name, `has parameter ${index} that is not an object`);
|
|
77
|
+
}
|
|
78
|
+
if (typeof candidate.name !== 'string' ||
|
|
79
|
+
!PARAMETER_NAME_PATTERN.test(candidate.name)) {
|
|
80
|
+
return refuse(name, `has parameter ${index} without a valid name`);
|
|
81
|
+
}
|
|
82
|
+
if (typeof candidate.type !== 'string' || !VALUE_TYPES.has(candidate.type)) {
|
|
83
|
+
return refuse(name, `declares parameter "${candidate.name}" with an unsupported type (expected one of ${exports.BPM_EXPRESSION_VALUE_TYPES.join(', ')})`);
|
|
84
|
+
}
|
|
85
|
+
const { description } = candidate;
|
|
86
|
+
if (description !== undefined && typeof description !== 'string') {
|
|
87
|
+
return refuse(name, `declares parameter "${candidate.name}" with a description that is not a string`);
|
|
88
|
+
}
|
|
89
|
+
return Object.freeze({
|
|
90
|
+
...(typeof description === 'string' ? { description } : {}),
|
|
91
|
+
name: candidate.name,
|
|
92
|
+
type: candidate.type,
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Checks one host function and returns a frozen copy of it. Throws a plain
|
|
97
|
+
* `Error` naming the function and the reason; the host's boot fails with it.
|
|
98
|
+
* Uniqueness across the list is checked by {@link validateExpressionFunctions}.
|
|
99
|
+
*/
|
|
100
|
+
const validateExpressionFunction = (candidate, index) => {
|
|
101
|
+
const displayName = readDisplayName(candidate, index);
|
|
102
|
+
if (!isRecord(candidate)) {
|
|
103
|
+
return refuse(displayName, 'is not an object');
|
|
104
|
+
}
|
|
105
|
+
const { description, handler, label, name, parameters, returnType } = candidate;
|
|
106
|
+
if (typeof name !== 'string') {
|
|
107
|
+
return refuse(displayName, 'has no name');
|
|
108
|
+
}
|
|
109
|
+
if (BUILT_IN_NAMES.has(name)) {
|
|
110
|
+
return refuse(name, 'uses the name of a built-in function');
|
|
111
|
+
}
|
|
112
|
+
// The pattern also keeps a host name clear of every cel-v2 built-in and CEL
|
|
113
|
+
// keyword: none of them ends in `_v<digits>`.
|
|
114
|
+
if (!bpm_core_shared_1.BPM_EXPRESSION_FUNCTION_NAME_PATTERN.test(name)) {
|
|
115
|
+
return refuse(name, 'has an invalid name (lower camel segments joined by "_", ending in a version such as "_v1")');
|
|
116
|
+
}
|
|
117
|
+
if (CEL_LEGACY_KEYWORD_PREFIX.test(name)) {
|
|
118
|
+
return refuse(name, 'starts with "true", "false" or "null", which cel-legacy reads as a keyword; such a name can never be called there');
|
|
119
|
+
}
|
|
120
|
+
if (typeof handler !== 'function') {
|
|
121
|
+
return refuse(name, 'has no handler function');
|
|
122
|
+
}
|
|
123
|
+
if (isAsyncOrGenerator(handler)) {
|
|
124
|
+
return refuse(name, 'has an async or generator handler; handlers must be synchronous');
|
|
125
|
+
}
|
|
126
|
+
if (typeof label !== 'string' || !label.trim()) {
|
|
127
|
+
return refuse(name, 'has no label');
|
|
128
|
+
}
|
|
129
|
+
if (typeof description !== 'string') {
|
|
130
|
+
return refuse(name, 'has no description');
|
|
131
|
+
}
|
|
132
|
+
if (!Array.isArray(parameters)) {
|
|
133
|
+
return refuse(name, 'has no parameter list');
|
|
134
|
+
}
|
|
135
|
+
if (typeof returnType !== 'string' || !VALUE_TYPES.has(returnType)) {
|
|
136
|
+
return refuse(name, `declares an unsupported return type (expected one of ${exports.BPM_EXPRESSION_VALUE_TYPES.join(', ')})`);
|
|
137
|
+
}
|
|
138
|
+
const checkedParameters = Object.freeze(parameters.map((parameter, parameterIndex) => readParameter(name, parameter, parameterIndex)));
|
|
139
|
+
const parameterNames = checkedParameters.map((parameter) => parameter.name);
|
|
140
|
+
if (new Set(parameterNames).size !== parameterNames.length) {
|
|
141
|
+
return refuse(name, 'declares the same parameter name twice');
|
|
142
|
+
}
|
|
143
|
+
return Object.freeze({
|
|
144
|
+
description,
|
|
145
|
+
handler: handler,
|
|
146
|
+
label,
|
|
147
|
+
name,
|
|
148
|
+
parameters: checkedParameters,
|
|
149
|
+
returnType: returnType,
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Validates every host function (ADR 22 §3.5) and returns frozen copies:
|
|
154
|
+
* the name matches `BPM_EXPRESSION_FUNCTION_NAME_PATTERN` and is neither a
|
|
155
|
+
* built-in nor registered twice; the handler is a plain synchronous function;
|
|
156
|
+
* every parameter and the result declare a supported type.
|
|
157
|
+
*
|
|
158
|
+
* Throws a plain `Error` naming the function and the reason, so a host that
|
|
159
|
+
* registers a bad function does not boot.
|
|
160
|
+
*/
|
|
161
|
+
const validateExpressionFunctions = (functions) => {
|
|
162
|
+
if (!Array.isArray(functions)) {
|
|
163
|
+
throw new Error(`${PREFIX} Expression functions must be given as an array.`);
|
|
164
|
+
}
|
|
165
|
+
const checked = functions.map(validateExpressionFunction);
|
|
166
|
+
checked.reduce((seen, fn) => {
|
|
167
|
+
if (seen.has(fn.name)) {
|
|
168
|
+
refuse(fn.name, 'is registered more than once');
|
|
169
|
+
}
|
|
170
|
+
return new Set([...seen, fn.name]);
|
|
171
|
+
}, new Set());
|
|
172
|
+
return Object.freeze(checked);
|
|
173
|
+
};
|
|
174
|
+
exports.validateExpressionFunctions = validateExpressionFunctions;
|
|
175
|
+
const toDescriptor = (fn, builtIn) => Object.freeze({
|
|
176
|
+
builtIn,
|
|
177
|
+
description: fn.description,
|
|
178
|
+
label: fn.label,
|
|
179
|
+
name: fn.name,
|
|
180
|
+
parameters: fn.parameters,
|
|
181
|
+
returnType: fn.returnType,
|
|
182
|
+
});
|
|
183
|
+
const BUILT_INS = validateBuiltIns();
|
|
184
|
+
/**
|
|
185
|
+
* The built-ins go through the same shape checks as host functions, except
|
|
186
|
+
* the name rule they are exempt from, so a mistake in them fails at import.
|
|
187
|
+
*/
|
|
188
|
+
function validateBuiltIns() {
|
|
189
|
+
return Object.freeze(expression_function_built_ins_1.BPM_BUILT_IN_EXPRESSION_FUNCTIONS.map((fn) => Object.freeze({
|
|
190
|
+
...fn,
|
|
191
|
+
parameters: Object.freeze(fn.parameters.map((parameter, index) => readParameter(fn.name, parameter, index))),
|
|
192
|
+
})));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* A fixed set of functions: the nine built-ins plus the host functions given
|
|
196
|
+
* at construction, validated there. Lookups are by own key only, so a name
|
|
197
|
+
* such as `constructor` or `toString` is never found on a prototype.
|
|
198
|
+
*/
|
|
199
|
+
class StaticBPMExpressionFunctionRegistry {
|
|
200
|
+
constructor(hostFunctions = []) {
|
|
201
|
+
const host = (0, exports.validateExpressionFunctions)(hostFunctions);
|
|
202
|
+
this.functions = new Map([...BUILT_INS, ...host].map((fn) => [fn.name, fn]));
|
|
203
|
+
this.descriptors = Object.freeze([
|
|
204
|
+
...BUILT_INS.map((fn) => toDescriptor(fn, true)),
|
|
205
|
+
...host.map((fn) => toDescriptor(fn, false)),
|
|
206
|
+
]);
|
|
207
|
+
}
|
|
208
|
+
get(name) {
|
|
209
|
+
return this.functions.get(name) ?? null;
|
|
210
|
+
}
|
|
211
|
+
list() {
|
|
212
|
+
return this.descriptors;
|
|
213
|
+
}
|
|
214
|
+
assertPublishable(names) {
|
|
215
|
+
return [...new Set(names)].filter((name) => !this.functions.has(name));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.StaticBPMExpressionFunctionRegistry = StaticBPMExpressionFunctionRegistry;
|
|
219
|
+
/** Only the nine built-ins: what BPM uses when the host registers no function. */
|
|
220
|
+
class EmptyBPMExpressionFunctionRegistry extends StaticBPMExpressionFunctionRegistry {
|
|
221
|
+
constructor() {
|
|
222
|
+
super([]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.EmptyBPMExpressionFunctionRegistry = EmptyBPMExpressionFunctionRegistry;
|
|
226
|
+
/**
|
|
227
|
+
* The shared built-ins-only registry. Evaluation falls back to it wherever no
|
|
228
|
+
* registry was handed in, so the built-ins are always available.
|
|
229
|
+
*/
|
|
230
|
+
exports.BUILT_IN_EXPRESSION_FUNCTION_REGISTRY = new EmptyBPMExpressionFunctionRegistry();
|
|
231
|
+
//# sourceMappingURL=expression-function.registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-function.registry.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/expression-function/expression-function.registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BPMExpressionFunctionDescriptor, BPMExpressionValue } from '@rytass/bpm-core-shared';
|
|
2
|
+
/**
|
|
3
|
+
* A function an expression may call (ADR 22 §3.5). The handler is host code:
|
|
4
|
+
* it must be synchronous and pure, and only ever sees deep-frozen copies of
|
|
5
|
+
* its arguments. The core never passes it an auth context.
|
|
6
|
+
*/
|
|
7
|
+
export interface BPMExpressionFunction extends Omit<BPMExpressionFunctionDescriptor, 'builtIn'> {
|
|
8
|
+
readonly handler: (...args: readonly BPMExpressionValue[]) => BPMExpressionValue;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The functions available to expressions: the core built-ins plus whatever
|
|
12
|
+
* the host registered. Shared contract between the publish lint (P2) and the
|
|
13
|
+
* registry implementation (P3); see docs/24 §3.
|
|
14
|
+
*/
|
|
15
|
+
export interface BPMExpressionFunctionRegistry {
|
|
16
|
+
/** The function registered under `name`, or `null`. */
|
|
17
|
+
get(name: string): BPMExpressionFunction | null;
|
|
18
|
+
/** Descriptors of every available function, built-ins first. */
|
|
19
|
+
list(): readonly BPMExpressionFunctionDescriptor[];
|
|
20
|
+
/**
|
|
21
|
+
* The names among `names` that are not available, in their first-seen
|
|
22
|
+
* order and without duplicates. An empty result means all are available;
|
|
23
|
+
* publish and rollback refuse a version whose result is not empty.
|
|
24
|
+
*/
|
|
25
|
+
assertPublishable(names: readonly string[]): readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/** Host-provided functions, as a multi-value list. Unset means none. */
|
|
28
|
+
export declare const BPM_EXPRESSION_FUNCTIONS: unique symbol;
|
|
29
|
+
/** The resolved registry the core injects. */
|
|
30
|
+
export declare const BPM_EXPRESSION_FUNCTION_REGISTRY: unique symbol;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BPM_EXPRESSION_FUNCTION_REGISTRY = exports.BPM_EXPRESSION_FUNCTIONS = void 0;
|
|
4
|
+
/** Host-provided functions, as a multi-value list. Unset means none. */
|
|
5
|
+
exports.BPM_EXPRESSION_FUNCTIONS = Symbol('BPM_EXPRESSION_FUNCTIONS');
|
|
6
|
+
/** The resolved registry the core injects. */
|
|
7
|
+
exports.BPM_EXPRESSION_FUNCTION_REGISTRY = Symbol('BPM_EXPRESSION_FUNCTION_REGISTRY');
|
|
8
|
+
//# sourceMappingURL=expression-function.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-function.types.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/expression-function/expression-function.types.ts"],"names":[],"mappings":";;;AAqCA,wEAAwE;AAC3D,QAAA,wBAAwB,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC;AAE3E,8CAA8C;AACjC,QAAA,gCAAgC,GAAG,MAAM,CACpD,kCAAkC,CACnC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./expression-function.built-ins"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./expression-function.module"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./expression-function.provider"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./expression-function.registry"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./expression-function.types"), exports);
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/expression-function/index.ts"],"names":[],"mappings":";;;AAAA,0EAAgD;AAChD,uEAA6C;AAC7C,yEAA+C;AAC/C,yEAA+C;AAC/C,sEAA4C"}
|
|
@@ -6,6 +6,9 @@ exports.lintFormSchemaJson = lintFormSchemaJson;
|
|
|
6
6
|
const form_1 = require("@rytass/bpm-core-shared/form");
|
|
7
7
|
const form_org_unit_value_validator_1 = require("./form-org-unit-value.validator");
|
|
8
8
|
const form_table_reference_1 = require("./form-table-reference");
|
|
9
|
+
const form_data_source_expression_1 = require("../form-data-source/form-data-source.expression");
|
|
10
|
+
/** The longest `EXPRESSION` binding the runtime evaluates (ConditionService). */
|
|
11
|
+
const MAX_EXPRESSION_BINDING_LENGTH = 2000;
|
|
9
12
|
const SUPPORTED_FIELD_TYPES = [
|
|
10
13
|
'boolean',
|
|
11
14
|
'checkbox',
|
|
@@ -466,7 +469,30 @@ function lintDataSourceBinding(value, path, scope) {
|
|
|
466
469
|
: []),
|
|
467
470
|
];
|
|
468
471
|
}
|
|
469
|
-
|
|
472
|
+
// Only the shape here: a draft with a half-written expression must still
|
|
473
|
+
// save. Its cel-v2 lint (roots, functions, field types, the parameter's
|
|
474
|
+
// type) needs the DataSource descriptor and runs with the registry check at
|
|
475
|
+
// publish (`FormDataSourceService.lintDefinitionSchemaEnvironment`).
|
|
476
|
+
if (from.kind === 'EXPRESSION') {
|
|
477
|
+
// A blank expression is a draft the designer has not written yet; the
|
|
478
|
+
// publish lint refuses it (`EXPR_PARSE_FAILED`).
|
|
479
|
+
return [
|
|
480
|
+
...errors,
|
|
481
|
+
...(typeof from.expression === 'string'
|
|
482
|
+
? []
|
|
483
|
+
: [`${path}.from.expression must be a string`]),
|
|
484
|
+
...(typeof from.expression === 'string' &&
|
|
485
|
+
from.expression.trim().length > MAX_EXPRESSION_BINDING_LENGTH
|
|
486
|
+
? [
|
|
487
|
+
`${path}.from.expression must be ${MAX_EXPRESSION_BINDING_LENGTH} characters or fewer`,
|
|
488
|
+
]
|
|
489
|
+
: []),
|
|
490
|
+
];
|
|
491
|
+
}
|
|
492
|
+
return [
|
|
493
|
+
...errors,
|
|
494
|
+
`${path}.from.kind must be FIELD, CONSTANT, ROW_FIELD, or EXPRESSION`,
|
|
495
|
+
];
|
|
470
496
|
}
|
|
471
497
|
function lintFieldBindingTarget(fieldKey, path, scope) {
|
|
472
498
|
if (typeof fieldKey !== 'string') {
|
|
@@ -752,8 +778,7 @@ function lintHiddenDataSourceDependencies(fields) {
|
|
|
752
778
|
.filter((fieldKey) => typeof fieldKey === 'string'));
|
|
753
779
|
const message = (path, dependencyKey) => `${path}.dataSource 所屬欄位為 hidden,只能綁定同為 hidden 的欄位,不可綁定顯示中的欄位:${dependencyKey}`;
|
|
754
780
|
const readVisibleDependencies = (owner) => readBindingSources(owner)
|
|
755
|
-
.
|
|
756
|
-
.map((from) => from.fieldKey)
|
|
781
|
+
.flatMap(readTopLevelBindingDependencies)
|
|
757
782
|
.filter((dependencyKey) => typeof dependencyKey === 'string' && visibleKeys.has(dependencyKey));
|
|
758
783
|
return fields.flatMap((field, index) => {
|
|
759
784
|
if (!isRecord(field) || field.hidden !== true) {
|
|
@@ -791,13 +816,26 @@ function readFieldDependencyEntries(field) {
|
|
|
791
816
|
[
|
|
792
817
|
`top:${fieldKey}`,
|
|
793
818
|
readBindingSources(field)
|
|
794
|
-
.
|
|
795
|
-
.map((from) => from.fieldKey)
|
|
796
|
-
.filter((dependencyKey) => typeof dependencyKey === 'string')
|
|
819
|
+
.flatMap(readTopLevelBindingDependencies)
|
|
797
820
|
.map((dependencyKey) => `top:${dependencyKey}`),
|
|
798
821
|
],
|
|
799
822
|
];
|
|
800
823
|
}
|
|
824
|
+
/**
|
|
825
|
+
* The top-level fields a binding reads: a `FIELD`'s key, or every `form.<key>`
|
|
826
|
+
* an `EXPRESSION` reads, from its AST (ADR 22 §3.7). The lint refuses dynamic
|
|
827
|
+
* access, so this is the whole dependency set; an expression that does not
|
|
828
|
+
* parse adds no edge here and is refused by the publish lint instead.
|
|
829
|
+
*/
|
|
830
|
+
function readTopLevelBindingDependencies(from) {
|
|
831
|
+
if (from.kind === 'FIELD') {
|
|
832
|
+
return typeof from.fieldKey === 'string' ? [from.fieldKey] : [];
|
|
833
|
+
}
|
|
834
|
+
if (from.kind === 'EXPRESSION' && typeof from.expression === 'string') {
|
|
835
|
+
return (0, form_data_source_expression_1.readExpressionBindingDependencies)(from.expression)?.formFieldKeys ?? [];
|
|
836
|
+
}
|
|
837
|
+
return [];
|
|
838
|
+
}
|
|
801
839
|
function readColumnDependencyNode(from, tableKey) {
|
|
802
840
|
if (from.kind === 'FIELD' && typeof from.fieldKey === 'string') {
|
|
803
841
|
return [`top:${from.fieldKey}`];
|
|
@@ -805,6 +843,15 @@ function readColumnDependencyNode(from, tableKey) {
|
|
|
805
843
|
if (from.kind === 'ROW_FIELD' && typeof from.columnKey === 'string') {
|
|
806
844
|
return [`col:${tableKey}.${from.columnKey}`];
|
|
807
845
|
}
|
|
846
|
+
if (from.kind === 'EXPRESSION' && typeof from.expression === 'string') {
|
|
847
|
+
const dependencies = (0, form_data_source_expression_1.readExpressionBindingDependencies)(from.expression);
|
|
848
|
+
return dependencies
|
|
849
|
+
? [
|
|
850
|
+
...dependencies.formFieldKeys.map((key) => `top:${key}`),
|
|
851
|
+
...dependencies.rowColumnKeys.map((key) => `col:${tableKey}.${key}`),
|
|
852
|
+
]
|
|
853
|
+
: [];
|
|
854
|
+
}
|
|
808
855
|
return [];
|
|
809
856
|
}
|
|
810
857
|
function readBindingSources(field) {
|