n8n-workflow 2.31.3 → 2.32.1

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