n8n-workflow 2.31.1 → 2.32.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/dist/cjs/augment-object.js +136 -146
- package/dist/cjs/augment-object.js.map +1 -1
- package/dist/cjs/build.tsbuildinfo +1 -1
- package/dist/cjs/common/find-ai-root-node-names.js +36 -46
- package/dist/cjs/common/find-ai-root-node-names.js.map +1 -1
- package/dist/cjs/common/get-child-nodes.js +8 -18
- package/dist/cjs/common/get-child-nodes.js.map +1 -1
- package/dist/cjs/common/get-connected-nodes.js +84 -94
- package/dist/cjs/common/get-connected-nodes.js.map +1 -1
- package/dist/cjs/common/get-node-by-name.js +16 -26
- package/dist/cjs/common/get-node-by-name.js.map +1 -1
- package/dist/cjs/common/get-parent-nodes.js +14 -24
- package/dist/cjs/common/get-parent-nodes.js.map +1 -1
- package/dist/cjs/common/index.js +9 -19
- package/dist/cjs/common/index.js.map +1 -1
- package/dist/cjs/common/map-connections-by-destination.js +31 -41
- package/dist/cjs/common/map-connections-by-destination.js.map +1 -1
- package/dist/cjs/common/resolve-variables.d.ts +8 -0
- package/dist/cjs/common/resolve-variables.d.ts.map +1 -1
- package/dist/cjs/common/resolve-variables.js +46 -33
- package/dist/cjs/common/resolve-variables.js.map +1 -1
- package/dist/cjs/connections-diff.js +58 -68
- package/dist/cjs/connections-diff.js.map +1 -1
- package/dist/cjs/constants.d.ts +3 -3
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +157 -166
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/credential-domain-restrictions.js +153 -163
- package/dist/cjs/credential-domain-restrictions.js.map +1 -1
- package/dist/cjs/cron.d.ts.map +1 -1
- package/dist/cjs/cron.js +25 -35
- package/dist/cjs/cron.js.map +1 -1
- package/dist/cjs/data-table.types.js +10 -20
- package/dist/cjs/data-table.types.js.map +1 -1
- package/dist/cjs/dynamic-credentials-helpers.js +93 -103
- package/dist/cjs/dynamic-credentials-helpers.js.map +1 -1
- package/dist/cjs/errors/abstract/execution-base.error.d.ts.map +1 -1
- package/dist/cjs/errors/abstract/execution-base.error.js +41 -51
- package/dist/cjs/errors/abstract/execution-base.error.js.map +1 -1
- package/dist/cjs/errors/abstract/node.error.d.ts.map +1 -1
- package/dist/cjs/errors/abstract/node.error.js +142 -152
- package/dist/cjs/errors/abstract/node.error.js.map +1 -1
- package/dist/cjs/errors/base/base.error.d.ts.map +1 -1
- package/dist/cjs/errors/base/base.error.js +35 -45
- package/dist/cjs/errors/base/base.error.js.map +1 -1
- package/dist/cjs/errors/base/operational.error.d.ts.map +1 -1
- package/dist/cjs/errors/base/operational.error.js +17 -27
- package/dist/cjs/errors/base/operational.error.js.map +1 -1
- package/dist/cjs/errors/base/unexpected.error.d.ts.map +1 -1
- package/dist/cjs/errors/base/unexpected.error.js +17 -27
- package/dist/cjs/errors/base/unexpected.error.js.map +1 -1
- package/dist/cjs/errors/base/user.error.d.ts.map +1 -1
- package/dist/cjs/errors/base/user.error.js +17 -27
- package/dist/cjs/errors/base/user.error.js.map +1 -1
- package/dist/cjs/errors/cli-subworkflow-operation.error.js +7 -17
- package/dist/cjs/errors/cli-subworkflow-operation.error.js.map +1 -1
- package/dist/cjs/errors/db-connection-timeout-error.d.ts.map +1 -1
- package/dist/cjs/errors/db-connection-timeout-error.js +11 -21
- package/dist/cjs/errors/db-connection-timeout-error.js.map +1 -1
- package/dist/cjs/errors/execution-cancelled.error.d.ts.map +1 -1
- package/dist/cjs/errors/execution-cancelled.error.js +33 -43
- package/dist/cjs/errors/execution-cancelled.error.js.map +1 -1
- package/dist/cjs/errors/expression-class-extension.error.d.ts.map +1 -1
- package/dist/cjs/errors/expression-class-extension.error.js +9 -19
- package/dist/cjs/errors/expression-class-extension.error.js.map +1 -1
- package/dist/cjs/errors/expression-computed-destructuring.error.d.ts.map +1 -1
- package/dist/cjs/errors/expression-computed-destructuring.error.js +9 -19
- package/dist/cjs/errors/expression-computed-destructuring.error.js.map +1 -1
- package/dist/cjs/errors/expression-destructuring.error.d.ts.map +1 -1
- package/dist/cjs/errors/expression-destructuring.error.js +9 -19
- package/dist/cjs/errors/expression-destructuring.error.js.map +1 -1
- package/dist/cjs/errors/expression-extension.error.js +7 -17
- package/dist/cjs/errors/expression-extension.error.js.map +1 -1
- package/dist/cjs/errors/expression-reserved-variable.error.d.ts.map +1 -1
- package/dist/cjs/errors/expression-reserved-variable.error.js +9 -19
- package/dist/cjs/errors/expression-reserved-variable.error.js.map +1 -1
- package/dist/cjs/errors/expression-with-statement.error.d.ts.map +1 -1
- package/dist/cjs/errors/expression-with-statement.error.js +9 -19
- package/dist/cjs/errors/expression-with-statement.error.js.map +1 -1
- package/dist/cjs/errors/expression.error.d.ts.map +1 -1
- package/dist/cjs/errors/expression.error.js +33 -43
- package/dist/cjs/errors/expression.error.js.map +1 -1
- package/dist/cjs/errors/index.js +62 -72
- package/dist/cjs/errors/index.js.map +1 -1
- package/dist/cjs/errors/node-api.error.d.ts.map +1 -1
- package/dist/cjs/errors/node-api.error.js +227 -237
- package/dist/cjs/errors/node-api.error.js.map +1 -1
- package/dist/cjs/errors/node-operation.error.d.ts.map +1 -1
- package/dist/cjs/errors/node-operation.error.js +43 -53
- package/dist/cjs/errors/node-operation.error.js.map +1 -1
- package/dist/cjs/errors/node-ssl.error.d.ts.map +1 -1
- package/dist/cjs/errors/node-ssl.error.js +9 -19
- package/dist/cjs/errors/node-ssl.error.js.map +1 -1
- package/dist/cjs/errors/subworkflow-operation.error.d.ts.map +1 -1
- package/dist/cjs/errors/subworkflow-operation.error.js +18 -28
- package/dist/cjs/errors/subworkflow-operation.error.js.map +1 -1
- package/dist/cjs/errors/trigger-close.error.d.ts.map +1 -1
- package/dist/cjs/errors/trigger-close.error.js +11 -21
- package/dist/cjs/errors/trigger-close.error.js.map +1 -1
- package/dist/cjs/errors/webhook-taken.error.d.ts.map +1 -1
- package/dist/cjs/errors/webhook-taken.error.js +9 -19
- package/dist/cjs/errors/webhook-taken.error.js.map +1 -1
- package/dist/cjs/errors/workflow-activation.error.d.ts.map +1 -1
- package/dist/cjs/errors/workflow-activation.error.js +54 -64
- package/dist/cjs/errors/workflow-activation.error.js.map +1 -1
- package/dist/cjs/errors/workflow-configuration.error.js +10 -20
- package/dist/cjs/errors/workflow-configuration.error.js.map +1 -1
- package/dist/cjs/errors/workflow-deactivation.error.js +7 -17
- package/dist/cjs/errors/workflow-deactivation.error.js.map +1 -1
- package/dist/cjs/errors/workflow-operation.error.d.ts.map +1 -1
- package/dist/cjs/errors/workflow-operation.error.js +20 -30
- package/dist/cjs/errors/workflow-operation.error.js.map +1 -1
- package/dist/cjs/evaluation-helpers.js +16 -26
- package/dist/cjs/evaluation-helpers.js.map +1 -1
- package/dist/cjs/execution-context-establishment-hooks.d.ts.map +1 -1
- package/dist/cjs/execution-context-establishment-hooks.js +43 -49
- package/dist/cjs/execution-context-establishment-hooks.js.map +1 -1
- package/dist/cjs/execution-context.d.ts +14 -14
- package/dist/cjs/execution-context.d.ts.map +1 -1
- package/dist/cjs/execution-context.js +203 -213
- package/dist/cjs/execution-context.js.map +1 -1
- package/dist/cjs/execution-status.d.ts +2 -2
- package/dist/cjs/execution-status.d.ts.map +1 -1
- package/dist/cjs/execution-status.js +27 -37
- package/dist/cjs/execution-status.js.map +1 -1
- package/dist/cjs/expression-evaluator-proxy.d.ts.map +1 -1
- package/dist/cjs/expression-evaluator-proxy.js +18 -28
- package/dist/cjs/expression-evaluator-proxy.js.map +1 -1
- package/dist/cjs/expression-sandboxing.d.ts.map +1 -1
- package/dist/cjs/expression-sandboxing.js +447 -457
- package/dist/cjs/expression-sandboxing.js.map +1 -1
- package/dist/cjs/expression.d.ts.map +1 -1
- package/dist/cjs/expression.js +535 -546
- package/dist/cjs/expression.js.map +1 -1
- package/dist/cjs/expressions/expression-helpers.d.ts.map +1 -1
- package/dist/cjs/expressions/expression-helpers.js +13 -23
- package/dist/cjs/expressions/expression-helpers.js.map +1 -1
- package/dist/cjs/extensions/array-extensions.js +591 -601
- package/dist/cjs/extensions/array-extensions.js.map +1 -1
- package/dist/cjs/extensions/boolean-extensions.d.ts +1 -1
- package/dist/cjs/extensions/boolean-extensions.js +38 -48
- package/dist/cjs/extensions/boolean-extensions.js.map +1 -1
- package/dist/cjs/extensions/date-extensions.js +507 -517
- package/dist/cjs/extensions/date-extensions.js.map +1 -1
- package/dist/cjs/extensions/expression-extension.d.ts.map +1 -1
- package/dist/cjs/extensions/expression-extension.js +455 -465
- package/dist/cjs/extensions/expression-extension.js.map +1 -1
- package/dist/cjs/extensions/expression-parser.d.ts.map +1 -1
- package/dist/cjs/extensions/expression-parser.js +82 -92
- package/dist/cjs/extensions/expression-parser.js.map +1 -1
- package/dist/cjs/extensions/extended-functions.d.ts +10 -18
- package/dist/cjs/extensions/extended-functions.d.ts.map +1 -1
- package/dist/cjs/extensions/extended-functions.js +80 -90
- package/dist/cjs/extensions/extended-functions.js.map +1 -1
- package/dist/cjs/extensions/extensions.js +2 -12
- package/dist/cjs/extensions/index.js +10 -20
- package/dist/cjs/extensions/index.js.map +1 -1
- package/dist/cjs/extensions/number-extensions.js +226 -236
- package/dist/cjs/extensions/number-extensions.js.map +1 -1
- package/dist/cjs/extensions/object-extensions.js +274 -284
- package/dist/cjs/extensions/object-extensions.js.map +1 -1
- package/dist/cjs/extensions/string-extensions.d.ts +1 -1
- package/dist/cjs/extensions/string-extensions.d.ts.map +1 -1
- package/dist/cjs/extensions/string-extensions.js +769 -779
- package/dist/cjs/extensions/string-extensions.js.map +1 -1
- package/dist/cjs/extensions/utils.d.ts.map +1 -1
- package/dist/cjs/extensions/utils.js +35 -45
- package/dist/cjs/extensions/utils.js.map +1 -1
- package/dist/cjs/from-ai-parse-utils.js +393 -403
- package/dist/cjs/from-ai-parse-utils.js.map +1 -1
- package/dist/cjs/global-state.js +12 -22
- package/dist/cjs/global-state.js.map +1 -1
- package/dist/cjs/graph/graph-utils.js +166 -176
- package/dist/cjs/graph/graph-utils.js.map +1 -1
- package/dist/cjs/highlighted-data.js +13 -23
- package/dist/cjs/highlighted-data.js.map +1 -1
- package/dist/cjs/index.js +105 -115
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interfaces.d.ts +112 -22
- package/dist/cjs/interfaces.d.ts.map +1 -1
- package/dist/cjs/interfaces.js +62 -72
- package/dist/cjs/interfaces.js.map +1 -1
- package/dist/cjs/jmespath-query.js +26 -36
- package/dist/cjs/jmespath-query.js.map +1 -1
- package/dist/cjs/logger-proxy.d.ts.map +1 -1
- package/dist/cjs/logger-proxy.js +15 -25
- package/dist/cjs/logger-proxy.js.map +1 -1
- package/dist/cjs/mcp-helpers.js +10 -20
- package/dist/cjs/mcp-helpers.js.map +1 -1
- package/dist/cjs/message-event-bus.d.ts +184 -165
- package/dist/cjs/message-event-bus.d.ts.map +1 -1
- package/dist/cjs/message-event-bus.js +207 -217
- package/dist/cjs/message-event-bus.js.map +1 -1
- package/dist/cjs/metadata-utils.js +35 -45
- package/dist/cjs/metadata-utils.js.map +1 -1
- package/dist/cjs/native-methods/array.methods.js +527 -537
- package/dist/cjs/native-methods/array.methods.js.map +1 -1
- package/dist/cjs/native-methods/boolean.methods.js +18 -28
- package/dist/cjs/native-methods/boolean.methods.js.map +1 -1
- package/dist/cjs/native-methods/index.js +16 -26
- package/dist/cjs/native-methods/index.js.map +1 -1
- package/dist/cjs/native-methods/number.methods.js +79 -89
- package/dist/cjs/native-methods/number.methods.js.map +1 -1
- package/dist/cjs/native-methods/object.methods.js +7 -17
- package/dist/cjs/native-methods/object.methods.js.map +1 -1
- package/dist/cjs/native-methods/string.methods.js +474 -484
- package/dist/cjs/native-methods/string.methods.js.map +1 -1
- package/dist/cjs/node-grouping-validation.d.ts +6 -0
- package/dist/cjs/node-grouping-validation.d.ts.map +1 -1
- package/dist/cjs/node-grouping-validation.js +165 -144
- package/dist/cjs/node-grouping-validation.js.map +1 -1
- package/dist/cjs/node-helpers.d.ts.map +1 -1
- package/dist/cjs/node-helpers.js +1486 -1493
- package/dist/cjs/node-helpers.js.map +1 -1
- package/dist/cjs/node-parameters/filter-parameter.d.ts.map +1 -1
- package/dist/cjs/node-parameters/filter-parameter.js +315 -325
- package/dist/cjs/node-parameters/filter-parameter.js.map +1 -1
- package/dist/cjs/node-parameters/node-parameter-value-type-guard.js +105 -115
- package/dist/cjs/node-parameters/node-parameter-value-type-guard.js.map +1 -1
- package/dist/cjs/node-parameters/parameter-type-validation.js +120 -130
- package/dist/cjs/node-parameters/parameter-type-validation.js.map +1 -1
- package/dist/cjs/node-parameters/path-utils.js +21 -31
- package/dist/cjs/node-parameters/path-utils.js.map +1 -1
- package/dist/cjs/node-parameters/rename-node-utils.js +22 -32
- package/dist/cjs/node-parameters/rename-node-utils.js.map +1 -1
- package/dist/cjs/node-reference-parser-utils.js +472 -482
- package/dist/cjs/node-reference-parser-utils.js.map +1 -1
- package/dist/cjs/node-validation.js +59 -69
- package/dist/cjs/node-validation.js.map +1 -1
- package/dist/cjs/observable-object.js +56 -66
- package/dist/cjs/observable-object.js.map +1 -1
- package/dist/cjs/redaction-channels.js +36 -46
- package/dist/cjs/redaction-channels.js.map +1 -1
- package/dist/cjs/run-execution-data/run-execution-data.js +15 -25
- package/dist/cjs/run-execution-data/run-execution-data.js.map +1 -1
- package/dist/cjs/run-execution-data/run-execution-data.v0.js +2 -12
- package/dist/cjs/run-execution-data/run-execution-data.v1.js +26 -36
- package/dist/cjs/run-execution-data/run-execution-data.v1.js.map +1 -1
- package/dist/cjs/run-execution-data-factory.js +113 -123
- package/dist/cjs/run-execution-data-factory.js.map +1 -1
- package/dist/cjs/schemas.d.ts +13 -13
- package/dist/cjs/schemas.d.ts.map +1 -1
- package/dist/cjs/schemas.js +351 -360
- package/dist/cjs/schemas.js.map +1 -1
- package/dist/cjs/sub-workflow-output.js +10 -20
- package/dist/cjs/sub-workflow-output.js.map +1 -1
- package/dist/cjs/telemetry-helpers.d.ts.map +1 -1
- package/dist/cjs/telemetry-helpers.js +716 -726
- package/dist/cjs/telemetry-helpers.js.map +1 -1
- package/dist/cjs/tool-helpers.js +18 -28
- package/dist/cjs/tool-helpers.js.map +1 -1
- package/dist/cjs/trigger-identity.js +41 -51
- package/dist/cjs/trigger-identity.js.map +1 -1
- package/dist/cjs/trimmed-task-data.js +21 -31
- package/dist/cjs/trimmed-task-data.js.map +1 -1
- package/dist/cjs/type-guards.d.ts +3 -3
- package/dist/cjs/type-guards.d.ts.map +1 -1
- package/dist/cjs/type-guards.js +74 -84
- package/dist/cjs/type-guards.js.map +1 -1
- package/dist/cjs/type-validation.d.ts.map +1 -1
- package/dist/cjs/type-validation.js +383 -393
- package/dist/cjs/type-validation.js.map +1 -1
- package/dist/cjs/utils.d.ts +2 -2
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +430 -440
- package/dist/cjs/utils.js.map +1 -1
- package/dist/cjs/versioned-node-type.d.ts.map +1 -1
- package/dist/cjs/versioned-node-type.js +20 -30
- package/dist/cjs/versioned-node-type.js.map +1 -1
- package/dist/cjs/workflow-checksum.js +67 -77
- package/dist/cjs/workflow-checksum.js.map +1 -1
- package/dist/cjs/workflow-data-proxy-env-provider.js +58 -68
- package/dist/cjs/workflow-data-proxy-env-provider.js.map +1 -1
- package/dist/cjs/workflow-data-proxy-helpers.js +8 -18
- package/dist/cjs/workflow-data-proxy-helpers.js.map +1 -1
- package/dist/cjs/workflow-data-proxy.d.ts.map +1 -1
- package/dist/cjs/workflow-data-proxy.js +1162 -1172
- package/dist/cjs/workflow-data-proxy.js.map +1 -1
- package/dist/cjs/workflow-diff.d.ts +2 -1
- package/dist/cjs/workflow-diff.d.ts.map +1 -1
- package/dist/cjs/workflow-diff.js +292 -300
- package/dist/cjs/workflow-diff.js.map +1 -1
- package/dist/cjs/workflow-environments-helper.js +23 -33
- package/dist/cjs/workflow-environments-helper.js.map +1 -1
- package/dist/cjs/workflow-expression.d.ts.map +1 -1
- package/dist/cjs/workflow-expression.js +97 -107
- package/dist/cjs/workflow-expression.js.map +1 -1
- package/dist/cjs/workflow-structure-validation.d.ts.map +1 -1
- package/dist/cjs/workflow-structure-validation.js +140 -150
- package/dist/cjs/workflow-structure-validation.js.map +1 -1
- package/dist/cjs/workflow-validation.js +40 -50
- package/dist/cjs/workflow-validation.js.map +1 -1
- package/dist/cjs/workflow.d.ts.map +1 -1
- package/dist/cjs/workflow.js +612 -622
- package/dist/cjs/workflow.js.map +1 -1
- package/dist/esm/common/get-child-nodes.js.map +1 -1
- package/dist/esm/common/get-connected-nodes.js.map +1 -1
- package/dist/esm/common/get-parent-nodes.js.map +1 -1
- package/dist/esm/common/resolve-variables.d.ts +8 -0
- package/dist/esm/common/resolve-variables.d.ts.map +1 -1
- package/dist/esm/common/resolve-variables.js +22 -0
- package/dist/esm/common/resolve-variables.js.map +1 -1
- package/dist/esm/constants.d.ts +3 -3
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/cron.d.ts.map +1 -1
- package/dist/esm/errors/abstract/execution-base.error.d.ts.map +1 -1
- package/dist/esm/errors/abstract/execution-base.error.js.map +1 -1
- package/dist/esm/errors/abstract/node.error.d.ts.map +1 -1
- package/dist/esm/errors/abstract/node.error.js.map +1 -1
- package/dist/esm/errors/base/base.error.d.ts.map +1 -1
- package/dist/esm/errors/base/base.error.js.map +1 -1
- package/dist/esm/errors/base/operational.error.d.ts.map +1 -1
- package/dist/esm/errors/base/operational.error.js.map +1 -1
- package/dist/esm/errors/base/unexpected.error.d.ts.map +1 -1
- package/dist/esm/errors/base/unexpected.error.js.map +1 -1
- package/dist/esm/errors/base/user.error.d.ts.map +1 -1
- package/dist/esm/errors/base/user.error.js.map +1 -1
- package/dist/esm/errors/db-connection-timeout-error.d.ts.map +1 -1
- package/dist/esm/errors/execution-cancelled.error.d.ts.map +1 -1
- package/dist/esm/errors/expression-class-extension.error.d.ts.map +1 -1
- package/dist/esm/errors/expression-computed-destructuring.error.d.ts.map +1 -1
- package/dist/esm/errors/expression-destructuring.error.d.ts.map +1 -1
- package/dist/esm/errors/expression-reserved-variable.error.d.ts.map +1 -1
- package/dist/esm/errors/expression-with-statement.error.d.ts.map +1 -1
- package/dist/esm/errors/expression.error.d.ts.map +1 -1
- package/dist/esm/errors/node-api.error.d.ts.map +1 -1
- package/dist/esm/errors/node-api.error.js.map +1 -1
- package/dist/esm/errors/node-operation.error.d.ts.map +1 -1
- package/dist/esm/errors/node-operation.error.js.map +1 -1
- package/dist/esm/errors/node-ssl.error.d.ts.map +1 -1
- package/dist/esm/errors/subworkflow-operation.error.d.ts.map +1 -1
- package/dist/esm/errors/trigger-close.error.d.ts.map +1 -1
- package/dist/esm/errors/trigger-close.error.js.map +1 -1
- package/dist/esm/errors/webhook-taken.error.d.ts.map +1 -1
- package/dist/esm/errors/workflow-activation.error.d.ts.map +1 -1
- package/dist/esm/errors/workflow-activation.error.js.map +1 -1
- package/dist/esm/errors/workflow-operation.error.d.ts.map +1 -1
- package/dist/esm/execution-context-establishment-hooks.d.ts.map +1 -1
- package/dist/esm/execution-context-establishment-hooks.js +7 -3
- package/dist/esm/execution-context-establishment-hooks.js.map +1 -1
- package/dist/esm/execution-context.d.ts +14 -14
- package/dist/esm/execution-context.d.ts.map +1 -1
- package/dist/esm/execution-status.d.ts +2 -2
- package/dist/esm/execution-status.d.ts.map +1 -1
- package/dist/esm/expression-evaluator-proxy.d.ts.map +1 -1
- package/dist/esm/expression-sandboxing.d.ts.map +1 -1
- package/dist/esm/expression-sandboxing.js.map +1 -1
- package/dist/esm/expression.d.ts.map +1 -1
- package/dist/esm/expression.js.map +1 -1
- package/dist/esm/expressions/expression-helpers.d.ts.map +1 -1
- package/dist/esm/extensions/boolean-extensions.d.ts +1 -1
- package/dist/esm/extensions/expression-extension.d.ts.map +1 -1
- package/dist/esm/extensions/expression-parser.d.ts.map +1 -1
- package/dist/esm/extensions/extended-functions.d.ts +10 -18
- package/dist/esm/extensions/extended-functions.d.ts.map +1 -1
- package/dist/esm/extensions/number-extensions.js.map +1 -1
- package/dist/esm/extensions/string-extensions.d.ts +1 -1
- package/dist/esm/extensions/string-extensions.d.ts.map +1 -1
- package/dist/esm/extensions/string-extensions.js.map +1 -1
- package/dist/esm/extensions/utils.d.ts.map +1 -1
- package/dist/esm/from-ai-parse-utils.js.map +1 -1
- package/dist/esm/interfaces.d.ts +112 -22
- package/dist/esm/interfaces.d.ts.map +1 -1
- package/dist/esm/interfaces.js.map +1 -1
- package/dist/esm/logger-proxy.d.ts.map +1 -1
- package/dist/esm/message-event-bus.d.ts +184 -165
- package/dist/esm/message-event-bus.d.ts.map +1 -1
- package/dist/esm/message-event-bus.js +2 -2
- package/dist/esm/message-event-bus.js.map +1 -1
- package/dist/esm/node-grouping-validation.d.ts +6 -0
- package/dist/esm/node-grouping-validation.d.ts.map +1 -1
- package/dist/esm/node-grouping-validation.js +34 -5
- package/dist/esm/node-grouping-validation.js.map +1 -1
- package/dist/esm/node-helpers.d.ts.map +1 -1
- package/dist/esm/node-helpers.js +3 -0
- package/dist/esm/node-helpers.js.map +1 -1
- package/dist/esm/node-parameters/filter-parameter.d.ts.map +1 -1
- package/dist/esm/node-parameters/filter-parameter.js.map +1 -1
- package/dist/esm/node-reference-parser-utils.js.map +1 -1
- package/dist/esm/run-execution-data-factory.js.map +1 -1
- package/dist/esm/schemas.d.ts +13 -13
- package/dist/esm/schemas.d.ts.map +1 -1
- package/dist/esm/schemas.js +1 -0
- package/dist/esm/schemas.js.map +1 -1
- package/dist/esm/telemetry-helpers.d.ts.map +1 -1
- package/dist/esm/telemetry-helpers.js.map +1 -1
- package/dist/esm/type-guards.d.ts +3 -3
- package/dist/esm/type-guards.d.ts.map +1 -1
- package/dist/esm/type-validation.d.ts.map +1 -1
- package/dist/esm/type-validation.js.map +1 -1
- package/dist/esm/typecheck.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +2 -2
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/versioned-node-type.d.ts.map +1 -1
- package/dist/esm/workflow-data-proxy.d.ts.map +1 -1
- package/dist/esm/workflow-data-proxy.js.map +1 -1
- package/dist/esm/workflow-diff.d.ts +2 -1
- package/dist/esm/workflow-diff.d.ts.map +1 -1
- package/dist/esm/workflow-diff.js +3 -1
- package/dist/esm/workflow-diff.js.map +1 -1
- package/dist/esm/workflow-expression.d.ts.map +1 -1
- package/dist/esm/workflow-expression.js.map +1 -1
- package/dist/esm/workflow-structure-validation.d.ts.map +1 -1
- package/dist/esm/workflow-structure-validation.js.map +1 -1
- package/dist/esm/workflow.d.ts.map +1 -1
- package/dist/esm/workflow.js.map +1 -1
- package/package.json +9 -8
package/dist/cjs/node-helpers.js
CHANGED
|
@@ -1,1667 +1,1660 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
2
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
5
|
};
|
|
5
|
-
(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
displayName: 'Item',
|
|
69
|
-
values: [
|
|
70
|
-
{
|
|
71
|
-
displayName: 'Mode',
|
|
72
|
-
name: 'mode',
|
|
73
|
-
type: 'options',
|
|
74
|
-
options: [
|
|
75
|
-
{
|
|
76
|
-
name: 'Every Minute',
|
|
77
|
-
value: 'everyMinute',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
name: 'Every Hour',
|
|
81
|
-
value: 'everyHour',
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: 'Every Day',
|
|
85
|
-
value: 'everyDay',
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
name: 'Every Week',
|
|
89
|
-
value: 'everyWeek',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: 'Every Month',
|
|
93
|
-
value: 'everyMonth',
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: 'Every X',
|
|
97
|
-
value: 'everyX',
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: 'Custom',
|
|
101
|
-
value: 'custom',
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
default: 'everyDay',
|
|
105
|
-
description: 'How often to trigger.',
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
displayName: 'Hour',
|
|
109
|
-
name: 'hour',
|
|
110
|
-
type: 'number',
|
|
111
|
-
typeOptions: {
|
|
112
|
-
minValue: 0,
|
|
113
|
-
maxValue: 23,
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getUpdatedToolDescription = exports.checkConditions = exports.cronNodeOptions = void 0;
|
|
8
|
+
exports.isSubNodeType = isSubNodeType;
|
|
9
|
+
exports.getNodeFeatures = getNodeFeatures;
|
|
10
|
+
exports.displayParameter = displayParameter;
|
|
11
|
+
exports.displayParameterPath = displayParameterPath;
|
|
12
|
+
exports.getContext = getContext;
|
|
13
|
+
exports.getNodeParameters = getNodeParameters;
|
|
14
|
+
exports.getNodeWebhookPath = getNodeWebhookPath;
|
|
15
|
+
exports.getNodeWebhookUrl = getNodeWebhookUrl;
|
|
16
|
+
exports.resolveNodeWebhookId = resolveNodeWebhookId;
|
|
17
|
+
exports.getConnectionTypes = getConnectionTypes;
|
|
18
|
+
exports.getNodeInputs = getNodeInputs;
|
|
19
|
+
exports.getNodeOutputs = getNodeOutputs;
|
|
20
|
+
exports.getNodeParametersIssues = getNodeParametersIssues;
|
|
21
|
+
exports.nodeIssuesToString = nodeIssuesToString;
|
|
22
|
+
exports.getParameterValueByPath = getParameterValueByPath;
|
|
23
|
+
exports.findDisplayedProperty = findDisplayedProperty;
|
|
24
|
+
exports.getParameterIssues = getParameterIssues;
|
|
25
|
+
exports.mergeIssues = mergeIssues;
|
|
26
|
+
exports.mergeNodeProperties = mergeNodeProperties;
|
|
27
|
+
exports.getVersionedNodeType = getVersionedNodeType;
|
|
28
|
+
exports.isTriggerNode = isTriggerNode;
|
|
29
|
+
exports.isExecutable = isExecutable;
|
|
30
|
+
exports.isNodeWithWorkflowSelector = isNodeWithWorkflowSelector;
|
|
31
|
+
exports.makeDescription = makeDescription;
|
|
32
|
+
exports.isTriggerNodeType = isTriggerNodeType;
|
|
33
|
+
exports.isToolType = isToolType;
|
|
34
|
+
exports.isHitlToolType = isHitlToolType;
|
|
35
|
+
exports.isTool = isTool;
|
|
36
|
+
exports.makeNodeName = makeNodeName;
|
|
37
|
+
exports.isDefaultNodeName = isDefaultNodeName;
|
|
38
|
+
exports.getToolDescriptionForNode = getToolDescriptionForNode;
|
|
39
|
+
exports.getSubworkflowId = getSubworkflowId;
|
|
40
|
+
exports.nodeAcceptsInputType = nodeAcceptsInputType;
|
|
41
|
+
exports.nodeHasOutputType = nodeHasOutputType;
|
|
42
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
43
|
+
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
|
44
|
+
const get_1 = __importDefault(require("lodash/get"));
|
|
45
|
+
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
46
|
+
const uuid_1 = require("uuid");
|
|
47
|
+
const constants_1 = require("./constants");
|
|
48
|
+
const errors_1 = require("./errors");
|
|
49
|
+
const expression_helpers_1 = require("./expressions/expression-helpers");
|
|
50
|
+
const from_ai_parse_utils_1 = require("./from-ai-parse-utils");
|
|
51
|
+
const interfaces_1 = require("./interfaces");
|
|
52
|
+
const filter_parameter_1 = require("./node-parameters/filter-parameter");
|
|
53
|
+
const type_guards_1 = require("./type-guards");
|
|
54
|
+
const type_validation_1 = require("./type-validation");
|
|
55
|
+
const utils_1 = require("./utils");
|
|
56
|
+
exports.cronNodeOptions = [
|
|
57
|
+
{
|
|
58
|
+
name: 'item',
|
|
59
|
+
displayName: 'Item',
|
|
60
|
+
values: [
|
|
61
|
+
{
|
|
62
|
+
displayName: 'Mode',
|
|
63
|
+
name: 'mode',
|
|
64
|
+
type: 'options',
|
|
65
|
+
options: [
|
|
66
|
+
{
|
|
67
|
+
name: 'Every Minute',
|
|
68
|
+
value: 'everyMinute',
|
|
114
69
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Every Hour',
|
|
72
|
+
value: 'everyHour',
|
|
119
73
|
},
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
74
|
+
{
|
|
75
|
+
name: 'Every Day',
|
|
76
|
+
value: 'everyDay',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'Every Week',
|
|
80
|
+
value: 'everyWeek',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'Every Month',
|
|
84
|
+
value: 'everyMonth',
|
|
130
85
|
},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
},
|
|
86
|
+
{
|
|
87
|
+
name: 'Every X',
|
|
88
|
+
value: 'everyX',
|
|
135
89
|
},
|
|
136
|
-
|
|
137
|
-
|
|
90
|
+
{
|
|
91
|
+
name: 'Custom',
|
|
92
|
+
value: 'custom',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
default: 'everyDay',
|
|
96
|
+
description: 'How often to trigger.',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
displayName: 'Hour',
|
|
100
|
+
name: 'hour',
|
|
101
|
+
type: 'number',
|
|
102
|
+
typeOptions: {
|
|
103
|
+
minValue: 0,
|
|
104
|
+
maxValue: 23,
|
|
138
105
|
},
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
type: 'number',
|
|
143
|
-
displayOptions: {
|
|
144
|
-
show: {
|
|
145
|
-
mode: ['everyMonth'],
|
|
146
|
-
},
|
|
106
|
+
displayOptions: {
|
|
107
|
+
hide: {
|
|
108
|
+
mode: ['custom', 'everyHour', 'everyMinute', 'everyX'],
|
|
147
109
|
},
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
110
|
+
},
|
|
111
|
+
default: 14,
|
|
112
|
+
description: 'The hour of the day to trigger (24h format)',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
displayName: 'Minute',
|
|
116
|
+
name: 'minute',
|
|
117
|
+
type: 'number',
|
|
118
|
+
typeOptions: {
|
|
119
|
+
minValue: 0,
|
|
120
|
+
maxValue: 59,
|
|
121
|
+
},
|
|
122
|
+
displayOptions: {
|
|
123
|
+
hide: {
|
|
124
|
+
mode: ['custom', 'everyMinute', 'everyX'],
|
|
151
125
|
},
|
|
152
|
-
default: 1,
|
|
153
|
-
description: 'The day of the month to trigger',
|
|
154
126
|
},
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
127
|
+
default: 0,
|
|
128
|
+
description: 'The minute past the hour to trigger (0-59)',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
displayName: 'Day of Month',
|
|
132
|
+
name: 'dayOfMonth',
|
|
133
|
+
type: 'number',
|
|
134
|
+
displayOptions: {
|
|
135
|
+
show: {
|
|
136
|
+
mode: ['everyMonth'],
|
|
163
137
|
},
|
|
164
|
-
options: [
|
|
165
|
-
{
|
|
166
|
-
name: 'Monday',
|
|
167
|
-
value: '1',
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
name: 'Tuesday',
|
|
171
|
-
value: '2',
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
name: 'Wednesday',
|
|
175
|
-
value: '3',
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
name: 'Thursday',
|
|
179
|
-
value: '4',
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
name: 'Friday',
|
|
183
|
-
value: '5',
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
name: 'Saturday',
|
|
187
|
-
value: '6',
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
name: 'Sunday',
|
|
191
|
-
value: '0',
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
default: '1',
|
|
195
|
-
description: 'The weekday to trigger',
|
|
196
138
|
},
|
|
197
|
-
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
139
|
+
typeOptions: {
|
|
140
|
+
minValue: 1,
|
|
141
|
+
maxValue: 31,
|
|
142
|
+
},
|
|
143
|
+
default: 1,
|
|
144
|
+
description: 'The day of the month to trigger',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
displayName: 'Weekday',
|
|
148
|
+
name: 'weekday',
|
|
149
|
+
type: 'options',
|
|
150
|
+
displayOptions: {
|
|
151
|
+
show: {
|
|
152
|
+
mode: ['everyWeek'],
|
|
205
153
|
},
|
|
206
|
-
default: '* * * * * *',
|
|
207
|
-
description: 'Use custom cron expression. Values and ranges as follows:<ul><li>Seconds: 0-59</li><li>Minutes: 0 - 59</li><li>Hours: 0 - 23</li><li>Day of Month: 1 - 31</li><li>Months: 0 - 11 (Jan - Dec)</li><li>Day of Week: 0 - 6 (Sun - Sat)</li></ul>',
|
|
208
154
|
},
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
155
|
+
options: [
|
|
156
|
+
{
|
|
157
|
+
name: 'Monday',
|
|
158
|
+
value: '1',
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: 'Tuesday',
|
|
162
|
+
value: '2',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'Wednesday',
|
|
166
|
+
value: '3',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: 'Thursday',
|
|
170
|
+
value: '4',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: 'Friday',
|
|
174
|
+
value: '5',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: 'Saturday',
|
|
178
|
+
value: '6',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'Sunday',
|
|
182
|
+
value: '0',
|
|
216
183
|
},
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
184
|
+
],
|
|
185
|
+
default: '1',
|
|
186
|
+
description: 'The weekday to trigger',
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
displayName: 'Cron Expression',
|
|
190
|
+
name: 'cronExpression',
|
|
191
|
+
type: 'string',
|
|
192
|
+
displayOptions: {
|
|
193
|
+
show: {
|
|
194
|
+
mode: ['custom'],
|
|
221
195
|
},
|
|
222
|
-
default: 2,
|
|
223
|
-
description: 'All how many X minutes/hours it should trigger',
|
|
224
196
|
},
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
197
|
+
default: '* * * * * *',
|
|
198
|
+
description: 'Use custom cron expression. Values and ranges as follows:<ul><li>Seconds: 0-59</li><li>Minutes: 0 - 59</li><li>Hours: 0 - 23</li><li>Day of Month: 1 - 31</li><li>Months: 0 - 11 (Jan - Dec)</li><li>Day of Week: 0 - 6 (Sun - Sat)</li></ul>',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
displayName: 'Value',
|
|
202
|
+
name: 'value',
|
|
203
|
+
type: 'number',
|
|
204
|
+
typeOptions: {
|
|
205
|
+
minValue: 0,
|
|
206
|
+
maxValue: 1000,
|
|
207
|
+
},
|
|
208
|
+
displayOptions: {
|
|
209
|
+
show: {
|
|
210
|
+
mode: ['everyX'],
|
|
233
211
|
},
|
|
234
|
-
options: [
|
|
235
|
-
{
|
|
236
|
-
name: 'Minutes',
|
|
237
|
-
value: 'minutes',
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
name: 'Hours',
|
|
241
|
-
value: 'hours',
|
|
242
|
-
},
|
|
243
|
-
],
|
|
244
|
-
default: 'hours',
|
|
245
|
-
description: 'If it should trigger all X minutes or hours',
|
|
246
212
|
},
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const features = {};
|
|
283
|
-
for (const [featureName, condition] of Object.entries(featuresDef)) {
|
|
284
|
-
features[featureName] = evaluateFeature(condition, nodeVersion);
|
|
285
|
-
}
|
|
286
|
-
return features;
|
|
213
|
+
default: 2,
|
|
214
|
+
description: 'All how many X minutes/hours it should trigger',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
displayName: 'Unit',
|
|
218
|
+
name: 'unit',
|
|
219
|
+
type: 'options',
|
|
220
|
+
displayOptions: {
|
|
221
|
+
show: {
|
|
222
|
+
mode: ['everyX'],
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
options: [
|
|
226
|
+
{
|
|
227
|
+
name: 'Minutes',
|
|
228
|
+
value: 'minutes',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: 'Hours',
|
|
232
|
+
value: 'hours',
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
default: 'hours',
|
|
236
|
+
description: 'If it should trigger all X minutes or hours',
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
/**
|
|
242
|
+
* Determines if the provided node type has any output types other than the main connection type.
|
|
243
|
+
* @param typeDescription The node's type description to check.
|
|
244
|
+
*/
|
|
245
|
+
function isSubNodeType(typeDescription) {
|
|
246
|
+
if (!typeDescription?.outputs || typeof typeDescription.outputs === 'string') {
|
|
247
|
+
return false;
|
|
287
248
|
}
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
249
|
+
const outputTypes = getConnectionTypes(typeDescription.outputs);
|
|
250
|
+
return outputTypes
|
|
251
|
+
? outputTypes.filter((output) => output !== interfaces_1.NodeConnectionTypes.Main).length > 0
|
|
252
|
+
: false;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Evaluates a feature condition against a node version.
|
|
256
|
+
* @param featureDef The feature condition definition
|
|
257
|
+
* @param nodeVersion The node version to evaluate against
|
|
258
|
+
* @returns true if the feature is enabled, false otherwise
|
|
259
|
+
*/
|
|
260
|
+
function evaluateFeature(featureDef, nodeVersion) {
|
|
261
|
+
return (0, exports.checkConditions)(featureDef['@version'], [nodeVersion]);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Evaluates all feature definitions for a node type and returns the computed features.
|
|
265
|
+
* @param featuresDef The feature definitions from the node type description
|
|
266
|
+
* @param nodeVersion The node version to evaluate against
|
|
267
|
+
* @returns A record of feature names to their enabled state
|
|
268
|
+
*/
|
|
269
|
+
function getNodeFeatures(featuresDef, nodeVersion) {
|
|
270
|
+
if (!featuresDef) {
|
|
271
|
+
return {};
|
|
272
|
+
}
|
|
273
|
+
const features = {};
|
|
274
|
+
for (const [featureName, condition] of Object.entries(featuresDef)) {
|
|
275
|
+
features[featureName] = evaluateFeature(condition, nodeVersion);
|
|
276
|
+
}
|
|
277
|
+
return features;
|
|
278
|
+
}
|
|
279
|
+
const getPropertyValues = (nodeValues, propertyName, node, nodeTypeDescription, nodeValuesRoot) => {
|
|
280
|
+
let value;
|
|
281
|
+
if (propertyName.charAt(0) === '/') {
|
|
282
|
+
// Get the value from the root of the node
|
|
283
|
+
value = (0, get_1.default)(nodeValuesRoot, propertyName.slice(1));
|
|
284
|
+
}
|
|
285
|
+
else if (propertyName === '@version') {
|
|
286
|
+
value = node?.typeVersion || 0;
|
|
287
|
+
}
|
|
288
|
+
else if (propertyName === '@tool') {
|
|
289
|
+
value = nodeTypeDescription?.name.endsWith('Tool') ?? false;
|
|
290
|
+
}
|
|
291
|
+
else if (propertyName === '@feature') {
|
|
292
|
+
if (!nodeTypeDescription?.features || !node?.typeVersion) {
|
|
293
|
+
return [];
|
|
299
294
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
295
|
+
const features = getNodeFeatures(nodeTypeDescription.features, node.typeVersion);
|
|
296
|
+
return Object.entries(features)
|
|
297
|
+
.filter(([_, enabled]) => enabled)
|
|
298
|
+
.map(([name]) => name);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
// Get the value from current level
|
|
302
|
+
value = (0, get_1.default)(nodeValues, propertyName);
|
|
303
|
+
}
|
|
304
|
+
if (value && typeof value === 'object' && '__rl' in value && value.__rl) {
|
|
305
|
+
value = value.value;
|
|
306
|
+
}
|
|
307
|
+
if (!Array.isArray(value)) {
|
|
308
|
+
return [value];
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
return value;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
const checkConditions = (conditions, actualValues) => {
|
|
315
|
+
return conditions.some((condition) => {
|
|
316
|
+
if (condition &&
|
|
317
|
+
typeof condition === 'object' &&
|
|
318
|
+
condition._cnd &&
|
|
319
|
+
Object.keys(condition).length === 1) {
|
|
320
|
+
const [key, targetValue] = Object.entries(condition._cnd)[0];
|
|
321
|
+
// Special case: empty array handling
|
|
322
|
+
if (actualValues.length === 0) {
|
|
323
|
+
if (key === 'not')
|
|
324
|
+
return true; // Value is not present, so 'not' is true
|
|
325
|
+
return false; // For all other keys, empty array means condition is not met
|
|
303
326
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
.map(([name]) => name);
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
// Get the value from current level
|
|
311
|
-
value = (0, get_1.default)(nodeValues, propertyName);
|
|
312
|
-
}
|
|
313
|
-
if (value && typeof value === 'object' && '__rl' in value && value.__rl) {
|
|
314
|
-
value = value.value;
|
|
315
|
-
}
|
|
316
|
-
if (!Array.isArray(value)) {
|
|
317
|
-
return [value];
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
return value;
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
|
-
const checkConditions = (conditions, actualValues) => {
|
|
324
|
-
return conditions.some((condition) => {
|
|
325
|
-
if (condition &&
|
|
326
|
-
typeof condition === 'object' &&
|
|
327
|
-
condition._cnd &&
|
|
328
|
-
Object.keys(condition).length === 1) {
|
|
329
|
-
const [key, targetValue] = Object.entries(condition._cnd)[0];
|
|
330
|
-
// Special case: empty array handling
|
|
331
|
-
if (actualValues.length === 0) {
|
|
332
|
-
if (key === 'not')
|
|
333
|
-
return true; // Value is not present, so 'not' is true
|
|
334
|
-
return false; // For all other keys, empty array means condition is not met
|
|
327
|
+
return actualValues.every((propertyValue) => {
|
|
328
|
+
if (key === 'eq') {
|
|
329
|
+
return (0, isEqual_1.default)(propertyValue, targetValue);
|
|
335
330
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
return (0, isEqual_1.default)(propertyValue, targetValue);
|
|
339
|
-
}
|
|
340
|
-
if (key === 'not') {
|
|
341
|
-
return !(0, isEqual_1.default)(propertyValue, targetValue);
|
|
342
|
-
}
|
|
343
|
-
if (key === 'gte') {
|
|
344
|
-
return propertyValue >= targetValue;
|
|
345
|
-
}
|
|
346
|
-
if (key === 'lte') {
|
|
347
|
-
return propertyValue <= targetValue;
|
|
348
|
-
}
|
|
349
|
-
if (key === 'gt') {
|
|
350
|
-
return propertyValue > targetValue;
|
|
351
|
-
}
|
|
352
|
-
if (key === 'lt') {
|
|
353
|
-
return propertyValue < targetValue;
|
|
354
|
-
}
|
|
355
|
-
if (key === 'between') {
|
|
356
|
-
const { from, to } = targetValue;
|
|
357
|
-
return propertyValue >= from && propertyValue <= to;
|
|
358
|
-
}
|
|
359
|
-
if (key === 'includes') {
|
|
360
|
-
return typeof propertyValue === 'string' && propertyValue.includes(targetValue);
|
|
361
|
-
}
|
|
362
|
-
if (key === 'startsWith') {
|
|
363
|
-
return (typeof propertyValue === 'string' && propertyValue.startsWith(targetValue));
|
|
364
|
-
}
|
|
365
|
-
if (key === 'endsWith') {
|
|
366
|
-
return typeof propertyValue === 'string' && propertyValue.endsWith(targetValue);
|
|
367
|
-
}
|
|
368
|
-
if (key === 'regex') {
|
|
369
|
-
return (typeof propertyValue === 'string' &&
|
|
370
|
-
new RegExp(targetValue).test(propertyValue));
|
|
371
|
-
}
|
|
372
|
-
if (key === 'exists') {
|
|
373
|
-
return propertyValue !== null && propertyValue !== undefined && propertyValue !== '';
|
|
374
|
-
}
|
|
375
|
-
return false;
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
return actualValues.includes(condition);
|
|
379
|
-
});
|
|
380
|
-
};
|
|
381
|
-
exports.checkConditions = checkConditions;
|
|
382
|
-
/**
|
|
383
|
-
* Returns if the parameter should be displayed or not
|
|
384
|
-
*
|
|
385
|
-
* @param {INodeParameters} nodeValues The data on the node which decides if the parameter
|
|
386
|
-
* should be displayed
|
|
387
|
-
* @param {(INodeProperties | INodeCredentialDescription)} parameter The parameter to check if it should be displayed
|
|
388
|
-
* @param {INodeParameters} [nodeValuesRoot] The root node-parameter-data
|
|
389
|
-
*/
|
|
390
|
-
function displayParameter(nodeValues, parameter, node, // Allow null as it does also get used by credentials and they do not have versioning yet
|
|
391
|
-
nodeTypeDescription, nodeValuesRoot, displayKey = 'displayOptions') {
|
|
392
|
-
if (!parameter[displayKey]) {
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
|
-
const { show, hide } = parameter[displayKey];
|
|
396
|
-
nodeValuesRoot = nodeValuesRoot || nodeValues;
|
|
397
|
-
if (show) {
|
|
398
|
-
// All the defined rules have to match to display parameter
|
|
399
|
-
for (const propertyName of Object.keys(show)) {
|
|
400
|
-
const values = getPropertyValues(nodeValues, propertyName, node, nodeTypeDescription, nodeValuesRoot);
|
|
401
|
-
if (values.some((v) => typeof v === 'string' && v.charAt(0) === '=')) {
|
|
402
|
-
return true;
|
|
331
|
+
if (key === 'not') {
|
|
332
|
+
return !(0, isEqual_1.default)(propertyValue, targetValue);
|
|
403
333
|
}
|
|
404
|
-
if (
|
|
405
|
-
return
|
|
334
|
+
if (key === 'gte') {
|
|
335
|
+
return propertyValue >= targetValue;
|
|
406
336
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (hide) {
|
|
410
|
-
// Any of the defined hide rules have to match to hide the parameter
|
|
411
|
-
for (const propertyName of Object.keys(hide)) {
|
|
412
|
-
const values = getPropertyValues(nodeValues, propertyName, node, nodeTypeDescription, nodeValuesRoot);
|
|
413
|
-
if (values.length !== 0 && (0, exports.checkConditions)(hide[propertyName], values)) {
|
|
414
|
-
return false;
|
|
337
|
+
if (key === 'lte') {
|
|
338
|
+
return propertyValue <= targetValue;
|
|
415
339
|
}
|
|
416
|
-
|
|
340
|
+
if (key === 'gt') {
|
|
341
|
+
return propertyValue > targetValue;
|
|
342
|
+
}
|
|
343
|
+
if (key === 'lt') {
|
|
344
|
+
return propertyValue < targetValue;
|
|
345
|
+
}
|
|
346
|
+
if (key === 'between') {
|
|
347
|
+
const { from, to } = targetValue;
|
|
348
|
+
return propertyValue >= from && propertyValue <= to;
|
|
349
|
+
}
|
|
350
|
+
if (key === 'includes') {
|
|
351
|
+
return typeof propertyValue === 'string' && propertyValue.includes(targetValue);
|
|
352
|
+
}
|
|
353
|
+
if (key === 'startsWith') {
|
|
354
|
+
return (typeof propertyValue === 'string' && propertyValue.startsWith(targetValue));
|
|
355
|
+
}
|
|
356
|
+
if (key === 'endsWith') {
|
|
357
|
+
return typeof propertyValue === 'string' && propertyValue.endsWith(targetValue);
|
|
358
|
+
}
|
|
359
|
+
if (key === 'regex') {
|
|
360
|
+
return (typeof propertyValue === 'string' &&
|
|
361
|
+
new RegExp(targetValue).test(propertyValue));
|
|
362
|
+
}
|
|
363
|
+
if (key === 'exists') {
|
|
364
|
+
return propertyValue !== null && propertyValue !== undefined && propertyValue !== '';
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
});
|
|
417
368
|
}
|
|
369
|
+
return actualValues.includes(condition);
|
|
370
|
+
});
|
|
371
|
+
};
|
|
372
|
+
exports.checkConditions = checkConditions;
|
|
373
|
+
/**
|
|
374
|
+
* Returns if the parameter should be displayed or not
|
|
375
|
+
*
|
|
376
|
+
* @param {INodeParameters} nodeValues The data on the node which decides if the parameter
|
|
377
|
+
* should be displayed
|
|
378
|
+
* @param {(INodeProperties | INodeCredentialDescription)} parameter The parameter to check if it should be displayed
|
|
379
|
+
* @param {INodeParameters} [nodeValuesRoot] The root node-parameter-data
|
|
380
|
+
*/
|
|
381
|
+
function displayParameter(nodeValues, parameter, node, // Allow null as it does also get used by credentials and they do not have versioning yet
|
|
382
|
+
nodeTypeDescription, nodeValuesRoot, displayKey = 'displayOptions') {
|
|
383
|
+
if (!parameter[displayKey]) {
|
|
418
384
|
return true;
|
|
419
385
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
*/
|
|
429
|
-
function displayParameterPath(nodeValues, parameter, path, node, nodeTypeDescription, displayKey = 'displayOptions') {
|
|
430
|
-
let resolvedNodeValues = nodeValues;
|
|
431
|
-
if (path !== '') {
|
|
432
|
-
resolvedNodeValues = (0, get_1.default)(nodeValues, path);
|
|
433
|
-
}
|
|
434
|
-
// Get the root parameter data
|
|
435
|
-
let nodeValuesRoot = nodeValues;
|
|
436
|
-
if (path && path.split('.').indexOf('parameters') === 0) {
|
|
437
|
-
nodeValuesRoot = (0, get_1.default)(nodeValues, 'parameters');
|
|
438
|
-
}
|
|
439
|
-
return displayParameter(resolvedNodeValues, parameter, node, nodeTypeDescription, nodeValuesRoot, displayKey);
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Returns the context data
|
|
443
|
-
*
|
|
444
|
-
* @param {IRunExecutionData} runExecutionData The run execution data
|
|
445
|
-
* @param {string} type The data type. "node"/"flow"
|
|
446
|
-
* @param {INode} [node] If type "node" is set the node to return the context of has to be supplied
|
|
447
|
-
*/
|
|
448
|
-
function getContext(runExecutionData, type, node) {
|
|
449
|
-
if (runExecutionData.executionData === undefined) {
|
|
450
|
-
// TODO: Should not happen leave it for test now
|
|
451
|
-
throw new errors_1.UnexpectedError('`executionData` is not initialized');
|
|
452
|
-
}
|
|
453
|
-
let key;
|
|
454
|
-
if (type === 'flow') {
|
|
455
|
-
key = 'flow';
|
|
456
|
-
}
|
|
457
|
-
else if (type === 'node') {
|
|
458
|
-
if (node === undefined) {
|
|
459
|
-
// @TODO: What does this mean?
|
|
460
|
-
throw new errors_1.UnexpectedError('The request data of context type "node" the node parameter has to be set!');
|
|
461
|
-
}
|
|
462
|
-
key = `node:${node.name}`;
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
throw new errors_1.UnexpectedError('Unknown context type. Only `flow` and `node` are supported.', {
|
|
466
|
-
extra: { contextType: type },
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
if (runExecutionData.executionData.contextData[key] === undefined) {
|
|
470
|
-
runExecutionData.executionData.contextData[key] = {};
|
|
471
|
-
}
|
|
472
|
-
return runExecutionData.executionData.contextData[key];
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Returns which parameters are dependent on which
|
|
476
|
-
*/
|
|
477
|
-
function getParameterDependencies(nodePropertiesArray) {
|
|
478
|
-
const dependencies = {};
|
|
479
|
-
for (const nodeProperties of nodePropertiesArray) {
|
|
480
|
-
const { name, displayOptions } = nodeProperties;
|
|
481
|
-
if (!dependencies[name]) {
|
|
482
|
-
dependencies[name] = [];
|
|
386
|
+
const { show, hide } = parameter[displayKey];
|
|
387
|
+
nodeValuesRoot = nodeValuesRoot || nodeValues;
|
|
388
|
+
if (show) {
|
|
389
|
+
// All the defined rules have to match to display parameter
|
|
390
|
+
for (const propertyName of Object.keys(show)) {
|
|
391
|
+
const values = getPropertyValues(nodeValues, propertyName, node, nodeTypeDescription, nodeValuesRoot);
|
|
392
|
+
if (values.some((v) => typeof v === 'string' && v.charAt(0) === '=')) {
|
|
393
|
+
return true;
|
|
483
394
|
}
|
|
484
|
-
if (!
|
|
485
|
-
|
|
486
|
-
continue;
|
|
395
|
+
if (!(0, exports.checkConditions)(show[propertyName], values)) {
|
|
396
|
+
return false;
|
|
487
397
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
}
|
|
497
|
-
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (hide) {
|
|
401
|
+
// Any of the defined hide rules have to match to hide the parameter
|
|
402
|
+
for (const propertyName of Object.keys(hide)) {
|
|
403
|
+
const values = getPropertyValues(nodeValues, propertyName, node, nodeTypeDescription, nodeValuesRoot);
|
|
404
|
+
if (values.length !== 0 && (0, exports.checkConditions)(hide[propertyName], values)) {
|
|
405
|
+
return false;
|
|
498
406
|
}
|
|
499
407
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
408
|
+
}
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Returns if the given parameter should be displayed or not considering the path
|
|
413
|
+
* to the properties
|
|
414
|
+
*
|
|
415
|
+
* @param {INodeParameters} nodeValues The data on the node which decides if the parameter
|
|
416
|
+
* should be displayed
|
|
417
|
+
* @param {(INodeProperties | INodeCredentialDescription)} parameter The parameter to check if it should be displayed
|
|
418
|
+
* @param {string} path The path to the property
|
|
419
|
+
*/
|
|
420
|
+
function displayParameterPath(nodeValues, parameter, path, node, nodeTypeDescription, displayKey = 'displayOptions') {
|
|
421
|
+
let resolvedNodeValues = nodeValues;
|
|
422
|
+
if (path !== '') {
|
|
423
|
+
resolvedNodeValues = (0, get_1.default)(nodeValues, path);
|
|
424
|
+
}
|
|
425
|
+
// Get the root parameter data
|
|
426
|
+
let nodeValuesRoot = nodeValues;
|
|
427
|
+
if (path && path.split('.').indexOf('parameters') === 0) {
|
|
428
|
+
nodeValuesRoot = (0, get_1.default)(nodeValues, 'parameters');
|
|
429
|
+
}
|
|
430
|
+
return displayParameter(resolvedNodeValues, parameter, node, nodeTypeDescription, nodeValuesRoot, displayKey);
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Returns the context data
|
|
434
|
+
*
|
|
435
|
+
* @param {IRunExecutionData} runExecutionData The run execution data
|
|
436
|
+
* @param {string} type The data type. "node"/"flow"
|
|
437
|
+
* @param {INode} [node] If type "node" is set the node to return the context of has to be supplied
|
|
438
|
+
*/
|
|
439
|
+
function getContext(runExecutionData, type, node) {
|
|
440
|
+
if (runExecutionData.executionData === undefined) {
|
|
441
|
+
// TODO: Should not happen leave it for test now
|
|
442
|
+
throw new errors_1.UnexpectedError('`executionData` is not initialized');
|
|
443
|
+
}
|
|
444
|
+
let key;
|
|
445
|
+
if (type === 'flow') {
|
|
446
|
+
key = 'flow';
|
|
447
|
+
}
|
|
448
|
+
else if (type === 'node') {
|
|
449
|
+
if (node === undefined) {
|
|
450
|
+
// @TODO: What does this mean?
|
|
451
|
+
throw new errors_1.UnexpectedError('The request data of context type "node" the node parameter has to be set!');
|
|
452
|
+
}
|
|
453
|
+
key = `node:${node.name}`;
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
throw new errors_1.UnexpectedError('Unknown context type. Only `flow` and `node` are supported.', {
|
|
457
|
+
extra: { contextType: type },
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
if (runExecutionData.executionData.contextData[key] === undefined) {
|
|
461
|
+
runExecutionData.executionData.contextData[key] = {};
|
|
462
|
+
}
|
|
463
|
+
return runExecutionData.executionData.contextData[key];
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Returns which parameters are dependent on which
|
|
467
|
+
*/
|
|
468
|
+
function getParameterDependencies(nodePropertiesArray) {
|
|
469
|
+
const dependencies = {};
|
|
470
|
+
for (const nodeProperties of nodePropertiesArray) {
|
|
471
|
+
const { name, displayOptions } = nodeProperties;
|
|
472
|
+
if (!dependencies[name]) {
|
|
473
|
+
dependencies[name] = [];
|
|
474
|
+
}
|
|
475
|
+
if (!displayOptions) {
|
|
476
|
+
// Does not have any dependencies
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
for (const displayRule of Object.values(displayOptions)) {
|
|
480
|
+
if (typeof displayRule !== 'object' || displayRule === null) {
|
|
523
481
|
continue;
|
|
524
482
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
// Assume that root level dependencies are resolved
|
|
483
|
+
for (const parameterName of Object.keys(displayRule)) {
|
|
484
|
+
if (!dependencies[name].includes(parameterName)) {
|
|
485
|
+
if (parameterName.charAt(0) === '@') {
|
|
486
|
+
// Is a special parameter so can be skipped
|
|
530
487
|
continue;
|
|
531
488
|
}
|
|
532
|
-
|
|
533
|
-
// try to add again later
|
|
534
|
-
indexToResolve.push(index);
|
|
535
|
-
continue;
|
|
489
|
+
dependencies[name].push(parameterName);
|
|
536
490
|
}
|
|
537
491
|
}
|
|
538
|
-
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return dependencies;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Returns in which order the parameters should be resolved
|
|
498
|
+
* to have the parameters available they depend on
|
|
499
|
+
*/
|
|
500
|
+
function getParameterResolveOrder(nodePropertiesArray, parameterDependencies) {
|
|
501
|
+
const executionOrder = [];
|
|
502
|
+
const indexToResolve = Array.from({ length: nodePropertiesArray.length }, (_, k) => k);
|
|
503
|
+
const resolvedParameters = [];
|
|
504
|
+
let index;
|
|
505
|
+
let property;
|
|
506
|
+
let lastIndexLength = indexToResolve.length;
|
|
507
|
+
let lastIndexReduction = -1;
|
|
508
|
+
let iterations = 0;
|
|
509
|
+
while (indexToResolve.length !== 0) {
|
|
510
|
+
iterations += 1;
|
|
511
|
+
index = indexToResolve.shift();
|
|
512
|
+
property = nodePropertiesArray[index];
|
|
513
|
+
if (parameterDependencies[property.name].length === 0) {
|
|
514
|
+
// Does not have any dependencies so simply add
|
|
539
515
|
executionOrder.push(index);
|
|
540
516
|
resolvedParameters.push(property.name);
|
|
541
|
-
|
|
542
|
-
lastIndexReduction = iterations;
|
|
543
|
-
}
|
|
544
|
-
if (iterations > lastIndexReduction + nodePropertiesArray.length) {
|
|
545
|
-
throw new errors_1.UserError('Could not resolve parameter dependencies. Max iterations reached! Hint: If `displayOptions` are specified in any child parameter of a parent `collection` or `fixedCollection`, remove the `displayOptions` from the child parameter.');
|
|
546
|
-
}
|
|
547
|
-
lastIndexLength = indexToResolve.length;
|
|
548
|
-
}
|
|
549
|
-
return executionOrder;
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Returns the node parameter values. Depending on the settings it either just returns the none
|
|
553
|
-
* default values or it applies all the default values.
|
|
554
|
-
*
|
|
555
|
-
* @param {INodeProperties[]} nodePropertiesArray The properties which exist and their settings
|
|
556
|
-
* @param {INodeParameters} nodeValues The node parameter data
|
|
557
|
-
* @param {boolean} returnDefaults If default values get added or only none default values returned
|
|
558
|
-
* @param {boolean} returnNoneDisplayed If also values which should not be displayed should be returned
|
|
559
|
-
* @param {GetNodeParametersOptions} options Optional properties
|
|
560
|
-
*/
|
|
561
|
-
// eslint-disable-next-line complexity
|
|
562
|
-
function getNodeParameters(nodePropertiesArray, nodeValues, returnDefaults, returnNoneDisplayed, node, nodeTypeDescription, options) {
|
|
563
|
-
let { nodeValuesRoot, parameterDependencies } = options ?? {};
|
|
564
|
-
const { onlySimpleTypes = false, dataIsResolved = false, parentType } = options ?? {};
|
|
565
|
-
if (parameterDependencies === undefined) {
|
|
566
|
-
parameterDependencies = getParameterDependencies(nodePropertiesArray);
|
|
517
|
+
continue;
|
|
567
518
|
}
|
|
568
|
-
//
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
if (!duplicateParameterNames.includes(nodeProperties.name)) {
|
|
575
|
-
duplicateParameterNames.push(nodeProperties.name);
|
|
519
|
+
// Parameter has dependencies
|
|
520
|
+
for (const dependency of parameterDependencies[property.name]) {
|
|
521
|
+
if (!resolvedParameters.includes(dependency)) {
|
|
522
|
+
if (dependency.charAt(0) === '/') {
|
|
523
|
+
// Assume that root level dependencies are resolved
|
|
524
|
+
continue;
|
|
576
525
|
}
|
|
526
|
+
// Dependencies for that parameter are still missing so
|
|
527
|
+
// try to add again later
|
|
528
|
+
indexToResolve.push(index);
|
|
529
|
+
continue;
|
|
577
530
|
}
|
|
578
|
-
|
|
579
|
-
|
|
531
|
+
}
|
|
532
|
+
// All dependencies got found so add
|
|
533
|
+
executionOrder.push(index);
|
|
534
|
+
resolvedParameters.push(property.name);
|
|
535
|
+
if (indexToResolve.length < lastIndexLength) {
|
|
536
|
+
lastIndexReduction = iterations;
|
|
537
|
+
}
|
|
538
|
+
if (iterations > lastIndexReduction + nodePropertiesArray.length) {
|
|
539
|
+
throw new errors_1.UserError('Could not resolve parameter dependencies. Max iterations reached! Hint: If `displayOptions` are specified in any child parameter of a parent `collection` or `fixedCollection`, remove the `displayOptions` from the child parameter.');
|
|
540
|
+
}
|
|
541
|
+
lastIndexLength = indexToResolve.length;
|
|
542
|
+
}
|
|
543
|
+
return executionOrder;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Returns the node parameter values. Depending on the settings it either just returns the none
|
|
547
|
+
* default values or it applies all the default values.
|
|
548
|
+
*
|
|
549
|
+
* @param {INodeProperties[]} nodePropertiesArray The properties which exist and their settings
|
|
550
|
+
* @param {INodeParameters} nodeValues The node parameter data
|
|
551
|
+
* @param {boolean} returnDefaults If default values get added or only none default values returned
|
|
552
|
+
* @param {boolean} returnNoneDisplayed If also values which should not be displayed should be returned
|
|
553
|
+
* @param {GetNodeParametersOptions} options Optional properties
|
|
554
|
+
*/
|
|
555
|
+
// eslint-disable-next-line complexity
|
|
556
|
+
function getNodeParameters(nodePropertiesArray, nodeValues, returnDefaults, returnNoneDisplayed, node, nodeTypeDescription, options) {
|
|
557
|
+
let { nodeValuesRoot, parameterDependencies } = options ?? {};
|
|
558
|
+
const { onlySimpleTypes = false, dataIsResolved = false, parentType } = options ?? {};
|
|
559
|
+
if (parameterDependencies === undefined) {
|
|
560
|
+
parameterDependencies = getParameterDependencies(nodePropertiesArray);
|
|
561
|
+
}
|
|
562
|
+
// Get the parameter names which get used multiple times as for this
|
|
563
|
+
// ones we have to always check which ones get displayed and which ones not
|
|
564
|
+
const duplicateParameterNames = [];
|
|
565
|
+
const parameterNames = [];
|
|
566
|
+
for (const nodeProperties of nodePropertiesArray) {
|
|
567
|
+
if (parameterNames.includes(nodeProperties.name)) {
|
|
568
|
+
if (!duplicateParameterNames.includes(nodeProperties.name)) {
|
|
569
|
+
duplicateParameterNames.push(nodeProperties.name);
|
|
580
570
|
}
|
|
581
571
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
let nodeValuesDisplayCheck = nodeParametersFull;
|
|
585
|
-
if (!dataIsResolved && !returnNoneDisplayed) {
|
|
586
|
-
nodeValuesDisplayCheck = getNodeParameters(nodePropertiesArray, nodeValues, true, true, node, nodeTypeDescription, {
|
|
587
|
-
onlySimpleTypes: true,
|
|
588
|
-
dataIsResolved: true,
|
|
589
|
-
nodeValuesRoot,
|
|
590
|
-
parentType,
|
|
591
|
-
parameterDependencies,
|
|
592
|
-
});
|
|
572
|
+
else {
|
|
573
|
+
parameterNames.push(nodeProperties.name);
|
|
593
574
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
575
|
+
}
|
|
576
|
+
const nodeParameters = {};
|
|
577
|
+
const nodeParametersFull = {};
|
|
578
|
+
let nodeValuesDisplayCheck = nodeParametersFull;
|
|
579
|
+
if (!dataIsResolved && !returnNoneDisplayed) {
|
|
580
|
+
nodeValuesDisplayCheck = getNodeParameters(nodePropertiesArray, nodeValues, true, true, node, nodeTypeDescription, {
|
|
581
|
+
onlySimpleTypes: true,
|
|
582
|
+
dataIsResolved: true,
|
|
583
|
+
nodeValuesRoot,
|
|
584
|
+
parentType,
|
|
585
|
+
parameterDependencies,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
nodeValuesRoot = nodeValuesRoot || nodeValuesDisplayCheck;
|
|
589
|
+
// Go through the parameters in order of their dependencies
|
|
590
|
+
const parameterIterationOrderIndex = getParameterResolveOrder(nodePropertiesArray, parameterDependencies);
|
|
591
|
+
for (const parameterIndex of parameterIterationOrderIndex) {
|
|
592
|
+
const nodeProperties = nodePropertiesArray[parameterIndex];
|
|
593
|
+
if (!nodeValues ||
|
|
594
|
+
(nodeValues[nodeProperties.name] === undefined &&
|
|
595
|
+
(!returnDefaults || parentType === 'collection'))) {
|
|
596
|
+
// The value is not defined so go to the next
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
if (!returnNoneDisplayed &&
|
|
600
|
+
!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeTypeDescription, nodeValuesRoot)) {
|
|
601
|
+
if (!returnNoneDisplayed || !returnDefaults) {
|
|
603
602
|
continue;
|
|
604
603
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
604
|
+
}
|
|
605
|
+
if (!['collection', 'fixedCollection'].includes(nodeProperties.type)) {
|
|
606
|
+
// Is a simple property so can be set as it is
|
|
607
|
+
if (duplicateParameterNames.includes(nodeProperties.name)) {
|
|
608
|
+
if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeTypeDescription, nodeValuesRoot)) {
|
|
608
609
|
continue;
|
|
609
610
|
}
|
|
610
611
|
}
|
|
611
|
-
if (
|
|
612
|
-
//
|
|
613
|
-
if (
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
612
|
+
if (returnDefaults) {
|
|
613
|
+
// Set also when it has the default value
|
|
614
|
+
if (['boolean', 'number', 'options'].includes(nodeProperties.type)) {
|
|
615
|
+
// Boolean, numbers and options are special as false and 0 are valid values
|
|
616
|
+
// and should not be replaced with default value
|
|
617
|
+
nodeParameters[nodeProperties.name] =
|
|
618
|
+
nodeValues[nodeProperties.name] !== undefined
|
|
619
|
+
? (0, utils_1.deepCopy)(nodeValues[nodeProperties.name])
|
|
620
|
+
: nodeProperties.default;
|
|
617
621
|
}
|
|
618
|
-
if (
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
nodeValues[nodeProperties.name] !== undefined
|
|
625
|
-
? (0, utils_1.deepCopy)(nodeValues[nodeProperties.name])
|
|
626
|
-
: nodeProperties.default;
|
|
627
|
-
}
|
|
628
|
-
else if (nodeProperties.type === 'resourceLocator' &&
|
|
629
|
-
typeof nodeProperties.default === 'object') {
|
|
630
|
-
nodeParameters[nodeProperties.name] =
|
|
631
|
-
nodeValues[nodeProperties.name] !== undefined
|
|
632
|
-
? (0, utils_1.deepCopy)(nodeValues[nodeProperties.name])
|
|
633
|
-
: { __rl: true, ...nodeProperties.default };
|
|
634
|
-
}
|
|
635
|
-
else if (
|
|
636
|
-
// Filter parameters may be missing "combinator" or "options" and
|
|
637
|
-
// still be considered valid (e.g. happens when generated by AI).
|
|
638
|
-
// this patches in the same way the UI does in FilterConditions.vue
|
|
639
|
-
nodeProperties.type === 'filter' &&
|
|
640
|
-
nodeValues[nodeProperties.name] !== undefined &&
|
|
641
|
-
typeof nodeValues[nodeProperties.name] === 'object' &&
|
|
642
|
-
nodeValues[nodeProperties.name] !== null) {
|
|
643
|
-
const defaultOptions = {
|
|
644
|
-
caseSensitive: true,
|
|
645
|
-
leftValue: '',
|
|
646
|
-
typeValidation: 'strict',
|
|
647
|
-
version: 1,
|
|
648
|
-
};
|
|
649
|
-
const filter = (0, utils_1.deepCopy)(nodeValues[nodeProperties.name]);
|
|
650
|
-
filter.combinator ??= 'and';
|
|
651
|
-
filter.options = { ...defaultOptions, ...filter.options };
|
|
652
|
-
nodeParameters[nodeProperties.name] = filter;
|
|
653
|
-
}
|
|
654
|
-
else {
|
|
655
|
-
nodeParameters[nodeProperties.name] =
|
|
656
|
-
(0, utils_1.deepCopy)(nodeValues[nodeProperties.name]) ?? nodeProperties.default;
|
|
657
|
-
}
|
|
658
|
-
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
622
|
+
else if (nodeProperties.type === 'resourceLocator' &&
|
|
623
|
+
typeof nodeProperties.default === 'object') {
|
|
624
|
+
nodeParameters[nodeProperties.name] =
|
|
625
|
+
nodeValues[nodeProperties.name] !== undefined
|
|
626
|
+
? (0, utils_1.deepCopy)(nodeValues[nodeProperties.name])
|
|
627
|
+
: { __rl: true, ...nodeProperties.default };
|
|
659
628
|
}
|
|
660
|
-
else if (
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
629
|
+
else if (
|
|
630
|
+
// Filter parameters may be missing "combinator" or "options" and
|
|
631
|
+
// still be considered valid (e.g. happens when generated by AI).
|
|
632
|
+
// this patches in the same way the UI does in FilterConditions.vue
|
|
633
|
+
nodeProperties.type === 'filter' &&
|
|
634
|
+
nodeValues[nodeProperties.name] !== undefined &&
|
|
635
|
+
typeof nodeValues[nodeProperties.name] === 'object' &&
|
|
636
|
+
nodeValues[nodeProperties.name] !== null) {
|
|
637
|
+
const defaultOptions = {
|
|
638
|
+
caseSensitive: true,
|
|
639
|
+
leftValue: '',
|
|
640
|
+
typeValidation: 'strict',
|
|
641
|
+
version: 1,
|
|
642
|
+
};
|
|
643
|
+
const filter = (0, utils_1.deepCopy)(nodeValues[nodeProperties.name]);
|
|
644
|
+
filter.combinator ??= 'and';
|
|
645
|
+
filter.options = { ...defaultOptions, ...filter.options };
|
|
646
|
+
nodeParameters[nodeProperties.name] = filter;
|
|
669
647
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
// A lone $fromAI() placeholder must keep its "=" or the AI tool call never resolves it (#30531)
|
|
674
|
-
if ((0, expression_helpers_1.isExpression)(value) && !(0, from_ai_parse_utils_1.isFromAIOnlyExpression)(value)) {
|
|
675
|
-
nodeParameters[nodeProperties.name] = value.slice(1);
|
|
676
|
-
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
677
|
-
}
|
|
648
|
+
else {
|
|
649
|
+
nodeParameters[nodeProperties.name] =
|
|
650
|
+
(0, utils_1.deepCopy)(nodeValues[nodeProperties.name]) ?? nodeProperties.default;
|
|
678
651
|
}
|
|
652
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
679
653
|
}
|
|
680
|
-
if (
|
|
681
|
-
|
|
654
|
+
else if ((nodeValues[nodeProperties.name] !== nodeProperties.default &&
|
|
655
|
+
typeof nodeValues[nodeProperties.name] !== 'object') ||
|
|
656
|
+
(typeof nodeValues[nodeProperties.name] === 'object' &&
|
|
657
|
+
!(0, isEqual_1.default)(nodeValues[nodeProperties.name], nodeProperties.default)) ||
|
|
658
|
+
(nodeValues[nodeProperties.name] !== undefined && parentType === 'collection')) {
|
|
659
|
+
// Set only if it is different to the default value
|
|
660
|
+
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeValues[nodeProperties.name]);
|
|
661
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
682
662
|
continue;
|
|
683
663
|
}
|
|
684
|
-
//
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
//
|
|
688
|
-
if (
|
|
689
|
-
nodeProperties.
|
|
690
|
-
// Multiple can be set so will be an array
|
|
691
|
-
// Return directly the values like they are
|
|
692
|
-
if (nodeValues[nodeProperties.name] !== undefined) {
|
|
693
|
-
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeValues[nodeProperties.name]);
|
|
694
|
-
}
|
|
695
|
-
else if (returnDefaults) {
|
|
696
|
-
// Does not have values defined but defaults should be returned
|
|
697
|
-
if (Array.isArray(nodeProperties.default)) {
|
|
698
|
-
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeProperties.default);
|
|
699
|
-
}
|
|
700
|
-
else {
|
|
701
|
-
// As it is probably wrong for many nodes, do we keep on returning an empty array if
|
|
702
|
-
// anything else than an array is set as default
|
|
703
|
-
nodeParameters[nodeProperties.name] = [];
|
|
704
|
-
}
|
|
705
|
-
}
|
|
664
|
+
// Strip expression prefix if noDataExpression is true
|
|
665
|
+
if (nodeProperties.noDataExpression && nodeParameters[nodeProperties.name] !== undefined) {
|
|
666
|
+
const value = nodeParameters[nodeProperties.name];
|
|
667
|
+
// A lone $fromAI() placeholder must keep its "=" or the AI tool call never resolves it (#30531)
|
|
668
|
+
if ((0, expression_helpers_1.isExpression)(value) && !(0, from_ai_parse_utils_1.isFromAIOnlyExpression)(value)) {
|
|
669
|
+
nodeParameters[nodeProperties.name] = value.slice(1);
|
|
706
670
|
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
707
671
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (onlySimpleTypes) {
|
|
675
|
+
// It is only supposed to resolve the simple types. So continue.
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
// Is a complex property so check lower levels
|
|
679
|
+
let tempValue;
|
|
680
|
+
if (nodeProperties.type === 'collection') {
|
|
681
|
+
// Is collection
|
|
682
|
+
if (nodeProperties.typeOptions !== undefined &&
|
|
683
|
+
nodeProperties.typeOptions.multipleValues === true) {
|
|
684
|
+
// Multiple can be set so will be an array
|
|
685
|
+
// Return directly the values like they are
|
|
686
|
+
if (nodeValues[nodeProperties.name] !== undefined) {
|
|
687
|
+
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeValues[nodeProperties.name]);
|
|
720
688
|
}
|
|
721
689
|
else if (returnDefaults) {
|
|
722
690
|
// Does not have values defined but defaults should be returned
|
|
723
|
-
|
|
724
|
-
|
|
691
|
+
if (Array.isArray(nodeProperties.default)) {
|
|
692
|
+
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeProperties.default);
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
// As it is probably wrong for many nodes, do we keep on returning an empty array if
|
|
696
|
+
// anything else than an array is set as default
|
|
697
|
+
nodeParameters[nodeProperties.name] = [];
|
|
698
|
+
}
|
|
725
699
|
}
|
|
700
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
726
701
|
}
|
|
727
|
-
else if (nodeProperties.
|
|
728
|
-
//
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
702
|
+
else if (nodeValues[nodeProperties.name] !== undefined) {
|
|
703
|
+
// Has values defined so get them
|
|
704
|
+
const tempNodeParameters = getNodeParameters(nodeProperties.options, nodeValues[nodeProperties.name], returnDefaults, returnNoneDisplayed, node, nodeTypeDescription, {
|
|
705
|
+
onlySimpleTypes: false,
|
|
706
|
+
dataIsResolved: false,
|
|
707
|
+
nodeValuesRoot,
|
|
708
|
+
parentType: nodeProperties.type,
|
|
709
|
+
});
|
|
710
|
+
if (tempNodeParameters !== null) {
|
|
711
|
+
nodeParameters[nodeProperties.name] = tempNodeParameters;
|
|
712
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
738
713
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
714
|
+
}
|
|
715
|
+
else if (returnDefaults) {
|
|
716
|
+
// Does not have values defined but defaults should be returned
|
|
717
|
+
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeProperties.default);
|
|
718
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
else if (nodeProperties.type === 'fixedCollection') {
|
|
722
|
+
// Is fixedCollection
|
|
723
|
+
const collectionValues = {};
|
|
724
|
+
let tempNodeParameters;
|
|
725
|
+
let tempNodePropertiesArray;
|
|
726
|
+
let nodePropertyOptions;
|
|
727
|
+
let propertyValues = (0, utils_1.deepCopy)(nodeValues[nodeProperties.name]);
|
|
728
|
+
if (returnDefaults) {
|
|
729
|
+
if (propertyValues === undefined) {
|
|
730
|
+
propertyValues = (0, utils_1.deepCopy)(nodeProperties.default);
|
|
747
731
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
732
|
+
}
|
|
733
|
+
if (!returnDefaults &&
|
|
734
|
+
nodeProperties.typeOptions?.multipleValues === false &&
|
|
735
|
+
propertyValues &&
|
|
736
|
+
Object.keys(propertyValues).length === 0) {
|
|
737
|
+
// For fixedCollections, which only allow one value, it is important to still return
|
|
738
|
+
// the empty object which indicates that a value got added, even if it does not have
|
|
739
|
+
// anything set. If that is not done, the value would get lost.
|
|
740
|
+
return (0, utils_1.deepCopy)(nodeValues);
|
|
741
|
+
}
|
|
742
|
+
// Track if any visible fields were processed across all collection items
|
|
743
|
+
let hadAnyVisibleFields = false;
|
|
744
|
+
// Iterate over all collections
|
|
745
|
+
for (const itemName of Object.keys(propertyValues || {})) {
|
|
746
|
+
if (nodeProperties.typeOptions !== undefined &&
|
|
747
|
+
nodeProperties.typeOptions.multipleValues === true) {
|
|
748
|
+
// Multiple can be set so will be an array
|
|
749
|
+
const tempArrayValue = [];
|
|
750
|
+
// Collection values should always be an object
|
|
751
|
+
if (typeof propertyValues !== 'object' || Array.isArray(propertyValues)) {
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
nodePropertyOptions = nodeProperties.options.find((nodePropertyOptions) => nodePropertyOptions.name === itemName);
|
|
755
|
+
if (nodePropertyOptions === undefined) {
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
// Iterate over all items as it contains multiple ones
|
|
759
|
+
for (const nodeValue of propertyValues[itemName]) {
|
|
760
|
+
tempNodePropertiesArray = nodePropertyOptions.values;
|
|
761
|
+
tempValue = getNodeParameters(tempNodePropertiesArray, nodeValue, returnDefaults, returnNoneDisplayed, node, nodeTypeDescription, {
|
|
762
|
+
onlySimpleTypes: false,
|
|
763
|
+
dataIsResolved: false,
|
|
764
|
+
nodeValuesRoot,
|
|
765
|
+
parentType: nodeProperties.type,
|
|
766
|
+
});
|
|
767
|
+
if (tempValue !== null) {
|
|
768
|
+
tempArrayValue.push(tempValue);
|
|
776
769
|
}
|
|
777
|
-
collectionValues[itemName] = tempArrayValue;
|
|
778
770
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
771
|
+
collectionValues[itemName] = tempArrayValue;
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
// Only one can be set so is an object of objects
|
|
775
|
+
tempNodeParameters = {};
|
|
776
|
+
let hadVisibleFields = false;
|
|
777
|
+
// Get the options of the current item
|
|
778
|
+
const nodePropertyOptions = nodeProperties.options.find((data) => data.name === itemName);
|
|
779
|
+
if (nodePropertyOptions !== undefined) {
|
|
780
|
+
tempNodePropertiesArray = nodePropertyOptions.values;
|
|
781
|
+
const itemNodeValues = nodeValues[nodeProperties.name][itemName];
|
|
782
|
+
tempValue = getNodeParameters(tempNodePropertiesArray, itemNodeValues, returnDefaults, returnNoneDisplayed, node, nodeTypeDescription, {
|
|
783
|
+
onlySimpleTypes: false,
|
|
784
|
+
dataIsResolved: false,
|
|
785
|
+
nodeValuesRoot,
|
|
786
|
+
parentType: nodeProperties.type,
|
|
787
|
+
});
|
|
788
|
+
if (tempValue !== null) {
|
|
789
|
+
Object.assign(tempNodeParameters, tempValue);
|
|
790
|
+
if (Object.keys(tempValue).length > 0) {
|
|
791
|
+
// tempValue has content, so fields are visible
|
|
792
|
+
hadVisibleFields = true;
|
|
793
|
+
hadAnyVisibleFields = true;
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
// tempValue is empty. Check if user provided non-default values that got filtered
|
|
797
|
+
const hasNonDefaultValues = itemNodeValues &&
|
|
798
|
+
Object.keys(itemNodeValues).some((key) => {
|
|
799
|
+
const field = tempNodePropertiesArray.find((f) => f.name === key);
|
|
800
|
+
return field && !(0, isEqual_1.default)(itemNodeValues[key], field.default);
|
|
801
|
+
});
|
|
802
|
+
if (!hasNonDefaultValues) {
|
|
803
|
+
// All values are defaults, so the collection is explicitly added with default values
|
|
804
|
+
// We should preserve this (GitHub case)
|
|
798
805
|
hadVisibleFields = true;
|
|
799
806
|
hadAnyVisibleFields = true;
|
|
800
807
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
const hasNonDefaultValues = itemNodeValues &&
|
|
804
|
-
Object.keys(itemNodeValues).some((key) => {
|
|
805
|
-
const field = tempNodePropertiesArray.find((f) => f.name === key);
|
|
806
|
-
return field && !(0, isEqual_1.default)(itemNodeValues[key], field.default);
|
|
807
|
-
});
|
|
808
|
-
if (!hasNonDefaultValues) {
|
|
809
|
-
// All values are defaults, so the collection is explicitly added with default values
|
|
810
|
-
// We should preserve this (GitHub case)
|
|
811
|
-
hadVisibleFields = true;
|
|
812
|
-
hadAnyVisibleFields = true;
|
|
813
|
-
}
|
|
814
|
-
// If hasNonDefaultValues is true, values were filtered by displayOptions (test case)
|
|
815
|
-
// So we don't set hadVisibleFields
|
|
816
|
-
}
|
|
808
|
+
// If hasNonDefaultValues is true, values were filtered by displayOptions (test case)
|
|
809
|
+
// So we don't set hadVisibleFields
|
|
817
810
|
}
|
|
818
811
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
812
|
+
}
|
|
813
|
+
if (Object.keys(tempNodeParameters).length !== 0) {
|
|
814
|
+
collectionValues[itemName] = tempNodeParameters;
|
|
815
|
+
}
|
|
816
|
+
else if (!returnDefaults &&
|
|
817
|
+
hadVisibleFields &&
|
|
818
|
+
propertyValues &&
|
|
819
|
+
propertyValues[itemName] !== undefined) {
|
|
820
|
+
// Preserve explicitly set empty collections when the user added an option
|
|
821
|
+
// that contains only default values. Only preserve if there were visible fields
|
|
822
|
+
// (hadVisibleFields), otherwise the collection is empty because all fields
|
|
823
|
+
// are hidden by displayOptions.
|
|
824
|
+
collectionValues[itemName] = tempNodeParameters;
|
|
832
825
|
}
|
|
833
826
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
else {
|
|
860
|
-
nodeParameters[nodeProperties.name] = collectionValues;
|
|
861
|
-
}
|
|
862
|
-
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
827
|
+
}
|
|
828
|
+
if (!returnDefaults &&
|
|
829
|
+
hadAnyVisibleFields &&
|
|
830
|
+
nodeProperties.typeOptions?.multipleValues === false &&
|
|
831
|
+
collectionValues &&
|
|
832
|
+
Object.keys(collectionValues).length === 0 &&
|
|
833
|
+
propertyValues &&
|
|
834
|
+
propertyValues?.constructor.name === 'Object' &&
|
|
835
|
+
Object.keys(propertyValues).length !== 0) {
|
|
836
|
+
// For fixedCollections, which only allow one value, it is important to still return
|
|
837
|
+
// the object with an empty collection property which indicates that a value got added
|
|
838
|
+
// which contains all default values. Only preserve if there were visible fields,
|
|
839
|
+
// otherwise the collection is empty because all fields are hidden by displayOptions.
|
|
840
|
+
const returnValue = {};
|
|
841
|
+
Object.keys(propertyValues || {}).forEach((value) => {
|
|
842
|
+
returnValue[value] = {};
|
|
843
|
+
});
|
|
844
|
+
nodeParameters[nodeProperties.name] = returnValue;
|
|
845
|
+
}
|
|
846
|
+
if (Object.keys(collectionValues).length !== 0 || returnDefaults) {
|
|
847
|
+
// Set only if value got found
|
|
848
|
+
if (returnDefaults) {
|
|
849
|
+
// Set also when it has the default value
|
|
850
|
+
if (collectionValues === undefined) {
|
|
851
|
+
nodeParameters[nodeProperties.name] = (0, utils_1.deepCopy)(nodeProperties.default);
|
|
863
852
|
}
|
|
864
|
-
else
|
|
865
|
-
// Set only if values got found and it is not the default
|
|
853
|
+
else {
|
|
866
854
|
nodeParameters[nodeProperties.name] = collectionValues;
|
|
867
|
-
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
868
855
|
}
|
|
856
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
857
|
+
}
|
|
858
|
+
else if (collectionValues !== nodeProperties.default) {
|
|
859
|
+
// Set only if values got found and it is not the default
|
|
860
|
+
nodeParameters[nodeProperties.name] = collectionValues;
|
|
861
|
+
nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
|
|
869
862
|
}
|
|
870
863
|
}
|
|
871
864
|
}
|
|
872
|
-
return nodeParameters;
|
|
873
|
-
}
|
|
874
|
-
/**
|
|
875
|
-
* Returns the webhook path
|
|
876
|
-
*/
|
|
877
|
-
function getNodeWebhookPath(workflowId, node, path, isFullPath, restartWebhook) {
|
|
878
|
-
let webhookPath = '';
|
|
879
|
-
if (restartWebhook === true) {
|
|
880
|
-
return path;
|
|
881
|
-
}
|
|
882
|
-
if (node.webhookId === undefined) {
|
|
883
|
-
const nodeName = encodeURIComponent(node.name.toLowerCase());
|
|
884
|
-
webhookPath = `${workflowId}/${nodeName}/${path}`;
|
|
885
|
-
}
|
|
886
|
-
else {
|
|
887
|
-
if (isFullPath === true) {
|
|
888
|
-
return path || node.webhookId;
|
|
889
|
-
}
|
|
890
|
-
webhookPath = `${node.webhookId}/${path}`;
|
|
891
|
-
}
|
|
892
|
-
return webhookPath;
|
|
893
|
-
}
|
|
894
|
-
/**
|
|
895
|
-
* Returns the webhook URL
|
|
896
|
-
*/
|
|
897
|
-
function getNodeWebhookUrl(baseUrl, workflowId, node, path, isFullPath) {
|
|
898
|
-
if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
|
|
899
|
-
// setting this to false to prefix the webhookId
|
|
900
|
-
isFullPath = false;
|
|
901
|
-
}
|
|
902
|
-
if (path.startsWith('/')) {
|
|
903
|
-
path = path.slice(1);
|
|
904
|
-
}
|
|
905
|
-
return `${baseUrl}/${getNodeWebhookPath(workflowId, node, path, isFullPath)}`;
|
|
906
|
-
}
|
|
907
|
-
/**
|
|
908
|
-
* Assigns a webhookId to a node if its type has webhook definitions
|
|
909
|
-
* and the node doesn't already have one.
|
|
910
|
-
*/
|
|
911
|
-
function resolveNodeWebhookId(node, nodeTypeDescription) {
|
|
912
|
-
if (nodeTypeDescription.webhooks?.length && !node.webhookId) {
|
|
913
|
-
node.webhookId = (0, uuid_1.v4)();
|
|
914
|
-
}
|
|
915
865
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
866
|
+
return nodeParameters;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Returns the webhook path
|
|
870
|
+
*/
|
|
871
|
+
function getNodeWebhookPath(workflowId, node, path, isFullPath, restartWebhook) {
|
|
872
|
+
let webhookPath = '';
|
|
873
|
+
if (restartWebhook === true) {
|
|
874
|
+
return path;
|
|
875
|
+
}
|
|
876
|
+
if (node.webhookId === undefined) {
|
|
877
|
+
const nodeName = encodeURIComponent(node.name.toLowerCase());
|
|
878
|
+
webhookPath = `${workflowId}/${nodeName}/${path}`;
|
|
925
879
|
}
|
|
926
|
-
|
|
927
|
-
if (
|
|
928
|
-
return
|
|
880
|
+
else {
|
|
881
|
+
if (isFullPath === true) {
|
|
882
|
+
return path || node.webhookId;
|
|
929
883
|
}
|
|
884
|
+
webhookPath = `${node.webhookId}/${path}`;
|
|
885
|
+
}
|
|
886
|
+
return webhookPath;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Returns the webhook URL
|
|
890
|
+
*/
|
|
891
|
+
function getNodeWebhookUrl(baseUrl, workflowId, node, path, isFullPath) {
|
|
892
|
+
if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
|
|
893
|
+
// setting this to false to prefix the webhookId
|
|
894
|
+
isFullPath = false;
|
|
895
|
+
}
|
|
896
|
+
if (path.startsWith('/')) {
|
|
897
|
+
path = path.slice(1);
|
|
898
|
+
}
|
|
899
|
+
return `${baseUrl}/${getNodeWebhookPath(workflowId, node, path, isFullPath)}`;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Assigns a webhookId to a node if its type has webhook definitions
|
|
903
|
+
* and the node doesn't already have one.
|
|
904
|
+
*/
|
|
905
|
+
function resolveNodeWebhookId(node, nodeTypeDescription) {
|
|
906
|
+
if (nodeTypeDescription.webhooks?.length && !node.webhookId) {
|
|
907
|
+
node.webhookId = (0, uuid_1.v4)();
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function getConnectionTypes(connections) {
|
|
911
|
+
return connections
|
|
912
|
+
.map((connection) => {
|
|
913
|
+
if (typeof connection === 'string') {
|
|
914
|
+
return connection;
|
|
915
|
+
}
|
|
916
|
+
return connection.type;
|
|
917
|
+
})
|
|
918
|
+
.filter((connection) => connection !== undefined);
|
|
919
|
+
}
|
|
920
|
+
function getNodeInputs(workflow, node, nodeTypeData) {
|
|
921
|
+
if (Array.isArray(nodeTypeData?.inputs)) {
|
|
922
|
+
return nodeTypeData.inputs;
|
|
923
|
+
}
|
|
924
|
+
// Calculate the outputs dynamically
|
|
925
|
+
try {
|
|
926
|
+
return (workflow.expression.getSimpleParameterValue(node, nodeTypeData.inputs, 'internal', {}) || []);
|
|
927
|
+
}
|
|
928
|
+
catch (e) {
|
|
929
|
+
console.warn('Could not calculate inputs dynamically for node: ', node.name);
|
|
930
|
+
return [];
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
function getNodeOutputs(workflow, node, nodeTypeData) {
|
|
934
|
+
let outputs = [];
|
|
935
|
+
if (!nodeTypeData) {
|
|
936
|
+
return [];
|
|
937
|
+
}
|
|
938
|
+
if (Array.isArray(nodeTypeData.outputs)) {
|
|
939
|
+
outputs = nodeTypeData.outputs;
|
|
940
|
+
}
|
|
941
|
+
else {
|
|
930
942
|
// Calculate the outputs dynamically
|
|
931
943
|
try {
|
|
932
|
-
|
|
944
|
+
const result = workflow.expression.getSimpleParameterValue(node, nodeTypeData.outputs, 'internal', {});
|
|
945
|
+
outputs = Array.isArray(result)
|
|
946
|
+
? result
|
|
947
|
+
: [];
|
|
933
948
|
}
|
|
934
949
|
catch (e) {
|
|
935
|
-
console.warn('Could not calculate
|
|
936
|
-
return [];
|
|
950
|
+
console.warn('Could not calculate outputs dynamically for node: ', node.name);
|
|
937
951
|
}
|
|
938
952
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
outputs
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
try {
|
|
950
|
-
const result = workflow.expression.getSimpleParameterValue(node, nodeTypeData.outputs, 'internal', {});
|
|
951
|
-
outputs = Array.isArray(result)
|
|
952
|
-
? result
|
|
953
|
-
: [];
|
|
954
|
-
}
|
|
955
|
-
catch (e) {
|
|
956
|
-
console.warn('Could not calculate outputs dynamically for node: ', node.name);
|
|
953
|
+
if (node.onError === 'continueErrorOutput') {
|
|
954
|
+
// Copy the data to make sure that we do not change the data of the
|
|
955
|
+
// node type and so change the displayNames for all nodes in the flow
|
|
956
|
+
outputs = (0, utils_1.deepCopy)(outputs);
|
|
957
|
+
if (outputs.length === 1) {
|
|
958
|
+
// Set the displayName to "Success"
|
|
959
|
+
if (typeof outputs[0] === 'string') {
|
|
960
|
+
outputs[0] = {
|
|
961
|
+
type: outputs[0],
|
|
962
|
+
};
|
|
957
963
|
}
|
|
964
|
+
outputs[0].displayName = 'Success';
|
|
965
|
+
}
|
|
966
|
+
return [
|
|
967
|
+
...outputs,
|
|
968
|
+
{
|
|
969
|
+
category: 'error',
|
|
970
|
+
type: interfaces_1.NodeConnectionTypes.Main,
|
|
971
|
+
displayName: 'Error',
|
|
972
|
+
},
|
|
973
|
+
];
|
|
974
|
+
}
|
|
975
|
+
return outputs;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Returns all the parameter-issues of the node
|
|
979
|
+
*
|
|
980
|
+
* @param {INodeProperties[]} nodePropertiesArray The properties of the node
|
|
981
|
+
* @param {INode} node The data of the node
|
|
982
|
+
*/
|
|
983
|
+
function getNodeParametersIssues(nodePropertiesArray, node, nodeTypeDescription, pinDataNodeNames) {
|
|
984
|
+
const foundIssues = {};
|
|
985
|
+
let propertyIssues;
|
|
986
|
+
if (node.disabled === true || pinDataNodeNames?.includes(node.name)) {
|
|
987
|
+
// Ignore issues on disabled and pindata nodes
|
|
988
|
+
return null;
|
|
989
|
+
}
|
|
990
|
+
for (const nodeProperty of nodePropertiesArray) {
|
|
991
|
+
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '', node, nodeTypeDescription);
|
|
992
|
+
mergeIssues(foundIssues, propertyIssues);
|
|
993
|
+
}
|
|
994
|
+
if (Object.keys(foundIssues).length === 0) {
|
|
995
|
+
return null;
|
|
996
|
+
}
|
|
997
|
+
return foundIssues;
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Returns the node's issues as a flat list of human-readable strings,
|
|
1001
|
+
* covering execution errors, parameter/credential/input issues, and unknown node types.
|
|
1002
|
+
*/
|
|
1003
|
+
function nodeIssuesToString(issues, node) {
|
|
1004
|
+
const messages = [];
|
|
1005
|
+
if (issues.execution !== undefined) {
|
|
1006
|
+
messages.push('Execution Error.');
|
|
1007
|
+
}
|
|
1008
|
+
for (const propertyIssues of [issues.parameters, issues.credentials, issues.input]) {
|
|
1009
|
+
if (propertyIssues === undefined)
|
|
1010
|
+
continue;
|
|
1011
|
+
for (const parameterName of Object.keys(propertyIssues)) {
|
|
1012
|
+
messages.push(...propertyIssues[parameterName]);
|
|
958
1013
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1014
|
+
}
|
|
1015
|
+
if (issues.typeUnknown !== undefined) {
|
|
1016
|
+
messages.push(node !== undefined ? `Node Type "${node.type}" is not known.` : 'Node Type is not known.');
|
|
1017
|
+
}
|
|
1018
|
+
return messages;
|
|
1019
|
+
}
|
|
1020
|
+
/*
|
|
1021
|
+
* Validates resource locator node parameters based on validation ruled defined in each parameter mode
|
|
1022
|
+
*/
|
|
1023
|
+
const validateResourceLocatorParameter = (value, parameterMode) => {
|
|
1024
|
+
const valueToValidate = value?.value?.toString() || '';
|
|
1025
|
+
if (valueToValidate.startsWith('=')) {
|
|
1026
|
+
return [];
|
|
1027
|
+
}
|
|
1028
|
+
const validationErrors = [];
|
|
1029
|
+
// Each mode can have multiple validations specified
|
|
1030
|
+
if (parameterMode.validation) {
|
|
1031
|
+
for (const validation of parameterMode.validation) {
|
|
1032
|
+
if (validation && validation.type === 'regex') {
|
|
1033
|
+
const regexValidation = validation;
|
|
1034
|
+
const regex = new RegExp(`^${regexValidation.properties.regex}$`);
|
|
1035
|
+
if (!regex.test(valueToValidate)) {
|
|
1036
|
+
validationErrors.push(regexValidation.properties.errorMessage);
|
|
969
1037
|
}
|
|
970
|
-
outputs[0].displayName = 'Success';
|
|
971
1038
|
}
|
|
972
|
-
return [
|
|
973
|
-
...outputs,
|
|
974
|
-
{
|
|
975
|
-
category: 'error',
|
|
976
|
-
type: interfaces_1.NodeConnectionTypes.Main,
|
|
977
|
-
displayName: 'Error',
|
|
978
|
-
},
|
|
979
|
-
];
|
|
980
|
-
}
|
|
981
|
-
return outputs;
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Returns all the parameter-issues of the node
|
|
985
|
-
*
|
|
986
|
-
* @param {INodeProperties[]} nodePropertiesArray The properties of the node
|
|
987
|
-
* @param {INode} node The data of the node
|
|
988
|
-
*/
|
|
989
|
-
function getNodeParametersIssues(nodePropertiesArray, node, nodeTypeDescription, pinDataNodeNames) {
|
|
990
|
-
const foundIssues = {};
|
|
991
|
-
let propertyIssues;
|
|
992
|
-
if (node.disabled === true || pinDataNodeNames?.includes(node.name)) {
|
|
993
|
-
// Ignore issues on disabled and pindata nodes
|
|
994
|
-
return null;
|
|
995
|
-
}
|
|
996
|
-
for (const nodeProperty of nodePropertiesArray) {
|
|
997
|
-
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '', node, nodeTypeDescription);
|
|
998
|
-
mergeIssues(foundIssues, propertyIssues);
|
|
999
1039
|
}
|
|
1000
|
-
if (Object.keys(foundIssues).length === 0) {
|
|
1001
|
-
return null;
|
|
1002
|
-
}
|
|
1003
|
-
return foundIssues;
|
|
1004
1040
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1041
|
+
return validationErrors;
|
|
1042
|
+
};
|
|
1043
|
+
/*
|
|
1044
|
+
* Validates resource mapper values based on service schema
|
|
1045
|
+
*/
|
|
1046
|
+
const validateResourceMapperParameter = (nodeProperties, value, skipRequiredCheck = false) => {
|
|
1047
|
+
// No issues to raise in automatic mapping mode, no user input to validate
|
|
1048
|
+
if (value.mappingMode === 'autoMapInputData') {
|
|
1049
|
+
return {};
|
|
1050
|
+
}
|
|
1051
|
+
const issues = {};
|
|
1052
|
+
let fieldWordSingular = nodeProperties.typeOptions?.resourceMapper?.fieldWords?.singular || 'Field';
|
|
1053
|
+
fieldWordSingular = fieldWordSingular.charAt(0).toUpperCase() + fieldWordSingular.slice(1);
|
|
1054
|
+
value.schema.forEach((field) => {
|
|
1055
|
+
const fieldValue = value.value ? value.value[field.id] : null;
|
|
1056
|
+
const key = `${nodeProperties.name}.${field.id}`;
|
|
1057
|
+
const fieldErrors = [];
|
|
1058
|
+
if (field.required && !skipRequiredCheck) {
|
|
1059
|
+
if (value.value === null || fieldValue === undefined) {
|
|
1060
|
+
const error = `${fieldWordSingular} "${field.id}" is required`;
|
|
1061
|
+
fieldErrors.push(error);
|
|
1019
1062
|
}
|
|
1020
1063
|
}
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
* Validates resource locator node parameters based on validation ruled defined in each parameter mode
|
|
1028
|
-
*/
|
|
1029
|
-
const validateResourceLocatorParameter = (value, parameterMode) => {
|
|
1030
|
-
const valueToValidate = value?.value?.toString() || '';
|
|
1031
|
-
if (valueToValidate.startsWith('=')) {
|
|
1032
|
-
return [];
|
|
1033
|
-
}
|
|
1034
|
-
const validationErrors = [];
|
|
1035
|
-
// Each mode can have multiple validations specified
|
|
1036
|
-
if (parameterMode.validation) {
|
|
1037
|
-
for (const validation of parameterMode.validation) {
|
|
1038
|
-
if (validation && validation.type === 'regex') {
|
|
1039
|
-
const regexValidation = validation;
|
|
1040
|
-
const regex = new RegExp(`^${regexValidation.properties.regex}$`);
|
|
1041
|
-
if (!regex.test(valueToValidate)) {
|
|
1042
|
-
validationErrors.push(regexValidation.properties.errorMessage);
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1064
|
+
if (!fieldValue?.toString().startsWith('=') && field.type) {
|
|
1065
|
+
const validationResult = (0, type_validation_1.validateFieldType)(field.id, fieldValue, field.type, {
|
|
1066
|
+
valueOptions: field.options,
|
|
1067
|
+
});
|
|
1068
|
+
if (!validationResult.valid && validationResult.errorMessage) {
|
|
1069
|
+
fieldErrors.push(validationResult.errorMessage);
|
|
1045
1070
|
}
|
|
1046
1071
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
/*
|
|
1050
|
-
* Validates resource mapper values based on service schema
|
|
1051
|
-
*/
|
|
1052
|
-
const validateResourceMapperParameter = (nodeProperties, value, skipRequiredCheck = false) => {
|
|
1053
|
-
// No issues to raise in automatic mapping mode, no user input to validate
|
|
1054
|
-
if (value.mappingMode === 'autoMapInputData') {
|
|
1055
|
-
return {};
|
|
1072
|
+
if (fieldErrors.length > 0) {
|
|
1073
|
+
issues[key] = fieldErrors;
|
|
1056
1074
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
const error = `${fieldWordSingular} "${field.id}" is required`;
|
|
1067
|
-
fieldErrors.push(error);
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
if (!fieldValue?.toString().startsWith('=') && field.type) {
|
|
1071
|
-
const validationResult = (0, type_validation_1.validateFieldType)(field.id, fieldValue, field.type, {
|
|
1072
|
-
valueOptions: field.options,
|
|
1073
|
-
});
|
|
1074
|
-
if (!validationResult.valid && validationResult.errorMessage) {
|
|
1075
|
-
fieldErrors.push(validationResult.errorMessage);
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
if (fieldErrors.length > 0) {
|
|
1079
|
-
issues[key] = fieldErrors;
|
|
1080
|
-
}
|
|
1075
|
+
});
|
|
1076
|
+
return issues;
|
|
1077
|
+
};
|
|
1078
|
+
const validateParameter = (nodeProperties, value, type) => {
|
|
1079
|
+
const nodeName = nodeProperties.name;
|
|
1080
|
+
const options = type === 'options' ? nodeProperties.options : undefined;
|
|
1081
|
+
if (!value?.toString().startsWith('=')) {
|
|
1082
|
+
const validationResult = (0, type_validation_1.validateFieldType)(nodeName, value, type, {
|
|
1083
|
+
valueOptions: options,
|
|
1081
1084
|
});
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
const validateParameter = (nodeProperties, value, type) => {
|
|
1085
|
-
const nodeName = nodeProperties.name;
|
|
1086
|
-
const options = type === 'options' ? nodeProperties.options : undefined;
|
|
1087
|
-
if (!value?.toString().startsWith('=')) {
|
|
1088
|
-
const validationResult = (0, type_validation_1.validateFieldType)(nodeName, value, type, {
|
|
1089
|
-
valueOptions: options,
|
|
1090
|
-
});
|
|
1091
|
-
if (!validationResult.valid && validationResult.errorMessage) {
|
|
1092
|
-
return validationResult.errorMessage;
|
|
1093
|
-
}
|
|
1085
|
+
if (!validationResult.valid && validationResult.errorMessage) {
|
|
1086
|
+
return validationResult.errorMessage;
|
|
1094
1087
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
}
|
|
1118
|
-
if (foundIssues.parameters[nodeProperties.name] === undefined) {
|
|
1119
|
-
foundIssues.parameters[nodeProperties.name] = [];
|
|
1120
|
-
}
|
|
1121
|
-
foundIssues.parameters[nodeProperties.name].push(`Parameter "${nodeProperties.displayName}" is required.`);
|
|
1088
|
+
}
|
|
1089
|
+
return undefined;
|
|
1090
|
+
};
|
|
1091
|
+
/**
|
|
1092
|
+
* Adds an issue if the parameter is not defined
|
|
1093
|
+
*
|
|
1094
|
+
* @param {INodeIssues} foundIssues The already found issues
|
|
1095
|
+
* @param {INodeProperties} nodeProperties The properties of the node
|
|
1096
|
+
* @param {NodeParameterValue} value The value of the parameter
|
|
1097
|
+
*/
|
|
1098
|
+
function addToIssuesIfMissing(foundIssues, nodeProperties, value) {
|
|
1099
|
+
// TODO: Check what it really has when undefined
|
|
1100
|
+
if ((nodeProperties.type === 'string' && (value === '' || value === undefined)) ||
|
|
1101
|
+
(nodeProperties.type === 'multiOptions' && Array.isArray(value) && value.length === 0) ||
|
|
1102
|
+
(nodeProperties.type === 'dateTime' && (value === '' || value === undefined)) ||
|
|
1103
|
+
(nodeProperties.type === 'options' && (value === '' || value === undefined)) ||
|
|
1104
|
+
((nodeProperties.type === 'resourceLocator' ||
|
|
1105
|
+
nodeProperties.type === 'workflowSelector' ||
|
|
1106
|
+
nodeProperties.type === 'agentSelector') &&
|
|
1107
|
+
!(0, type_guards_1.isValidResourceLocatorParameterValue)(value))) {
|
|
1108
|
+
// Parameter is required but empty
|
|
1109
|
+
if (foundIssues.parameters === undefined) {
|
|
1110
|
+
foundIssues.parameters = {};
|
|
1122
1111
|
}
|
|
1112
|
+
if (foundIssues.parameters[nodeProperties.name] === undefined) {
|
|
1113
|
+
foundIssues.parameters[nodeProperties.name] = [];
|
|
1114
|
+
}
|
|
1115
|
+
foundIssues.parameters[nodeProperties.name].push(`Parameter "${nodeProperties.displayName}" is required.`);
|
|
1123
1116
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
}
|
|
1160
|
-
else {
|
|
1161
|
-
return undefined;
|
|
1162
|
-
}
|
|
1163
|
-
if (!property)
|
|
1164
|
-
return undefined;
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Returns the parameter value
|
|
1120
|
+
*
|
|
1121
|
+
* @param {INodeParameters} nodeValues The values of the node
|
|
1122
|
+
* @param {string} parameterName The name of the parameter to return the value of
|
|
1123
|
+
* @param {string} path The path to the properties
|
|
1124
|
+
*/
|
|
1125
|
+
function getParameterValueByPath(nodeValues, parameterName, path) {
|
|
1126
|
+
return (0, get_1.default)(nodeValues, path ? `${path}.${parameterName}` : parameterName);
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Resolves the property definition for a parameter path, honoring `displayOptions` so that
|
|
1130
|
+
* duplicate-named variants resolve to the one shown for the given node values (e.g. version- or
|
|
1131
|
+
* source-gated parameters). Descends into `collection`/`fixedCollection`; the leading
|
|
1132
|
+
* `parameters.` prefix and array indices in the path are ignored. Returns `undefined` when the
|
|
1133
|
+
* path resolves to no displayed property.
|
|
1134
|
+
*/
|
|
1135
|
+
function findDisplayedProperty(parameterPath, properties, nodeValues, node, nodeTypeDescription) {
|
|
1136
|
+
const parts = parameterPath.replace(/^parameters\./, '').split('.');
|
|
1137
|
+
let currentPath = '';
|
|
1138
|
+
let property;
|
|
1139
|
+
const findProp = (name, options) => options.find((option) => option.name === name &&
|
|
1140
|
+
displayParameterPath(nodeValues, option, currentPath, node, nodeTypeDescription));
|
|
1141
|
+
for (const part of parts) {
|
|
1142
|
+
const name = part.split('[')[0];
|
|
1143
|
+
if (!property) {
|
|
1144
|
+
property = findProp(name, properties);
|
|
1145
|
+
}
|
|
1146
|
+
else if ('options' in property && property.options) {
|
|
1147
|
+
property = findProp(name, property.options);
|
|
1148
|
+
currentPath += `.${name}`;
|
|
1149
|
+
}
|
|
1150
|
+
else if ('values' in property) {
|
|
1151
|
+
property = findProp(name, property.values);
|
|
1152
|
+
currentPath += `.${name}`;
|
|
1165
1153
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
function isINodeParameterResourceLocator(value) {
|
|
1169
|
-
return typeof value === 'object' && value !== null && 'value' in value && 'mode' in value;
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* Returns all the issues with the given node-values
|
|
1173
|
-
*
|
|
1174
|
-
* @param {INodeProperties} nodeProperties The properties of the node
|
|
1175
|
-
* @param {INodeParameters} nodeValues The values of the node
|
|
1176
|
-
* @param {string} path The path to the properties
|
|
1177
|
-
*/
|
|
1178
|
-
// eslint-disable-next-line complexity
|
|
1179
|
-
function getParameterIssues(nodeProperties, nodeValues, path, node, nodeTypeDescription) {
|
|
1180
|
-
const foundIssues = {};
|
|
1181
|
-
const isDisplayed = displayParameterPath(nodeValues, nodeProperties, path, node, nodeTypeDescription);
|
|
1182
|
-
if (nodeProperties.required === true) {
|
|
1183
|
-
if (isDisplayed) {
|
|
1184
|
-
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1185
|
-
if (
|
|
1186
|
-
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
|
1187
|
-
nodeProperties.typeOptions !== undefined &&
|
|
1188
|
-
nodeProperties.typeOptions.multipleValues !== undefined) {
|
|
1189
|
-
// Multiple can be set so will be an array
|
|
1190
|
-
if (Array.isArray(value)) {
|
|
1191
|
-
for (const singleValue of value) {
|
|
1192
|
-
addToIssuesIfMissing(foundIssues, nodeProperties, singleValue);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
else {
|
|
1197
|
-
// Only one can be set so will be a single value
|
|
1198
|
-
addToIssuesIfMissing(foundIssues, nodeProperties, value);
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1154
|
+
else {
|
|
1155
|
+
return undefined;
|
|
1201
1156
|
}
|
|
1202
|
-
if (
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1157
|
+
if (!property)
|
|
1158
|
+
return undefined;
|
|
1159
|
+
}
|
|
1160
|
+
return property;
|
|
1161
|
+
}
|
|
1162
|
+
function isINodeParameterResourceLocator(value) {
|
|
1163
|
+
return typeof value === 'object' && value !== null && 'value' in value && 'mode' in value;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Returns all the issues with the given node-values
|
|
1167
|
+
*
|
|
1168
|
+
* @param {INodeProperties} nodeProperties The properties of the node
|
|
1169
|
+
* @param {INodeParameters} nodeValues The values of the node
|
|
1170
|
+
* @param {string} path The path to the properties
|
|
1171
|
+
*/
|
|
1172
|
+
// eslint-disable-next-line complexity
|
|
1173
|
+
function getParameterIssues(nodeProperties, nodeValues, path, node, nodeTypeDescription) {
|
|
1174
|
+
const foundIssues = {};
|
|
1175
|
+
const isDisplayed = displayParameterPath(nodeValues, nodeProperties, path, node, nodeTypeDescription);
|
|
1176
|
+
if (nodeProperties.required === true) {
|
|
1177
|
+
if (isDisplayed) {
|
|
1206
1178
|
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1207
|
-
if (
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
foundIssues.parameters[nodeProperties.name] = [];
|
|
1217
|
-
}
|
|
1218
|
-
foundIssues.parameters[nodeProperties.name].push(error);
|
|
1219
|
-
});
|
|
1179
|
+
if (
|
|
1180
|
+
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
|
1181
|
+
nodeProperties.typeOptions !== undefined &&
|
|
1182
|
+
nodeProperties.typeOptions.multipleValues !== undefined) {
|
|
1183
|
+
// Multiple can be set so will be an array
|
|
1184
|
+
if (Array.isArray(value)) {
|
|
1185
|
+
for (const singleValue of value) {
|
|
1186
|
+
addToIssuesIfMissing(foundIssues, nodeProperties, singleValue);
|
|
1187
|
+
}
|
|
1220
1188
|
}
|
|
1221
1189
|
}
|
|
1190
|
+
else {
|
|
1191
|
+
// Only one can be set so will be a single value
|
|
1192
|
+
addToIssuesIfMissing(foundIssues, nodeProperties, value);
|
|
1193
|
+
}
|
|
1222
1194
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1195
|
+
}
|
|
1196
|
+
if ((nodeProperties.type === 'resourceLocator' ||
|
|
1197
|
+
nodeProperties.type === 'workflowSelector' ||
|
|
1198
|
+
nodeProperties.type === 'agentSelector') &&
|
|
1199
|
+
isDisplayed) {
|
|
1200
|
+
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1201
|
+
if (isINodeParameterResourceLocator(value)) {
|
|
1202
|
+
const mode = nodeProperties.modes?.find((option) => option.name === value.mode);
|
|
1203
|
+
if (mode) {
|
|
1204
|
+
const errors = validateResourceLocatorParameter(value, mode);
|
|
1205
|
+
errors.forEach((error) => {
|
|
1229
1206
|
if (foundIssues.parameters === undefined) {
|
|
1230
1207
|
foundIssues.parameters = {};
|
|
1231
1208
|
}
|
|
1232
1209
|
if (foundIssues.parameters[nodeProperties.name] === undefined) {
|
|
1233
1210
|
foundIssues.parameters[nodeProperties.name] = [];
|
|
1234
1211
|
}
|
|
1235
|
-
foundIssues.parameters
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
else if (nodeProperties.type === 'filter' && isDisplayed) {
|
|
1240
|
-
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1241
|
-
if ((0, type_guards_1.isFilterValue)(value)) {
|
|
1242
|
-
const issues = (0, filter_parameter_1.validateFilterParameter)(nodeProperties, value);
|
|
1243
|
-
if (Object.keys(issues).length > 0) {
|
|
1244
|
-
foundIssues.parameters = { ...foundIssues.parameters, ...issues };
|
|
1245
|
-
}
|
|
1212
|
+
foundIssues.parameters[nodeProperties.name].push(error);
|
|
1213
|
+
});
|
|
1246
1214
|
}
|
|
1247
1215
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1216
|
+
}
|
|
1217
|
+
else if (nodeProperties.type === 'resourceMapper' && isDisplayed) {
|
|
1218
|
+
const skipRequiredCheck = nodeProperties.typeOptions?.resourceMapper?.mode !== 'add';
|
|
1219
|
+
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1220
|
+
if ((0, type_guards_1.isResourceMapperValue)(value)) {
|
|
1221
|
+
const issues = validateResourceMapperParameter(nodeProperties, value, skipRequiredCheck);
|
|
1222
|
+
if (Object.keys(issues).length > 0) {
|
|
1252
1223
|
if (foundIssues.parameters === undefined) {
|
|
1253
1224
|
foundIssues.parameters = {};
|
|
1254
1225
|
}
|
|
1255
1226
|
if (foundIssues.parameters[nodeProperties.name] === undefined) {
|
|
1256
1227
|
foundIssues.parameters[nodeProperties.name] = [];
|
|
1257
1228
|
}
|
|
1258
|
-
foundIssues.parameters
|
|
1229
|
+
foundIssues.parameters = { ...foundIssues.parameters, ...issues };
|
|
1259
1230
|
}
|
|
1260
1231
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
// Checks the child properties only if the property is defined on current level.
|
|
1269
|
-
// That means that the required flag works only for the current level only. If
|
|
1270
|
-
// it is set on a lower level it means that the property is only required in case
|
|
1271
|
-
// the parent property got set.
|
|
1272
|
-
let basePath = path ? `${path}.` : '';
|
|
1273
|
-
const checkChildNodeProperties = [];
|
|
1274
|
-
// Collect all the properties to check
|
|
1275
|
-
if (nodeProperties.type === 'collection') {
|
|
1276
|
-
for (const option of nodeProperties.options) {
|
|
1277
|
-
checkChildNodeProperties.push({
|
|
1278
|
-
basePath,
|
|
1279
|
-
data: option,
|
|
1280
|
-
});
|
|
1232
|
+
}
|
|
1233
|
+
else if (nodeProperties.type === 'filter' && isDisplayed) {
|
|
1234
|
+
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1235
|
+
if ((0, type_guards_1.isFilterValue)(value)) {
|
|
1236
|
+
const issues = (0, filter_parameter_1.validateFilterParameter)(nodeProperties, value);
|
|
1237
|
+
if (Object.keys(issues).length > 0) {
|
|
1238
|
+
foundIssues.parameters = { ...foundIssues.parameters, ...issues };
|
|
1281
1239
|
}
|
|
1282
1240
|
}
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
const valueArray = Array.isArray(value) ? value : [];
|
|
1291
|
-
const { minRequiredFields, maxAllowedFields } = nodeProperties.typeOptions ?? {};
|
|
1292
|
-
let error = '';
|
|
1293
|
-
if (minRequiredFields && valueArray.length < minRequiredFields) {
|
|
1294
|
-
error = `At least ${minRequiredFields} ${minRequiredFields === 1 ? 'field is' : 'fields are'} required.`;
|
|
1295
|
-
}
|
|
1296
|
-
if (maxAllowedFields && valueArray.length > maxAllowedFields) {
|
|
1297
|
-
error = `At most ${maxAllowedFields} ${maxAllowedFields === 1 ? 'field is' : 'fields are'} allowed.`;
|
|
1298
|
-
}
|
|
1299
|
-
if (error) {
|
|
1300
|
-
foundIssues.parameters ??= {};
|
|
1301
|
-
foundIssues.parameters[nodeProperties.name] ??= [];
|
|
1302
|
-
foundIssues.parameters[nodeProperties.name].push(error);
|
|
1303
|
-
}
|
|
1304
|
-
if (value === undefined) {
|
|
1305
|
-
continue;
|
|
1306
|
-
}
|
|
1307
|
-
if (
|
|
1308
|
-
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
|
1309
|
-
nodeProperties.typeOptions !== undefined &&
|
|
1310
|
-
nodeProperties.typeOptions.multipleValues !== undefined) {
|
|
1311
|
-
// Multiple can be set so will be an array of objects
|
|
1312
|
-
if (Array.isArray(value)) {
|
|
1313
|
-
for (let i = 0; i < value.length; i++) {
|
|
1314
|
-
for (const option of propertyOptions.values) {
|
|
1315
|
-
checkChildNodeProperties.push({
|
|
1316
|
-
basePath: `${basePath}${propertyOptions.name}[${i}]`,
|
|
1317
|
-
data: option,
|
|
1318
|
-
});
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
else {
|
|
1324
|
-
// Only one can be set so will be an object
|
|
1325
|
-
for (const option of propertyOptions.values) {
|
|
1326
|
-
checkChildNodeProperties.push({
|
|
1327
|
-
basePath: basePath + propertyOptions.name,
|
|
1328
|
-
data: option,
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1241
|
+
}
|
|
1242
|
+
else if (nodeProperties.validateType) {
|
|
1243
|
+
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
|
1244
|
+
const error = validateParameter(nodeProperties, value, nodeProperties.validateType);
|
|
1245
|
+
if (error) {
|
|
1246
|
+
if (foundIssues.parameters === undefined) {
|
|
1247
|
+
foundIssues.parameters = {};
|
|
1332
1248
|
}
|
|
1249
|
+
if (foundIssues.parameters[nodeProperties.name] === undefined) {
|
|
1250
|
+
foundIssues.parameters[nodeProperties.name] = [];
|
|
1251
|
+
}
|
|
1252
|
+
foundIssues.parameters[nodeProperties.name].push(error);
|
|
1333
1253
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
let propertyIssues;
|
|
1339
|
-
for (const optionData of checkChildNodeProperties) {
|
|
1340
|
-
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath, node, nodeTypeDescription);
|
|
1341
|
-
mergeIssues(foundIssues, propertyIssues);
|
|
1342
|
-
}
|
|
1254
|
+
}
|
|
1255
|
+
// Check if there are any child parameters
|
|
1256
|
+
if (nodeProperties.options === undefined) {
|
|
1257
|
+
// There are none so nothing else to check
|
|
1343
1258
|
return foundIssues;
|
|
1344
1259
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
let destinationProperty;
|
|
1361
|
-
for (const propertyName of objectProperties) {
|
|
1362
|
-
if (source[propertyName] !== undefined) {
|
|
1363
|
-
if (destination[propertyName] === undefined) {
|
|
1364
|
-
destination[propertyName] = {};
|
|
1365
|
-
}
|
|
1366
|
-
let parameterName;
|
|
1367
|
-
for (parameterName of Object.keys(source[propertyName])) {
|
|
1368
|
-
destinationProperty = destination[propertyName];
|
|
1369
|
-
if (destinationProperty[parameterName] === undefined) {
|
|
1370
|
-
destinationProperty[parameterName] = [];
|
|
1371
|
-
}
|
|
1372
|
-
destinationProperty[parameterName].push.apply(destinationProperty[parameterName], source[propertyName][parameterName]);
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
if (source.typeUnknown === true) {
|
|
1377
|
-
destination.typeUnknown = true;
|
|
1260
|
+
// Check the child parameters
|
|
1261
|
+
// Important:
|
|
1262
|
+
// Checks the child properties only if the property is defined on current level.
|
|
1263
|
+
// That means that the required flag works only for the current level only. If
|
|
1264
|
+
// it is set on a lower level it means that the property is only required in case
|
|
1265
|
+
// the parent property got set.
|
|
1266
|
+
let basePath = path ? `${path}.` : '';
|
|
1267
|
+
const checkChildNodeProperties = [];
|
|
1268
|
+
// Collect all the properties to check
|
|
1269
|
+
if (nodeProperties.type === 'collection') {
|
|
1270
|
+
for (const option of nodeProperties.options) {
|
|
1271
|
+
checkChildNodeProperties.push({
|
|
1272
|
+
basePath,
|
|
1273
|
+
data: option,
|
|
1274
|
+
});
|
|
1378
1275
|
}
|
|
1379
1276
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1277
|
+
else if (nodeProperties.type === 'fixedCollection' && isDisplayed) {
|
|
1278
|
+
basePath = basePath ? `${basePath}.` : `${nodeProperties.name}.`;
|
|
1279
|
+
let propertyOptions;
|
|
1280
|
+
for (propertyOptions of nodeProperties.options) {
|
|
1281
|
+
// Check if the option got set and if not skip it
|
|
1282
|
+
const value = getParameterValueByPath(nodeValues, propertyOptions.name, basePath.slice(0, -1));
|
|
1283
|
+
// Validate allowed field counts
|
|
1284
|
+
const valueArray = Array.isArray(value) ? value : [];
|
|
1285
|
+
const { minRequiredFields, maxAllowedFields } = nodeProperties.typeOptions ?? {};
|
|
1286
|
+
let error = '';
|
|
1287
|
+
if (minRequiredFields && valueArray.length < minRequiredFields) {
|
|
1288
|
+
error = `At least ${minRequiredFields} ${minRequiredFields === 1 ? 'field is' : 'fields are'} required.`;
|
|
1289
|
+
}
|
|
1290
|
+
if (maxAllowedFields && valueArray.length > maxAllowedFields) {
|
|
1291
|
+
error = `At most ${maxAllowedFields} ${maxAllowedFields === 1 ? 'field is' : 'fields are'} allowed.`;
|
|
1292
|
+
}
|
|
1293
|
+
if (error) {
|
|
1294
|
+
foundIssues.parameters ??= {};
|
|
1295
|
+
foundIssues.parameters[nodeProperties.name] ??= [];
|
|
1296
|
+
foundIssues.parameters[nodeProperties.name].push(error);
|
|
1297
|
+
}
|
|
1298
|
+
if (value === undefined) {
|
|
1387
1299
|
continue;
|
|
1388
|
-
|
|
1389
|
-
if (
|
|
1390
|
-
|
|
1391
|
-
|
|
1300
|
+
}
|
|
1301
|
+
if (
|
|
1302
|
+
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
|
1303
|
+
nodeProperties.typeOptions !== undefined &&
|
|
1304
|
+
nodeProperties.typeOptions.multipleValues !== undefined) {
|
|
1305
|
+
// Multiple can be set so will be an array of objects
|
|
1306
|
+
if (Array.isArray(value)) {
|
|
1307
|
+
for (let i = 0; i < value.length; i++) {
|
|
1308
|
+
for (const option of propertyOptions.values) {
|
|
1309
|
+
checkChildNodeProperties.push({
|
|
1310
|
+
basePath: `${basePath}${propertyOptions.name}[${i}]`,
|
|
1311
|
+
data: option,
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1392
1316
|
}
|
|
1393
1317
|
else {
|
|
1394
|
-
//
|
|
1395
|
-
|
|
1318
|
+
// Only one can be set so will be an object
|
|
1319
|
+
for (const option of propertyOptions.values) {
|
|
1320
|
+
checkChildNodeProperties.push({
|
|
1321
|
+
basePath: basePath + propertyOptions.name,
|
|
1322
|
+
data: option,
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1396
1325
|
}
|
|
1397
1326
|
}
|
|
1398
1327
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
}
|
|
1403
|
-
return object;
|
|
1328
|
+
else {
|
|
1329
|
+
// For all other types there is nothing to check so return
|
|
1330
|
+
return foundIssues;
|
|
1404
1331
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1332
|
+
let propertyIssues;
|
|
1333
|
+
for (const optionData of checkChildNodeProperties) {
|
|
1334
|
+
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath, node, nodeTypeDescription);
|
|
1335
|
+
mergeIssues(foundIssues, propertyIssues);
|
|
1407
1336
|
}
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
return
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
if (
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
if (langProp?.options && (0, type_guards_1.isINodePropertyOptionsList)(langProp.options)) {
|
|
1431
|
-
const found = langProp.options.find((o) => o.value === language);
|
|
1432
|
-
if (found?.action)
|
|
1433
|
-
return { action: found.action };
|
|
1337
|
+
return foundIssues;
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Merges multiple NodeIssues together
|
|
1341
|
+
*
|
|
1342
|
+
* @param {INodeIssues} destination The issues to merge into
|
|
1343
|
+
* @param {(INodeIssues | null)} source The issues to merge
|
|
1344
|
+
*/
|
|
1345
|
+
function mergeIssues(destination, source) {
|
|
1346
|
+
if (source === null) {
|
|
1347
|
+
// Nothing to merge
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
if (source.execution === true) {
|
|
1351
|
+
destination.execution = true;
|
|
1352
|
+
}
|
|
1353
|
+
const objectProperties = ['parameters', 'credentials'];
|
|
1354
|
+
let destinationProperty;
|
|
1355
|
+
for (const propertyName of objectProperties) {
|
|
1356
|
+
if (source[propertyName] !== undefined) {
|
|
1357
|
+
if (destination[propertyName] === undefined) {
|
|
1358
|
+
destination[propertyName] = {};
|
|
1434
1359
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
return { action: foundOperation.action };
|
|
1360
|
+
let parameterName;
|
|
1361
|
+
for (parameterName of Object.keys(source[propertyName])) {
|
|
1362
|
+
destinationProperty = destination[propertyName];
|
|
1363
|
+
if (destinationProperty[parameterName] === undefined) {
|
|
1364
|
+
destinationProperty[parameterName] = [];
|
|
1365
|
+
}
|
|
1366
|
+
destinationProperty[parameterName].push.apply(destinationProperty[parameterName], source[propertyName][parameterName]);
|
|
1443
1367
|
}
|
|
1444
1368
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1369
|
+
}
|
|
1370
|
+
if (source.typeUnknown === true) {
|
|
1371
|
+
destination.typeUnknown = true;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Merges the given node properties
|
|
1376
|
+
*/
|
|
1377
|
+
function mergeNodeProperties(mainProperties, addProperties) {
|
|
1378
|
+
let existingIndex;
|
|
1379
|
+
for (const property of addProperties) {
|
|
1380
|
+
if (property.doNotInherit)
|
|
1381
|
+
continue;
|
|
1382
|
+
existingIndex = mainProperties.findIndex((element) => element.name === property.name);
|
|
1383
|
+
if (existingIndex === -1) {
|
|
1384
|
+
// Property does not exist yet, so add
|
|
1385
|
+
mainProperties.push(property);
|
|
1447
1386
|
}
|
|
1448
1387
|
else {
|
|
1449
|
-
|
|
1388
|
+
// Property exists already, so overwrite
|
|
1389
|
+
mainProperties[existingIndex] = property;
|
|
1450
1390
|
}
|
|
1451
1391
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1392
|
+
}
|
|
1393
|
+
function getVersionedNodeType(object, version) {
|
|
1394
|
+
if ('nodeVersions' in object) {
|
|
1395
|
+
return object.getNodeType(version);
|
|
1396
|
+
}
|
|
1397
|
+
return object;
|
|
1398
|
+
}
|
|
1399
|
+
function isTriggerNode(nodeTypeData) {
|
|
1400
|
+
return nodeTypeData.group.includes('trigger');
|
|
1401
|
+
}
|
|
1402
|
+
function isExecutable(workflow, node, nodeTypeData) {
|
|
1403
|
+
if (!nodeTypeData) {
|
|
1404
|
+
return false;
|
|
1405
|
+
}
|
|
1406
|
+
const outputs = getNodeOutputs(workflow, node, nodeTypeData);
|
|
1407
|
+
const outputNames = getConnectionTypes(outputs);
|
|
1408
|
+
return (outputNames.includes(interfaces_1.NodeConnectionTypes.Main) ||
|
|
1409
|
+
outputNames.includes(interfaces_1.NodeConnectionTypes.AiTool) ||
|
|
1410
|
+
isTriggerNode(nodeTypeData));
|
|
1411
|
+
}
|
|
1412
|
+
function isNodeWithWorkflowSelector(node) {
|
|
1413
|
+
return [constants_1.EXECUTE_WORKFLOW_NODE_TYPE, constants_1.WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE].includes(node.type);
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* @returns An object containing either the resolved operation's action if available,
|
|
1417
|
+
* else the resource and operation if both exist.
|
|
1418
|
+
* If neither can be resolved, returns an empty object.
|
|
1419
|
+
*/
|
|
1420
|
+
function resolveResourceAndOperation(nodeParameters, nodeTypeDescription) {
|
|
1421
|
+
if (nodeTypeDescription.name === 'n8n-nodes-base.code') {
|
|
1422
|
+
const language = nodeParameters.language;
|
|
1423
|
+
const langProp = nodeTypeDescription.properties.find((p) => p.name === 'language');
|
|
1424
|
+
if (langProp?.options && (0, type_guards_1.isINodePropertyOptionsList)(langProp.options)) {
|
|
1425
|
+
const found = langProp.options.find((o) => o.value === language);
|
|
1426
|
+
if (found?.action)
|
|
1427
|
+
return { action: found.action };
|
|
1467
1428
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1429
|
+
}
|
|
1430
|
+
const resource = nodeParameters.resource;
|
|
1431
|
+
const operation = nodeParameters.operation;
|
|
1432
|
+
const nodeTypeOperation = nodeTypeDescription.properties.find((p) => p.name === 'operation' && p.displayOptions?.show?.resource?.includes(resource));
|
|
1433
|
+
if (nodeTypeOperation?.options && (0, type_guards_1.isINodePropertyOptionsList)(nodeTypeOperation.options)) {
|
|
1434
|
+
const foundOperation = nodeTypeOperation.options.find((option) => option.value === operation);
|
|
1435
|
+
if (foundOperation?.action) {
|
|
1436
|
+
return { action: foundOperation.action };
|
|
1470
1437
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1438
|
+
}
|
|
1439
|
+
if (resource && operation) {
|
|
1440
|
+
return { operation, resource };
|
|
1441
|
+
}
|
|
1442
|
+
else {
|
|
1443
|
+
return {};
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Generates a human-readable description for a node based on its parameters and type definition.
|
|
1448
|
+
*
|
|
1449
|
+
* This function creates a descriptive string that represents what the node does,
|
|
1450
|
+
* based on its resource, operation, and node type information. The description is
|
|
1451
|
+
* formatted in one of the following ways:
|
|
1452
|
+
*
|
|
1453
|
+
* 1. "{action} in {displayName}" if the operation has a defined action
|
|
1454
|
+
* 2. "{operation} {resource} in {displayName}" if resource and operation exist
|
|
1455
|
+
* 3. The node type's description field as a fallback
|
|
1456
|
+
*/
|
|
1457
|
+
function makeDescription(nodeParameters, nodeTypeDescription) {
|
|
1458
|
+
const { action, operation, resource } = resolveResourceAndOperation(nodeParameters, nodeTypeDescription);
|
|
1459
|
+
if (action) {
|
|
1460
|
+
return `${action} in ${nodeTypeDescription.defaults.name}`;
|
|
1461
|
+
}
|
|
1462
|
+
if (resource && operation) {
|
|
1463
|
+
return `${operation} ${resource} in ${nodeTypeDescription.defaults.name}`;
|
|
1464
|
+
}
|
|
1465
|
+
return nodeTypeDescription.description;
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Trigger node types that don't have "trigger" in their name
|
|
1469
|
+
* but still function as workflow entry points
|
|
1470
|
+
*/
|
|
1471
|
+
const TRIGGER_NODE_TYPES = new Set([
|
|
1472
|
+
'n8n-nodes-base.webhook',
|
|
1473
|
+
'n8n-nodes-base.cron', // Legacy schedule trigger
|
|
1474
|
+
'n8n-nodes-base.emailReadImap', // Email polling trigger
|
|
1475
|
+
'n8n-nodes-base.telegramBot', // Can act as webhook trigger
|
|
1476
|
+
'n8n-nodes-base.start', // Legacy trigger
|
|
1477
|
+
]);
|
|
1478
|
+
/**
|
|
1479
|
+
* Check if a node type is a trigger
|
|
1480
|
+
*/
|
|
1481
|
+
function isTriggerNodeType(type) {
|
|
1482
|
+
if (TRIGGER_NODE_TYPES.has(type)) {
|
|
1483
|
+
return true;
|
|
1484
|
+
}
|
|
1485
|
+
return type.toLowerCase().includes('trigger');
|
|
1486
|
+
}
|
|
1487
|
+
function isToolType(nodeType, { includeHitl = true } = {}) {
|
|
1488
|
+
if (!nodeType)
|
|
1489
|
+
return false;
|
|
1490
|
+
const node = nodeType.split('.').pop();
|
|
1491
|
+
if (node?.endsWith('Tool') || node?.startsWith('tool')) {
|
|
1492
|
+
// don't check if it's hitl
|
|
1493
|
+
if (includeHitl) {
|
|
1489
1494
|
return true;
|
|
1490
1495
|
}
|
|
1491
|
-
return
|
|
1492
|
-
}
|
|
1493
|
-
function isToolType(nodeType, { includeHitl = true } = {}) {
|
|
1494
|
-
if (!nodeType)
|
|
1495
|
-
return false;
|
|
1496
|
-
const node = nodeType.split('.').pop();
|
|
1497
|
-
if (node?.endsWith('Tool') || node?.startsWith('tool')) {
|
|
1498
|
-
// don't check if it's hitl
|
|
1499
|
-
if (includeHitl) {
|
|
1500
|
-
return true;
|
|
1501
|
-
}
|
|
1502
|
-
return !isHitlToolType(nodeType);
|
|
1503
|
-
}
|
|
1504
|
-
return false;
|
|
1496
|
+
return !isHitlToolType(nodeType);
|
|
1505
1497
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
function isHitlToolType(nodeType) {
|
|
1501
|
+
if (!nodeType)
|
|
1502
|
+
return false;
|
|
1503
|
+
return nodeType.endsWith('HitlTool');
|
|
1504
|
+
}
|
|
1505
|
+
function isTool(nodeTypeDescription, parameters) {
|
|
1506
|
+
// Check if node is a vector store in retrieve-as-tool mode
|
|
1507
|
+
if (nodeTypeDescription.name.includes('vectorStore')) {
|
|
1508
|
+
const mode = parameters.mode;
|
|
1509
|
+
return mode === 'retrieve-as-tool';
|
|
1510
1510
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
for (const output of nodeTypeDescription.outputs) {
|
|
1521
|
-
if (typeof output === 'string') {
|
|
1522
|
-
return output === interfaces_1.NodeConnectionTypes.AiTool;
|
|
1523
|
-
}
|
|
1524
|
-
else if (output?.type && output.type === interfaces_1.NodeConnectionTypes.AiTool) {
|
|
1525
|
-
return true;
|
|
1526
|
-
}
|
|
1511
|
+
// Check for other tool nodes
|
|
1512
|
+
if (Array.isArray(nodeTypeDescription.outputs)) {
|
|
1513
|
+
// Handle static outputs (array case)
|
|
1514
|
+
for (const output of nodeTypeDescription.outputs) {
|
|
1515
|
+
if (typeof output === 'string') {
|
|
1516
|
+
return output === interfaces_1.NodeConnectionTypes.AiTool;
|
|
1517
|
+
}
|
|
1518
|
+
else if (output?.type && output.type === interfaces_1.NodeConnectionTypes.AiTool) {
|
|
1519
|
+
return true;
|
|
1527
1520
|
}
|
|
1528
1521
|
}
|
|
1529
|
-
return false;
|
|
1530
1522
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
const { action, operation, resource } = resolveResourceAndOperation(nodeParameters, nodeTypeDescription);
|
|
1546
|
-
const postfix = isTool(nodeTypeDescription, nodeParameters)
|
|
1547
|
-
? ` in ${nodeTypeDescription.defaults.name}`
|
|
1548
|
-
: '';
|
|
1549
|
-
if (action) {
|
|
1550
|
-
return `${action}${postfix}`;
|
|
1551
|
-
}
|
|
1552
|
-
if (resource && operation) {
|
|
1553
|
-
const operationProper = operation[0].toUpperCase() + operation.slice(1);
|
|
1554
|
-
return `${operationProper} ${resource}${postfix}`;
|
|
1555
|
-
}
|
|
1523
|
+
return false;
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Generates a resource and operation aware node name.
|
|
1527
|
+
*
|
|
1528
|
+
* Appends `in {nodeTypeDisplayName}` if nodeType is a tool
|
|
1529
|
+
*
|
|
1530
|
+
* 1. "{action}" if the operation has a defined action
|
|
1531
|
+
* 2. "{operation} {resource}" if resource and operation exist
|
|
1532
|
+
* 3. The node type's defaults.name field or displayName as a fallback
|
|
1533
|
+
*/
|
|
1534
|
+
function makeNodeName(nodeParameters, nodeTypeDescription) {
|
|
1535
|
+
// If skipNameGeneration is set, skip resource/operation resolution
|
|
1536
|
+
if (nodeTypeDescription.skipNameGeneration) {
|
|
1556
1537
|
return nodeTypeDescription.defaults.name ?? nodeTypeDescription.displayName;
|
|
1557
1538
|
}
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
return
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1539
|
+
const { action, operation, resource } = resolveResourceAndOperation(nodeParameters, nodeTypeDescription);
|
|
1540
|
+
const postfix = isTool(nodeTypeDescription, nodeParameters)
|
|
1541
|
+
? ` in ${nodeTypeDescription.defaults.name}`
|
|
1542
|
+
: '';
|
|
1543
|
+
if (action) {
|
|
1544
|
+
return `${action}${postfix}`;
|
|
1545
|
+
}
|
|
1546
|
+
if (resource && operation) {
|
|
1547
|
+
const operationProper = operation[0].toUpperCase() + operation.slice(1);
|
|
1548
|
+
return `${operationProper} ${resource}${postfix}`;
|
|
1549
|
+
}
|
|
1550
|
+
return nodeTypeDescription.defaults.name ?? nodeTypeDescription.displayName;
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Returns true if the node name is of format `<defaultNodeName>\d*` , which includes auto-renamed nodes
|
|
1554
|
+
*/
|
|
1555
|
+
function isDefaultNodeName(name, nodeType, parameters) {
|
|
1556
|
+
const currentDefaultName = makeNodeName(parameters, nodeType);
|
|
1557
|
+
return name.startsWith(currentDefaultName) && /^\d*$/.test(name.slice(currentDefaultName.length));
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Determines whether a tool description should be updated and returns the new description if needed.
|
|
1561
|
+
* Returns undefined if no update is needed.
|
|
1562
|
+
*/
|
|
1563
|
+
const getUpdatedToolDescription = (currentNodeType, newParameters, currentParameters) => {
|
|
1564
|
+
if (!currentNodeType)
|
|
1581
1565
|
return;
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
* the upstream input data — matching how other tool nodes (e.g. `toolWorkflow`)
|
|
1590
|
-
* resolve their description parameter via `getNodeParameter`. Without a resolver,
|
|
1591
|
-
* the raw value is returned unchanged for backward compatibility.
|
|
1592
|
-
*/
|
|
1593
|
-
function getToolDescriptionForNode(node, nodeType, resolveToolDescription) {
|
|
1594
|
-
let toolDescription;
|
|
1595
|
-
if (node.parameters.descriptionType === 'auto' ||
|
|
1596
|
-
!node?.parameters.toolDescription?.toString().trim()) {
|
|
1597
|
-
toolDescription = makeDescription(node.parameters, nodeType.description);
|
|
1566
|
+
if (newParameters?.descriptionType === 'manual' && currentParameters) {
|
|
1567
|
+
const previousDescription = makeDescription(currentParameters, currentNodeType);
|
|
1568
|
+
const newDescription = makeDescription(newParameters, currentNodeType);
|
|
1569
|
+
if (newParameters.toolDescription === previousDescription ||
|
|
1570
|
+
!newParameters.toolDescription?.toString().trim() ||
|
|
1571
|
+
newParameters.toolDescription === currentNodeType.description) {
|
|
1572
|
+
return newDescription;
|
|
1598
1573
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1574
|
+
}
|
|
1575
|
+
return;
|
|
1576
|
+
};
|
|
1577
|
+
exports.getUpdatedToolDescription = getUpdatedToolDescription;
|
|
1578
|
+
/**
|
|
1579
|
+
* Generates a tool description for a given node based on its parameters and type.
|
|
1580
|
+
*
|
|
1581
|
+
* When the user-provided `toolDescription` is an n8n expression (starts with `=`),
|
|
1582
|
+
* the optional `resolveToolDescription` callback is used to evaluate it against
|
|
1583
|
+
* the upstream input data — matching how other tool nodes (e.g. `toolWorkflow`)
|
|
1584
|
+
* resolve their description parameter via `getNodeParameter`. Without a resolver,
|
|
1585
|
+
* the raw value is returned unchanged for backward compatibility.
|
|
1586
|
+
*/
|
|
1587
|
+
function getToolDescriptionForNode(node, nodeType, resolveToolDescription) {
|
|
1588
|
+
let toolDescription;
|
|
1589
|
+
if (node.parameters.descriptionType === 'auto' ||
|
|
1590
|
+
!node?.parameters.toolDescription?.toString().trim()) {
|
|
1591
|
+
toolDescription = makeDescription(node.parameters, nodeType.description);
|
|
1592
|
+
}
|
|
1593
|
+
else if (node?.parameters.toolDescription) {
|
|
1594
|
+
const raw = node.parameters.toolDescription;
|
|
1595
|
+
if (resolveToolDescription && typeof raw === 'string' && raw.startsWith('=')) {
|
|
1596
|
+
toolDescription = resolveToolDescription();
|
|
1607
1597
|
}
|
|
1608
1598
|
else {
|
|
1609
|
-
toolDescription =
|
|
1610
|
-
}
|
|
1611
|
-
return toolDescription;
|
|
1612
|
-
}
|
|
1613
|
-
/**
|
|
1614
|
-
* Attempts to retrieve the ID of a subworkflow from a execute workflow node.
|
|
1615
|
-
*/
|
|
1616
|
-
function getSubworkflowId(node) {
|
|
1617
|
-
if (isNodeWithWorkflowSelector(node) && (0, type_guards_1.isResourceLocatorValue)(node.parameters.workflowId)) {
|
|
1618
|
-
return node.parameters.workflowId.value;
|
|
1599
|
+
toolDescription = raw;
|
|
1619
1600
|
}
|
|
1620
|
-
return;
|
|
1621
1601
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
* @param nodeType - The node type description
|
|
1625
|
-
* @param connectionType - The connection type to check (e.g., 'main', 'ai_tool')
|
|
1626
|
-
* @returns True if the node accepts the input type
|
|
1627
|
-
*/
|
|
1628
|
-
function nodeAcceptsInputType(nodeType, connectionType) {
|
|
1629
|
-
// Handle string-based inputs (expression or simple string)
|
|
1630
|
-
if (typeof nodeType.inputs === 'string') {
|
|
1631
|
-
return nodeType.inputs === connectionType || nodeType.inputs.includes(connectionType);
|
|
1632
|
-
}
|
|
1633
|
-
// Handle array-based inputs
|
|
1634
|
-
if (!nodeType.inputs || !Array.isArray(nodeType.inputs)) {
|
|
1635
|
-
return false;
|
|
1636
|
-
}
|
|
1637
|
-
return nodeType.inputs.some((input) => {
|
|
1638
|
-
if (typeof input === 'string') {
|
|
1639
|
-
return input === connectionType || input.includes(connectionType);
|
|
1640
|
-
}
|
|
1641
|
-
return input.type === connectionType;
|
|
1642
|
-
});
|
|
1602
|
+
else {
|
|
1603
|
+
toolDescription = nodeType.description.description;
|
|
1643
1604
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1605
|
+
return toolDescription;
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Attempts to retrieve the ID of a subworkflow from a execute workflow node.
|
|
1609
|
+
*/
|
|
1610
|
+
function getSubworkflowId(node) {
|
|
1611
|
+
if (isNodeWithWorkflowSelector(node) && (0, type_guards_1.isResourceLocatorValue)(node.parameters.workflowId)) {
|
|
1612
|
+
return node.parameters.workflowId.value;
|
|
1613
|
+
}
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Check if a node type accepts a specific input connection type
|
|
1618
|
+
* @param nodeType - The node type description
|
|
1619
|
+
* @param connectionType - The connection type to check (e.g., 'main', 'ai_tool')
|
|
1620
|
+
* @returns True if the node accepts the input type
|
|
1621
|
+
*/
|
|
1622
|
+
function nodeAcceptsInputType(nodeType, connectionType) {
|
|
1623
|
+
// Handle string-based inputs (expression or simple string)
|
|
1624
|
+
if (typeof nodeType.inputs === 'string') {
|
|
1625
|
+
return nodeType.inputs === connectionType || nodeType.inputs.includes(connectionType);
|
|
1665
1626
|
}
|
|
1666
|
-
|
|
1627
|
+
// Handle array-based inputs
|
|
1628
|
+
if (!nodeType.inputs || !Array.isArray(nodeType.inputs)) {
|
|
1629
|
+
return false;
|
|
1630
|
+
}
|
|
1631
|
+
return nodeType.inputs.some((input) => {
|
|
1632
|
+
if (typeof input === 'string') {
|
|
1633
|
+
return input === connectionType || input.includes(connectionType);
|
|
1634
|
+
}
|
|
1635
|
+
return input.type === connectionType;
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Check if a node type has a specific output connection type
|
|
1640
|
+
* @param nodeType - The node type description
|
|
1641
|
+
* @param connectionType - The connection type to check (e.g., 'main', 'ai_tool')
|
|
1642
|
+
* @returns True if the node supports the output type
|
|
1643
|
+
*/
|
|
1644
|
+
function nodeHasOutputType(nodeType, connectionType) {
|
|
1645
|
+
// Handle string-based outputs (expression or simple string)
|
|
1646
|
+
if (typeof nodeType.outputs === 'string') {
|
|
1647
|
+
return nodeType.outputs === connectionType || nodeType.outputs.includes(connectionType);
|
|
1648
|
+
}
|
|
1649
|
+
// Handle array-based outputs
|
|
1650
|
+
if (!nodeType.outputs || !Array.isArray(nodeType.outputs)) {
|
|
1651
|
+
return false;
|
|
1652
|
+
}
|
|
1653
|
+
return nodeType.outputs.some((output) => {
|
|
1654
|
+
if (typeof output === 'string') {
|
|
1655
|
+
return output === connectionType || output.includes(connectionType);
|
|
1656
|
+
}
|
|
1657
|
+
return output.type === connectionType;
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1667
1660
|
//# sourceMappingURL=node-helpers.js.map
|