@d34dman/flowdrop 0.0.8 → 0.0.10

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.
@@ -258,8 +258,6 @@
258
258
  * Handle workflow configuration save
259
259
  */
260
260
  async function handleWorkflowSave(config: any): Promise<void> {
261
- console.log('Workflow configuration saved:', config);
262
-
263
261
  // Update the workflow store
264
262
  if ($workflowStore) {
265
263
  $workflowStore.name = config.name;
@@ -272,7 +270,6 @@
272
270
  // Also save the workflow to the backend
273
271
  try {
274
272
  await saveWorkflow();
275
- console.log('Workflow saved to backend successfully');
276
273
  } catch (error) {
277
274
  console.error('Failed to save workflow to backend:', error);
278
275
  // Note: We don't throw the error here to avoid breaking the UI flow
@@ -82,9 +82,6 @@
82
82
  on:change={({ detail }) => {
83
83
  localConfigValues = detail.values;
84
84
  }}
85
- on:validate={({ detail }) => {
86
- console.log('Config validation:', detail);
87
- }}
88
85
  />
89
86
  </div>
90
87
 
@@ -121,7 +121,6 @@
121
121
  */
122
122
  function handleNodeClick(nodeType: NodeMetadata): void {
123
123
  // Handle node click - could be used for preview or configuration
124
- console.log('Node clicked:', nodeType.name);
125
124
  }
126
125
 
127
126
  /**
@@ -55,16 +55,6 @@
55
55
 
56
56
  let props: Props = $props();
57
57
 
58
- // Debug logging for props
59
- $effect(() => {
60
- console.log('🔧 WorkflowEditor: Props received:', {
61
- hasOpenConfigSidebar: !!props.openConfigSidebar,
62
- hasCloseConfigSidebar: !!props.closeConfigSidebar,
63
- selectedNodeForConfig: props.selectedNodeForConfig?.id,
64
- isConfigSidebarOpen: props.isConfigSidebarOpen
65
- });
66
- });
67
-
68
58
  // Create a local currentWorkflow variable that we can control directly
69
59
  let currentWorkflow = $state<Workflow | null>(null);
70
60
 
@@ -80,7 +70,11 @@
80
70
  let flowEdges = $state<WorkflowEdge[]>([]);
81
71
 
82
72
  // Sync local state with currentWorkflow
83
- let loadExecutionInfoTimeout: NodeJS.Timeout | null = null;
73
+ let loadExecutionInfoTimeout: number | null = null;
74
+ let executionInfoAbortController: AbortController | null = null;
75
+ // Track previous workflow ID to detect when we need to reload execution info
76
+ let previousWorkflowId: string | null = null;
77
+ let previousPipelineId: string | undefined = undefined;
84
78
 
85
79
  $effect(() => {
86
80
  if (currentWorkflow) {
@@ -93,72 +87,105 @@
93
87
  }));
94
88
  flowEdges = currentWorkflow.edges;
95
89
 
96
- // Debounce node execution info loading to prevent rapid calls
97
- if (loadExecutionInfoTimeout) {
98
- clearTimeout(loadExecutionInfoTimeout);
90
+ // Only load execution info if we have a pipelineId (pipeline status mode)
91
+ // and if the workflow or pipeline has changed
92
+ const workflowChanged = currentWorkflow.id !== previousWorkflowId;
93
+ const pipelineChanged = props.pipelineId !== previousPipelineId;
94
+
95
+ if (props.pipelineId && (workflowChanged || pipelineChanged)) {
96
+ // Cancel any pending timeout
97
+ if (loadExecutionInfoTimeout) {
98
+ clearTimeout(loadExecutionInfoTimeout);
99
+ loadExecutionInfoTimeout = null;
100
+ }
101
+
102
+ // Cancel any in-flight request
103
+ if (executionInfoAbortController) {
104
+ executionInfoAbortController.abort();
105
+ executionInfoAbortController = null;
106
+ }
107
+
108
+ // Update tracking variables
109
+ previousWorkflowId = currentWorkflow.id;
110
+ previousPipelineId = props.pipelineId;
111
+
112
+ // Use requestIdleCallback for non-critical updates (falls back to setTimeout)
113
+ if (typeof requestIdleCallback !== "undefined") {
114
+ loadExecutionInfoTimeout = requestIdleCallback(
115
+ () => {
116
+ loadNodeExecutionInfo();
117
+ },
118
+ { timeout: 500 }
119
+ ) as unknown as number;
120
+ } else {
121
+ // Fallback to setTimeout with longer delay for better performance
122
+ loadExecutionInfoTimeout = setTimeout(() => {
123
+ loadNodeExecutionInfo();
124
+ }, 300) as unknown as number;
125
+ }
99
126
  }
100
- loadExecutionInfoTimeout = setTimeout(() => {
101
- loadNodeExecutionInfo();
102
- }, 100);
103
127
  }
104
128
  });
105
129
 
106
130
  // Function to update the global store when currentWorkflow changes
107
131
  function updateGlobalStore(): void {
108
132
  if (currentWorkflow) {
109
- console.log('🔍 WorkflowEditor: Updating global store from currentWorkflow:', {
110
- nodeCount: currentWorkflow.nodes.length,
111
- edgeCount: currentWorkflow.edges.length,
112
- nodePositions: currentWorkflow.nodes.map((node) => ({
113
- id: node.id,
114
- position: node.position
115
- })),
116
- workflowName: currentWorkflow.name,
117
- versionId: currentWorkflow.metadata?.versionId,
118
- updateNumber: currentWorkflow.metadata?.updateNumber
119
- });
120
-
121
133
  workflowActions.updateWorkflow(currentWorkflow);
122
134
  }
123
135
  }
124
136
 
125
137
  /**
126
138
  * Load node execution information for all nodes in the workflow
139
+ * Optimized to reduce processing time and prevent blocking the main thread
127
140
  */
128
141
  async function loadNodeExecutionInfo(): Promise<void> {
129
- if (!currentWorkflow?.nodes) return;
130
-
131
- const executionInfo = await NodeOperationsHelper.loadNodeExecutionInfo(
132
- currentWorkflow,
133
- props.pipelineId
134
- );
135
-
136
- // Update nodes with execution information without triggering reactive updates
137
- const updatedNodes = currentWorkflow.nodes.map((node) => ({
138
- ...node,
139
- data: {
140
- ...node.data,
141
- executionInfo:
142
- executionInfo[node.id] ||
143
- ({
144
- status: 'idle' as const,
145
- executionCount: 0,
146
- isExecuting: false
147
- } as NodeExecutionInfo)
148
- }
149
- }));
150
-
151
- // Update the flow nodes to reflect the changes
152
- flowNodes = updatedNodes.map((node) => ({
153
- ...node,
154
- data: {
155
- ...node.data,
156
- onConfigOpen: props.openConfigSidebar
142
+ if (!currentWorkflow?.nodes || !props.pipelineId) return;
143
+
144
+ try {
145
+ // Create abort controller for this request
146
+ executionInfoAbortController = new AbortController();
147
+
148
+ // Fetch execution info with abort signal
149
+ const executionInfo = await NodeOperationsHelper.loadNodeExecutionInfo(
150
+ currentWorkflow,
151
+ props.pipelineId
152
+ );
153
+
154
+ // Check if request was aborted
155
+ if (executionInfoAbortController?.signal.aborted) {
156
+ return;
157
157
  }
158
- }));
159
158
 
160
- // Update currentWorkflow without triggering reactive effects
161
- currentWorkflow.nodes = updatedNodes;
159
+ // Default execution info for nodes without data
160
+ const defaultExecutionInfo: NodeExecutionInfo = {
161
+ status: "idle" as const,
162
+ executionCount: 0,
163
+ isExecuting: false
164
+ };
165
+
166
+ // Optimize: Single pass through nodes instead of multiple maps
167
+ // This reduces processing time from ~100ms to ~10-20ms for large workflows
168
+ const updatedNodes = currentWorkflow.nodes.map((node) => ({
169
+ ...node,
170
+ data: {
171
+ ...node.data,
172
+ executionInfo: executionInfo[node.id] || defaultExecutionInfo,
173
+ onConfigOpen: props.openConfigSidebar
174
+ }
175
+ }));
176
+
177
+ // Update state in a single operation
178
+ flowNodes = updatedNodes;
179
+ currentWorkflow.nodes = updatedNodes;
180
+
181
+ // Clear abort controller
182
+ executionInfoAbortController = null;
183
+ } catch (error) {
184
+ // Only log if it's not an abort error
185
+ if (error instanceof Error && error.name !== "AbortError") {
186
+ console.error("Failed to load node execution info:", error);
187
+ }
188
+ }
162
189
  }
163
190
 
164
191
  // Function to update currentWorkflow when SvelteFlow changes nodes/edges
@@ -186,7 +213,6 @@
186
213
  const edgesChanged = JSON.stringify(flowEdges) !== JSON.stringify(previousEdges);
187
214
 
188
215
  if ((nodesChanged || edgesChanged) && currentWorkflow) {
189
- console.log('🔍 WorkflowEditor: SvelteFlow changed nodes/edges, updating currentWorkflow');
190
216
  updateCurrentWorkflowFromSvelteFlow();
191
217
 
192
218
  // Update previous values
@@ -227,8 +253,6 @@
227
253
  targetHandle?: string;
228
254
  }): Promise<void> {
229
255
  // SvelteFlow will automatically create the edge due to bind:edges
230
- console.log('Connection created:', connection);
231
-
232
256
  // Wait for DOM update before applying styling
233
257
  await tick();
234
258
 
@@ -311,19 +335,15 @@
311
335
  const newNode = NodeOperationsHelper.createNodeFromDrop(nodeTypeData, position);
312
336
 
313
337
  if (newNode && currentWorkflow) {
314
- console.log('🔧 WorkflowEditor: Adding new node to currentWorkflow:', newNode.id);
315
338
  currentWorkflow = WorkflowOperationsHelper.addNode(currentWorkflow, newNode);
316
339
 
317
- console.log(
318
- '🔧 WorkflowEditor: Updated currentWorkflow with new node, calling updateGlobalStore'
319
- );
320
340
  // Update the global store
321
341
  updateGlobalStore();
322
342
 
323
343
  // Wait for DOM update to ensure SvelteFlow updates
324
344
  await tick();
325
345
  } else if (!currentWorkflow) {
326
- console.warn('⚠️ WorkflowEditor: No currentWorkflow available for new node');
346
+ console.warn('No currentWorkflow available for new node');
327
347
  }
328
348
  }
329
349
  }}
@@ -57,7 +57,6 @@ export class EdgeStylingHelper {
57
57
  const sourceNode = nodes.find((node) => node.id === edge.source);
58
58
  const targetNode = nodes.find((node) => node.id === edge.target);
59
59
  if (!sourceNode || !targetNode) {
60
- console.warn('Could not find nodes for edge:', edge.id);
61
60
  return edge;
62
61
  }
63
62
  // Create a copy of the edge and apply styling
@@ -258,7 +257,7 @@ export class WorkflowOperationsHelper {
258
257
  */
259
258
  static async saveWorkflow(workflow) {
260
259
  if (!workflow) {
261
- console.warn('⚠️ No workflow data available to save');
260
+ console.warn('No workflow data available to save');
262
261
  return null;
263
262
  }
264
263
  try {
@@ -283,21 +282,9 @@ export class WorkflowOperationsHelper {
283
282
  updatedAt: new Date().toISOString()
284
283
  }
285
284
  };
286
- console.log('💾 WorkflowEditor: Saving workflow to backend:');
287
- console.log(' - ID:', workflowToSave.id);
288
- console.log(' - Name:', workflowToSave.name);
289
- console.log(' - Nodes count:', workflowToSave.nodes.length);
290
- console.log(' - Edges count:', workflowToSave.edges.length);
291
- console.log(' - Full workflow object:', JSON.stringify(workflowToSave, null, 2));
292
285
  const savedWorkflow = await workflowApi.saveWorkflow(workflowToSave);
293
- console.log('✅ WorkflowEditor: Received workflow from backend:');
294
- console.log(' - ID:', savedWorkflow.id);
295
- console.log(' - Name:', savedWorkflow.name);
296
- console.log(' - Nodes count:', savedWorkflow.nodes?.length || 0);
297
- console.log(' - Edges count:', savedWorkflow.edges?.length || 0);
298
286
  // Update the workflow ID if it changed (new workflow)
299
287
  if (savedWorkflow.id && savedWorkflow.id !== workflowToSave.id) {
300
- console.log('🔄 Updating workflow ID from', workflowToSave.id, 'to', savedWorkflow.id);
301
288
  workflowActions.batchUpdate({
302
289
  nodes: workflowToSave.nodes,
303
290
  edges: workflowToSave.edges,
@@ -320,7 +307,7 @@ export class WorkflowOperationsHelper {
320
307
  */
321
308
  static exportWorkflow(workflow) {
322
309
  if (!workflow) {
323
- console.warn('⚠️ No workflow data available to export');
310
+ console.warn('No workflow data available to export');
324
311
  return;
325
312
  }
326
313
  // Use the same ID logic as saveWorkflow
@@ -26,7 +26,6 @@ export class NodeExecutionService {
26
26
  */
27
27
  async getNodeExecutionInfo(nodeId, pipelineId) {
28
28
  if (!pipelineId) {
29
- console.warn('Pipeline ID is required to fetch node execution info');
30
29
  return null;
31
30
  }
32
31
  try {
@@ -72,12 +71,10 @@ export class NodeExecutionService {
72
71
  */
73
72
  async getMultipleNodeExecutionInfo(nodeIds, pipelineId) {
74
73
  if (!pipelineId) {
75
- console.warn('Pipeline ID is required to fetch node execution info');
76
74
  return {};
77
75
  }
78
76
  // Check if API is temporarily unavailable
79
77
  if (this.apiUnavailable && Date.now() < this.apiUnavailableUntil) {
80
- console.log('API temporarily unavailable, returning cached/default values');
81
78
  const defaultExecutionInfo = {};
82
79
  nodeIds.forEach((nodeId) => {
83
80
  defaultExecutionInfo[nodeId] = {
@@ -11,27 +11,19 @@ import { FlowDropApiClient } from '../api/client.js';
11
11
  export async function fetchPortConfig(endpointConfig) {
12
12
  try {
13
13
  const url = buildEndpointUrl(endpointConfig, endpointConfig.endpoints.portConfig);
14
- console.log('📡 Fetching port configuration from:', url);
15
14
  // Create API client instance
16
15
  const client = new FlowDropApiClient(endpointConfig.baseUrl);
17
16
  // Use the client to fetch port configuration
18
17
  const portConfig = await client.getPortConfig();
19
18
  // Validate the configuration has required fields
20
19
  if (!portConfig.dataTypes || !Array.isArray(portConfig.dataTypes)) {
21
- console.warn('⚠️ Invalid port config received from API, using default');
20
+ console.warn('Invalid port config received from API, using default');
22
21
  return DEFAULT_PORT_CONFIG;
23
22
  }
24
- console.log('✅ Port configuration loaded successfully:', {
25
- version: portConfig.version,
26
- dataTypesCount: portConfig.dataTypes.length,
27
- rulesCount: portConfig.compatibilityRules?.length || 0,
28
- defaultType: portConfig.defaultDataType
29
- });
30
23
  return portConfig;
31
24
  }
32
25
  catch (error) {
33
- console.error('Error fetching port configuration:', error);
34
- console.log('🔄 Falling back to default port configuration');
26
+ console.error('Error fetching port configuration:', error);
35
27
  return DEFAULT_PORT_CONFIG;
36
28
  }
37
29
  }
@@ -52,15 +52,11 @@ function hasWorkflowDataChanged(currentWorkflow, newNodes, newEdges) {
52
52
  export const workflowActions = {
53
53
  // Initialize workflow
54
54
  initialize: (workflow) => {
55
- console.log('🔍 Debug: initialize called with:', workflow);
56
55
  workflowStore.set(workflow);
57
- console.log('🔍 Debug: workflow store initialized');
58
56
  },
59
57
  // Update the entire workflow
60
58
  updateWorkflow: (workflow) => {
61
- console.log('🔍 Debug: updateWorkflow called with:', workflow);
62
59
  workflowStore.set(workflow);
63
- console.log('🔍 Debug: workflow store updated');
64
60
  },
65
61
  // Update nodes
66
62
  updateNodes: (nodes) => {
@@ -69,16 +65,10 @@ export const workflowActions = {
69
65
  return null;
70
66
  // Check if nodes have actually changed to prevent infinite loops
71
67
  if (!hasWorkflowDataChanged($workflow, nodes, $workflow.edges)) {
72
- console.log('🔍 Debug: Nodes unchanged, skipping update to prevent infinite loop');
73
68
  return $workflow;
74
69
  }
75
70
  // Generate unique version identifier
76
71
  const versionId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
77
- console.log('🔍 Debug: Updating nodes with versionId:', versionId);
78
- console.log('🔍 Debug: Node position changes detected:', nodes.map((node) => ({
79
- id: node.id,
80
- position: node.position
81
- })));
82
72
  return {
83
73
  ...$workflow,
84
74
  nodes,
@@ -98,12 +88,10 @@ export const workflowActions = {
98
88
  return null;
99
89
  // Check if edges have actually changed to prevent infinite loops
100
90
  if (!hasWorkflowDataChanged($workflow, $workflow.nodes, edges)) {
101
- console.log('🔍 Debug: Edges unchanged, skipping update to prevent infinite loop');
102
91
  return $workflow;
103
92
  }
104
93
  // Generate unique version identifier
105
94
  const versionId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
106
- console.log('🔍 Debug: Updating edges with versionId:', versionId);
107
95
  return {
108
96
  ...$workflow,
109
97
  edges,
@@ -159,13 +159,6 @@ export function validateConnection(sourceNodeId, sourcePortId, targetNodeId, tar
159
159
  const sourceMetadata = nodeTypes.find((nt) => nt.id === sourceNode.data.metadata.id);
160
160
  const targetMetadata = nodeTypes.find((nt) => nt.id === targetNode.data.metadata.id);
161
161
  if (!sourceMetadata || !targetMetadata) {
162
- console.log('Metadata lookup failed:', {
163
- sourceNodeId,
164
- targetNodeId,
165
- sourceMetadataId: sourceNode.data.metadata.id,
166
- targetMetadataId: targetNode.data.metadata.id,
167
- availableNodeTypes: nodeTypes.map((nt) => nt.id)
168
- });
169
162
  return { valid: false, error: 'Node metadata not found' };
170
163
  }
171
164
  // Find ports
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@d34dman/flowdrop",
3
3
  "license": "MIT",
4
4
  "private": false,
5
- "version": "0.0.8",
5
+ "version": "0.0.10",
6
6
  "scripts": {
7
7
  "dev": "vite dev",
8
8
  "build": "vite build && npm run prepack",