n8n-mcp 2.7.7

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 (375) hide show
  1. package/.env.example +79 -0
  2. package/LICENSE +21 -0
  3. package/README.md +670 -0
  4. package/data/nodes.db +0 -0
  5. package/dist/config/n8n-api.d.ts +9 -0
  6. package/dist/config/n8n-api.d.ts.map +1 -0
  7. package/dist/config/n8n-api.js +41 -0
  8. package/dist/config/n8n-api.js.map +1 -0
  9. package/dist/database/database-adapter.d.ts +32 -0
  10. package/dist/database/database-adapter.d.ts.map +1 -0
  11. package/dist/database/database-adapter.js +328 -0
  12. package/dist/database/database-adapter.js.map +1 -0
  13. package/dist/database/node-repository.d.ts +11 -0
  14. package/dist/database/node-repository.d.ts.map +1 -0
  15. package/dist/database/node-repository.js +67 -0
  16. package/dist/database/node-repository.js.map +1 -0
  17. package/dist/http-server-single-session.d.ts +21 -0
  18. package/dist/http-server-single-session.d.ts.map +1 -0
  19. package/dist/http-server-single-session.js +279 -0
  20. package/dist/http-server-single-session.js.map +1 -0
  21. package/dist/http-server.d.ts +9 -0
  22. package/dist/http-server.d.ts.map +1 -0
  23. package/dist/http-server.js +342 -0
  24. package/dist/http-server.js.map +1 -0
  25. package/dist/index.d.ts +7 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +17 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/loaders/node-loader.d.ts +11 -0
  30. package/dist/loaders/node-loader.d.ts.map +1 -0
  31. package/dist/loaders/node-loader.js +79 -0
  32. package/dist/loaders/node-loader.js.map +1 -0
  33. package/dist/mappers/docs-mapper.d.ts +6 -0
  34. package/dist/mappers/docs-mapper.d.ts.map +1 -0
  35. package/dist/mappers/docs-mapper.js +59 -0
  36. package/dist/mappers/docs-mapper.js.map +1 -0
  37. package/dist/mcp/absolute-minimal.d.ts +4 -0
  38. package/dist/mcp/absolute-minimal.d.ts.map +1 -0
  39. package/dist/mcp/absolute-minimal.js +34 -0
  40. package/dist/mcp/absolute-minimal.js.map +1 -0
  41. package/dist/mcp/fixed-protocol.d.ts +17 -0
  42. package/dist/mcp/fixed-protocol.d.ts.map +1 -0
  43. package/dist/mcp/fixed-protocol.js +162 -0
  44. package/dist/mcp/fixed-protocol.js.map +1 -0
  45. package/dist/mcp/handlers-documentation.d.ts +18 -0
  46. package/dist/mcp/handlers-documentation.d.ts.map +1 -0
  47. package/dist/mcp/handlers-documentation.js +113 -0
  48. package/dist/mcp/handlers-documentation.js.map +1 -0
  49. package/dist/mcp/handlers-n8n-manager.d.ts +21 -0
  50. package/dist/mcp/handlers-n8n-manager.d.ts.map +1 -0
  51. package/dist/mcp/handlers-n8n-manager.js +827 -0
  52. package/dist/mcp/handlers-n8n-manager.js.map +1 -0
  53. package/dist/mcp/handlers-workflow-diff.d.ts +3 -0
  54. package/dist/mcp/handlers-workflow-diff.d.ts.map +1 -0
  55. package/dist/mcp/handlers-workflow-diff.js +125 -0
  56. package/dist/mcp/handlers-workflow-diff.js.map +1 -0
  57. package/dist/mcp/index.d.ts +3 -0
  58. package/dist/mcp/index.d.ts.map +1 -0
  59. package/dist/mcp/index.js +106 -0
  60. package/dist/mcp/index.js.map +1 -0
  61. package/dist/mcp/minimal-test.d.ts +3 -0
  62. package/dist/mcp/minimal-test.d.ts.map +1 -0
  63. package/dist/mcp/minimal-test.js +83 -0
  64. package/dist/mcp/minimal-test.js.map +1 -0
  65. package/dist/mcp/server.d.ts +42 -0
  66. package/dist/mcp/server.d.ts.map +1 -0
  67. package/dist/mcp/server.js +1258 -0
  68. package/dist/mcp/server.js.map +1 -0
  69. package/dist/mcp/stderr-test.d.ts +2 -0
  70. package/dist/mcp/stderr-test.d.ts.map +1 -0
  71. package/dist/mcp/stderr-test.js +32 -0
  72. package/dist/mcp/stderr-test.js.map +1 -0
  73. package/dist/mcp/stdio-wrapper.d.ts +3 -0
  74. package/dist/mcp/stdio-wrapper.d.ts.map +1 -0
  75. package/dist/mcp/stdio-wrapper.js +52 -0
  76. package/dist/mcp/stdio-wrapper.js.map +1 -0
  77. package/dist/mcp/tools-documentation.d.ts +34 -0
  78. package/dist/mcp/tools-documentation.d.ts.map +1 -0
  79. package/dist/mcp/tools-documentation.js +609 -0
  80. package/dist/mcp/tools-documentation.js.map +1 -0
  81. package/dist/mcp/tools-n8n-manager.d.ts +3 -0
  82. package/dist/mcp/tools-n8n-manager.d.ts.map +1 -0
  83. package/dist/mcp/tools-n8n-manager.js +496 -0
  84. package/dist/mcp/tools-n8n-manager.js.map +1 -0
  85. package/dist/mcp/tools.d.ts +3 -0
  86. package/dist/mcp/tools.d.ts.map +1 -0
  87. package/dist/mcp/tools.js +405 -0
  88. package/dist/mcp/tools.js.map +1 -0
  89. package/dist/mcp/ultra-minimal.d.ts +8 -0
  90. package/dist/mcp/ultra-minimal.d.ts.map +1 -0
  91. package/dist/mcp/ultra-minimal.js +93 -0
  92. package/dist/mcp/ultra-minimal.js.map +1 -0
  93. package/dist/mcp/working-test.d.ts +3 -0
  94. package/dist/mcp/working-test.d.ts.map +1 -0
  95. package/dist/mcp/working-test.js +48 -0
  96. package/dist/mcp/working-test.js.map +1 -0
  97. package/dist/mcp/wrapper.sh +28 -0
  98. package/dist/mcp-engine.d.ts +32 -0
  99. package/dist/mcp-engine.d.ts.map +1 -0
  100. package/dist/mcp-engine.js +63 -0
  101. package/dist/mcp-engine.js.map +1 -0
  102. package/dist/n8n/MCPApi.credentials.d.ts +8 -0
  103. package/dist/n8n/MCPApi.credentials.d.ts.map +1 -0
  104. package/dist/n8n/MCPApi.credentials.js +53 -0
  105. package/dist/n8n/MCPApi.credentials.js.map +1 -0
  106. package/dist/n8n/MCPNode.node.d.ts +13 -0
  107. package/dist/n8n/MCPNode.node.d.ts.map +1 -0
  108. package/dist/n8n/MCPNode.node.js +260 -0
  109. package/dist/n8n/MCPNode.node.js.map +1 -0
  110. package/dist/parsers/node-parser.d.ts +30 -0
  111. package/dist/parsers/node-parser.d.ts.map +1 -0
  112. package/dist/parsers/node-parser.js +152 -0
  113. package/dist/parsers/node-parser.js.map +1 -0
  114. package/dist/parsers/property-extractor.d.ts +10 -0
  115. package/dist/parsers/property-extractor.d.ts.map +1 -0
  116. package/dist/parsers/property-extractor.js +155 -0
  117. package/dist/parsers/property-extractor.js.map +1 -0
  118. package/dist/parsers/simple-parser.d.ts +24 -0
  119. package/dist/parsers/simple-parser.d.ts.map +1 -0
  120. package/dist/parsers/simple-parser.js +160 -0
  121. package/dist/parsers/simple-parser.js.map +1 -0
  122. package/dist/scripts/debug-n8n-auth.d.ts +3 -0
  123. package/dist/scripts/debug-n8n-auth.d.ts.map +1 -0
  124. package/dist/scripts/debug-n8n-auth.js +97 -0
  125. package/dist/scripts/debug-n8n-auth.js.map +1 -0
  126. package/dist/scripts/debug-node.d.ts +3 -0
  127. package/dist/scripts/debug-node.d.ts.map +1 -0
  128. package/dist/scripts/debug-node.js +59 -0
  129. package/dist/scripts/debug-node.js.map +1 -0
  130. package/dist/scripts/extract-from-docker.d.ts +3 -0
  131. package/dist/scripts/extract-from-docker.d.ts.map +1 -0
  132. package/dist/scripts/extract-from-docker.js +210 -0
  133. package/dist/scripts/extract-from-docker.js.map +1 -0
  134. package/dist/scripts/fetch-templates-robust.d.ts +4 -0
  135. package/dist/scripts/fetch-templates-robust.d.ts.map +1 -0
  136. package/dist/scripts/fetch-templates-robust.js +126 -0
  137. package/dist/scripts/fetch-templates-robust.js.map +1 -0
  138. package/dist/scripts/fetch-templates.d.ts +4 -0
  139. package/dist/scripts/fetch-templates.d.ts.map +1 -0
  140. package/dist/scripts/fetch-templates.js +94 -0
  141. package/dist/scripts/fetch-templates.js.map +1 -0
  142. package/dist/scripts/rebuild-database.d.ts +4 -0
  143. package/dist/scripts/rebuild-database.d.ts.map +1 -0
  144. package/dist/scripts/rebuild-database.js +95 -0
  145. package/dist/scripts/rebuild-database.js.map +1 -0
  146. package/dist/scripts/rebuild-optimized.d.ts +3 -0
  147. package/dist/scripts/rebuild-optimized.d.ts.map +1 -0
  148. package/dist/scripts/rebuild-optimized.js +198 -0
  149. package/dist/scripts/rebuild-optimized.js.map +1 -0
  150. package/dist/scripts/rebuild.d.ts +3 -0
  151. package/dist/scripts/rebuild.d.ts.map +1 -0
  152. package/dist/scripts/rebuild.js +163 -0
  153. package/dist/scripts/rebuild.js.map +1 -0
  154. package/dist/scripts/sanitize-templates.d.ts +3 -0
  155. package/dist/scripts/sanitize-templates.d.ts.map +1 -0
  156. package/dist/scripts/sanitize-templates.js +56 -0
  157. package/dist/scripts/sanitize-templates.js.map +1 -0
  158. package/dist/scripts/test-ai-workflow-validation.d.ts +3 -0
  159. package/dist/scripts/test-ai-workflow-validation.d.ts.map +1 -0
  160. package/dist/scripts/test-ai-workflow-validation.js +191 -0
  161. package/dist/scripts/test-ai-workflow-validation.js.map +1 -0
  162. package/dist/scripts/test-api-headers.d.ts +3 -0
  163. package/dist/scripts/test-api-headers.d.ts.map +1 -0
  164. package/dist/scripts/test-api-headers.js +35 -0
  165. package/dist/scripts/test-api-headers.js.map +1 -0
  166. package/dist/scripts/test-docker-config-simulation.d.ts +3 -0
  167. package/dist/scripts/test-docker-config-simulation.d.ts.map +1 -0
  168. package/dist/scripts/test-docker-config-simulation.js +74 -0
  169. package/dist/scripts/test-docker-config-simulation.js.map +1 -0
  170. package/dist/scripts/test-enhanced-validation.d.ts +3 -0
  171. package/dist/scripts/test-enhanced-validation.d.ts.map +1 -0
  172. package/dist/scripts/test-enhanced-validation.js +117 -0
  173. package/dist/scripts/test-enhanced-validation.js.map +1 -0
  174. package/dist/scripts/test-lazy-config.d.ts +3 -0
  175. package/dist/scripts/test-lazy-config.d.ts.map +1 -0
  176. package/dist/scripts/test-lazy-config.js +60 -0
  177. package/dist/scripts/test-lazy-config.js.map +1 -0
  178. package/dist/scripts/test-limited-results.d.ts +3 -0
  179. package/dist/scripts/test-limited-results.d.ts.map +1 -0
  180. package/dist/scripts/test-limited-results.js +76 -0
  181. package/dist/scripts/test-limited-results.js.map +1 -0
  182. package/dist/scripts/test-mcp-n8n-update-partial.d.ts +3 -0
  183. package/dist/scripts/test-mcp-n8n-update-partial.d.ts.map +1 -0
  184. package/dist/scripts/test-mcp-n8n-update-partial.js +138 -0
  185. package/dist/scripts/test-mcp-n8n-update-partial.js.map +1 -0
  186. package/dist/scripts/test-mcp-tools.d.ts +3 -0
  187. package/dist/scripts/test-mcp-tools.d.ts.map +1 -0
  188. package/dist/scripts/test-mcp-tools.js +36 -0
  189. package/dist/scripts/test-mcp-tools.js.map +1 -0
  190. package/dist/scripts/test-n8n-manager-integration.d.ts +3 -0
  191. package/dist/scripts/test-n8n-manager-integration.d.ts.map +1 -0
  192. package/dist/scripts/test-n8n-manager-integration.js +122 -0
  193. package/dist/scripts/test-n8n-manager-integration.js.map +1 -0
  194. package/dist/scripts/test-n8n-validate-workflow.d.ts +3 -0
  195. package/dist/scripts/test-n8n-validate-workflow.d.ts.map +1 -0
  196. package/dist/scripts/test-n8n-validate-workflow.js +125 -0
  197. package/dist/scripts/test-n8n-validate-workflow.js.map +1 -0
  198. package/dist/scripts/test-nodes.d.ts +3 -0
  199. package/dist/scripts/test-nodes.d.ts.map +1 -0
  200. package/dist/scripts/test-nodes.js +91 -0
  201. package/dist/scripts/test-nodes.js.map +1 -0
  202. package/dist/scripts/test-single-workflow.d.ts +3 -0
  203. package/dist/scripts/test-single-workflow.d.ts.map +1 -0
  204. package/dist/scripts/test-single-workflow.js +112 -0
  205. package/dist/scripts/test-single-workflow.js.map +1 -0
  206. package/dist/scripts/test-template-validation.d.ts +3 -0
  207. package/dist/scripts/test-template-validation.d.ts.map +1 -0
  208. package/dist/scripts/test-template-validation.js +142 -0
  209. package/dist/scripts/test-template-validation.js.map +1 -0
  210. package/dist/scripts/test-templates.d.ts +4 -0
  211. package/dist/scripts/test-templates.d.ts.map +1 -0
  212. package/dist/scripts/test-templates.js +99 -0
  213. package/dist/scripts/test-templates.js.map +1 -0
  214. package/dist/scripts/test-transactional-diff.d.ts +2 -0
  215. package/dist/scripts/test-transactional-diff.d.ts.map +1 -0
  216. package/dist/scripts/test-transactional-diff.js +240 -0
  217. package/dist/scripts/test-transactional-diff.js.map +1 -0
  218. package/dist/scripts/test-update-partial-debug.d.ts +3 -0
  219. package/dist/scripts/test-update-partial-debug.d.ts.map +1 -0
  220. package/dist/scripts/test-update-partial-debug.js +92 -0
  221. package/dist/scripts/test-update-partial-debug.js.map +1 -0
  222. package/dist/scripts/test-version-extraction.d.ts +2 -0
  223. package/dist/scripts/test-version-extraction.d.ts.map +1 -0
  224. package/dist/scripts/test-version-extraction.js +74 -0
  225. package/dist/scripts/test-version-extraction.js.map +1 -0
  226. package/dist/scripts/test-workflow-diff.d.ts +3 -0
  227. package/dist/scripts/test-workflow-diff.d.ts.map +1 -0
  228. package/dist/scripts/test-workflow-diff.js +328 -0
  229. package/dist/scripts/test-workflow-diff.js.map +1 -0
  230. package/dist/scripts/test-workflow-validation.d.ts +3 -0
  231. package/dist/scripts/test-workflow-validation.d.ts.map +1 -0
  232. package/dist/scripts/test-workflow-validation.js +238 -0
  233. package/dist/scripts/test-workflow-validation.js.map +1 -0
  234. package/dist/scripts/validate.d.ts +3 -0
  235. package/dist/scripts/validate.d.ts.map +1 -0
  236. package/dist/scripts/validate.js +121 -0
  237. package/dist/scripts/validate.js.map +1 -0
  238. package/dist/scripts/validation-summary.d.ts +3 -0
  239. package/dist/scripts/validation-summary.d.ts.map +1 -0
  240. package/dist/scripts/validation-summary.js +135 -0
  241. package/dist/scripts/validation-summary.js.map +1 -0
  242. package/dist/services/config-validator.d.ts +39 -0
  243. package/dist/services/config-validator.d.ts.map +1 -0
  244. package/dist/services/config-validator.js +376 -0
  245. package/dist/services/config-validator.js.map +1 -0
  246. package/dist/services/enhanced-config-validator.d.ts +38 -0
  247. package/dist/services/enhanced-config-validator.d.ts.map +1 -0
  248. package/dist/services/enhanced-config-validator.js +300 -0
  249. package/dist/services/enhanced-config-validator.js.map +1 -0
  250. package/dist/services/example-generator.d.ts +14 -0
  251. package/dist/services/example-generator.d.ts.map +1 -0
  252. package/dist/services/example-generator.js +556 -0
  253. package/dist/services/example-generator.js.map +1 -0
  254. package/dist/services/expression-validator.d.ts +27 -0
  255. package/dist/services/expression-validator.d.ts.map +1 -0
  256. package/dist/services/expression-validator.js +163 -0
  257. package/dist/services/expression-validator.js.map +1 -0
  258. package/dist/services/n8n-api-client.d.ts +39 -0
  259. package/dist/services/n8n-api-client.d.ts.map +1 -0
  260. package/dist/services/n8n-api-client.js +326 -0
  261. package/dist/services/n8n-api-client.js.map +1 -0
  262. package/dist/services/n8n-validation.d.ts +127 -0
  263. package/dist/services/n8n-validation.d.ts.map +1 -0
  264. package/dist/services/n8n-validation.js +238 -0
  265. package/dist/services/n8n-validation.js.map +1 -0
  266. package/dist/services/node-documentation-service.d.ts +70 -0
  267. package/dist/services/node-documentation-service.d.ts.map +1 -0
  268. package/dist/services/node-documentation-service.js +518 -0
  269. package/dist/services/node-documentation-service.js.map +1 -0
  270. package/dist/services/node-specific-validators.d.ts +28 -0
  271. package/dist/services/node-specific-validators.d.ts.map +1 -0
  272. package/dist/services/node-specific-validators.js +666 -0
  273. package/dist/services/node-specific-validators.js.map +1 -0
  274. package/dist/services/property-dependencies.d.ts +36 -0
  275. package/dist/services/property-dependencies.d.ts.map +1 -0
  276. package/dist/services/property-dependencies.js +168 -0
  277. package/dist/services/property-dependencies.js.map +1 -0
  278. package/dist/services/property-filter.d.ts +39 -0
  279. package/dist/services/property-filter.d.ts.map +1 -0
  280. package/dist/services/property-filter.js +362 -0
  281. package/dist/services/property-filter.js.map +1 -0
  282. package/dist/services/task-templates.d.ts +26 -0
  283. package/dist/services/task-templates.d.ts.map +1 -0
  284. package/dist/services/task-templates.js +555 -0
  285. package/dist/services/task-templates.js.map +1 -0
  286. package/dist/services/workflow-diff-engine.d.ts +31 -0
  287. package/dist/services/workflow-diff-engine.d.ts.map +1 -0
  288. package/dist/services/workflow-diff-engine.js +478 -0
  289. package/dist/services/workflow-diff-engine.js.map +1 -0
  290. package/dist/services/workflow-validator.d.ts +87 -0
  291. package/dist/services/workflow-validator.d.ts.map +1 -0
  292. package/dist/services/workflow-validator.js +656 -0
  293. package/dist/services/workflow-validator.js.map +1 -0
  294. package/dist/templates/template-fetcher.d.ts +41 -0
  295. package/dist/templates/template-fetcher.d.ts.map +1 -0
  296. package/dist/templates/template-fetcher.js +94 -0
  297. package/dist/templates/template-fetcher.js.map +1 -0
  298. package/dist/templates/template-repository.d.ts +34 -0
  299. package/dist/templates/template-repository.d.ts.map +1 -0
  300. package/dist/templates/template-repository.js +121 -0
  301. package/dist/templates/template-repository.js.map +1 -0
  302. package/dist/templates/template-service.d.ts +31 -0
  303. package/dist/templates/template-service.d.ts.map +1 -0
  304. package/dist/templates/template-service.js +131 -0
  305. package/dist/templates/template-service.js.map +1 -0
  306. package/dist/types/index.d.ts +31 -0
  307. package/dist/types/index.d.ts.map +1 -0
  308. package/dist/types/index.js +3 -0
  309. package/dist/types/index.js.map +1 -0
  310. package/dist/types/n8n-api.d.ts +241 -0
  311. package/dist/types/n8n-api.d.ts.map +1 -0
  312. package/dist/types/n8n-api.js +10 -0
  313. package/dist/types/n8n-api.js.map +1 -0
  314. package/dist/types/workflow-diff.d.ts +113 -0
  315. package/dist/types/workflow-diff.d.ts.map +1 -0
  316. package/dist/types/workflow-diff.js +15 -0
  317. package/dist/types/workflow-diff.js.map +1 -0
  318. package/dist/utils/auth.d.ts +12 -0
  319. package/dist/utils/auth.d.ts.map +1 -0
  320. package/dist/utils/auth.js +66 -0
  321. package/dist/utils/auth.js.map +1 -0
  322. package/dist/utils/bridge.d.ts +12 -0
  323. package/dist/utils/bridge.d.ts.map +1 -0
  324. package/dist/utils/bridge.js +127 -0
  325. package/dist/utils/bridge.js.map +1 -0
  326. package/dist/utils/console-manager.d.ts +10 -0
  327. package/dist/utils/console-manager.d.ts.map +1 -0
  328. package/dist/utils/console-manager.js +63 -0
  329. package/dist/utils/console-manager.js.map +1 -0
  330. package/dist/utils/documentation-fetcher.d.ts +2 -0
  331. package/dist/utils/documentation-fetcher.d.ts.map +1 -0
  332. package/dist/utils/documentation-fetcher.js +18 -0
  333. package/dist/utils/documentation-fetcher.js.map +1 -0
  334. package/dist/utils/enhanced-documentation-fetcher.d.ts +73 -0
  335. package/dist/utils/enhanced-documentation-fetcher.d.ts.map +1 -0
  336. package/dist/utils/enhanced-documentation-fetcher.js +397 -0
  337. package/dist/utils/enhanced-documentation-fetcher.js.map +1 -0
  338. package/dist/utils/error-handler.d.ts +24 -0
  339. package/dist/utils/error-handler.d.ts.map +1 -0
  340. package/dist/utils/error-handler.js +84 -0
  341. package/dist/utils/error-handler.js.map +1 -0
  342. package/dist/utils/example-generator.d.ts +8 -0
  343. package/dist/utils/example-generator.d.ts.map +1 -0
  344. package/dist/utils/example-generator.js +106 -0
  345. package/dist/utils/example-generator.js.map +1 -0
  346. package/dist/utils/logger.d.ts +32 -0
  347. package/dist/utils/logger.d.ts.map +1 -0
  348. package/dist/utils/logger.js +97 -0
  349. package/dist/utils/logger.js.map +1 -0
  350. package/dist/utils/mcp-client.d.ts +21 -0
  351. package/dist/utils/mcp-client.d.ts.map +1 -0
  352. package/dist/utils/mcp-client.js +96 -0
  353. package/dist/utils/mcp-client.js.map +1 -0
  354. package/dist/utils/n8n-errors.d.ts +25 -0
  355. package/dist/utils/n8n-errors.d.ts.map +1 -0
  356. package/dist/utils/n8n-errors.js +129 -0
  357. package/dist/utils/n8n-errors.js.map +1 -0
  358. package/dist/utils/node-source-extractor.d.ts +21 -0
  359. package/dist/utils/node-source-extractor.d.ts.map +1 -0
  360. package/dist/utils/node-source-extractor.js +377 -0
  361. package/dist/utils/node-source-extractor.js.map +1 -0
  362. package/dist/utils/simple-cache.d.ts +8 -0
  363. package/dist/utils/simple-cache.d.ts.map +1 -0
  364. package/dist/utils/simple-cache.js +34 -0
  365. package/dist/utils/simple-cache.js.map +1 -0
  366. package/dist/utils/template-sanitizer.d.ts +21 -0
  367. package/dist/utils/template-sanitizer.d.ts.map +1 -0
  368. package/dist/utils/template-sanitizer.js +108 -0
  369. package/dist/utils/template-sanitizer.js.map +1 -0
  370. package/dist/utils/version.d.ts +2 -0
  371. package/dist/utils/version.d.ts.map +1 -0
  372. package/dist/utils/version.js +18 -0
  373. package/dist/utils/version.js.map +1 -0
  374. package/package.json +100 -0
  375. package/package.runtime.json +19 -0
@@ -0,0 +1,656 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowValidator = void 0;
4
+ const expression_validator_1 = require("./expression-validator");
5
+ const logger_1 = require("../utils/logger");
6
+ const logger = new logger_1.Logger({ prefix: '[WorkflowValidator]' });
7
+ class WorkflowValidator {
8
+ constructor(nodeRepository, nodeValidator) {
9
+ this.nodeRepository = nodeRepository;
10
+ this.nodeValidator = nodeValidator;
11
+ }
12
+ async validateWorkflow(workflow, options = {}) {
13
+ const { validateNodes = true, validateConnections = true, validateExpressions = true, profile = 'runtime' } = options;
14
+ const result = {
15
+ valid: true,
16
+ errors: [],
17
+ warnings: [],
18
+ statistics: {
19
+ totalNodes: workflow.nodes.length,
20
+ enabledNodes: workflow.nodes.filter(n => !n.disabled).length,
21
+ triggerNodes: 0,
22
+ validConnections: 0,
23
+ invalidConnections: 0,
24
+ expressionsValidated: 0,
25
+ },
26
+ suggestions: []
27
+ };
28
+ try {
29
+ this.validateWorkflowStructure(workflow, result);
30
+ if (validateNodes) {
31
+ await this.validateAllNodes(workflow, result, profile);
32
+ }
33
+ if (validateConnections) {
34
+ this.validateConnections(workflow, result);
35
+ }
36
+ if (validateExpressions) {
37
+ this.validateExpressions(workflow, result);
38
+ }
39
+ this.checkWorkflowPatterns(workflow, result);
40
+ this.generateSuggestions(workflow, result);
41
+ }
42
+ catch (error) {
43
+ logger.error('Error validating workflow:', error);
44
+ result.errors.push({
45
+ type: 'error',
46
+ message: `Workflow validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`
47
+ });
48
+ }
49
+ result.valid = result.errors.length === 0;
50
+ return result;
51
+ }
52
+ validateWorkflowStructure(workflow, result) {
53
+ if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
54
+ result.errors.push({
55
+ type: 'error',
56
+ message: 'Workflow must have a nodes array'
57
+ });
58
+ return;
59
+ }
60
+ if (!workflow.connections || typeof workflow.connections !== 'object') {
61
+ result.errors.push({
62
+ type: 'error',
63
+ message: 'Workflow must have a connections object'
64
+ });
65
+ return;
66
+ }
67
+ if (workflow.nodes.length === 0) {
68
+ result.errors.push({
69
+ type: 'error',
70
+ message: 'Workflow has no nodes'
71
+ });
72
+ return;
73
+ }
74
+ if (workflow.nodes.length === 1) {
75
+ const singleNode = workflow.nodes[0];
76
+ const normalizedType = singleNode.type.replace('n8n-nodes-base.', 'nodes-base.');
77
+ const isWebhook = normalizedType === 'nodes-base.webhook' ||
78
+ normalizedType === 'nodes-base.webhookTrigger';
79
+ if (!isWebhook) {
80
+ result.errors.push({
81
+ type: 'error',
82
+ message: 'Single-node workflows are only valid for webhook endpoints. Add at least one more connected node to create a functional workflow.'
83
+ });
84
+ }
85
+ else if (Object.keys(workflow.connections).length === 0) {
86
+ result.warnings.push({
87
+ type: 'warning',
88
+ message: 'Webhook node has no connections. Consider adding nodes to process the webhook data.'
89
+ });
90
+ }
91
+ }
92
+ if (workflow.nodes.length > 1) {
93
+ const hasEnabledNodes = workflow.nodes.some(n => !n.disabled);
94
+ const hasConnections = Object.keys(workflow.connections).length > 0;
95
+ if (hasEnabledNodes && !hasConnections) {
96
+ result.errors.push({
97
+ type: 'error',
98
+ message: 'Multi-node workflow has no connections. Nodes must be connected to create a workflow. Use connections: { "Source Node Name": { "main": [[{ "node": "Target Node Name", "type": "main", "index": 0 }]] } }'
99
+ });
100
+ }
101
+ }
102
+ const nodeNames = new Set();
103
+ const nodeIds = new Set();
104
+ for (const node of workflow.nodes) {
105
+ if (nodeNames.has(node.name)) {
106
+ result.errors.push({
107
+ type: 'error',
108
+ nodeId: node.id,
109
+ nodeName: node.name,
110
+ message: `Duplicate node name: "${node.name}"`
111
+ });
112
+ }
113
+ nodeNames.add(node.name);
114
+ if (nodeIds.has(node.id)) {
115
+ result.errors.push({
116
+ type: 'error',
117
+ nodeId: node.id,
118
+ message: `Duplicate node ID: "${node.id}"`
119
+ });
120
+ }
121
+ nodeIds.add(node.id);
122
+ }
123
+ const triggerNodes = workflow.nodes.filter(n => {
124
+ const normalizedType = n.type.replace('n8n-nodes-base.', 'nodes-base.');
125
+ return normalizedType.toLowerCase().includes('trigger') ||
126
+ normalizedType.toLowerCase().includes('webhook') ||
127
+ normalizedType === 'nodes-base.start' ||
128
+ normalizedType === 'nodes-base.manualTrigger' ||
129
+ normalizedType === 'nodes-base.formTrigger';
130
+ });
131
+ result.statistics.triggerNodes = triggerNodes.length;
132
+ if (triggerNodes.length === 0 && workflow.nodes.filter(n => !n.disabled).length > 0) {
133
+ result.warnings.push({
134
+ type: 'warning',
135
+ message: 'Workflow has no trigger nodes. It can only be executed manually.'
136
+ });
137
+ }
138
+ }
139
+ async validateAllNodes(workflow, result, profile) {
140
+ for (const node of workflow.nodes) {
141
+ if (node.disabled)
142
+ continue;
143
+ try {
144
+ if (node.type.startsWith('nodes-base.')) {
145
+ const correctType = node.type.replace('nodes-base.', 'n8n-nodes-base.');
146
+ result.errors.push({
147
+ type: 'error',
148
+ nodeId: node.id,
149
+ nodeName: node.name,
150
+ message: `Invalid node type: "${node.type}". Use "${correctType}" instead. Node types in workflows must use the full package name.`
151
+ });
152
+ continue;
153
+ }
154
+ let nodeInfo = this.nodeRepository.getNode(node.type);
155
+ if (!nodeInfo) {
156
+ let normalizedType = node.type;
157
+ if (node.type.startsWith('n8n-nodes-base.')) {
158
+ normalizedType = node.type.replace('n8n-nodes-base.', 'nodes-base.');
159
+ nodeInfo = this.nodeRepository.getNode(normalizedType);
160
+ }
161
+ else if (node.type.startsWith('@n8n/n8n-nodes-langchain.')) {
162
+ normalizedType = node.type.replace('@n8n/n8n-nodes-langchain.', 'nodes-langchain.');
163
+ nodeInfo = this.nodeRepository.getNode(normalizedType);
164
+ }
165
+ }
166
+ if (!nodeInfo) {
167
+ let suggestion = '';
168
+ if (node.type.startsWith('nodes-base.')) {
169
+ const withPrefix = node.type.replace('nodes-base.', 'n8n-nodes-base.');
170
+ const exists = this.nodeRepository.getNode(withPrefix) ||
171
+ this.nodeRepository.getNode(withPrefix.replace('n8n-nodes-base.', 'nodes-base.'));
172
+ if (exists) {
173
+ suggestion = ` Did you mean "n8n-nodes-base.${node.type.substring(11)}"?`;
174
+ }
175
+ }
176
+ else if (!node.type.includes('.')) {
177
+ const commonNodes = [
178
+ 'webhook', 'httpRequest', 'set', 'code', 'manualTrigger',
179
+ 'scheduleTrigger', 'emailSend', 'slack', 'discord'
180
+ ];
181
+ if (commonNodes.includes(node.type)) {
182
+ suggestion = ` Did you mean "n8n-nodes-base.${node.type}"?`;
183
+ }
184
+ }
185
+ if (!suggestion) {
186
+ const similarNodes = this.findSimilarNodeTypes(node.type);
187
+ if (similarNodes.length > 0) {
188
+ suggestion = ` Did you mean: ${similarNodes.map(n => `"${n}"`).join(', ')}?`;
189
+ }
190
+ }
191
+ result.errors.push({
192
+ type: 'error',
193
+ nodeId: node.id,
194
+ nodeName: node.name,
195
+ message: `Unknown node type: "${node.type}".${suggestion} Node types must include the package prefix (e.g., "n8n-nodes-base.webhook", not "webhook" or "nodes-base.webhook").`
196
+ });
197
+ continue;
198
+ }
199
+ if (nodeInfo.isVersioned) {
200
+ if (!node.typeVersion) {
201
+ result.errors.push({
202
+ type: 'error',
203
+ nodeId: node.id,
204
+ nodeName: node.name,
205
+ message: `Missing required property 'typeVersion'. Add typeVersion: ${nodeInfo.version || 1}`
206
+ });
207
+ }
208
+ else if (typeof node.typeVersion !== 'number' || node.typeVersion < 1) {
209
+ result.errors.push({
210
+ type: 'error',
211
+ nodeId: node.id,
212
+ nodeName: node.name,
213
+ message: `Invalid typeVersion: ${node.typeVersion}. Must be a positive number`
214
+ });
215
+ }
216
+ else if (nodeInfo.version && node.typeVersion < nodeInfo.version) {
217
+ result.warnings.push({
218
+ type: 'warning',
219
+ nodeId: node.id,
220
+ nodeName: node.name,
221
+ message: `Outdated typeVersion: ${node.typeVersion}. Latest is ${nodeInfo.version}`
222
+ });
223
+ }
224
+ else if (nodeInfo.version && node.typeVersion > nodeInfo.version) {
225
+ result.errors.push({
226
+ type: 'error',
227
+ nodeId: node.id,
228
+ nodeName: node.name,
229
+ message: `typeVersion ${node.typeVersion} exceeds maximum supported version ${nodeInfo.version}`
230
+ });
231
+ }
232
+ }
233
+ const nodeValidation = this.nodeValidator.validateWithMode(node.type, node.parameters, nodeInfo.properties || [], 'operation', profile);
234
+ nodeValidation.errors.forEach((error) => {
235
+ result.errors.push({
236
+ type: 'error',
237
+ nodeId: node.id,
238
+ nodeName: node.name,
239
+ message: error
240
+ });
241
+ });
242
+ nodeValidation.warnings.forEach((warning) => {
243
+ result.warnings.push({
244
+ type: 'warning',
245
+ nodeId: node.id,
246
+ nodeName: node.name,
247
+ message: warning
248
+ });
249
+ });
250
+ }
251
+ catch (error) {
252
+ result.errors.push({
253
+ type: 'error',
254
+ nodeId: node.id,
255
+ nodeName: node.name,
256
+ message: `Failed to validate node: ${error instanceof Error ? error.message : 'Unknown error'}`
257
+ });
258
+ }
259
+ }
260
+ }
261
+ validateConnections(workflow, result) {
262
+ const nodeMap = new Map(workflow.nodes.map(n => [n.name, n]));
263
+ const nodeIdMap = new Map(workflow.nodes.map(n => [n.id, n]));
264
+ for (const [sourceName, outputs] of Object.entries(workflow.connections)) {
265
+ const sourceNode = nodeMap.get(sourceName);
266
+ if (!sourceNode) {
267
+ const nodeById = nodeIdMap.get(sourceName);
268
+ if (nodeById) {
269
+ result.errors.push({
270
+ type: 'error',
271
+ nodeId: nodeById.id,
272
+ nodeName: nodeById.name,
273
+ message: `Connection uses node ID '${sourceName}' instead of node name '${nodeById.name}'. In n8n, connections must use node names, not IDs.`
274
+ });
275
+ }
276
+ else {
277
+ result.errors.push({
278
+ type: 'error',
279
+ message: `Connection from non-existent node: "${sourceName}"`
280
+ });
281
+ }
282
+ result.statistics.invalidConnections++;
283
+ continue;
284
+ }
285
+ if (outputs.main) {
286
+ this.validateConnectionOutputs(sourceName, outputs.main, nodeMap, nodeIdMap, result, 'main');
287
+ }
288
+ if (outputs.error) {
289
+ this.validateConnectionOutputs(sourceName, outputs.error, nodeMap, nodeIdMap, result, 'error');
290
+ }
291
+ if (outputs.ai_tool) {
292
+ this.validateConnectionOutputs(sourceName, outputs.ai_tool, nodeMap, nodeIdMap, result, 'ai_tool');
293
+ }
294
+ }
295
+ const connectedNodes = new Set();
296
+ Object.keys(workflow.connections).forEach(name => connectedNodes.add(name));
297
+ Object.values(workflow.connections).forEach(outputs => {
298
+ if (outputs.main) {
299
+ outputs.main.flat().forEach(conn => {
300
+ if (conn)
301
+ connectedNodes.add(conn.node);
302
+ });
303
+ }
304
+ if (outputs.error) {
305
+ outputs.error.flat().forEach(conn => {
306
+ if (conn)
307
+ connectedNodes.add(conn.node);
308
+ });
309
+ }
310
+ if (outputs.ai_tool) {
311
+ outputs.ai_tool.flat().forEach(conn => {
312
+ if (conn)
313
+ connectedNodes.add(conn.node);
314
+ });
315
+ }
316
+ });
317
+ for (const node of workflow.nodes) {
318
+ if (node.disabled)
319
+ continue;
320
+ const normalizedType = node.type.replace('n8n-nodes-base.', 'nodes-base.');
321
+ const isTrigger = normalizedType.toLowerCase().includes('trigger') ||
322
+ normalizedType.toLowerCase().includes('webhook') ||
323
+ normalizedType === 'nodes-base.start' ||
324
+ normalizedType === 'nodes-base.manualTrigger' ||
325
+ normalizedType === 'nodes-base.formTrigger';
326
+ if (!connectedNodes.has(node.name) && !isTrigger) {
327
+ result.warnings.push({
328
+ type: 'warning',
329
+ nodeId: node.id,
330
+ nodeName: node.name,
331
+ message: 'Node is not connected to any other nodes'
332
+ });
333
+ }
334
+ }
335
+ if (this.hasCycle(workflow)) {
336
+ result.errors.push({
337
+ type: 'error',
338
+ message: 'Workflow contains a cycle (infinite loop)'
339
+ });
340
+ }
341
+ }
342
+ validateConnectionOutputs(sourceName, outputs, nodeMap, nodeIdMap, result, outputType) {
343
+ outputs.forEach((outputConnections, outputIndex) => {
344
+ if (!outputConnections)
345
+ return;
346
+ outputConnections.forEach(connection => {
347
+ const targetNode = nodeMap.get(connection.node);
348
+ if (!targetNode) {
349
+ const nodeById = nodeIdMap.get(connection.node);
350
+ if (nodeById) {
351
+ result.errors.push({
352
+ type: 'error',
353
+ nodeId: nodeById.id,
354
+ nodeName: nodeById.name,
355
+ message: `Connection target uses node ID '${connection.node}' instead of node name '${nodeById.name}' (from ${sourceName}). In n8n, connections must use node names, not IDs.`
356
+ });
357
+ }
358
+ else {
359
+ result.errors.push({
360
+ type: 'error',
361
+ message: `Connection to non-existent node: "${connection.node}" from "${sourceName}"`
362
+ });
363
+ }
364
+ result.statistics.invalidConnections++;
365
+ }
366
+ else if (targetNode.disabled) {
367
+ result.warnings.push({
368
+ type: 'warning',
369
+ message: `Connection to disabled node: "${connection.node}" from "${sourceName}"`
370
+ });
371
+ }
372
+ else {
373
+ result.statistics.validConnections++;
374
+ if (outputType === 'ai_tool') {
375
+ this.validateAIToolConnection(sourceName, targetNode, result);
376
+ }
377
+ }
378
+ });
379
+ });
380
+ }
381
+ validateAIToolConnection(sourceName, targetNode, result) {
382
+ let targetNodeInfo = this.nodeRepository.getNode(targetNode.type);
383
+ if (!targetNodeInfo) {
384
+ let normalizedType = targetNode.type;
385
+ if (targetNode.type.startsWith('n8n-nodes-base.')) {
386
+ normalizedType = targetNode.type.replace('n8n-nodes-base.', 'nodes-base.');
387
+ targetNodeInfo = this.nodeRepository.getNode(normalizedType);
388
+ }
389
+ else if (targetNode.type.startsWith('@n8n/n8n-nodes-langchain.')) {
390
+ normalizedType = targetNode.type.replace('@n8n/n8n-nodes-langchain.', 'nodes-langchain.');
391
+ targetNodeInfo = this.nodeRepository.getNode(normalizedType);
392
+ }
393
+ }
394
+ if (targetNodeInfo && !targetNodeInfo.isAITool && targetNodeInfo.package !== 'n8n-nodes-base') {
395
+ result.warnings.push({
396
+ type: 'warning',
397
+ nodeId: targetNode.id,
398
+ nodeName: targetNode.name,
399
+ message: `Community node "${targetNode.name}" is being used as an AI tool. Ensure N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true is set.`
400
+ });
401
+ }
402
+ }
403
+ hasCycle(workflow) {
404
+ const visited = new Set();
405
+ const recursionStack = new Set();
406
+ const hasCycleDFS = (nodeName) => {
407
+ visited.add(nodeName);
408
+ recursionStack.add(nodeName);
409
+ const connections = workflow.connections[nodeName];
410
+ if (connections) {
411
+ const allTargets = [];
412
+ if (connections.main) {
413
+ connections.main.flat().forEach(conn => {
414
+ if (conn)
415
+ allTargets.push(conn.node);
416
+ });
417
+ }
418
+ if (connections.error) {
419
+ connections.error.flat().forEach(conn => {
420
+ if (conn)
421
+ allTargets.push(conn.node);
422
+ });
423
+ }
424
+ if (connections.ai_tool) {
425
+ connections.ai_tool.flat().forEach(conn => {
426
+ if (conn)
427
+ allTargets.push(conn.node);
428
+ });
429
+ }
430
+ for (const target of allTargets) {
431
+ if (!visited.has(target)) {
432
+ if (hasCycleDFS(target))
433
+ return true;
434
+ }
435
+ else if (recursionStack.has(target)) {
436
+ return true;
437
+ }
438
+ }
439
+ }
440
+ recursionStack.delete(nodeName);
441
+ return false;
442
+ };
443
+ for (const node of workflow.nodes) {
444
+ if (!visited.has(node.name)) {
445
+ if (hasCycleDFS(node.name))
446
+ return true;
447
+ }
448
+ }
449
+ return false;
450
+ }
451
+ validateExpressions(workflow, result) {
452
+ const nodeNames = workflow.nodes.map(n => n.name);
453
+ for (const node of workflow.nodes) {
454
+ if (node.disabled)
455
+ continue;
456
+ const context = {
457
+ availableNodes: nodeNames.filter(n => n !== node.name),
458
+ currentNodeName: node.name,
459
+ hasInputData: this.nodeHasInput(node.name, workflow),
460
+ isInLoop: false
461
+ };
462
+ const exprValidation = expression_validator_1.ExpressionValidator.validateNodeExpressions(node.parameters, context);
463
+ result.statistics.expressionsValidated += exprValidation.usedVariables.size;
464
+ exprValidation.errors.forEach(error => {
465
+ result.errors.push({
466
+ type: 'error',
467
+ nodeId: node.id,
468
+ nodeName: node.name,
469
+ message: `Expression error: ${error}`
470
+ });
471
+ });
472
+ exprValidation.warnings.forEach(warning => {
473
+ result.warnings.push({
474
+ type: 'warning',
475
+ nodeId: node.id,
476
+ nodeName: node.name,
477
+ message: `Expression warning: ${warning}`
478
+ });
479
+ });
480
+ }
481
+ }
482
+ nodeHasInput(nodeName, workflow) {
483
+ for (const [sourceName, outputs] of Object.entries(workflow.connections)) {
484
+ if (outputs.main) {
485
+ for (const outputConnections of outputs.main) {
486
+ if (outputConnections?.some(conn => conn.node === nodeName)) {
487
+ return true;
488
+ }
489
+ }
490
+ }
491
+ }
492
+ return false;
493
+ }
494
+ checkWorkflowPatterns(workflow, result) {
495
+ const hasErrorHandling = Object.values(workflow.connections).some(outputs => outputs.error && outputs.error.length > 0);
496
+ if (!hasErrorHandling && workflow.nodes.length > 3) {
497
+ result.warnings.push({
498
+ type: 'warning',
499
+ message: 'Consider adding error handling to your workflow'
500
+ });
501
+ }
502
+ const linearChainLength = this.getLongestLinearChain(workflow);
503
+ if (linearChainLength > 10) {
504
+ result.warnings.push({
505
+ type: 'warning',
506
+ message: `Long linear chain detected (${linearChainLength} nodes). Consider breaking into sub-workflows.`
507
+ });
508
+ }
509
+ for (const node of workflow.nodes) {
510
+ if (node.credentials && Object.keys(node.credentials).length > 0) {
511
+ for (const [credType, credConfig] of Object.entries(node.credentials)) {
512
+ if (!credConfig || (typeof credConfig === 'object' && !('id' in credConfig))) {
513
+ result.warnings.push({
514
+ type: 'warning',
515
+ nodeId: node.id,
516
+ nodeName: node.name,
517
+ message: `Missing credentials configuration for ${credType}`
518
+ });
519
+ }
520
+ }
521
+ }
522
+ }
523
+ const aiAgentNodes = workflow.nodes.filter(n => n.type.toLowerCase().includes('agent') ||
524
+ n.type.includes('langchain.agent'));
525
+ if (aiAgentNodes.length > 0) {
526
+ for (const agentNode of aiAgentNodes) {
527
+ const connections = workflow.connections[agentNode.name];
528
+ if (!connections?.ai_tool || connections.ai_tool.flat().filter(c => c).length === 0) {
529
+ result.warnings.push({
530
+ type: 'warning',
531
+ nodeId: agentNode.id,
532
+ nodeName: agentNode.name,
533
+ message: 'AI Agent has no tools connected. Consider adding tools to enhance agent capabilities.'
534
+ });
535
+ }
536
+ }
537
+ const hasAIToolConnections = Object.values(workflow.connections).some(outputs => outputs.ai_tool && outputs.ai_tool.length > 0);
538
+ if (hasAIToolConnections) {
539
+ result.suggestions.push('For community nodes used as AI tools, ensure N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true is set');
540
+ }
541
+ }
542
+ }
543
+ getLongestLinearChain(workflow) {
544
+ const memo = new Map();
545
+ const visiting = new Set();
546
+ const getChainLength = (nodeName) => {
547
+ if (visiting.has(nodeName))
548
+ return 0;
549
+ if (memo.has(nodeName))
550
+ return memo.get(nodeName);
551
+ visiting.add(nodeName);
552
+ let maxLength = 0;
553
+ const connections = workflow.connections[nodeName];
554
+ if (connections?.main) {
555
+ for (const outputConnections of connections.main) {
556
+ if (outputConnections) {
557
+ for (const conn of outputConnections) {
558
+ const length = getChainLength(conn.node);
559
+ maxLength = Math.max(maxLength, length);
560
+ }
561
+ }
562
+ }
563
+ }
564
+ visiting.delete(nodeName);
565
+ const result = maxLength + 1;
566
+ memo.set(nodeName, result);
567
+ return result;
568
+ };
569
+ let maxChain = 0;
570
+ for (const node of workflow.nodes) {
571
+ if (!this.nodeHasInput(node.name, workflow)) {
572
+ maxChain = Math.max(maxChain, getChainLength(node.name));
573
+ }
574
+ }
575
+ return maxChain;
576
+ }
577
+ findSimilarNodeTypes(invalidType) {
578
+ const suggestions = [];
579
+ const nodeName = invalidType.includes('.') ? invalidType.split('.').pop() : invalidType;
580
+ const commonNodeMappings = {
581
+ 'webhook': ['nodes-base.webhook'],
582
+ 'httpRequest': ['nodes-base.httpRequest'],
583
+ 'http': ['nodes-base.httpRequest'],
584
+ 'set': ['nodes-base.set'],
585
+ 'code': ['nodes-base.code'],
586
+ 'manualTrigger': ['nodes-base.manualTrigger'],
587
+ 'manual': ['nodes-base.manualTrigger'],
588
+ 'scheduleTrigger': ['nodes-base.scheduleTrigger'],
589
+ 'schedule': ['nodes-base.scheduleTrigger'],
590
+ 'cron': ['nodes-base.scheduleTrigger'],
591
+ 'emailSend': ['nodes-base.emailSend'],
592
+ 'email': ['nodes-base.emailSend'],
593
+ 'slack': ['nodes-base.slack'],
594
+ 'discord': ['nodes-base.discord'],
595
+ 'postgres': ['nodes-base.postgres'],
596
+ 'mysql': ['nodes-base.mySql'],
597
+ 'mongodb': ['nodes-base.mongoDb'],
598
+ 'redis': ['nodes-base.redis'],
599
+ 'if': ['nodes-base.if'],
600
+ 'switch': ['nodes-base.switch'],
601
+ 'merge': ['nodes-base.merge'],
602
+ 'splitInBatches': ['nodes-base.splitInBatches'],
603
+ 'loop': ['nodes-base.splitInBatches'],
604
+ 'googleSheets': ['nodes-base.googleSheets'],
605
+ 'sheets': ['nodes-base.googleSheets'],
606
+ 'airtable': ['nodes-base.airtable'],
607
+ 'github': ['nodes-base.github'],
608
+ 'git': ['nodes-base.github'],
609
+ };
610
+ const lowerNodeName = nodeName.toLowerCase();
611
+ if (commonNodeMappings[lowerNodeName]) {
612
+ suggestions.push(...commonNodeMappings[lowerNodeName]);
613
+ }
614
+ Object.entries(commonNodeMappings).forEach(([key, values]) => {
615
+ if (key.includes(lowerNodeName) || lowerNodeName.includes(key)) {
616
+ values.forEach(v => {
617
+ if (!suggestions.includes(v)) {
618
+ suggestions.push(v);
619
+ }
620
+ });
621
+ }
622
+ });
623
+ return suggestions.slice(0, 3);
624
+ }
625
+ generateSuggestions(workflow, result) {
626
+ if (result.statistics.triggerNodes === 0) {
627
+ result.suggestions.push('Add a trigger node (e.g., Webhook, Schedule Trigger) to automate workflow execution');
628
+ }
629
+ const hasConnectionErrors = result.errors.some(e => e.message && (e.message.includes('connection') ||
630
+ e.message.includes('Connection') ||
631
+ e.message.includes('Multi-node workflow has no connections')));
632
+ if (hasConnectionErrors) {
633
+ result.suggestions.push('Example connection structure: connections: { "Manual Trigger": { "main": [[{ "node": "Set", "type": "main", "index": 0 }]] } }');
634
+ result.suggestions.push('Remember: Use node NAMES (not IDs) in connections. The name is what you see in the UI, not the node type.');
635
+ }
636
+ if (!Object.values(workflow.connections).some(o => o.error)) {
637
+ result.suggestions.push('Add error handling using the error output of nodes or an Error Trigger node');
638
+ }
639
+ if (workflow.nodes.length > 20) {
640
+ result.suggestions.push('Consider breaking this workflow into smaller sub-workflows for better maintainability');
641
+ }
642
+ const complexExpressionNodes = workflow.nodes.filter(node => {
643
+ const jsonString = JSON.stringify(node.parameters);
644
+ const expressionCount = (jsonString.match(/\{\{/g) || []).length;
645
+ return expressionCount > 5;
646
+ });
647
+ if (complexExpressionNodes.length > 0) {
648
+ result.suggestions.push('Consider using a Code node for complex data transformations instead of multiple expressions');
649
+ }
650
+ if (workflow.nodes.length === 1 && Object.keys(workflow.connections).length === 0) {
651
+ result.suggestions.push('A minimal workflow needs: 1) A trigger node (e.g., Manual Trigger), 2) An action node (e.g., Set, HTTP Request), 3) A connection between them');
652
+ }
653
+ }
654
+ }
655
+ exports.WorkflowValidator = WorkflowValidator;
656
+ //# sourceMappingURL=workflow-validator.js.map