n8n-workflow 2.31.3 → 2.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 -53
- 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.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
|
@@ -1,527 +1,517 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
2
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3
4
|
};
|
|
4
|
-
(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hasDotNotationBannedChar = hasDotNotationBannedChar;
|
|
7
|
+
exports.backslashEscape = backslashEscape;
|
|
8
|
+
exports.dollarEscape = dollarEscape;
|
|
9
|
+
exports.applyAccessPatterns = applyAccessPatterns;
|
|
10
|
+
exports.extractReferencesInNodeExpressions = extractReferencesInNodeExpressions;
|
|
11
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
12
|
+
const escapeRegExp_1 = __importDefault(require("lodash/escapeRegExp"));
|
|
13
|
+
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
14
|
+
const mapValues_1 = __importDefault(require("lodash/mapValues"));
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
class LazyRegExp {
|
|
17
|
+
pattern;
|
|
18
|
+
flags;
|
|
19
|
+
regExp;
|
|
20
|
+
constructor(pattern, flags) {
|
|
21
|
+
this.pattern = pattern;
|
|
22
|
+
this.flags = flags;
|
|
8
23
|
}
|
|
9
|
-
|
|
10
|
-
|
|
24
|
+
get() {
|
|
25
|
+
if (!this.regExp)
|
|
26
|
+
this.regExp = new RegExp(this.pattern(), this.flags);
|
|
27
|
+
return this.regExp;
|
|
11
28
|
}
|
|
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
|
-
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()_+\-=[\]{};':"\\|,.<>?~]/g;
|
|
57
|
-
return DOT_NOTATION_BANNED_CHARS.test(nodeName);
|
|
58
|
-
}
|
|
59
|
-
function backslashEscape(nodeName) {
|
|
60
|
-
const BACKSLASH_ESCAPABLE_CHARS = /[.*+?^${}()|[\]\\]/g;
|
|
61
|
-
return nodeName.replace(BACKSLASH_ESCAPABLE_CHARS, (char) => `\\${char}`);
|
|
62
|
-
}
|
|
63
|
-
function dollarEscape(nodeName) {
|
|
64
|
-
return nodeName.replace(new RegExp('\\$', 'g'), '$$$$');
|
|
65
|
-
}
|
|
66
|
-
const ACCESS_PATTERNS = [
|
|
67
|
-
{
|
|
68
|
-
checkPattern: '$(',
|
|
69
|
-
replacePattern: (s) => String.raw `(\$\(['"])${s}(['"]\))`,
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
checkPattern: '$node[',
|
|
73
|
-
replacePattern: (s) => String.raw `(\$node\[['"])${s}(['"]\])`,
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
checkPattern: '$node.',
|
|
77
|
-
replacePattern: (s) => String.raw `(\$node\.)${s}(\.?)`,
|
|
78
|
-
customCallback: (expression, newName, escapedNewName) => {
|
|
79
|
-
if (hasDotNotationBannedChar(newName)) {
|
|
80
|
-
const regex = new RegExp(`.${backslashEscape(newName)}( |\\.)`, 'g');
|
|
81
|
-
return expression.replace(regex, `["${escapedNewName}"]$1`);
|
|
82
|
-
}
|
|
83
|
-
return expression;
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
checkPattern: '$items(',
|
|
88
|
-
replacePattern: (s) => String.raw `(\$items\(['"])${s}(['"],|['"]\))`,
|
|
89
|
-
},
|
|
90
|
-
];
|
|
91
|
-
function prepareOldNodeName(nodeName) {
|
|
92
|
-
// if node name contains literal \ -> replace with \\
|
|
93
|
-
// since that's how it'll be written in a JS expression
|
|
94
|
-
const doubleSlashes = nodeName.replaceAll('\\', '\\\\');
|
|
95
|
-
// escape special characters for regex
|
|
96
|
-
const escaped = backslashEscape(doubleSlashes);
|
|
97
|
-
// quotes may or may not be escaped in the JS expression
|
|
98
|
-
// so we replace literal quotes with regexes handle that
|
|
99
|
-
return escaped.replace(/"/g, '(?:\\\\?")').replace(/'/g, "(?:\\\\?')");
|
|
100
|
-
}
|
|
101
|
-
function prepareNewNodeName(nodeName) {
|
|
102
|
-
// escape $ for replacement regex
|
|
103
|
-
const dollarEscaped = dollarEscape(nodeName);
|
|
104
|
-
// escape literal \ ' " characters
|
|
105
|
-
return dollarEscaped.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll("'", "\\'");
|
|
106
|
-
}
|
|
107
|
-
function applyAccessPatterns(expression, previousName, newName) {
|
|
108
|
-
// To not run the "expensive" regex stuff when it is not needed
|
|
109
|
-
// make a simple check first if it contains any of the access patterns
|
|
110
|
-
let noMatch = true;
|
|
111
|
-
for (const pattern of ACCESS_PATTERNS) {
|
|
112
|
-
if (expression.includes(pattern.checkPattern)) {
|
|
113
|
-
noMatch = false;
|
|
114
|
-
break;
|
|
29
|
+
}
|
|
30
|
+
const DOT_REFERENCEABLE_JS_VARIABLE = /\w[\w\d_\$]*/;
|
|
31
|
+
const INVALID_JS_DOT_PATH = /[^\.\w\d_\$]/;
|
|
32
|
+
const INVALID_JS_DOT_NAME = /[^\w\d_\$]/;
|
|
33
|
+
// These are the keys that are followed by one of DATA_ACCESSORS
|
|
34
|
+
const ITEM_TO_DATA_ACCESSORS = [
|
|
35
|
+
/^first\(\)/,
|
|
36
|
+
/^last\(\)/,
|
|
37
|
+
/^all\(\)/,
|
|
38
|
+
// The order here is relevant because `item` would match occurrences of `itemMatching`
|
|
39
|
+
/^itemMatching\(\d+\)/, // We only support trivial itemMatching arguments
|
|
40
|
+
/^item/,
|
|
41
|
+
];
|
|
42
|
+
const SPLIT_OUT_NODE_TYPE = 'n8n-nodes-base.splitOut';
|
|
43
|
+
// These we safely can convert to a normal argument
|
|
44
|
+
const ITEM_ACCESSORS = ['params', 'isExecuted'];
|
|
45
|
+
const DATA_ACCESSORS = ['json', 'binary'];
|
|
46
|
+
function hasDotNotationBannedChar(nodeName) {
|
|
47
|
+
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()_+\-=[\]{};':"\\|,.<>?~]/g;
|
|
48
|
+
return DOT_NOTATION_BANNED_CHARS.test(nodeName);
|
|
49
|
+
}
|
|
50
|
+
function backslashEscape(nodeName) {
|
|
51
|
+
const BACKSLASH_ESCAPABLE_CHARS = /[.*+?^${}()|[\]\\]/g;
|
|
52
|
+
return nodeName.replace(BACKSLASH_ESCAPABLE_CHARS, (char) => `\\${char}`);
|
|
53
|
+
}
|
|
54
|
+
function dollarEscape(nodeName) {
|
|
55
|
+
return nodeName.replace(new RegExp('\\$', 'g'), '$$$$');
|
|
56
|
+
}
|
|
57
|
+
const ACCESS_PATTERNS = [
|
|
58
|
+
{
|
|
59
|
+
checkPattern: '$(',
|
|
60
|
+
replacePattern: (s) => String.raw `(\$\(['"])${s}(['"]\))`,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
checkPattern: '$node[',
|
|
64
|
+
replacePattern: (s) => String.raw `(\$node\[['"])${s}(['"]\])`,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
checkPattern: '$node.',
|
|
68
|
+
replacePattern: (s) => String.raw `(\$node\.)${s}(\.?)`,
|
|
69
|
+
customCallback: (expression, newName, escapedNewName) => {
|
|
70
|
+
if (hasDotNotationBannedChar(newName)) {
|
|
71
|
+
const regex = new RegExp(`.${backslashEscape(newName)}( |\\.)`, 'g');
|
|
72
|
+
return expression.replace(regex, `["${escapedNewName}"]$1`);
|
|
115
73
|
}
|
|
116
|
-
}
|
|
117
|
-
if (noMatch) {
|
|
118
74
|
return expression;
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
checkPattern: '$items(',
|
|
79
|
+
replacePattern: (s) => String.raw `(\$items\(['"])${s}(['"],|['"]\))`,
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
function prepareOldNodeName(nodeName) {
|
|
83
|
+
// if node name contains literal \ -> replace with \\
|
|
84
|
+
// since that's how it'll be written in a JS expression
|
|
85
|
+
const doubleSlashes = nodeName.replaceAll('\\', '\\\\');
|
|
86
|
+
// escape special characters for regex
|
|
87
|
+
const escaped = backslashEscape(doubleSlashes);
|
|
88
|
+
// quotes may or may not be escaped in the JS expression
|
|
89
|
+
// so we replace literal quotes with regexes handle that
|
|
90
|
+
return escaped.replace(/"/g, '(?:\\\\?")').replace(/'/g, "(?:\\\\?')");
|
|
91
|
+
}
|
|
92
|
+
function prepareNewNodeName(nodeName) {
|
|
93
|
+
// escape $ for replacement regex
|
|
94
|
+
const dollarEscaped = dollarEscape(nodeName);
|
|
95
|
+
// escape literal \ ' " characters
|
|
96
|
+
return dollarEscaped.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll("'", "\\'");
|
|
97
|
+
}
|
|
98
|
+
function applyAccessPatterns(expression, previousName, newName) {
|
|
99
|
+
// To not run the "expensive" regex stuff when it is not needed
|
|
100
|
+
// make a simple check first if it contains any of the access patterns
|
|
101
|
+
let noMatch = true;
|
|
102
|
+
for (const pattern of ACCESS_PATTERNS) {
|
|
103
|
+
if (expression.includes(pattern.checkPattern)) {
|
|
104
|
+
noMatch = false;
|
|
105
|
+
break;
|
|
119
106
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
107
|
+
}
|
|
108
|
+
if (noMatch) {
|
|
109
|
+
return expression;
|
|
110
|
+
}
|
|
111
|
+
const preparedOldName = prepareOldNodeName(previousName);
|
|
112
|
+
const preparedNewName = prepareNewNodeName(newName);
|
|
113
|
+
for (const pattern of ACCESS_PATTERNS) {
|
|
114
|
+
if (expression.includes(pattern.checkPattern)) {
|
|
115
|
+
expression = expression.replace(new RegExp(pattern.replacePattern(preparedOldName), 'g'), `$1${preparedNewName}$2`);
|
|
116
|
+
if (pattern.customCallback) {
|
|
117
|
+
expression = pattern.customCallback(expression, newName, preparedNewName);
|
|
128
118
|
}
|
|
129
119
|
}
|
|
130
|
-
return expression;
|
|
131
120
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// By adding our own index in the array we also avoid running into theoretical cases
|
|
142
|
-
// where a node with the name 'ourName_27' exists for our reduced name 'ourName'
|
|
143
|
-
// because we must have a different index, so therefore only one of us can be `ourName_27_27`
|
|
144
|
-
//
|
|
145
|
-
// The underscore prevents colliding e.g. index 1 with 11
|
|
146
|
-
while (allNodeNames.includes(jsLegal))
|
|
147
|
-
jsLegal += `_${allNodeNames.indexOf(nodeName)}`;
|
|
121
|
+
return expression;
|
|
122
|
+
}
|
|
123
|
+
function convertToUniqueJsDotName(nodeName, allNodeNames) {
|
|
124
|
+
let jsLegal = nodeName
|
|
125
|
+
.replaceAll(' ', '_')
|
|
126
|
+
.split('')
|
|
127
|
+
.filter((x) => !INVALID_JS_DOT_NAME.test(x))
|
|
128
|
+
.join('');
|
|
129
|
+
if (nodeName === jsLegal)
|
|
148
130
|
return jsLegal;
|
|
131
|
+
// This accounts for theoretical cases where we collide with other reduced names
|
|
132
|
+
// By adding our own index in the array we also avoid running into theoretical cases
|
|
133
|
+
// where a node with the name 'ourName_27' exists for our reduced name 'ourName'
|
|
134
|
+
// because we must have a different index, so therefore only one of us can be `ourName_27_27`
|
|
135
|
+
//
|
|
136
|
+
// The underscore prevents colliding e.g. index 1 with 11
|
|
137
|
+
while (allNodeNames.includes(jsLegal))
|
|
138
|
+
jsLegal += `_${allNodeNames.indexOf(nodeName)}`;
|
|
139
|
+
return jsLegal;
|
|
140
|
+
}
|
|
141
|
+
function convertDataAccessorName(name) {
|
|
142
|
+
const [fnName, maybeDigits] = name.split('(');
|
|
143
|
+
switch (fnName.toLowerCase()) {
|
|
144
|
+
case 'item':
|
|
145
|
+
return fnName;
|
|
146
|
+
case 'first':
|
|
147
|
+
case 'last':
|
|
148
|
+
return `${fnName}Item`;
|
|
149
|
+
case 'all':
|
|
150
|
+
return `${fnName}Items`;
|
|
149
151
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
152
|
+
// use the digits without the )
|
|
153
|
+
return `${fnName}_${maybeDigits?.slice(0, -1) ?? 'unknown'}`;
|
|
154
|
+
}
|
|
155
|
+
function parseExpressionMapping(isolatedExpression, nodeNameInExpression, nodeNamePlainJs, startNodeName) {
|
|
156
|
+
const splitExpr = isolatedExpression.split('.');
|
|
157
|
+
// This supports literal . used in the node name
|
|
158
|
+
const dotsInName = nodeNameInExpression?.split('').filter((x) => x === '.').length ?? 0;
|
|
159
|
+
const dotInAccessorsOffset = isolatedExpression.startsWith('$node.') ? 1 : 0;
|
|
160
|
+
const exprStart = splitExpr.slice(0, dotInAccessorsOffset + dotsInName + 1).join('.');
|
|
161
|
+
const parts = splitExpr.slice(dotInAccessorsOffset + dotsInName + 1);
|
|
162
|
+
// The calling code is expected to only handle $json expressions for the root node
|
|
163
|
+
// As these are invalid conversions for inner nodes
|
|
164
|
+
if (exprStart === '$json') {
|
|
165
|
+
let partsIdx = 0;
|
|
166
|
+
for (; partsIdx < parts.length; ++partsIdx) {
|
|
167
|
+
if (!DOT_REFERENCEABLE_JS_VARIABLE.test(parts[partsIdx]))
|
|
168
|
+
break;
|
|
160
169
|
}
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
return {
|
|
171
|
+
nodeNameInExpression: null,
|
|
172
|
+
originalExpression: `${exprStart}.${parts.slice(0, partsIdx + 1).join('.')}`, // $json.valid.until, but not ['x'] after
|
|
173
|
+
replacementPrefix: `${exprStart}`, // $json
|
|
174
|
+
replacementName: `${parts.slice(0, partsIdx).join('_')}`, // valid_until
|
|
175
|
+
};
|
|
163
176
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
if (parts.length === 0) {
|
|
178
|
+
// If a node is referenced by name without any accessor we return a proxy that stringifies as an empty object
|
|
179
|
+
// But it can still be validly passed to other functions
|
|
180
|
+
// However when passed to a sub-workflow it collapses into a true empty object
|
|
181
|
+
// So lets just abort porting this and don't touch it
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
// Handling `all()` is very awkward since we need to pass the value as a single parameter but
|
|
185
|
+
// can't do `$('Start').all() since it would be a different node's all
|
|
186
|
+
const accessorPrefix = parts[0] === 'all()' ? 'first()' : parts[0];
|
|
187
|
+
if (ITEM_TO_DATA_ACCESSORS.some((x) => parts[0].match(x))) {
|
|
188
|
+
if (parts.length === 1) {
|
|
189
|
+
// this case is a literal use of the return value of `$('nodeName').first()`
|
|
190
|
+
// Note that it's safe to rename to first, even if there is a variable of the same name
|
|
191
|
+
// since we resolve duplicate names later in the process
|
|
192
|
+
const originalName = parts[0];
|
|
179
193
|
return {
|
|
180
|
-
nodeNameInExpression
|
|
181
|
-
originalExpression: `${exprStart}.${parts
|
|
182
|
-
replacementPrefix: `${
|
|
183
|
-
replacementName: `${
|
|
194
|
+
nodeNameInExpression,
|
|
195
|
+
originalExpression: `${exprStart}.${parts[0]}`, // $('abc').first()
|
|
196
|
+
replacementPrefix: `$('${startNodeName}').${accessorPrefix}.json`, // $('Start').first().json
|
|
197
|
+
replacementName: `${nodeNamePlainJs}_${convertDataAccessorName(originalName)}`, // nodeName_firstItem, nodeName_itemMatching_20
|
|
184
198
|
};
|
|
185
199
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const accessorPrefix = parts[0] === 'all()' ? 'first()' : parts[0];
|
|
196
|
-
if (ITEM_TO_DATA_ACCESSORS.some((x) => parts[0].match(x))) {
|
|
197
|
-
if (parts.length === 1) {
|
|
198
|
-
// this case is a literal use of the return value of `$('nodeName').first()`
|
|
199
|
-
// Note that it's safe to rename to first, even if there is a variable of the same name
|
|
200
|
-
// since we resolve duplicate names later in the process
|
|
201
|
-
const originalName = parts[0];
|
|
200
|
+
else {
|
|
201
|
+
if (DATA_ACCESSORS.some((x) => parts[1] === x)) {
|
|
202
|
+
let partsIdx = 2;
|
|
203
|
+
for (; partsIdx < parts.length; ++partsIdx) {
|
|
204
|
+
if (!DOT_REFERENCEABLE_JS_VARIABLE.test(parts[partsIdx]))
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
// Use a separate name for anything except item to avoid users confusing their e.g. first() variables
|
|
208
|
+
const replacementPostfix = parts[0] === 'item' ? '' : `_${convertDataAccessorName(parts[0])}`;
|
|
202
209
|
return {
|
|
203
210
|
nodeNameInExpression,
|
|
204
|
-
originalExpression: `${exprStart}.${parts
|
|
205
|
-
replacementPrefix: `$('${startNodeName}').${accessorPrefix}
|
|
206
|
-
replacementName:
|
|
211
|
+
originalExpression: `${exprStart}.${parts.slice(0, partsIdx + 1).join('.')}`, // $('abc').item.json.valid.until, but not ['x'] after
|
|
212
|
+
replacementPrefix: `$('${startNodeName}').${accessorPrefix}.${parts[1]}`, // $('Start').item.json
|
|
213
|
+
replacementName: parts.slice(2, partsIdx).join('_') + replacementPostfix, // valid_until, or valid_until_firstItem
|
|
207
214
|
};
|
|
208
215
|
}
|
|
209
216
|
else {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return {
|
|
219
|
-
nodeNameInExpression,
|
|
220
|
-
originalExpression: `${exprStart}.${parts.slice(0, partsIdx + 1).join('.')}`, // $('abc').item.json.valid.until, but not ['x'] after
|
|
221
|
-
replacementPrefix: `$('${startNodeName}').${accessorPrefix}.${parts[1]}`, // $('Start').item.json
|
|
222
|
-
replacementName: parts.slice(2, partsIdx).join('_') + replacementPostfix, // valid_until, or valid_until_firstItem
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
// this case covers any normal ObjectExtensions functions called on the ITEM_TO_DATA_ACCESSORS entry
|
|
227
|
-
// e.g. $('nodeName').first().toJsonObject().randomJSFunction() or $('nodeName').all().map(x => ({...x, a: 3 }))
|
|
228
|
-
return {
|
|
229
|
-
nodeNameInExpression,
|
|
230
|
-
originalExpression: `${exprStart}.${parts[0]}`, // $('abc').first()
|
|
231
|
-
replacementPrefix: `$('${startNodeName}').${accessorPrefix}.json`, // $('Start').first().json.
|
|
232
|
-
replacementName: `${nodeNamePlainJs}_${convertDataAccessorName(parts[0])}`, // nodeName_firstItem
|
|
233
|
-
};
|
|
234
|
-
}
|
|
217
|
+
// this case covers any normal ObjectExtensions functions called on the ITEM_TO_DATA_ACCESSORS entry
|
|
218
|
+
// e.g. $('nodeName').first().toJsonObject().randomJSFunction() or $('nodeName').all().map(x => ({...x, a: 3 }))
|
|
219
|
+
return {
|
|
220
|
+
nodeNameInExpression,
|
|
221
|
+
originalExpression: `${exprStart}.${parts[0]}`, // $('abc').first()
|
|
222
|
+
replacementPrefix: `$('${startNodeName}').${accessorPrefix}.json`, // $('Start').first().json.
|
|
223
|
+
replacementName: `${nodeNamePlainJs}_${convertDataAccessorName(parts[0])}`, // nodeName_firstItem
|
|
224
|
+
};
|
|
235
225
|
}
|
|
236
226
|
}
|
|
237
|
-
// This covers specific metadata functions available on nodes
|
|
238
|
-
const itemAccessorMatch = ITEM_ACCESSORS.flatMap((x) => (x === parts[0] ? x : []))[0];
|
|
239
|
-
if (itemAccessorMatch !== undefined) {
|
|
240
|
-
return {
|
|
241
|
-
nodeNameInExpression,
|
|
242
|
-
originalExpression: `${exprStart}.${parts[0]}`, // $('abc').isExecuted
|
|
243
|
-
replacementPrefix: `$('${startNodeName}').first().json`, // $('Start').first()
|
|
244
|
-
replacementName: `${nodeNamePlainJs}_${parts[0]}`, // nodeName_isExecuted
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
// If we end up here it means that:
|
|
248
|
-
// - we have a complex `itemMatching(<expr>)` case, or
|
|
249
|
-
// - the expression should be invalid, or
|
|
250
|
-
// - a new function was added that we're not aware of.
|
|
251
|
-
//
|
|
252
|
-
// In these cases let's just not touch it and keep it as is
|
|
253
|
-
return null;
|
|
254
227
|
}
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const after_accessor = expression.slice(after_accessor_idx);
|
|
265
|
-
const firstInvalidCharMatch = INVALID_JS_DOT_PATH.exec(after_accessor);
|
|
266
|
-
// we should at least find the }} closing the JS expressions in valid cases
|
|
267
|
-
if (!firstInvalidCharMatch)
|
|
268
|
-
return null;
|
|
269
|
-
return expression.slice(startIndex, after_accessor_idx + firstInvalidCharMatch.index);
|
|
270
|
-
}
|
|
271
|
-
// Parse a given regex accessor match (e.g. `$('nodeName')`, `$node['nodeName']`)
|
|
272
|
-
// and extract a potential ExpressionMapping
|
|
273
|
-
function parseCandidateMatch(match, expression, nodeNames, startNodeName) {
|
|
274
|
-
const startIndex = match.index;
|
|
275
|
-
const endIndex = startIndex + match[0].length + 1;
|
|
276
|
-
// this works because all access patterns define match groups
|
|
277
|
-
// [fullMatch, "$('", "nodeName", "')"]
|
|
278
|
-
const nodeNameInExpression = match[2];
|
|
279
|
-
// This should be invalid in theory, since the regex matches should only act
|
|
280
|
-
// on known node names
|
|
281
|
-
if (!nodeNames.includes(nodeNameInExpression))
|
|
282
|
-
return null;
|
|
283
|
-
const candidate = extractExpressionCandidate(expression, startIndex, endIndex);
|
|
284
|
-
if (candidate === null)
|
|
285
|
-
return null;
|
|
286
|
-
return parseExpressionMapping(candidate, nodeNameInExpression, convertToUniqueJsDotName(nodeNameInExpression, nodeNames), startNodeName);
|
|
228
|
+
// This covers specific metadata functions available on nodes
|
|
229
|
+
const itemAccessorMatch = ITEM_ACCESSORS.flatMap((x) => (x === parts[0] ? x : []))[0];
|
|
230
|
+
if (itemAccessorMatch !== undefined) {
|
|
231
|
+
return {
|
|
232
|
+
nodeNameInExpression,
|
|
233
|
+
originalExpression: `${exprStart}.${parts[0]}`, // $('abc').isExecuted
|
|
234
|
+
replacementPrefix: `$('${startNodeName}').first().json`, // $('Start').first()
|
|
235
|
+
replacementName: `${nodeNamePlainJs}_${parts[0]}`, // nodeName_isExecuted
|
|
236
|
+
};
|
|
287
237
|
}
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
238
|
+
// If we end up here it means that:
|
|
239
|
+
// - we have a complex `itemMatching(<expr>)` case, or
|
|
240
|
+
// - the expression should be invalid, or
|
|
241
|
+
// - a new function was added that we're not aware of.
|
|
242
|
+
//
|
|
243
|
+
// In these cases let's just not touch it and keep it as is
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
// find `$('NodeName').item.json.path.to.x` in `{{ $('NodeName').item.json.path.to.x[someFunction()] }}`
|
|
247
|
+
function extractExpressionCandidate(expression, startIndex, endIndex) {
|
|
248
|
+
const firstPartException = ITEM_TO_DATA_ACCESSORS.map((x) => x.exec(expression.slice(endIndex))).filter((x) => x !== null);
|
|
249
|
+
// Note that by choosing match 0 we use `itemMatching` matches over `item`
|
|
250
|
+
// matches by relying on the order in ITEM_TO_DATA_ACCESSORS
|
|
251
|
+
let after_accessor_idx = endIndex + (firstPartException[0]?.[0].length ?? -1);
|
|
252
|
+
// skip `.` to continue, but halt before other symbols like `[` in `all()[0]`
|
|
253
|
+
if (expression[after_accessor_idx + 1] === '.')
|
|
254
|
+
after_accessor_idx += 1;
|
|
255
|
+
const after_accessor = expression.slice(after_accessor_idx);
|
|
256
|
+
const firstInvalidCharMatch = INVALID_JS_DOT_PATH.exec(after_accessor);
|
|
257
|
+
// we should at least find the }} closing the JS expressions in valid cases
|
|
258
|
+
if (!firstInvalidCharMatch)
|
|
259
|
+
return null;
|
|
260
|
+
return expression.slice(startIndex, after_accessor_idx + firstInvalidCharMatch.index);
|
|
261
|
+
}
|
|
262
|
+
// Parse a given regex accessor match (e.g. `$('nodeName')`, `$node['nodeName']`)
|
|
263
|
+
// and extract a potential ExpressionMapping
|
|
264
|
+
function parseCandidateMatch(match, expression, nodeNames, startNodeName) {
|
|
265
|
+
const startIndex = match.index;
|
|
266
|
+
const endIndex = startIndex + match[0].length + 1;
|
|
267
|
+
// this works because all access patterns define match groups
|
|
268
|
+
// [fullMatch, "$('", "nodeName", "')"]
|
|
269
|
+
const nodeNameInExpression = match[2];
|
|
270
|
+
// This should be invalid in theory, since the regex matches should only act
|
|
271
|
+
// on known node names
|
|
272
|
+
if (!nodeNames.includes(nodeNameInExpression))
|
|
273
|
+
return null;
|
|
274
|
+
const candidate = extractExpressionCandidate(expression, startIndex, endIndex);
|
|
275
|
+
if (candidate === null)
|
|
276
|
+
return null;
|
|
277
|
+
return parseExpressionMapping(candidate, nodeNameInExpression, convertToUniqueJsDotName(nodeNameInExpression, nodeNames), startNodeName);
|
|
278
|
+
}
|
|
279
|
+
// Handle matches of form `$json.path.to.value`, which is necessary for the selection input node
|
|
280
|
+
function parse$jsonMatch(match, expression, startNodeName) {
|
|
281
|
+
const candidate = extractExpressionCandidate(expression, match.index, match.index + match[0].length + 1);
|
|
282
|
+
if (candidate === null)
|
|
283
|
+
return null;
|
|
284
|
+
return parseExpressionMapping(candidate, null, null, startNodeName);
|
|
285
|
+
}
|
|
286
|
+
// Parse all references to other nodes in `expression` and return them as `ExpressionMappings`
|
|
287
|
+
function parseReferencingExpressions(expression, nodeRegexps, nodeNames, startNodeName, parse$json) {
|
|
288
|
+
const result = [];
|
|
289
|
+
for (const [pattern, regexp] of nodeRegexps) {
|
|
290
|
+
if (!expression.includes(pattern))
|
|
291
|
+
continue;
|
|
292
|
+
const matches = [...expression.matchAll(regexp.get())];
|
|
293
|
+
result.push(...matches
|
|
294
|
+
.map((x) => parseCandidateMatch(x, expression, nodeNames, startNodeName))
|
|
295
|
+
.filter((x) => x !== null));
|
|
294
296
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
continue;
|
|
301
|
-
const matches = [...expression.matchAll(regexp.get())];
|
|
302
|
-
result.push(...matches
|
|
303
|
-
.map((x) => parseCandidateMatch(x, expression, nodeNames, startNodeName))
|
|
304
|
-
.filter((x) => x !== null));
|
|
297
|
+
if (parse$json && expression.includes('$json')) {
|
|
298
|
+
for (const match of expression.matchAll(/\$json/gi)) {
|
|
299
|
+
const res = parse$jsonMatch(match, expression, startNodeName);
|
|
300
|
+
if (res)
|
|
301
|
+
result.push(res);
|
|
305
302
|
}
|
|
306
|
-
if (parse$json && expression.includes('$json')) {
|
|
307
|
-
for (const match of expression.matchAll(/\$json/gi)) {
|
|
308
|
-
const res = parse$jsonMatch(match, expression, startNodeName);
|
|
309
|
-
if (res)
|
|
310
|
-
result.push(res);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return result;
|
|
314
303
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return [
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
// Recursively apply `mapper` to all expressions in `parameterValue`
|
|
307
|
+
function applyParameterMapping(parameterValue, mapper, keyOfValue) {
|
|
308
|
+
const result = {};
|
|
309
|
+
if (typeof parameterValue !== 'object' || parameterValue === null) {
|
|
310
|
+
if (typeof parameterValue === 'string' &&
|
|
311
|
+
(parameterValue.charAt(0) === '=' || keyOfValue === 'jsCode')) {
|
|
312
|
+
const mapping = mapper(parameterValue);
|
|
313
|
+
return [mapping, mapping];
|
|
325
314
|
}
|
|
326
|
-
|
|
327
|
-
for (const [key, value] of Object.entries(parameterValue)) {
|
|
328
|
-
const [mapping, all] = applyParameterMapping(value, mapper, key);
|
|
329
|
-
result[key] = mapping;
|
|
330
|
-
allMappings.push(...all);
|
|
331
|
-
}
|
|
332
|
-
return [result, allMappings];
|
|
315
|
+
return [undefined, []];
|
|
333
316
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
for (const mapping of data) {
|
|
340
|
-
const { nodeNameInExpression, originalExpression, replacementPrefix } = mapping;
|
|
341
|
-
let { replacementName } = mapping;
|
|
342
|
-
const hasKeyAndCollides = (key) => {
|
|
343
|
-
const value = triggerArgumentMap.get(key);
|
|
344
|
-
if (!value)
|
|
345
|
-
return false;
|
|
346
|
-
return !(0, isEqual_1.default)(value, mapping);
|
|
347
|
-
};
|
|
348
|
-
// We need both parts in the key as we may need to pass e.g. `.first()` and `.item` separately
|
|
349
|
-
// Since we cannot pass the node itself as its proxy reduces it to an empty object
|
|
350
|
-
const key = () => `${replacementPrefix}.${replacementName}`;
|
|
351
|
-
// This covers a realistic case where two nodes have the same path, e.g.
|
|
352
|
-
// $('original input').item.json.path.to.url
|
|
353
|
-
// $('some time later in the workflow').item.json.path.to.url
|
|
354
|
-
if (hasKeyAndCollides(key()) && nodeNameInExpression) {
|
|
355
|
-
replacementName = `${convertToUniqueJsDotName(nodeNameInExpression, allNodeNames)}_${replacementName}`;
|
|
356
|
-
}
|
|
357
|
-
// This covers all other theoretical cases, like where `${nodeName}_${variable}` might clash with another variable name
|
|
358
|
-
while (hasKeyAndCollides(key()))
|
|
359
|
-
replacementName += '_1';
|
|
360
|
-
triggerArgumentMap.set(key(), {
|
|
361
|
-
originalExpression,
|
|
362
|
-
nodeNameInExpression,
|
|
363
|
-
replacementName,
|
|
364
|
-
replacementPrefix,
|
|
365
|
-
});
|
|
366
|
-
originalExpressionMap.set(originalExpression, key());
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
triggerArgumentMap,
|
|
370
|
-
originalExpressionMap,
|
|
371
|
-
};
|
|
317
|
+
const allMappings = [];
|
|
318
|
+
for (const [key, value] of Object.entries(parameterValue)) {
|
|
319
|
+
const [mapping, all] = applyParameterMapping(value, mapper, key);
|
|
320
|
+
result[key] = mapping;
|
|
321
|
+
allMappings.push(...all);
|
|
372
322
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return parameters;
|
|
389
|
-
}
|
|
390
|
-
// This should be an invalid state, though an explicit check makes typings easier
|
|
391
|
-
if (Array.isArray(mapping)) {
|
|
392
|
-
return parameters;
|
|
393
|
-
}
|
|
394
|
-
if (Array.isArray(parameters) && typeof mapping === 'object' && !Array.isArray(mapping)) {
|
|
395
|
-
return parameters.map((x, i) => applyMapping(x, mapping[i]));
|
|
396
|
-
}
|
|
397
|
-
return (0, mapValues_1.default)(parameters, (v, k) => applyMapping(v, mapping[k]));
|
|
323
|
+
return [result, allMappings];
|
|
324
|
+
}
|
|
325
|
+
// Ensure all expressions have a unique variable name
|
|
326
|
+
function resolveDuplicates(data, allNodeNames) {
|
|
327
|
+
// Map from candidate variableName to its expressionData
|
|
328
|
+
const triggerArgumentMap = new Map();
|
|
329
|
+
const originalExpressionMap = new Map();
|
|
330
|
+
for (const mapping of data) {
|
|
331
|
+
const { nodeNameInExpression, originalExpression, replacementPrefix } = mapping;
|
|
332
|
+
let { replacementName } = mapping;
|
|
333
|
+
const hasKeyAndCollides = (key) => {
|
|
334
|
+
const value = triggerArgumentMap.get(key);
|
|
335
|
+
if (!value)
|
|
336
|
+
return false;
|
|
337
|
+
return !(0, isEqual_1.default)(value, mapping);
|
|
398
338
|
};
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
// Sort by longest so that we don't accidentally replace part of a longer expression
|
|
408
|
-
return mapping
|
|
409
|
-
.map(getCanonicalData)
|
|
410
|
-
.filter((x) => x !== undefined)
|
|
411
|
-
.sort((a, b) => b.originalExpression.length - a.originalExpression.length);
|
|
339
|
+
// We need both parts in the key as we may need to pass e.g. `.first()` and `.item` separately
|
|
340
|
+
// Since we cannot pass the node itself as its proxy reduces it to an empty object
|
|
341
|
+
const key = () => `${replacementPrefix}.${replacementName}`;
|
|
342
|
+
// This covers a realistic case where two nodes have the same path, e.g.
|
|
343
|
+
// $('original input').item.json.path.to.url
|
|
344
|
+
// $('some time later in the workflow').item.json.path.to.url
|
|
345
|
+
if (hasKeyAndCollides(key()) && nodeNameInExpression) {
|
|
346
|
+
replacementName = `${convertToUniqueJsDotName(nodeNameInExpression, allNodeNames)}_${replacementName}`;
|
|
412
347
|
}
|
|
413
|
-
|
|
348
|
+
// This covers all other theoretical cases, like where `${nodeName}_${variable}` might clash with another variable name
|
|
349
|
+
while (hasKeyAndCollides(key()))
|
|
350
|
+
replacementName += '_1';
|
|
351
|
+
triggerArgumentMap.set(key(), {
|
|
352
|
+
originalExpression,
|
|
353
|
+
nodeNameInExpression,
|
|
354
|
+
replacementName,
|
|
355
|
+
replacementPrefix,
|
|
356
|
+
});
|
|
357
|
+
originalExpressionMap.set(originalExpression, key());
|
|
414
358
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
if (subGraphNames.some((x) => !nodeNames.includes(x))) {
|
|
434
|
-
throw new errors_1.OperationalError(`extractReferencesInNodeExpressions called with node in subGraph ${JSON.stringify(subGraphNames)} whose name is not in provided 'nodeNames' list ${JSON.stringify(nodeNames)}.`);
|
|
435
|
-
}
|
|
436
|
-
////
|
|
437
|
-
// STEP 2 - Compile all candidate regexp patterns
|
|
438
|
-
////
|
|
439
|
-
// This looks scary for large workflows, but RegExp should support >1 million characters and
|
|
440
|
-
// it's a very linear pattern.
|
|
441
|
-
const namesRegexp = '(' + nodeNames.map(escapeRegExp_1.default).join('|') + ')';
|
|
442
|
-
const nodeRegexps = ACCESS_PATTERNS.map((pattern) => [
|
|
443
|
-
pattern.checkPattern,
|
|
444
|
-
// avoid compiling the expensive regex for rare legacy ways of accessing nodes
|
|
445
|
-
new LazyRegExp(() => pattern.replacePattern(namesRegexp), 'g'),
|
|
446
|
-
]);
|
|
447
|
-
////
|
|
448
|
-
// STEP 3 - Parse expressions used in parameters and build mappings
|
|
449
|
-
////
|
|
450
|
-
// This map is used to change the actual expressions once resolved
|
|
451
|
-
// The value represents fields in the actual parameters object which require change
|
|
452
|
-
const parameterTreeMappingByNode = new Map();
|
|
453
|
-
// This is used to track all candidates for change, necessary for deduplication
|
|
454
|
-
const allData = [];
|
|
455
|
-
// Additional mappings that should contribute to sub-workflow inputs (e.g. Split Out 'fieldToSplitOut')
|
|
456
|
-
const extraVariableCandidates = [];
|
|
457
|
-
for (const node of subGraph) {
|
|
458
|
-
const [parameterMapping, allMappings] = applyParameterMapping(node.parameters, (s) => parseReferencingExpressions(s, nodeRegexps, nodeNames, insertedStartName, graphInputNodeNames?.includes(node.name) ?? false));
|
|
459
|
-
parameterTreeMappingByNode.set(node.name, parameterMapping);
|
|
460
|
-
allData.push(...allMappings);
|
|
461
|
-
if (node.name === start && node.type === SPLIT_OUT_NODE_TYPE) {
|
|
462
|
-
const raw = node.parameters?.fieldToSplitOut;
|
|
463
|
-
if (typeof raw === 'string' && raw.trim() !== '') {
|
|
464
|
-
const trimmed = raw.trim();
|
|
465
|
-
const isExpression = trimmed.startsWith('=');
|
|
466
|
-
// Expressions in Split Out 'fieldToSplitOut' parameters are not supported,
|
|
467
|
-
// as they define the fields to split out only at execution time.
|
|
468
|
-
if (isExpression) {
|
|
469
|
-
throw new errors_1.OperationalError(`Extracting sub-workflow from Split Out node with 'fieldToSplitOut' parameter having expression "${trimmed}" is not supported.`);
|
|
470
|
-
}
|
|
471
|
-
// Parameter value is a CSV of fields to split out.
|
|
472
|
-
// Create synthetic $json expressions for each field
|
|
473
|
-
const fields = isExpression
|
|
474
|
-
? [trimmed]
|
|
475
|
-
: trimmed.split(',').map((field) => `={{$json.${field.trim()}}}`);
|
|
476
|
-
for (const expression of fields) {
|
|
477
|
-
const mappingsFromField = parseReferencingExpressions(expression, nodeRegexps, nodeNames, insertedStartName, graphInputNodeNames?.includes(node.name) ?? false);
|
|
478
|
-
extraVariableCandidates.push(...mappingsFromField);
|
|
479
|
-
}
|
|
359
|
+
return {
|
|
360
|
+
triggerArgumentMap,
|
|
361
|
+
originalExpressionMap,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
// Recursively loop through the nodeProperties and apply `parameterExtractMapping` where defined
|
|
365
|
+
function applyExtractMappingToNode(node, parameterExtractMapping) {
|
|
366
|
+
const usedMappings = [];
|
|
367
|
+
const applyMapping = (parameters, mapping) => {
|
|
368
|
+
if (!mapping)
|
|
369
|
+
return parameters;
|
|
370
|
+
if (typeof parameters !== 'object' || parameters === null) {
|
|
371
|
+
if (Array.isArray(mapping) && typeof parameters === 'string') {
|
|
372
|
+
for (const mapper of mapping) {
|
|
373
|
+
if (!parameters.includes(mapper.originalExpression))
|
|
374
|
+
continue;
|
|
375
|
+
parameters = parameters.replaceAll(mapper.originalExpression, `${mapper.replacementPrefix}.${mapper.replacementName}`);
|
|
376
|
+
usedMappings.push(mapper);
|
|
480
377
|
}
|
|
481
378
|
}
|
|
379
|
+
return parameters;
|
|
482
380
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const subGraphNodeNames = new Set(subGraphNames);
|
|
487
|
-
const dataFromOutsideSubgraph = [...allData, ...extraVariableCandidates].filter(
|
|
488
|
-
// `nodeNameInExpression` being absent implies direct access via `$json` or `$binary`
|
|
489
|
-
(x) => !x.nodeNameInExpression || !subGraphNodeNames.has(x.nodeNameInExpression));
|
|
490
|
-
const { originalExpressionMap, triggerArgumentMap } = resolveDuplicates(dataFromOutsideSubgraph, nodeNames);
|
|
491
|
-
////
|
|
492
|
-
// STEP 5 - Apply canonical mappings to nodes and track created variables
|
|
493
|
-
////
|
|
494
|
-
// triggerArgumentMap[originalExpressionMap[originalExpression]] returns its canonical object
|
|
495
|
-
// These should never be undefined at this stage
|
|
496
|
-
const getCanonicalData = (e) => {
|
|
497
|
-
const key = originalExpressionMap.get(e.originalExpression);
|
|
498
|
-
if (!key)
|
|
499
|
-
return undefined;
|
|
500
|
-
return triggerArgumentMap.get(key);
|
|
501
|
-
};
|
|
502
|
-
for (const [key, value] of parameterTreeMappingByNode.entries()) {
|
|
503
|
-
parameterTreeMappingByNode.set(key, applyCanonicalMapping(value, getCanonicalData));
|
|
381
|
+
// This should be an invalid state, though an explicit check makes typings easier
|
|
382
|
+
if (Array.isArray(mapping)) {
|
|
383
|
+
return parameters;
|
|
504
384
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
for (const node of subGraph) {
|
|
508
|
-
const { result, usedMappings } = applyExtractMappingToNode((0, cloneDeep_1.default)(node), parameterTreeMappingByNode.get(node.name));
|
|
509
|
-
allUsedMappings.push(...usedMappings);
|
|
510
|
-
output.push(result);
|
|
385
|
+
if (Array.isArray(parameters) && typeof mapping === 'object' && !Array.isArray(mapping)) {
|
|
386
|
+
return parameters.map((x, i) => applyMapping(x, mapping[i]));
|
|
511
387
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
388
|
+
return (0, mapValues_1.default)(parameters, (v, k) => applyMapping(v, mapping[k]));
|
|
389
|
+
};
|
|
390
|
+
const parameters = applyMapping(node.parameters, parameterExtractMapping);
|
|
391
|
+
return { result: { ...node, parameters }, usedMappings };
|
|
392
|
+
}
|
|
393
|
+
// Recursively find the finalized mapping for provisional mappings
|
|
394
|
+
function applyCanonicalMapping(mapping, getCanonicalData) {
|
|
395
|
+
if (!mapping)
|
|
396
|
+
return;
|
|
397
|
+
if (Array.isArray(mapping)) {
|
|
398
|
+
// Sort by longest so that we don't accidentally replace part of a longer expression
|
|
399
|
+
return mapping
|
|
400
|
+
.map(getCanonicalData)
|
|
401
|
+
.filter((x) => x !== undefined)
|
|
402
|
+
.sort((a, b) => b.originalExpression.length - a.originalExpression.length);
|
|
403
|
+
}
|
|
404
|
+
return (0, mapValues_1.default)(mapping, (v) => applyCanonicalMapping(v, getCanonicalData));
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Extracts references to nodes in `nodeNames` from the nodes in `subGraph`.
|
|
408
|
+
*
|
|
409
|
+
* @returns an object with two keys:
|
|
410
|
+
* - nodes: Transformed copies of nodes in `subGraph`, ready for use in a sub-workflow
|
|
411
|
+
* - variables: A map from variable name in the sub-workflow to the replaced expression
|
|
412
|
+
*
|
|
413
|
+
* @throws if the startNodeName already exists in `nodeNames`
|
|
414
|
+
* @throws if `nodeNames` does not include all node names in `subGraph`
|
|
415
|
+
*/
|
|
416
|
+
function extractReferencesInNodeExpressions(subGraph, nodeNames, insertedStartName, graphInputNodeNames) {
|
|
417
|
+
const [start] = graphInputNodeNames ?? [];
|
|
418
|
+
////
|
|
419
|
+
// STEP 1 - Validate input invariants
|
|
420
|
+
////
|
|
421
|
+
const subGraphNames = subGraph.map((x) => x.name);
|
|
422
|
+
if (subGraphNames.includes(insertedStartName))
|
|
423
|
+
throw new errors_1.OperationalError(`StartNodeName ${insertedStartName} already exists in nodeNames: ${JSON.stringify(subGraphNames)}`);
|
|
424
|
+
if (subGraphNames.some((x) => !nodeNames.includes(x))) {
|
|
425
|
+
throw new errors_1.OperationalError(`extractReferencesInNodeExpressions called with node in subGraph ${JSON.stringify(subGraphNames)} whose name is not in provided 'nodeNames' list ${JSON.stringify(nodeNames)}.`);
|
|
426
|
+
}
|
|
427
|
+
////
|
|
428
|
+
// STEP 2 - Compile all candidate regexp patterns
|
|
429
|
+
////
|
|
430
|
+
// This looks scary for large workflows, but RegExp should support >1 million characters and
|
|
431
|
+
// it's a very linear pattern.
|
|
432
|
+
const namesRegexp = '(' + nodeNames.map(escapeRegExp_1.default).join('|') + ')';
|
|
433
|
+
const nodeRegexps = ACCESS_PATTERNS.map((pattern) => [
|
|
434
|
+
pattern.checkPattern,
|
|
435
|
+
// avoid compiling the expensive regex for rare legacy ways of accessing nodes
|
|
436
|
+
new LazyRegExp(() => pattern.replacePattern(namesRegexp), 'g'),
|
|
437
|
+
]);
|
|
438
|
+
////
|
|
439
|
+
// STEP 3 - Parse expressions used in parameters and build mappings
|
|
440
|
+
////
|
|
441
|
+
// This map is used to change the actual expressions once resolved
|
|
442
|
+
// The value represents fields in the actual parameters object which require change
|
|
443
|
+
const parameterTreeMappingByNode = new Map();
|
|
444
|
+
// This is used to track all candidates for change, necessary for deduplication
|
|
445
|
+
const allData = [];
|
|
446
|
+
// Additional mappings that should contribute to sub-workflow inputs (e.g. Split Out 'fieldToSplitOut')
|
|
447
|
+
const extraVariableCandidates = [];
|
|
448
|
+
for (const node of subGraph) {
|
|
449
|
+
const [parameterMapping, allMappings] = applyParameterMapping(node.parameters, (s) => parseReferencingExpressions(s, nodeRegexps, nodeNames, insertedStartName, graphInputNodeNames?.includes(node.name) ?? false));
|
|
450
|
+
parameterTreeMappingByNode.set(node.name, parameterMapping);
|
|
451
|
+
allData.push(...allMappings);
|
|
452
|
+
if (node.name === start && node.type === SPLIT_OUT_NODE_TYPE) {
|
|
453
|
+
const raw = node.parameters?.fieldToSplitOut;
|
|
454
|
+
if (typeof raw === 'string' && raw.trim() !== '') {
|
|
455
|
+
const trimmed = raw.trim();
|
|
456
|
+
const isExpression = trimmed.startsWith('=');
|
|
457
|
+
// Expressions in Split Out 'fieldToSplitOut' parameters are not supported,
|
|
458
|
+
// as they define the fields to split out only at execution time.
|
|
459
|
+
if (isExpression) {
|
|
460
|
+
throw new errors_1.OperationalError(`Extracting sub-workflow from Split Out node with 'fieldToSplitOut' parameter having expression "${trimmed}" is not supported.`);
|
|
461
|
+
}
|
|
462
|
+
// Parameter value is a CSV of fields to split out.
|
|
463
|
+
// Create synthetic $json expressions for each field
|
|
464
|
+
const fields = isExpression
|
|
465
|
+
? [trimmed]
|
|
466
|
+
: trimmed.split(',').map((field) => `={{$json.${field.trim()}}}`);
|
|
467
|
+
for (const expression of fields) {
|
|
468
|
+
const mappingsFromField = parseReferencingExpressions(expression, nodeRegexps, nodeNames, insertedStartName, graphInputNodeNames?.includes(node.name) ?? false);
|
|
469
|
+
extraVariableCandidates.push(...mappingsFromField);
|
|
470
|
+
}
|
|
521
471
|
}
|
|
522
472
|
}
|
|
523
|
-
const variables = new Map(allUsedMappings.map((m) => [m.replacementName, m.originalExpression]));
|
|
524
|
-
return { nodes: output, variables };
|
|
525
473
|
}
|
|
526
|
-
|
|
474
|
+
////
|
|
475
|
+
// STEP 4 - Filter out nodes in subGraph and handle name clashes
|
|
476
|
+
////
|
|
477
|
+
const subGraphNodeNames = new Set(subGraphNames);
|
|
478
|
+
const dataFromOutsideSubgraph = [...allData, ...extraVariableCandidates].filter(
|
|
479
|
+
// `nodeNameInExpression` being absent implies direct access via `$json` or `$binary`
|
|
480
|
+
(x) => !x.nodeNameInExpression || !subGraphNodeNames.has(x.nodeNameInExpression));
|
|
481
|
+
const { originalExpressionMap, triggerArgumentMap } = resolveDuplicates(dataFromOutsideSubgraph, nodeNames);
|
|
482
|
+
////
|
|
483
|
+
// STEP 5 - Apply canonical mappings to nodes and track created variables
|
|
484
|
+
////
|
|
485
|
+
// triggerArgumentMap[originalExpressionMap[originalExpression]] returns its canonical object
|
|
486
|
+
// These should never be undefined at this stage
|
|
487
|
+
const getCanonicalData = (e) => {
|
|
488
|
+
const key = originalExpressionMap.get(e.originalExpression);
|
|
489
|
+
if (!key)
|
|
490
|
+
return undefined;
|
|
491
|
+
return triggerArgumentMap.get(key);
|
|
492
|
+
};
|
|
493
|
+
for (const [key, value] of parameterTreeMappingByNode.entries()) {
|
|
494
|
+
parameterTreeMappingByNode.set(key, applyCanonicalMapping(value, getCanonicalData));
|
|
495
|
+
}
|
|
496
|
+
const allUsedMappings = [];
|
|
497
|
+
const output = [];
|
|
498
|
+
for (const node of subGraph) {
|
|
499
|
+
const { result, usedMappings } = applyExtractMappingToNode((0, cloneDeep_1.default)(node), parameterTreeMappingByNode.get(node.name));
|
|
500
|
+
allUsedMappings.push(...usedMappings);
|
|
501
|
+
output.push(result);
|
|
502
|
+
}
|
|
503
|
+
for (const candidate of extraVariableCandidates) {
|
|
504
|
+
const key = originalExpressionMap.get(candidate.originalExpression);
|
|
505
|
+
if (!key)
|
|
506
|
+
continue;
|
|
507
|
+
const canonical = triggerArgumentMap.get(key);
|
|
508
|
+
if (!canonical)
|
|
509
|
+
continue;
|
|
510
|
+
if (!allUsedMappings.some((u) => u.replacementName === canonical.replacementName)) {
|
|
511
|
+
allUsedMappings.push(canonical);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
const variables = new Map(allUsedMappings.map((m) => [m.replacementName, m.originalExpression]));
|
|
515
|
+
return { nodes: output, variables };
|
|
516
|
+
}
|
|
527
517
|
//# sourceMappingURL=node-reference-parser-utils.js.map
|