n8n-workflow 2.31.2 → 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.
Files changed (406) hide show
  1. package/dist/cjs/augment-object.js +136 -146
  2. package/dist/cjs/augment-object.js.map +1 -1
  3. package/dist/cjs/build.tsbuildinfo +1 -1
  4. package/dist/cjs/common/find-ai-root-node-names.js +36 -46
  5. package/dist/cjs/common/find-ai-root-node-names.js.map +1 -1
  6. package/dist/cjs/common/get-child-nodes.js +8 -18
  7. package/dist/cjs/common/get-child-nodes.js.map +1 -1
  8. package/dist/cjs/common/get-connected-nodes.js +84 -94
  9. package/dist/cjs/common/get-connected-nodes.js.map +1 -1
  10. package/dist/cjs/common/get-node-by-name.js +16 -26
  11. package/dist/cjs/common/get-node-by-name.js.map +1 -1
  12. package/dist/cjs/common/get-parent-nodes.js +14 -24
  13. package/dist/cjs/common/get-parent-nodes.js.map +1 -1
  14. package/dist/cjs/common/index.js +9 -19
  15. package/dist/cjs/common/index.js.map +1 -1
  16. package/dist/cjs/common/map-connections-by-destination.js +31 -41
  17. package/dist/cjs/common/map-connections-by-destination.js.map +1 -1
  18. package/dist/cjs/common/resolve-variables.d.ts +8 -0
  19. package/dist/cjs/common/resolve-variables.d.ts.map +1 -1
  20. package/dist/cjs/common/resolve-variables.js +46 -33
  21. package/dist/cjs/common/resolve-variables.js.map +1 -1
  22. package/dist/cjs/connections-diff.js +58 -68
  23. package/dist/cjs/connections-diff.js.map +1 -1
  24. package/dist/cjs/constants.d.ts +3 -3
  25. package/dist/cjs/constants.d.ts.map +1 -1
  26. package/dist/cjs/constants.js +157 -166
  27. package/dist/cjs/constants.js.map +1 -1
  28. package/dist/cjs/credential-domain-restrictions.js +153 -163
  29. package/dist/cjs/credential-domain-restrictions.js.map +1 -1
  30. package/dist/cjs/cron.d.ts.map +1 -1
  31. package/dist/cjs/cron.js +25 -35
  32. package/dist/cjs/cron.js.map +1 -1
  33. package/dist/cjs/data-table.types.js +10 -20
  34. package/dist/cjs/data-table.types.js.map +1 -1
  35. package/dist/cjs/dynamic-credentials-helpers.js +93 -103
  36. package/dist/cjs/dynamic-credentials-helpers.js.map +1 -1
  37. package/dist/cjs/errors/abstract/execution-base.error.d.ts.map +1 -1
  38. package/dist/cjs/errors/abstract/execution-base.error.js +41 -51
  39. package/dist/cjs/errors/abstract/execution-base.error.js.map +1 -1
  40. package/dist/cjs/errors/abstract/node.error.d.ts.map +1 -1
  41. package/dist/cjs/errors/abstract/node.error.js +142 -152
  42. package/dist/cjs/errors/abstract/node.error.js.map +1 -1
  43. package/dist/cjs/errors/base/base.error.d.ts.map +1 -1
  44. package/dist/cjs/errors/base/base.error.js +35 -45
  45. package/dist/cjs/errors/base/base.error.js.map +1 -1
  46. package/dist/cjs/errors/base/operational.error.d.ts.map +1 -1
  47. package/dist/cjs/errors/base/operational.error.js +17 -27
  48. package/dist/cjs/errors/base/operational.error.js.map +1 -1
  49. package/dist/cjs/errors/base/unexpected.error.d.ts.map +1 -1
  50. package/dist/cjs/errors/base/unexpected.error.js +17 -27
  51. package/dist/cjs/errors/base/unexpected.error.js.map +1 -1
  52. package/dist/cjs/errors/base/user.error.d.ts.map +1 -1
  53. package/dist/cjs/errors/base/user.error.js +17 -27
  54. package/dist/cjs/errors/base/user.error.js.map +1 -1
  55. package/dist/cjs/errors/cli-subworkflow-operation.error.js +7 -17
  56. package/dist/cjs/errors/cli-subworkflow-operation.error.js.map +1 -1
  57. package/dist/cjs/errors/db-connection-timeout-error.d.ts.map +1 -1
  58. package/dist/cjs/errors/db-connection-timeout-error.js +11 -21
  59. package/dist/cjs/errors/db-connection-timeout-error.js.map +1 -1
  60. package/dist/cjs/errors/execution-cancelled.error.d.ts.map +1 -1
  61. package/dist/cjs/errors/execution-cancelled.error.js +33 -43
  62. package/dist/cjs/errors/execution-cancelled.error.js.map +1 -1
  63. package/dist/cjs/errors/expression-class-extension.error.d.ts.map +1 -1
  64. package/dist/cjs/errors/expression-class-extension.error.js +9 -19
  65. package/dist/cjs/errors/expression-class-extension.error.js.map +1 -1
  66. package/dist/cjs/errors/expression-computed-destructuring.error.d.ts.map +1 -1
  67. package/dist/cjs/errors/expression-computed-destructuring.error.js +9 -19
  68. package/dist/cjs/errors/expression-computed-destructuring.error.js.map +1 -1
  69. package/dist/cjs/errors/expression-destructuring.error.d.ts.map +1 -1
  70. package/dist/cjs/errors/expression-destructuring.error.js +9 -19
  71. package/dist/cjs/errors/expression-destructuring.error.js.map +1 -1
  72. package/dist/cjs/errors/expression-extension.error.js +7 -17
  73. package/dist/cjs/errors/expression-extension.error.js.map +1 -1
  74. package/dist/cjs/errors/expression-reserved-variable.error.d.ts.map +1 -1
  75. package/dist/cjs/errors/expression-reserved-variable.error.js +9 -19
  76. package/dist/cjs/errors/expression-reserved-variable.error.js.map +1 -1
  77. package/dist/cjs/errors/expression-with-statement.error.d.ts.map +1 -1
  78. package/dist/cjs/errors/expression-with-statement.error.js +9 -19
  79. package/dist/cjs/errors/expression-with-statement.error.js.map +1 -1
  80. package/dist/cjs/errors/expression.error.d.ts.map +1 -1
  81. package/dist/cjs/errors/expression.error.js +33 -43
  82. package/dist/cjs/errors/expression.error.js.map +1 -1
  83. package/dist/cjs/errors/index.js +62 -72
  84. package/dist/cjs/errors/index.js.map +1 -1
  85. package/dist/cjs/errors/node-api.error.d.ts.map +1 -1
  86. package/dist/cjs/errors/node-api.error.js +227 -237
  87. package/dist/cjs/errors/node-api.error.js.map +1 -1
  88. package/dist/cjs/errors/node-operation.error.d.ts.map +1 -1
  89. package/dist/cjs/errors/node-operation.error.js +43 -53
  90. package/dist/cjs/errors/node-operation.error.js.map +1 -1
  91. package/dist/cjs/errors/node-ssl.error.d.ts.map +1 -1
  92. package/dist/cjs/errors/node-ssl.error.js +9 -19
  93. package/dist/cjs/errors/node-ssl.error.js.map +1 -1
  94. package/dist/cjs/errors/subworkflow-operation.error.d.ts.map +1 -1
  95. package/dist/cjs/errors/subworkflow-operation.error.js +18 -28
  96. package/dist/cjs/errors/subworkflow-operation.error.js.map +1 -1
  97. package/dist/cjs/errors/trigger-close.error.d.ts.map +1 -1
  98. package/dist/cjs/errors/trigger-close.error.js +11 -21
  99. package/dist/cjs/errors/trigger-close.error.js.map +1 -1
  100. package/dist/cjs/errors/webhook-taken.error.d.ts.map +1 -1
  101. package/dist/cjs/errors/webhook-taken.error.js +9 -19
  102. package/dist/cjs/errors/webhook-taken.error.js.map +1 -1
  103. package/dist/cjs/errors/workflow-activation.error.d.ts.map +1 -1
  104. package/dist/cjs/errors/workflow-activation.error.js +54 -64
  105. package/dist/cjs/errors/workflow-activation.error.js.map +1 -1
  106. package/dist/cjs/errors/workflow-configuration.error.js +10 -20
  107. package/dist/cjs/errors/workflow-configuration.error.js.map +1 -1
  108. package/dist/cjs/errors/workflow-deactivation.error.js +7 -17
  109. package/dist/cjs/errors/workflow-deactivation.error.js.map +1 -1
  110. package/dist/cjs/errors/workflow-operation.error.d.ts.map +1 -1
  111. package/dist/cjs/errors/workflow-operation.error.js +20 -30
  112. package/dist/cjs/errors/workflow-operation.error.js.map +1 -1
  113. package/dist/cjs/evaluation-helpers.js +16 -26
  114. package/dist/cjs/evaluation-helpers.js.map +1 -1
  115. package/dist/cjs/execution-context-establishment-hooks.d.ts.map +1 -1
  116. package/dist/cjs/execution-context-establishment-hooks.js +43 -53
  117. package/dist/cjs/execution-context-establishment-hooks.js.map +1 -1
  118. package/dist/cjs/execution-context.d.ts +14 -14
  119. package/dist/cjs/execution-context.d.ts.map +1 -1
  120. package/dist/cjs/execution-context.js +203 -213
  121. package/dist/cjs/execution-context.js.map +1 -1
  122. package/dist/cjs/execution-status.d.ts +2 -2
  123. package/dist/cjs/execution-status.d.ts.map +1 -1
  124. package/dist/cjs/execution-status.js +27 -37
  125. package/dist/cjs/execution-status.js.map +1 -1
  126. package/dist/cjs/expression-evaluator-proxy.d.ts.map +1 -1
  127. package/dist/cjs/expression-evaluator-proxy.js +18 -28
  128. package/dist/cjs/expression-evaluator-proxy.js.map +1 -1
  129. package/dist/cjs/expression-sandboxing.d.ts.map +1 -1
  130. package/dist/cjs/expression-sandboxing.js +447 -457
  131. package/dist/cjs/expression-sandboxing.js.map +1 -1
  132. package/dist/cjs/expression.d.ts.map +1 -1
  133. package/dist/cjs/expression.js +535 -546
  134. package/dist/cjs/expression.js.map +1 -1
  135. package/dist/cjs/expressions/expression-helpers.d.ts.map +1 -1
  136. package/dist/cjs/expressions/expression-helpers.js +13 -23
  137. package/dist/cjs/expressions/expression-helpers.js.map +1 -1
  138. package/dist/cjs/extensions/array-extensions.js +591 -601
  139. package/dist/cjs/extensions/array-extensions.js.map +1 -1
  140. package/dist/cjs/extensions/boolean-extensions.d.ts +1 -1
  141. package/dist/cjs/extensions/boolean-extensions.js +38 -48
  142. package/dist/cjs/extensions/boolean-extensions.js.map +1 -1
  143. package/dist/cjs/extensions/date-extensions.js +507 -517
  144. package/dist/cjs/extensions/date-extensions.js.map +1 -1
  145. package/dist/cjs/extensions/expression-extension.d.ts.map +1 -1
  146. package/dist/cjs/extensions/expression-extension.js +455 -465
  147. package/dist/cjs/extensions/expression-extension.js.map +1 -1
  148. package/dist/cjs/extensions/expression-parser.d.ts.map +1 -1
  149. package/dist/cjs/extensions/expression-parser.js +82 -92
  150. package/dist/cjs/extensions/expression-parser.js.map +1 -1
  151. package/dist/cjs/extensions/extended-functions.d.ts +10 -18
  152. package/dist/cjs/extensions/extended-functions.d.ts.map +1 -1
  153. package/dist/cjs/extensions/extended-functions.js +80 -90
  154. package/dist/cjs/extensions/extended-functions.js.map +1 -1
  155. package/dist/cjs/extensions/extensions.js +2 -12
  156. package/dist/cjs/extensions/index.js +10 -20
  157. package/dist/cjs/extensions/index.js.map +1 -1
  158. package/dist/cjs/extensions/number-extensions.js +226 -236
  159. package/dist/cjs/extensions/number-extensions.js.map +1 -1
  160. package/dist/cjs/extensions/object-extensions.js +274 -284
  161. package/dist/cjs/extensions/object-extensions.js.map +1 -1
  162. package/dist/cjs/extensions/string-extensions.d.ts +1 -1
  163. package/dist/cjs/extensions/string-extensions.d.ts.map +1 -1
  164. package/dist/cjs/extensions/string-extensions.js +769 -779
  165. package/dist/cjs/extensions/string-extensions.js.map +1 -1
  166. package/dist/cjs/extensions/utils.d.ts.map +1 -1
  167. package/dist/cjs/extensions/utils.js +35 -45
  168. package/dist/cjs/extensions/utils.js.map +1 -1
  169. package/dist/cjs/from-ai-parse-utils.js +393 -403
  170. package/dist/cjs/from-ai-parse-utils.js.map +1 -1
  171. package/dist/cjs/global-state.js +12 -22
  172. package/dist/cjs/global-state.js.map +1 -1
  173. package/dist/cjs/graph/graph-utils.js +166 -176
  174. package/dist/cjs/graph/graph-utils.js.map +1 -1
  175. package/dist/cjs/highlighted-data.js +13 -23
  176. package/dist/cjs/highlighted-data.js.map +1 -1
  177. package/dist/cjs/index.js +105 -115
  178. package/dist/cjs/index.js.map +1 -1
  179. package/dist/cjs/interfaces.d.ts +112 -22
  180. package/dist/cjs/interfaces.d.ts.map +1 -1
  181. package/dist/cjs/interfaces.js +62 -72
  182. package/dist/cjs/interfaces.js.map +1 -1
  183. package/dist/cjs/jmespath-query.js +26 -36
  184. package/dist/cjs/jmespath-query.js.map +1 -1
  185. package/dist/cjs/logger-proxy.d.ts.map +1 -1
  186. package/dist/cjs/logger-proxy.js +15 -25
  187. package/dist/cjs/logger-proxy.js.map +1 -1
  188. package/dist/cjs/mcp-helpers.js +10 -20
  189. package/dist/cjs/mcp-helpers.js.map +1 -1
  190. package/dist/cjs/message-event-bus.d.ts +184 -165
  191. package/dist/cjs/message-event-bus.d.ts.map +1 -1
  192. package/dist/cjs/message-event-bus.js +207 -217
  193. package/dist/cjs/message-event-bus.js.map +1 -1
  194. package/dist/cjs/metadata-utils.js +35 -45
  195. package/dist/cjs/metadata-utils.js.map +1 -1
  196. package/dist/cjs/native-methods/array.methods.js +527 -537
  197. package/dist/cjs/native-methods/array.methods.js.map +1 -1
  198. package/dist/cjs/native-methods/boolean.methods.js +18 -28
  199. package/dist/cjs/native-methods/boolean.methods.js.map +1 -1
  200. package/dist/cjs/native-methods/index.js +16 -26
  201. package/dist/cjs/native-methods/index.js.map +1 -1
  202. package/dist/cjs/native-methods/number.methods.js +79 -89
  203. package/dist/cjs/native-methods/number.methods.js.map +1 -1
  204. package/dist/cjs/native-methods/object.methods.js +7 -17
  205. package/dist/cjs/native-methods/object.methods.js.map +1 -1
  206. package/dist/cjs/native-methods/string.methods.js +474 -484
  207. package/dist/cjs/native-methods/string.methods.js.map +1 -1
  208. package/dist/cjs/node-grouping-validation.d.ts +6 -0
  209. package/dist/cjs/node-grouping-validation.d.ts.map +1 -1
  210. package/dist/cjs/node-grouping-validation.js +165 -144
  211. package/dist/cjs/node-grouping-validation.js.map +1 -1
  212. package/dist/cjs/node-helpers.d.ts.map +1 -1
  213. package/dist/cjs/node-helpers.js +1486 -1493
  214. package/dist/cjs/node-helpers.js.map +1 -1
  215. package/dist/cjs/node-parameters/filter-parameter.d.ts.map +1 -1
  216. package/dist/cjs/node-parameters/filter-parameter.js +315 -325
  217. package/dist/cjs/node-parameters/filter-parameter.js.map +1 -1
  218. package/dist/cjs/node-parameters/node-parameter-value-type-guard.js +105 -115
  219. package/dist/cjs/node-parameters/node-parameter-value-type-guard.js.map +1 -1
  220. package/dist/cjs/node-parameters/parameter-type-validation.js +120 -130
  221. package/dist/cjs/node-parameters/parameter-type-validation.js.map +1 -1
  222. package/dist/cjs/node-parameters/path-utils.js +21 -31
  223. package/dist/cjs/node-parameters/path-utils.js.map +1 -1
  224. package/dist/cjs/node-parameters/rename-node-utils.js +22 -32
  225. package/dist/cjs/node-parameters/rename-node-utils.js.map +1 -1
  226. package/dist/cjs/node-reference-parser-utils.js +472 -482
  227. package/dist/cjs/node-reference-parser-utils.js.map +1 -1
  228. package/dist/cjs/node-validation.js +59 -69
  229. package/dist/cjs/node-validation.js.map +1 -1
  230. package/dist/cjs/observable-object.js +56 -66
  231. package/dist/cjs/observable-object.js.map +1 -1
  232. package/dist/cjs/redaction-channels.js +36 -46
  233. package/dist/cjs/redaction-channels.js.map +1 -1
  234. package/dist/cjs/run-execution-data/run-execution-data.js +15 -25
  235. package/dist/cjs/run-execution-data/run-execution-data.js.map +1 -1
  236. package/dist/cjs/run-execution-data/run-execution-data.v0.js +2 -12
  237. package/dist/cjs/run-execution-data/run-execution-data.v1.js +26 -36
  238. package/dist/cjs/run-execution-data/run-execution-data.v1.js.map +1 -1
  239. package/dist/cjs/run-execution-data-factory.js +113 -123
  240. package/dist/cjs/run-execution-data-factory.js.map +1 -1
  241. package/dist/cjs/schemas.d.ts +13 -13
  242. package/dist/cjs/schemas.d.ts.map +1 -1
  243. package/dist/cjs/schemas.js +351 -360
  244. package/dist/cjs/schemas.js.map +1 -1
  245. package/dist/cjs/sub-workflow-output.js +10 -20
  246. package/dist/cjs/sub-workflow-output.js.map +1 -1
  247. package/dist/cjs/telemetry-helpers.d.ts.map +1 -1
  248. package/dist/cjs/telemetry-helpers.js +716 -726
  249. package/dist/cjs/telemetry-helpers.js.map +1 -1
  250. package/dist/cjs/tool-helpers.js +18 -28
  251. package/dist/cjs/tool-helpers.js.map +1 -1
  252. package/dist/cjs/trigger-identity.js +41 -51
  253. package/dist/cjs/trigger-identity.js.map +1 -1
  254. package/dist/cjs/trimmed-task-data.js +21 -31
  255. package/dist/cjs/trimmed-task-data.js.map +1 -1
  256. package/dist/cjs/type-guards.d.ts +3 -3
  257. package/dist/cjs/type-guards.d.ts.map +1 -1
  258. package/dist/cjs/type-guards.js +74 -84
  259. package/dist/cjs/type-guards.js.map +1 -1
  260. package/dist/cjs/type-validation.d.ts.map +1 -1
  261. package/dist/cjs/type-validation.js +383 -393
  262. package/dist/cjs/type-validation.js.map +1 -1
  263. package/dist/cjs/utils.d.ts +2 -2
  264. package/dist/cjs/utils.d.ts.map +1 -1
  265. package/dist/cjs/utils.js +430 -440
  266. package/dist/cjs/utils.js.map +1 -1
  267. package/dist/cjs/versioned-node-type.d.ts.map +1 -1
  268. package/dist/cjs/versioned-node-type.js +20 -30
  269. package/dist/cjs/versioned-node-type.js.map +1 -1
  270. package/dist/cjs/workflow-checksum.js +67 -77
  271. package/dist/cjs/workflow-checksum.js.map +1 -1
  272. package/dist/cjs/workflow-data-proxy-env-provider.js +58 -68
  273. package/dist/cjs/workflow-data-proxy-env-provider.js.map +1 -1
  274. package/dist/cjs/workflow-data-proxy-helpers.js +8 -18
  275. package/dist/cjs/workflow-data-proxy-helpers.js.map +1 -1
  276. package/dist/cjs/workflow-data-proxy.d.ts.map +1 -1
  277. package/dist/cjs/workflow-data-proxy.js +1162 -1172
  278. package/dist/cjs/workflow-data-proxy.js.map +1 -1
  279. package/dist/cjs/workflow-diff.d.ts +2 -1
  280. package/dist/cjs/workflow-diff.d.ts.map +1 -1
  281. package/dist/cjs/workflow-diff.js +292 -300
  282. package/dist/cjs/workflow-diff.js.map +1 -1
  283. package/dist/cjs/workflow-environments-helper.js +23 -33
  284. package/dist/cjs/workflow-environments-helper.js.map +1 -1
  285. package/dist/cjs/workflow-expression.d.ts.map +1 -1
  286. package/dist/cjs/workflow-expression.js +97 -107
  287. package/dist/cjs/workflow-expression.js.map +1 -1
  288. package/dist/cjs/workflow-structure-validation.d.ts.map +1 -1
  289. package/dist/cjs/workflow-structure-validation.js +140 -150
  290. package/dist/cjs/workflow-structure-validation.js.map +1 -1
  291. package/dist/cjs/workflow-validation.js +40 -50
  292. package/dist/cjs/workflow-validation.js.map +1 -1
  293. package/dist/cjs/workflow.d.ts.map +1 -1
  294. package/dist/cjs/workflow.js +612 -622
  295. package/dist/cjs/workflow.js.map +1 -1
  296. package/dist/esm/common/get-child-nodes.js.map +1 -1
  297. package/dist/esm/common/get-connected-nodes.js.map +1 -1
  298. package/dist/esm/common/get-parent-nodes.js.map +1 -1
  299. package/dist/esm/common/resolve-variables.d.ts +8 -0
  300. package/dist/esm/common/resolve-variables.d.ts.map +1 -1
  301. package/dist/esm/common/resolve-variables.js +22 -0
  302. package/dist/esm/common/resolve-variables.js.map +1 -1
  303. package/dist/esm/constants.d.ts +3 -3
  304. package/dist/esm/constants.d.ts.map +1 -1
  305. package/dist/esm/cron.d.ts.map +1 -1
  306. package/dist/esm/errors/abstract/execution-base.error.d.ts.map +1 -1
  307. package/dist/esm/errors/abstract/execution-base.error.js.map +1 -1
  308. package/dist/esm/errors/abstract/node.error.d.ts.map +1 -1
  309. package/dist/esm/errors/abstract/node.error.js.map +1 -1
  310. package/dist/esm/errors/base/base.error.d.ts.map +1 -1
  311. package/dist/esm/errors/base/base.error.js.map +1 -1
  312. package/dist/esm/errors/base/operational.error.d.ts.map +1 -1
  313. package/dist/esm/errors/base/operational.error.js.map +1 -1
  314. package/dist/esm/errors/base/unexpected.error.d.ts.map +1 -1
  315. package/dist/esm/errors/base/unexpected.error.js.map +1 -1
  316. package/dist/esm/errors/base/user.error.d.ts.map +1 -1
  317. package/dist/esm/errors/base/user.error.js.map +1 -1
  318. package/dist/esm/errors/db-connection-timeout-error.d.ts.map +1 -1
  319. package/dist/esm/errors/execution-cancelled.error.d.ts.map +1 -1
  320. package/dist/esm/errors/expression-class-extension.error.d.ts.map +1 -1
  321. package/dist/esm/errors/expression-computed-destructuring.error.d.ts.map +1 -1
  322. package/dist/esm/errors/expression-destructuring.error.d.ts.map +1 -1
  323. package/dist/esm/errors/expression-reserved-variable.error.d.ts.map +1 -1
  324. package/dist/esm/errors/expression-with-statement.error.d.ts.map +1 -1
  325. package/dist/esm/errors/expression.error.d.ts.map +1 -1
  326. package/dist/esm/errors/node-api.error.d.ts.map +1 -1
  327. package/dist/esm/errors/node-api.error.js.map +1 -1
  328. package/dist/esm/errors/node-operation.error.d.ts.map +1 -1
  329. package/dist/esm/errors/node-operation.error.js.map +1 -1
  330. package/dist/esm/errors/node-ssl.error.d.ts.map +1 -1
  331. package/dist/esm/errors/subworkflow-operation.error.d.ts.map +1 -1
  332. package/dist/esm/errors/trigger-close.error.d.ts.map +1 -1
  333. package/dist/esm/errors/trigger-close.error.js.map +1 -1
  334. package/dist/esm/errors/webhook-taken.error.d.ts.map +1 -1
  335. package/dist/esm/errors/workflow-activation.error.d.ts.map +1 -1
  336. package/dist/esm/errors/workflow-activation.error.js.map +1 -1
  337. package/dist/esm/errors/workflow-operation.error.d.ts.map +1 -1
  338. package/dist/esm/execution-context-establishment-hooks.d.ts.map +1 -1
  339. package/dist/esm/execution-context.d.ts +14 -14
  340. package/dist/esm/execution-context.d.ts.map +1 -1
  341. package/dist/esm/execution-status.d.ts +2 -2
  342. package/dist/esm/execution-status.d.ts.map +1 -1
  343. package/dist/esm/expression-evaluator-proxy.d.ts.map +1 -1
  344. package/dist/esm/expression-sandboxing.d.ts.map +1 -1
  345. package/dist/esm/expression-sandboxing.js.map +1 -1
  346. package/dist/esm/expression.d.ts.map +1 -1
  347. package/dist/esm/expression.js.map +1 -1
  348. package/dist/esm/expressions/expression-helpers.d.ts.map +1 -1
  349. package/dist/esm/extensions/boolean-extensions.d.ts +1 -1
  350. package/dist/esm/extensions/expression-extension.d.ts.map +1 -1
  351. package/dist/esm/extensions/expression-parser.d.ts.map +1 -1
  352. package/dist/esm/extensions/extended-functions.d.ts +10 -18
  353. package/dist/esm/extensions/extended-functions.d.ts.map +1 -1
  354. package/dist/esm/extensions/number-extensions.js.map +1 -1
  355. package/dist/esm/extensions/string-extensions.d.ts +1 -1
  356. package/dist/esm/extensions/string-extensions.d.ts.map +1 -1
  357. package/dist/esm/extensions/string-extensions.js.map +1 -1
  358. package/dist/esm/extensions/utils.d.ts.map +1 -1
  359. package/dist/esm/from-ai-parse-utils.js.map +1 -1
  360. package/dist/esm/interfaces.d.ts +112 -22
  361. package/dist/esm/interfaces.d.ts.map +1 -1
  362. package/dist/esm/interfaces.js.map +1 -1
  363. package/dist/esm/logger-proxy.d.ts.map +1 -1
  364. package/dist/esm/message-event-bus.d.ts +184 -165
  365. package/dist/esm/message-event-bus.d.ts.map +1 -1
  366. package/dist/esm/message-event-bus.js +2 -2
  367. package/dist/esm/message-event-bus.js.map +1 -1
  368. package/dist/esm/node-grouping-validation.d.ts +6 -0
  369. package/dist/esm/node-grouping-validation.d.ts.map +1 -1
  370. package/dist/esm/node-grouping-validation.js +34 -5
  371. package/dist/esm/node-grouping-validation.js.map +1 -1
  372. package/dist/esm/node-helpers.d.ts.map +1 -1
  373. package/dist/esm/node-helpers.js +3 -0
  374. package/dist/esm/node-helpers.js.map +1 -1
  375. package/dist/esm/node-parameters/filter-parameter.d.ts.map +1 -1
  376. package/dist/esm/node-parameters/filter-parameter.js.map +1 -1
  377. package/dist/esm/node-reference-parser-utils.js.map +1 -1
  378. package/dist/esm/run-execution-data-factory.js.map +1 -1
  379. package/dist/esm/schemas.d.ts +13 -13
  380. package/dist/esm/schemas.d.ts.map +1 -1
  381. package/dist/esm/schemas.js +1 -0
  382. package/dist/esm/schemas.js.map +1 -1
  383. package/dist/esm/telemetry-helpers.d.ts.map +1 -1
  384. package/dist/esm/telemetry-helpers.js.map +1 -1
  385. package/dist/esm/type-guards.d.ts +3 -3
  386. package/dist/esm/type-guards.d.ts.map +1 -1
  387. package/dist/esm/type-validation.d.ts.map +1 -1
  388. package/dist/esm/type-validation.js.map +1 -1
  389. package/dist/esm/typecheck.tsbuildinfo +1 -1
  390. package/dist/esm/utils.d.ts +2 -2
  391. package/dist/esm/utils.d.ts.map +1 -1
  392. package/dist/esm/utils.js.map +1 -1
  393. package/dist/esm/versioned-node-type.d.ts.map +1 -1
  394. package/dist/esm/workflow-data-proxy.d.ts.map +1 -1
  395. package/dist/esm/workflow-data-proxy.js.map +1 -1
  396. package/dist/esm/workflow-diff.d.ts +2 -1
  397. package/dist/esm/workflow-diff.d.ts.map +1 -1
  398. package/dist/esm/workflow-diff.js +3 -1
  399. package/dist/esm/workflow-diff.js.map +1 -1
  400. package/dist/esm/workflow-expression.d.ts.map +1 -1
  401. package/dist/esm/workflow-expression.js.map +1 -1
  402. package/dist/esm/workflow-structure-validation.d.ts.map +1 -1
  403. package/dist/esm/workflow-structure-validation.js.map +1 -1
  404. package/dist/esm/workflow.d.ts.map +1 -1
  405. package/dist/esm/workflow.js.map +1 -1
  406. package/package.json +10 -9
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
2
3
  /* eslint-disable @typescript-eslint/no-this-alias */
3
4
  /* eslint-disable @typescript-eslint/no-unsafe-return */
@@ -34,1306 +35,1295 @@ var __importStar = (this && this.__importStar) || (function () {
34
35
  return result;
35
36
  };
36
37
  })();
37
- (function (factory) {
38
- if (typeof module === "object" && typeof module.exports === "object") {
39
- var v = factory(require, exports);
40
- if (v !== undefined) module.exports = v;
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.WorkflowDataProxy = void 0;
40
+ const jmespath = __importStar(require("jmespath"));
41
+ const luxon_1 = require("luxon");
42
+ const augment_object_1 = require("./augment-object");
43
+ const constants_1 = require("./constants");
44
+ const errors_1 = require("./errors");
45
+ const expression_error_1 = require("./errors/expression.error");
46
+ const expression_helpers_1 = require("./expressions/expression-helpers");
47
+ const global_state_1 = require("./global-state");
48
+ const interfaces_1 = require("./interfaces");
49
+ const NodeHelpers = __importStar(require("./node-helpers"));
50
+ const result_1 = require("@n8n/utils/result");
51
+ const type_guards_1 = require("./type-guards");
52
+ const utils_1 = require("./utils");
53
+ const workflow_data_proxy_env_provider_1 = require("./workflow-data-proxy-env-provider");
54
+ const workflow_data_proxy_helpers_1 = require("./workflow-data-proxy-helpers");
55
+ const isScriptingNode = (nodeName, workflow) => {
56
+ const node = workflow.getNode(nodeName);
57
+ return node && constants_1.SCRIPTING_NODE_TYPES.includes(node.type);
58
+ };
59
+ const PAIRED_ITEM_METHOD = {
60
+ PAIRED_ITEM: 'pairedItem',
61
+ ITEM_MATCHING: 'itemMatching',
62
+ ITEM: 'item',
63
+ $GET_PAIRED_ITEM: '$getPairedItem',
64
+ };
65
+ /**
66
+ * Whether the runtime can compile expressions. The expression engine compiles
67
+ * expressions via `new Function`, which throws when the process is started with
68
+ * `--disallow-code-generation-from-strings` — as the secure-mode task runner is.
69
+ * This is a process-wide invariant, so we probe once and cache the result.
70
+ */
71
+ let codeGenerationAllowed;
72
+ const isCodeGenerationAllowed = () => {
73
+ if (codeGenerationAllowed === undefined) {
74
+ try {
75
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
76
+ new Function('return 1');
77
+ codeGenerationAllowed = true;
78
+ }
79
+ catch {
80
+ codeGenerationAllowed = false;
81
+ }
41
82
  }
42
- else if (typeof define === "function" && define.amd) {
43
- define(["require", "exports", "jmespath", "luxon", "./augment-object", "./constants", "./errors", "./errors/expression.error", "./expressions/expression-helpers", "./global-state", "./interfaces", "./node-helpers", "@n8n/utils/result", "./type-guards", "./utils", "./workflow-data-proxy-env-provider", "./workflow-data-proxy-helpers"], factory);
83
+ return codeGenerationAllowed;
84
+ };
85
+ class WorkflowDataProxy {
86
+ workflow;
87
+ runIndex;
88
+ itemIndex;
89
+ activeNodeName;
90
+ siblingParameters;
91
+ mode;
92
+ additionalKeys;
93
+ executeData;
94
+ defaultReturnRunIndex;
95
+ selfData;
96
+ contextNodeName;
97
+ envProviderState;
98
+ runExecutionData;
99
+ connectionInputData;
100
+ timezone;
101
+ // TODO: Clean that up at some point and move all the options into an options object
102
+ constructor(workflow, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, siblingParameters, mode, additionalKeys, executeData, defaultReturnRunIndex = -1, selfData = {}, contextNodeName = activeNodeName, envProviderState) {
103
+ this.workflow = workflow;
104
+ this.runIndex = runIndex;
105
+ this.itemIndex = itemIndex;
106
+ this.activeNodeName = activeNodeName;
107
+ this.siblingParameters = siblingParameters;
108
+ this.mode = mode;
109
+ this.additionalKeys = additionalKeys;
110
+ this.executeData = executeData;
111
+ this.defaultReturnRunIndex = defaultReturnRunIndex;
112
+ this.selfData = selfData;
113
+ this.contextNodeName = contextNodeName;
114
+ this.envProviderState = envProviderState;
115
+ this.runExecutionData = isScriptingNode(this.contextNodeName, workflow)
116
+ ? runExecutionData !== null
117
+ ? (0, augment_object_1.augmentObject)(runExecutionData)
118
+ : null
119
+ : runExecutionData;
120
+ this.connectionInputData = isScriptingNode(this.contextNodeName, workflow)
121
+ ? (0, augment_object_1.augmentArray)(connectionInputData)
122
+ : connectionInputData;
123
+ this.timezone = workflow.settings?.timezone ?? (0, global_state_1.getGlobalState)().defaultTimezone;
124
+ luxon_1.Settings.defaultZone = this.timezone;
44
125
  }
45
- })(function (require, exports) {
46
- "use strict";
47
- Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.WorkflowDataProxy = void 0;
49
- const jmespath = __importStar(require("jmespath"));
50
- const luxon_1 = require("luxon");
51
- const augment_object_1 = require("./augment-object");
52
- const constants_1 = require("./constants");
53
- const errors_1 = require("./errors");
54
- const expression_error_1 = require("./errors/expression.error");
55
- const expression_helpers_1 = require("./expressions/expression-helpers");
56
- const global_state_1 = require("./global-state");
57
- const interfaces_1 = require("./interfaces");
58
- const NodeHelpers = __importStar(require("./node-helpers"));
59
- const result_1 = require("@n8n/utils/result");
60
- const type_guards_1 = require("./type-guards");
61
- const utils_1 = require("./utils");
62
- const workflow_data_proxy_env_provider_1 = require("./workflow-data-proxy-env-provider");
63
- const workflow_data_proxy_helpers_1 = require("./workflow-data-proxy-helpers");
64
- const isScriptingNode = (nodeName, workflow) => {
65
- const node = workflow.getNode(nodeName);
66
- return node && constants_1.SCRIPTING_NODE_TYPES.includes(node.type);
67
- };
68
- const PAIRED_ITEM_METHOD = {
69
- PAIRED_ITEM: 'pairedItem',
70
- ITEM_MATCHING: 'itemMatching',
71
- ITEM: 'item',
72
- $GET_PAIRED_ITEM: '$getPairedItem',
73
- };
74
126
  /**
75
- * Whether the runtime can compile expressions. The expression engine compiles
76
- * expressions via `new Function`, which throws when the process is started with
77
- * `--disallow-code-generation-from-strings` — as the secure-mode task runner is.
78
- * This is a process-wide invariant, so we probe once and cache the result.
127
+ * Returns execution data, conditionally extracting only 'json' from the item based on workflow 'binaryMode' setting.
128
+ * When binary mode is 'combined', this method returns only the 'json' from the item unless 'fullItem' is true.
129
+ *
130
+ * @private
131
+ * @param {INodeExecutionData | INodeExecutionData[]} data - The execution data to process
132
+ * @param {boolean} fullItem - If true, always returns the complete item data
133
+ * @returns The full execution data or only the json property, depending on workflow 'binaryMode' setting
79
134
  */
80
- let codeGenerationAllowed;
81
- const isCodeGenerationAllowed = () => {
82
- if (codeGenerationAllowed === undefined) {
83
- try {
84
- // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
85
- new Function('return 1');
86
- codeGenerationAllowed = true;
87
- }
88
- catch {
89
- codeGenerationAllowed = false;
90
- }
91
- }
92
- return codeGenerationAllowed;
93
- };
94
- class WorkflowDataProxy {
95
- workflow;
96
- runIndex;
97
- itemIndex;
98
- activeNodeName;
99
- siblingParameters;
100
- mode;
101
- additionalKeys;
102
- executeData;
103
- defaultReturnRunIndex;
104
- selfData;
105
- contextNodeName;
106
- envProviderState;
107
- runExecutionData;
108
- connectionInputData;
109
- timezone;
110
- // TODO: Clean that up at some point and move all the options into an options object
111
- constructor(workflow, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, siblingParameters, mode, additionalKeys, executeData, defaultReturnRunIndex = -1, selfData = {}, contextNodeName = activeNodeName, envProviderState) {
112
- this.workflow = workflow;
113
- this.runIndex = runIndex;
114
- this.itemIndex = itemIndex;
115
- this.activeNodeName = activeNodeName;
116
- this.siblingParameters = siblingParameters;
117
- this.mode = mode;
118
- this.additionalKeys = additionalKeys;
119
- this.executeData = executeData;
120
- this.defaultReturnRunIndex = defaultReturnRunIndex;
121
- this.selfData = selfData;
122
- this.contextNodeName = contextNodeName;
123
- this.envProviderState = envProviderState;
124
- this.runExecutionData = isScriptingNode(this.contextNodeName, workflow)
125
- ? runExecutionData !== null
126
- ? (0, augment_object_1.augmentObject)(runExecutionData)
127
- : null
128
- : runExecutionData;
129
- this.connectionInputData = isScriptingNode(this.contextNodeName, workflow)
130
- ? (0, augment_object_1.augmentArray)(connectionInputData)
131
- : connectionInputData;
132
- this.timezone = workflow.settings?.timezone ?? (0, global_state_1.getGlobalState)().defaultTimezone;
133
- luxon_1.Settings.defaultZone = this.timezone;
135
+ returnExecutionData(data, fullItem = false) {
136
+ if (fullItem)
137
+ return data;
138
+ if (this.workflow.settings?.binaryMode !== constants_1.BINARY_MODE_COMBINED)
139
+ return data;
140
+ if (Array.isArray(data)) {
141
+ return data.map((i) => i.json);
134
142
  }
135
- /**
136
- * Returns execution data, conditionally extracting only 'json' from the item based on workflow 'binaryMode' setting.
137
- * When binary mode is 'combined', this method returns only the 'json' from the item unless 'fullItem' is true.
138
- *
139
- * @private
140
- * @param {INodeExecutionData | INodeExecutionData[]} data - The execution data to process
141
- * @param {boolean} fullItem - If true, always returns the complete item data
142
- * @returns The full execution data or only the json property, depending on workflow 'binaryMode' setting
143
- */
144
- returnExecutionData(data, fullItem = false) {
145
- if (fullItem)
146
- return data;
147
- if (this.workflow.settings?.binaryMode !== constants_1.BINARY_MODE_COMBINED)
148
- return data;
149
- if (Array.isArray(data)) {
150
- return data.map((i) => i.json);
151
- }
152
- return data.json;
143
+ return data.json;
144
+ }
145
+ /**
146
+ * Returns a proxy which allows to query context data of a given node
147
+ *
148
+ * @private
149
+ * @param {string} nodeName The name of the node to get the context from
150
+ */
151
+ nodeContextGetter(nodeName) {
152
+ const that = this;
153
+ const node = this.workflow.nodes[nodeName];
154
+ if (!that.runExecutionData?.executionData && that.connectionInputData.length > 0) {
155
+ return {}; // incoming connection has pinned data, so stub context object
153
156
  }
154
- /**
155
- * Returns a proxy which allows to query context data of a given node
156
- *
157
- * @private
158
- * @param {string} nodeName The name of the node to get the context from
159
- */
160
- nodeContextGetter(nodeName) {
161
- const that = this;
162
- const node = this.workflow.nodes[nodeName];
163
- if (!that.runExecutionData?.executionData && that.connectionInputData.length > 0) {
164
- return {}; // incoming connection has pinned data, so stub context object
165
- }
166
- if (!that.runExecutionData?.executionData && !that.runExecutionData?.resultData) {
167
- throw new expression_error_1.ExpressionError("The workflow hasn't been executed yet, so you can't reference any context data", {
168
- runIndex: that.runIndex,
169
- itemIndex: that.itemIndex,
170
- type: 'no_execution_data',
171
- });
172
- }
173
- return new Proxy({}, {
174
- has: () => true,
175
- ownKeys(target) {
176
- if (Reflect.ownKeys(target).length === 0) {
177
- // Target object did not get set yet
178
- Object.assign(target, NodeHelpers.getContext(that.runExecutionData, 'node', node));
179
- }
180
- return Reflect.ownKeys(target);
181
- },
182
- getOwnPropertyDescriptor() {
183
- return {
184
- enumerable: true,
185
- configurable: true,
186
- };
187
- },
188
- get(_, name) {
189
- if (name === 'isProxy')
190
- return true;
191
- name = name.toString();
192
- const contextData = NodeHelpers.getContext(that.runExecutionData, 'node', node);
193
- return contextData[name];
194
- },
157
+ if (!that.runExecutionData?.executionData && !that.runExecutionData?.resultData) {
158
+ throw new expression_error_1.ExpressionError("The workflow hasn't been executed yet, so you can't reference any context data", {
159
+ runIndex: that.runIndex,
160
+ itemIndex: that.itemIndex,
161
+ type: 'no_execution_data',
195
162
  });
196
163
  }
197
- selfGetter() {
198
- const that = this;
199
- return new Proxy({}, {
200
- has: () => true,
201
- ownKeys(target) {
202
- return Reflect.ownKeys(target);
203
- },
204
- get(_, name) {
205
- if (name === 'isProxy')
206
- return true;
207
- name = name.toString();
208
- const value = that.selfData[name];
209
- // A credential field saved in expression mode keeps n8n's leading "="
210
- // marker in its stored value. Returning it verbatim leaks the marker
211
- // (or an unevaluated `{{ }}` expression) into the consuming template —
212
- // e.g. a `$self` reference embedded mid-URL in an OAuth2
213
- // authUrl/accessTokenUrl. Resolve it here so callers receive the
214
- // evaluated value.
215
- if ((0, expression_helpers_1.isExpression)(value)) {
216
- return that.workflow.expression.getParameterValue(value, that.runExecutionData, that.runIndex, that.itemIndex, that.activeNodeName, that.connectionInputData, that.mode, that.additionalKeys, that.executeData, false, {}, that.contextNodeName);
217
- }
218
- return value;
219
- },
220
- });
221
- }
222
- buildAgentToolInfo(node) {
223
- const nodeType = this.workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
224
- if (!nodeType) {
164
+ return new Proxy({}, {
165
+ has: () => true,
166
+ ownKeys(target) {
167
+ if (Reflect.ownKeys(target).length === 0) {
168
+ // Target object did not get set yet
169
+ Object.assign(target, NodeHelpers.getContext(that.runExecutionData, 'node', node));
170
+ }
171
+ return Reflect.ownKeys(target);
172
+ },
173
+ getOwnPropertyDescriptor() {
225
174
  return {
226
- name: node.name,
227
- type: node.type,
175
+ enumerable: true,
176
+ configurable: true,
228
177
  };
229
- }
230
- const type = nodeType.description.displayName;
231
- const params = NodeHelpers.getNodeParameters(nodeType.description.properties, node.parameters, true, false, node, nodeType.description);
232
- const resourceKey = params?.resource;
233
- const operationKey = params?.operation;
234
- const resource = nodeType.description.properties
235
- .find((nodeProperties) => nodeProperties.name === 'resource')
236
- ?.options?.find((option) => 'value' in option && option.value === resourceKey)?.name ??
237
- null;
238
- const operation = nodeType.description.properties
239
- .find((nodeProperty) => nodeProperty.name === 'operation' &&
240
- nodeProperty.displayOptions?.show?.resource?.some((y) => y === resourceKey))
241
- ?.options?.find((y) => 'value' in y && y.value === operationKey)?.name ?? null;
242
- const hasCredentials = !(0, utils_1.isObjectEmpty)(node.credentials ?? {});
243
- const hasValidCalendar = nodeType.description.name.includes('googleCalendar')
244
- ? (0, type_guards_1.isResourceLocatorValue)(node.parameters.calendar) && node.parameters.calendar.value !== ''
245
- : undefined;
246
- const aiDefinedFields = Object.entries(node.parameters)
247
- .map(([key, value]) => [key, (0, type_guards_1.isResourceLocatorValue)(value) ? value.value : value])
248
- .filter(([_, value]) => value?.toString().toLowerCase().includes('$fromai'))
249
- .map(([key]) => nodeType.description.properties.find((property) => property.name === key)?.displayName);
178
+ },
179
+ get(_, name) {
180
+ if (name === 'isProxy')
181
+ return true;
182
+ name = name.toString();
183
+ const contextData = NodeHelpers.getContext(that.runExecutionData, 'node', node);
184
+ return contextData[name];
185
+ },
186
+ });
187
+ }
188
+ selfGetter() {
189
+ const that = this;
190
+ return new Proxy({}, {
191
+ has: () => true,
192
+ ownKeys(target) {
193
+ return Reflect.ownKeys(target);
194
+ },
195
+ get(_, name) {
196
+ if (name === 'isProxy')
197
+ return true;
198
+ name = name.toString();
199
+ const value = that.selfData[name];
200
+ // A credential field saved in expression mode keeps n8n's leading "="
201
+ // marker in its stored value. Returning it verbatim leaks the marker
202
+ // (or an unevaluated `{{ }}` expression) into the consuming template —
203
+ // e.g. a `$self` reference embedded mid-URL in an OAuth2
204
+ // authUrl/accessTokenUrl. Resolve it here so callers receive the
205
+ // evaluated value.
206
+ if ((0, expression_helpers_1.isExpression)(value)) {
207
+ return that.workflow.expression.getParameterValue(value, that.runExecutionData, that.runIndex, that.itemIndex, that.activeNodeName, that.connectionInputData, that.mode, that.additionalKeys, that.executeData, false, {}, that.contextNodeName);
208
+ }
209
+ return value;
210
+ },
211
+ });
212
+ }
213
+ buildAgentToolInfo(node) {
214
+ const nodeType = this.workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
215
+ if (!nodeType) {
250
216
  return {
251
217
  name: node.name,
252
- type,
253
- resource,
254
- operation,
255
- hasCredentials,
256
- hasValidCalendar,
257
- aiDefinedFields,
258
- };
259
- }
260
- agentInfo() {
261
- const agentNode = this.workflow.getNode(this.activeNodeName);
262
- if (!agentNode || agentNode.type !== constants_1.AGENT_LANGCHAIN_NODE_TYPE)
263
- return undefined;
264
- const connectedTools = this.workflow
265
- .getParentNodes(this.activeNodeName, interfaces_1.NodeConnectionTypes.AiTool)
266
- .map((nodeName) => this.workflow.getNode(nodeName))
267
- .filter((node) => node);
268
- const memoryConnectedToAgent = this.workflow.getParentNodes(this.activeNodeName, interfaces_1.NodeConnectionTypes.AiMemory).length > 0;
269
- const allTools = this.workflow.queryNodes((nodeType) => {
270
- return nodeType.description.name.toLowerCase().includes('tool');
271
- });
272
- const unconnectedTools = allTools
273
- .filter((node) => this.workflow.getChildNodes(node.name, interfaces_1.NodeConnectionTypes.AiTool, 1).length === 0)
274
- .filter((node) => !connectedTools.includes(node));
275
- return {
276
- memoryConnectedToAgent,
277
- tools: [
278
- ...connectedTools.map((node) => ({ connected: true, ...this.buildAgentToolInfo(node) })),
279
- ...unconnectedTools.map((node) => ({ connected: false, ...this.buildAgentToolInfo(node) })),
280
- ],
218
+ type: node.type,
281
219
  };
282
220
  }
283
- /**
284
- * Returns a proxy which allows to query parameter data of a given node
285
- *
286
- * @private
287
- * @param {string} nodeName The name of the node to query data from
288
- * @param {boolean} [resolveValue=true] If the expression value should get resolved
289
- */
290
- nodeParameterGetter(nodeName, resolveValue = true) {
291
- const that = this;
292
- const node = this.workflow.nodes[nodeName];
293
- // `node` is `undefined` only in expressions in credentials
294
- return new Proxy(node?.parameters ?? {}, {
295
- has: () => true,
296
- ownKeys(target) {
297
- return Reflect.ownKeys(target);
298
- },
299
- getOwnPropertyDescriptor() {
300
- return {
301
- enumerable: true,
302
- configurable: true,
303
- };
304
- },
305
- get(target, name) {
306
- if (name === 'isProxy')
307
- return true;
308
- if (name === 'toJSON')
309
- return () => (0, utils_1.deepCopy)(target);
310
- name = name.toString();
311
- let returnValue;
312
- if (name[0] === '&') {
313
- const key = name.slice(1);
314
- if (!that.siblingParameters.hasOwnProperty(key)) {
315
- throw new errors_1.UnexpectedError('Could not find sibling parameter on node', {
316
- extra: { nodeName, parameter: key },
317
- });
318
- }
319
- returnValue = that.siblingParameters[key];
320
- }
321
- else {
322
- if (!node.parameters.hasOwnProperty(name)) {
323
- // Parameter does not exist on node
324
- return undefined;
325
- }
326
- returnValue = node.parameters[name];
221
+ const type = nodeType.description.displayName;
222
+ const params = NodeHelpers.getNodeParameters(nodeType.description.properties, node.parameters, true, false, node, nodeType.description);
223
+ const resourceKey = params?.resource;
224
+ const operationKey = params?.operation;
225
+ const resource = nodeType.description.properties
226
+ .find((nodeProperties) => nodeProperties.name === 'resource')
227
+ ?.options?.find((option) => 'value' in option && option.value === resourceKey)?.name ??
228
+ null;
229
+ const operation = nodeType.description.properties
230
+ .find((nodeProperty) => nodeProperty.name === 'operation' &&
231
+ nodeProperty.displayOptions?.show?.resource?.some((y) => y === resourceKey))
232
+ ?.options?.find((y) => 'value' in y && y.value === operationKey)?.name ?? null;
233
+ const hasCredentials = !(0, utils_1.isObjectEmpty)(node.credentials ?? {});
234
+ const hasValidCalendar = nodeType.description.name.includes('googleCalendar')
235
+ ? (0, type_guards_1.isResourceLocatorValue)(node.parameters.calendar) && node.parameters.calendar.value !== ''
236
+ : undefined;
237
+ const aiDefinedFields = Object.entries(node.parameters)
238
+ .map(([key, value]) => [key, (0, type_guards_1.isResourceLocatorValue)(value) ? value.value : value])
239
+ .filter(([_, value]) => value?.toString().toLowerCase().includes('$fromai'))
240
+ .map(([key]) => nodeType.description.properties.find((property) => property.name === key)?.displayName);
241
+ return {
242
+ name: node.name,
243
+ type,
244
+ resource,
245
+ operation,
246
+ hasCredentials,
247
+ hasValidCalendar,
248
+ aiDefinedFields,
249
+ };
250
+ }
251
+ agentInfo() {
252
+ const agentNode = this.workflow.getNode(this.activeNodeName);
253
+ if (!agentNode || agentNode.type !== constants_1.AGENT_LANGCHAIN_NODE_TYPE)
254
+ return undefined;
255
+ const connectedTools = this.workflow
256
+ .getParentNodes(this.activeNodeName, interfaces_1.NodeConnectionTypes.AiTool)
257
+ .map((nodeName) => this.workflow.getNode(nodeName))
258
+ .filter((node) => node);
259
+ const memoryConnectedToAgent = this.workflow.getParentNodes(this.activeNodeName, interfaces_1.NodeConnectionTypes.AiMemory).length > 0;
260
+ const allTools = this.workflow.queryNodes((nodeType) => {
261
+ return nodeType.description.name.toLowerCase().includes('tool');
262
+ });
263
+ const unconnectedTools = allTools
264
+ .filter((node) => this.workflow.getChildNodes(node.name, interfaces_1.NodeConnectionTypes.AiTool, 1).length === 0)
265
+ .filter((node) => !connectedTools.includes(node));
266
+ return {
267
+ memoryConnectedToAgent,
268
+ tools: [
269
+ ...connectedTools.map((node) => ({ connected: true, ...this.buildAgentToolInfo(node) })),
270
+ ...unconnectedTools.map((node) => ({ connected: false, ...this.buildAgentToolInfo(node) })),
271
+ ],
272
+ };
273
+ }
274
+ /**
275
+ * Returns a proxy which allows to query parameter data of a given node
276
+ *
277
+ * @private
278
+ * @param {string} nodeName The name of the node to query data from
279
+ * @param {boolean} [resolveValue=true] If the expression value should get resolved
280
+ */
281
+ nodeParameterGetter(nodeName, resolveValue = true) {
282
+ const that = this;
283
+ const node = this.workflow.nodes[nodeName];
284
+ // `node` is `undefined` only in expressions in credentials
285
+ return new Proxy(node?.parameters ?? {}, {
286
+ has: () => true,
287
+ ownKeys(target) {
288
+ return Reflect.ownKeys(target);
289
+ },
290
+ getOwnPropertyDescriptor() {
291
+ return {
292
+ enumerable: true,
293
+ configurable: true,
294
+ };
295
+ },
296
+ get(target, name) {
297
+ if (name === 'isProxy')
298
+ return true;
299
+ if (name === 'toJSON')
300
+ return () => (0, utils_1.deepCopy)(target);
301
+ name = name.toString();
302
+ let returnValue;
303
+ if (name[0] === '&') {
304
+ const key = name.slice(1);
305
+ if (!that.siblingParameters.hasOwnProperty(key)) {
306
+ throw new errors_1.UnexpectedError('Could not find sibling parameter on node', {
307
+ extra: { nodeName, parameter: key },
308
+ });
327
309
  }
328
- // Avoid recursion
329
- if (returnValue === `={{ $parameter.${name} }}`)
310
+ returnValue = that.siblingParameters[key];
311
+ }
312
+ else {
313
+ if (!node.parameters.hasOwnProperty(name)) {
314
+ // Parameter does not exist on node
330
315
  return undefined;
331
- if ((0, type_guards_1.isResourceLocatorValue)(returnValue)) {
332
- if (returnValue.__regex && typeof returnValue.value === 'string') {
333
- const expr = new RegExp(returnValue.__regex);
334
- const extracted = expr.exec(returnValue.value);
335
- if (extracted && extracted.length >= 2) {
336
- returnValue = extracted[1];
337
- }
338
- else {
339
- return returnValue.value;
340
- }
316
+ }
317
+ returnValue = node.parameters[name];
318
+ }
319
+ // Avoid recursion
320
+ if (returnValue === `={{ $parameter.${name} }}`)
321
+ return undefined;
322
+ if ((0, type_guards_1.isResourceLocatorValue)(returnValue)) {
323
+ if (returnValue.__regex && typeof returnValue.value === 'string') {
324
+ const expr = new RegExp(returnValue.__regex);
325
+ const extracted = expr.exec(returnValue.value);
326
+ if (extracted && extracted.length >= 2) {
327
+ returnValue = extracted[1];
341
328
  }
342
329
  else {
343
- returnValue = returnValue.value;
330
+ return returnValue.value;
344
331
  }
345
332
  }
346
- if (resolveValue && typeof returnValue === 'string' && returnValue.charAt(0) === '=') {
347
- // The found value is an expression so resolve it
348
- return that.workflow.expression.getParameterValue(returnValue, that.runExecutionData, that.runIndex, that.itemIndex, that.activeNodeName, that.connectionInputData, that.mode, that.additionalKeys, that.executeData, false, {}, that.contextNodeName);
333
+ else {
334
+ returnValue = returnValue.value;
349
335
  }
350
- return returnValue;
351
- },
352
- });
353
- }
354
- getNodeExecutionOrPinnedData({ nodeName, branchIndex, runIndex, shortSyntax = false, }) {
355
- try {
356
- return this.getNodeExecutionData(nodeName, shortSyntax, branchIndex, runIndex);
357
- }
358
- catch (e) {
359
- const pinData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(this.workflow, nodeName, this.mode);
360
- if (pinData) {
361
- return pinData;
362
336
  }
363
- throw e;
337
+ if (resolveValue && typeof returnValue === 'string' && returnValue.charAt(0) === '=') {
338
+ // The found value is an expression so resolve it
339
+ return that.workflow.expression.getParameterValue(returnValue, that.runExecutionData, that.runIndex, that.itemIndex, that.activeNodeName, that.connectionInputData, that.mode, that.additionalKeys, that.executeData, false, {}, that.contextNodeName);
340
+ }
341
+ return returnValue;
342
+ },
343
+ });
344
+ }
345
+ getNodeExecutionOrPinnedData({ nodeName, branchIndex, runIndex, shortSyntax = false, }) {
346
+ try {
347
+ return this.getNodeExecutionData(nodeName, shortSyntax, branchIndex, runIndex);
348
+ }
349
+ catch (e) {
350
+ const pinData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(this.workflow, nodeName, this.mode);
351
+ if (pinData) {
352
+ return pinData;
364
353
  }
354
+ throw e;
365
355
  }
366
- /**
367
- * Returns the node ExecutionData
368
- *
369
- * @private
370
- * @param {string} nodeName The name of the node query data from
371
- * @param {boolean} [shortSyntax=false] If short syntax got used
372
- * @param {number} [outputIndex] The index of the output, if not given the first one gets used
373
- * @param {number} [runIndex] The index of the run, if not given the current one does get used
374
- */
375
- getNodeExecutionData(nodeName, shortSyntax = false, outputIndex, runIndex) {
376
- const that = this;
377
- let executionData;
378
- if (!shortSyntax) {
379
- // Long syntax got used to return data from node in path
380
- if (that.runExecutionData === null) {
381
- throw new expression_error_1.ExpressionError("The workflow hasn't been executed yet, so you can't reference any output data", {
382
- runIndex: that.runIndex,
383
- itemIndex: that.itemIndex,
384
- });
385
- }
386
- if (!that.workflow.getNode(nodeName)) {
387
- throw new expression_error_1.ExpressionError("Referenced node doesn't exist", {
356
+ }
357
+ /**
358
+ * Returns the node ExecutionData
359
+ *
360
+ * @private
361
+ * @param {string} nodeName The name of the node query data from
362
+ * @param {boolean} [shortSyntax=false] If short syntax got used
363
+ * @param {number} [outputIndex] The index of the output, if not given the first one gets used
364
+ * @param {number} [runIndex] The index of the run, if not given the current one does get used
365
+ */
366
+ getNodeExecutionData(nodeName, shortSyntax = false, outputIndex, runIndex) {
367
+ const that = this;
368
+ let executionData;
369
+ if (!shortSyntax) {
370
+ // Long syntax got used to return data from node in path
371
+ if (that.runExecutionData === null) {
372
+ throw new expression_error_1.ExpressionError("The workflow hasn't been executed yet, so you can't reference any output data", {
373
+ runIndex: that.runIndex,
374
+ itemIndex: that.itemIndex,
375
+ });
376
+ }
377
+ if (!that.workflow.getNode(nodeName)) {
378
+ throw new expression_error_1.ExpressionError("Referenced node doesn't exist", {
379
+ runIndex: that.runIndex,
380
+ itemIndex: that.itemIndex,
381
+ nodeCause: nodeName,
382
+ descriptionKey: 'nodeNotFound',
383
+ });
384
+ }
385
+ if (!that.runExecutionData.resultData.runData.hasOwnProperty(nodeName) &&
386
+ !(0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode)) {
387
+ throw new expression_error_1.ExpressionError(`Node '${nodeName}' hasn't been executed`, {
388
+ messageTemplate: 'An expression references this node, but the node is unexecuted. Consider re-wiring your nodes or checking for execution first, i.e. {{ $if( $("{{nodeName}}").isExecuted, <action_if_executed>, "") }}',
389
+ functionality: 'pairedItem',
390
+ descriptionKey: isScriptingNode(nodeName, that.workflow)
391
+ ? 'pairedItemNoConnectionCodeNode'
392
+ : 'pairedItemNoConnection',
393
+ type: 'no_execution_data',
394
+ nodeCause: nodeName,
395
+ runIndex: that.runIndex,
396
+ itemIndex: that.itemIndex,
397
+ });
398
+ }
399
+ runIndex = runIndex === undefined ? that.defaultReturnRunIndex : runIndex;
400
+ runIndex =
401
+ runIndex === -1 ? that.runExecutionData.resultData.runData[nodeName].length - 1 : runIndex;
402
+ if (that.runExecutionData.resultData.runData[nodeName].length <= runIndex) {
403
+ throw new expression_error_1.ExpressionError(`Run ${runIndex} of node "${nodeName}" not found`, {
404
+ runIndex: that.runIndex,
405
+ itemIndex: that.itemIndex,
406
+ });
407
+ }
408
+ const taskData = that.runExecutionData.resultData.runData[nodeName][runIndex].data;
409
+ if (!taskData.main?.length || taskData.main[0] === null) {
410
+ // throw new ApplicationError('No data found for item-index', { extra: { itemIndex } });
411
+ throw new expression_error_1.ExpressionError('No data found from `main` input', {
412
+ runIndex: that.runIndex,
413
+ itemIndex: that.itemIndex,
414
+ });
415
+ }
416
+ // Check from which output to read the data.
417
+ // Depends on how the nodes are connected.
418
+ // (example "IF" node. If node is connected to "true" or to "false" output)
419
+ if (outputIndex === undefined) {
420
+ const nodeConnection = that.workflow.getNodeConnectionIndexes(that.contextNodeName, nodeName, interfaces_1.NodeConnectionTypes.Main);
421
+ if (nodeConnection === undefined) {
422
+ throw new expression_error_1.ExpressionError(`connect "${that.contextNodeName}" to "${nodeName}"`, {
388
423
  runIndex: that.runIndex,
389
424
  itemIndex: that.itemIndex,
390
- nodeCause: nodeName,
391
- descriptionKey: 'nodeNotFound',
392
425
  });
393
426
  }
394
- if (!that.runExecutionData.resultData.runData.hasOwnProperty(nodeName) &&
395
- !(0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode)) {
396
- throw new expression_error_1.ExpressionError(`Node '${nodeName}' hasn't been executed`, {
397
- messageTemplate: 'An expression references this node, but the node is unexecuted. Consider re-wiring your nodes or checking for execution first, i.e. {{ $if( $("{{nodeName}}").isExecuted, <action_if_executed>, "") }}',
427
+ outputIndex = nodeConnection.sourceIndex;
428
+ }
429
+ if (outputIndex === undefined) {
430
+ outputIndex = 0;
431
+ }
432
+ if (taskData.main.length <= outputIndex) {
433
+ throw new expression_error_1.ExpressionError(`Node "${nodeName}" has no branch with index ${outputIndex}.`, {
434
+ runIndex: that.runIndex,
435
+ itemIndex: that.itemIndex,
436
+ });
437
+ }
438
+ executionData = taskData.main[outputIndex];
439
+ }
440
+ else {
441
+ // Short syntax got used to return data from active node
442
+ executionData = that.connectionInputData;
443
+ }
444
+ return executionData;
445
+ }
446
+ /**
447
+ * Returns a proxy which allows to query data of a given node
448
+ *
449
+ * @private
450
+ * @param {string} nodeName The name of the node query data from
451
+ * @param {boolean} [shortSyntax=false] If short syntax got used
452
+ * @param {boolean} [throwOnMissingExecutionData=true] If an error should get thrown if no execution data is available
453
+ */
454
+ nodeDataGetter(nodeName, shortSyntax = false, throwOnMissingExecutionData = true) {
455
+ const that = this;
456
+ const node = this.workflow.nodes[nodeName];
457
+ return new Proxy({ binary: undefined, data: undefined, json: undefined }, {
458
+ has: () => true,
459
+ get(target, name, receiver) {
460
+ if (name === 'isProxy')
461
+ return true;
462
+ name = name.toString();
463
+ if (!node) {
464
+ throw new expression_error_1.ExpressionError('Referenced node does not exist', {
465
+ messageTemplate: 'Make sure to double-check the node name for typos',
398
466
  functionality: 'pairedItem',
399
467
  descriptionKey: isScriptingNode(nodeName, that.workflow)
400
468
  ? 'pairedItemNoConnectionCodeNode'
401
469
  : 'pairedItemNoConnection',
402
- type: 'no_execution_data',
470
+ type: 'paired_item_no_connection',
403
471
  nodeCause: nodeName,
404
472
  runIndex: that.runIndex,
405
473
  itemIndex: that.itemIndex,
406
474
  });
407
475
  }
408
- runIndex = runIndex === undefined ? that.defaultReturnRunIndex : runIndex;
409
- runIndex =
410
- runIndex === -1 ? that.runExecutionData.resultData.runData[nodeName].length - 1 : runIndex;
411
- if (that.runExecutionData.resultData.runData[nodeName].length <= runIndex) {
412
- throw new expression_error_1.ExpressionError(`Run ${runIndex} of node "${nodeName}" not found`, {
413
- runIndex: that.runIndex,
414
- itemIndex: that.itemIndex,
415
- });
416
- }
417
- const taskData = that.runExecutionData.resultData.runData[nodeName][runIndex].data;
418
- if (!taskData.main?.length || taskData.main[0] === null) {
419
- // throw new ApplicationError('No data found for item-index', { extra: { itemIndex } });
420
- throw new expression_error_1.ExpressionError('No data found from `main` input', {
421
- runIndex: that.runIndex,
422
- itemIndex: that.itemIndex,
476
+ if (['binary', 'data', 'json'].includes(name)) {
477
+ const executionData = that.getNodeExecutionOrPinnedData({
478
+ nodeName,
479
+ shortSyntax,
423
480
  });
424
- }
425
- // Check from which output to read the data.
426
- // Depends on how the nodes are connected.
427
- // (example "IF" node. If node is connected to "true" or to "false" output)
428
- if (outputIndex === undefined) {
429
- const nodeConnection = that.workflow.getNodeConnectionIndexes(that.contextNodeName, nodeName, interfaces_1.NodeConnectionTypes.Main);
430
- if (nodeConnection === undefined) {
431
- throw new expression_error_1.ExpressionError(`connect "${that.contextNodeName}" to "${nodeName}"`, {
432
- runIndex: that.runIndex,
433
- itemIndex: that.itemIndex,
434
- });
481
+ if (executionData.length === 0 && !throwOnMissingExecutionData) {
482
+ return undefined;
435
483
  }
436
- outputIndex = nodeConnection.sourceIndex;
437
- }
438
- if (outputIndex === undefined) {
439
- outputIndex = 0;
440
- }
441
- if (taskData.main.length <= outputIndex) {
442
- throw new expression_error_1.ExpressionError(`Node "${nodeName}" has no branch with index ${outputIndex}.`, {
443
- runIndex: that.runIndex,
444
- itemIndex: that.itemIndex,
445
- });
446
- }
447
- executionData = taskData.main[outputIndex];
448
- }
449
- else {
450
- // Short syntax got used to return data from active node
451
- executionData = that.connectionInputData;
452
- }
453
- return executionData;
454
- }
455
- /**
456
- * Returns a proxy which allows to query data of a given node
457
- *
458
- * @private
459
- * @param {string} nodeName The name of the node query data from
460
- * @param {boolean} [shortSyntax=false] If short syntax got used
461
- * @param {boolean} [throwOnMissingExecutionData=true] If an error should get thrown if no execution data is available
462
- */
463
- nodeDataGetter(nodeName, shortSyntax = false, throwOnMissingExecutionData = true) {
464
- const that = this;
465
- const node = this.workflow.nodes[nodeName];
466
- return new Proxy({ binary: undefined, data: undefined, json: undefined }, {
467
- has: () => true,
468
- get(target, name, receiver) {
469
- if (name === 'isProxy')
470
- return true;
471
- name = name.toString();
472
- if (!node) {
473
- throw new expression_error_1.ExpressionError('Referenced node does not exist', {
474
- messageTemplate: 'Make sure to double-check the node name for typos',
484
+ // Ultra-simple execution-based validation: if no execution data exists, throw error
485
+ if (executionData.length === 0) {
486
+ throw new expression_error_1.ExpressionError(`Node '${nodeName}' hasn't been executed`, {
487
+ messageTemplate: 'An expression references this node, but the node is unexecuted. Consider re-wiring your nodes or checking for execution first, i.e. {{ $if( $("{{nodeName}}").isExecuted, <action_if_executed>, "") }}',
475
488
  functionality: 'pairedItem',
476
489
  descriptionKey: isScriptingNode(nodeName, that.workflow)
477
490
  ? 'pairedItemNoConnectionCodeNode'
478
491
  : 'pairedItemNoConnection',
479
- type: 'paired_item_no_connection',
492
+ type: 'no_execution_data',
480
493
  nodeCause: nodeName,
481
494
  runIndex: that.runIndex,
482
495
  itemIndex: that.itemIndex,
483
496
  });
484
497
  }
485
- if (['binary', 'data', 'json'].includes(name)) {
486
- const executionData = that.getNodeExecutionOrPinnedData({
487
- nodeName,
488
- shortSyntax,
498
+ if (executionData.length <= that.itemIndex) {
499
+ throw new expression_error_1.ExpressionError(`"${nodeName}" node has ${executionData.length} item(s) but you're trying to access item ${that.itemIndex}`, {
500
+ messageTemplate: 'Adjust your expression to access an existing item index (0-{{maxIndex}})',
501
+ functionality: 'pairedItem',
502
+ descriptionKey: 'pairedItemInvalidIndex',
503
+ type: 'no_execution_data',
504
+ nodeCause: nodeName,
505
+ runIndex: that.runIndex,
506
+ itemIndex: that.itemIndex,
489
507
  });
490
- if (executionData.length === 0 && !throwOnMissingExecutionData) {
491
- return undefined;
492
- }
493
- // Ultra-simple execution-based validation: if no execution data exists, throw error
494
- if (executionData.length === 0) {
495
- throw new expression_error_1.ExpressionError(`Node '${nodeName}' hasn't been executed`, {
496
- messageTemplate: 'An expression references this node, but the node is unexecuted. Consider re-wiring your nodes or checking for execution first, i.e. {{ $if( $("{{nodeName}}").isExecuted, <action_if_executed>, "") }}',
497
- functionality: 'pairedItem',
498
- descriptionKey: isScriptingNode(nodeName, that.workflow)
499
- ? 'pairedItemNoConnectionCodeNode'
500
- : 'pairedItemNoConnection',
501
- type: 'no_execution_data',
502
- nodeCause: nodeName,
503
- runIndex: that.runIndex,
504
- itemIndex: that.itemIndex,
505
- });
506
- }
507
- if (executionData.length <= that.itemIndex) {
508
- throw new expression_error_1.ExpressionError(`"${nodeName}" node has ${executionData.length} item(s) but you're trying to access item ${that.itemIndex}`, {
509
- messageTemplate: 'Adjust your expression to access an existing item index (0-{{maxIndex}})',
510
- functionality: 'pairedItem',
511
- descriptionKey: 'pairedItemInvalidIndex',
512
- type: 'no_execution_data',
513
- nodeCause: nodeName,
514
- runIndex: that.runIndex,
515
- itemIndex: that.itemIndex,
516
- });
517
- }
518
- if (['data', 'json'].includes(name)) {
519
- // JSON-Data
520
- return executionData[that.itemIndex].json;
508
+ }
509
+ if (['data', 'json'].includes(name)) {
510
+ // JSON-Data
511
+ return executionData[that.itemIndex].json;
512
+ }
513
+ if (name === 'binary') {
514
+ // Binary-Data
515
+ const returnData = {};
516
+ if (!executionData[that.itemIndex].binary) {
517
+ return returnData;
521
518
  }
522
- if (name === 'binary') {
523
- // Binary-Data
524
- const returnData = {};
525
- if (!executionData[that.itemIndex].binary) {
526
- return returnData;
527
- }
528
- const binaryKeyData = executionData[that.itemIndex].binary;
529
- for (const keyName of Object.keys(binaryKeyData)) {
530
- returnData[keyName] = {};
531
- const binaryData = binaryKeyData[keyName];
532
- for (const propertyName in binaryData) {
533
- if (propertyName === 'data') {
534
- // Skip the data property
535
- continue;
536
- }
537
- returnData[keyName][propertyName] = binaryData[propertyName];
519
+ const binaryKeyData = executionData[that.itemIndex].binary;
520
+ for (const keyName of Object.keys(binaryKeyData)) {
521
+ returnData[keyName] = {};
522
+ const binaryData = binaryKeyData[keyName];
523
+ for (const propertyName in binaryData) {
524
+ if (propertyName === 'data') {
525
+ // Skip the data property
526
+ continue;
538
527
  }
528
+ returnData[keyName][propertyName] = binaryData[propertyName];
539
529
  }
540
- return returnData;
541
- }
542
- }
543
- else if (name === 'context') {
544
- return that.nodeContextGetter(nodeName);
545
- }
546
- else if (name === 'parameter') {
547
- // Get node parameter data
548
- return that.nodeParameterGetter(nodeName);
549
- }
550
- else if (name === 'runIndex') {
551
- if (!that.runExecutionData?.resultData.runData[nodeName]) {
552
- return -1;
553
530
  }
554
- return that.runExecutionData.resultData.runData[nodeName].length - 1;
555
- }
556
- return Reflect.get(target, name, receiver);
557
- },
558
- });
559
- }
560
- prevNodeGetter() {
561
- const allowedValues = ['name', 'outputIndex', 'runIndex'];
562
- const that = this;
563
- return new Proxy({}, {
564
- has: () => true,
565
- ownKeys() {
566
- return allowedValues;
567
- },
568
- getOwnPropertyDescriptor() {
569
- return {
570
- enumerable: true,
571
- configurable: true,
572
- };
573
- },
574
- get(target, name, receiver) {
575
- if (name === 'isProxy')
576
- return true;
577
- if (!that.executeData?.source) {
578
- // Means the previous node did not get executed yet
579
- return undefined;
531
+ return returnData;
580
532
  }
581
- const sourceData = that.executeData.source.main[0];
582
- if (name === 'name') {
583
- return sourceData.previousNode;
584
- }
585
- if (name === 'outputIndex') {
586
- return sourceData.previousNodeOutput || 0;
587
- }
588
- if (name === 'runIndex') {
589
- return sourceData.previousNodeRun || 0;
590
- }
591
- return Reflect.get(target, name, receiver);
592
- },
593
- });
594
- }
595
- /**
596
- * Returns a proxy to query data from the workflow
597
- *
598
- * @private
599
- */
600
- workflowGetter() {
601
- const allowedValues = ['active', 'id', 'name'];
602
- const that = this;
603
- return new Proxy({}, {
604
- has: () => true,
605
- ownKeys() {
606
- return allowedValues;
607
- },
608
- getOwnPropertyDescriptor() {
609
- return {
610
- enumerable: true,
611
- configurable: true,
612
- };
613
- },
614
- get(target, name, receiver) {
615
- if (name === 'isProxy')
616
- return true;
617
- if (allowedValues.includes(name.toString())) {
618
- const value = that.workflow[name];
619
- if (value === undefined && name === 'id') {
620
- throw new expression_error_1.ExpressionError('save workflow to view', {
621
- description: 'Please save the workflow first to use $workflow',
622
- runIndex: that.runIndex,
623
- itemIndex: that.itemIndex,
624
- });
625
- }
626
- return value;
533
+ }
534
+ else if (name === 'context') {
535
+ return that.nodeContextGetter(nodeName);
536
+ }
537
+ else if (name === 'parameter') {
538
+ // Get node parameter data
539
+ return that.nodeParameterGetter(nodeName);
540
+ }
541
+ else if (name === 'runIndex') {
542
+ if (!that.runExecutionData?.resultData.runData[nodeName]) {
543
+ return -1;
627
544
  }
628
- return Reflect.get(target, name, receiver);
629
- },
630
- });
631
- }
632
- /**
633
- * Returns a proxy to query data of all nodes
634
- *
635
- * @private
636
- */
637
- nodeGetter() {
638
- const that = this;
639
- return new Proxy({}, {
640
- has: () => true,
641
- get(_, name) {
642
- if (name === 'isProxy')
643
- return true;
644
- const nodeName = name.toString();
645
- if (that.workflow.getNode(nodeName) === null) {
646
- throw new expression_error_1.ExpressionError("Referenced node doesn't exist", {
545
+ return that.runExecutionData.resultData.runData[nodeName].length - 1;
546
+ }
547
+ return Reflect.get(target, name, receiver);
548
+ },
549
+ });
550
+ }
551
+ prevNodeGetter() {
552
+ const allowedValues = ['name', 'outputIndex', 'runIndex'];
553
+ const that = this;
554
+ return new Proxy({}, {
555
+ has: () => true,
556
+ ownKeys() {
557
+ return allowedValues;
558
+ },
559
+ getOwnPropertyDescriptor() {
560
+ return {
561
+ enumerable: true,
562
+ configurable: true,
563
+ };
564
+ },
565
+ get(target, name, receiver) {
566
+ if (name === 'isProxy')
567
+ return true;
568
+ if (!that.executeData?.source) {
569
+ // Means the previous node did not get executed yet
570
+ return undefined;
571
+ }
572
+ const sourceData = that.executeData.source.main[0];
573
+ if (name === 'name') {
574
+ return sourceData.previousNode;
575
+ }
576
+ if (name === 'outputIndex') {
577
+ return sourceData.previousNodeOutput || 0;
578
+ }
579
+ if (name === 'runIndex') {
580
+ return sourceData.previousNodeRun || 0;
581
+ }
582
+ return Reflect.get(target, name, receiver);
583
+ },
584
+ });
585
+ }
586
+ /**
587
+ * Returns a proxy to query data from the workflow
588
+ *
589
+ * @private
590
+ */
591
+ workflowGetter() {
592
+ const allowedValues = ['active', 'id', 'name'];
593
+ const that = this;
594
+ return new Proxy({}, {
595
+ has: () => true,
596
+ ownKeys() {
597
+ return allowedValues;
598
+ },
599
+ getOwnPropertyDescriptor() {
600
+ return {
601
+ enumerable: true,
602
+ configurable: true,
603
+ };
604
+ },
605
+ get(target, name, receiver) {
606
+ if (name === 'isProxy')
607
+ return true;
608
+ if (allowedValues.includes(name.toString())) {
609
+ const value = that.workflow[name];
610
+ if (value === undefined && name === 'id') {
611
+ throw new expression_error_1.ExpressionError('save workflow to view', {
612
+ description: 'Please save the workflow first to use $workflow',
647
613
  runIndex: that.runIndex,
648
614
  itemIndex: that.itemIndex,
649
- nodeCause: nodeName,
650
- descriptionKey: 'nodeNotFound',
651
615
  });
652
616
  }
653
- return that.nodeDataGetter(nodeName);
654
- },
655
- });
656
- }
657
- /**
658
- * Returns the data proxy object which allows to query data from current run
659
- *
660
- */
661
- getDataProxy(opts) {
662
- const that = this;
663
- // replacing proxies with the actual data.
664
- const jmespathWrapper = (data, query) => {
665
- if (typeof data !== 'object' || typeof query !== 'string') {
666
- throw new expression_error_1.ExpressionError('expected two arguments (Object, string) for this function', {
667
- runIndex: that.runIndex,
668
- itemIndex: that.itemIndex,
669
- });
617
+ return value;
670
618
  }
671
- // jmespath decodes escape sequences inside quoted identifiers, so
672
- // the token check below must run against an unescaped query. Reject
673
- // any backslash up front to keep the property-name match meaningful.
674
- if (query.includes('\\') || (0, utils_1.containsUnsafeObjectPropertyToken)(query)) {
675
- throw new expression_error_1.ExpressionError('Cannot access this property in a jmespath query due to security concerns', {
619
+ return Reflect.get(target, name, receiver);
620
+ },
621
+ });
622
+ }
623
+ /**
624
+ * Returns a proxy to query data of all nodes
625
+ *
626
+ * @private
627
+ */
628
+ nodeGetter() {
629
+ const that = this;
630
+ return new Proxy({}, {
631
+ has: () => true,
632
+ get(_, name) {
633
+ if (name === 'isProxy')
634
+ return true;
635
+ const nodeName = name.toString();
636
+ if (that.workflow.getNode(nodeName) === null) {
637
+ throw new expression_error_1.ExpressionError("Referenced node doesn't exist", {
676
638
  runIndex: that.runIndex,
677
639
  itemIndex: that.itemIndex,
640
+ nodeCause: nodeName,
641
+ descriptionKey: 'nodeNotFound',
678
642
  });
679
643
  }
680
- if (!Array.isArray(data) && typeof data === 'object') {
681
- return jmespath.search({ ...data }, query);
682
- }
683
- return jmespath.search(data, query);
684
- };
685
- const createExpressionError = (message, context) => {
686
- if (isScriptingNode(that.activeNodeName, that.workflow) && context?.functionOverrides) {
687
- // If the node in which the error is thrown is a function node,
688
- // display a different error message in case there is one defined
689
- message = context.functionOverrides.message || message;
690
- context.description = context.functionOverrides.description || context.description;
691
- // The error will be in the code and not on an expression on a parameter
692
- // so remove the messageTemplate as it would overwrite the message
693
- context.messageTemplate = undefined;
694
- }
695
- if (context?.nodeCause) {
696
- const nodeName = context.nodeCause;
697
- const pinData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode);
698
- if (pinData) {
699
- if (!context) {
700
- context = {};
701
- }
702
- message = `Unpin '${nodeName}' to execute`;
703
- context.messageTemplate = undefined;
704
- context.descriptionKey = 'pairedItemPinned';
705
- }
706
- if (context.moreInfoLink && (pinData || isScriptingNode(nodeName, that.workflow))) {
707
- const moreInfoLink = ' <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-errors/">More info</a>';
708
- context.description += moreInfoLink;
709
- if (context.descriptionTemplate)
710
- context.descriptionTemplate += moreInfoLink;
711
- }
712
- }
713
- return new expression_error_1.ExpressionError(message, {
644
+ return that.nodeDataGetter(nodeName);
645
+ },
646
+ });
647
+ }
648
+ /**
649
+ * Returns the data proxy object which allows to query data from current run
650
+ *
651
+ */
652
+ getDataProxy(opts) {
653
+ const that = this;
654
+ // replacing proxies with the actual data.
655
+ const jmespathWrapper = (data, query) => {
656
+ if (typeof data !== 'object' || typeof query !== 'string') {
657
+ throw new expression_error_1.ExpressionError('expected two arguments (Object, string) for this function', {
714
658
  runIndex: that.runIndex,
715
659
  itemIndex: that.itemIndex,
716
- ...context,
717
660
  });
718
- };
719
- const createMissingPairedItemError = (nodeCause, usedMethodName = PAIRED_ITEM_METHOD.PAIRED_ITEM) => {
720
- const pinData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeCause, that.mode);
721
- const message = pinData
722
- ? `Using the ${usedMethodName} method doesn't work with pinned data in this scenario. Please unpin '${nodeCause}' and try again.`
723
- : `Paired item data for ${usedMethodName} from node '${nodeCause}' is unavailable. Ensure '${nodeCause}' is providing the required output.`;
724
- return new expression_error_1.ExpressionError(message, {
661
+ }
662
+ // jmespath decodes escape sequences inside quoted identifiers, so
663
+ // the token check below must run against an unescaped query. Reject
664
+ // any backslash up front to keep the property-name match meaningful.
665
+ if (query.includes('\\') || (0, utils_1.containsUnsafeObjectPropertyToken)(query)) {
666
+ throw new expression_error_1.ExpressionError('Cannot access this property in a jmespath query due to security concerns', {
725
667
  runIndex: that.runIndex,
726
668
  itemIndex: that.itemIndex,
727
- functionality: 'pairedItem',
728
- descriptionKey: isScriptingNode(nodeCause, that.workflow)
729
- ? 'pairedItemNoInfoCodeNode'
730
- : 'pairedItemNoInfo',
731
- nodeCause,
732
- causeDetailed: `Missing pairedItem data (node '${nodeCause}' probably didn't supply it)`,
733
- type: 'paired_item_no_info',
734
- });
735
- };
736
- const createNoConnectionError = (nodeCause) => {
737
- return createExpressionError('Invalid expression', {
738
- messageTemplate: 'No path back to referenced node',
739
- functionality: 'pairedItem',
740
- descriptionKey: isScriptingNode(nodeCause, that.workflow)
741
- ? 'pairedItemNoConnectionCodeNode'
742
- : 'pairedItemNoConnection',
743
- type: 'paired_item_no_connection',
744
- moreInfoLink: true,
745
- nodeCause,
746
- });
747
- };
748
- function createBranchNotFoundError(node, item, cause) {
749
- return createExpressionError('Branch not found', {
750
- messageTemplate: 'Paired item references non-existent branch',
751
- functionality: 'pairedItem',
752
- nodeCause: cause,
753
- functionOverrides: { message: 'Invalid branch reference' },
754
- description: `Item ${item} in node ${node} references a branch that doesn't exist.`,
755
- type: 'paired_item_invalid_info',
756
669
  });
757
670
  }
758
- function createPairedItemNotFound(destNode, cause) {
759
- return createExpressionError('Paired item resolution failed', {
760
- messageTemplate: 'Unable to find paired item source',
761
- functionality: 'pairedItem',
762
- nodeCause: cause,
763
- functionOverrides: { message: 'Data not found' },
764
- description: `Could not trace back to node '${destNode}'`,
765
- type: 'paired_item_no_info',
766
- moreInfoLink: true,
767
- });
671
+ if (!Array.isArray(data) && typeof data === 'object') {
672
+ return jmespath.search({ ...data }, query);
768
673
  }
769
- function createPairedItemMultipleItemsFound(destNode, itemIndex) {
770
- return createExpressionError('Multiple matches found', {
771
- messageTemplate: `Multiple matching items for item [${itemIndex}]`,
772
- functionality: 'pairedItem',
773
- functionOverrides: { message: 'Multiple matches' },
774
- nodeCause: destNode,
775
- descriptionKey: isScriptingNode(destNode, that.workflow)
776
- ? 'pairedItemMultipleMatchesCodeNode'
777
- : 'pairedItemMultipleMatches',
778
- type: 'paired_item_multiple_matches',
779
- });
674
+ return jmespath.search(data, query);
675
+ };
676
+ const createExpressionError = (message, context) => {
677
+ if (isScriptingNode(that.activeNodeName, that.workflow) && context?.functionOverrides) {
678
+ // If the node in which the error is thrown is a function node,
679
+ // display a different error message in case there is one defined
680
+ message = context.functionOverrides.message || message;
681
+ context.description = context.functionOverrides.description || context.description;
682
+ // The error will be in the code and not on an expression on a parameter
683
+ // so remove the messageTemplate as it would overwrite the message
684
+ context.messageTemplate = undefined;
780
685
  }
781
- function normalizeInputs(pairedItem, sourceData) {
782
- if (typeof pairedItem === 'number') {
783
- pairedItem = { item: pairedItem };
686
+ if (context?.nodeCause) {
687
+ const nodeName = context.nodeCause;
688
+ const pinData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode);
689
+ if (pinData) {
690
+ if (!context) {
691
+ context = {};
692
+ }
693
+ message = `Unpin '${nodeName}' to execute`;
694
+ context.messageTemplate = undefined;
695
+ context.descriptionKey = 'pairedItemPinned';
696
+ }
697
+ if (context.moreInfoLink && (pinData || isScriptingNode(nodeName, that.workflow))) {
698
+ const moreInfoLink = ' <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-errors/">More info</a>';
699
+ context.description += moreInfoLink;
700
+ if (context.descriptionTemplate)
701
+ context.descriptionTemplate += moreInfoLink;
784
702
  }
785
- const finalSource = pairedItem.sourceOverwrite || sourceData;
786
- return [pairedItem, finalSource];
787
703
  }
788
- function pinDataToTask(pinData) {
789
- if (!pinData)
790
- return undefined;
791
- return {
792
- data: { main: [pinData] },
793
- startTime: 0,
794
- executionTime: 0,
795
- executionIndex: 0,
796
- source: [],
797
- };
704
+ return new expression_error_1.ExpressionError(message, {
705
+ runIndex: that.runIndex,
706
+ itemIndex: that.itemIndex,
707
+ ...context,
708
+ });
709
+ };
710
+ const createMissingPairedItemError = (nodeCause, usedMethodName = PAIRED_ITEM_METHOD.PAIRED_ITEM) => {
711
+ const pinData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeCause, that.mode);
712
+ const message = pinData
713
+ ? `Using the ${usedMethodName} method doesn't work with pinned data in this scenario. Please unpin '${nodeCause}' and try again.`
714
+ : `Paired item data for ${usedMethodName} from node '${nodeCause}' is unavailable. Ensure '${nodeCause}' is providing the required output.`;
715
+ return new expression_error_1.ExpressionError(message, {
716
+ runIndex: that.runIndex,
717
+ itemIndex: that.itemIndex,
718
+ functionality: 'pairedItem',
719
+ descriptionKey: isScriptingNode(nodeCause, that.workflow)
720
+ ? 'pairedItemNoInfoCodeNode'
721
+ : 'pairedItemNoInfo',
722
+ nodeCause,
723
+ causeDetailed: `Missing pairedItem data (node '${nodeCause}' probably didn't supply it)`,
724
+ type: 'paired_item_no_info',
725
+ });
726
+ };
727
+ const createNoConnectionError = (nodeCause) => {
728
+ return createExpressionError('Invalid expression', {
729
+ messageTemplate: 'No path back to referenced node',
730
+ functionality: 'pairedItem',
731
+ descriptionKey: isScriptingNode(nodeCause, that.workflow)
732
+ ? 'pairedItemNoConnectionCodeNode'
733
+ : 'pairedItemNoConnection',
734
+ type: 'paired_item_no_connection',
735
+ moreInfoLink: true,
736
+ nodeCause,
737
+ });
738
+ };
739
+ function createBranchNotFoundError(node, item, cause) {
740
+ return createExpressionError('Branch not found', {
741
+ messageTemplate: 'Paired item references non-existent branch',
742
+ functionality: 'pairedItem',
743
+ nodeCause: cause,
744
+ functionOverrides: { message: 'Invalid branch reference' },
745
+ description: `Item ${item} in node ${node} references a branch that doesn't exist.`,
746
+ type: 'paired_item_invalid_info',
747
+ });
748
+ }
749
+ function createPairedItemNotFound(destNode, cause) {
750
+ return createExpressionError('Paired item resolution failed', {
751
+ messageTemplate: 'Unable to find paired item source',
752
+ functionality: 'pairedItem',
753
+ nodeCause: cause,
754
+ functionOverrides: { message: 'Data not found' },
755
+ description: `Could not trace back to node '${destNode}'`,
756
+ type: 'paired_item_no_info',
757
+ moreInfoLink: true,
758
+ });
759
+ }
760
+ function createPairedItemMultipleItemsFound(destNode, itemIndex) {
761
+ return createExpressionError('Multiple matches found', {
762
+ messageTemplate: `Multiple matching items for item [${itemIndex}]`,
763
+ functionality: 'pairedItem',
764
+ functionOverrides: { message: 'Multiple matches' },
765
+ nodeCause: destNode,
766
+ descriptionKey: isScriptingNode(destNode, that.workflow)
767
+ ? 'pairedItemMultipleMatchesCodeNode'
768
+ : 'pairedItemMultipleMatches',
769
+ type: 'paired_item_multiple_matches',
770
+ });
771
+ }
772
+ function normalizeInputs(pairedItem, sourceData) {
773
+ if (typeof pairedItem === 'number') {
774
+ pairedItem = { item: pairedItem };
798
775
  }
799
- function getTaskData(source) {
800
- return (that.runExecutionData?.resultData?.runData?.[source.previousNode]?.[source.previousNodeRun || 0] ??
801
- pinDataToTask((0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, source.previousNode, that.mode)));
776
+ const finalSource = pairedItem.sourceOverwrite || sourceData;
777
+ return [pairedItem, finalSource];
778
+ }
779
+ function pinDataToTask(pinData) {
780
+ if (!pinData)
781
+ return undefined;
782
+ return {
783
+ data: { main: [pinData] },
784
+ startTime: 0,
785
+ executionTime: 0,
786
+ executionIndex: 0,
787
+ source: [],
788
+ };
789
+ }
790
+ function getTaskData(source) {
791
+ return (that.runExecutionData?.resultData?.runData?.[source.previousNode]?.[source.previousNodeRun || 0] ??
792
+ pinDataToTask((0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, source.previousNode, that.mode)));
793
+ }
794
+ function getNodeOutput(taskData, source, nodeCause) {
795
+ const outputIndex = source.previousNodeOutput || 0;
796
+ const outputs = taskData?.data?.main?.[outputIndex];
797
+ if (!outputs) {
798
+ throw createExpressionError('Can’t get data for expression', {
799
+ messageTemplate: 'Missing output data',
800
+ functionOverrides: { message: 'Missing output' },
801
+ nodeCause,
802
+ description: `Expected output #${outputIndex} from node ${source.previousNode}`,
803
+ type: 'internal',
804
+ });
802
805
  }
803
- function getNodeOutput(taskData, source, nodeCause) {
804
- const outputIndex = source.previousNodeOutput || 0;
805
- const outputs = taskData?.data?.main?.[outputIndex];
806
- if (!outputs) {
807
- throw createExpressionError('Can’t get data for expression', {
808
- messageTemplate: 'Missing output data',
809
- functionOverrides: { message: 'Missing output' },
810
- nodeCause,
811
- description: `Expected output #${outputIndex} from node ${source.previousNode}`,
812
- type: 'internal',
813
- });
806
+ return outputs;
807
+ }
808
+ const normalizePairedItem = (paired) => {
809
+ if (paired === null || paired === undefined) {
810
+ return [];
811
+ }
812
+ const pairedItems = Array.isArray(paired) ? paired : [paired];
813
+ return pairedItems.map((p) => (typeof p === 'number' ? { item: p } : p));
814
+ };
815
+ const getPairedItem = (destinationNodeName, incomingSourceData, initialPairedItem, usedMethodName = PAIRED_ITEM_METHOD.$GET_PAIRED_ITEM, nodeBeforeLast) => {
816
+ // Normalize inputs
817
+ const [pairedItem, sourceData] = normalizeInputs(initialPairedItem, incomingSourceData);
818
+ if (!sourceData) {
819
+ throw createPairedItemNotFound(destinationNodeName, nodeBeforeLast);
820
+ }
821
+ const taskData = getTaskData(sourceData);
822
+ const outputData = getNodeOutput(taskData, sourceData, nodeBeforeLast);
823
+ const item = outputData[pairedItem.item];
824
+ const sourceArray = taskData?.source ?? [];
825
+ // Done: reached the destination node in the ancestry chain
826
+ if (sourceData.previousNode === destinationNodeName) {
827
+ if (pairedItem.item >= outputData.length) {
828
+ throw createMissingPairedItemError(sourceData.previousNode, usedMethodName);
814
829
  }
815
- return outputs;
830
+ return item;
816
831
  }
817
- const normalizePairedItem = (paired) => {
818
- if (paired === null || paired === undefined) {
832
+ // Normalize paired item to always be IPairedItemData[]
833
+ const nextPairedItems = normalizePairedItem(item.pairedItem);
834
+ if (nextPairedItems.length === 0) {
835
+ throw createMissingPairedItemError(sourceData.previousNode, usedMethodName);
836
+ }
837
+ // Recursively traverse ancestry to find the destination node + paired item
838
+ const results = nextPairedItems.flatMap((nextPairedItem) => {
839
+ const inputIndex = nextPairedItem.input ?? 0;
840
+ if (inputIndex >= sourceArray.length)
819
841
  return [];
842
+ const nextSource = nextPairedItem.sourceOverwrite ?? sourceArray[inputIndex];
843
+ try {
844
+ return (0, result_1.createResultOk)(getPairedItem(destinationNodeName, nextSource, { ...nextPairedItem, input: inputIndex }, usedMethodName, sourceData.previousNode));
820
845
  }
821
- const pairedItems = Array.isArray(paired) ? paired : [paired];
822
- return pairedItems.map((p) => (typeof p === 'number' ? { item: p } : p));
823
- };
824
- const getPairedItem = (destinationNodeName, incomingSourceData, initialPairedItem, usedMethodName = PAIRED_ITEM_METHOD.$GET_PAIRED_ITEM, nodeBeforeLast) => {
825
- // Normalize inputs
826
- const [pairedItem, sourceData] = normalizeInputs(initialPairedItem, incomingSourceData);
827
- if (!sourceData) {
828
- throw createPairedItemNotFound(destinationNodeName, nodeBeforeLast);
829
- }
830
- const taskData = getTaskData(sourceData);
831
- const outputData = getNodeOutput(taskData, sourceData, nodeBeforeLast);
832
- const item = outputData[pairedItem.item];
833
- const sourceArray = taskData?.source ?? [];
834
- // Done: reached the destination node in the ancestry chain
835
- if (sourceData.previousNode === destinationNodeName) {
836
- if (pairedItem.item >= outputData.length) {
837
- throw createMissingPairedItemError(sourceData.previousNode, usedMethodName);
838
- }
839
- return item;
840
- }
841
- // Normalize paired item to always be IPairedItemData[]
842
- const nextPairedItems = normalizePairedItem(item.pairedItem);
843
- if (nextPairedItems.length === 0) {
844
- throw createMissingPairedItemError(sourceData.previousNode, usedMethodName);
846
+ catch (error) {
847
+ return (0, result_1.createResultError)(error);
845
848
  }
846
- // Recursively traverse ancestry to find the destination node + paired item
847
- const results = nextPairedItems.flatMap((nextPairedItem) => {
848
- const inputIndex = nextPairedItem.input ?? 0;
849
- if (inputIndex >= sourceArray.length)
850
- return [];
851
- const nextSource = nextPairedItem.sourceOverwrite ?? sourceArray[inputIndex];
852
- try {
853
- return (0, result_1.createResultOk)(getPairedItem(destinationNodeName, nextSource, { ...nextPairedItem, input: inputIndex }, usedMethodName, sourceData.previousNode));
854
- }
855
- catch (error) {
856
- return (0, result_1.createResultError)(error);
857
- }
849
+ });
850
+ if (results.every((result) => !result.ok)) {
851
+ throw results[0].error;
852
+ }
853
+ const matchedItems = results.filter((result) => result.ok).map((result) => result.result);
854
+ if (matchedItems.length === 0) {
855
+ if (sourceArray.length === 0)
856
+ throw createNoConnectionError(destinationNodeName);
857
+ throw createBranchNotFoundError(sourceData.previousNode, pairedItem.item, nodeBeforeLast);
858
+ }
859
+ const [first, ...rest] = matchedItems;
860
+ if (rest.some((r) => r !== first)) {
861
+ throw createPairedItemMultipleItemsFound(destinationNodeName, pairedItem.item);
862
+ }
863
+ return first;
864
+ };
865
+ const handleFromAi = (name, _description, _type = 'string', defaultValue) => {
866
+ const { itemIndex, runIndex } = that;
867
+ if (!name || name === '') {
868
+ throw new expression_error_1.ExpressionError("Add a key, e.g. $fromAI('placeholder_name')", {
869
+ runIndex,
870
+ itemIndex,
858
871
  });
859
- if (results.every((result) => !result.ok)) {
860
- throw results[0].error;
861
- }
862
- const matchedItems = results.filter((result) => result.ok).map((result) => result.result);
863
- if (matchedItems.length === 0) {
864
- if (sourceArray.length === 0)
865
- throw createNoConnectionError(destinationNodeName);
866
- throw createBranchNotFoundError(sourceData.previousNode, pairedItem.item, nodeBeforeLast);
867
- }
868
- const [first, ...rest] = matchedItems;
869
- if (rest.some((r) => r !== first)) {
870
- throw createPairedItemMultipleItemsFound(destinationNodeName, pairedItem.item);
871
- }
872
- return first;
873
- };
874
- const handleFromAi = (name, _description, _type = 'string', defaultValue) => {
875
- const { itemIndex, runIndex } = that;
876
- if (!name || name === '') {
877
- throw new expression_error_1.ExpressionError("Add a key, e.g. $fromAI('placeholder_name')", {
878
- runIndex,
879
- itemIndex,
880
- });
881
- }
882
- const nameValidationRegex = /^[a-zA-Z0-9_-]{0,64}$/;
883
- if (!nameValidationRegex.test(name)) {
884
- throw new expression_error_1.ExpressionError('Invalid parameter key, must be between 1 and 64 characters long and only contain lowercase letters, uppercase letters, numbers, underscores, and hyphens', {
885
- runIndex,
886
- itemIndex,
887
- });
872
+ }
873
+ const nameValidationRegex = /^[a-zA-Z0-9_-]{0,64}$/;
874
+ if (!nameValidationRegex.test(name)) {
875
+ throw new expression_error_1.ExpressionError('Invalid parameter key, must be between 1 and 64 characters long and only contain lowercase letters, uppercase letters, numbers, underscores, and hyphens', {
876
+ runIndex,
877
+ itemIndex,
878
+ });
879
+ }
880
+ const resultData = that.runExecutionData?.resultData?.runData?.[that.activeNodeName]?.[runIndex];
881
+ let inputData;
882
+ let placeholdersDataInputData;
883
+ if (!resultData) {
884
+ inputData = this.connectionInputData?.[runIndex];
885
+ placeholdersDataInputData = inputData?.json;
886
+ }
887
+ else {
888
+ inputData =
889
+ that.runExecutionData?.resultData.runData[that.activeNodeName]?.[runIndex].inputOverride;
890
+ placeholdersDataInputData = inputData?.[interfaces_1.NodeConnectionTypes.AiTool]?.[0]?.[itemIndex].json;
891
+ }
892
+ if (!placeholdersDataInputData) {
893
+ throw new expression_error_1.ExpressionError('No execution data available', {
894
+ runIndex,
895
+ itemIndex,
896
+ type: 'no_execution_data',
897
+ });
898
+ }
899
+ return (
900
+ // TS does not know that the key exists, we need to address this in refactor
901
+ placeholdersDataInputData?.query?.[name] ??
902
+ placeholdersDataInputData?.[name] ??
903
+ defaultValue);
904
+ };
905
+ const handleTool = (throwOnError = true) => {
906
+ const fallbackValue = that.additionalKeys?.['$tool'];
907
+ try {
908
+ const toolName = handleFromAi('tool', '');
909
+ const toolParameters = handleFromAi('toolParameters', '');
910
+ return {
911
+ name: toolName ?? fallbackValue?.name,
912
+ parameters: toolParameters ?? fallbackValue?.parameters,
913
+ };
914
+ }
915
+ catch (error) {
916
+ const isNoExecutionDataError = error instanceof expression_error_1.ExpressionError && error.context.type === 'no_execution_data';
917
+ // always suppress no_execution_data error
918
+ // $tool can get accessed in some cases where no execution data is available, e.g. task runners
919
+ if (isNoExecutionDataError) {
920
+ return fallbackValue;
888
921
  }
889
- const resultData = that.runExecutionData?.resultData?.runData?.[that.activeNodeName]?.[runIndex];
890
- let inputData;
891
- let placeholdersDataInputData;
892
- if (!resultData) {
893
- inputData = this.connectionInputData?.[runIndex];
894
- placeholdersDataInputData = inputData?.json;
922
+ if (throwOnError) {
923
+ throw error;
895
924
  }
896
- else {
897
- inputData =
898
- that.runExecutionData?.resultData.runData[that.activeNodeName]?.[runIndex].inputOverride;
899
- placeholdersDataInputData = inputData?.[interfaces_1.NodeConnectionTypes.AiTool]?.[0]?.[itemIndex].json;
925
+ return undefined;
926
+ }
927
+ };
928
+ const base = {
929
+ $: (nodeName, resolveFullItem) => {
930
+ if (!nodeName) {
931
+ nodeName = that.prevNodeGetter().name;
932
+ if (!nodeName) {
933
+ throw createExpressionError('When calling $(), please specify a node');
934
+ }
900
935
  }
901
- if (!placeholdersDataInputData) {
902
- throw new expression_error_1.ExpressionError('No execution data available', {
903
- runIndex,
904
- itemIndex,
905
- type: 'no_execution_data',
936
+ const referencedNode = that.workflow.getNode(nodeName);
937
+ if (referencedNode === null) {
938
+ throw createExpressionError("Referenced node doesn't exist", {
939
+ runIndex: that.runIndex,
940
+ itemIndex: that.itemIndex,
941
+ nodeCause: nodeName,
942
+ descriptionKey: 'nodeNotFound',
906
943
  });
907
944
  }
908
- return (
909
- // TS does not know that the key exists, we need to address this in refactor
910
- placeholdersDataInputData?.query?.[name] ??
911
- placeholdersDataInputData?.[name] ??
912
- defaultValue);
913
- };
914
- const handleTool = (throwOnError = true) => {
915
- const fallbackValue = that.additionalKeys?.['$tool'];
916
- try {
917
- const toolName = handleFromAi('tool', '');
918
- const toolParameters = handleFromAi('toolParameters', '');
919
- return {
920
- name: toolName ?? fallbackValue?.name,
921
- parameters: toolParameters ?? fallbackValue?.parameters,
922
- };
923
- }
924
- catch (error) {
925
- const isNoExecutionDataError = error instanceof expression_error_1.ExpressionError && error.context.type === 'no_execution_data';
926
- // always suppress no_execution_data error
927
- // $tool can get accessed in some cases where no execution data is available, e.g. task runners
928
- if (isNoExecutionDataError) {
929
- return fallbackValue;
930
- }
931
- if (throwOnError) {
932
- throw error;
933
- }
934
- return undefined;
935
- }
936
- };
937
- const base = {
938
- $: (nodeName, resolveFullItem) => {
939
- if (!nodeName) {
940
- nodeName = that.prevNodeGetter().name;
941
- if (!nodeName) {
942
- throw createExpressionError('When calling $(), please specify a node');
943
- }
944
- }
945
- const referencedNode = that.workflow.getNode(nodeName);
946
- if (referencedNode === null) {
947
- throw createExpressionError("Referenced node doesn't exist", {
945
+ const ensureNodeExecutionData = () => {
946
+ if (!that?.runExecutionData?.resultData?.runData.hasOwnProperty(nodeName) &&
947
+ !(0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode)) {
948
+ throw createExpressionError(`Node '${nodeName}' hasn't been executed`, {
949
+ messageTemplate: 'An expression references this node, but the node is unexecuted. Consider re-wiring your nodes or checking for execution first, i.e. {{ $if( $("{{nodeName}}").isExecuted, <action_if_executed>, "") }}',
950
+ functionality: 'pairedItem',
951
+ descriptionKey: isScriptingNode(nodeName, that.workflow)
952
+ ? 'pairedItemNoConnectionCodeNode'
953
+ : 'pairedItemNoConnection',
954
+ type: 'no_execution_data',
955
+ nodeCause: nodeName,
948
956
  runIndex: that.runIndex,
949
957
  itemIndex: that.itemIndex,
950
- nodeCause: nodeName,
951
- descriptionKey: 'nodeNotFound',
952
958
  });
953
959
  }
954
- const ensureNodeExecutionData = () => {
955
- if (!that?.runExecutionData?.resultData?.runData.hasOwnProperty(nodeName) &&
956
- !(0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode)) {
957
- throw createExpressionError(`Node '${nodeName}' hasn't been executed`, {
958
- messageTemplate: 'An expression references this node, but the node is unexecuted. Consider re-wiring your nodes or checking for execution first, i.e. {{ $if( $("{{nodeName}}").isExecuted, <action_if_executed>, "") }}',
959
- functionality: 'pairedItem',
960
- descriptionKey: isScriptingNode(nodeName, that.workflow)
961
- ? 'pairedItemNoConnectionCodeNode'
962
- : 'pairedItemNoConnection',
963
- type: 'no_execution_data',
964
- nodeCause: nodeName,
965
- runIndex: that.runIndex,
966
- itemIndex: that.itemIndex,
967
- });
960
+ };
961
+ return new Proxy({}, {
962
+ has: () => true,
963
+ ownKeys() {
964
+ return [
965
+ PAIRED_ITEM_METHOD.PAIRED_ITEM,
966
+ 'isExecuted',
967
+ PAIRED_ITEM_METHOD.ITEM_MATCHING,
968
+ PAIRED_ITEM_METHOD.ITEM,
969
+ 'first',
970
+ 'last',
971
+ 'all',
972
+ 'context',
973
+ 'params',
974
+ ];
975
+ },
976
+ get(target, property, receiver) {
977
+ if (property === 'isProxy')
978
+ return true;
979
+ if (property === 'isExecuted') {
980
+ return (that?.runExecutionData?.resultData?.runData.hasOwnProperty(nodeName) ?? false);
968
981
  }
969
- };
970
- return new Proxy({}, {
971
- has: () => true,
972
- ownKeys() {
973
- return [
974
- PAIRED_ITEM_METHOD.PAIRED_ITEM,
975
- 'isExecuted',
976
- PAIRED_ITEM_METHOD.ITEM_MATCHING,
977
- PAIRED_ITEM_METHOD.ITEM,
978
- 'first',
979
- 'last',
980
- 'all',
981
- 'context',
982
- 'params',
983
- ];
984
- },
985
- get(target, property, receiver) {
986
- if (property === 'isProxy')
987
- return true;
988
- if (property === 'isExecuted') {
989
- return (that?.runExecutionData?.resultData?.runData.hasOwnProperty(nodeName) ?? false);
982
+ if (property === PAIRED_ITEM_METHOD.PAIRED_ITEM ||
983
+ property === PAIRED_ITEM_METHOD.ITEM_MATCHING ||
984
+ property === PAIRED_ITEM_METHOD.ITEM) {
985
+ // Before resolving the pairedItem make sure that the requested node comes in the
986
+ // graph before the current one
987
+ const activeNode = that.workflow.getNode(that.activeNodeName);
988
+ let contextNode = that.contextNodeName;
989
+ if (activeNode) {
990
+ const parentMainInputNode = that.workflow.getParentMainInputNode(activeNode);
991
+ contextNode = parentMainInputNode?.name ?? contextNode;
990
992
  }
991
- if (property === PAIRED_ITEM_METHOD.PAIRED_ITEM ||
992
- property === PAIRED_ITEM_METHOD.ITEM_MATCHING ||
993
- property === PAIRED_ITEM_METHOD.ITEM) {
994
- // Before resolving the pairedItem make sure that the requested node comes in the
995
- // graph before the current one
996
- const activeNode = that.workflow.getNode(that.activeNodeName);
997
- let contextNode = that.contextNodeName;
998
- if (activeNode) {
999
- const parentMainInputNode = that.workflow.getParentMainInputNode(activeNode);
1000
- contextNode = parentMainInputNode?.name ?? contextNode;
1001
- }
1002
- // Check if the node has any children and check parents for them instead of the activeNodeName
1003
- const children = that.workflow.getChildNodes(that.activeNodeName, 'ALL_NON_MAIN');
1004
- if (children.length === 0) {
1005
- // Node has no children, check parent of context node
1006
- const parents = that.workflow.getParentNodes(contextNode);
1007
- if (!parents.includes(nodeName)) {
1008
- throw createNoConnectionError(nodeName);
1009
- }
993
+ // Check if the node has any children and check parents for them instead of the activeNodeName
994
+ const children = that.workflow.getChildNodes(that.activeNodeName, 'ALL_NON_MAIN');
995
+ if (children.length === 0) {
996
+ // Node has no children, check parent of context node
997
+ const parents = that.workflow.getParentNodes(contextNode);
998
+ if (!parents.includes(nodeName)) {
999
+ throw createNoConnectionError(nodeName);
1010
1000
  }
1011
- else {
1012
- // Node has children, check parent of children
1013
- const parents = children.flatMap((child) => that.workflow.getParentNodes(child, 'ALL'));
1014
- if (!parents.includes(nodeName)) {
1015
- throw createNoConnectionError(nodeName);
1016
- }
1001
+ }
1002
+ else {
1003
+ // Node has children, check parent of children
1004
+ const parents = children.flatMap((child) => that.workflow.getParentNodes(child, 'ALL'));
1005
+ if (!parents.includes(nodeName)) {
1006
+ throw createNoConnectionError(nodeName);
1017
1007
  }
1018
- ensureNodeExecutionData();
1019
- const pairedItemMethod = (itemIndex) => {
1020
- if (itemIndex === undefined) {
1021
- if (property === PAIRED_ITEM_METHOD.ITEM_MATCHING) {
1022
- throw createExpressionError('Missing item index for .itemMatching()', {
1023
- itemIndex,
1024
- });
1025
- }
1026
- itemIndex = that.itemIndex;
1027
- }
1028
- if (!that.connectionInputData.length) {
1029
- const pinnedData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode);
1030
- if (pinnedData) {
1031
- return that.returnExecutionData(pinnedData[itemIndex], resolveFullItem);
1032
- }
1033
- // The active node has not run yet (e.g. partial execution),
1034
- // so paired item resolution cannot trace through the chain.
1035
- // Fall back to reading directly from the referenced node's
1036
- // run data, which is what first()/last()/all() do.
1037
- const nodeRunData = that.getNodeExecutionOrPinnedData({
1038
- nodeName,
1039
- });
1040
- if (nodeRunData.length) {
1041
- // In the UI preview itemIndex is always 0, but guard against
1042
- // out-of-bounds access in case that assumption ever changes.
1043
- if (itemIndex >= nodeRunData.length) {
1044
- throw createExpressionError(`"${nodeName}" node has ${nodeRunData.length} item(s) but expression references item ${itemIndex}`, { itemIndex });
1045
- }
1046
- return that.returnExecutionData(nodeRunData[itemIndex], resolveFullItem);
1047
- }
1048
- }
1049
- const executionData = that.connectionInputData;
1050
- const input = executionData?.[itemIndex];
1051
- if (!input) {
1052
- throw createExpressionError('Can’t get data for expression', {
1053
- messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
1054
- functionality: 'pairedItem',
1055
- functionOverrides: {
1056
- description: `Some intermediate nodes between ‘<strong>${nodeName}</strong>‘ and ‘<strong>${that.activeNodeName}</strong>‘ have not executed yet.`,
1057
- message: 'Can’t get data',
1058
- },
1059
- description: `Some intermediate nodes between ‘<strong>${nodeName}</strong>‘ and ‘<strong>${that.activeNodeName}</strong>‘ have not executed yet.`,
1060
- causeDetailed: `pairedItem can\'t be found when intermediate nodes between ‘<strong>${nodeName}</strong>‘ and ‘<strong>${that.activeNodeName}</strong> have not executed yet.`,
1008
+ }
1009
+ ensureNodeExecutionData();
1010
+ const pairedItemMethod = (itemIndex) => {
1011
+ if (itemIndex === undefined) {
1012
+ if (property === PAIRED_ITEM_METHOD.ITEM_MATCHING) {
1013
+ throw createExpressionError('Missing item index for .itemMatching()', {
1061
1014
  itemIndex,
1062
- type: 'paired_item_intermediate_nodes',
1063
1015
  });
1064
1016
  }
1065
- // As we operate on the incoming item we can be sure that pairedItem is not an
1066
- // array. After all can it only come from exactly one previous node via a certain
1067
- // input. For that reason do we not have to consider the array case.
1068
- const pairedItem = input.pairedItem;
1069
- if (pairedItem === undefined) {
1070
- throw createMissingPairedItemError(that.activeNodeName, property);
1017
+ itemIndex = that.itemIndex;
1018
+ }
1019
+ if (!that.connectionInputData.length) {
1020
+ const pinnedData = (0, workflow_data_proxy_helpers_1.getPinDataIfManualExecution)(that.workflow, nodeName, that.mode);
1021
+ if (pinnedData) {
1022
+ return that.returnExecutionData(pinnedData[itemIndex], resolveFullItem);
1071
1023
  }
1072
- if (!that.executeData?.source) {
1073
- throw createExpressionError('Can’t get data for expression', {
1074
- messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
1075
- functionality: 'pairedItem',
1076
- functionOverrides: {
1077
- message: 'Can’t get data',
1078
- },
1079
- description: 'Apologies, this is an internal error. See details for more information',
1080
- causeDetailed: 'Missing sourceData (probably an internal error)',
1081
- itemIndex,
1082
- });
1024
+ // The active node has not run yet (e.g. partial execution),
1025
+ // so paired item resolution cannot trace through the chain.
1026
+ // Fall back to reading directly from the referenced node's
1027
+ // run data, which is what first()/last()/all() do.
1028
+ const nodeRunData = that.getNodeExecutionOrPinnedData({
1029
+ nodeName,
1030
+ });
1031
+ if (nodeRunData.length) {
1032
+ // In the UI preview itemIndex is always 0, but guard against
1033
+ // out-of-bounds access in case that assumption ever changes.
1034
+ if (itemIndex >= nodeRunData.length) {
1035
+ throw createExpressionError(`"${nodeName}" node has ${nodeRunData.length} item(s) but expression references item ${itemIndex}`, { itemIndex });
1036
+ }
1037
+ return that.returnExecutionData(nodeRunData[itemIndex], resolveFullItem);
1083
1038
  }
1084
- const sourceData = that.executeData.source.main[pairedItem.input || 0] ??
1085
- that.executeData.source.main[0];
1086
- return that.returnExecutionData(getPairedItem(nodeName, sourceData, pairedItem, property), resolveFullItem);
1087
- };
1088
- if (property === PAIRED_ITEM_METHOD.ITEM) {
1089
- return pairedItemMethod();
1090
1039
  }
1091
- return pairedItemMethod;
1092
- }
1093
- if (property === 'first') {
1094
- ensureNodeExecutionData();
1095
- return (branchIndex, runIndex) => {
1096
- branchIndex =
1097
- branchIndex ??
1098
- // default to the output the active node is connected to
1099
- that.workflow.getNodeConnectionIndexes(that.activeNodeName, nodeName)
1100
- ?.sourceIndex ??
1101
- 0;
1102
- const executionData = that.getNodeExecutionOrPinnedData({
1103
- nodeName,
1104
- branchIndex,
1105
- runIndex,
1040
+ const executionData = that.connectionInputData;
1041
+ const input = executionData?.[itemIndex];
1042
+ if (!input) {
1043
+ throw createExpressionError('Can’t get data for expression', {
1044
+ messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
1045
+ functionality: 'pairedItem',
1046
+ functionOverrides: {
1047
+ description: `Some intermediate nodes between ‘<strong>${nodeName}</strong>‘ and ‘<strong>${that.activeNodeName}</strong>‘ have not executed yet.`,
1048
+ message: 'Can’t get data',
1049
+ },
1050
+ description: `Some intermediate nodes between ‘<strong>${nodeName}</strong>‘ and ‘<strong>${that.activeNodeName}</strong>‘ have not executed yet.`,
1051
+ causeDetailed: `pairedItem can\'t be found when intermediate nodes between ‘<strong>${nodeName}</strong>‘ and ‘<strong>${that.activeNodeName}</strong> have not executed yet.`,
1052
+ itemIndex,
1053
+ type: 'paired_item_intermediate_nodes',
1106
1054
  });
1107
- if (executionData[0])
1108
- return that.returnExecutionData(executionData[0], resolveFullItem);
1109
- return undefined;
1110
- };
1111
- }
1112
- if (property === 'last') {
1113
- ensureNodeExecutionData();
1114
- return (branchIndex, runIndex) => {
1115
- branchIndex =
1116
- branchIndex ??
1117
- // default to the output the active node is connected to
1118
- that.workflow.getNodeConnectionIndexes(that.activeNodeName, nodeName)
1119
- ?.sourceIndex ??
1120
- 0;
1121
- const executionData = that.getNodeExecutionOrPinnedData({
1122
- nodeName,
1123
- branchIndex,
1124
- runIndex,
1055
+ }
1056
+ // As we operate on the incoming item we can be sure that pairedItem is not an
1057
+ // array. After all can it only come from exactly one previous node via a certain
1058
+ // input. For that reason do we not have to consider the array case.
1059
+ const pairedItem = input.pairedItem;
1060
+ if (pairedItem === undefined) {
1061
+ throw createMissingPairedItemError(that.activeNodeName, property);
1062
+ }
1063
+ if (!that.executeData?.source) {
1064
+ throw createExpressionError('Can’t get data for expression', {
1065
+ messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
1066
+ functionality: 'pairedItem',
1067
+ functionOverrides: {
1068
+ message: 'Can’t get data',
1069
+ },
1070
+ description: 'Apologies, this is an internal error. See details for more information',
1071
+ causeDetailed: 'Missing sourceData (probably an internal error)',
1072
+ itemIndex,
1125
1073
  });
1126
- if (!executionData.length)
1127
- return undefined;
1128
- if (executionData[executionData.length - 1]) {
1129
- return that.returnExecutionData(executionData[executionData.length - 1], resolveFullItem);
1130
- }
1131
- return undefined;
1132
- };
1133
- }
1134
- if (property === 'all') {
1135
- ensureNodeExecutionData();
1136
- return (branchIndex, runIndex) => {
1137
- branchIndex =
1138
- branchIndex ??
1139
- // default to the output the active node is connected to
1140
- that.workflow.getNodeConnectionIndexes(that.activeNodeName, nodeName)
1141
- ?.sourceIndex ??
1142
- 0;
1143
- return that.returnExecutionData(that.getNodeExecutionOrPinnedData({
1144
- nodeName,
1145
- branchIndex,
1146
- runIndex,
1147
- }), resolveFullItem);
1148
- };
1149
- }
1150
- if (property === 'context') {
1151
- return that.nodeContextGetter(nodeName);
1152
- }
1153
- if (property === 'params') {
1154
- return that.workflow.getNode(nodeName)?.parameters;
1074
+ }
1075
+ const sourceData = that.executeData.source.main[pairedItem.input || 0] ??
1076
+ that.executeData.source.main[0];
1077
+ return that.returnExecutionData(getPairedItem(nodeName, sourceData, pairedItem, property), resolveFullItem);
1078
+ };
1079
+ if (property === PAIRED_ITEM_METHOD.ITEM) {
1080
+ return pairedItemMethod();
1155
1081
  }
1156
- return Reflect.get(target, property, receiver);
1157
- },
1158
- });
1159
- },
1160
- $input: new Proxy({}, {
1161
- has: () => true,
1162
- ownKeys() {
1163
- return ['all', 'context', 'first', 'item', 'last', 'params'];
1164
- },
1165
- getOwnPropertyDescriptor() {
1166
- return {
1167
- enumerable: true,
1168
- configurable: true,
1169
- };
1170
- },
1171
- get(target, property, receiver) {
1172
- if (property === 'isProxy')
1173
- return true;
1174
- if (that.connectionInputData.length === 0) {
1175
- throw createExpressionError('No execution data available', {
1176
- runIndex: that.runIndex,
1177
- itemIndex: that.itemIndex,
1178
- type: 'no_execution_data',
1179
- });
1180
- }
1181
- if (property === 'item') {
1182
- return that.returnExecutionData(that.connectionInputData[that.itemIndex]);
1082
+ return pairedItemMethod;
1183
1083
  }
1184
1084
  if (property === 'first') {
1185
- return (...args) => {
1186
- if (args.length) {
1187
- throw createExpressionError("$input.first() takes no arguments. To get items from a specific upstream node, use $('NodeName').first() (or $('NodeName').all() for every item).");
1188
- }
1189
- const result = that.connectionInputData;
1190
- if (result[0]) {
1191
- return that.returnExecutionData(result[0]);
1192
- }
1085
+ ensureNodeExecutionData();
1086
+ return (branchIndex, runIndex) => {
1087
+ branchIndex =
1088
+ branchIndex ??
1089
+ // default to the output the active node is connected to
1090
+ that.workflow.getNodeConnectionIndexes(that.activeNodeName, nodeName)
1091
+ ?.sourceIndex ??
1092
+ 0;
1093
+ const executionData = that.getNodeExecutionOrPinnedData({
1094
+ nodeName,
1095
+ branchIndex,
1096
+ runIndex,
1097
+ });
1098
+ if (executionData[0])
1099
+ return that.returnExecutionData(executionData[0], resolveFullItem);
1193
1100
  return undefined;
1194
1101
  };
1195
1102
  }
1196
1103
  if (property === 'last') {
1197
- return (...args) => {
1198
- if (args.length) {
1199
- throw createExpressionError("$input.last() takes no arguments. To get items from a specific upstream node, use $('NodeName').last() (or $('NodeName').all() for every item).");
1200
- }
1201
- const result = that.connectionInputData;
1202
- if (result.length && result[result.length - 1]) {
1203
- return that.returnExecutionData(result[result.length - 1]);
1104
+ ensureNodeExecutionData();
1105
+ return (branchIndex, runIndex) => {
1106
+ branchIndex =
1107
+ branchIndex ??
1108
+ // default to the output the active node is connected to
1109
+ that.workflow.getNodeConnectionIndexes(that.activeNodeName, nodeName)
1110
+ ?.sourceIndex ??
1111
+ 0;
1112
+ const executionData = that.getNodeExecutionOrPinnedData({
1113
+ nodeName,
1114
+ branchIndex,
1115
+ runIndex,
1116
+ });
1117
+ if (!executionData.length)
1118
+ return undefined;
1119
+ if (executionData[executionData.length - 1]) {
1120
+ return that.returnExecutionData(executionData[executionData.length - 1], resolveFullItem);
1204
1121
  }
1205
1122
  return undefined;
1206
1123
  };
1207
1124
  }
1208
1125
  if (property === 'all') {
1209
- return () => {
1210
- const result = that.connectionInputData;
1211
- if (result.length) {
1212
- return that.returnExecutionData(result);
1213
- }
1214
- return [];
1126
+ ensureNodeExecutionData();
1127
+ return (branchIndex, runIndex) => {
1128
+ branchIndex =
1129
+ branchIndex ??
1130
+ // default to the output the active node is connected to
1131
+ that.workflow.getNodeConnectionIndexes(that.activeNodeName, nodeName)
1132
+ ?.sourceIndex ??
1133
+ 0;
1134
+ return that.returnExecutionData(that.getNodeExecutionOrPinnedData({
1135
+ nodeName,
1136
+ branchIndex,
1137
+ runIndex,
1138
+ }), resolveFullItem);
1215
1139
  };
1216
1140
  }
1217
- if (['context', 'params'].includes(property)) {
1218
- // For the following properties we need the source data so fail in case it is missing
1219
- // for some reason (even though that should actually never happen)
1220
- if (!that.executeData?.source) {
1221
- throw createExpressionError('Can’t get data for expression', {
1222
- messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
1223
- functionOverrides: {
1224
- message: 'Can’t get data',
1225
- },
1226
- description: 'Apologies, this is an internal error. See details for more information',
1227
- causeDetailed: 'Missing sourceData (probably an internal error)',
1228
- runIndex: that.runIndex,
1229
- });
1230
- }
1231
- const sourceData = that.executeData.source.main[0];
1232
- if (property === 'context') {
1233
- return that.nodeContextGetter(sourceData.previousNode);
1234
- }
1235
- if (property === 'params') {
1236
- return that.workflow.getNode(sourceData.previousNode)?.parameters;
1237
- }
1141
+ if (property === 'context') {
1142
+ return that.nodeContextGetter(nodeName);
1143
+ }
1144
+ if (property === 'params') {
1145
+ return that.workflow.getNode(nodeName)?.parameters;
1238
1146
  }
1239
1147
  return Reflect.get(target, property, receiver);
1240
1148
  },
1241
- }),
1242
- $binary: {}, // Placeholder
1243
- $data: {}, // Placeholder
1244
- $env: (0, workflow_data_proxy_env_provider_1.createEnvProvider)(that.runIndex, that.itemIndex, that.envProviderState ?? (0, workflow_data_proxy_env_provider_1.createEnvProviderState)()),
1245
- $evaluateExpression: (expression, itemIndex) => {
1246
- if (!isCodeGenerationAllowed()) {
1247
- throw new expression_error_1.ExpressionError("$evaluateExpression can't be used in the Code node while task runners run in secure mode", {
1248
- description: 'Secure-mode task runners disable evaluating strings as code, which expressions rely on. Evaluate the expression in a node field instead, for example an Edit Fields (Set) node before the Code node.',
1249
- });
1250
- }
1251
- itemIndex = itemIndex || that.itemIndex;
1252
- return that.workflow.expression.getParameterValue(`=${expression}`, that.runExecutionData, that.runIndex, itemIndex, that.activeNodeName, that.connectionInputData, that.mode, that.additionalKeys, that.executeData, false, {}, that.contextNodeName);
1253
- },
1254
- // this is legacy syntax that is not documented
1255
- $item: (itemIndex, runIndex) => {
1256
- const defaultReturnRunIndex = runIndex === undefined ? -1 : runIndex;
1257
- const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData, that.siblingParameters, that.mode, that.additionalKeys, that.executeData, defaultReturnRunIndex, {}, that.contextNodeName);
1258
- return dataProxy.getDataProxy();
1149
+ });
1150
+ },
1151
+ $input: new Proxy({}, {
1152
+ has: () => true,
1153
+ ownKeys() {
1154
+ return ['all', 'context', 'first', 'item', 'last', 'params'];
1259
1155
  },
1260
- $fromAI: handleFromAi,
1261
- // Make sure mis-capitalized $fromAI is handled correctly even though we don't auto-complete it
1262
- $fromai: handleFromAi,
1263
- $fromAi: handleFromAi,
1264
- // this is a legacy syntax that is not documented
1265
- $items: (nodeName, outputIndex, runIndex) => {
1266
- if (nodeName === undefined) {
1267
- nodeName = that.prevNodeGetter().name;
1268
- const node = this.workflow.nodes[nodeName];
1269
- let result = that.connectionInputData;
1270
- if (node.executeOnce === true) {
1271
- result = result.slice(0, 1);
1272
- }
1273
- if (result.length) {
1274
- return result;
1275
- }
1276
- return [];
1277
- }
1278
- outputIndex = outputIndex || 0;
1279
- runIndex = runIndex === undefined ? -1 : runIndex;
1280
- return that.getNodeExecutionData(nodeName, false, outputIndex, runIndex);
1156
+ getOwnPropertyDescriptor() {
1157
+ return {
1158
+ enumerable: true,
1159
+ configurable: true,
1160
+ };
1281
1161
  },
1282
- $tool: {}, // Placeholder
1283
- $json: {}, // Placeholder
1284
- $node: this.nodeGetter(),
1285
- $self: this.selfGetter(),
1286
- $parameter: this.nodeParameterGetter(this.activeNodeName),
1287
- $rawParameter: this.nodeParameterGetter(this.activeNodeName, false),
1288
- $prevNode: this.prevNodeGetter(),
1289
- $runIndex: this.runIndex,
1290
- $mode: this.mode,
1291
- $workflow: this.workflowGetter(),
1292
- $itemIndex: this.itemIndex,
1293
- $now: luxon_1.DateTime.now(),
1294
- $today: luxon_1.DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }),
1295
- $jmesPath: jmespathWrapper,
1296
- DateTime: luxon_1.DateTime,
1297
- Interval: luxon_1.Interval,
1298
- Duration: luxon_1.Duration,
1299
- ...that.additionalKeys,
1300
- $getPairedItem: getPairedItem,
1301
- // deprecated
1302
- $jmespath: jmespathWrapper,
1303
- $position: this.itemIndex,
1304
- $thisItem: that.connectionInputData[that.itemIndex],
1305
- $thisItemIndex: this.itemIndex,
1306
- $thisRunIndex: this.runIndex,
1307
- $nodeVersion: that.workflow.getNode(that.activeNodeName)?.typeVersion,
1308
- $nodeId: that.workflow.getNode(that.activeNodeName)?.id,
1309
- $agentInfo: this.agentInfo(),
1310
- $webhookId: that.workflow.getNode(that.activeNodeName)?.webhookId,
1311
- };
1312
- const throwOnMissingExecutionData = opts?.throwOnMissingExecutionData ?? true;
1313
- return new Proxy(base, {
1314
- has: () => true,
1315
- get(target, name, receiver) {
1316
- if (name === 'isProxy')
1162
+ get(target, property, receiver) {
1163
+ if (property === 'isProxy')
1317
1164
  return true;
1318
- const JSON_ACCESS_KEYS = ['$data', '$json'];
1319
- if (that.workflow.settings?.binaryMode === constants_1.BINARY_MODE_COMBINED) {
1320
- JSON_ACCESS_KEYS.push('$item');
1165
+ if (that.connectionInputData.length === 0) {
1166
+ throw createExpressionError('No execution data available', {
1167
+ runIndex: that.runIndex,
1168
+ itemIndex: that.itemIndex,
1169
+ type: 'no_execution_data',
1170
+ });
1321
1171
  }
1322
- if (typeof name === 'string' && JSON_ACCESS_KEYS.includes(name)) {
1323
- return that.nodeDataGetter(that.contextNodeName, true, throwOnMissingExecutionData)?.json;
1172
+ if (property === 'item') {
1173
+ return that.returnExecutionData(that.connectionInputData[that.itemIndex]);
1324
1174
  }
1325
- if (name === '$binary') {
1326
- return that.nodeDataGetter(that.contextNodeName, true, throwOnMissingExecutionData)
1327
- ?.binary;
1175
+ if (property === 'first') {
1176
+ return (...args) => {
1177
+ if (args.length) {
1178
+ throw createExpressionError("$input.first() takes no arguments. To get items from a specific upstream node, use $('NodeName').first() (or $('NodeName').all() for every item).");
1179
+ }
1180
+ const result = that.connectionInputData;
1181
+ if (result[0]) {
1182
+ return that.returnExecutionData(result[0]);
1183
+ }
1184
+ return undefined;
1185
+ };
1186
+ }
1187
+ if (property === 'last') {
1188
+ return (...args) => {
1189
+ if (args.length) {
1190
+ throw createExpressionError("$input.last() takes no arguments. To get items from a specific upstream node, use $('NodeName').last() (or $('NodeName').all() for every item).");
1191
+ }
1192
+ const result = that.connectionInputData;
1193
+ if (result.length && result[result.length - 1]) {
1194
+ return that.returnExecutionData(result[result.length - 1]);
1195
+ }
1196
+ return undefined;
1197
+ };
1328
1198
  }
1329
- if (name === '$tool') {
1330
- return handleTool(throwOnMissingExecutionData);
1199
+ if (property === 'all') {
1200
+ return () => {
1201
+ const result = that.connectionInputData;
1202
+ if (result.length) {
1203
+ return that.returnExecutionData(result);
1204
+ }
1205
+ return [];
1206
+ };
1331
1207
  }
1332
- return Reflect.get(target, name, receiver);
1208
+ if (['context', 'params'].includes(property)) {
1209
+ // For the following properties we need the source data so fail in case it is missing
1210
+ // for some reason (even though that should actually never happen)
1211
+ if (!that.executeData?.source) {
1212
+ throw createExpressionError('Can’t get data for expression', {
1213
+ messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
1214
+ functionOverrides: {
1215
+ message: 'Can’t get data',
1216
+ },
1217
+ description: 'Apologies, this is an internal error. See details for more information',
1218
+ causeDetailed: 'Missing sourceData (probably an internal error)',
1219
+ runIndex: that.runIndex,
1220
+ });
1221
+ }
1222
+ const sourceData = that.executeData.source.main[0];
1223
+ if (property === 'context') {
1224
+ return that.nodeContextGetter(sourceData.previousNode);
1225
+ }
1226
+ if (property === 'params') {
1227
+ return that.workflow.getNode(sourceData.previousNode)?.parameters;
1228
+ }
1229
+ }
1230
+ return Reflect.get(target, property, receiver);
1333
1231
  },
1334
- });
1335
- }
1232
+ }),
1233
+ $binary: {}, // Placeholder
1234
+ $data: {}, // Placeholder
1235
+ $env: (0, workflow_data_proxy_env_provider_1.createEnvProvider)(that.runIndex, that.itemIndex, that.envProviderState ?? (0, workflow_data_proxy_env_provider_1.createEnvProviderState)()),
1236
+ $evaluateExpression: (expression, itemIndex) => {
1237
+ if (!isCodeGenerationAllowed()) {
1238
+ throw new expression_error_1.ExpressionError("$evaluateExpression can't be used in the Code node while task runners run in secure mode", {
1239
+ description: 'Secure-mode task runners disable evaluating strings as code, which expressions rely on. Evaluate the expression in a node field instead, for example an Edit Fields (Set) node before the Code node.',
1240
+ });
1241
+ }
1242
+ itemIndex = itemIndex || that.itemIndex;
1243
+ return that.workflow.expression.getParameterValue(`=${expression}`, that.runExecutionData, that.runIndex, itemIndex, that.activeNodeName, that.connectionInputData, that.mode, that.additionalKeys, that.executeData, false, {}, that.contextNodeName);
1244
+ },
1245
+ // this is legacy syntax that is not documented
1246
+ $item: (itemIndex, runIndex) => {
1247
+ const defaultReturnRunIndex = runIndex === undefined ? -1 : runIndex;
1248
+ const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData, that.siblingParameters, that.mode, that.additionalKeys, that.executeData, defaultReturnRunIndex, {}, that.contextNodeName);
1249
+ return dataProxy.getDataProxy();
1250
+ },
1251
+ $fromAI: handleFromAi,
1252
+ // Make sure mis-capitalized $fromAI is handled correctly even though we don't auto-complete it
1253
+ $fromai: handleFromAi,
1254
+ $fromAi: handleFromAi,
1255
+ // this is a legacy syntax that is not documented
1256
+ $items: (nodeName, outputIndex, runIndex) => {
1257
+ if (nodeName === undefined) {
1258
+ nodeName = that.prevNodeGetter().name;
1259
+ const node = this.workflow.nodes[nodeName];
1260
+ let result = that.connectionInputData;
1261
+ if (node.executeOnce === true) {
1262
+ result = result.slice(0, 1);
1263
+ }
1264
+ if (result.length) {
1265
+ return result;
1266
+ }
1267
+ return [];
1268
+ }
1269
+ outputIndex = outputIndex || 0;
1270
+ runIndex = runIndex === undefined ? -1 : runIndex;
1271
+ return that.getNodeExecutionData(nodeName, false, outputIndex, runIndex);
1272
+ },
1273
+ $tool: {}, // Placeholder
1274
+ $json: {}, // Placeholder
1275
+ $node: this.nodeGetter(),
1276
+ $self: this.selfGetter(),
1277
+ $parameter: this.nodeParameterGetter(this.activeNodeName),
1278
+ $rawParameter: this.nodeParameterGetter(this.activeNodeName, false),
1279
+ $prevNode: this.prevNodeGetter(),
1280
+ $runIndex: this.runIndex,
1281
+ $mode: this.mode,
1282
+ $workflow: this.workflowGetter(),
1283
+ $itemIndex: this.itemIndex,
1284
+ $now: luxon_1.DateTime.now(),
1285
+ $today: luxon_1.DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }),
1286
+ $jmesPath: jmespathWrapper,
1287
+ DateTime: luxon_1.DateTime,
1288
+ Interval: luxon_1.Interval,
1289
+ Duration: luxon_1.Duration,
1290
+ ...that.additionalKeys,
1291
+ $getPairedItem: getPairedItem,
1292
+ // deprecated
1293
+ $jmespath: jmespathWrapper,
1294
+ $position: this.itemIndex,
1295
+ $thisItem: that.connectionInputData[that.itemIndex],
1296
+ $thisItemIndex: this.itemIndex,
1297
+ $thisRunIndex: this.runIndex,
1298
+ $nodeVersion: that.workflow.getNode(that.activeNodeName)?.typeVersion,
1299
+ $nodeId: that.workflow.getNode(that.activeNodeName)?.id,
1300
+ $agentInfo: this.agentInfo(),
1301
+ $webhookId: that.workflow.getNode(that.activeNodeName)?.webhookId,
1302
+ };
1303
+ const throwOnMissingExecutionData = opts?.throwOnMissingExecutionData ?? true;
1304
+ return new Proxy(base, {
1305
+ has: () => true,
1306
+ get(target, name, receiver) {
1307
+ if (name === 'isProxy')
1308
+ return true;
1309
+ const JSON_ACCESS_KEYS = ['$data', '$json'];
1310
+ if (that.workflow.settings?.binaryMode === constants_1.BINARY_MODE_COMBINED) {
1311
+ JSON_ACCESS_KEYS.push('$item');
1312
+ }
1313
+ if (typeof name === 'string' && JSON_ACCESS_KEYS.includes(name)) {
1314
+ return that.nodeDataGetter(that.contextNodeName, true, throwOnMissingExecutionData)?.json;
1315
+ }
1316
+ if (name === '$binary') {
1317
+ return that.nodeDataGetter(that.contextNodeName, true, throwOnMissingExecutionData)
1318
+ ?.binary;
1319
+ }
1320
+ if (name === '$tool') {
1321
+ return handleTool(throwOnMissingExecutionData);
1322
+ }
1323
+ return Reflect.get(target, name, receiver);
1324
+ },
1325
+ });
1336
1326
  }
1337
- exports.WorkflowDataProxy = WorkflowDataProxy;
1338
- });
1327
+ }
1328
+ exports.WorkflowDataProxy = WorkflowDataProxy;
1339
1329
  //# sourceMappingURL=workflow-data-proxy.js.map