@d34dman/flowdrop 0.0.1 → 0.0.2
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.
- package/README.md +307 -215
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +30 -30
- package/dist/api/client.d.ts +24 -1
- package/dist/api/client.js +55 -38
- package/dist/api/enhanced-client.d.ts +46 -0
- package/dist/api/enhanced-client.js +211 -0
- package/dist/clients/ApiClient.d.ts +19 -23
- package/dist/clients/ApiClient.js +36 -34
- package/dist/components/App.svelte +1299 -230
- package/dist/components/App.svelte.d.ts +21 -1
- package/dist/components/CanvasBanner.svelte +50 -44
- package/dist/components/CanvasBanner.svelte.d.ts +5 -19
- package/dist/components/ConfigForm.svelte +555 -0
- package/dist/components/ConfigForm.svelte.d.ts +32 -0
- package/dist/components/ConfigModal.svelte +261 -0
- package/dist/components/ConfigModal.svelte.d.ts +31 -0
- package/dist/components/ConfigSidebar.svelte +934 -0
- package/dist/components/ConfigSidebar.svelte.d.ts +51 -0
- package/dist/components/ConnectionLine.svelte +32 -0
- package/dist/components/ConnectionLine.svelte.d.ts +3 -0
- package/dist/components/GatewayNode.svelte +471 -0
- package/dist/components/GatewayNode.svelte.d.ts +15 -0
- package/dist/components/LoadingSpinner.svelte +23 -23
- package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
- package/dist/components/Logo.svelte +82 -0
- package/dist/components/Logo.svelte.d.ts +26 -0
- package/dist/components/LogsSidebar.svelte +565 -0
- package/dist/components/LogsSidebar.svelte.d.ts +34 -0
- package/dist/components/MarkdownDisplay.svelte +28 -0
- package/dist/components/MarkdownDisplay.svelte.d.ts +7 -0
- package/dist/components/Navbar.svelte +663 -0
- package/dist/components/Navbar.svelte.d.ts +21 -0
- package/dist/components/NodeSidebar.svelte +629 -488
- package/dist/components/NodeSidebar.svelte.d.ts +1 -2
- package/dist/components/NodeStatusOverlay.svelte +327 -0
- package/dist/components/NodeStatusOverlay.svelte.d.ts +11 -0
- package/dist/components/NotesNode.svelte +566 -0
- package/dist/components/NotesNode.svelte.d.ts +43 -0
- package/dist/components/PipelineStatus.svelte +331 -0
- package/dist/components/PipelineStatus.svelte.d.ts +18 -0
- package/dist/components/SimpleNode.svelte +447 -0
- package/dist/components/SimpleNode.svelte.d.ts +24 -0
- package/dist/components/SquareNode.svelte +346 -0
- package/dist/components/SquareNode.svelte.d.ts +24 -0
- package/dist/components/StatusIcon.svelte +112 -0
- package/dist/components/StatusIcon.svelte.d.ts +10 -0
- package/dist/components/StatusLabel.svelte +33 -0
- package/dist/components/StatusLabel.svelte.d.ts +7 -0
- package/dist/components/ToolNode.svelte +385 -0
- package/dist/components/ToolNode.svelte.d.ts +36 -0
- package/dist/components/UniversalNode.svelte +126 -0
- package/dist/components/UniversalNode.svelte.d.ts +15 -0
- package/dist/components/WorkflowEditor.svelte +871 -528
- package/dist/components/WorkflowEditor.svelte.d.ts +15 -5
- package/dist/components/WorkflowNode.svelte +428 -542
- package/dist/components/WorkflowNode.svelte.d.ts +7 -3
- package/dist/config/apiConfig.d.ts +33 -0
- package/dist/config/apiConfig.js +39 -0
- package/dist/config/defaultPortConfig.d.ts +6 -0
- package/dist/config/defaultPortConfig.js +192 -0
- package/dist/config/demo.d.ts +58 -0
- package/dist/config/demo.js +142 -0
- package/dist/config/endpoints.d.ts +106 -0
- package/dist/config/endpoints.js +128 -0
- package/dist/data/samples.d.ts +38 -4
- package/dist/data/samples.js +2789 -737
- package/dist/examples/adapter-usage.d.ts +4 -4
- package/dist/examples/adapter-usage.js +21 -26
- package/dist/examples/api-client-usage.d.ts +6 -6
- package/dist/examples/api-client-usage.js +55 -54
- package/dist/index.d.ts +23 -15
- package/dist/index.js +23 -15
- package/dist/mocks/app-environment.d.ts +8 -0
- package/dist/mocks/app-environment.js +16 -0
- package/dist/mocks/app-forms.d.ts +2 -0
- package/dist/mocks/app-forms.js +21 -0
- package/dist/mocks/app-navigation.d.ts +5 -0
- package/dist/mocks/app-navigation.js +34 -0
- package/dist/mocks/app-stores.d.ts +14 -0
- package/dist/mocks/app-stores.js +26 -0
- package/dist/services/api.d.ts +13 -3
- package/dist/services/api.js +91 -36
- package/dist/services/globalSave.d.ts +20 -0
- package/dist/services/globalSave.js +165 -0
- package/dist/services/nodeExecutionService.d.ts +63 -0
- package/dist/services/nodeExecutionService.js +261 -0
- package/dist/services/portConfigApi.d.ts +14 -0
- package/dist/services/portConfigApi.js +69 -0
- package/dist/services/toastService.d.ts +147 -0
- package/dist/services/toastService.js +235 -0
- package/dist/services/workflowStorage.d.ts +2 -2
- package/dist/services/workflowStorage.js +10 -10
- package/dist/stores/workflowStore.d.ts +53 -0
- package/dist/stores/workflowStore.js +264 -0
- package/dist/styles/base.css +896 -363
- package/dist/svelte-app.d.ts +52 -5
- package/dist/svelte-app.js +128 -6
- package/dist/types/config.d.ts +291 -0
- package/dist/types/config.js +4 -0
- package/dist/types/index.d.ts +231 -19
- package/dist/types/index.js +1 -1
- package/dist/utils/colors.d.ts +67 -33
- package/dist/utils/colors.js +183 -118
- package/dist/utils/config.d.ts +41 -0
- package/dist/utils/config.js +248 -0
- package/dist/utils/connections.d.ts +40 -3
- package/dist/utils/connections.js +115 -44
- package/dist/utils/icons.d.ts +1 -1
- package/dist/utils/icons.js +71 -70
- package/dist/utils/nodeStatus.d.ts +53 -0
- package/dist/utils/nodeStatus.js +183 -0
- package/dist/utils/nodeTypes.d.ts +57 -0
- package/dist/utils/nodeTypes.js +109 -0
- package/dist/utils/nodeWrapper.d.ts +39 -0
- package/dist/utils/nodeWrapper.js +62 -0
- package/package.json +129 -97
- package/dist/components/Node.svelte +0 -38
- package/dist/components/Node.svelte.d.ts +0 -4
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast Service
|
|
3
|
+
* Centralized toast notification service using svelte-french-toast
|
|
4
|
+
* Provides consistent toast notifications across the FlowDrop application
|
|
5
|
+
*/
|
|
6
|
+
import { toast } from 'svelte-5-french-toast';
|
|
7
|
+
/**
|
|
8
|
+
* Show a success toast notification
|
|
9
|
+
*/
|
|
10
|
+
export function showSuccess(message, options) {
|
|
11
|
+
return toast.success(message, {
|
|
12
|
+
duration: options?.duration || 4000,
|
|
13
|
+
position: options?.position || 'bottom-center'
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Show an error toast notification
|
|
18
|
+
*/
|
|
19
|
+
export function showError(message, options) {
|
|
20
|
+
return toast.error(message, {
|
|
21
|
+
duration: options?.duration || 6000,
|
|
22
|
+
position: options?.position || 'bottom-center'
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Show a warning toast notification
|
|
27
|
+
*/
|
|
28
|
+
export function showWarning(message, options) {
|
|
29
|
+
return toast.error(message, {
|
|
30
|
+
duration: options?.duration || 5000,
|
|
31
|
+
position: options?.position || 'bottom-center'
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Show an info toast notification
|
|
36
|
+
*/
|
|
37
|
+
export function showInfo(message, options) {
|
|
38
|
+
return toast.success(message, {
|
|
39
|
+
duration: options?.duration || 4000,
|
|
40
|
+
position: options?.position || 'bottom-center'
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Show a loading toast notification
|
|
45
|
+
*/
|
|
46
|
+
export function showLoading(message, options) {
|
|
47
|
+
return toast.loading(message, {
|
|
48
|
+
duration: options?.duration || Infinity,
|
|
49
|
+
position: options?.position || 'bottom-center'
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Dismiss a specific toast by ID
|
|
54
|
+
*/
|
|
55
|
+
export function dismissToast(toastId) {
|
|
56
|
+
toast.dismiss(toastId);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Dismiss all toasts
|
|
60
|
+
*/
|
|
61
|
+
export function dismissAllToasts() {
|
|
62
|
+
toast.dismiss();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Show a promise-based toast (loading -> success/error)
|
|
66
|
+
*/
|
|
67
|
+
export function showPromise(promise, { loading, success, error, options }) {
|
|
68
|
+
return toast.promise(promise, {
|
|
69
|
+
loading,
|
|
70
|
+
success,
|
|
71
|
+
error,
|
|
72
|
+
...options
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Show a confirmation toast (simplified version without action buttons)
|
|
77
|
+
*/
|
|
78
|
+
export function showConfirmation(message, options) {
|
|
79
|
+
return toast(message, {
|
|
80
|
+
duration: options?.duration || 5000,
|
|
81
|
+
position: options?.position || 'bottom-center'
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* API-specific toast helpers
|
|
86
|
+
*/
|
|
87
|
+
export const apiToasts = {
|
|
88
|
+
/**
|
|
89
|
+
* Show API success message
|
|
90
|
+
*/
|
|
91
|
+
success: (operation, details) => {
|
|
92
|
+
const message = details ? `${operation}: ${details}` : operation;
|
|
93
|
+
return showSuccess(message);
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* Show API error message
|
|
97
|
+
*/
|
|
98
|
+
error: (operation, error) => {
|
|
99
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
100
|
+
return showError(`${operation} failed: ${errorMessage}`);
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* Show API loading message
|
|
104
|
+
*/
|
|
105
|
+
loading: (operation) => {
|
|
106
|
+
return showLoading(`${operation}...`);
|
|
107
|
+
},
|
|
108
|
+
/**
|
|
109
|
+
* Show API promise with automatic success/error handling
|
|
110
|
+
*/
|
|
111
|
+
promise: (promise, operation, options) => {
|
|
112
|
+
return showPromise(promise, {
|
|
113
|
+
loading: `${operation}...`,
|
|
114
|
+
success: options?.successMessage || `${operation} completed successfully`,
|
|
115
|
+
error: options?.errorMessage || `${operation} failed`
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Workflow-specific toast helpers
|
|
121
|
+
*/
|
|
122
|
+
export const workflowToasts = {
|
|
123
|
+
/**
|
|
124
|
+
* Show workflow save success
|
|
125
|
+
*/
|
|
126
|
+
saved: (workflowName) => {
|
|
127
|
+
const message = workflowName
|
|
128
|
+
? `Workflow "${workflowName}" saved successfully`
|
|
129
|
+
: 'Workflow saved successfully';
|
|
130
|
+
return showSuccess(message);
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* Show workflow save error
|
|
134
|
+
*/
|
|
135
|
+
saveError: (error) => {
|
|
136
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
137
|
+
return showError(`Failed to save workflow: ${errorMessage}`);
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* Show workflow delete success
|
|
141
|
+
*/
|
|
142
|
+
deleted: (workflowName) => {
|
|
143
|
+
const message = workflowName
|
|
144
|
+
? `Workflow "${workflowName}" deleted successfully`
|
|
145
|
+
: 'Workflow deleted successfully';
|
|
146
|
+
return showSuccess(message);
|
|
147
|
+
},
|
|
148
|
+
/**
|
|
149
|
+
* Show workflow delete error
|
|
150
|
+
*/
|
|
151
|
+
deleteError: (error) => {
|
|
152
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
153
|
+
return showError(`Failed to delete workflow: ${errorMessage}`);
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Show workflow execution started
|
|
157
|
+
*/
|
|
158
|
+
executionStarted: (workflowName) => {
|
|
159
|
+
const message = workflowName
|
|
160
|
+
? `Workflow "${workflowName}" execution started`
|
|
161
|
+
: 'Workflow execution started';
|
|
162
|
+
return showInfo(message);
|
|
163
|
+
},
|
|
164
|
+
/**
|
|
165
|
+
* Show workflow execution completed
|
|
166
|
+
*/
|
|
167
|
+
executionCompleted: (workflowName) => {
|
|
168
|
+
const message = workflowName
|
|
169
|
+
? `Workflow "${workflowName}" execution completed`
|
|
170
|
+
: 'Workflow execution completed';
|
|
171
|
+
return showSuccess(message);
|
|
172
|
+
},
|
|
173
|
+
/**
|
|
174
|
+
* Show workflow export success
|
|
175
|
+
*/
|
|
176
|
+
exported: (workflowName) => {
|
|
177
|
+
const message = workflowName
|
|
178
|
+
? `Workflow "${workflowName}" exported successfully`
|
|
179
|
+
: 'Workflow exported successfully';
|
|
180
|
+
return showSuccess(message);
|
|
181
|
+
},
|
|
182
|
+
/**
|
|
183
|
+
* Show workflow execution error
|
|
184
|
+
*/
|
|
185
|
+
executionError: (error) => {
|
|
186
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
187
|
+
return showError(`Workflow execution failed: ${errorMessage}`);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Pipeline-specific toast helpers
|
|
192
|
+
*/
|
|
193
|
+
export const pipelineToasts = {
|
|
194
|
+
/**
|
|
195
|
+
* Show pipeline creation success
|
|
196
|
+
*/
|
|
197
|
+
created: (pipelineName) => {
|
|
198
|
+
const message = pipelineName
|
|
199
|
+
? `Pipeline "${pipelineName}" created successfully`
|
|
200
|
+
: 'Pipeline created successfully';
|
|
201
|
+
return showSuccess(message);
|
|
202
|
+
},
|
|
203
|
+
/**
|
|
204
|
+
* Show pipeline creation error
|
|
205
|
+
*/
|
|
206
|
+
creationError: (error) => {
|
|
207
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
208
|
+
return showError(`Failed to create pipeline: ${errorMessage}`);
|
|
209
|
+
},
|
|
210
|
+
/**
|
|
211
|
+
* Show pipeline execution started
|
|
212
|
+
*/
|
|
213
|
+
executionStarted: (pipelineId) => {
|
|
214
|
+
return showInfo(`Pipeline ${pipelineId} execution started`);
|
|
215
|
+
},
|
|
216
|
+
/**
|
|
217
|
+
* Show pipeline execution completed
|
|
218
|
+
*/
|
|
219
|
+
executionCompleted: (pipelineId) => {
|
|
220
|
+
return showSuccess(`Pipeline ${pipelineId} execution completed`);
|
|
221
|
+
},
|
|
222
|
+
/**
|
|
223
|
+
* Show pipeline execution error
|
|
224
|
+
*/
|
|
225
|
+
executionError: (pipelineId, error) => {
|
|
226
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
227
|
+
return showError(`Pipeline ${pipelineId} execution failed: ${errorMessage}`);
|
|
228
|
+
},
|
|
229
|
+
/**
|
|
230
|
+
* Show pipeline status update
|
|
231
|
+
*/
|
|
232
|
+
statusUpdate: (pipelineId, status) => {
|
|
233
|
+
return showInfo(`Pipeline ${pipelineId} status: ${status}`);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* In-memory workflow storage service
|
|
3
3
|
* This can be replaced with a database implementation later
|
|
4
4
|
*/
|
|
5
|
-
import type { Workflow } from
|
|
5
|
+
import type { Workflow } from '../types/index.js';
|
|
6
6
|
/**
|
|
7
7
|
* Save a workflow
|
|
8
8
|
*/
|
|
9
|
-
export declare function saveWorkflow(workflow: Omit<Workflow,
|
|
9
|
+
export declare function saveWorkflow(workflow: Omit<Workflow, 'id'>): Promise<Workflow>;
|
|
10
10
|
/**
|
|
11
11
|
* Update an existing workflow
|
|
12
12
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* In-memory workflow storage service
|
|
3
3
|
* This can be replaced with a database implementation later
|
|
4
4
|
*/
|
|
5
|
-
import { v4 as uuidv4 } from
|
|
5
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
6
|
// In-memory storage
|
|
7
7
|
const workflows = new Map();
|
|
8
8
|
/**
|
|
@@ -20,7 +20,7 @@ export async function saveWorkflow(workflow) {
|
|
|
20
20
|
...workflow,
|
|
21
21
|
id,
|
|
22
22
|
metadata: {
|
|
23
|
-
version:
|
|
23
|
+
version: '1.0.0',
|
|
24
24
|
createdAt: new Date().toISOString(),
|
|
25
25
|
updatedAt: new Date().toISOString(),
|
|
26
26
|
...workflow.metadata
|
|
@@ -42,7 +42,7 @@ export async function updateWorkflow(id, workflow) {
|
|
|
42
42
|
...workflow,
|
|
43
43
|
id, // Ensure ID doesn't change
|
|
44
44
|
metadata: {
|
|
45
|
-
version: existing.metadata?.version ||
|
|
45
|
+
version: existing.metadata?.version || '1.0.0',
|
|
46
46
|
createdAt: existing.metadata?.createdAt || new Date().toISOString(),
|
|
47
47
|
updatedAt: new Date().toISOString(),
|
|
48
48
|
author: workflow.metadata?.author || existing.metadata?.author,
|
|
@@ -66,9 +66,9 @@ export async function getWorkflows(options) {
|
|
|
66
66
|
// Apply search filter
|
|
67
67
|
if (options?.search) {
|
|
68
68
|
const searchLower = options.search.toLowerCase();
|
|
69
|
-
filteredWorkflows = filteredWorkflows.filter(workflow => workflow.name.toLowerCase().includes(searchLower) ||
|
|
69
|
+
filteredWorkflows = filteredWorkflows.filter((workflow) => workflow.name.toLowerCase().includes(searchLower) ||
|
|
70
70
|
workflow.description?.toLowerCase().includes(searchLower) ||
|
|
71
|
-
workflow.metadata?.tags?.some(tag => tag.toLowerCase().includes(searchLower)));
|
|
71
|
+
workflow.metadata?.tags?.some((tag) => tag.toLowerCase().includes(searchLower)));
|
|
72
72
|
}
|
|
73
73
|
// Sort by updated date (newest first)
|
|
74
74
|
filteredWorkflows.sort((a, b) => new Date(b.metadata?.updatedAt || 0).getTime() -
|
|
@@ -100,16 +100,16 @@ export async function initializeSampleWorkflows() {
|
|
|
100
100
|
}
|
|
101
101
|
// Add a sample workflow
|
|
102
102
|
const sampleWorkflow = {
|
|
103
|
-
name:
|
|
104
|
-
description:
|
|
103
|
+
name: 'Sample Chat Workflow',
|
|
104
|
+
description: 'A simple workflow demonstrating chat completion',
|
|
105
105
|
nodes: [],
|
|
106
106
|
edges: [],
|
|
107
107
|
metadata: {
|
|
108
|
-
version:
|
|
108
|
+
version: '1.0.0',
|
|
109
109
|
createdAt: new Date().toISOString(),
|
|
110
110
|
updatedAt: new Date().toISOString(),
|
|
111
|
-
author:
|
|
112
|
-
tags: [
|
|
111
|
+
author: 'System',
|
|
112
|
+
tags: ['sample', 'chat']
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
115
|
await saveWorkflow(sampleWorkflow);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Workflow, WorkflowNode, WorkflowEdge } from '../types';
|
|
2
|
+
export declare const workflowStore: import("svelte/store").Writable<Workflow>;
|
|
3
|
+
export declare const workflowId: import("svelte/store").Readable<string>;
|
|
4
|
+
export declare const workflowName: import("svelte/store").Readable<string>;
|
|
5
|
+
export declare const workflowNodes: import("svelte/store").Readable<WorkflowNode[]>;
|
|
6
|
+
export declare const workflowEdges: import("svelte/store").Readable<WorkflowEdge[]>;
|
|
7
|
+
export declare const workflowMetadata: import("svelte/store").Readable<{
|
|
8
|
+
version: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
updatedAt: string;
|
|
11
|
+
author?: string;
|
|
12
|
+
tags?: string[];
|
|
13
|
+
versionId?: string;
|
|
14
|
+
updateNumber?: number;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const workflowActions: {
|
|
17
|
+
initialize: (workflow: Workflow) => void;
|
|
18
|
+
updateWorkflow: (workflow: Workflow) => void;
|
|
19
|
+
updateNodes: (nodes: WorkflowNode[]) => void;
|
|
20
|
+
updateEdges: (edges: WorkflowEdge[]) => void;
|
|
21
|
+
updateName: (name: string) => void;
|
|
22
|
+
addNode: (node: WorkflowNode) => void;
|
|
23
|
+
removeNode: (nodeId: string) => void;
|
|
24
|
+
addEdge: (edge: WorkflowEdge) => void;
|
|
25
|
+
removeEdge: (edgeId: string) => void;
|
|
26
|
+
updateNode: (nodeId: string, updates: Partial<WorkflowNode>) => void;
|
|
27
|
+
clear: () => void;
|
|
28
|
+
updateMetadata: (metadata: Partial<Workflow["metadata"]>) => void;
|
|
29
|
+
batchUpdate: (updates: {
|
|
30
|
+
nodes?: WorkflowNode[];
|
|
31
|
+
edges?: WorkflowEdge[];
|
|
32
|
+
name?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
metadata?: Partial<Workflow["metadata"]>;
|
|
35
|
+
}) => void;
|
|
36
|
+
};
|
|
37
|
+
export declare const workflowChanged: import("svelte/store").Readable<{
|
|
38
|
+
nodes: WorkflowNode[];
|
|
39
|
+
edges: WorkflowEdge[];
|
|
40
|
+
name: string;
|
|
41
|
+
}>;
|
|
42
|
+
export declare const workflowValidation: import("svelte/store").Readable<{
|
|
43
|
+
hasNodes: boolean;
|
|
44
|
+
hasEdges: boolean;
|
|
45
|
+
nodeCount: number;
|
|
46
|
+
edgeCount: number;
|
|
47
|
+
isValid: boolean;
|
|
48
|
+
}>;
|
|
49
|
+
export declare const workflowMetadataChanged: import("svelte/store").Readable<{
|
|
50
|
+
createdAt: string;
|
|
51
|
+
updatedAt: string;
|
|
52
|
+
version: string;
|
|
53
|
+
}>;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { writable, derived } from 'svelte/store';
|
|
2
|
+
// Global workflow state
|
|
3
|
+
export const workflowStore = writable(null);
|
|
4
|
+
// Derived stores for individual workflow properties
|
|
5
|
+
export const workflowId = derived(workflowStore, ($workflow) => $workflow?.id || null);
|
|
6
|
+
export const workflowName = derived(workflowStore, ($workflow) => $workflow?.name || 'Untitled Workflow');
|
|
7
|
+
export const workflowNodes = derived(workflowStore, ($workflow) => $workflow?.nodes || []);
|
|
8
|
+
export const workflowEdges = derived(workflowStore, ($workflow) => $workflow?.edges || []);
|
|
9
|
+
export const workflowMetadata = derived(workflowStore, ($workflow) => $workflow?.metadata || {
|
|
10
|
+
version: '1.0.0',
|
|
11
|
+
createdAt: new Date().toISOString(),
|
|
12
|
+
updatedAt: new Date().toISOString(),
|
|
13
|
+
versionId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
14
|
+
updateNumber: 0
|
|
15
|
+
});
|
|
16
|
+
// Helper function to check if workflow data has actually changed
|
|
17
|
+
function hasWorkflowDataChanged(currentWorkflow, newNodes, newEdges) {
|
|
18
|
+
if (!currentWorkflow)
|
|
19
|
+
return true;
|
|
20
|
+
// Check if nodes have changed
|
|
21
|
+
if (currentWorkflow.nodes.length !== newNodes.length)
|
|
22
|
+
return true;
|
|
23
|
+
for (let i = 0; i < newNodes.length; i++) {
|
|
24
|
+
const currentNode = currentWorkflow.nodes[i];
|
|
25
|
+
const newNode = newNodes[i];
|
|
26
|
+
if (!currentNode || !newNode)
|
|
27
|
+
return true;
|
|
28
|
+
if (currentNode.id !== newNode.id)
|
|
29
|
+
return true;
|
|
30
|
+
if (currentNode.position.x !== newNode.position.x ||
|
|
31
|
+
currentNode.position.y !== newNode.position.y)
|
|
32
|
+
return true;
|
|
33
|
+
if (JSON.stringify(currentNode.data) !== JSON.stringify(newNode.data))
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// Check if edges have changed
|
|
37
|
+
if (currentWorkflow.edges.length !== newEdges.length)
|
|
38
|
+
return true;
|
|
39
|
+
for (let i = 0; i < newEdges.length; i++) {
|
|
40
|
+
const currentEdge = currentWorkflow.edges[i];
|
|
41
|
+
const newEdge = newEdges[i];
|
|
42
|
+
if (!currentEdge || !newEdge)
|
|
43
|
+
return true;
|
|
44
|
+
if (currentEdge.id !== newEdge.id)
|
|
45
|
+
return true;
|
|
46
|
+
if (currentEdge.source !== newEdge.source || currentEdge.target !== newEdge.target)
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
// Actions for updating the workflow
|
|
52
|
+
export const workflowActions = {
|
|
53
|
+
// Initialize workflow
|
|
54
|
+
initialize: (workflow) => {
|
|
55
|
+
console.log('🔍 Debug: initialize called with:', workflow);
|
|
56
|
+
workflowStore.set(workflow);
|
|
57
|
+
console.log('🔍 Debug: workflow store initialized');
|
|
58
|
+
},
|
|
59
|
+
// Update the entire workflow
|
|
60
|
+
updateWorkflow: (workflow) => {
|
|
61
|
+
console.log('🔍 Debug: updateWorkflow called with:', workflow);
|
|
62
|
+
workflowStore.set(workflow);
|
|
63
|
+
console.log('🔍 Debug: workflow store updated');
|
|
64
|
+
},
|
|
65
|
+
// Update nodes
|
|
66
|
+
updateNodes: (nodes) => {
|
|
67
|
+
workflowStore.update(($workflow) => {
|
|
68
|
+
if (!$workflow)
|
|
69
|
+
return null;
|
|
70
|
+
// Check if nodes have actually changed to prevent infinite loops
|
|
71
|
+
if (!hasWorkflowDataChanged($workflow, nodes, $workflow.edges)) {
|
|
72
|
+
console.log('🔍 Debug: Nodes unchanged, skipping update to prevent infinite loop');
|
|
73
|
+
return $workflow;
|
|
74
|
+
}
|
|
75
|
+
// Generate unique version identifier
|
|
76
|
+
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
|
+
return {
|
|
83
|
+
...$workflow,
|
|
84
|
+
nodes,
|
|
85
|
+
metadata: {
|
|
86
|
+
...$workflow.metadata,
|
|
87
|
+
updatedAt: new Date().toISOString(),
|
|
88
|
+
versionId,
|
|
89
|
+
updateNumber: ($workflow.metadata?.updateNumber || 0) + 1
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
// Update edges
|
|
95
|
+
updateEdges: (edges) => {
|
|
96
|
+
workflowStore.update(($workflow) => {
|
|
97
|
+
if (!$workflow)
|
|
98
|
+
return null;
|
|
99
|
+
// Check if edges have actually changed to prevent infinite loops
|
|
100
|
+
if (!hasWorkflowDataChanged($workflow, $workflow.nodes, edges)) {
|
|
101
|
+
console.log('🔍 Debug: Edges unchanged, skipping update to prevent infinite loop');
|
|
102
|
+
return $workflow;
|
|
103
|
+
}
|
|
104
|
+
// Generate unique version identifier
|
|
105
|
+
const versionId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
106
|
+
console.log('🔍 Debug: Updating edges with versionId:', versionId);
|
|
107
|
+
return {
|
|
108
|
+
...$workflow,
|
|
109
|
+
edges,
|
|
110
|
+
metadata: {
|
|
111
|
+
...$workflow.metadata,
|
|
112
|
+
updatedAt: new Date().toISOString(),
|
|
113
|
+
versionId,
|
|
114
|
+
updateNumber: ($workflow.metadata?.updateNumber || 0) + 1
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
// Update workflow name
|
|
120
|
+
updateName: (name) => {
|
|
121
|
+
workflowStore.update(($workflow) => {
|
|
122
|
+
if (!$workflow)
|
|
123
|
+
return null;
|
|
124
|
+
return {
|
|
125
|
+
...$workflow,
|
|
126
|
+
name,
|
|
127
|
+
metadata: {
|
|
128
|
+
...$workflow.metadata,
|
|
129
|
+
updatedAt: new Date().toISOString()
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
// Add a node
|
|
135
|
+
addNode: (node) => {
|
|
136
|
+
workflowStore.update(($workflow) => {
|
|
137
|
+
if (!$workflow)
|
|
138
|
+
return null;
|
|
139
|
+
return {
|
|
140
|
+
...$workflow,
|
|
141
|
+
nodes: [...$workflow.nodes, node],
|
|
142
|
+
metadata: {
|
|
143
|
+
...$workflow.metadata,
|
|
144
|
+
updatedAt: new Date().toISOString()
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
// Remove a node
|
|
150
|
+
removeNode: (nodeId) => {
|
|
151
|
+
workflowStore.update(($workflow) => {
|
|
152
|
+
if (!$workflow)
|
|
153
|
+
return null;
|
|
154
|
+
return {
|
|
155
|
+
...$workflow,
|
|
156
|
+
nodes: $workflow.nodes.filter((node) => node.id !== nodeId),
|
|
157
|
+
edges: $workflow.edges.filter((edge) => edge.source !== nodeId && edge.target !== nodeId),
|
|
158
|
+
metadata: {
|
|
159
|
+
...$workflow.metadata,
|
|
160
|
+
updatedAt: new Date().toISOString()
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
// Add an edge
|
|
166
|
+
addEdge: (edge) => {
|
|
167
|
+
workflowStore.update(($workflow) => {
|
|
168
|
+
if (!$workflow)
|
|
169
|
+
return null;
|
|
170
|
+
return {
|
|
171
|
+
...$workflow,
|
|
172
|
+
edges: [...$workflow.edges, edge],
|
|
173
|
+
metadata: {
|
|
174
|
+
...$workflow.metadata,
|
|
175
|
+
updatedAt: new Date().toISOString()
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
// Remove an edge
|
|
181
|
+
removeEdge: (edgeId) => {
|
|
182
|
+
workflowStore.update(($workflow) => {
|
|
183
|
+
if (!$workflow)
|
|
184
|
+
return null;
|
|
185
|
+
return {
|
|
186
|
+
...$workflow,
|
|
187
|
+
edges: $workflow.edges.filter((edge) => edge.id !== edgeId),
|
|
188
|
+
metadata: {
|
|
189
|
+
...$workflow.metadata,
|
|
190
|
+
updatedAt: new Date().toISOString()
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
// Update a specific node
|
|
196
|
+
updateNode: (nodeId, updates) => {
|
|
197
|
+
workflowStore.update(($workflow) => {
|
|
198
|
+
if (!$workflow)
|
|
199
|
+
return null;
|
|
200
|
+
return {
|
|
201
|
+
...$workflow,
|
|
202
|
+
nodes: $workflow.nodes.map((node) => (node.id === nodeId ? { ...node, ...updates } : node)),
|
|
203
|
+
metadata: {
|
|
204
|
+
...$workflow.metadata,
|
|
205
|
+
updatedAt: new Date().toISOString()
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
// Clear the workflow
|
|
211
|
+
clear: () => {
|
|
212
|
+
workflowStore.set(null);
|
|
213
|
+
},
|
|
214
|
+
// Update workflow metadata
|
|
215
|
+
updateMetadata: (metadata) => {
|
|
216
|
+
workflowStore.update(($workflow) => {
|
|
217
|
+
if (!$workflow)
|
|
218
|
+
return null;
|
|
219
|
+
return {
|
|
220
|
+
...$workflow,
|
|
221
|
+
metadata: {
|
|
222
|
+
...$workflow.metadata,
|
|
223
|
+
...metadata,
|
|
224
|
+
updatedAt: new Date().toISOString()
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
// Batch update nodes and edges (useful for complex operations)
|
|
230
|
+
batchUpdate: (updates) => {
|
|
231
|
+
workflowStore.update(($workflow) => {
|
|
232
|
+
if (!$workflow)
|
|
233
|
+
return null;
|
|
234
|
+
return {
|
|
235
|
+
...$workflow,
|
|
236
|
+
...(updates.nodes && { nodes: updates.nodes }),
|
|
237
|
+
...(updates.edges && { edges: updates.edges }),
|
|
238
|
+
...(updates.name && { name: updates.name }),
|
|
239
|
+
...(updates.description !== undefined && { description: updates.description }),
|
|
240
|
+
metadata: {
|
|
241
|
+
...$workflow.metadata,
|
|
242
|
+
...(updates.metadata && { ...updates.metadata }),
|
|
243
|
+
updatedAt: new Date().toISOString()
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
// Derived store for workflow changes (useful for triggering saves)
|
|
250
|
+
export const workflowChanged = derived([workflowNodes, workflowEdges, workflowName], ([nodes, edges, name]) => ({ nodes, edges, name }));
|
|
251
|
+
// Derived store for workflow validation
|
|
252
|
+
export const workflowValidation = derived([workflowNodes, workflowEdges], ([nodes, edges]) => ({
|
|
253
|
+
hasNodes: nodes.length > 0,
|
|
254
|
+
hasEdges: edges.length > 0,
|
|
255
|
+
nodeCount: nodes.length,
|
|
256
|
+
edgeCount: edges.length,
|
|
257
|
+
isValid: nodes.length > 0 && edges.length >= 0
|
|
258
|
+
}));
|
|
259
|
+
// Derived store for workflow metadata changes
|
|
260
|
+
export const workflowMetadataChanged = derived(workflowMetadata, (metadata) => ({
|
|
261
|
+
createdAt: metadata.createdAt,
|
|
262
|
+
updatedAt: metadata.updatedAt,
|
|
263
|
+
version: metadata.version || '1.0.0'
|
|
264
|
+
}));
|