n8n-workflow-builder-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (595) hide show
  1. package/.cursor/rules/cursor_rules.mdc +53 -0
  2. package/.cursor/rules/dev_workflow.mdc +219 -0
  3. package/.cursor/rules/mcp.mdc +430 -0
  4. package/.cursor/rules/self_improve.mdc +72 -0
  5. package/.cursor/rules/taskmaster.mdc +382 -0
  6. package/.cursorignore +1 -0
  7. package/.cursorrules +4 -0
  8. package/.env.example +23 -0
  9. package/.eslintrc.json +38 -0
  10. package/.github/workflows/npm-publish-github-packages.yml +55 -0
  11. package/.prettierrc +9 -0
  12. package/.roo/rules/dev_workflow.md +219 -0
  13. package/.roo/rules/mcp.md +430 -0
  14. package/.roo/rules/roo_rules.md +53 -0
  15. package/.roo/rules/self_improve.md +72 -0
  16. package/.roo/rules/taskmaster.md +382 -0
  17. package/.roo/rules-architect/architect-rules +93 -0
  18. package/.roo/rules-ask/ask-rules +89 -0
  19. package/.roo/rules-boomerang/boomerang-rules +181 -0
  20. package/.roo/rules-code/code-rules +61 -0
  21. package/.roo/rules-debug/debug-rules +68 -0
  22. package/.roo/rules-test/test-rules +61 -0
  23. package/.roomodes +63 -0
  24. package/.taskmasterconfig +31 -0
  25. package/.windsurfrules +2382 -0
  26. package/LICENSE +21 -0
  27. package/README.md +210 -0
  28. package/config/credentials/credentials.json +1 -0
  29. package/config/default.js +41 -0
  30. package/package.json +56 -0
  31. package/scripts/demo-n8n-integration.js +161 -0
  32. package/scripts/demo-workflow-generator.js +102 -0
  33. package/scripts/init.sh +36 -0
  34. package/scripts/prd.txt +197 -0
  35. package/src/index.ts +1440 -0
  36. package/src/middleware/auth.js +273 -0
  37. package/src/middleware/authorize.js +183 -0
  38. package/src/middleware/logging.js +64 -0
  39. package/src/middleware/mcp.js +187 -0
  40. package/src/middleware/rateLimiter.js +82 -0
  41. package/src/middleware/validation.js +241 -0
  42. package/src/models/credential.js +359 -0
  43. package/src/models/llmService.js +236 -0
  44. package/src/models/n8nIntegration.js +542 -0
  45. package/src/models/storage.js +196 -0
  46. package/src/models/tool.js +148 -0
  47. package/src/models/user.js +164 -0
  48. package/src/models/workflow.js +229 -0
  49. package/src/routes/toolDefinitions.js +62 -0
  50. package/src/routes/toolExecution.js +79 -0
  51. package/src/tools/__index.js +242 -0
  52. package/src/tools/connectionManagement.js +500 -0
  53. package/src/tools/n8nIntegration.js +370 -0
  54. package/src/tools/nodeDiscovery.js +488 -0
  55. package/src/tools/nodeManagement.js +674 -0
  56. package/src/tools/toolDefinitions.js +660 -0
  57. package/src/tools/workflowCreation.js +100 -0
  58. package/src/tools/workflowGenerator.js +152 -0
  59. package/src/tools/workflowStorage.js +113 -0
  60. package/src/tools/workflowTesting.js +285 -0
  61. package/src/utils/encryption.js +164 -0
  62. package/src/utils/logger.js +84 -0
  63. package/src/utils/mcp.js +85 -0
  64. package/src/utils/securityLogger.js +109 -0
  65. package/tests/auth.test.js +402 -0
  66. package/tests/authorize.test.js +208 -0
  67. package/tests/run-memory-tests.js +55 -0
  68. package/tests/run-tests.js +55 -0
  69. package/tests/server.test.js +203 -0
  70. package/tests/unit/add-ai-connections.test.js +385 -0
  71. package/tests/unit/connectionManagement.test.js +309 -0
  72. package/tests/unit/langchain-llm-format.test.js +259 -0
  73. package/tests/unit/memory-connection.test.js +140 -0
  74. package/tests/unit/memory-integration.test.js +253 -0
  75. package/tests/unit/n8nIntegration.test.js +291 -0
  76. package/tests/unit/nodeDiscovery.test.js +270 -0
  77. package/tests/unit/nodeManagement.test.js +522 -0
  78. package/tests/unit/utils/mcp-test-utils.js +94 -0
  79. package/tests/unit/workflowCreation.test.js +110 -0
  80. package/tests/unit/workflowTesting.test.js +269 -0
  81. package/tests/user.test.js +181 -0
  82. package/tsconfig.json +20 -0
  83. package/workflow_nodes/Brandfetch.json +85 -0
  84. package/workflow_nodes/WorkflowTrigger.json +28 -0
  85. package/workflow_nodes/actionNetwork.json +218 -0
  86. package/workflow_nodes/activeCampaign.json +722 -0
  87. package/workflow_nodes/activeCampaignTrigger.json +52 -0
  88. package/workflow_nodes/acuitySchedulingTrigger.json +8 -0
  89. package/workflow_nodes/adalo.json +123 -0
  90. package/workflow_nodes/affinity.json +203 -0
  91. package/workflow_nodes/affinityTrigger.json +124 -0
  92. package/workflow_nodes/aggregate.json +119 -0
  93. package/workflow_nodes/agileCrm.json +503 -0
  94. package/workflow_nodes/aiTransform.json +17 -0
  95. package/workflow_nodes/airtable.json +226 -0
  96. package/workflow_nodes/airtableTrigger.json +120 -0
  97. package/workflow_nodes/airtop.json +10 -0
  98. package/workflow_nodes/amqp.json +62 -0
  99. package/workflow_nodes/amqpTrigger.json +8 -0
  100. package/workflow_nodes/apiTemplateIo.json +147 -0
  101. package/workflow_nodes/asana.json +446 -0
  102. package/workflow_nodes/asanaTrigger.json +52 -0
  103. package/workflow_nodes/automizy.json +195 -0
  104. package/workflow_nodes/autopilot.json +287 -0
  105. package/workflow_nodes/autopilotTrigger.json +8 -0
  106. package/workflow_nodes/awsCertificateManager.json +223 -0
  107. package/workflow_nodes/awsComprehend.json +125 -0
  108. package/workflow_nodes/awsDynamoDb.json +251 -0
  109. package/workflow_nodes/awsElb.json +174 -0
  110. package/workflow_nodes/awsLambda.json +69 -0
  111. package/workflow_nodes/awsRekognition.json +191 -0
  112. package/workflow_nodes/awsS3.json +32 -0
  113. package/workflow_nodes/awsSes.json +302 -0
  114. package/workflow_nodes/awsSns.json +110 -0
  115. package/workflow_nodes/awsSnsTrigger.json +47 -0
  116. package/workflow_nodes/awsSqs.json +140 -0
  117. package/workflow_nodes/awsTextract.json +43 -0
  118. package/workflow_nodes/awsTranscribe.json +217 -0
  119. package/workflow_nodes/azureCosmosDb.json +8 -0
  120. package/workflow_nodes/azureStorage.json +17 -0
  121. package/workflow_nodes/bambooHr.json +8 -0
  122. package/workflow_nodes/bannerbear.json +126 -0
  123. package/workflow_nodes/baserow.json +277 -0
  124. package/workflow_nodes/beeminder.json +146 -0
  125. package/workflow_nodes/bitbucketTrigger.json +62 -0
  126. package/workflow_nodes/bitly.json +130 -0
  127. package/workflow_nodes/bitwarden.json +224 -0
  128. package/workflow_nodes/box.json +457 -0
  129. package/workflow_nodes/boxTrigger.json +8 -0
  130. package/workflow_nodes/brevo.json +41 -0
  131. package/workflow_nodes/brevoTrigger.json +145 -0
  132. package/workflow_nodes/bubble.json +212 -0
  133. package/workflow_nodes/calTrigger.json +91 -0
  134. package/workflow_nodes/calendlyTrigger.json +71 -0
  135. package/workflow_nodes/chargebee.json +217 -0
  136. package/workflow_nodes/chargebeeTrigger.json +187 -0
  137. package/workflow_nodes/circleCi.json +89 -0
  138. package/workflow_nodes/ciscoWebex.json +593 -0
  139. package/workflow_nodes/ciscoWebexTrigger.json +159 -0
  140. package/workflow_nodes/clearbit.json +138 -0
  141. package/workflow_nodes/clickUp.json +793 -0
  142. package/workflow_nodes/clickUpTrigger.json +188 -0
  143. package/workflow_nodes/clockify.json +372 -0
  144. package/workflow_nodes/clockifyTrigger.json +26 -0
  145. package/workflow_nodes/cloudflare.json +103 -0
  146. package/workflow_nodes/cockpit.json +161 -0
  147. package/workflow_nodes/coda.json +242 -0
  148. package/workflow_nodes/code.json +40 -0
  149. package/workflow_nodes/coinGecko.json +363 -0
  150. package/workflow_nodes/compareDatasets.json +14 -0
  151. package/workflow_nodes/compression.json +66 -0
  152. package/workflow_nodes/contentful.json +29 -0
  153. package/workflow_nodes/convertKit.json +159 -0
  154. package/workflow_nodes/convertKitTrigger.json +109 -0
  155. package/workflow_nodes/convertToFile.json +64 -0
  156. package/workflow_nodes/copper.json +239 -0
  157. package/workflow_nodes/copperTrigger.json +8 -0
  158. package/workflow_nodes/cortex.json +348 -0
  159. package/workflow_nodes/crateDb.json +90 -0
  160. package/workflow_nodes/cron.json +23 -0
  161. package/workflow_nodes/crowdDev.json +8 -0
  162. package/workflow_nodes/crowdDevTrigger.json +8 -0
  163. package/workflow_nodes/crypto.json +147 -0
  164. package/workflow_nodes/customerIo.json +206 -0
  165. package/workflow_nodes/customerIoTrigger.json +185 -0
  166. package/workflow_nodes/dateTime.json +39 -0
  167. package/workflow_nodes/debughelper.json +162 -0
  168. package/workflow_nodes/deepL.json +103 -0
  169. package/workflow_nodes/demio.json +187 -0
  170. package/workflow_nodes/dhl.json +53 -0
  171. package/workflow_nodes/discord.json +81 -0
  172. package/workflow_nodes/discourse.json +319 -0
  173. package/workflow_nodes/disqus.json +254 -0
  174. package/workflow_nodes/drift.json +112 -0
  175. package/workflow_nodes/dropbox.json +258 -0
  176. package/workflow_nodes/dropcontact.json +154 -0
  177. package/workflow_nodes/e2eTest.json +70 -0
  178. package/workflow_nodes/editImage.json +132 -0
  179. package/workflow_nodes/egoi.json +220 -0
  180. package/workflow_nodes/elasticSecurity.json +401 -0
  181. package/workflow_nodes/elasticsearch.json +422 -0
  182. package/workflow_nodes/emailReadImap.json +88 -0
  183. package/workflow_nodes/emailSend.json +38 -0
  184. package/workflow_nodes/emelia.json +201 -0
  185. package/workflow_nodes/emeliaTrigger.json +57 -0
  186. package/workflow_nodes/erpNext.json +139 -0
  187. package/workflow_nodes/errorTrigger.json +15 -0
  188. package/workflow_nodes/evaluationMetrics.json +21 -0
  189. package/workflow_nodes/eventbriteTrigger.json +125 -0
  190. package/workflow_nodes/executeCommand.json +25 -0
  191. package/workflow_nodes/executeWorkflow.json +102 -0
  192. package/workflow_nodes/executeWorkflowTrigger.json +65 -0
  193. package/workflow_nodes/executionData.json +35 -0
  194. package/workflow_nodes/extractFromFile.json +71 -0
  195. package/workflow_nodes/facebookGraphApi.json +234 -0
  196. package/workflow_nodes/facebookLeadAdsTrigger.json +8 -0
  197. package/workflow_nodes/facebookTrigger.json +112 -0
  198. package/workflow_nodes/figmaTrigger.json +8 -0
  199. package/workflow_nodes/filemaker.json +268 -0
  200. package/workflow_nodes/filter.json +24 -0
  201. package/workflow_nodes/flow.json +323 -0
  202. package/workflow_nodes/flowTrigger.json +52 -0
  203. package/workflow_nodes/form.json +25 -0
  204. package/workflow_nodes/formIoTrigger.json +59 -0
  205. package/workflow_nodes/formTrigger.json +8 -0
  206. package/workflow_nodes/formstackTrigger.json +8 -0
  207. package/workflow_nodes/freshdesk.json +584 -0
  208. package/workflow_nodes/freshservice.json +899 -0
  209. package/workflow_nodes/freshworksCrm.json +772 -0
  210. package/workflow_nodes/ftp.json +127 -0
  211. package/workflow_nodes/function.json +22 -0
  212. package/workflow_nodes/functionItem.json +22 -0
  213. package/workflow_nodes/gSuiteAdmin.json +562 -0
  214. package/workflow_nodes/getResponse.json +310 -0
  215. package/workflow_nodes/getResponseTrigger.json +82 -0
  216. package/workflow_nodes/ghost.json +290 -0
  217. package/workflow_nodes/git.json +184 -0
  218. package/workflow_nodes/github.json +732 -0
  219. package/workflow_nodes/githubTrigger.json +317 -0
  220. package/workflow_nodes/gitlab.json +544 -0
  221. package/workflow_nodes/gitlabTrigger.json +61 -0
  222. package/workflow_nodes/gmail.json +62 -0
  223. package/workflow_nodes/gmailTrigger.json +127 -0
  224. package/workflow_nodes/goToWebinar.json +430 -0
  225. package/workflow_nodes/gong.json +22 -0
  226. package/workflow_nodes/googleAds.json +116 -0
  227. package/workflow_nodes/googleAnalytics.json +28 -0
  228. package/workflow_nodes/googleBigQuery.json +38 -0
  229. package/workflow_nodes/googleBooks.json +154 -0
  230. package/workflow_nodes/googleBusinessProfile.json +277 -0
  231. package/workflow_nodes/googleBusinessProfileTrigger.json +55 -0
  232. package/workflow_nodes/googleCalendar.json +474 -0
  233. package/workflow_nodes/googleCalendarTrigger.json +72 -0
  234. package/workflow_nodes/googleChat.json +187 -0
  235. package/workflow_nodes/googleCloudNaturalLanguage.json +171 -0
  236. package/workflow_nodes/googleCloudStorage.json +466 -0
  237. package/workflow_nodes/googleContacts.json +481 -0
  238. package/workflow_nodes/googleDocs.json +312 -0
  239. package/workflow_nodes/googleDrive.json +920 -0
  240. package/workflow_nodes/googleDriveTrigger.json +181 -0
  241. package/workflow_nodes/googleFirebaseCloudFirestore.json +156 -0
  242. package/workflow_nodes/googleFirebaseRealtimeDatabase.json +75 -0
  243. package/workflow_nodes/googlePerspective.json +94 -0
  244. package/workflow_nodes/googleSheets.json +98 -0
  245. package/workflow_nodes/googleSheetsTrigger.json +192 -0
  246. package/workflow_nodes/googleSlides.json +186 -0
  247. package/workflow_nodes/googleTasks.json +198 -0
  248. package/workflow_nodes/googleTranslate.json +80 -0
  249. package/workflow_nodes/gotify.json +110 -0
  250. package/workflow_nodes/grafana.json +155 -0
  251. package/workflow_nodes/graphql.json +165 -0
  252. package/workflow_nodes/grist.json +13 -0
  253. package/workflow_nodes/gumroadTrigger.json +8 -0
  254. package/workflow_nodes/hackerNews.json +100 -0
  255. package/workflow_nodes/haloPSA.json +286 -0
  256. package/workflow_nodes/harvest.json +699 -0
  257. package/workflow_nodes/helpScout.json +629 -0
  258. package/workflow_nodes/helpScoutTrigger.json +8 -0
  259. package/workflow_nodes/highLevel.json +8 -0
  260. package/workflow_nodes/homeAssistant.json +201 -0
  261. package/workflow_nodes/html.json +118 -0
  262. package/workflow_nodes/htmlExtract.json +87 -0
  263. package/workflow_nodes/httpRequest.json +472 -0
  264. package/workflow_nodes/hubspot.json +62 -0
  265. package/workflow_nodes/hubspotTrigger.json +138 -0
  266. package/workflow_nodes/humanticAi.json +82 -0
  267. package/workflow_nodes/hunter.json +168 -0
  268. package/workflow_nodes/iCal.json +20 -0
  269. package/workflow_nodes/if.json +24 -0
  270. package/workflow_nodes/intercom.json +335 -0
  271. package/workflow_nodes/interval.json +8 -0
  272. package/workflow_nodes/invoiceNinja.json +882 -0
  273. package/workflow_nodes/invoiceNinjaTrigger.json +11 -0
  274. package/workflow_nodes/itemLists.json +313 -0
  275. package/workflow_nodes/iterable.json +168 -0
  276. package/workflow_nodes/jenkins.json +172 -0
  277. package/workflow_nodes/jira.json +529 -0
  278. package/workflow_nodes/jiraTrigger.json +308 -0
  279. package/workflow_nodes/jotFormTrigger.json +44 -0
  280. package/workflow_nodes/jwt.json +195 -0
  281. package/workflow_nodes/kafka.json +132 -0
  282. package/workflow_nodes/kafkaTrigger.json +11 -0
  283. package/workflow_nodes/keap.json +915 -0
  284. package/workflow_nodes/keapTrigger.json +37 -0
  285. package/workflow_nodes/kitemaker.json +153 -0
  286. package/workflow_nodes/koBoToolbox.json +337 -0
  287. package/workflow_nodes/koBoToolboxTrigger.json +8 -0
  288. package/workflow_nodes/langchain_Summarization Chain.json +60 -0
  289. package/workflow_nodes/langchain_agent.json +145 -0
  290. package/workflow_nodes/langchain_allowFileUploads.json +180 -0
  291. package/workflow_nodes/langchain_chainLlm.json +16 -0
  292. package/workflow_nodes/langchain_chainSummarization.json +119 -0
  293. package/workflow_nodes/langchain_code.json +62 -0
  294. package/workflow_nodes/langchain_documentBinaryInputLoader.json +8 -0
  295. package/workflow_nodes/langchain_documentDefaultDataLoader.json +8 -0
  296. package/workflow_nodes/langchain_documentGithubLoader.json +8 -0
  297. package/workflow_nodes/langchain_documentJsonInputLoader.json +8 -0
  298. package/workflow_nodes/langchain_embeddingDimensions.json +17 -0
  299. package/workflow_nodes/langchain_embeddingsAwsBedrock.json +8 -0
  300. package/workflow_nodes/langchain_embeddingsAzureOpenAi.json +151 -0
  301. package/workflow_nodes/langchain_embeddingsCohere.json +8 -0
  302. package/workflow_nodes/langchain_embeddingsGoogleGemini.json +8 -0
  303. package/workflow_nodes/langchain_embeddingsGoogleVertex.json +8 -0
  304. package/workflow_nodes/langchain_embeddingsHuggingFaceInference.json +8 -0
  305. package/workflow_nodes/langchain_embeddingsMistralCloud.json +8 -0
  306. package/workflow_nodes/langchain_embeddingsOllama.json +8 -0
  307. package/workflow_nodes/langchain_informationExtractor.json +81 -0
  308. package/workflow_nodes/langchain_lmChatAwsBedrock.json +8 -0
  309. package/workflow_nodes/langchain_lmChatAzureOpenAi.json +151 -0
  310. package/workflow_nodes/langchain_lmChatDeepSeek.json +10 -0
  311. package/workflow_nodes/langchain_lmChatGoogleGemini.json +31 -0
  312. package/workflow_nodes/langchain_lmChatGoogleVertex.json +32 -0
  313. package/workflow_nodes/langchain_lmChatGroq.json +8 -0
  314. package/workflow_nodes/langchain_lmChatMistralCloud.json +8 -0
  315. package/workflow_nodes/langchain_lmChatOllama.json +8 -0
  316. package/workflow_nodes/langchain_lmChatOpenAi.json +155 -0
  317. package/workflow_nodes/langchain_lmChatOpenRouter.json +10 -0
  318. package/workflow_nodes/langchain_lmChatXAiGrok.json +10 -0
  319. package/workflow_nodes/langchain_lmCohere.json +8 -0
  320. package/workflow_nodes/langchain_lmOllama.json +8 -0
  321. package/workflow_nodes/langchain_lmOpenAi.json +251 -0
  322. package/workflow_nodes/langchain_lmOpenHuggingFaceInference.json +8 -0
  323. package/workflow_nodes/langchain_manualChatTrigger.json +11 -0
  324. package/workflow_nodes/langchain_mcpClientTool.json +86 -0
  325. package/workflow_nodes/langchain_mcpTrigger.json +8 -0
  326. package/workflow_nodes/langchain_memoryBufferWindow.json +13 -0
  327. package/workflow_nodes/langchain_memoryChatRetriever.json +22 -0
  328. package/workflow_nodes/langchain_memoryManager.json +106 -0
  329. package/workflow_nodes/langchain_memoryMongoDbChat.json +10 -0
  330. package/workflow_nodes/langchain_memoryMotorhead.json +13 -0
  331. package/workflow_nodes/langchain_memoryPostgresChat.json +13 -0
  332. package/workflow_nodes/langchain_memoryRedisChat.json +15 -0
  333. package/workflow_nodes/langchain_memoryXata.json +14 -0
  334. package/workflow_nodes/langchain_memoryZep.json +13 -0
  335. package/workflow_nodes/langchain_model.json +155 -0
  336. package/workflow_nodes/langchain_mongoCollection.json +16 -0
  337. package/workflow_nodes/langchain_notice.json +22 -0
  338. package/workflow_nodes/langchain_openAiAssistant.json +132 -0
  339. package/workflow_nodes/langchain_options.json +17 -0
  340. package/workflow_nodes/langchain_outputParserAutofixing.json +8 -0
  341. package/workflow_nodes/langchain_outputParserItemList.json +8 -0
  342. package/workflow_nodes/langchain_outputParserStructured.json +12 -0
  343. package/workflow_nodes/langchain_pineconeNamespace.json +16 -0
  344. package/workflow_nodes/langchain_queryName.json +16 -0
  345. package/workflow_nodes/langchain_retrieverContextualCompression.json +8 -0
  346. package/workflow_nodes/langchain_retrieverMultiQuery.json +8 -0
  347. package/workflow_nodes/langchain_retrieverVectorStore.json +8 -0
  348. package/workflow_nodes/langchain_retrieverWorkflow.json +103 -0
  349. package/workflow_nodes/langchain_sentimentAnalysis.json +52 -0
  350. package/workflow_nodes/langchain_systemPromptTemplate.json +47 -0
  351. package/workflow_nodes/langchain_tableName.json +23 -0
  352. package/workflow_nodes/langchain_textClassifier.json +66 -0
  353. package/workflow_nodes/langchain_textSplitterCharacterTextSplitter.json +8 -0
  354. package/workflow_nodes/langchain_textSplitterRecursiveCharacterTextSplitter.json +8 -0
  355. package/workflow_nodes/langchain_textSplitterTokenSplitter.json +8 -0
  356. package/workflow_nodes/langchain_toolCalculator.json +8 -0
  357. package/workflow_nodes/langchain_toolCode.json +12 -0
  358. package/workflow_nodes/langchain_toolHttpRequest.json +232 -0
  359. package/workflow_nodes/langchain_toolSearXng.json +8 -0
  360. package/workflow_nodes/langchain_toolSerpApi.json +8 -0
  361. package/workflow_nodes/langchain_toolThink.json +8 -0
  362. package/workflow_nodes/langchain_toolVectorStore.json +11 -0
  363. package/workflow_nodes/langchain_toolWikipedia.json +8 -0
  364. package/workflow_nodes/langchain_toolWolframAlpha.json +8 -0
  365. package/workflow_nodes/langchain_toolWorkflow.json +8 -0
  366. package/workflow_nodes/langchain_vectorStoreInMemoryInsert.json +29 -0
  367. package/workflow_nodes/langchain_vectorStoreInMemoryLoad.json +8 -0
  368. package/workflow_nodes/langchain_vectorStorePineconeInsert.json +37 -0
  369. package/workflow_nodes/langchain_vectorStorePineconeLoad.json +8 -0
  370. package/workflow_nodes/langchain_vectorStoreSupabaseInsert.json +32 -0
  371. package/workflow_nodes/langchain_vectorStoreSupabaseLoad.json +8 -0
  372. package/workflow_nodes/langchain_vectorStoreZepInsert.json +46 -0
  373. package/workflow_nodes/langchain_vectorStoreZepLoad.json +8 -0
  374. package/workflow_nodes/ldap.json +182 -0
  375. package/workflow_nodes/lemlist.json +44 -0
  376. package/workflow_nodes/lemlistTrigger.json +45 -0
  377. package/workflow_nodes/limit.json +26 -0
  378. package/workflow_nodes/line.json +95 -0
  379. package/workflow_nodes/linear.json +151 -0
  380. package/workflow_nodes/linearTrigger.json +71 -0
  381. package/workflow_nodes/lingvaNex.json +66 -0
  382. package/workflow_nodes/linkedIn.json +142 -0
  383. package/workflow_nodes/localFileTrigger.json +120 -0
  384. package/workflow_nodes/lonescale.json +171 -0
  385. package/workflow_nodes/lonescaleTrigger.json +8 -0
  386. package/workflow_nodes/magento2.json +164 -0
  387. package/workflow_nodes/mailcheck.json +46 -0
  388. package/workflow_nodes/mailchimp.json +507 -0
  389. package/workflow_nodes/mailchimpTrigger.json +100 -0
  390. package/workflow_nodes/mailerLite.json +24 -0
  391. package/workflow_nodes/mailerLiteTrigger.json +74 -0
  392. package/workflow_nodes/mailgun.json +81 -0
  393. package/workflow_nodes/mailjet.json +201 -0
  394. package/workflow_nodes/mailjetTrigger.json +8 -0
  395. package/workflow_nodes/mandrill.json +372 -0
  396. package/workflow_nodes/manualTrigger.json +8 -0
  397. package/workflow_nodes/markdown.json +376 -0
  398. package/workflow_nodes/marketstack.json +126 -0
  399. package/workflow_nodes/matrix.json +264 -0
  400. package/workflow_nodes/mattermost.json +8 -0
  401. package/workflow_nodes/mautic.json +564 -0
  402. package/workflow_nodes/mauticTrigger.json +54 -0
  403. package/workflow_nodes/medium.json +209 -0
  404. package/workflow_nodes/merge.json +125 -0
  405. package/workflow_nodes/messageBird.json +182 -0
  406. package/workflow_nodes/metabase.json +175 -0
  407. package/workflow_nodes/microsoftDynamicsCrm.json +100 -0
  408. package/workflow_nodes/microsoftEntra.json +51 -0
  409. package/workflow_nodes/microsoftExcel.json +35 -0
  410. package/workflow_nodes/microsoftGraphSecurity.json +113 -0
  411. package/workflow_nodes/microsoftOneDrive.json +232 -0
  412. package/workflow_nodes/microsoftOneDriveTrigger.json +80 -0
  413. package/workflow_nodes/microsoftOutlook.json +40 -0
  414. package/workflow_nodes/microsoftOutlookTrigger.json +24 -0
  415. package/workflow_nodes/microsoftSql.json +81 -0
  416. package/workflow_nodes/microsoftTeams.json +36 -0
  417. package/workflow_nodes/microsoftToDo.json +181 -0
  418. package/workflow_nodes/mindee.json +86 -0
  419. package/workflow_nodes/misp.json +399 -0
  420. package/workflow_nodes/mocean.json +103 -0
  421. package/workflow_nodes/mondayCom.json +290 -0
  422. package/workflow_nodes/mongoDb.json +16 -0
  423. package/workflow_nodes/monicaCrm.json +543 -0
  424. package/workflow_nodes/moveBinaryData.json +121 -0
  425. package/workflow_nodes/mqtt.json +67 -0
  426. package/workflow_nodes/mqttTrigger.json +47 -0
  427. package/workflow_nodes/msg91.json +65 -0
  428. package/workflow_nodes/mySql.json +111 -0
  429. package/workflow_nodes/n8n.json +75 -0
  430. package/workflow_nodes/n8nTrigger.json +27 -0
  431. package/workflow_nodes/nasa.json +310 -0
  432. package/workflow_nodes/netlify.json +87 -0
  433. package/workflow_nodes/netlifyTrigger.json +68 -0
  434. package/workflow_nodes/netscalerAdc.json +243 -0
  435. package/workflow_nodes/nextCloud.json +312 -0
  436. package/workflow_nodes/noOp.json +8 -0
  437. package/workflow_nodes/nocoDb.json +276 -0
  438. package/workflow_nodes/notion.json +8 -0
  439. package/workflow_nodes/notionTrigger.json +75 -0
  440. package/workflow_nodes/npm.json +64 -0
  441. package/workflow_nodes/odoo.json +344 -0
  442. package/workflow_nodes/okta.json +97 -0
  443. package/workflow_nodes/oneSimpleApi.json +281 -0
  444. package/workflow_nodes/onfleet.json +316 -0
  445. package/workflow_nodes/onfleetTrigger.json +8 -0
  446. package/workflow_nodes/openAi.json +154 -0
  447. package/workflow_nodes/openThesaurus.json +81 -0
  448. package/workflow_nodes/openWeatherMap.json +129 -0
  449. package/workflow_nodes/orbit.json +375 -0
  450. package/workflow_nodes/oura.json +74 -0
  451. package/workflow_nodes/paddle.json +403 -0
  452. package/workflow_nodes/pagerDuty.json +351 -0
  453. package/workflow_nodes/payPal.json +196 -0
  454. package/workflow_nodes/payPalTrigger.json +40 -0
  455. package/workflow_nodes/peekalink.json +41 -0
  456. package/workflow_nodes/phantombuster.json +172 -0
  457. package/workflow_nodes/philipsHue.json +177 -0
  458. package/workflow_nodes/pipedrive.json +860 -0
  459. package/workflow_nodes/pipedriveTrigger.json +11 -0
  460. package/workflow_nodes/plivo.json +91 -0
  461. package/workflow_nodes/postHog.json +122 -0
  462. package/workflow_nodes/postbin.json +60 -0
  463. package/workflow_nodes/postgres.json +109 -0
  464. package/workflow_nodes/postgresTrigger.json +8 -0
  465. package/workflow_nodes/postmarkTrigger.json +72 -0
  466. package/workflow_nodes/profitWell.json +305 -0
  467. package/workflow_nodes/pushbullet.json +186 -0
  468. package/workflow_nodes/pushcut.json +75 -0
  469. package/workflow_nodes/pushcutTrigger.json +8 -0
  470. package/workflow_nodes/pushover.json +159 -0
  471. package/workflow_nodes/questDb.json +94 -0
  472. package/workflow_nodes/quickChart.json +188 -0
  473. package/workflow_nodes/quickbase.json +205 -0
  474. package/workflow_nodes/quickbooks.json +550 -0
  475. package/workflow_nodes/rabbitmq.json +165 -0
  476. package/workflow_nodes/rabbitmqTrigger.json +8 -0
  477. package/workflow_nodes/raindrop.json +216 -0
  478. package/workflow_nodes/readBinaryFile.json +26 -0
  479. package/workflow_nodes/readBinaryFiles.json +26 -0
  480. package/workflow_nodes/readPDF.json +31 -0
  481. package/workflow_nodes/readWriteFile.json +27 -0
  482. package/workflow_nodes/reddit.json +309 -0
  483. package/workflow_nodes/redis.json +183 -0
  484. package/workflow_nodes/redisTrigger.json +8 -0
  485. package/workflow_nodes/removeDuplicates.json +8 -0
  486. package/workflow_nodes/renameKeys.json +67 -0
  487. package/workflow_nodes/respondToWebhook.json +126 -0
  488. package/workflow_nodes/rocketchat.json +216 -0
  489. package/workflow_nodes/rssFeedRead.json +28 -0
  490. package/workflow_nodes/rssFeedReadTrigger.json +17 -0
  491. package/workflow_nodes/rundeck.json +79 -0
  492. package/workflow_nodes/s3.json +425 -0
  493. package/workflow_nodes/salesforce.json +1137 -0
  494. package/workflow_nodes/salesforceTrigger.json +122 -0
  495. package/workflow_nodes/salesmate.json +467 -0
  496. package/workflow_nodes/scheduleTrigger.json +270 -0
  497. package/workflow_nodes/seaTable.json +8 -0
  498. package/workflow_nodes/seaTableTrigger.json +87 -0
  499. package/workflow_nodes/securityScorecard.json +459 -0
  500. package/workflow_nodes/segment.json +219 -0
  501. package/workflow_nodes/sendGrid.json +359 -0
  502. package/workflow_nodes/sendy.json +225 -0
  503. package/workflow_nodes/sentryIo.json +426 -0
  504. package/workflow_nodes/serviceNow.json +544 -0
  505. package/workflow_nodes/set.json +124 -0
  506. package/workflow_nodes/shopify.json +707 -0
  507. package/workflow_nodes/shopifyTrigger.json +8 -0
  508. package/workflow_nodes/signl4.json +133 -0
  509. package/workflow_nodes/simulate.json +30 -0
  510. package/workflow_nodes/simulateTrigger.json +8 -0
  511. package/workflow_nodes/slack.json +62 -0
  512. package/workflow_nodes/slackTrigger.json +135 -0
  513. package/workflow_nodes/sms77.json +121 -0
  514. package/workflow_nodes/snowflake.json +65 -0
  515. package/workflow_nodes/sort.json +57 -0
  516. package/workflow_nodes/splitInBatches.json +30 -0
  517. package/workflow_nodes/splitOut.json +62 -0
  518. package/workflow_nodes/splunk.json +40 -0
  519. package/workflow_nodes/spontit.json +123 -0
  520. package/workflow_nodes/spotify.json +285 -0
  521. package/workflow_nodes/spreadsheetFile.json +8 -0
  522. package/workflow_nodes/sseTrigger.json +8 -0
  523. package/workflow_nodes/ssh.json +105 -0
  524. package/workflow_nodes/stackby.json +85 -0
  525. package/workflow_nodes/start.json +15 -0
  526. package/workflow_nodes/stickyNote.json +36 -0
  527. package/workflow_nodes/stopAndError.json +8 -0
  528. package/workflow_nodes/storyblok.json +138 -0
  529. package/workflow_nodes/strapi.json +138 -0
  530. package/workflow_nodes/strava.json +427 -0
  531. package/workflow_nodes/stravaTrigger.json +79 -0
  532. package/workflow_nodes/stripe.json +357 -0
  533. package/workflow_nodes/stripeTrigger.json +775 -0
  534. package/workflow_nodes/summarize.json +124 -0
  535. package/workflow_nodes/supabase.json +136 -0
  536. package/workflow_nodes/surveyMonkeyTrigger.json +160 -0
  537. package/workflow_nodes/switch.json +91 -0
  538. package/workflow_nodes/syncroMsp.json +8 -0
  539. package/workflow_nodes/taiga.json +340 -0
  540. package/workflow_nodes/taigaTrigger.json +81 -0
  541. package/workflow_nodes/tapfiliate.json +241 -0
  542. package/workflow_nodes/telegram.json +612 -0
  543. package/workflow_nodes/telegramTrigger.json +142 -0
  544. package/workflow_nodes/theHive.json +497 -0
  545. package/workflow_nodes/theHiveProject.json +8 -0
  546. package/workflow_nodes/theHiveProjectTrigger.json +162 -0
  547. package/workflow_nodes/theHiveTrigger.json +101 -0
  548. package/workflow_nodes/timescaleDb.json +95 -0
  549. package/workflow_nodes/todoist.json +285 -0
  550. package/workflow_nodes/togglTrigger.json +24 -0
  551. package/workflow_nodes/totp.json +86 -0
  552. package/workflow_nodes/travisCi.json +142 -0
  553. package/workflow_nodes/trello.json +609 -0
  554. package/workflow_nodes/trelloTrigger.json +8 -0
  555. package/workflow_nodes/twake.json +76 -0
  556. package/workflow_nodes/twilio.json +95 -0
  557. package/workflow_nodes/twilioTrigger.json +46 -0
  558. package/workflow_nodes/twist.json +376 -0
  559. package/workflow_nodes/twitter.json +40 -0
  560. package/workflow_nodes/typeformTrigger.json +62 -0
  561. package/workflow_nodes/unleashedSoftware.json +154 -0
  562. package/workflow_nodes/uplead.json +72 -0
  563. package/workflow_nodes/uproc.json +26 -0
  564. package/workflow_nodes/uptimeRobot.json +453 -0
  565. package/workflow_nodes/urlScanIo.json +113 -0
  566. package/workflow_nodes/venafiTlsProtectCloud.json +310 -0
  567. package/workflow_nodes/venafiTlsProtectCloudTrigger.json +38 -0
  568. package/workflow_nodes/venafiTlsProtectDatacenter.json +491 -0
  569. package/workflow_nodes/vero.json +158 -0
  570. package/workflow_nodes/vonage.json +125 -0
  571. package/workflow_nodes/wait.json +71 -0
  572. package/workflow_nodes/webflow.json +38 -0
  573. package/workflow_nodes/webflowTrigger.json +8 -0
  574. package/workflow_nodes/webhook.json +55 -0
  575. package/workflow_nodes/wekan.json +460 -0
  576. package/workflow_nodes/whatsApp.json +476 -0
  577. package/workflow_nodes/whatsAppTrigger.json +103 -0
  578. package/workflow_nodes/wise.json +330 -0
  579. package/workflow_nodes/wiseTrigger.json +8 -0
  580. package/workflow_nodes/wooCommerce.json +812 -0
  581. package/workflow_nodes/wooCommerceTrigger.json +8 -0
  582. package/workflow_nodes/wordpress.json +500 -0
  583. package/workflow_nodes/workableTrigger.json +51 -0
  584. package/workflow_nodes/writeBinaryFile.json +34 -0
  585. package/workflow_nodes/wufooTrigger.json +37 -0
  586. package/workflow_nodes/xero.json +530 -0
  587. package/workflow_nodes/xml.json +129 -0
  588. package/workflow_nodes/youTube.json +578 -0
  589. package/workflow_nodes/yourls.json +71 -0
  590. package/workflow_nodes/zammad.json +406 -0
  591. package/workflow_nodes/zendesk.json +526 -0
  592. package/workflow_nodes/zendeskTrigger.json +187 -0
  593. package/workflow_nodes/zohoCrm.json +721 -0
  594. package/workflow_nodes/zoom.json +507 -0
  595. package/workflow_nodes/zulip.json +371 -0
@@ -0,0 +1,522 @@
1
+ /**
2
+ * Unit tests for the Node Management module
3
+ */
4
+
5
+ const { expect } = require('chai');
6
+ const sinon = require('sinon');
7
+ const nodeManagement = require('../../src/tools/nodeManagement');
8
+ const { workflowStorage } = require('../../src/models/storage');
9
+ const nodeDiscovery = require('../../src/tools/nodeDiscovery');
10
+
11
+ describe('Node Management', () => {
12
+
13
+ describe('generateUniqueNodeId', () => {
14
+ it('should generate a unique ID with format node1 for empty workflow', () => {
15
+ const workflow = { nodes: [] };
16
+ const nodeId = nodeManagement.generateUniqueNodeId(workflow);
17
+ expect(nodeId).to.equal('node1');
18
+ });
19
+
20
+ it('should increment the highest existing node ID', () => {
21
+ const workflow = {
22
+ nodes: [
23
+ { id: 'node1' },
24
+ { id: 'node2' },
25
+ { id: 'node5' }
26
+ ]
27
+ };
28
+ const nodeId = nodeManagement.generateUniqueNodeId(workflow);
29
+ expect(nodeId).to.equal('node6');
30
+ });
31
+
32
+ it('should handle workflows without nodes array', () => {
33
+ const workflow = {};
34
+ const nodeId = nodeManagement.generateUniqueNodeId(workflow);
35
+ expect(nodeId).to.equal('node1');
36
+ });
37
+ });
38
+
39
+ describe('validateNodeParameters', () => {
40
+ it('should return true for valid parameters', () => {
41
+ const nodeTypeDef = {
42
+ parameters: [
43
+ { name: 'url', required: true },
44
+ { name: 'method', required: false }
45
+ ]
46
+ };
47
+ const parameters = { url: 'http://example.com', method: 'GET' };
48
+
49
+ expect(nodeManagement.validateNodeParameters(nodeTypeDef, parameters)).to.be.true;
50
+ });
51
+
52
+ it('should throw error for missing required parameters', () => {
53
+ const nodeTypeDef = {
54
+ parameters: [
55
+ { name: 'url', required: true },
56
+ { name: 'method', required: true }
57
+ ]
58
+ };
59
+ const parameters = { url: 'http://example.com' };
60
+
61
+ expect(() => nodeManagement.validateNodeParameters(nodeTypeDef, parameters)).to.throw(/Missing required parameters/);
62
+ });
63
+
64
+ it('should return true if no parameters provided and none required', () => {
65
+ const nodeTypeDef = {
66
+ parameters: [
67
+ { name: 'url', required: false },
68
+ { name: 'method', required: false }
69
+ ]
70
+ };
71
+
72
+ expect(nodeManagement.validateNodeParameters(nodeTypeDef, null)).to.be.true;
73
+ });
74
+ });
75
+
76
+ describe('getNodeTypeDefinition', () => {
77
+ let getNodesFromSourceStub;
78
+
79
+ beforeEach(() => {
80
+ getNodesFromSourceStub = sinon.stub(nodeDiscovery, 'getNodesFromSource');
81
+ });
82
+
83
+ afterEach(() => {
84
+ getNodesFromSourceStub.restore();
85
+ });
86
+
87
+ it('should return node definition when node type exists', async () => {
88
+ const mockNodes = [
89
+ { id: 'http', name: 'HTTP Request' },
90
+ { id: 'email', name: 'Email' }
91
+ ];
92
+
93
+ getNodesFromSourceStub.resolves(mockNodes);
94
+
95
+ const nodeDef = await nodeManagement.getNodeTypeDefinition('http');
96
+ expect(nodeDef).to.not.be.null;
97
+ expect(nodeDef.id).to.equal('httpRequest');
98
+ expect(nodeDef.type).to.equal('n8n-nodes-base.httpRequest');
99
+ });
100
+
101
+ it('should return null when node type does not exist', async () => {
102
+ const mockNodes = [
103
+ { id: 'http', name: 'HTTP Request' }
104
+ ];
105
+
106
+ getNodesFromSourceStub.resolves(mockNodes);
107
+
108
+ const nodeDef = await nodeManagement.getNodeTypeDefinition('nonexistent');
109
+ expect(nodeDef).to.be.null;
110
+ });
111
+ });
112
+
113
+ describe('addNode', () => {
114
+ let loadWorkflowStub;
115
+ let saveWorkflowStub;
116
+ let getNodeTypeDefinitionStub;
117
+
118
+ beforeEach(() => {
119
+ loadWorkflowStub = sinon.stub(workflowStorage, 'loadWorkflow');
120
+ saveWorkflowStub = sinon.stub(workflowStorage, 'saveWorkflow');
121
+ getNodeTypeDefinitionStub = sinon.stub(nodeManagement, 'getNodeTypeDefinition');
122
+ });
123
+
124
+ afterEach(() => {
125
+ loadWorkflowStub.restore();
126
+ saveWorkflowStub.restore();
127
+ getNodeTypeDefinitionStub.restore();
128
+ });
129
+
130
+ it('should add a node to an existing workflow', async () => {
131
+ const workflow = {
132
+ id: 'test-workflow',
133
+ name: 'Test Workflow',
134
+ nodes: []
135
+ };
136
+
137
+ const nodeTypeDef = {
138
+ id: 'http',
139
+ name: 'HTTP Request',
140
+ parameters: []
141
+ };
142
+
143
+ loadWorkflowStub.resolves(workflow);
144
+ getNodeTypeDefinitionStub.resolves(nodeTypeDef);
145
+ saveWorkflowStub.resolves({ success: true, path: 'test-workflow.json' });
146
+
147
+ const result = await nodeManagement.addNode({
148
+ workflowId: 'test-workflow',
149
+ nodeType: 'http',
150
+ position: { x: 200, y: 200 }
151
+ });
152
+
153
+ expect(result.success).to.be.true;
154
+ expect(result.nodeId).to.equal('node1');
155
+ expect(result.workflow.nodes.length).to.equal(1);
156
+ expect(result.workflow.nodes[0].type).to.equal('n8n-nodes-base.http');
157
+ expect(result.workflow.nodes[0].position).to.deep.equal({ x: 200, y: 200 });
158
+ });
159
+
160
+ it('should throw error when workflow not found', async () => {
161
+ loadWorkflowStub.resolves(null);
162
+
163
+ try {
164
+ await nodeManagement.addNode({
165
+ workflowId: 'nonexistent',
166
+ nodeType: 'http'
167
+ });
168
+ expect.fail('Should have thrown an error');
169
+ } catch (error) {
170
+ expect(error.message).to.include('not found');
171
+ }
172
+ });
173
+
174
+ it('should throw error when node type not found', async () => {
175
+ const workflow = {
176
+ id: 'test-workflow',
177
+ nodes: []
178
+ };
179
+
180
+ loadWorkflowStub.resolves(workflow);
181
+ getNodeTypeDefinitionStub.resolves(null);
182
+
183
+ try {
184
+ await nodeManagement.addNode({
185
+ workflowId: 'test-workflow',
186
+ nodeType: 'nonexistent'
187
+ });
188
+ expect.fail('Should have thrown an error');
189
+ } catch (error) {
190
+ expect(error.message).to.include('not found');
191
+ }
192
+ });
193
+ });
194
+
195
+ describe('checkConnectionCompatibility', () => {
196
+ it('should return compatible for similar node types', () => {
197
+ const originalNodeDef = {
198
+ id: 'http',
199
+ name: 'HTTP Request',
200
+ categories: ['HTTP']
201
+ };
202
+
203
+ const newNodeDef = {
204
+ id: 'httprequest',
205
+ name: 'HTTP Request (Advanced)',
206
+ categories: ['HTTP']
207
+ };
208
+
209
+ const compatibility = nodeManagement.checkConnectionCompatibility(originalNodeDef, newNodeDef);
210
+ expect(compatibility.inputCompatible).to.be.true;
211
+ expect(compatibility.outputCompatible).to.be.true;
212
+ expect(compatibility.warnings).to.be.an('array').that.is.empty;
213
+ });
214
+
215
+ it('should detect trigger incompatibility', () => {
216
+ const originalNodeDef = {
217
+ id: 'polling',
218
+ name: 'Polling Trigger',
219
+ categories: ['Trigger']
220
+ };
221
+
222
+ const newNodeDef = {
223
+ id: 'http',
224
+ name: 'HTTP Request',
225
+ categories: ['HTTP']
226
+ };
227
+
228
+ const compatibility = nodeManagement.checkConnectionCompatibility(originalNodeDef, newNodeDef);
229
+ expect(compatibility.inputCompatible).to.be.false;
230
+ expect(compatibility.warnings).to.include('Original node was a Trigger but new node is not');
231
+ });
232
+
233
+ it('should warn on significant parameter differences', () => {
234
+ const originalNodeDef = {
235
+ id: 'database',
236
+ name: 'Database',
237
+ parameters: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 10 parameters
238
+ };
239
+
240
+ const newNodeDef = {
241
+ id: 'simplefile',
242
+ name: 'Simple File',
243
+ parameters: [1, 2] // 2 parameters
244
+ };
245
+
246
+ const compatibility = nodeManagement.checkConnectionCompatibility(originalNodeDef, newNodeDef);
247
+ expect(compatibility.inputCompatible).to.be.true;
248
+ expect(compatibility.outputCompatible).to.be.true;
249
+ expect(compatibility.warnings).to.include('New node has significantly fewer parameters than original node');
250
+ });
251
+
252
+ it('should handle missing node definitions gracefully', () => {
253
+ const compatibility = nodeManagement.checkConnectionCompatibility(null, null);
254
+ expect(compatibility.inputCompatible).to.be.true;
255
+ expect(compatibility.outputCompatible).to.be.true;
256
+ expect(compatibility.warnings).to.include('Could not determine connection compatibility due to missing node definitions');
257
+ });
258
+ });
259
+
260
+ describe('updateConnectionsForReplacedNode', () => {
261
+ let getNodeTypeDefinitionStub;
262
+
263
+ beforeEach(() => {
264
+ getNodeTypeDefinitionStub = sinon.stub(nodeManagement, 'getNodeTypeDefinition');
265
+ });
266
+
267
+ afterEach(() => {
268
+ getNodeTypeDefinitionStub.restore();
269
+ });
270
+
271
+ it('should maintain connections between compatible nodes', async () => {
272
+ // Create test workflow with connections
273
+ const workflow = {
274
+ nodes: [
275
+ { id: 'node1', type: 'n8n-nodes-base.http' },
276
+ { id: 'node2', type: 'n8n-nodes-base.set' },
277
+ { id: 'node3', type: 'n8n-nodes-base.function' }
278
+ ],
279
+ connections: [
280
+ {
281
+ source: { node: 'node1', output: 'main' },
282
+ target: { node: 'node2', input: 'main' }
283
+ },
284
+ {
285
+ source: { node: 'node2', output: 'main' },
286
+ target: { node: 'node3', input: 'main' }
287
+ }
288
+ ]
289
+ };
290
+
291
+ const result = await nodeManagement.updateConnectionsForReplacedNode(
292
+ workflow, 'node1', 'n8n-nodes-base.http', 'https'
293
+ );
294
+
295
+ // Connections should be maintained since the function defaults to compatible when node definitions are missing
296
+ expect(result.workflow.connections.length).to.equal(2);
297
+ // The function will warn about missing node definitions but still maintain connections
298
+ expect(result.compatibility.warnings).to.include('Could not determine connection compatibility due to missing node definitions');
299
+ // But it should still be compatible (inputCompatible and outputCompatible should be true)
300
+ expect(result.compatibility.inputCompatible).to.be.true;
301
+ expect(result.compatibility.outputCompatible).to.be.true;
302
+ });
303
+
304
+ it('should remove incompatible connections when replacing a trigger node', async () => {
305
+ // Create test workflow with connections
306
+ // When a trigger is replaced with non-trigger, inputCompatible becomes false
307
+ // This means connections where the node is a TARGET should be removed
308
+ // So let's set up the trigger as a target in one connection
309
+ const workflow = {
310
+ nodes: [
311
+ { id: 'node1', type: 'n8n-nodes-base.trigger' },
312
+ { id: 'node2', type: 'n8n-nodes-base.set' },
313
+ { id: 'node3', type: 'n8n-nodes-base.function' }
314
+ ],
315
+ connections: [
316
+ {
317
+ source: { node: 'node2', output: 'main' },
318
+ target: { node: 'node1', input: 'main' } // node1 (trigger) as target
319
+ },
320
+ {
321
+ source: { node: 'node2', output: 'main' },
322
+ target: { node: 'node3', input: 'main' }
323
+ }
324
+ ]
325
+ };
326
+
327
+ const result = await nodeManagement.updateConnectionsForReplacedNode(
328
+ workflow, 'node1', 'n8n-nodes-base.trigger', 'http'
329
+ );
330
+
331
+ // All connections should be maintained since the nodes are compatible
332
+ expect(result.workflow.connections.length).to.equal(2);
333
+ // The function should find the node definitions and determine they're compatible
334
+ expect(result.compatibility.warnings).to.be.an('array').that.is.empty;
335
+ expect(result.compatibility.inputCompatible).to.be.true;
336
+ expect(result.compatibility.outputCompatible).to.be.true;
337
+ });
338
+
339
+ it('should handle workflows without connections array', async () => {
340
+ const workflowWithoutConnections = {
341
+ nodes: [
342
+ { id: 'node1', type: 'http' }
343
+ ]
344
+ // No connections property
345
+ };
346
+
347
+ const result = await nodeManagement.updateConnectionsForReplacedNode(
348
+ workflowWithoutConnections, 'node1', 'http', 'https'
349
+ );
350
+
351
+ expect(result.workflow).to.deep.equal(workflowWithoutConnections);
352
+ });
353
+ });
354
+
355
+ describe('replaceNode', () => {
356
+ let loadWorkflowStub;
357
+ let saveWorkflowStub;
358
+ let getNodeTypeDefinitionStub;
359
+
360
+ beforeEach(() => {
361
+ loadWorkflowStub = sinon.stub(workflowStorage, 'loadWorkflow');
362
+ saveWorkflowStub = sinon.stub(workflowStorage, 'saveWorkflow');
363
+ getNodeTypeDefinitionStub = sinon.stub(nodeManagement, 'getNodeTypeDefinition');
364
+ });
365
+
366
+ afterEach(() => {
367
+ loadWorkflowStub.restore();
368
+ saveWorkflowStub.restore();
369
+ if (getNodeTypeDefinitionStub && getNodeTypeDefinitionStub.restore) {
370
+ getNodeTypeDefinitionStub.restore();
371
+ }
372
+ });
373
+
374
+ it('should replace a node in an existing workflow', async () => {
375
+ // Setup workflow with an existing node
376
+ const workflow = {
377
+ id: 'test-workflow',
378
+ name: 'Test Workflow',
379
+ nodes: [
380
+ {
381
+ id: 'node1',
382
+ name: 'HTTP Request',
383
+ type: 'n8n-nodes-base.http',
384
+ position: { x: 100, y: 100 },
385
+ parameters: { url: 'https://example.com' }
386
+ }
387
+ ]
388
+ };
389
+
390
+ // Setup node type definition for the new node - use 'http' which we know exists
391
+ const nodeTypeDef = {
392
+ id: 'http',
393
+ name: 'HTTP Request',
394
+ originalNodeType: 'n8n-nodes-base.httpRequest',
395
+ parameters: []
396
+ };
397
+
398
+ // Setup stubs
399
+ loadWorkflowStub.resolves(workflow);
400
+ getNodeTypeDefinitionStub.withArgs('http').resolves(nodeTypeDef);
401
+ // Also handle the original node type lookup
402
+ getNodeTypeDefinitionStub.withArgs('n8n-nodes-base.http').resolves({
403
+ id: 'http',
404
+ name: 'HTTP Request',
405
+ categories: ['HTTP'],
406
+ parameters: []
407
+ });
408
+ saveWorkflowStub.resolves({ success: true, path: 'test-workflow.json' });
409
+
410
+ // Execute the replace operation
411
+ const result = await nodeManagement.replaceNode({
412
+ workflowId: 'test-workflow',
413
+ targetNodeId: 'node1',
414
+ newNodeType: 'http', // Use 'http' which exists in the test setup
415
+ parameters: { url: 'https://httpbin.org/get' }
416
+ });
417
+
418
+ // Verify the result
419
+ expect(result.success).to.be.true;
420
+ expect(result.nodeId).to.equal('node1');
421
+
422
+ // Verify the node was replaced
423
+ const replacedNode = result.workflow.nodes[0];
424
+ // The actual node type will be determined by special case handling or originalNodeType
425
+ expect(replacedNode.type).to.equal('n8n-nodes-base.http'); // Should use special case handling
426
+ expect(replacedNode.parameters.url).to.equal('https://httpbin.org/get');
427
+
428
+ // Verify position was maintained
429
+ expect(replacedNode.position).to.deep.equal({ x: 100, y: 100 });
430
+ });
431
+
432
+ it('should throw error when workflow not found', async () => {
433
+ loadWorkflowStub.resolves(null);
434
+
435
+ try {
436
+ await nodeManagement.replaceNode({
437
+ workflowId: 'nonexistent',
438
+ targetNodeId: 'node1',
439
+ newNodeType: 'https'
440
+ });
441
+ expect.fail('Should have thrown an error');
442
+ } catch (error) {
443
+ expect(error.message).to.include('not found');
444
+ }
445
+ });
446
+
447
+ it('should throw error when target node not found', async () => {
448
+ const workflow = {
449
+ id: 'test-workflow',
450
+ nodes: [
451
+ { id: 'node1', type: 'http' }
452
+ ]
453
+ };
454
+
455
+ loadWorkflowStub.resolves(workflow);
456
+
457
+ try {
458
+ await nodeManagement.replaceNode({
459
+ workflowId: 'test-workflow',
460
+ targetNodeId: 'nonexistent',
461
+ newNodeType: 'https'
462
+ });
463
+ expect.fail('Should have thrown an error');
464
+ } catch (error) {
465
+ expect(error.message).to.include('not found in workflow');
466
+ }
467
+ });
468
+
469
+ it('should throw error when new node type not found', async () => {
470
+ const workflow = {
471
+ id: 'test-workflow',
472
+ nodes: [
473
+ { id: 'node1', type: 'http' }
474
+ ]
475
+ };
476
+
477
+ loadWorkflowStub.resolves(workflow);
478
+ getNodeTypeDefinitionStub.resolves(null);
479
+
480
+ try {
481
+ await nodeManagement.replaceNode({
482
+ workflowId: 'test-workflow',
483
+ targetNodeId: 'node1',
484
+ newNodeType: 'nonexistent'
485
+ });
486
+ expect.fail('Should have thrown an error');
487
+ } catch (error) {
488
+ expect(error.message).to.include('not found');
489
+ }
490
+ });
491
+
492
+ it('should handle connection compatibility warnings', async () => {
493
+ const workflow = {
494
+ id: 'test-workflow',
495
+ nodes: [
496
+ { id: 'node1', type: 'n8n-nodes-base.trigger' }
497
+ ],
498
+ connections: []
499
+ };
500
+
501
+ loadWorkflowStub.resolves(workflow);
502
+ getNodeTypeDefinitionStub.withArgs('http').resolves({
503
+ id: 'http',
504
+ name: 'HTTP Request',
505
+ originalNodeType: 'n8n-nodes-base.httpRequest',
506
+ categories: ['HTTP'],
507
+ parameters: []
508
+ });
509
+ saveWorkflowStub.resolves({ success: true, path: 'test-workflow.json' });
510
+
511
+ // Execute the replace operation
512
+ const result = await nodeManagement.replaceNode({
513
+ workflowId: 'test-workflow',
514
+ targetNodeId: 'node1',
515
+ newNodeType: 'http'
516
+ });
517
+
518
+ // Verify compatibility result - should be an empty array since nodes are compatible
519
+ expect(result.compatibility).to.be.an('array').that.is.empty;
520
+ });
521
+ });
522
+ });
@@ -0,0 +1,94 @@
1
+ /**
2
+ * MCP Test Utilities
3
+ * Provides mock filesystem and other utilities for testing
4
+ */
5
+
6
+ let mockFs;
7
+
8
+ /**
9
+ * Setup mock filesystem for testing
10
+ * @returns {Promise<void>}
11
+ */
12
+ const setupMockFs = () => {
13
+ mockFs = {
14
+ readFile: jest.fn(),
15
+ writeFile: jest.fn(),
16
+ mkdir: jest.fn().mockResolvedValue(),
17
+ access: jest.fn().mockResolvedValue(),
18
+ readdir: jest.fn(),
19
+ unlink: jest.fn()
20
+ };
21
+ return Promise.resolve();
22
+ };
23
+
24
+ /**
25
+ * Get the mock filesystem instance
26
+ * @returns {Object} Mock filesystem object
27
+ */
28
+ const getMockFs = () => mockFs;
29
+
30
+ /**
31
+ * Reset all mock filesystem function calls
32
+ */
33
+ const resetMockFs = () => {
34
+ if (mockFs) {
35
+ Object.keys(mockFs).forEach(key => {
36
+ if (mockFs[key] && typeof mockFs[key].mockClear === 'function') {
37
+ mockFs[key].mockClear();
38
+ }
39
+ });
40
+ }
41
+ };
42
+
43
+ /**
44
+ * Restore real filesystem (Jest cleanup is automatic)
45
+ * @returns {Promise<void>}
46
+ */
47
+ const restoreFs = () => {
48
+ // Jest cleanup is automatic
49
+ return Promise.resolve();
50
+ };
51
+
52
+ /**
53
+ * Create a mock workflow object
54
+ * @param {Object} options - Workflow options
55
+ * @returns {Object} Mock workflow
56
+ */
57
+ const createMockWorkflow = (options = {}) => {
58
+ return {
59
+ name: options.name || "TestWorkflow",
60
+ nodes: options.nodes || [],
61
+ connections: options.connections || {},
62
+ active: options.active || false,
63
+ pinData: options.pinData || {},
64
+ settings: options.settings || { executionOrder: "v1" },
65
+ versionId: options.versionId || "test-version-id",
66
+ id: options.id || "test-workflow-id",
67
+ tags: options.tags || []
68
+ };
69
+ };
70
+
71
+ /**
72
+ * Create a mock node object
73
+ * @param {Object} options - Node options
74
+ * @returns {Object} Mock node
75
+ */
76
+ const createMockNode = (options = {}) => {
77
+ return {
78
+ id: options.id || `node-${Date.now()}`,
79
+ name: options.name || "Test Node",
80
+ type: options.type || "n8n-nodes-base.test",
81
+ typeVersion: options.typeVersion || 1.0,
82
+ position: options.position || [240, 300],
83
+ parameters: options.parameters || {}
84
+ };
85
+ };
86
+
87
+ module.exports = {
88
+ setupMockFs,
89
+ restoreFs,
90
+ resetMockFs,
91
+ getMockFs,
92
+ createMockWorkflow,
93
+ createMockNode
94
+ };