@d34dman/flowdrop 0.0.1 → 0.0.3

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 (120) hide show
  1. package/README.md +307 -215
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +30 -30
  4. package/dist/api/client.d.ts +24 -1
  5. package/dist/api/client.js +55 -38
  6. package/dist/api/enhanced-client.d.ts +46 -0
  7. package/dist/api/enhanced-client.js +211 -0
  8. package/dist/clients/ApiClient.d.ts +19 -23
  9. package/dist/clients/ApiClient.js +36 -34
  10. package/dist/components/App.svelte +1299 -230
  11. package/dist/components/App.svelte.d.ts +21 -1
  12. package/dist/components/CanvasBanner.svelte +50 -44
  13. package/dist/components/CanvasBanner.svelte.d.ts +5 -19
  14. package/dist/components/ConfigForm.svelte +555 -0
  15. package/dist/components/ConfigForm.svelte.d.ts +32 -0
  16. package/dist/components/ConfigModal.svelte +261 -0
  17. package/dist/components/ConfigModal.svelte.d.ts +31 -0
  18. package/dist/components/ConfigSidebar.svelte +934 -0
  19. package/dist/components/ConfigSidebar.svelte.d.ts +51 -0
  20. package/dist/components/ConnectionLine.svelte +32 -0
  21. package/dist/components/ConnectionLine.svelte.d.ts +3 -0
  22. package/dist/components/GatewayNode.svelte +471 -0
  23. package/dist/components/GatewayNode.svelte.d.ts +15 -0
  24. package/dist/components/LoadingSpinner.svelte +23 -23
  25. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  26. package/dist/components/Logo.svelte +82 -0
  27. package/dist/components/Logo.svelte.d.ts +26 -0
  28. package/dist/components/LogsSidebar.svelte +565 -0
  29. package/dist/components/LogsSidebar.svelte.d.ts +34 -0
  30. package/dist/components/MarkdownDisplay.svelte +28 -0
  31. package/dist/components/MarkdownDisplay.svelte.d.ts +7 -0
  32. package/dist/components/Navbar.svelte +663 -0
  33. package/dist/components/Navbar.svelte.d.ts +21 -0
  34. package/dist/components/NodeSidebar.svelte +629 -488
  35. package/dist/components/NodeSidebar.svelte.d.ts +1 -2
  36. package/dist/components/NodeStatusOverlay.svelte +327 -0
  37. package/dist/components/NodeStatusOverlay.svelte.d.ts +11 -0
  38. package/dist/components/NotesNode.svelte +566 -0
  39. package/dist/components/NotesNode.svelte.d.ts +43 -0
  40. package/dist/components/PipelineStatus.svelte +331 -0
  41. package/dist/components/PipelineStatus.svelte.d.ts +18 -0
  42. package/dist/components/SimpleNode.svelte +447 -0
  43. package/dist/components/SimpleNode.svelte.d.ts +24 -0
  44. package/dist/components/SquareNode.svelte +346 -0
  45. package/dist/components/SquareNode.svelte.d.ts +24 -0
  46. package/dist/components/StatusIcon.svelte +112 -0
  47. package/dist/components/StatusIcon.svelte.d.ts +10 -0
  48. package/dist/components/StatusLabel.svelte +33 -0
  49. package/dist/components/StatusLabel.svelte.d.ts +7 -0
  50. package/dist/components/ToolNode.svelte +385 -0
  51. package/dist/components/ToolNode.svelte.d.ts +36 -0
  52. package/dist/components/UniversalNode.svelte +126 -0
  53. package/dist/components/UniversalNode.svelte.d.ts +15 -0
  54. package/dist/components/WorkflowEditor.svelte +871 -528
  55. package/dist/components/WorkflowEditor.svelte.d.ts +15 -5
  56. package/dist/components/WorkflowNode.svelte +428 -542
  57. package/dist/components/WorkflowNode.svelte.d.ts +7 -3
  58. package/dist/config/apiConfig.d.ts +33 -0
  59. package/dist/config/apiConfig.js +39 -0
  60. package/dist/config/defaultPortConfig.d.ts +6 -0
  61. package/dist/config/defaultPortConfig.js +192 -0
  62. package/dist/config/demo.d.ts +58 -0
  63. package/dist/config/demo.js +142 -0
  64. package/dist/config/endpoints.d.ts +106 -0
  65. package/dist/config/endpoints.js +128 -0
  66. package/dist/data/samples.d.ts +38 -4
  67. package/dist/data/samples.js +2789 -737
  68. package/dist/examples/adapter-usage.d.ts +4 -4
  69. package/dist/examples/adapter-usage.js +21 -26
  70. package/dist/examples/api-client-usage.d.ts +6 -6
  71. package/dist/examples/api-client-usage.js +55 -54
  72. package/dist/index.d.ts +23 -15
  73. package/dist/index.js +23 -15
  74. package/dist/mocks/app-environment.d.ts +8 -0
  75. package/dist/mocks/app-environment.js +16 -0
  76. package/dist/mocks/app-forms.d.ts +2 -0
  77. package/dist/mocks/app-forms.js +21 -0
  78. package/dist/mocks/app-navigation.d.ts +5 -0
  79. package/dist/mocks/app-navigation.js +34 -0
  80. package/dist/mocks/app-stores.d.ts +14 -0
  81. package/dist/mocks/app-stores.js +26 -0
  82. package/dist/services/api.d.ts +13 -3
  83. package/dist/services/api.js +91 -36
  84. package/dist/services/globalSave.d.ts +20 -0
  85. package/dist/services/globalSave.js +165 -0
  86. package/dist/services/nodeExecutionService.d.ts +63 -0
  87. package/dist/services/nodeExecutionService.js +261 -0
  88. package/dist/services/portConfigApi.d.ts +14 -0
  89. package/dist/services/portConfigApi.js +69 -0
  90. package/dist/services/toastService.d.ts +147 -0
  91. package/dist/services/toastService.js +235 -0
  92. package/dist/services/workflowStorage.d.ts +2 -2
  93. package/dist/services/workflowStorage.js +10 -10
  94. package/dist/stores/workflowStore.d.ts +53 -0
  95. package/dist/stores/workflowStore.js +264 -0
  96. package/dist/styles/base.css +896 -363
  97. package/dist/svelte-app.d.ts +52 -5
  98. package/dist/svelte-app.js +128 -6
  99. package/dist/types/config.d.ts +291 -0
  100. package/dist/types/config.js +4 -0
  101. package/dist/types/index.d.ts +231 -19
  102. package/dist/types/index.js +1 -1
  103. package/dist/utils/colors.d.ts +67 -33
  104. package/dist/utils/colors.js +183 -118
  105. package/dist/utils/config.d.ts +41 -0
  106. package/dist/utils/config.js +248 -0
  107. package/dist/utils/connections.d.ts +40 -3
  108. package/dist/utils/connections.js +115 -44
  109. package/dist/utils/icons.d.ts +1 -1
  110. package/dist/utils/icons.js +71 -70
  111. package/dist/utils/nodeStatus.d.ts +53 -0
  112. package/dist/utils/nodeStatus.js +183 -0
  113. package/dist/utils/nodeTypes.d.ts +57 -0
  114. package/dist/utils/nodeTypes.js +109 -0
  115. package/dist/utils/nodeWrapper.d.ts +39 -0
  116. package/dist/utils/nodeWrapper.js +62 -0
  117. package/package.json +132 -97
  118. package/dist/app.css +0 -0
  119. package/dist/components/Node.svelte +0 -38
  120. package/dist/components/Node.svelte.d.ts +0 -4
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Configuration utilities for FlowDrop Editor
3
+ */
4
+ import { createEndpointConfig } from '../config/endpoints.js';
5
+ /**
6
+ * Create default editor features configuration
7
+ */
8
+ export function createDefaultFeatures() {
9
+ return {
10
+ dragAndDrop: true,
11
+ nodeEditing: true,
12
+ execution: true,
13
+ saveWorkflow: true,
14
+ loadWorkflow: true,
15
+ undoRedo: true,
16
+ nodeSearch: true,
17
+ nodeCategories: true,
18
+ nodeValidation: true,
19
+ collaboration: false,
20
+ templates: false,
21
+ importExport: false
22
+ };
23
+ }
24
+ /**
25
+ * Create default UI configuration
26
+ */
27
+ export function createDefaultUIConfig() {
28
+ return {
29
+ showSidebar: true,
30
+ showToolbar: true,
31
+ showMinimap: true,
32
+ showGrid: true,
33
+ gridSize: 20,
34
+ nodeSpacing: 100,
35
+ canvasPadding: 50,
36
+ navbarHeight: 60, // Default navbar height in pixels (current demo height)
37
+ zoom: {
38
+ min: 0.1,
39
+ max: 2,
40
+ default: 1
41
+ },
42
+ colors: {
43
+ primary: '#3b82f6',
44
+ secondary: '#64748b',
45
+ accent: '#f59e0b',
46
+ background: '#ffffff',
47
+ text: '#1f2937'
48
+ },
49
+ cssClasses: {}
50
+ };
51
+ }
52
+ /**
53
+ * Create default API configuration
54
+ */
55
+ export function createDefaultAPIConfig() {
56
+ return {
57
+ endpoints: createEndpointConfig('/api/flowdrop'),
58
+ timeout: 30000,
59
+ retry: {
60
+ enabled: true,
61
+ maxAttempts: 3,
62
+ delay: 1000
63
+ },
64
+ auth: {
65
+ type: 'none'
66
+ },
67
+ headers: {
68
+ 'Content-Type': 'application/json'
69
+ }
70
+ };
71
+ }
72
+ /**
73
+ * Create default execution configuration
74
+ */
75
+ export function createDefaultExecutionConfig() {
76
+ return {
77
+ realTimeUpdates: true,
78
+ timeout: 300,
79
+ maxConcurrent: 5,
80
+ showProgress: true,
81
+ autoSaveState: true,
82
+ caching: {
83
+ enabled: true,
84
+ ttl: 3600
85
+ }
86
+ };
87
+ }
88
+ /**
89
+ * Create default storage configuration
90
+ */
91
+ export function createDefaultStorageConfig() {
92
+ return {
93
+ type: 'api',
94
+ autoSaveInterval: 5000,
95
+ maxUndoSteps: 50,
96
+ keyPrefix: 'flowdrop_'
97
+ };
98
+ }
99
+ /**
100
+ * Create default workflow editor configuration
101
+ */
102
+ export function createDefaultConfig(endpointConfig) {
103
+ return {
104
+ theme: 'auto',
105
+ features: createDefaultFeatures(),
106
+ ui: createDefaultUIConfig(),
107
+ api: {
108
+ ...createDefaultAPIConfig(),
109
+ endpoints: endpointConfig || createEndpointConfig('/api/flowdrop')
110
+ },
111
+ ports: {
112
+ dataTypes: [],
113
+ compatibilityRules: [],
114
+ defaultDataType: 'mixed'
115
+ },
116
+ execution: createDefaultExecutionConfig(),
117
+ storage: createDefaultStorageConfig()
118
+ };
119
+ }
120
+ /**
121
+ * Merge configuration with defaults
122
+ */
123
+ export function mergeConfig(userConfig, defaultConfig) {
124
+ return {
125
+ ...defaultConfig,
126
+ ...userConfig,
127
+ features: {
128
+ ...defaultConfig.features,
129
+ ...userConfig.features
130
+ },
131
+ ui: {
132
+ ...defaultConfig.ui,
133
+ ...userConfig.ui,
134
+ zoom: {
135
+ ...defaultConfig.ui.zoom,
136
+ ...userConfig.ui?.zoom
137
+ },
138
+ colors: {
139
+ ...defaultConfig.ui.colors,
140
+ ...userConfig.ui?.colors
141
+ },
142
+ cssClasses: {
143
+ ...defaultConfig.ui.cssClasses,
144
+ ...userConfig.ui?.cssClasses
145
+ }
146
+ },
147
+ api: {
148
+ ...defaultConfig.api,
149
+ ...userConfig.api,
150
+ retry: {
151
+ ...defaultConfig.api.retry,
152
+ ...userConfig.api?.retry
153
+ },
154
+ auth: {
155
+ ...defaultConfig.api.auth,
156
+ ...userConfig.api?.auth
157
+ },
158
+ headers: {
159
+ ...defaultConfig.api.headers,
160
+ ...userConfig.api?.headers
161
+ },
162
+ endpoints: {
163
+ ...defaultConfig.api.endpoints,
164
+ ...userConfig.api?.endpoints
165
+ }
166
+ },
167
+ execution: {
168
+ ...defaultConfig.execution,
169
+ ...userConfig.execution,
170
+ caching: {
171
+ ...defaultConfig.execution.caching,
172
+ ...userConfig.execution?.caching
173
+ }
174
+ },
175
+ storage: {
176
+ ...defaultConfig.storage,
177
+ ...userConfig.storage
178
+ }
179
+ };
180
+ }
181
+ /**
182
+ * Validate configuration
183
+ */
184
+ export function validateConfig(config) {
185
+ const errors = [];
186
+ if (!config.features) {
187
+ errors.push('features configuration is required');
188
+ }
189
+ if (!config.ui) {
190
+ errors.push('ui configuration is required');
191
+ }
192
+ if (!config.api) {
193
+ errors.push('api configuration is required');
194
+ }
195
+ if (!config.execution) {
196
+ errors.push('execution configuration is required');
197
+ }
198
+ if (!config.storage) {
199
+ errors.push('storage configuration is required');
200
+ }
201
+ // Validate API configuration
202
+ if (config.api.timeout <= 0) {
203
+ errors.push('API timeout must be greater than 0');
204
+ }
205
+ if (config.api.retry.maxAttempts < 0) {
206
+ errors.push('Retry max attempts must be non-negative');
207
+ }
208
+ // Validate execution configuration
209
+ if (config.execution.timeout <= 0) {
210
+ errors.push('Execution timeout must be greater than 0');
211
+ }
212
+ if (config.execution.maxConcurrent <= 0) {
213
+ errors.push('Max concurrent executions must be greater than 0');
214
+ }
215
+ // Validate UI configuration
216
+ if (config.ui.gridSize <= 0) {
217
+ errors.push('Grid size must be greater than 0');
218
+ }
219
+ if (config.ui.nodeSpacing <= 0) {
220
+ errors.push('Node spacing must be greater than 0');
221
+ }
222
+ if (config.ui.zoom.min >= config.ui.zoom.max) {
223
+ errors.push('Zoom min must be less than zoom max');
224
+ }
225
+ return errors;
226
+ }
227
+ /**
228
+ * Create configuration from environment variables
229
+ */
230
+ export function createConfigFromEnv() {
231
+ const apiBaseUrl = import.meta.env.VITE_FLOWDROP_API_URL || '/api/flowdrop';
232
+ const endpointConfig = createEndpointConfig(apiBaseUrl);
233
+ const config = createDefaultConfig(endpointConfig);
234
+ // Override with environment variables
235
+ if (import.meta.env.VITE_FLOWDROP_THEME) {
236
+ config.theme = import.meta.env.VITE_FLOWDROP_THEME;
237
+ }
238
+ if (import.meta.env.VITE_FLOWDROP_TIMEOUT) {
239
+ config.api.timeout = parseInt(import.meta.env.VITE_FLOWDROP_TIMEOUT);
240
+ }
241
+ if (import.meta.env.VITE_FLOWDROP_AUTH_TYPE) {
242
+ config.api.auth.type = import.meta.env.VITE_FLOWDROP_AUTH_TYPE;
243
+ }
244
+ if (import.meta.env.VITE_FLOWDROP_AUTH_TOKEN) {
245
+ config.api.auth.token = import.meta.env.VITE_FLOWDROP_AUTH_TOKEN;
246
+ }
247
+ return config;
248
+ }
@@ -1,9 +1,46 @@
1
1
  /**
2
2
  * Connection validation utilities for FlowDrop
3
3
  */
4
- import type { NodeMetadata, NodePort, NodeDataType, WorkflowNode, WorkflowEdge } from "../types/index.js";
4
+ import type { NodeMetadata, NodePort, NodeDataType, WorkflowNode, WorkflowEdge, PortConfig, PortDataTypeConfig } from '../types/index.js';
5
5
  /**
6
- * Check if two data types are compatible for connection
6
+ * Configurable port compatibility checker
7
+ */
8
+ export declare class PortCompatibilityChecker {
9
+ private portConfig;
10
+ private compatibilityMap;
11
+ constructor(portConfig: PortConfig);
12
+ /**
13
+ * Build the compatibility map from configuration rules
14
+ */
15
+ private buildCompatibilityMap;
16
+ /**
17
+ * Check if two data types are compatible for connection
18
+ */
19
+ areDataTypesCompatible(outputType: NodeDataType, inputType: NodeDataType): boolean;
20
+ /**
21
+ * Get all compatible target types for a source type
22
+ */
23
+ getCompatibleTypes(sourceType: NodeDataType): NodeDataType[];
24
+ /**
25
+ * Get data type configuration by ID
26
+ */
27
+ getDataTypeConfig(dataTypeId: string): PortDataTypeConfig | undefined;
28
+ /**
29
+ * Get all enabled data types
30
+ */
31
+ getEnabledDataTypes(): PortDataTypeConfig[];
32
+ }
33
+ /**
34
+ * Initialize the global port compatibility checker
35
+ */
36
+ export declare function initializePortCompatibility(portConfig: PortConfig): void;
37
+ /**
38
+ * Get the global port compatibility checker
39
+ */
40
+ export declare function getPortCompatibilityChecker(): PortCompatibilityChecker;
41
+ /**
42
+ * Check if two data types are compatible for connection (legacy function)
43
+ * @deprecated Use PortCompatibilityChecker.areDataTypesCompatible() instead
7
44
  */
8
45
  export declare function areDataTypesCompatible(outputType: NodeDataType, inputType: NodeDataType): boolean;
9
46
  /**
@@ -33,7 +70,7 @@ export declare function getConnectionSuggestions(nodeId: string, nodes: Workflow
33
70
  nodeName: string;
34
71
  portId: string;
35
72
  portName: string;
36
- portType: "input" | "output";
73
+ portType: 'input' | 'output';
37
74
  dataType: NodeDataType;
38
75
  compatible: boolean;
39
76
  }>;
@@ -2,39 +2,110 @@
2
2
  * Connection validation utilities for FlowDrop
3
3
  */
4
4
  /**
5
- * Check if two data types are compatible for connection
5
+ * Configurable port compatibility checker
6
6
  */
7
- export function areDataTypesCompatible(outputType, inputType) {
8
- // Direct type matches
9
- if (outputType === inputType)
10
- return true;
11
- // String can be converted to most types
12
- if (outputType === "string") {
13
- return ["string", "number", "boolean"].includes(inputType);
7
+ export class PortCompatibilityChecker {
8
+ portConfig;
9
+ compatibilityMap;
10
+ constructor(portConfig) {
11
+ this.portConfig = portConfig;
12
+ this.compatibilityMap = new Map();
13
+ this.buildCompatibilityMap();
14
14
  }
15
- // Number can be converted to string
16
- if (outputType === "number") {
17
- return ["string", "number"].includes(inputType);
15
+ /**
16
+ * Build the compatibility map from configuration rules
17
+ */
18
+ buildCompatibilityMap() {
19
+ this.compatibilityMap.clear();
20
+ // First, add direct type matches (every type is compatible with itself)
21
+ for (const dataType of this.portConfig.dataTypes) {
22
+ if (!this.compatibilityMap.has(dataType.id)) {
23
+ this.compatibilityMap.set(dataType.id, new Set());
24
+ }
25
+ this.compatibilityMap.get(dataType.id).add(dataType.id);
26
+ }
27
+ // Then add configured compatibility rules
28
+ for (const rule of this.portConfig.compatibilityRules) {
29
+ if (!this.compatibilityMap.has(rule.from)) {
30
+ this.compatibilityMap.set(rule.from, new Set());
31
+ }
32
+ this.compatibilityMap.get(rule.from).add(rule.to);
33
+ }
34
+ // Add alias support
35
+ for (const dataType of this.portConfig.dataTypes) {
36
+ if (dataType.aliases) {
37
+ for (const alias of dataType.aliases) {
38
+ // Make aliases point to the main type's compatibility set
39
+ const mainCompatibility = this.compatibilityMap.get(dataType.id);
40
+ if (mainCompatibility) {
41
+ this.compatibilityMap.set(alias, new Set(mainCompatibility));
42
+ // Also make the main type compatible with the alias
43
+ mainCompatibility.add(alias);
44
+ }
45
+ }
46
+ }
47
+ }
18
48
  }
19
- // Boolean can be converted to string
20
- if (outputType === "boolean") {
21
- return ["string", "boolean"].includes(inputType);
49
+ /**
50
+ * Check if two data types are compatible for connection
51
+ */
52
+ areDataTypesCompatible(outputType, inputType) {
53
+ const compatibleTypes = this.compatibilityMap.get(outputType);
54
+ return compatibleTypes ? compatibleTypes.has(inputType) : false;
22
55
  }
23
- // Object can be converted to string (JSON)
24
- if (outputType === "object") {
25
- return ["string", "object"].includes(inputType);
56
+ /**
57
+ * Get all compatible target types for a source type
58
+ */
59
+ getCompatibleTypes(sourceType) {
60
+ const compatibleTypes = this.compatibilityMap.get(sourceType);
61
+ return compatibleTypes ? Array.from(compatibleTypes) : [];
26
62
  }
27
- // Array can be converted to string (JSON)
28
- if (outputType === "array") {
29
- return ["string", "array"].includes(inputType);
63
+ /**
64
+ * Get data type configuration by ID
65
+ */
66
+ getDataTypeConfig(dataTypeId) {
67
+ return this.portConfig.dataTypes.find((dt) => dt.id === dataTypeId || dt.aliases?.includes(dataTypeId));
30
68
  }
31
- return false;
69
+ /**
70
+ * Get all enabled data types
71
+ */
72
+ getEnabledDataTypes() {
73
+ return this.portConfig.dataTypes.filter((dt) => dt.enabled !== false);
74
+ }
75
+ }
76
+ // Global instance - will be initialized with configuration
77
+ let globalCompatibilityChecker = null;
78
+ /**
79
+ * Initialize the global port compatibility checker
80
+ */
81
+ export function initializePortCompatibility(portConfig) {
82
+ globalCompatibilityChecker = new PortCompatibilityChecker(portConfig);
83
+ }
84
+ /**
85
+ * Get the global port compatibility checker
86
+ */
87
+ export function getPortCompatibilityChecker() {
88
+ if (!globalCompatibilityChecker) {
89
+ throw new Error('Port compatibility checker not initialized. Call initializePortCompatibility() first.');
90
+ }
91
+ return globalCompatibilityChecker;
92
+ }
93
+ /**
94
+ * Check if two data types are compatible for connection (legacy function)
95
+ * @deprecated Use PortCompatibilityChecker.areDataTypesCompatible() instead
96
+ */
97
+ export function areDataTypesCompatible(outputType, inputType) {
98
+ if (!globalCompatibilityChecker) {
99
+ // Fallback to basic compatibility for backward compatibility
100
+ return outputType === inputType;
101
+ }
102
+ return globalCompatibilityChecker.areDataTypesCompatible(outputType, inputType);
32
103
  }
33
104
  /**
34
105
  * Get all possible connections from a source node to target nodes
35
106
  */
36
107
  export function getPossibleConnections(sourceNode, targetNodes, nodeTypes) {
37
- const sourceMetadata = nodeTypes.find(nt => nt.id === sourceNode.data.metadata.id);
108
+ const sourceMetadata = nodeTypes.find((nt) => nt.id === sourceNode.data.metadata.id);
38
109
  if (!sourceMetadata)
39
110
  return [];
40
111
  const possibleConnections = [];
@@ -44,7 +115,7 @@ export function getPossibleConnections(sourceNode, targetNodes, nodeTypes) {
44
115
  for (const targetNode of targetNodes) {
45
116
  if (targetNode.id === sourceNode.id)
46
117
  continue; // Skip self-connection
47
- const targetMetadata = nodeTypes.find(nt => nt.id === targetNode.data.metadata.id);
118
+ const targetMetadata = nodeTypes.find((nt) => nt.id === targetNode.data.metadata.id);
48
119
  if (!targetMetadata)
49
120
  continue;
50
121
  // Get all input ports from target node
@@ -72,39 +143,39 @@ export function getPossibleConnections(sourceNode, targetNodes, nodeTypes) {
72
143
  */
73
144
  export function validateConnection(sourceNodeId, sourcePortId, targetNodeId, targetPortId, nodes, nodeTypes) {
74
145
  // Check if nodes exist
75
- const sourceNode = nodes.find(n => n.id === sourceNodeId);
76
- const targetNode = nodes.find(n => n.id === targetNodeId);
146
+ const sourceNode = nodes.find((n) => n.id === sourceNodeId);
147
+ const targetNode = nodes.find((n) => n.id === targetNodeId);
77
148
  if (!sourceNode) {
78
- return { valid: false, error: "Source node not found" };
149
+ return { valid: false, error: 'Source node not found' };
79
150
  }
80
151
  if (!targetNode) {
81
- return { valid: false, error: "Target node not found" };
152
+ return { valid: false, error: 'Target node not found' };
82
153
  }
83
154
  // Check for self-connection
84
155
  if (sourceNodeId === targetNodeId) {
85
- return { valid: false, error: "Cannot connect node to itself" };
156
+ return { valid: false, error: 'Cannot connect node to itself' };
86
157
  }
87
158
  // Get node metadata
88
- const sourceMetadata = nodeTypes.find(nt => nt.id === sourceNode.data.metadata.id);
89
- const targetMetadata = nodeTypes.find(nt => nt.id === targetNode.data.metadata.id);
159
+ const sourceMetadata = nodeTypes.find((nt) => nt.id === sourceNode.data.metadata.id);
160
+ const targetMetadata = nodeTypes.find((nt) => nt.id === targetNode.data.metadata.id);
90
161
  if (!sourceMetadata || !targetMetadata) {
91
- console.log("Metadata lookup failed:", {
162
+ console.log('Metadata lookup failed:', {
92
163
  sourceNodeId,
93
164
  targetNodeId,
94
165
  sourceMetadataId: sourceNode.data.metadata.id,
95
166
  targetMetadataId: targetNode.data.metadata.id,
96
- availableNodeTypes: nodeTypes.map(nt => nt.id)
167
+ availableNodeTypes: nodeTypes.map((nt) => nt.id)
97
168
  });
98
- return { valid: false, error: "Node metadata not found" };
169
+ return { valid: false, error: 'Node metadata not found' };
99
170
  }
100
171
  // Find ports
101
- const sourcePort = sourceMetadata.outputs.find(p => p.id === sourcePortId);
102
- const targetPort = targetMetadata.inputs.find(p => p.id === targetPortId);
172
+ const sourcePort = sourceMetadata.outputs.find((p) => p.id === sourcePortId);
173
+ const targetPort = targetMetadata.inputs.find((p) => p.id === targetPortId);
103
174
  if (!sourcePort) {
104
- return { valid: false, error: "Source port not found" };
175
+ return { valid: false, error: 'Source port not found' };
105
176
  }
106
177
  if (!targetPort) {
107
- return { valid: false, error: "Target port not found" };
178
+ return { valid: false, error: 'Target port not found' };
108
179
  }
109
180
  // Check data type compatibility
110
181
  if (!areDataTypesCompatible(sourcePort.dataType, targetPort.dataType)) {
@@ -119,17 +190,17 @@ export function validateConnection(sourceNodeId, sourcePortId, targetNodeId, tar
119
190
  * Get connection suggestions for a node
120
191
  */
121
192
  export function getConnectionSuggestions(nodeId, nodes, nodeTypes) {
122
- const node = nodes.find(n => n.id === nodeId);
193
+ const node = nodes.find((n) => n.id === nodeId);
123
194
  if (!node)
124
195
  return [];
125
- const metadata = nodeTypes.find(nt => nt.id === node.data.metadata.id);
196
+ const metadata = nodeTypes.find((nt) => nt.id === node.data.metadata.id);
126
197
  if (!metadata)
127
198
  return [];
128
199
  const suggestions = [];
129
200
  // Get all other nodes
130
- const otherNodes = nodes.filter(n => n.id !== nodeId);
201
+ const otherNodes = nodes.filter((n) => n.id !== nodeId);
131
202
  for (const otherNode of otherNodes) {
132
- const otherMetadata = nodeTypes.find(nt => nt.id === otherNode.data.metadata.id);
203
+ const otherMetadata = nodeTypes.find((nt) => nt.id === otherNode.data.metadata.id);
133
204
  if (!otherMetadata)
134
205
  continue;
135
206
  // Check outputs from other nodes to inputs of current node
@@ -141,7 +212,7 @@ export function getConnectionSuggestions(nodeId, nodes, nodeTypes) {
141
212
  nodeName: otherNode.data.label,
142
213
  portId: output.id,
143
214
  portName: output.name,
144
- portType: "output",
215
+ portType: 'output',
145
216
  dataType: output.dataType,
146
217
  compatible
147
218
  });
@@ -156,7 +227,7 @@ export function getConnectionSuggestions(nodeId, nodes, nodeTypes) {
156
227
  nodeName: otherNode.data.label,
157
228
  portId: input.id,
158
229
  portName: input.name,
159
- portType: "input",
230
+ portType: 'input',
160
231
  dataType: input.dataType,
161
232
  compatible
162
233
  });
@@ -179,7 +250,7 @@ export function hasCycles(nodes, edges) {
179
250
  visited.add(nodeId);
180
251
  recursionStack.add(nodeId);
181
252
  // Get all outgoing edges from this node
182
- const outgoingEdges = edges.filter(e => e.source === nodeId);
253
+ const outgoingEdges = edges.filter((e) => e.source === nodeId);
183
254
  for (const edge of outgoingEdges) {
184
255
  if (hasCycleUtil(edge.target))
185
256
  return true;
@@ -2,7 +2,7 @@
2
2
  * Centralized icon management for FlowDrop
3
3
  * Ensures consistent icon usage across all components
4
4
  */
5
- import type { NodeCategory } from "../types/index.js";
5
+ import type { NodeCategory } from '../types/index.js';
6
6
  /**
7
7
  * Default icons for different contexts
8
8
  */