@motiadev/workbench 0.3.1-beta.87 → 0.3.1-beta.88-041205

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 (219) hide show
  1. package/dist/index.d.ts +3 -4
  2. package/dist/index.html +3 -2
  3. package/dist/index.js +2 -3
  4. package/dist/public/icon.png +0 -0
  5. package/dist/public/motia-dark.png +0 -0
  6. package/dist/public/motia-light.png +0 -0
  7. package/dist/src/App.d.ts +2 -0
  8. package/dist/src/App.js +19 -0
  9. package/dist/src/components/endpoints/endpoint-badge.d.ts +1 -1
  10. package/dist/src/components/endpoints/endpoint-badge.js +8 -8
  11. package/dist/src/components/endpoints/endpoint-call.d.ts +3 -3
  12. package/dist/src/components/endpoints/endpoint-call.js +28 -23
  13. package/dist/src/components/endpoints/endpoint-response-schema.d.ts +10 -0
  14. package/dist/src/components/endpoints/endpoint-response-schema.js +17 -0
  15. package/dist/src/components/endpoints/endpoint-response.d.ts +8 -0
  16. package/dist/src/components/endpoints/endpoint-response.js +39 -0
  17. package/dist/src/components/endpoints/endpoints-page.js +14 -0
  18. package/dist/src/components/endpoints/hooks/use-get-endpoints.d.ts +1 -15
  19. package/dist/src/components/endpoints/json-editor.d.ts +9 -0
  20. package/dist/src/components/endpoints/json-editor.js +31 -0
  21. package/dist/src/components/flow/flow-page.d.ts +1 -0
  22. package/dist/src/components/flow/flow-page.js +20 -0
  23. package/dist/src/components/flow/flow-tab-menu-item.d.ts +1 -0
  24. package/dist/src/components/flow/flow-tab-menu-item.js +15 -0
  25. package/dist/src/{views → components}/flow/flow-view.d.ts +1 -2
  26. package/dist/src/components/flow/flow-view.js +21 -0
  27. package/dist/src/components/flow/hooks/use-get-flow-state.d.ts +10 -0
  28. package/dist/src/{views → components}/flow/hooks/use-get-flow-state.js +17 -10
  29. package/dist/src/{views → components}/flow/hooks/use-organize-nodes.d.ts +1 -1
  30. package/dist/src/{views → components}/flow/hooks/use-save-workflow-config.d.ts +1 -1
  31. package/dist/src/components/flow/nodes/api-flow-node.d.ts +2 -0
  32. package/dist/src/{views → components}/flow/nodes/api-flow-node.js +1 -1
  33. package/dist/src/components/flow/nodes/cron-flow-node.d.ts +2 -0
  34. package/dist/src/components/flow/nodes/cron-flow-node.js +5 -0
  35. package/dist/src/{views → components}/flow/nodes/event-flow-node.d.ts +1 -1
  36. package/dist/src/components/flow/nodes/event-flow-node.js +5 -0
  37. package/dist/src/components/flow/nodes/noop-flow-node.d.ts +2 -0
  38. package/dist/src/{views → components}/flow/nodes/noop-flow-node.js +1 -1
  39. package/dist/src/components/header/header.js +3 -11
  40. package/dist/src/components/logs/log-detail.d.ts +3 -1
  41. package/dist/src/components/logs/log-detail.js +33 -11
  42. package/dist/src/components/logs/log-level-badge.js +6 -6
  43. package/dist/src/components/logs/log-level-dot.js +7 -7
  44. package/dist/src/components/logs/logs-page.js +26 -0
  45. package/dist/src/components/observability/events/code/function-call.js +1 -1
  46. package/dist/src/components/observability/events/trace-event.d.ts +1 -1
  47. package/dist/src/components/observability/events/trace-log-event.d.ts +1 -1
  48. package/dist/src/components/observability/events/trace-log-event.js +2 -2
  49. package/dist/src/components/observability/hooks/use-get-endtime.d.ts +1 -1
  50. package/dist/src/components/observability/trace-item/trace-item-detail.d.ts +1 -0
  51. package/dist/src/components/observability/trace-item/trace-item-detail.js +5 -4
  52. package/dist/src/components/observability/trace-item/trace-item.d.ts +1 -0
  53. package/dist/src/components/observability/trace-item/trace-item.js +11 -17
  54. package/dist/src/components/observability/trace-status.d.ts +6 -10
  55. package/dist/src/components/observability/trace-status.js +7 -32
  56. package/dist/src/components/observability/trace-timeline.js +16 -4
  57. package/dist/src/components/observability/traces-groups.d.ts +2 -2
  58. package/dist/src/components/observability/traces-groups.js +4 -4
  59. package/dist/src/components/observability/traces-page.js +12 -0
  60. package/dist/src/components/sidebar/sidebar.d.ts +8 -0
  61. package/dist/src/components/sidebar/sidebar.js +39 -0
  62. package/dist/src/components/states/hooks/states-hooks.d.ts +7 -3
  63. package/dist/src/components/states/hooks/states-hooks.js +5 -33
  64. package/dist/src/components/states/state-detail.d.ts +2 -1
  65. package/dist/src/components/states/state-detail.js +15 -9
  66. package/dist/src/components/states/state-value.js +7 -7
  67. package/dist/src/components/states/states-page.js +18 -0
  68. package/dist/src/components/ui/badge.d.ts +1 -1
  69. package/dist/src/components/ui/table.js +1 -1
  70. package/dist/src/components/ui/theme-toggle.js +4 -3
  71. package/dist/src/hooks/use-fetch-flows.d.ts +1 -5
  72. package/dist/src/hooks/use-fetch-flows.js +18 -13
  73. package/dist/src/hooks/use-log-listener.js +2 -2
  74. package/dist/src/hooks/use-update-handle-positions.d.ts +10 -0
  75. package/dist/src/hooks/use-update-handle-positions.js +35 -0
  76. package/dist/src/index.css +36 -176
  77. package/dist/src/lib/utils.d.ts +1 -0
  78. package/dist/src/lib/utils.js +4 -0
  79. package/dist/src/main.d.ts +1 -0
  80. package/dist/src/main.js +4 -11
  81. package/dist/src/publicComponents/api-node.js +2 -4
  82. package/dist/src/publicComponents/{base-handle.d.ts → base-node/base-handle.d.ts} +1 -0
  83. package/dist/src/publicComponents/base-node/base-handle.js +8 -0
  84. package/dist/src/publicComponents/base-node/base-node.d.ts +21 -0
  85. package/dist/src/publicComponents/base-node/base-node.js +13 -0
  86. package/dist/src/publicComponents/{emits.d.ts → base-node/emits.d.ts} +1 -1
  87. package/dist/src/publicComponents/base-node/emits.js +5 -0
  88. package/dist/src/{views/flow/nodes → publicComponents/base-node}/language-indicator.d.ts +1 -1
  89. package/dist/src/{views/flow/nodes → publicComponents/base-node}/language-indicator.js +8 -7
  90. package/dist/src/publicComponents/base-node/node-header.d.ts +12 -0
  91. package/dist/src/publicComponents/base-node/node-header.js +30 -0
  92. package/dist/src/publicComponents/base-node/node-sidebar.d.ts +18 -0
  93. package/dist/src/publicComponents/base-node/node-sidebar.js +20 -0
  94. package/dist/src/publicComponents/base-node/subscribe.js +4 -0
  95. package/dist/src/publicComponents/cron-node.d.ts +2 -1
  96. package/dist/src/publicComponents/cron-node.js +3 -4
  97. package/dist/src/publicComponents/event-node.d.ts +1 -5
  98. package/dist/src/publicComponents/event-node.js +4 -6
  99. package/dist/src/publicComponents/node-details.js +21 -12
  100. package/dist/src/publicComponents/node-props.d.ts +13 -6
  101. package/dist/src/publicComponents/noop-node.d.ts +3 -7
  102. package/dist/src/publicComponents/noop-node.js +3 -3
  103. package/dist/src/stores/use-flow-store.d.ts +18 -0
  104. package/dist/src/stores/use-flow-store.js +15 -0
  105. package/dist/src/stores/use-global-store.d.ts +24 -0
  106. package/dist/src/stores/use-global-store.js +20 -0
  107. package/dist/src/stores/{use-logs.d.ts → use-logs-store.d.ts} +1 -3
  108. package/dist/src/stores/use-logs-store.js +10 -0
  109. package/dist/src/stores/use-tabs-store.d.ts +17 -0
  110. package/dist/src/stores/use-tabs-store.js +13 -0
  111. package/dist/src/stores/use-theme-store.d.ts +17 -0
  112. package/dist/src/stores/use-theme-store.js +26 -0
  113. package/dist/src/types/endpoint.d.ts +14 -0
  114. package/dist/src/{views/flow/nodes/nodes.types.d.ts → types/flow.d.ts} +45 -0
  115. package/dist/src/types/flow.js +1 -0
  116. package/dist/tsconfig.app.tsbuildinfo +1 -1
  117. package/package.json +13 -12
  118. package/dist/public/.empty +0 -0
  119. package/dist/src/components/app-sidebar.d.ts +0 -1
  120. package/dist/src/components/app-sidebar.js +0 -12
  121. package/dist/src/components/endpoints/endpoints.d.ts +0 -1
  122. package/dist/src/components/endpoints/endpoints.js +0 -34
  123. package/dist/src/components/endpoints/selected-endpoint.d.ts +0 -7
  124. package/dist/src/components/endpoints/selected-endpoint.js +0 -7
  125. package/dist/src/components/logs/log-console.d.ts +0 -1
  126. package/dist/src/components/logs/log-console.js +0 -69
  127. package/dist/src/components/logs/log-field.d.ts +0 -7
  128. package/dist/src/components/logs/log-field.js +0 -20
  129. package/dist/src/components/logs/logs.d.ts +0 -1
  130. package/dist/src/components/logs/logs.js +0 -18
  131. package/dist/src/components/observability/observability-stats.d.ts +0 -5
  132. package/dist/src/components/observability/observability-stats.js +0 -17
  133. package/dist/src/components/states/states.d.ts +0 -1
  134. package/dist/src/components/states/states.js +0 -21
  135. package/dist/src/components/ui/BadgeCount.d.ts +0 -7
  136. package/dist/src/components/ui/BadgeCount.js +0 -13
  137. package/dist/src/components/ui/button.d.ts +0 -11
  138. package/dist/src/components/ui/button.js +0 -33
  139. package/dist/src/components/ui/card.d.ts +0 -8
  140. package/dist/src/components/ui/card.js +0 -16
  141. package/dist/src/components/ui/collapsible.d.ts +0 -5
  142. package/dist/src/components/ui/collapsible.js +0 -5
  143. package/dist/src/components/ui/dialog.d.ts +0 -19
  144. package/dist/src/components/ui/dialog.js +0 -22
  145. package/dist/src/components/ui/dropdown-menu.d.ts +0 -25
  146. package/dist/src/components/ui/dropdown-menu.js +0 -50
  147. package/dist/src/components/ui/input.d.ts +0 -3
  148. package/dist/src/components/ui/input.js +0 -8
  149. package/dist/src/components/ui/logo-icon.d.ts +0 -5
  150. package/dist/src/components/ui/logo-icon.js +0 -5
  151. package/dist/src/components/ui/navigation-menu.d.ts +0 -13
  152. package/dist/src/components/ui/navigation-menu.js +0 -30
  153. package/dist/src/components/ui/scroll-area.d.ts +0 -5
  154. package/dist/src/components/ui/scroll-area.js +0 -9
  155. package/dist/src/components/ui/select.d.ts +0 -13
  156. package/dist/src/components/ui/select.js +0 -25
  157. package/dist/src/components/ui/separator.d.ts +0 -4
  158. package/dist/src/components/ui/separator.js +0 -8
  159. package/dist/src/components/ui/sheet.d.ts +0 -25
  160. package/dist/src/components/ui/sheet.js +0 -36
  161. package/dist/src/components/ui/sidebar.d.ts +0 -12
  162. package/dist/src/components/ui/sidebar.js +0 -25
  163. package/dist/src/components/ui/skeleton.d.ts +0 -3
  164. package/dist/src/components/ui/skeleton.js +0 -6
  165. package/dist/src/components/ui/switch.d.ts +0 -4
  166. package/dist/src/components/ui/switch.js +0 -7
  167. package/dist/src/components/ui/tabs.d.ts +0 -7
  168. package/dist/src/components/ui/tabs.js +0 -12
  169. package/dist/src/components/ui/textarea.d.ts +0 -3
  170. package/dist/src/components/ui/textarea.js +0 -8
  171. package/dist/src/components/ui/tooltip.d.ts +0 -7
  172. package/dist/src/components/ui/tooltip.js +0 -11
  173. package/dist/src/hooks/use-list-flows.d.ts +0 -9
  174. package/dist/src/hooks/use-list-flows.js +0 -8
  175. package/dist/src/hooks/use-theme.d.ts +0 -6
  176. package/dist/src/hooks/use-theme.js +0 -28
  177. package/dist/src/publicComponents/base-handle.js +0 -10
  178. package/dist/src/publicComponents/base-node.d.ts +0 -16
  179. package/dist/src/publicComponents/base-node.js +0 -25
  180. package/dist/src/publicComponents/colorMap.d.ts +0 -6
  181. package/dist/src/publicComponents/colorMap.js +0 -6
  182. package/dist/src/publicComponents/components/header-bar.d.ts +0 -11
  183. package/dist/src/publicComponents/components/header-bar.js +0 -15
  184. package/dist/src/publicComponents/emits.js +0 -6
  185. package/dist/src/publicComponents/subscribe.js +0 -5
  186. package/dist/src/route-wrapper.d.ts +0 -2
  187. package/dist/src/route-wrapper.js +0 -5
  188. package/dist/src/routes/endpoints-page.js +0 -5
  189. package/dist/src/routes/flow.d.ts +0 -1
  190. package/dist/src/routes/flow.js +0 -11
  191. package/dist/src/routes/index.d.ts +0 -1
  192. package/dist/src/routes/index.js +0 -5
  193. package/dist/src/routes/logs-page.js +0 -12
  194. package/dist/src/routes/states-page.js +0 -5
  195. package/dist/src/routes/traces-page.js +0 -14
  196. package/dist/src/stores/use-logs.js +0 -52
  197. package/dist/src/views/flow/arrow-head.d.ts +0 -8
  198. package/dist/src/views/flow/arrow-head.js +0 -6
  199. package/dist/src/views/flow/flow-view.js +0 -48
  200. package/dist/src/views/flow/hooks/use-get-flow-state.d.ts +0 -52
  201. package/dist/src/views/flow/legend.d.ts +0 -4
  202. package/dist/src/views/flow/legend.js +0 -51
  203. package/dist/src/views/flow/nodes/api-flow-node.d.ts +0 -4
  204. package/dist/src/views/flow/nodes/event-flow-node.js +0 -5
  205. package/dist/src/views/flow/nodes/noop-flow-node.d.ts +0 -4
  206. /package/dist/src/{routes → components/endpoints}/endpoints-page.d.ts +0 -0
  207. /package/dist/src/{views → components}/flow/base-edge.d.ts +0 -0
  208. /package/dist/src/{views → components}/flow/base-edge.js +0 -0
  209. /package/dist/src/{views → components}/flow/flow-loader.d.ts +0 -0
  210. /package/dist/src/{views → components}/flow/flow-loader.js +0 -0
  211. /package/dist/src/{views → components}/flow/hooks/use-organize-nodes.js +0 -0
  212. /package/dist/src/{views → components}/flow/hooks/use-save-workflow-config.js +0 -0
  213. /package/dist/src/{views → components}/flow/node-organizer.d.ts +0 -0
  214. /package/dist/src/{views → components}/flow/node-organizer.js +0 -0
  215. /package/dist/src/{routes → components/logs}/logs-page.d.ts +0 -0
  216. /package/dist/src/{routes → components/observability}/traces-page.d.ts +0 -0
  217. /package/dist/src/{routes → components/states}/states-page.d.ts +0 -0
  218. /package/dist/src/publicComponents/{subscribe.d.ts → base-node/subscribe.d.ts} +0 -0
  219. /package/dist/src/{views/flow/nodes/nodes.types.js → types/endpoint.js} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  export { EventNode } from './src/publicComponents/event-node';
2
2
  export { ApiNode } from './src/publicComponents/api-node';
3
3
  export { NoopNode } from './src/publicComponents/noop-node';
4
- export { BaseNode } from './src/publicComponents/base-node';
5
- export { BaseHandle } from './src/publicComponents/base-handle';
4
+ export { BaseNode } from './src/publicComponents/base-node/base-node';
5
+ export { BaseHandle } from './src/publicComponents/base-node/base-handle';
6
6
  export { Position } from '@xyflow/react';
7
- export type { EventNodeData, ApiNodeData } from './src/views/flow/nodes/nodes.types';
7
+ export type { EventNodeData, ApiNodeData } from './src/types/flow';
8
8
  export type { ApiNodeProps, BaseNodeProps, CronNodeProps, EventNodeProps, NoopNodeProps, } from './src/publicComponents/node-props';
9
- export { Button } from './src/components/ui/button';
package/dist/index.html CHANGED
@@ -3,10 +3,11 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
 
6
+ <link rel="icon" type="image/png" href="/icon.png" />
6
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
7
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
8
9
  <link
9
- href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
10
+ href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
10
11
  rel="stylesheet"
11
12
  />
12
13
  <script src="https://cdn.amplitude.com/libs/analytics-browser-2.11.1-min.js.gz"></script>
@@ -23,7 +24,7 @@
23
24
  </script>
24
25
 
25
26
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
26
- <title>Motia</title>
27
+ <title>Motia Workbench</title>
27
28
  </head>
28
29
  <body class="dark">
29
30
  <div id="root"></div>
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export { EventNode } from './src/publicComponents/event-node';
2
2
  export { ApiNode } from './src/publicComponents/api-node';
3
3
  export { NoopNode } from './src/publicComponents/noop-node';
4
- export { BaseNode } from './src/publicComponents/base-node';
5
- export { BaseHandle } from './src/publicComponents/base-handle';
4
+ export { BaseNode } from './src/publicComponents/base-node/base-node';
5
+ export { BaseHandle } from './src/publicComponents/base-node/base-handle';
6
6
  export { Position } from '@xyflow/react';
7
- export { Button } from './src/components/ui/button';
Binary file
Binary file
Binary file
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const App: React.FC;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CollapsiblePanel, CollapsiblePanelGroup, TabsContent, TabsList, TabsTrigger } from '@motiadev/ui';
3
+ import { ReactFlowProvider } from '@xyflow/react';
4
+ import { File, GanttChart, Link2, LogsIcon } from 'lucide-react';
5
+ import { EndpointsPage } from './components/endpoints/endpoints-page';
6
+ import { FlowPage } from './components/flow/flow-page';
7
+ import { FlowTabMenuItem } from './components/flow/flow-tab-menu-item';
8
+ import { Header } from './components/header/header';
9
+ import { LogsPage } from './components/logs/logs-page';
10
+ import { TracesPage } from './components/observability/traces-page';
11
+ import { APP_SIDEBAR_CONTAINER_ID } from './components/sidebar/sidebar';
12
+ import { StatesPage } from './components/states/states-page';
13
+ import { useTabsStore } from './stores/use-tabs-store';
14
+ export const App = () => {
15
+ const tab = useTabsStore((state) => state.tab);
16
+ const setTopTab = useTabsStore((state) => state.setTopTab);
17
+ const setBottomTab = useTabsStore((state) => state.setBottomTab);
18
+ return (_jsxs("div", { className: "grid grid-rows-[auto_1fr] grid-cols-[1fr_auto] bg-background text-foreground h-screen", children: [_jsx("div", { className: "col-span-2", children: _jsx(Header, {}) }), _jsx("main", { className: "m-2 overflow-hidden", role: "main", children: _jsxs(CollapsiblePanelGroup, { autoSaveId: "app-panel", direction: "vertical", className: "gap-1 h-full", "aria-label": "Workbench panels", children: [_jsxs(CollapsiblePanel, { id: "top-panel", variant: 'tabs', defaultTab: tab.top, onTabChange: setTopTab, header: _jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "flow", children: _jsx(FlowTabMenuItem, {}) }), _jsxs(TabsTrigger, { value: "endpoint", children: [_jsx(Link2, {}), "Endpoint"] })] }), children: [_jsx(TabsContent, { value: "flow", className: "h-full", asChild: true, children: _jsx(ReactFlowProvider, { children: _jsx(FlowPage, {}) }) }), _jsx(TabsContent, { value: "endpoint", asChild: true, children: _jsx(EndpointsPage, {}) })] }), _jsxs(CollapsiblePanel, { id: "bottom-panel", variant: 'tabs', defaultTab: tab.bottom, onTabChange: setBottomTab, header: _jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "tracing", children: [_jsx(GanttChart, {}), " Tracing"] }), _jsxs(TabsTrigger, { value: "logs", children: [_jsx(LogsIcon, {}), "Logs"] }), _jsxs(TabsTrigger, { value: "states", children: [_jsx(File, {}), "States"] })] }), children: [_jsx(TabsContent, { value: "tracing", className: "max-h-fit", asChild: true, children: _jsx(TracesPage, {}) }), _jsx(TabsContent, { value: "logs", asChild: true, children: _jsx(LogsPage, {}) }), _jsx(TabsContent, { value: "states", asChild: true, children: _jsx(StatesPage, {}) })] })] }) }), _jsx("div", { id: APP_SIDEBAR_CONTAINER_ID })] }));
19
+ };
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { type VariantProps } from 'class-variance-authority';
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | null | undefined;
4
+ variant?: "POST" | "GET" | "DELETE" | "PUT" | "PATCH" | "HEAD" | "OPTIONS" | null | undefined;
5
5
  defaultVariants?: "variant" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
@@ -1,16 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cva } from 'class-variance-authority';
3
3
  import { cn } from '@/lib/utils';
4
- const badgeVariants = cva('inline-flex items-center rounded-lg border px-2 py-1 text-xs font-bold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', {
4
+ const badgeVariants = cva('rounded-lg px-2 py-1 text-sm font-mono font-bold transition-colors', {
5
5
  variants: {
6
6
  variant: {
7
- POST: 'bg-sky-500/50 text-sky-100',
8
- GET: 'bg-lime-500/50 text-lime-100',
9
- PUT: 'bg-yellow-500/50 text-yellow-100',
10
- DELETE: 'bg-red-500/50 text-red-100',
11
- PATCH: 'bg-yellow-500/50 text-yellow-100',
12
- HEAD: 'bg-blue-500/50 text-blue-100',
13
- OPTIONS: 'bg-purple-500/50 text-purple-100',
7
+ POST: 'bg-[#258DC3]/15 text-[#258DC3]',
8
+ GET: 'bg-[#709A2D]/15 text-[#709A2D]',
9
+ DELETE: 'bg-[#DE2134]/15 text-[#DE2134]',
10
+ PUT: 'bg-yellow-500/50 text-yellow-100', // TODO color
11
+ PATCH: 'bg-yellow-500/50 text-yellow-100', // TODO color
12
+ HEAD: 'bg-blue-500/50 text-blue-100', // TODO color
13
+ OPTIONS: 'bg-purple-500/50 text-purple-100', // TODO color
14
14
  },
15
15
  defaultVariants: {
16
16
  variant: 'bg-blue-500/50 text-blue-100',
@@ -1,8 +1,8 @@
1
- import React from 'react';
2
- import { ApiEndpoint } from './hooks/use-get-endpoints';
1
+ import { ApiEndpoint } from '@/types/endpoint';
2
+ import { FC } from 'react';
3
3
  type Props = {
4
4
  endpoint: ApiEndpoint;
5
5
  onClose: () => void;
6
6
  };
7
- export declare const EndpointCall: React.FC<Props>;
7
+ export declare const EndpointCall: FC<Props>;
8
8
  export {};
@@ -1,49 +1,46 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useMemo, useState } from 'react';
2
+ import { Sidebar } from '@/components/sidebar/sidebar';
3
+ import { Button, Input, Panel } from '@motiadev/ui';
3
4
  import { Loader2, Play, X } from 'lucide-react';
4
- import { Button } from '../ui/button';
5
- import { Input } from '../ui/input';
6
- import { Textarea } from '../ui/textarea';
5
+ import { useEffect, useMemo, useState } from 'react';
7
6
  import { EndpointBadge } from './endpoint-badge';
7
+ import { EndpointResponse } from './endpoint-response';
8
+ import { EndpointResponseSchema } from './endpoint-response-schema';
8
9
  import { useJsonSchemaToJson } from './hooks/use-json-schema-to-json';
9
10
  import { usePathParams } from './hooks/use-path-params';
10
- import { useStateStream } from './hooks/use-state-stream';
11
+ import { JsonEditor } from './json-editor';
11
12
  export const EndpointCall = ({ endpoint, onClose }) => {
12
13
  const shouldHaveBody = ['post', 'put', 'patch'].includes(endpoint.method.toLowerCase());
13
14
  const [isRequestLoading, setIsRequestLoading] = useState(false);
14
- const [responseCode, setResponseCode] = useState();
15
- const [responseBody, setResponseBody] = useState();
16
- const [executionTime, setExecutionTime] = useState();
15
+ const [responseCode, setResponseCode] = useState(undefined);
16
+ const [responseBody, setResponseBody] = useState(undefined);
17
+ const [executionTime, setExecutionTime] = useState(undefined);
17
18
  const { body, setBody } = useJsonSchemaToJson(endpoint.bodySchema);
18
- const [isJsonValid, setIsJsonValid] = useState(true);
19
+ const [isBodyValid, setIsBodyValid] = useState(true);
19
20
  const pathParams = usePathParams(endpoint.path);
20
21
  const [pathParamsValues, setPathParamsValues] = useState(pathParams?.reduce((acc, param) => ({ ...acc, [param]: '' }), {}));
21
22
  const [queryParamsValues, setQueryParamsValues] = useState(endpoint.queryParams?.reduce((acc, param) => ({ ...acc, [param.name]: '' }), {}) ?? {});
22
- const { data: responseBodyData, isStreamed } = useStateStream(responseBody);
23
23
  const isPlayEnabled = useMemo(() => {
24
24
  if (!pathParams)
25
25
  return true;
26
- if (shouldHaveBody && !isJsonValid)
26
+ if (shouldHaveBody && !isBodyValid)
27
27
  return false;
28
28
  return pathParams?.every((param) => pathParamsValues[param]);
29
- }, [pathParams, pathParamsValues, shouldHaveBody, isJsonValid]);
29
+ }, [pathParams, pathParamsValues, shouldHaveBody, isBodyValid]);
30
30
  const onPathParamChange = (param, value) => {
31
31
  setPathParamsValues((prev) => ({ ...prev, [param]: value }));
32
32
  };
33
33
  const onQueryParamChange = (param, value) => {
34
34
  setQueryParamsValues((prev) => ({ ...prev, [param]: value }));
35
35
  };
36
- const handleBodyChange = useCallback((e) => {
37
- const value = e.target.value;
38
- setBody(value);
39
- try {
40
- JSON.parse(value);
41
- setIsJsonValid(true);
36
+ useEffect(() => {
37
+ if (endpoint.id) {
38
+ setResponseCode(undefined);
39
+ setResponseBody(undefined);
40
+ setExecutionTime(undefined);
41
+ setIsRequestLoading(false);
42
42
  }
43
- catch {
44
- setIsJsonValid(false);
45
- }
46
- }, [setBody]);
43
+ }, [endpoint.id]);
47
44
  const handleRequest = async () => {
48
45
  setIsRequestLoading(true);
49
46
  const startTime = Date.now();
@@ -67,5 +64,13 @@ export const EndpointCall = ({ endpoint, onClose }) => {
67
64
  setExecutionTime(executionTime);
68
65
  setIsRequestLoading(false);
69
66
  };
70
- return (_jsxs("div", { className: "flex flex-col gap-2 overflow-y-auto", children: [_jsxs("div", { className: "text-xs flex flex-row gap-2 items-center justify-between w-full", children: [_jsx("span", { className: "font-bold", children: "Request" }), _jsx("div", { className: "flex flex-row gap-2 items-center hover:bg-white/10 rounded-md p-1", children: _jsx(X, { className: "cursor-pointer w-4 h-4", onClick: onClose }) })] }), _jsxs("div", { className: "flex flex-row gap-2 items-center", children: [_jsx(EndpointBadge, { variant: endpoint.method, children: endpoint.method.toUpperCase() }), _jsx("span", { className: "text-md font-bold", children: endpoint.path })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: endpoint.description }), !!pathParams.length && (_jsxs("div", { className: "flex flex-col gap-2 p-4 rounded-lg bg-muted", children: [_jsx("span", { className: "text-xs font-bold", children: "Path Params" }), _jsx("div", { className: "flex flex-col gap-4", children: pathParams.map((param) => (_jsxs("div", { className: "text-xs", children: [_jsx("div", { className: "font-bold mb-2", children: param }), _jsx(Input, { className: "w-full", value: pathParamsValues[param], onChange: (e) => onPathParamChange(param, e.target.value) })] }, param))) })] })), !!endpoint.queryParams?.length && (_jsxs("div", { className: "flex flex-col gap-2 p-4 rounded-lg bg-muted", children: [_jsx("span", { className: "text-xs font-bold", children: "Query Params" }), _jsx("div", { className: "flex flex-col gap-4", children: endpoint.queryParams.map((param) => (_jsxs("div", { className: "text-xs", children: [_jsx("div", { className: "font-bold mb-2", children: param.name }), _jsx(Input, { className: "w-full", value: queryParamsValues[param.name], onChange: (e) => onQueryParamChange(param.name, e.target.value) })] }, param.name))) })] })), shouldHaveBody && (_jsxs("div", { className: "flex flex-col gap-2 rounded-lg bg-muted", children: [_jsx("span", { className: "text-xs font-bold", children: "Body" }), _jsx(Textarea, { "data-testid": "endpoint-body-textarea", className: `w-full font-mono font-medium min-h-[200px] ${!isJsonValid ? 'border-red-500' : ''}`, value: body, onChange: handleBodyChange }), _jsx("span", { "data-testid": "endpoint-invalid-json-message", className: `text-xs text-red-500 ${isJsonValid ? 'invisible' : ''}`, children: "Invalid JSON" })] })), _jsxs(Button, { className: "w-fit", onClick: handleRequest, "data-testid": "endpoint-play-button", disabled: isRequestLoading || !isPlayEnabled, children: [isRequestLoading ? _jsx(Loader2, { className: "animate-spin" }) : _jsx(Play, {}), " Play"] }), responseCode !== undefined && (_jsxs("div", { className: "flex flex-col gap-2 rounded-lg bg-muted", "data-testid": "endpoint-response-container", children: [_jsxs("span", { className: "text-xs font-bold", children: [_jsx(EndpointBadge, { variant: responseCode >= 400 ? 'DELETE' : 'GET', children: responseCode }), " Execution time: ", _jsxs("span", { className: "text-muted-foreground", children: [executionTime, "ms"] })] }), isStreamed && (_jsxs("span", { className: "flex flex-row items-center font-medium text-muted-foreground text-xs", children: [_jsxs("span", { className: "ml-1 inline-block w-2 h-2 rounded-full bg-green-500 mr-2 relative", children: [_jsx("span", { className: "absolute inset-0 rounded-full bg-green-500 animate-[ping_1.5s_ease-in-out_infinite]" }), _jsx("span", { className: "absolute inset-0 rounded-full bg-green-500" })] }), "Object is being streamed, this is not the actual response from the API Endpoint"] })), _jsx("span", { className: "text-xs font-mono font-bold dark:bg-black/50 bg-white/50 p-2 rounded-lg whitespace-pre-wrap", children: JSON.stringify(responseBodyData, null, 2) })] }))] }));
67
+ return (_jsxs(Sidebar, { initialWidth: 600, title: _jsxs("div", { className: "flex flex-row gap-2 items-center", children: [_jsx(EndpointBadge, { variant: endpoint.method, children: endpoint.method.toUpperCase() }), _jsx("span", { className: "text-md font-bold", children: endpoint.path })] }), onClose: onClose, actions: [
68
+ {
69
+ icon: _jsx(X, { className: "cursor-pointer w-4 h-4", onClick: onClose }),
70
+ onClick: onClose,
71
+ },
72
+ ], children: [endpoint.description && (_jsx("div", { className: "rounded-lg border p-4 font-medium text-muted-foreground", children: endpoint.description })), !!pathParams.length && (_jsx(Panel, { title: "Path params", size: "sm", children: _jsx("table", { children: pathParams.map((param) => (_jsxs("tr", { children: [_jsx("td", { className: "flex flex-col font-bold leading-[36px]", children: param }), _jsx("td", { className: "w-2/3 pl-4", children: _jsx(Input, { className: "w-full", value: pathParamsValues[param], onChange: (e) => onPathParamChange(param, e.target.value) }) })] }, param))) }) })), !!endpoint.queryParams?.length && (_jsx(Panel, { title: "Query params", size: "sm", children: _jsx("table", { children: endpoint.queryParams.map((param) => (_jsxs("tr", { children: [_jsxs("td", { className: "flex flex-col", children: [_jsx("span", { className: "font-bold", children: param.name }), _jsx("span", { className: "text-md text-muted-foreground", children: param.description })] }), _jsx("td", { className: "w-2/3 pl-4", children: _jsx(Input, { className: "w-full", value: queryParamsValues[param.name], onChange: (e) => onQueryParamChange(param.name, e.target.value) }) })] }, param.name))) }) })), shouldHaveBody && (_jsx(Panel, { title: "Body", size: "sm", contentClassName: "p-0", children: _jsx(JsonEditor, { value: body, schema: endpoint.bodySchema, onChange: setBody, onValidate: setIsBodyValid }) })), _jsxs(Button, { className: "w-fit", onClick: handleRequest, variant: "accent", "data-testid": "endpoint-play-button", disabled: isRequestLoading || !isPlayEnabled, children: [isRequestLoading ? _jsx(Loader2, { className: "animate-spin" }) : _jsx(Play, {}), " Play"] }), _jsx(EndpointResponse, { responseCode: responseCode, responseBody: responseBody, executionTime: executionTime }), _jsx(EndpointResponseSchema, { items: Object.entries(endpoint?.responseSchema ?? {}).map(([status, schema]) => ({
73
+ responseCode: status,
74
+ bodySchema: schema,
75
+ })) })] }));
71
76
  };
@@ -0,0 +1,10 @@
1
+ import { FC } from 'react';
2
+ export type EndpointResponseItem = {
3
+ responseCode: string;
4
+ bodySchema: Record<string, Record<string, any>>;
5
+ };
6
+ type EndpointResponseProps = {
7
+ items: EndpointResponseItem[];
8
+ };
9
+ export declare const EndpointResponseSchema: FC<EndpointResponseProps>;
10
+ export {};
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { convertJsonSchemaToJson } from '@/components/endpoints/hooks/utils';
3
+ import { useThemeStore } from '@/stores/use-theme-store';
4
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@motiadev/ui';
5
+ import { useMemo } from 'react';
6
+ import ReactJson from 'react18-json-view';
7
+ const EndpointResponseSchemaItem = ({ responseCode, bodySchema }) => {
8
+ const theme = useThemeStore((store) => store.theme);
9
+ const schema = useMemo(() => convertJsonSchemaToJson(bodySchema), [bodySchema]);
10
+ return (_jsx(TabsContent, { value: responseCode, className: "border-t", children: _jsx("div", { className: "text-xs font-mono rounded-lg whitespace-pre-wrap", children: _jsx(ReactJson, { src: schema, dark: theme === 'dark', enableClipboard: false, style: { backgroundColor: 'transparent' } }) }) }, responseCode));
11
+ };
12
+ export const EndpointResponseSchema = ({ items }) => {
13
+ if (items.length === 0) {
14
+ return null;
15
+ }
16
+ return (_jsx("div", { className: "flex flex-col rounded-lg border", "data-testid": "endpoint-response-container", children: _jsxs(Tabs, { defaultValue: items[0].responseCode, children: [_jsx("div", { className: "flex items-center justify-between bg-card", children: _jsx(TabsList, { className: "bg-transparent p-0", children: items.map((item) => (_jsx(TabsTrigger, { value: item.responseCode, className: "text-xs font-bold cursor-pointer", children: item.responseCode }, item.responseCode))) }) }), items.map((props) => (_jsx(EndpointResponseSchemaItem, { ...props }, props.responseCode)))] }) }));
17
+ };
@@ -0,0 +1,8 @@
1
+ import { FC } from 'react';
2
+ type EndpointResponseProps = {
3
+ responseCode: number | string | undefined;
4
+ responseBody: Record<string, any> | undefined;
5
+ executionTime?: number;
6
+ };
7
+ export declare const EndpointResponse: FC<EndpointResponseProps>;
8
+ export {};
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useStateStream } from '@/components/endpoints/hooks/use-state-stream';
3
+ import { useThemeStore } from '@/stores/use-theme-store';
4
+ import { Panel } from '@motiadev/ui';
5
+ import { XCircle } from 'lucide-react';
6
+ import { useMemo } from 'react';
7
+ import ReactJson from 'react18-json-view';
8
+ const getStatusMessage = (status) => {
9
+ switch (status) {
10
+ case 200:
11
+ return 'OK';
12
+ case 201:
13
+ return 'Created';
14
+ case 204:
15
+ return 'No Content';
16
+ case 400:
17
+ return 'Bad Request';
18
+ case 401:
19
+ return 'Unauthorized';
20
+ case 403:
21
+ return 'Forbidden';
22
+ case 404:
23
+ return 'Not Found';
24
+ case 500:
25
+ return 'Internal Server Error';
26
+ default:
27
+ return 'Unknown Status';
28
+ }
29
+ };
30
+ export const EndpointResponse = ({ responseCode, executionTime, responseBody }) => {
31
+ const theme = useThemeStore((state) => state.theme);
32
+ const { data, isStreamed } = useStateStream(responseBody);
33
+ const statusMessage = useMemo(() => getStatusMessage(Number(responseCode)), [responseCode]);
34
+ const isError = Number(responseCode) >= 400;
35
+ if (!responseBody || !responseCode) {
36
+ return null;
37
+ }
38
+ return (_jsx(Panel, { title: _jsxs("div", { className: "flex flex-row justify-between items-center flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [isError && _jsx(XCircle, { className: "text-red-500 w-4 h-4" }), _jsxs("span", { className: "font-bold text-xs", children: [responseCode, " - ", statusMessage] })] }), !!executionTime && (_jsxs("span", { className: "text-xs text-muted-foreground justify-self-end", children: ["Execution time: ", _jsxs("span", { className: "font-bold", children: [executionTime, "ms"] })] }))] }), subtitle: isStreamed && (_jsxs("span", { className: "col-span-2 flex flex-row items-center font-medium text-card-foreground text-xs mt-2", children: [_jsxs("span", { className: "inline-block w-2 h-2 rounded-full bg-green-500 mr-2 relative", children: [_jsx("span", { className: "absolute inset-0 rounded-full bg-green-500 animate-[ping_1.5s_ease-in-out_infinite]" }), _jsx("span", { className: "absolute inset-0 rounded-full bg-green-500" })] }), "Object is being streamed, this is not the actual response from the API Endpoint"] })), children: _jsx(ReactJson, { src: data, dark: theme === 'dark', enableClipboard: false, style: { backgroundColor: 'transparent' } }) }));
39
+ };
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '@/lib/utils';
3
+ import { useGlobalStore } from '@/stores/use-global-store';
4
+ import { useMemo } from 'react';
5
+ import { EndpointBadge } from './endpoint-badge';
6
+ import { EndpointCall } from './endpoint-call';
7
+ import { useGetEndpoints } from './hooks/use-get-endpoints';
8
+ export const EndpointsPage = () => {
9
+ const endpoints = useGetEndpoints();
10
+ const selectedEndpointId = useGlobalStore((state) => state.selectedEndpointId);
11
+ const selectEndpointId = useGlobalStore((state) => state.selectEndpointId);
12
+ const selectedEndpoint = useMemo(() => selectedEndpointId && endpoints.find((endpoint) => endpoint.id === selectedEndpointId), [endpoints, selectedEndpointId]);
13
+ return (_jsxs("div", { className: "flex flex-row w-full h-full", children: [_jsx("div", { className: "flex flex-col flex-1 overflow-y-auto", children: endpoints.map((endpoint) => (_jsx("div", { "data-testid": `endpoint-${endpoint.method}-${endpoint.path}`, className: cn(selectedEndpoint === endpoint && 'bg-muted-foreground/10', 'cursor-pointer select-none'), onClick: () => selectEndpointId(endpoint.id), children: _jsxs("div", { className: "flex flex-row gap-2 items-center hover:bg-muted-foreground/10 p-2", children: [_jsx(EndpointBadge, { variant: endpoint.method, children: endpoint.method.toUpperCase() }), _jsx("span", { className: "text-md font-mono font-bold whitespace-nowrap", children: endpoint.path }), _jsx("span", { className: "text-md text-muted-foreground truncate", children: endpoint.description })] }) }, `${endpoint.method} ${endpoint.path}`))) }), selectedEndpoint && _jsx(EndpointCall, { endpoint: selectedEndpoint, onClose: () => selectEndpointId(undefined) })] }));
14
+ };
@@ -1,16 +1,2 @@
1
- type ApiRouteMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';
2
- type QueryParam = {
3
- name: string;
4
- description: string;
5
- };
6
- export type ApiEndpoint = {
7
- id: string;
8
- method: ApiRouteMethod;
9
- path: string;
10
- description?: string;
11
- queryParams?: QueryParam[];
12
- responseSchema?: Record<string, any>;
13
- bodySchema?: Record<string, Record<string, any>>;
14
- };
1
+ import { ApiEndpoint } from '@/types/endpoint';
15
2
  export declare const useGetEndpoints: () => ApiEndpoint[];
16
- export {};
@@ -0,0 +1,9 @@
1
+ import { FC } from 'react';
2
+ type JsonEditorProps = {
3
+ value: string;
4
+ schema: Record<string, unknown> | undefined;
5
+ onChange: (value: string) => void;
6
+ onValidate: (isValid: boolean) => void;
7
+ };
8
+ export declare const JsonEditor: FC<JsonEditorProps>;
9
+ export {};
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useMemo } from 'react';
3
+ import Editor, { useMonaco } from '@monaco-editor/react';
4
+ import { useThemeStore } from '@/stores/use-theme-store';
5
+ export const JsonEditor = ({ value, schema, onChange, onValidate }) => {
6
+ const monaco = useMonaco();
7
+ const theme = useThemeStore((state) => state.theme);
8
+ const editorTheme = useMemo(() => (theme === 'dark' ? 'vs-dark' : 'light'), [theme]);
9
+ useEffect(() => {
10
+ if (!monaco || !schema)
11
+ return;
12
+ monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
13
+ validate: true,
14
+ schemas: [
15
+ {
16
+ uri: window.location.href,
17
+ fileMatch: ['*'],
18
+ schema,
19
+ },
20
+ ],
21
+ });
22
+ }, [monaco, schema]);
23
+ return (_jsx(Editor, { height: "200px", language: "json", value: value, theme: editorTheme, onChange: (value) => {
24
+ onChange(value ?? '');
25
+ }, onValidate: (markers) => {
26
+ onValidate(markers.length === 0);
27
+ }, options: {
28
+ lineNumbers: 'off',
29
+ minimap: { enabled: false },
30
+ } }));
31
+ };
@@ -0,0 +1 @@
1
+ export declare const FlowPage: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useFlowStore } from '@/stores/use-flow-store';
3
+ import { useStreamItem } from '@motiadev/stream-client-react';
4
+ import { FlowView } from './flow-view';
5
+ export const FlowPage = () => {
6
+ const selectedFlowId = useFlowStore((state) => state.selectedFlowId);
7
+ const { data: flow } = useStreamItem({
8
+ streamName: '__motia.flows',
9
+ groupId: 'default',
10
+ id: selectedFlowId ?? '',
11
+ });
12
+ const { data: flowConfig } = useStreamItem({
13
+ streamName: '__motia.flowsConfig',
14
+ groupId: 'default',
15
+ id: selectedFlowId ?? '',
16
+ });
17
+ if (!flow || flow.error)
18
+ return (_jsx("div", { className: "w-full h-full bg-background flex flex-col items-center justify-center", children: _jsx("p", { children: flow?.error }) }));
19
+ return _jsx(FlowView, { flow: flow, flowConfig: flowConfig });
20
+ };
@@ -0,0 +1 @@
1
+ export declare const FlowTabMenuItem: () => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@motiadev/ui';
3
+ import { ChevronsUpDown, Workflow } from 'lucide-react';
4
+ import { useFlowStore } from '@/stores/use-flow-store';
5
+ import { useFetchFlows } from '@/hooks/use-fetch-flows';
6
+ export const FlowTabMenuItem = () => {
7
+ useFetchFlows();
8
+ const selectFlowId = useFlowStore((state) => state.selectFlowId);
9
+ const flows = useFlowStore((state) => state.flows);
10
+ const selectedFlowId = useFlowStore((state) => state.selectedFlowId);
11
+ if (flows.length === 0) {
12
+ return null;
13
+ }
14
+ return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("div", { className: "flex flex-row justify-center items-center gap-2 cursor-pointer", children: [_jsx(Workflow, {}), selectedFlowId ?? 'No flow selected', _jsx(ChevronsUpDown, { className: "size-4" })] }) }), _jsx(DropdownMenuContent, { className: "bg-background text-foreground", children: flows.map((item) => (_jsx(DropdownMenuItem, { className: "cursor-pointer gap-2", onClick: () => selectFlowId(item), children: item }, `dropdown-${item}`))) })] }));
15
+ };
@@ -1,7 +1,6 @@
1
+ import { EdgeData, FlowConfigResponse, FlowResponse, NodeData } from '@/types/flow';
1
2
  import { Edge as ReactFlowEdge, Node as ReactFlowNode } from '@xyflow/react';
2
3
  import React from 'react';
3
- import { EdgeData, NodeData } from './nodes/nodes.types';
4
- import { FlowConfigResponse, FlowResponse } from './hooks/use-get-flow-state';
5
4
  import '@xyflow/react/dist/style.css';
6
5
  export type FlowNode = ReactFlowNode<NodeData>;
7
6
  export type FlowEdge = ReactFlowEdge<EdgeData>;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Background, BackgroundVariant, ReactFlow, } from '@xyflow/react';
3
+ import { useCallback, useState } from 'react';
4
+ import { BaseEdge } from './base-edge';
5
+ import { FlowLoader } from './flow-loader';
6
+ import { useGetFlowState } from './hooks/use-get-flow-state';
7
+ import { NodeOrganizer } from './node-organizer';
8
+ import '@xyflow/react/dist/style.css';
9
+ const edgeTypes = {
10
+ base: BaseEdge,
11
+ };
12
+ export const FlowView = ({ flow, flowConfig }) => {
13
+ const { nodes, edges, onNodesChange, onEdgesChange, nodeTypes } = useGetFlowState(flow, flowConfig);
14
+ const [initialized, setInitialized] = useState(false);
15
+ const onInitialized = useCallback(() => setInitialized(true), []);
16
+ const onNodesChangeHandler = useCallback((changes) => onNodesChange(changes), [onNodesChange]);
17
+ if (!nodeTypes) {
18
+ return null;
19
+ }
20
+ return (_jsxs("div", { className: "w-full h-full relative", children: [!initialized && _jsx(FlowLoader, {}), _jsxs(ReactFlow, { nodes: nodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodesChange: onNodesChangeHandler, onEdgesChange: onEdgesChange, children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 50, size: 2, className: "[--xy-background-color-dots:theme(colors.muted.DEFAULT)] [--xy-background-color:theme(colors.background)]" }), _jsx(NodeOrganizer, { onInitialized: onInitialized })] })] }));
21
+ };
@@ -0,0 +1,10 @@
1
+ import type { EdgeData, FlowConfigResponse, FlowResponse, NodeData } from '@/types/flow';
2
+ import { Edge, Node } from '@xyflow/react';
3
+ import React from 'react';
4
+ export declare const useGetFlowState: (flow: FlowResponse, flowConfig: FlowConfigResponse) => {
5
+ nodes: Node<NodeData>[];
6
+ edges: Edge<EdgeData>[];
7
+ onNodesChange: import("@xyflow/react").OnNodesChange<Node<NodeData>>;
8
+ onEdgesChange: import("@xyflow/react").OnEdgesChange<Edge<EdgeData>>;
9
+ nodeTypes: Record<string, React.ComponentType<any>>;
10
+ };
@@ -1,14 +1,14 @@
1
1
  import { useEdgesState, useNodesState } from '@xyflow/react';
2
- import { useCallback, useEffect, useRef, useState, useMemo } from 'react';
2
+ import isEqual from 'fast-deep-equal';
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
4
  import { ApiFlowNode } from '../nodes/api-flow-node';
4
- import { NoopFlowNode } from '../nodes/noop-flow-node';
5
+ import { CronFlowNode } from '../nodes/cron-flow-node';
5
6
  import { EventFlowNode } from '../nodes/event-flow-node';
6
- import { CronNode } from '@/publicComponents/cron-node';
7
- import isEqual from 'fast-deep-equal';
8
- import { useSaveWorkflowConfig } from '@/views/flow/hooks/use-save-workflow-config';
9
- const DEFAULT_POSITION = { x: 0, y: 0 };
7
+ import { NoopFlowNode } from '../nodes/noop-flow-node';
8
+ import { useSaveWorkflowConfig } from './use-save-workflow-config';
9
+ const DEFAULT_CONFIG = { x: 0, y: 0 };
10
10
  const getNodePosition = (flowConfig, stepName) => {
11
- return flowConfig?.config[stepName] || DEFAULT_POSITION;
11
+ return flowConfig?.config[stepName] || DEFAULT_CONFIG;
12
12
  };
13
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
14
  const nodeComponentCache = new Map();
@@ -17,7 +17,7 @@ const BASE_NODE_TYPES = {
17
17
  event: EventFlowNode,
18
18
  api: ApiFlowNode,
19
19
  noop: NoopFlowNode,
20
- cron: CronNode,
20
+ cron: CronFlowNode,
21
21
  };
22
22
  async function importFlow(flow, flowConfig) {
23
23
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -46,8 +46,8 @@ async function importFlow(flow, flowConfig) {
46
46
  id: step.id,
47
47
  type: step.nodeComponentPath || step.type,
48
48
  filePath: step.filePath,
49
- position: step.filePath ? getNodePosition(flowConfig, step.filePath) : DEFAULT_POSITION,
50
- data: step,
49
+ position: step.filePath ? getNodePosition(flowConfig, step.filePath) : DEFAULT_CONFIG,
50
+ data: { ...step, nodeConfig: step.filePath ? getNodePosition(flowConfig, step.filePath) : DEFAULT_CONFIG },
51
51
  language: step.language,
52
52
  }));
53
53
  const edges = flow.edges.map((edge) => ({
@@ -102,10 +102,17 @@ export const useGetFlowState = (flow, flowConfig) => {
102
102
  x: Math.round(node.position.x),
103
103
  y: Math.round(node.position.y),
104
104
  };
105
+ if (node.data.nodeConfig?.sourceHandlePosition) {
106
+ acc[node.data.filePath].sourceHandlePosition = node.data.nodeConfig.sourceHandlePosition;
107
+ }
108
+ if (node.data.nodeConfig?.targetHandlePosition) {
109
+ acc[node.data.filePath].targetHandlePosition = node.data.nodeConfig.targetHandlePosition;
110
+ }
105
111
  }
106
112
  return acc;
107
113
  }, {});
108
114
  if (!isEqual(steps, lastSavedConfigRef.current)) {
115
+ console.log('steps', steps, lastSavedConfigRef.current);
109
116
  lastSavedConfigRef.current = steps;
110
117
  const newConfig = { id: flowIdRef.current, config: steps };
111
118
  try {
@@ -1,3 +1,3 @@
1
+ import { ApiNodeData, EdgeData, EventNodeData } from '@/types/flow';
1
2
  import { Edge, Node } from '@xyflow/react';
2
- import { EventNodeData, EdgeData, ApiNodeData } from '../nodes/nodes.types';
3
3
  export declare const useOrganizeNodes: (nodes: Node<EventNodeData | ApiNodeData>[], edges: Edge<EdgeData>[], setNodes: (nodes: Node<EventNodeData | ApiNodeData>[]) => void) => void;
@@ -1,2 +1,2 @@
1
- import { FlowConfigResponse } from '@/views/flow/hooks/use-get-flow-state';
1
+ import { FlowConfigResponse } from '@/types/flow';
2
2
  export declare const useSaveWorkflowConfig: () => (body: FlowConfigResponse) => Promise<any>;
@@ -0,0 +1,2 @@
1
+ import { ApiNodeProps } from '@/publicComponents/node-props';
2
+ export declare const ApiFlowNode: ({ data }: ApiNodeProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { ApiNode } from '../../../publicComponents/api-node';
2
+ import { ApiNode } from '@/publicComponents/api-node';
3
3
  export const ApiFlowNode = ({ data }) => {
4
4
  return _jsx(ApiNode, { data: data });
5
5
  };
@@ -0,0 +1,2 @@
1
+ import { CronNodeProps } from '@/publicComponents/node-props';
2
+ export declare const CronFlowNode: ({ data }: CronNodeProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CronNode } from '@/publicComponents/cron-node';
3
+ export const CronFlowNode = ({ data }) => {
4
+ return _jsx(CronNode, { data: data });
5
+ };
@@ -1,2 +1,2 @@
1
- import { EventNodeProps } from '../../../publicComponents/node-props';
1
+ import { EventNodeProps } from '@/publicComponents/node-props';
2
2
  export declare const EventFlowNode: ({ data }: EventNodeProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { EventNode } from '@/publicComponents/event-node';
3
+ export const EventFlowNode = ({ data }) => {
4
+ return _jsx(EventNode, { data: data });
5
+ };
@@ -0,0 +1,2 @@
1
+ import { NoopNodeProps } from '@/publicComponents/node-props';
2
+ export declare const NoopFlowNode: ({ data }: NoopNodeProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { NoopNode } from '../../../publicComponents/noop-node';
2
+ import { NoopNode } from '@/publicComponents/noop-node';
3
3
  export const NoopFlowNode = ({ data }) => {
4
4
  return _jsx(NoopNode, { data: data });
5
5
  };