@kiberon-labs/behave-graph-flow 1.0.0 → 3.0.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 (378) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/manager.ts +6 -0
  4. package/.storybook/preview.ts +64 -0
  5. package/.storybook/styles.css +16 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/CHANGELOG.md +368 -0
  8. package/LICENSE +6 -0
  9. package/README.md +2 -2
  10. package/data/Polynomial.json +510 -0
  11. package/data/sequence.json +337 -0
  12. package/data/trigger-event.json +241 -0
  13. package/data/variable-change.json +210 -0
  14. package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
  15. package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
  16. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
  17. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
  18. package/dist/entry.css +4 -0
  19. package/dist/index.css +42 -0
  20. package/dist/index.css.map +1 -0
  21. package/dist/index.d.ts +3597 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +18009 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/noteImpl-KkrrWgJd.js +242 -0
  26. package/dist/noteImpl-KkrrWgJd.js.map +1 -0
  27. package/dist/styles.module-CvmpDkZj.css +3 -0
  28. package/dist/styles.module-CvmpDkZj.css.map +1 -0
  29. package/dist/styles.module-DZxg8aW9.js +271 -0
  30. package/dist/styles.module-DZxg8aW9.js.map +1 -0
  31. package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
  32. package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
  33. package/docs/notifications.md +246 -0
  34. package/docs/protocol.md +702 -0
  35. package/docs/specifics.md +191 -0
  36. package/package.json +82 -22
  37. package/postcss.config.ts +3 -4
  38. package/src/annotations/index.ts +32 -0
  39. package/src/components/FloatingToolbar/index.module.css +37 -0
  40. package/src/components/FloatingToolbar/index.tsx +256 -0
  41. package/src/components/Flow.tsx +287 -75
  42. package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
  43. package/src/components/contextMenus/NodePicker.module.css +274 -0
  44. package/src/components/contextMenus/NodePicker.tsx +481 -0
  45. package/src/components/contextMenus/edge.tsx +22 -0
  46. package/src/components/contextMenus/node.tsx +15 -0
  47. package/src/components/contextMenus/selection.tsx +11 -0
  48. package/src/components/controls/any/AnyControlImpl.tsx +14 -0
  49. package/src/components/controls/any/index.tsx +19 -0
  50. package/src/components/controls/boolean/index.tsx +13 -0
  51. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  52. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  53. package/src/components/controls/colorPicker/index.module.css +18 -0
  54. package/src/components/controls/colorPicker/index.tsx +61 -0
  55. package/src/components/controls/number/index.tsx +35 -0
  56. package/src/components/controls/string/index.tsx +16 -0
  57. package/src/components/edges/index.tsx +475 -0
  58. package/src/components/edges/offsetBezier.ts +134 -0
  59. package/src/components/hotKeys.tsx +20 -0
  60. package/src/components/layoutController/index.module.css +13 -0
  61. package/src/components/layoutController/index.tsx +140 -0
  62. package/src/components/layoutController/utils.ts +248 -0
  63. package/src/components/menubar/defaults.tsx +516 -0
  64. package/src/components/menubar/index.tsx +49 -0
  65. package/src/components/menubar/menuItem.module.css +31 -0
  66. package/src/components/menubar/menuItem.tsx +65 -0
  67. package/src/components/nodes/behave/Node.module.css +23 -0
  68. package/src/components/nodes/behave/Node.tsx +176 -0
  69. package/src/components/nodes/behave/NodeContainer.module.css +88 -0
  70. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  71. package/src/components/nodes/behave/index.tsx +14 -0
  72. package/src/components/nodes/group/index.tsx +109 -0
  73. package/src/components/nodes/wrapper/index.tsx +73 -0
  74. package/src/components/nodes/wrapper/styles.module.css +87 -0
  75. package/src/components/notifications/NotificationProvider.tsx +81 -0
  76. package/src/components/notifications/index.ts +2 -0
  77. package/src/components/notifications/utils.ts +71 -0
  78. package/src/components/panels/alignment/index.module.css +10 -0
  79. package/src/components/panels/alignment/index.tsx +244 -0
  80. package/src/components/panels/base/index.tsx +5 -0
  81. package/src/components/panels/base/styles.module.css +12 -0
  82. package/src/components/panels/common/PanelHeader.module.css +24 -0
  83. package/src/components/panels/common/PanelHeader.tsx +22 -0
  84. package/src/components/panels/common/SectionTitle.module.css +13 -0
  85. package/src/components/panels/common/SectionTitle.tsx +10 -0
  86. package/src/components/panels/events/EditEventPanel.tsx +324 -0
  87. package/src/components/panels/events/ManageEventsPanel.tsx +101 -0
  88. package/src/components/panels/events/index.tsx +23 -0
  89. package/src/components/panels/events/styles.module.css +178 -0
  90. package/src/components/panels/graphProperties/index.tsx +125 -0
  91. package/src/components/panels/history/index.tsx +92 -0
  92. package/src/components/panels/history/styles.module.css +97 -0
  93. package/src/components/panels/keymaps/index.module.css +68 -0
  94. package/src/components/panels/keymaps/index.tsx +166 -0
  95. package/src/components/panels/layers/index.tsx +245 -0
  96. package/src/components/panels/layers/styles.module.css +107 -0
  97. package/src/components/panels/legend/index.module.css +6 -0
  98. package/src/components/panels/legend/index.tsx +76 -0
  99. package/src/components/panels/logs/index.module.css +218 -0
  100. package/src/components/panels/logs/index.tsx +288 -0
  101. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  102. package/src/components/panels/nodeInputs/InputsGroup.tsx +65 -0
  103. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  104. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  105. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  106. package/src/components/panels/nodeInputs/OutputsGroup.tsx +55 -0
  107. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  108. package/src/components/panels/nodeInputs/index.module.css +308 -0
  109. package/src/components/panels/nodeInputs/index.tsx +349 -0
  110. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  111. package/src/components/panels/nodeInputs/useNodeInputsData.ts +153 -0
  112. package/src/components/panels/nodePicker/index.tsx +115 -0
  113. package/src/components/panels/panel/index.module.css +66 -0
  114. package/src/components/panels/panel/index.tsx +88 -0
  115. package/src/components/panels/search/index.module.css +16 -0
  116. package/src/components/panels/search/index.tsx +215 -0
  117. package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
  118. package/src/components/panels/systemSettings/index.tsx +251 -0
  119. package/src/components/panels/systemSettings/styles.module.css +138 -0
  120. package/src/components/panels/traces/GridLines.tsx +38 -0
  121. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  122. package/src/components/panels/traces/TraceLane.tsx +62 -0
  123. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  124. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  125. package/src/components/panels/traces/index.module.css +159 -0
  126. package/src/components/panels/traces/index.tsx +298 -0
  127. package/src/components/panels/traces/types.ts +48 -0
  128. package/src/components/panels/traces/useDerivedSpans.ts +307 -0
  129. package/src/components/panels/traces/utils.ts +33 -0
  130. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  131. package/src/components/panels/variables/ManageVariablesScreen.tsx +147 -0
  132. package/src/components/panels/variables/index.tsx +125 -0
  133. package/src/components/panels/variables/styles.module.css +149 -0
  134. package/src/components/primitives/icon.module.css +45 -0
  135. package/src/components/primitives/icon.tsx +38 -0
  136. package/src/components/sockets/input/index.tsx +83 -0
  137. package/src/components/sockets/input/styles.module.css +26 -0
  138. package/src/components/sockets/output/index.tsx +68 -0
  139. package/src/components/sockets/output/styles.module.css +22 -0
  140. package/src/css/notes.css +135 -0
  141. package/src/css/prosemirror.css +57 -0
  142. package/src/css/rc-dock.css +212 -0
  143. package/src/css/rc-menu.css +101 -0
  144. package/src/css/themes/kiberon.css +127 -0
  145. package/src/css/vars.css +198 -0
  146. package/src/css/vscode-elements.css +124 -0
  147. package/src/entry.css +4 -0
  148. package/src/generators/CallSubgraphGenerator.tsx +136 -0
  149. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  150. package/src/generators/GraphBoundaryGenerator.module.css +32 -0
  151. package/src/generators/GraphBoundaryGenerator.tsx +193 -0
  152. package/src/generators/SequenceGenerator.tsx +104 -0
  153. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  154. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  155. package/src/generators/callSubgraphSync.ts +126 -0
  156. package/src/generators/registerDefaultGenerators.ts +55 -0
  157. package/src/generators/registerDefaults.ts +26 -0
  158. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  159. package/src/hooks/useFlowHandlers.ts +154 -30
  160. package/src/hooks/useWasdPan.ts +210 -0
  161. package/src/index.css +134 -0
  162. package/src/index.ts +53 -18
  163. package/src/manifest/contributionRegistry.ts +93 -0
  164. package/src/manifest/index.ts +4 -0
  165. package/src/manifest/loadManifest.ts +82 -0
  166. package/src/manifest/manifestPlugin.ts +29 -0
  167. package/src/manifest/passthroughValueType.ts +40 -0
  168. package/src/plugin/alignment/index.ts +91 -0
  169. package/src/plugin/autosave/controller.ts +366 -0
  170. package/src/plugin/autosave/index.tsx +114 -0
  171. package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
  172. package/src/plugin/autosave/panel/index.tsx +1 -0
  173. package/src/plugin/autosave/panel/styles.module.css +56 -0
  174. package/src/plugin/autosave/settings.ts +65 -0
  175. package/src/plugin/autosave/storage.ts +147 -0
  176. package/src/plugin/docs/index.tsx +297 -0
  177. package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
  178. package/src/plugin/docs/panel/index.tsx +21 -0
  179. package/src/plugin/docs/panel/styles.module.css +174 -0
  180. package/src/plugin/graphrunner/actions.ts +326 -0
  181. package/src/plugin/graphrunner/buttons.tsx +95 -0
  182. package/src/plugin/graphrunner/client.ts +707 -0
  183. package/src/plugin/graphrunner/index.tsx +184 -0
  184. package/src/plugin/graphrunner/panel.tsx +386 -0
  185. package/src/plugin/graphrunner/runController.ts +283 -0
  186. package/src/plugin/graphrunner/runner.ts +187 -0
  187. package/src/plugin/graphrunner/session.ts +243 -0
  188. package/src/plugin/graphrunner/store.ts +196 -0
  189. package/src/plugin/graphrunner/styles.module.css +171 -0
  190. package/src/plugin/graphrunner/transport.ts +250 -0
  191. package/src/plugin/graphrunner/types.ts +693 -0
  192. package/src/plugin/graphrunner-local/execution-utils.ts +637 -0
  193. package/src/plugin/graphrunner-local/index.tsx +172 -0
  194. package/src/plugin/graphrunner-local/panel.tsx +187 -0
  195. package/src/plugin/graphrunner-local/store.ts +41 -0
  196. package/src/plugin/graphrunner-local/styles.module.css +82 -0
  197. package/src/plugin/graphrunner-local/transport.ts +1339 -0
  198. package/src/plugin/graphrunner-local/types.ts +10 -0
  199. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +635 -0
  200. package/src/plugin/graphrunner-webworker/index.tsx +140 -0
  201. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  202. package/src/plugin/graphrunner-webworker/store.ts +98 -0
  203. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  204. package/src/plugin/kitchen-sink/index.ts +38 -0
  205. package/src/plugin/layout/dagre.ts +131 -0
  206. package/src/plugin/layout/elk.ts +216 -0
  207. package/src/plugin/layout/index.ts +80 -0
  208. package/src/plugin/notes/FormatToolbar.tsx +200 -0
  209. package/src/plugin/notes/index.tsx +191 -0
  210. package/src/plugin/notes/nodeActions.ts +100 -0
  211. package/src/plugin/notes/note.tsx +20 -0
  212. package/src/plugin/notes/noteImpl.tsx +89 -0
  213. package/src/plugin/realtime/realtimeRunner.ts +624 -0
  214. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  215. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  216. package/src/specifics/VariableGetSpecific.tsx +110 -0
  217. package/src/specifics/VariableSetSpecific.tsx +110 -0
  218. package/src/store/actions.tsx +698 -0
  219. package/src/store/commands.ts +278 -0
  220. package/src/store/contextMenu.ts +192 -0
  221. package/src/store/controls.tsx +62 -0
  222. package/src/store/conversions.ts +47 -0
  223. package/src/store/documentation.tsx +69 -0
  224. package/src/store/events.tsx +116 -0
  225. package/src/store/flow.tsx +230 -0
  226. package/src/store/graphMeta.ts +39 -0
  227. package/src/store/hotKeys.tsx +364 -0
  228. package/src/store/layers.ts +259 -0
  229. package/src/store/legend.tsx +76 -0
  230. package/src/store/logs.ts +28 -0
  231. package/src/store/menubar.ts +41 -0
  232. package/src/store/refs.ts +84 -0
  233. package/src/store/registry.ts +51 -0
  234. package/src/store/selection.ts +22 -0
  235. package/src/store/settings.ts +99 -0
  236. package/src/store/settingsSchema.ts +210 -0
  237. package/src/store/socketGenerator.tsx +54 -0
  238. package/src/store/specific.tsx +75 -0
  239. package/src/store/specs.tsx +35 -0
  240. package/src/store/tabs.ts +282 -0
  241. package/src/store/toolbar.tsx +45 -0
  242. package/src/store/traces.ts +240 -0
  243. package/src/store/variables.ts +37 -0
  244. package/src/system/graph.ts +131 -0
  245. package/src/system/graphSession.ts +172 -0
  246. package/src/system/index.ts +6 -0
  247. package/src/system/notifications.ts +111 -0
  248. package/src/system/persistence.ts +82 -0
  249. package/src/system/plugin.ts +55 -0
  250. package/src/system/provider.tsx +86 -0
  251. package/src/system/pubsub.ts +323 -0
  252. package/src/system/system.ts +653 -0
  253. package/src/system/tabLoader.tsx +303 -0
  254. package/src/system/undoRedo.ts +103 -0
  255. package/src/transformers/Uigraph.ts +61 -0
  256. package/src/transformers/behaveToFlow.ts +16 -4
  257. package/src/transformers/contract.ts +87 -0
  258. package/src/transformers/flowToBehave.ts +40 -12
  259. package/src/types/NodeMetadata.ts +27 -0
  260. package/src/types/graph.ts +49 -0
  261. package/src/types/nodes.ts +50 -0
  262. package/src/types.ts +18 -0
  263. package/src/util/autoConvert.ts +200 -0
  264. package/src/util/colors.ts +1 -29
  265. package/src/util/downloadJson.ts +18 -0
  266. package/src/util/extractNodeMetadata.ts +16 -0
  267. package/src/util/getPickerFilters.ts +1 -1
  268. package/src/util/isBehaveNode.ts +6 -0
  269. package/src/util/isValidConnection.ts +51 -17
  270. package/src/util/mergeSockets.ts +29 -0
  271. package/src/util/serializeVariables.ts +66 -0
  272. package/src/util/sockets.ts +43 -0
  273. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  274. package/stories/apex/layoutController/index.stories.tsx +48 -0
  275. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  276. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  277. package/stories/components/colorpicker/index.stories.tsx +20 -0
  278. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  279. package/stories/components/contextMenus/node.stories.tsx +26 -0
  280. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  281. package/stories/components/controls/any/index.stories.tsx +19 -0
  282. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  283. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  284. package/stories/components/controls/number/index.stories.tsx +19 -0
  285. package/stories/components/controls/string/index.stories.tsx +19 -0
  286. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  287. package/stories/components/panels/alignment.stories.tsx +24 -0
  288. package/stories/components/panels/events.stories.tsx +38 -0
  289. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  290. package/stories/components/panels/history.stories.tsx +37 -0
  291. package/stories/components/panels/keymaps.stories.tsx +21 -0
  292. package/stories/components/panels/legend.stories.tsx +37 -0
  293. package/stories/components/panels/logs.stories.tsx +24 -0
  294. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  295. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  296. package/stories/components/panels/panel.stories.tsx +39 -0
  297. package/stories/components/panels/search.stories.tsx +24 -0
  298. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  299. package/stories/components/panels/traces.stories.tsx +225 -0
  300. package/stories/components/panels/variables.stories.tsx +24 -0
  301. package/stories/defaults/defaultStoryProvider.tsx +170 -0
  302. package/stories/defaults/systemGenerator.ts +43 -0
  303. package/stories/plugins/notes.stories.tsx +100 -0
  304. package/tests/autoConvert.test.ts +329 -0
  305. package/tests/autosavePlugin.test.ts +204 -0
  306. package/tests/callSubgraphSync.test.ts +148 -0
  307. package/tests/commandRegistry.test.ts +137 -0
  308. package/tests/components/edges/offsetBezier.test.ts +51 -0
  309. package/tests/components/layoutController/utils.test.ts +68 -0
  310. package/tests/components/panels/traces/utils.test.ts +52 -0
  311. package/tests/contract.test.ts +51 -0
  312. package/tests/contractSerialize.test.ts +62 -0
  313. package/tests/deriveSpans.test.ts +71 -0
  314. package/tests/flowToBehave.test.ts +27 -4
  315. package/tests/hotkeys.test.ts +79 -0
  316. package/tests/keepAliveLifecycle.test.ts +167 -0
  317. package/tests/loadManifest.test.ts +113 -0
  318. package/tests/noteMarkdown.test.ts +65 -0
  319. package/tests/notesPlugin.test.ts +162 -0
  320. package/tests/notifications.test.ts +87 -0
  321. package/tests/persistence.test.ts +51 -0
  322. package/tests/saveLoad.test.ts +373 -0
  323. package/tests/settings.test.ts +178 -0
  324. package/tests/traceStore.test.ts +46 -0
  325. package/tests/util/calculateNewEdge.test.ts +98 -0
  326. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  327. package/tests/util/hasPositionMetaData.test.ts +33 -0
  328. package/tests/util/isBehaveNode.test.ts +22 -0
  329. package/tests/util/isHandleConnected.test.ts +37 -0
  330. package/tests/util/mergeSockets.test.ts +43 -0
  331. package/tests/visual/README.md +64 -0
  332. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  333. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  334. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  335. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  336. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  337. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  338. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  339. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
  340. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  341. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  342. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  343. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  344. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  345. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  346. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  347. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  348. package/tests/visual/panels.visual.test.tsx +76 -0
  349. package/tests/wasdPan.test.ts +71 -0
  350. package/tsconfig.base.json +39 -0
  351. package/tsconfig.json +18 -59
  352. package/tsconfig.prod.json +23 -0
  353. package/tsdown.config.ts +15 -3
  354. package/typedoc.json +7 -7
  355. package/vite.config.js +7 -0
  356. package/vitest.config.ts +5 -2
  357. package/vitest.visual.config.ts +55 -0
  358. package/src/components/AutoSizeInput.tsx +0 -65
  359. package/src/components/Controls.tsx +0 -87
  360. package/src/components/InputSocket.tsx +0 -142
  361. package/src/components/Node.tsx +0 -68
  362. package/src/components/NodeContainer.tsx +0 -46
  363. package/src/components/NodePicker.tsx +0 -77
  364. package/src/components/OutputSocket.tsx +0 -58
  365. package/src/components/modals/ClearModal.tsx +0 -40
  366. package/src/components/modals/HelpModal.tsx +0 -36
  367. package/src/components/modals/LoadModal.tsx +0 -96
  368. package/src/components/modals/Modal.tsx +0 -64
  369. package/src/components/modals/SaveModal.tsx +0 -60
  370. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  371. package/src/hooks/useGraphRunner.ts +0 -104
  372. package/src/hooks/useMergeMap.ts +0 -14
  373. package/src/hooks/useNodeSpecJson.ts +0 -20
  374. package/src/hooks/useQueriableDefinitions.ts +0 -22
  375. package/src/styles.css +0 -8
  376. package/tailwind.config.ts +0 -19
  377. package/tests/tsconfig.json +0 -10
  378. /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
@@ -0,0 +1,373 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import {
3
+ registerCoreProfile,
4
+ writeNodeSpecsToJSON
5
+ } from '@kiberon-labs/behave-graph';
6
+ import { System } from '../src/system/system.js';
7
+ import { buildUIGraphJSON } from '../src/transformers/Uigraph.js';
8
+
9
+ describe('Save and Load Graph', () => {
10
+ let system: System;
11
+
12
+ beforeEach(() => {
13
+ // Create a system with a basic registry
14
+ const coreRegistry = registerCoreProfile({
15
+ nodes: {},
16
+ values: {},
17
+ dependencies: {}
18
+ });
19
+
20
+ const nodeSpecs = writeNodeSpecsToJSON(coreRegistry);
21
+ const registry = {
22
+ values: coreRegistry.values,
23
+ specs: nodeSpecs
24
+ };
25
+
26
+ system = new System(registry);
27
+ system.createSession('graph');
28
+ });
29
+
30
+ it('should save and load a graph with node positions', () => {
31
+ // Setup: Create a graph with positioned nodes
32
+ const initialNodes = [
33
+ {
34
+ id: 'node1',
35
+ type: 'behaveNode',
36
+ position: { x: 100, y: 200 },
37
+ data: {
38
+ type: 'lifecycle/onStart',
39
+ configuration: {},
40
+ ports: {},
41
+ annotations: {}
42
+ }
43
+ },
44
+ {
45
+ id: 'node2',
46
+ type: 'behaveNode',
47
+ position: { x: 300, y: 400 },
48
+ data: {
49
+ type: 'debug/log',
50
+ configuration: {},
51
+ ports: {},
52
+ annotations: {}
53
+ }
54
+ }
55
+ ];
56
+
57
+ const initialEdges = [
58
+ {
59
+ id: 'edge1',
60
+ source: 'node1',
61
+ target: 'node2',
62
+ sourceHandle: 'flow',
63
+ targetHandle: 'flow'
64
+ }
65
+ ];
66
+
67
+ system.nodeStore.getState().setNodes(initialNodes);
68
+ system.edgeStore.getState().setEdges(initialEdges);
69
+
70
+ // Save the graph
71
+ const savedGraph = buildUIGraphJSON(system.session!);
72
+
73
+ // Verify saved graph has nodes with positions
74
+ expect(savedGraph.nodes).toHaveLength(2);
75
+ expect(savedGraph.nodes[0].position).toEqual({ x: 100, y: 200 });
76
+ expect(savedGraph.nodes[1].position).toEqual({ x: 300, y: 400 });
77
+
78
+ // Clear the system
79
+ system.nodeStore.getState().setNodes([]);
80
+ system.edgeStore.getState().setEdges([]);
81
+
82
+ // Load the graph
83
+ system.graph.deseralize(savedGraph);
84
+ system.flowStore.getState().setGraph(savedGraph.flow, { skipLayout: true });
85
+
86
+ // Verify loaded nodes have correct positions
87
+ const loadedNodes = system.nodeStore.getState().nodes;
88
+ expect(loadedNodes).toHaveLength(2);
89
+ expect(loadedNodes[0].position).toEqual({ x: 100, y: 200 });
90
+ expect(loadedNodes[1].position).toEqual({ x: 300, y: 400 });
91
+ });
92
+
93
+ it('should preserve viewport when saving and loading', () => {
94
+ // Setup: Create nodes and set viewport
95
+ const mockReactFlow = {
96
+ getViewport: () => ({ x: 50, y: 100, zoom: 1.5 }),
97
+ setViewport: () => {}
98
+ };
99
+
100
+ system.refStore.getState().setRef('reactflow', mockReactFlow);
101
+
102
+ const initialNodes = [
103
+ {
104
+ id: 'node1',
105
+ type: 'behaveNode',
106
+ position: { x: 100, y: 200 },
107
+ data: {
108
+ type: 'lifecycle/onStart',
109
+ configuration: {},
110
+ ports: {},
111
+ annotations: {}
112
+ }
113
+ }
114
+ ];
115
+
116
+ system.nodeStore.getState().setNodes(initialNodes);
117
+
118
+ // Save the graph
119
+ const savedGraph = buildUIGraphJSON(system.session!);
120
+
121
+ // Verify viewport is saved
122
+ expect(savedGraph.user?.viewport).toEqual({ x: 50, y: 100, zoom: 1.5 });
123
+ });
124
+
125
+ it('should preserve variables when saving and loading', () => {
126
+ // Setup: Create variables
127
+ const variables = {
128
+ var1: {
129
+ id: 'var1',
130
+ name: 'myVariable',
131
+ valueTypeName: 'string',
132
+ initialValue: 'test value'
133
+ }
134
+ };
135
+
136
+ system.variableStore.getState().setVariables(variables);
137
+
138
+ // Add a node so we have something to save
139
+ const nodes = [
140
+ {
141
+ id: 'node1',
142
+ type: 'behaveNode',
143
+ position: { x: 0, y: 0 },
144
+ data: {
145
+ type: 'lifecycle/onStart',
146
+ configuration: {},
147
+ ports: {},
148
+ annotations: {}
149
+ }
150
+ }
151
+ ];
152
+ system.nodeStore.getState().setNodes(nodes);
153
+
154
+ // Save the graph
155
+ const savedGraph = buildUIGraphJSON(system.session!);
156
+
157
+ // Verify variables are in the flow
158
+ expect(savedGraph.flow.variables).toBeDefined();
159
+ expect(savedGraph.flow.variables?.length).toBe(1);
160
+ expect(savedGraph.flow.variables?.[0].name).toBe('myVariable');
161
+
162
+ // Clear variables
163
+ system.variableStore.getState().setVariables({});
164
+
165
+ // Load the graph
166
+ system.graph.deseralize(savedGraph);
167
+ system.flowStore.getState().setGraph(savedGraph.flow, { skipLayout: true });
168
+
169
+ // Verify variables are restored
170
+ const loadedVariables = system.variableStore.getState().variables;
171
+ expect(Object.keys(loadedVariables)).toHaveLength(1);
172
+ expect(loadedVariables['var1'].name).toBe('myVariable');
173
+ });
174
+
175
+ it('should preserve custom events when saving and loading', () => {
176
+ // Setup: Create custom events
177
+ const customEvents = [
178
+ {
179
+ id: 'event1',
180
+ name: 'customEvent',
181
+ parameters: []
182
+ }
183
+ ];
184
+
185
+ system.eventsStore.getState().setCustomEvents(customEvents);
186
+
187
+ // Add a node so we have something to save
188
+ const nodes = [
189
+ {
190
+ id: 'node1',
191
+ type: 'behaveNode',
192
+ position: { x: 0, y: 0 },
193
+ data: {
194
+ type: 'lifecycle/onStart',
195
+ configuration: {},
196
+ ports: {},
197
+ annotations: {}
198
+ }
199
+ }
200
+ ];
201
+ system.nodeStore.getState().setNodes(nodes);
202
+
203
+ // Save the graph
204
+ const savedGraph = buildUIGraphJSON(system.session!);
205
+
206
+ // Verify custom events are in the flow
207
+ expect(savedGraph.flow.customEvents).toEqual(customEvents);
208
+
209
+ // Clear events
210
+ system.eventsStore.getState().setCustomEvents([]);
211
+
212
+ // Load the graph
213
+ system.graph.deseralize(savedGraph);
214
+ system.flowStore.getState().setGraph(savedGraph.flow, { skipLayout: true });
215
+
216
+ // Verify custom events are restored
217
+ const loadedEvents = system.eventsStore.getState().getCustomEvents();
218
+ expect(loadedEvents).toEqual(customEvents);
219
+ });
220
+
221
+ it('should not overwrite node positions when loading with skipLayout', () => {
222
+ // Setup: Create a graph with specific positions
223
+ const nodesWithPositions = [
224
+ {
225
+ id: 'node1',
226
+ type: 'behaveNode',
227
+ position: { x: 100, y: 200 },
228
+ data: {
229
+ type: 'lifecycle/onStart',
230
+ configuration: {},
231
+ ports: {},
232
+ annotations: {}
233
+ }
234
+ }
235
+ ];
236
+
237
+ system.nodeStore.getState().setNodes(nodesWithPositions);
238
+
239
+ // Save the graph
240
+ const savedGraph = buildUIGraphJSON(system.session!);
241
+
242
+ // Modify the node position
243
+ system.nodeStore.getState().setNodes([
244
+ {
245
+ ...nodesWithPositions[0],
246
+ position: { x: 999, y: 999 }
247
+ }
248
+ ]);
249
+
250
+ // Load the graph with skipLayout
251
+ system.graph.deseralize(savedGraph);
252
+ system.flowStore.getState().setGraph(savedGraph.flow, { skipLayout: true });
253
+
254
+ // Verify positions from deseralize are preserved (not overwritten)
255
+ const loadedNodes = system.nodeStore.getState().nodes;
256
+ expect(loadedNodes[0].position).toEqual({ x: 100, y: 200 });
257
+ });
258
+
259
+ it('should apply auto-layout when loading graph without position metadata', () => {
260
+ // Create a plain GraphJSON without position metadata
261
+ const graphWithoutPositions = {
262
+ nodes: [
263
+ {
264
+ id: 'node1',
265
+ type: 'lifecycle/onStart',
266
+ metadata: {}
267
+ },
268
+ {
269
+ id: 'node2',
270
+ type: 'debug/log',
271
+ metadata: {}
272
+ }
273
+ ],
274
+ variables: [],
275
+ customEvents: []
276
+ };
277
+
278
+ // Load the graph (should apply auto-layout)
279
+ system.flowStore.getState().setGraph(graphWithoutPositions);
280
+
281
+ // Verify nodes were created with positions (auto-layout applied)
282
+ const loadedNodes = system.nodeStore.getState().nodes;
283
+ expect(loadedNodes).toHaveLength(2);
284
+ expect(loadedNodes[0].position).toBeDefined();
285
+ expect(loadedNodes[1].position).toBeDefined();
286
+ // Auto-layout should set non-zero positions
287
+ const hasLayout = loadedNodes.some(
288
+ (n) => n.position.x !== 0 || n.position.y !== 0
289
+ );
290
+ expect(hasLayout).toBe(true);
291
+ });
292
+
293
+ it('should handle round-trip save/load without data loss', () => {
294
+ // Setup a complete graph
295
+ const nodes = [
296
+ {
297
+ id: 'node1',
298
+ type: 'behaveNode',
299
+ position: { x: 100, y: 200 },
300
+ data: {
301
+ type: 'lifecycle/onStart',
302
+ configuration: {},
303
+ ports: {},
304
+ annotations: {}
305
+ }
306
+ },
307
+ {
308
+ id: 'node2',
309
+ type: 'behaveNode',
310
+ position: { x: 300, y: 400 },
311
+ data: {
312
+ type: 'debug/log',
313
+ configuration: { text: { value: 'test' } },
314
+ ports: {},
315
+ annotations: {}
316
+ }
317
+ }
318
+ ];
319
+
320
+ const edges = [
321
+ {
322
+ id: 'edge1',
323
+ source: 'node1',
324
+ target: 'node2',
325
+ sourceHandle: 'flow',
326
+ targetHandle: 'flow'
327
+ }
328
+ ];
329
+
330
+ const variables = {
331
+ var1: {
332
+ id: 'var1',
333
+ name: 'testVar',
334
+ valueTypeName: 'float',
335
+ initialValue: 42
336
+ }
337
+ };
338
+
339
+ system.nodeStore.getState().setNodes(nodes);
340
+ system.edgeStore.getState().setEdges(edges);
341
+ system.variableStore.getState().setVariables(variables);
342
+
343
+ // Save
344
+ const saved = buildUIGraphJSON(system.session!);
345
+
346
+ // Clear
347
+ system.nodeStore.getState().setNodes([]);
348
+ system.edgeStore.getState().setEdges([]);
349
+ system.variableStore.getState().setVariables({});
350
+
351
+ // Load
352
+ system.graph.deseralize(saved);
353
+ system.flowStore.getState().setGraph(saved.flow, { skipLayout: true });
354
+
355
+ // Verify everything is restored
356
+ const loadedNodes = system.nodeStore.getState().nodes;
357
+ const loadedEdges = system.edgeStore.getState().edges;
358
+ const loadedVars = system.variableStore.getState().variables;
359
+
360
+ expect(loadedNodes).toHaveLength(2);
361
+ expect(loadedNodes[0].position).toEqual({ x: 100, y: 200 });
362
+ expect(loadedNodes[1].data.configuration).toEqual({
363
+ text: { value: 'test' }
364
+ });
365
+
366
+ expect(loadedEdges).toHaveLength(1);
367
+ expect(loadedEdges[0].source).toBe('node1');
368
+ expect(loadedEdges[0].target).toBe('node2');
369
+
370
+ expect(Object.keys(loadedVars)).toHaveLength(1);
371
+ expect(loadedVars['var1'].initialValue).toBe(42);
372
+ });
373
+ });
@@ -0,0 +1,178 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { System } from '../src/system/system.js';
3
+ import { registerDefaults } from '../src/generators/registerDefaults.js';
4
+
5
+ describe('editor settings serialization', () => {
6
+ it('round-trips toggles and custom conversions', () => {
7
+ const a = new System();
8
+ a.systemSettings.getState().setAutoConvert(false);
9
+ a.systemSettings.getState().setGridSize(42);
10
+ a.registerConversion({ from: 'integer', to: 'string', nodeType: 'x/conv' });
11
+
12
+ const json = a.serializeSettings();
13
+
14
+ const b = new System();
15
+ b.applySettings(json);
16
+
17
+ expect(b.systemSettings.getState().autoConvert).toBe(false);
18
+ expect(b.systemSettings.getState().gridSize).toBe(42);
19
+ expect(b.conversionStore.getState().conversions).toEqual([
20
+ { from: 'integer', to: 'string', nodeType: 'x/conv' }
21
+ ]);
22
+ });
23
+
24
+ it('round-trips settings that the old hand-written store dropped', () => {
25
+ // inlineValues lacked a setter (so applySettings could not restore it) and
26
+ // setShowMenu was untyped , both fixed by the declarative schema.
27
+ const a = new System();
28
+ a.systemSettings.getState().setInlineValues(true);
29
+ a.systemSettings.getState().setShowMenu(false);
30
+
31
+ const b = new System();
32
+ b.applySettings(a.serializeSettings());
33
+
34
+ expect(b.systemSettings.getState().inlineValues).toBe(true);
35
+ expect(b.systemSettings.getState().showMenu).toBe(false);
36
+ });
37
+
38
+ it('does not persist transient settings (showSearch)', () => {
39
+ const a = new System();
40
+ a.systemSettings.getState().setShowSearch(true);
41
+ expect(a.serializeSettings().settings).not.toHaveProperty('showSearch');
42
+ });
43
+ });
44
+
45
+ describe('plugin-contributed settings (schema registry)', () => {
46
+ it('seeds the built-in descriptors so the panel auto-generates', () => {
47
+ const sys = new System();
48
+ const keys = sys.settingsSchema.getState().settings.map((s) => s.key);
49
+ expect(keys).toContain('edgeType');
50
+ expect(keys).toContain('autoConvert');
51
+ expect(sys.settingsSchema.getState().sectionOrder).toContain('Layout');
52
+ });
53
+
54
+ it('registerSetting adds a descriptor and seeds its default value', () => {
55
+ const sys = new System();
56
+ sys.registerSetting({
57
+ key: 'myPlugin.apiUrl',
58
+ section: 'My Plugin',
59
+ type: 'string',
60
+ default: 'https://example.com',
61
+ title: 'API URL'
62
+ });
63
+
64
+ expect(sys.getSetting('myPlugin.apiUrl')).toBe('https://example.com');
65
+ expect(
66
+ sys.settingsSchema
67
+ .getState()
68
+ .settings.some((s) => s.key === 'myPlugin.apiUrl')
69
+ ).toBe(true);
70
+ expect(sys.settingsSchema.getState().sectionOrder).toContain('My Plugin');
71
+ });
72
+
73
+ it('ignores a duplicate key without clobbering the original', () => {
74
+ const sys = new System();
75
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
76
+ try {
77
+ // edgeType is a built-in; a plugin must not be able to redefine it.
78
+ sys.registerSetting({
79
+ key: 'edgeType',
80
+ section: 'Hijack',
81
+ type: 'boolean',
82
+ default: true
83
+ });
84
+ expect(warn).toHaveBeenCalled();
85
+ const edge = sys.settingsSchema
86
+ .getState()
87
+ .settings.find((s) => s.key === 'edgeType');
88
+ expect(edge?.section).toBe('Layout');
89
+ } finally {
90
+ warn.mockRestore();
91
+ }
92
+ });
93
+
94
+ it('round-trips plugin setting values through persistence', () => {
95
+ const a = new System();
96
+ a.registerSetting({
97
+ key: 'myPlugin.autoStart',
98
+ section: 'My Plugin',
99
+ type: 'boolean',
100
+ default: false
101
+ });
102
+ a.setSetting('myPlugin.autoStart', true);
103
+
104
+ const json = a.serializeSettings();
105
+ expect(json.settings).toHaveProperty('myPlugin.autoStart', true);
106
+
107
+ const b = new System();
108
+ b.registerSetting({
109
+ key: 'myPlugin.autoStart',
110
+ section: 'My Plugin',
111
+ type: 'boolean',
112
+ default: false
113
+ });
114
+ b.applySettings(json);
115
+ expect(b.getSetting('myPlugin.autoStart')).toBe(true);
116
+ });
117
+
118
+ it('excludes persist:false plugin settings from serialization', () => {
119
+ const sys = new System();
120
+ sys.registerSetting({
121
+ key: 'myPlugin.scratch',
122
+ section: 'My Plugin',
123
+ type: 'boolean',
124
+ default: false,
125
+ persist: false
126
+ });
127
+ sys.setSetting('myPlugin.scratch', true);
128
+ expect(sys.serializeSettings().settings).not.toHaveProperty(
129
+ 'myPlugin.scratch'
130
+ );
131
+ });
132
+ });
133
+
134
+ describe('registerDefaults', () => {
135
+ it('registers built-in generators and is idempotent per editor', () => {
136
+ const sys = new System();
137
+ registerDefaults(sys);
138
+ const first = sys.socketGeneratorStore.getState().generators.length;
139
+ expect(first).toBeGreaterThan(0);
140
+
141
+ // Second call (e.g. another graph tab mounting) is a no-op.
142
+ expect(() => registerDefaults(sys)).not.toThrow();
143
+ expect(sys.socketGeneratorStore.getState().generators.length).toBe(first);
144
+ });
145
+
146
+ it('persists to and loads from a storage adapter', () => {
147
+ vi.useFakeTimers();
148
+ try {
149
+ const backing: Record<string, string> = {};
150
+ const storage = {
151
+ getItem: (k: string) => backing[k] ?? null,
152
+ setItem: (k: string, v: string) => {
153
+ backing[k] = v;
154
+ }
155
+ };
156
+
157
+ const a = new System();
158
+ a.enableSettingsPersistence(storage);
159
+ a.registerConversion({ from: 'float', to: 'string', nodeType: 'f/conv' });
160
+ a.systemSettings.getState().setShowGrid(false);
161
+ vi.advanceTimersByTime(400); // flush the debounced save
162
+
163
+ expect(Object.keys(backing).length).toBe(1);
164
+
165
+ // A fresh system loads the saved state on init.
166
+ const b = new System();
167
+ b.enableSettingsPersistence(storage);
168
+ expect(b.systemSettings.getState().showGrid).toBe(false);
169
+ expect(b.conversionStore.getState().conversions).toContainEqual({
170
+ from: 'float',
171
+ to: 'string',
172
+ nodeType: 'f/conv'
173
+ });
174
+ } finally {
175
+ vi.useRealTimers();
176
+ }
177
+ });
178
+ });
@@ -0,0 +1,46 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { traceStoreFactory } from '../src/store/traces.js';
3
+ import type { TraceSpan } from '../src/store/traces.js';
4
+
5
+ const newStore = () => traceStoreFactory({} as any).getState();
6
+
7
+ const usedLanes = (spans: TraceSpan[], size: number): Set<number> =>
8
+ new Set(spans.slice(0, size).map((s) => s.lane));
9
+
10
+ describe('trace store lane allocation', () => {
11
+ it('reuses a lane for sequential spans (closed before the next opens)', () => {
12
+ const s = newStore();
13
+ // A opens and closes, then B opens and closes , never overlapping.
14
+ s.addSpan({ nodeId: 'a', name: 'a', start: 0, end: Number.NaN });
15
+ s.updateSpan('a', { end: 1 });
16
+ s.addSpan({ nodeId: 'b', name: 'b', start: 2, end: Number.NaN });
17
+ s.updateSpan('b', { end: 3 });
18
+
19
+ const c = s.collector;
20
+ expect(c.size).toBe(2);
21
+ // Both land in lane 0 → the panel shows a single lane.
22
+ expect(usedLanes(c.spans, c.size)).toEqual(new Set([0]));
23
+ });
24
+
25
+ it('allocates separate lanes for concurrent (overlapping) spans', () => {
26
+ const s = newStore();
27
+ // Both open at once (no end between them) → must not share a lane.
28
+ s.addSpan({ nodeId: 'a', name: 'a', start: 0, end: Number.NaN });
29
+ s.addSpan({ nodeId: 'b', name: 'b', start: 0, end: Number.NaN });
30
+
31
+ const c = s.collector;
32
+ expect(c.size).toBe(2);
33
+ expect(usedLanes(c.spans, c.size)).toEqual(new Set([0, 1]));
34
+ });
35
+
36
+ it('keeps an open span as open (NaN end) until updateSpan closes it', () => {
37
+ const s = newStore();
38
+ s.addSpan({ nodeId: 'a', name: 'a', start: 5, end: Number.NaN });
39
+
40
+ const open = s.collector.spans[0]!;
41
+ expect(Number.isNaN(open.end)).toBe(true);
42
+
43
+ s.updateSpan('a', { end: 9 });
44
+ expect(s.collector.spans[0]!.end).toBe(9);
45
+ });
46
+ });
@@ -0,0 +1,98 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { calculateNewEdge } from '@/util/calculateNewEdge';
3
+ import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
4
+ import type { Node, OnConnectStartParams } from 'reactflow';
5
+
6
+ const specJSON = [
7
+ {
8
+ type: 'source/node',
9
+ inputs: [],
10
+ outputs: [{ name: 'out', valueType: 'flow' }]
11
+ },
12
+ {
13
+ type: 'target/node',
14
+ inputs: [{ name: 'in', valueType: 'flow' }],
15
+ outputs: []
16
+ }
17
+ ] as unknown as NodeSpecJSON[];
18
+
19
+ const originNode = { id: 'origin', type: 'source/node' } as Node;
20
+
21
+ describe('calculateNewEdge', () => {
22
+ it('wires source -> target when dragging from a source handle', () => {
23
+ const connection: OnConnectStartParams = {
24
+ nodeId: 'origin',
25
+ handleId: 'out',
26
+ handleType: 'source'
27
+ };
28
+
29
+ const edge = calculateNewEdge(
30
+ originNode,
31
+ 'target/node',
32
+ 'dest',
33
+ connection,
34
+ specJSON
35
+ );
36
+
37
+ expect(edge).toMatchObject({
38
+ source: 'origin',
39
+ sourceHandle: 'out',
40
+ target: 'dest',
41
+ targetHandle: 'in'
42
+ });
43
+ expect(typeof edge.id).toBe('string');
44
+ expect(edge.id.length).toBeGreaterThan(0);
45
+ });
46
+
47
+ it('wires target -> source when dragging from a target handle', () => {
48
+ const connection: OnConnectStartParams = {
49
+ nodeId: 'origin',
50
+ handleId: 'in',
51
+ handleType: 'target'
52
+ };
53
+ const targetOrigin = { id: 'origin', type: 'target/node' } as Node;
54
+
55
+ const edge = calculateNewEdge(
56
+ targetOrigin,
57
+ 'source/node',
58
+ 'dest',
59
+ connection,
60
+ specJSON
61
+ );
62
+
63
+ expect(edge).toMatchObject({
64
+ target: 'origin',
65
+ targetHandle: 'in',
66
+ source: 'dest',
67
+ sourceHandle: 'out'
68
+ });
69
+ });
70
+
71
+ it('matches the destination socket by value type', () => {
72
+ const multiSpec = [
73
+ {
74
+ type: 'source/node',
75
+ inputs: [],
76
+ outputs: [{ name: 'out', valueType: 'string' }]
77
+ },
78
+ {
79
+ type: 'target/node',
80
+ inputs: [
81
+ { name: 'flowIn', valueType: 'flow' },
82
+ { name: 'strIn', valueType: 'string' }
83
+ ],
84
+ outputs: []
85
+ }
86
+ ] as unknown as NodeSpecJSON[];
87
+
88
+ const edge = calculateNewEdge(
89
+ originNode,
90
+ 'target/node',
91
+ 'dest',
92
+ { nodeId: 'origin', handleId: 'out', handleType: 'source' },
93
+ multiSpec
94
+ );
95
+
96
+ expect(edge.targetHandle).toBe('strIn');
97
+ });
98
+ });