@d34dman/flowdrop 0.0.15 → 0.0.16
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 +0 -1
- package/dist/api/enhanced-client.d.ts +121 -5
- package/dist/api/enhanced-client.js +245 -66
- package/dist/components/App.svelte +145 -33
- package/dist/components/App.svelte.d.ts +27 -1
- package/dist/data/samples.js +9 -9
- package/dist/examples/adapter-usage.js +1 -1
- package/dist/index.d.ts +13 -6
- package/dist/index.js +12 -4
- package/dist/services/draftStorage.d.ts +171 -0
- package/dist/services/draftStorage.js +298 -0
- package/dist/stores/workflowStore.d.ts +104 -1
- package/dist/stores/workflowStore.js +251 -31
- package/dist/svelte-app.d.ts +112 -30
- package/dist/svelte-app.js +162 -39
- package/dist/types/auth.d.ts +278 -0
- package/dist/types/auth.js +244 -0
- package/dist/types/events.d.ts +163 -0
- package/dist/types/events.js +30 -0
- package/package.json +2 -3
|
@@ -17,24 +17,44 @@
|
|
|
17
17
|
import { sampleNodes } from '../data/samples.js';
|
|
18
18
|
import { createEndpointConfig } from '../config/endpoints.js';
|
|
19
19
|
import type { EndpointConfig } from '../config/endpoints.js';
|
|
20
|
-
import {
|
|
20
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
21
|
+
import type { FlowDropEventHandlers, FlowDropFeatures } from '../types/events.js';
|
|
22
|
+
import { mergeFeatures } from '../types/events.js';
|
|
23
|
+
import {
|
|
24
|
+
workflowStore,
|
|
25
|
+
workflowActions,
|
|
26
|
+
workflowName,
|
|
27
|
+
markAsSaved
|
|
28
|
+
} from '../stores/workflowStore.js';
|
|
21
29
|
import { apiToasts, dismissToast } from '../services/toastService.js';
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Configuration props for runtime customization
|
|
33
|
+
*/
|
|
24
34
|
interface Props {
|
|
35
|
+
/** Initial workflow to load */
|
|
25
36
|
workflow?: Workflow;
|
|
37
|
+
/** Pre-loaded node types (if provided, skips API fetch) */
|
|
38
|
+
nodes?: NodeMetadata[];
|
|
39
|
+
/** Editor height */
|
|
26
40
|
height?: string | number;
|
|
41
|
+
/** Editor width */
|
|
27
42
|
width?: string | number;
|
|
43
|
+
/** Show the navbar */
|
|
28
44
|
showNavbar?: boolean;
|
|
29
|
-
|
|
45
|
+
/** Disable the node sidebar */
|
|
30
46
|
disableSidebar?: boolean;
|
|
47
|
+
/** Lock the workflow (prevent changes) */
|
|
31
48
|
lockWorkflow?: boolean;
|
|
49
|
+
/** Read-only mode */
|
|
32
50
|
readOnly?: boolean;
|
|
51
|
+
/** Node execution statuses */
|
|
33
52
|
nodeStatuses?: Record<string, 'pending' | 'running' | 'completed' | 'error'>;
|
|
34
|
-
|
|
53
|
+
/** Pipeline ID for fetching node execution info */
|
|
35
54
|
pipelineId?: string;
|
|
36
|
-
|
|
55
|
+
/** Custom navbar title */
|
|
37
56
|
navbarTitle?: string;
|
|
57
|
+
/** Custom navbar actions */
|
|
38
58
|
navbarActions?: Array<{
|
|
39
59
|
label: string;
|
|
40
60
|
href: string;
|
|
@@ -42,13 +62,21 @@
|
|
|
42
62
|
variant?: 'primary' | 'secondary' | 'outline';
|
|
43
63
|
onclick?: (event: Event) => void;
|
|
44
64
|
}>;
|
|
45
|
-
|
|
65
|
+
/** API base URL */
|
|
46
66
|
apiBaseUrl?: string;
|
|
67
|
+
/** Endpoint configuration */
|
|
47
68
|
endpointConfig?: EndpointConfig;
|
|
69
|
+
/** Authentication provider */
|
|
70
|
+
authProvider?: AuthProvider;
|
|
71
|
+
/** Event handlers */
|
|
72
|
+
eventHandlers?: FlowDropEventHandlers;
|
|
73
|
+
/** Feature configuration */
|
|
74
|
+
features?: FlowDropFeatures;
|
|
48
75
|
}
|
|
49
76
|
|
|
50
77
|
let {
|
|
51
78
|
workflow: initialWorkflow,
|
|
79
|
+
nodes: propNodes,
|
|
52
80
|
height = '100vh',
|
|
53
81
|
width = '100%',
|
|
54
82
|
showNavbar = false,
|
|
@@ -60,9 +88,15 @@
|
|
|
60
88
|
navbarTitle,
|
|
61
89
|
navbarActions = [],
|
|
62
90
|
apiBaseUrl,
|
|
63
|
-
endpointConfig: propEndpointConfig
|
|
91
|
+
endpointConfig: propEndpointConfig,
|
|
92
|
+
authProvider,
|
|
93
|
+
eventHandlers,
|
|
94
|
+
features: propFeatures
|
|
64
95
|
}: Props = $props();
|
|
65
96
|
|
|
97
|
+
// Merge features with defaults
|
|
98
|
+
const features = mergeFeatures(propFeatures);
|
|
99
|
+
|
|
66
100
|
// Create breadcrumb-style title - at top level to avoid store subscription issues
|
|
67
101
|
let breadcrumbTitle = $derived(() => {
|
|
68
102
|
// Use custom navbar title if provided
|
|
@@ -129,10 +163,19 @@
|
|
|
129
163
|
|
|
130
164
|
/**
|
|
131
165
|
* Fetch node types from the server
|
|
166
|
+
*
|
|
167
|
+
* If propNodes is provided, uses those instead of fetching from API.
|
|
168
|
+
* This fixes the bug where propNodes was ignored.
|
|
132
169
|
*/
|
|
133
170
|
async function fetchNodeTypes(): Promise<void> {
|
|
134
|
-
//
|
|
135
|
-
|
|
171
|
+
// If nodes were provided as props, use them directly (skip API fetch)
|
|
172
|
+
if (propNodes && propNodes.length > 0) {
|
|
173
|
+
nodes = propNodes;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Show loading toast (if toasts are enabled)
|
|
178
|
+
const loadingToast = features.showToasts ? apiToasts.loading('Loading node types') : null;
|
|
136
179
|
try {
|
|
137
180
|
error = null;
|
|
138
181
|
|
|
@@ -142,13 +185,35 @@
|
|
|
142
185
|
error = null;
|
|
143
186
|
|
|
144
187
|
// Dismiss loading toast
|
|
145
|
-
|
|
188
|
+
if (loadingToast) {
|
|
189
|
+
dismissToast(loadingToast);
|
|
190
|
+
}
|
|
146
191
|
} catch (err) {
|
|
147
192
|
// Dismiss loading toast and show error toast
|
|
148
|
-
|
|
193
|
+
if (loadingToast) {
|
|
194
|
+
dismissToast(loadingToast);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
198
|
+
|
|
199
|
+
// Notify parent via event handler
|
|
200
|
+
if (eventHandlers?.onApiError) {
|
|
201
|
+
const suppressToast = eventHandlers.onApiError(
|
|
202
|
+
err instanceof Error ? err : new Error(errorMessage),
|
|
203
|
+
'fetchNodes'
|
|
204
|
+
);
|
|
205
|
+
if (suppressToast) {
|
|
206
|
+
// Parent handled the error, don't show default toast
|
|
207
|
+
nodes = sampleNodes;
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
149
212
|
// Show error but don't block the UI
|
|
150
|
-
error = `API Error: ${
|
|
151
|
-
|
|
213
|
+
error = `API Error: ${errorMessage}. Using sample data.`;
|
|
214
|
+
if (features.showToasts) {
|
|
215
|
+
apiToasts.error('Load node types', errorMessage);
|
|
216
|
+
}
|
|
152
217
|
|
|
153
218
|
// Fallback to sample data
|
|
154
219
|
nodes = sampleNodes;
|
|
@@ -283,27 +348,37 @@
|
|
|
283
348
|
|
|
284
349
|
/**
|
|
285
350
|
* Save workflow - exposed API function
|
|
351
|
+
*
|
|
352
|
+
* Integrates with event handlers for enterprise customization.
|
|
286
353
|
*/
|
|
287
354
|
async function saveWorkflow(): Promise<void> {
|
|
288
355
|
// Wait for any pending DOM updates before saving
|
|
289
356
|
await tick();
|
|
290
357
|
|
|
291
|
-
//
|
|
292
|
-
const
|
|
358
|
+
// Use current workflow from global store
|
|
359
|
+
const workflowToSave = $workflowStore;
|
|
360
|
+
|
|
361
|
+
if (!workflowToSave) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Call onBeforeSave if provided - allows cancellation
|
|
366
|
+
if (eventHandlers?.onBeforeSave) {
|
|
367
|
+
const shouldContinue = await eventHandlers.onBeforeSave(workflowToSave);
|
|
368
|
+
if (shouldContinue === false) {
|
|
369
|
+
// Save cancelled by event handler
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Show loading toast (if enabled)
|
|
375
|
+
const loadingToast = features.showToasts ? apiToasts.loading('Saving workflow') : null;
|
|
293
376
|
|
|
294
377
|
try {
|
|
295
378
|
// Import necessary modules
|
|
296
379
|
const { workflowApi } = await import('../services/api.js');
|
|
297
380
|
const { v4: uuidv4 } = await import('uuid');
|
|
298
381
|
|
|
299
|
-
// Use current workflow from global store
|
|
300
|
-
const workflowToSave = $workflowStore;
|
|
301
|
-
|
|
302
|
-
if (!workflowToSave) {
|
|
303
|
-
dismissToast(loadingToast);
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
382
|
// Determine the workflow ID
|
|
308
383
|
let workflowId: string;
|
|
309
384
|
if (workflowToSave.id) {
|
|
@@ -313,7 +388,7 @@
|
|
|
313
388
|
}
|
|
314
389
|
|
|
315
390
|
// Create workflow object for saving
|
|
316
|
-
const finalWorkflow = {
|
|
391
|
+
const finalWorkflow: Workflow = {
|
|
317
392
|
id: workflowId,
|
|
318
393
|
name: workflowToSave.name || 'Untitled Workflow',
|
|
319
394
|
description: workflowToSave.description || '',
|
|
@@ -342,14 +417,45 @@
|
|
|
342
417
|
});
|
|
343
418
|
}
|
|
344
419
|
|
|
420
|
+
// Mark as saved (clears dirty state)
|
|
421
|
+
markAsSaved();
|
|
422
|
+
|
|
345
423
|
// Dismiss loading toast and show success
|
|
346
|
-
|
|
347
|
-
|
|
424
|
+
if (loadingToast) {
|
|
425
|
+
dismissToast(loadingToast);
|
|
426
|
+
}
|
|
427
|
+
if (features.showToasts) {
|
|
428
|
+
apiToasts.success('Save workflow', 'Workflow saved successfully');
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Call onAfterSave if provided
|
|
432
|
+
if (eventHandlers?.onAfterSave) {
|
|
433
|
+
await eventHandlers.onAfterSave(savedWorkflow);
|
|
434
|
+
}
|
|
348
435
|
} catch (error) {
|
|
349
|
-
// Dismiss loading toast
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
436
|
+
// Dismiss loading toast
|
|
437
|
+
if (loadingToast) {
|
|
438
|
+
dismissToast(loadingToast);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const errorObj = error instanceof Error ? error : new Error('Unknown error occurred');
|
|
442
|
+
|
|
443
|
+
// Call onSaveError if provided
|
|
444
|
+
if (eventHandlers?.onSaveError && workflowToSave) {
|
|
445
|
+
await eventHandlers.onSaveError(errorObj, workflowToSave);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Check if parent wants to handle API errors
|
|
449
|
+
let suppressToast = false;
|
|
450
|
+
if (eventHandlers?.onApiError) {
|
|
451
|
+
suppressToast = eventHandlers.onApiError(errorObj, 'save') === true;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Show error toast if not suppressed
|
|
455
|
+
if (features.showToasts && !suppressToast) {
|
|
456
|
+
apiToasts.error('Save workflow', errorObj.message);
|
|
457
|
+
}
|
|
458
|
+
|
|
353
459
|
throw error; // Re-throw to allow calling code to handle if needed
|
|
354
460
|
}
|
|
355
461
|
}
|
|
@@ -398,9 +504,7 @@
|
|
|
398
504
|
|
|
399
505
|
// Expose save and export functions globally for external access
|
|
400
506
|
if (typeof window !== 'undefined') {
|
|
401
|
-
// @ts-expect-error - Adding to window for external access
|
|
402
507
|
window.flowdropSave = saveWorkflow;
|
|
403
|
-
// @ts-expect-error - Adding to window for external access
|
|
404
508
|
window.flowdropExport = exportWorkflow;
|
|
405
509
|
}
|
|
406
510
|
|
|
@@ -425,6 +529,11 @@
|
|
|
425
529
|
// Initialize the workflow store if we have an initial workflow
|
|
426
530
|
if (initialWorkflow) {
|
|
427
531
|
workflowActions.initialize(initialWorkflow);
|
|
532
|
+
|
|
533
|
+
// Emit onWorkflowLoad event
|
|
534
|
+
if (eventHandlers?.onWorkflowLoad) {
|
|
535
|
+
eventHandlers.onWorkflowLoad(initialWorkflow);
|
|
536
|
+
}
|
|
428
537
|
}
|
|
429
538
|
})();
|
|
430
539
|
|
|
@@ -635,7 +744,10 @@
|
|
|
635
744
|
<div class="flowdrop-config-sidebar__detail">
|
|
636
745
|
<span class="flowdrop-config-sidebar__detail-label">Node ID:</span>
|
|
637
746
|
<div class="flowdrop-config-sidebar__detail-value-with-copy">
|
|
638
|
-
<span
|
|
747
|
+
<span
|
|
748
|
+
class="flowdrop-config-sidebar__detail-value"
|
|
749
|
+
style="font-family: monospace;"
|
|
750
|
+
>
|
|
639
751
|
{selectedNodeForConfig().id}
|
|
640
752
|
</span>
|
|
641
753
|
<button
|
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
import type { Workflow } from '../types/index.js';
|
|
1
|
+
import type { NodeMetadata, Workflow } from '../types/index.js';
|
|
2
2
|
import type { EndpointConfig } from '../config/endpoints.js';
|
|
3
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
4
|
+
import type { FlowDropEventHandlers, FlowDropFeatures } from '../types/events.js';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration props for runtime customization
|
|
7
|
+
*/
|
|
3
8
|
interface Props {
|
|
9
|
+
/** Initial workflow to load */
|
|
4
10
|
workflow?: Workflow;
|
|
11
|
+
/** Pre-loaded node types (if provided, skips API fetch) */
|
|
12
|
+
nodes?: NodeMetadata[];
|
|
13
|
+
/** Editor height */
|
|
5
14
|
height?: string | number;
|
|
15
|
+
/** Editor width */
|
|
6
16
|
width?: string | number;
|
|
17
|
+
/** Show the navbar */
|
|
7
18
|
showNavbar?: boolean;
|
|
19
|
+
/** Disable the node sidebar */
|
|
8
20
|
disableSidebar?: boolean;
|
|
21
|
+
/** Lock the workflow (prevent changes) */
|
|
9
22
|
lockWorkflow?: boolean;
|
|
23
|
+
/** Read-only mode */
|
|
10
24
|
readOnly?: boolean;
|
|
25
|
+
/** Node execution statuses */
|
|
11
26
|
nodeStatuses?: Record<string, 'pending' | 'running' | 'completed' | 'error'>;
|
|
27
|
+
/** Pipeline ID for fetching node execution info */
|
|
12
28
|
pipelineId?: string;
|
|
29
|
+
/** Custom navbar title */
|
|
13
30
|
navbarTitle?: string;
|
|
31
|
+
/** Custom navbar actions */
|
|
14
32
|
navbarActions?: Array<{
|
|
15
33
|
label: string;
|
|
16
34
|
href: string;
|
|
@@ -18,8 +36,16 @@ interface Props {
|
|
|
18
36
|
variant?: 'primary' | 'secondary' | 'outline';
|
|
19
37
|
onclick?: (event: Event) => void;
|
|
20
38
|
}>;
|
|
39
|
+
/** API base URL */
|
|
21
40
|
apiBaseUrl?: string;
|
|
41
|
+
/** Endpoint configuration */
|
|
22
42
|
endpointConfig?: EndpointConfig;
|
|
43
|
+
/** Authentication provider */
|
|
44
|
+
authProvider?: AuthProvider;
|
|
45
|
+
/** Event handlers */
|
|
46
|
+
eventHandlers?: FlowDropEventHandlers;
|
|
47
|
+
/** Feature configuration */
|
|
48
|
+
features?: FlowDropFeatures;
|
|
23
49
|
}
|
|
24
50
|
declare const App: import("svelte").Component<Props, {}, "">;
|
|
25
51
|
type App = ReturnType<typeof App>;
|
package/dist/data/samples.js
CHANGED
|
@@ -444,8 +444,8 @@ export const sampleNodes = [
|
|
|
444
444
|
type: 'string',
|
|
445
445
|
title: 'Model',
|
|
446
446
|
description: 'OpenAI model to use',
|
|
447
|
-
default: 'gpt-
|
|
448
|
-
enum: ['gpt-
|
|
447
|
+
default: 'gpt-4o-mini',
|
|
448
|
+
enum: ['gpt-4o-mini', 'gpt-5-chat-latest', 'gpt-4.1']
|
|
449
449
|
},
|
|
450
450
|
temperature: {
|
|
451
451
|
type: 'number',
|
|
@@ -2107,8 +2107,8 @@ export const sampleNodes = [
|
|
|
2107
2107
|
type: 'string',
|
|
2108
2108
|
title: 'Model',
|
|
2109
2109
|
description: 'Chat model to use',
|
|
2110
|
-
default: 'gpt-
|
|
2111
|
-
enum: ['gpt-
|
|
2110
|
+
default: 'gpt-4o-mini',
|
|
2111
|
+
enum: ['gpt-4o-mini', 'gpt-5-chat-latest', 'claude-3-sonnet']
|
|
2112
2112
|
},
|
|
2113
2113
|
temperature: {
|
|
2114
2114
|
type: 'number',
|
|
@@ -2601,8 +2601,8 @@ export const sampleNodes = [
|
|
|
2601
2601
|
type: 'string',
|
|
2602
2602
|
title: 'AI Model',
|
|
2603
2603
|
description: 'AI model to use for content analysis',
|
|
2604
|
-
default: 'gpt-
|
|
2605
|
-
enum: ['gpt-
|
|
2604
|
+
default: 'gpt-5-chat-latest',
|
|
2605
|
+
enum: ['gpt-4o-mini', 'gpt-5-chat-latest', 'claude-3-sonnet', 'claude-3-haiku']
|
|
2606
2606
|
},
|
|
2607
2607
|
analysisType: {
|
|
2608
2608
|
type: 'string',
|
|
@@ -2725,8 +2725,8 @@ export const sampleNodes = [
|
|
|
2725
2725
|
type: 'string',
|
|
2726
2726
|
title: 'AI Model',
|
|
2727
2727
|
description: 'AI model to use for content editing',
|
|
2728
|
-
default: 'gpt-
|
|
2729
|
-
enum: ['gpt-
|
|
2728
|
+
default: 'gpt-5-chat-latest',
|
|
2729
|
+
enum: ['gpt-4o-mini', 'gpt-5-chat-latest', 'claude-3-sonnet', 'claude-3-haiku']
|
|
2730
2730
|
},
|
|
2731
2731
|
editingStyle: {
|
|
2732
2732
|
type: 'string',
|
|
@@ -3184,7 +3184,7 @@ export const sampleWorkflow = {
|
|
|
3184
3184
|
data: {
|
|
3185
3185
|
label: 'OpenAI',
|
|
3186
3186
|
config: {
|
|
3187
|
-
model: 'gpt-
|
|
3187
|
+
model: 'gpt-4o-mini',
|
|
3188
3188
|
temperature: 0.7,
|
|
3189
3189
|
maxTokens: 1000
|
|
3190
3190
|
},
|
|
@@ -14,7 +14,7 @@ function createSimpleWorkflow() {
|
|
|
14
14
|
placeholder: 'Enter your message'
|
|
15
15
|
});
|
|
16
16
|
const modelNode = adapter.addNode(workflow, 'openai', { x: 300, y: 100 }, {
|
|
17
|
-
model: 'gpt-
|
|
17
|
+
model: 'gpt-4o-mini',
|
|
18
18
|
temperature: 0.7
|
|
19
19
|
});
|
|
20
20
|
const outputNode = adapter.addNode(workflow, 'text-output', { x: 500, y: 100 });
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* FlowDrop - Visual Workflow Editor Library
|
|
3
3
|
* A Svelte 5 component library built on @xyflow/svelte for creating node-based workflow editors
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
6
|
-
export type { NodeCategory, NodeDataType, NodePort, NodeMetadata, NodeConfig, WorkflowNode, WorkflowEdge, Workflow, ApiResponse, NodesResponse, WorkflowResponse, WorkflowsResponse, ExecutionStatus, ExecutionResult, FlowDropConfig, WorkflowEvents } from
|
|
7
|
-
export type { WorkflowEditorConfig, EditorFeatures, UIConfig, APIConfig, ExecutionConfig, StorageConfig, NodeType, WorkflowData, ExecutionResult as EditorExecutionResult, EditorState } from
|
|
5
|
+
import "./styles/base.css";
|
|
6
|
+
export type { NodeCategory, NodeDataType, NodePort, NodeMetadata, NodeConfig, WorkflowNode, WorkflowEdge, Workflow, ApiResponse, NodesResponse, WorkflowResponse, WorkflowsResponse, ExecutionStatus, ExecutionResult, FlowDropConfig, WorkflowEvents } from "./types/index.js";
|
|
7
|
+
export type { WorkflowEditorConfig, EditorFeatures, UIConfig, APIConfig, ExecutionConfig, StorageConfig, NodeType, WorkflowData, ExecutionResult as EditorExecutionResult, EditorState } from "./types/config.js";
|
|
8
|
+
export type { AuthProvider, StaticAuthConfig, CallbackAuthConfig } from "./types/auth.js";
|
|
9
|
+
export { StaticAuthProvider, CallbackAuthProvider, NoAuthProvider, createAuthProviderFromLegacyConfig } from "./types/auth.js";
|
|
10
|
+
export type { WorkflowChangeType, FlowDropEventHandlers, FlowDropFeatures } from "./types/events.js";
|
|
11
|
+
export { DEFAULT_FEATURES, mergeFeatures } from "./types/events.js";
|
|
8
12
|
export { FlowDropApiClient } from './api/client.js';
|
|
9
13
|
export { EnhancedFlowDropApiClient } from './api/enhanced-client.js';
|
|
10
14
|
export { default as WorkflowEditor } from './components/WorkflowEditor.svelte';
|
|
@@ -45,9 +49,10 @@ export type { ToastType, ToastOptions } from './services/toastService.js';
|
|
|
45
49
|
export { NodeExecutionService, nodeExecutionService } from './services/nodeExecutionService.js';
|
|
46
50
|
export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from './services/workflowStorage.js';
|
|
47
51
|
export { globalSaveWorkflow, globalExportWorkflow, initializeGlobalSave } from './services/globalSave.js';
|
|
48
|
-
export { fetchPortConfig, validatePortConfig } from
|
|
52
|
+
export { fetchPortConfig, validatePortConfig } from "./services/portConfigApi.js";
|
|
53
|
+
export { getDraftStorageKey, saveDraft, loadDraft, deleteDraft, hasDraft, getDraftMetadata, DraftAutoSaveManager } from "./services/draftStorage.js";
|
|
49
54
|
export { EdgeStylingHelper, NodeOperationsHelper, WorkflowOperationsHelper, ConfigurationHelper } from './helpers/workflowEditorHelper.js';
|
|
50
|
-
export { workflowStore, workflowActions, workflowId, workflowName, workflowNodes, workflowEdges, workflowMetadata, workflowChanged, workflowValidation, workflowMetadataChanged } from
|
|
55
|
+
export { workflowStore, workflowActions, workflowId, workflowName, workflowNodes, workflowEdges, workflowMetadata, workflowChanged, workflowValidation, workflowMetadataChanged, isDirtyStore, isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange } from "./stores/workflowStore.js";
|
|
51
56
|
export * from './config/endpoints.js';
|
|
52
57
|
export { defaultApiConfig, getEndpointUrl } from './config/apiConfig.js';
|
|
53
58
|
export type { ApiConfig } from './config/apiConfig.js';
|
|
@@ -55,4 +60,6 @@ export { DEFAULT_PORT_CONFIG } from './config/defaultPortConfig.js';
|
|
|
55
60
|
export * from './config/runtimeConfig.js';
|
|
56
61
|
export * from './adapters/WorkflowAdapter.js';
|
|
57
62
|
export * from './clients/ApiClient.js';
|
|
58
|
-
export { mountWorkflowEditor, unmountWorkflowEditor, mountFlowDropApp, unmountFlowDropApp } from
|
|
63
|
+
export { mountWorkflowEditor, unmountWorkflowEditor, mountFlowDropApp, unmountFlowDropApp } from "./svelte-app.js";
|
|
64
|
+
export type { FlowDropMountOptions, MountedFlowDropApp, NavbarAction } from "./svelte-app.js";
|
|
65
|
+
export { ApiError } from "./api/enhanced-client.js";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* A Svelte 5 component library built on @xyflow/svelte for creating node-based workflow editors
|
|
4
4
|
*/
|
|
5
5
|
// Import CSS to ensure styles are included in the library build
|
|
6
|
-
import
|
|
6
|
+
import "./styles/base.css";
|
|
7
|
+
export { StaticAuthProvider, CallbackAuthProvider, NoAuthProvider, createAuthProviderFromLegacyConfig } from "./types/auth.js";
|
|
8
|
+
export { DEFAULT_FEATURES, mergeFeatures } from "./types/events.js";
|
|
7
9
|
// Export API clients
|
|
8
10
|
export { FlowDropApiClient } from './api/client.js';
|
|
9
11
|
export { EnhancedFlowDropApiClient } from './api/enhanced-client.js';
|
|
@@ -47,11 +49,15 @@ export { showSuccess, showError, showWarning, showInfo, showLoading, dismissToas
|
|
|
47
49
|
export { NodeExecutionService, nodeExecutionService } from './services/nodeExecutionService.js';
|
|
48
50
|
export { saveWorkflow, updateWorkflow, getWorkflow, getWorkflows, deleteWorkflow, getWorkflowCount, initializeSampleWorkflows } from './services/workflowStorage.js';
|
|
49
51
|
export { globalSaveWorkflow, globalExportWorkflow, initializeGlobalSave } from './services/globalSave.js';
|
|
50
|
-
export { fetchPortConfig, validatePortConfig } from
|
|
52
|
+
export { fetchPortConfig, validatePortConfig } from "./services/portConfigApi.js";
|
|
53
|
+
// Export draft storage service
|
|
54
|
+
export { getDraftStorageKey, saveDraft, loadDraft, deleteDraft, hasDraft, getDraftMetadata, DraftAutoSaveManager } from "./services/draftStorage.js";
|
|
51
55
|
// Export helpers
|
|
52
56
|
export { EdgeStylingHelper, NodeOperationsHelper, WorkflowOperationsHelper, ConfigurationHelper } from './helpers/workflowEditorHelper.js';
|
|
53
57
|
// Export stores
|
|
54
|
-
export { workflowStore, workflowActions, workflowId, workflowName, workflowNodes, workflowEdges, workflowMetadata, workflowChanged, workflowValidation, workflowMetadataChanged
|
|
58
|
+
export { workflowStore, workflowActions, workflowId, workflowName, workflowNodes, workflowEdges, workflowMetadata, workflowChanged, workflowValidation, workflowMetadataChanged,
|
|
59
|
+
// Dirty state tracking
|
|
60
|
+
isDirtyStore, isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange } from "./stores/workflowStore.js";
|
|
55
61
|
// Export endpoint configuration
|
|
56
62
|
export * from './config/endpoints.js';
|
|
57
63
|
export { defaultApiConfig, getEndpointUrl } from './config/apiConfig.js';
|
|
@@ -62,4 +68,6 @@ export * from './adapters/WorkflowAdapter.js';
|
|
|
62
68
|
// Export API client
|
|
63
69
|
export * from './clients/ApiClient.js';
|
|
64
70
|
// Export Svelte app wrapper for framework integration
|
|
65
|
-
export { mountWorkflowEditor, unmountWorkflowEditor, mountFlowDropApp, unmountFlowDropApp } from
|
|
71
|
+
export { mountWorkflowEditor, unmountWorkflowEditor, mountFlowDropApp, unmountFlowDropApp } from "./svelte-app.js";
|
|
72
|
+
// Export API error class
|
|
73
|
+
export { ApiError } from "./api/enhanced-client.js";
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draft Storage Service for FlowDrop
|
|
3
|
+
*
|
|
4
|
+
* Handles saving and loading workflow drafts to/from localStorage.
|
|
5
|
+
* Provides interval-based auto-save functionality.
|
|
6
|
+
*
|
|
7
|
+
* @module services/draftStorage
|
|
8
|
+
*/
|
|
9
|
+
import type { Workflow } from "../types/index.js";
|
|
10
|
+
/**
|
|
11
|
+
* Draft metadata stored alongside the workflow
|
|
12
|
+
*/
|
|
13
|
+
interface DraftMetadata {
|
|
14
|
+
/** Timestamp when the draft was saved */
|
|
15
|
+
savedAt: string;
|
|
16
|
+
/** Workflow ID (if available) */
|
|
17
|
+
workflowId?: string;
|
|
18
|
+
/** Workflow name */
|
|
19
|
+
workflowName?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Complete draft data stored in localStorage
|
|
23
|
+
*/
|
|
24
|
+
interface StoredDraft {
|
|
25
|
+
/** The workflow data */
|
|
26
|
+
workflow: Workflow;
|
|
27
|
+
/** Draft metadata */
|
|
28
|
+
metadata: DraftMetadata;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a storage key for a workflow
|
|
32
|
+
*
|
|
33
|
+
* If a custom key is provided, use it directly.
|
|
34
|
+
* Otherwise, generate based on workflow ID or use "new" for unsaved workflows.
|
|
35
|
+
*
|
|
36
|
+
* @param workflowId - The workflow ID (optional)
|
|
37
|
+
* @param customKey - Custom storage key provided by enterprise (optional)
|
|
38
|
+
* @returns The storage key to use
|
|
39
|
+
*/
|
|
40
|
+
export declare function getDraftStorageKey(workflowId?: string, customKey?: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Save a workflow draft to localStorage
|
|
43
|
+
*
|
|
44
|
+
* @param workflow - The workflow to save
|
|
45
|
+
* @param storageKey - The storage key to use
|
|
46
|
+
* @returns true if saved successfully, false otherwise
|
|
47
|
+
*/
|
|
48
|
+
export declare function saveDraft(workflow: Workflow, storageKey: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Load a workflow draft from localStorage
|
|
51
|
+
*
|
|
52
|
+
* @param storageKey - The storage key to load from
|
|
53
|
+
* @returns The stored draft, or null if not found
|
|
54
|
+
*/
|
|
55
|
+
export declare function loadDraft(storageKey: string): StoredDraft | null;
|
|
56
|
+
/**
|
|
57
|
+
* Delete a workflow draft from localStorage
|
|
58
|
+
*
|
|
59
|
+
* @param storageKey - The storage key to delete
|
|
60
|
+
*/
|
|
61
|
+
export declare function deleteDraft(storageKey: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Check if a draft exists for a given storage key
|
|
64
|
+
*
|
|
65
|
+
* @param storageKey - The storage key to check
|
|
66
|
+
* @returns true if a draft exists
|
|
67
|
+
*/
|
|
68
|
+
export declare function hasDraft(storageKey: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Get draft metadata without loading the full workflow
|
|
71
|
+
*
|
|
72
|
+
* Useful for displaying draft information without parsing the entire workflow.
|
|
73
|
+
*
|
|
74
|
+
* @param storageKey - The storage key to check
|
|
75
|
+
* @returns Draft metadata, or null if not found
|
|
76
|
+
*/
|
|
77
|
+
export declare function getDraftMetadata(storageKey: string): DraftMetadata | null;
|
|
78
|
+
/**
|
|
79
|
+
* Draft auto-save manager
|
|
80
|
+
*
|
|
81
|
+
* Handles interval-based auto-saving of workflow drafts.
|
|
82
|
+
* Should be instantiated per FlowDrop instance.
|
|
83
|
+
*/
|
|
84
|
+
export declare class DraftAutoSaveManager {
|
|
85
|
+
/** Interval timer ID */
|
|
86
|
+
private intervalId;
|
|
87
|
+
/** Storage key for drafts */
|
|
88
|
+
private storageKey;
|
|
89
|
+
/** Auto-save interval in milliseconds */
|
|
90
|
+
private interval;
|
|
91
|
+
/** Whether auto-save is enabled */
|
|
92
|
+
private enabled;
|
|
93
|
+
/** Function to get current workflow */
|
|
94
|
+
private getWorkflow;
|
|
95
|
+
/** Function to check if workflow is dirty */
|
|
96
|
+
private isDirty;
|
|
97
|
+
/** Last saved workflow hash (for change detection) */
|
|
98
|
+
private lastSavedHash;
|
|
99
|
+
/**
|
|
100
|
+
* Create a new DraftAutoSaveManager
|
|
101
|
+
*
|
|
102
|
+
* @param options - Configuration options
|
|
103
|
+
*/
|
|
104
|
+
constructor(options: {
|
|
105
|
+
storageKey: string;
|
|
106
|
+
interval: number;
|
|
107
|
+
enabled: boolean;
|
|
108
|
+
getWorkflow: () => Workflow | null;
|
|
109
|
+
isDirty: () => boolean;
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* Start auto-save interval
|
|
113
|
+
*
|
|
114
|
+
* Will save drafts at the configured interval if there are unsaved changes.
|
|
115
|
+
*/
|
|
116
|
+
start(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Stop auto-save interval
|
|
119
|
+
*/
|
|
120
|
+
stop(): void;
|
|
121
|
+
/**
|
|
122
|
+
* Save draft if there are unsaved changes
|
|
123
|
+
*
|
|
124
|
+
* @returns true if a draft was saved
|
|
125
|
+
*/
|
|
126
|
+
saveIfDirty(): boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Force save the current workflow as a draft
|
|
129
|
+
*
|
|
130
|
+
* Saves regardless of dirty state.
|
|
131
|
+
*
|
|
132
|
+
* @returns true if saved successfully
|
|
133
|
+
*/
|
|
134
|
+
forceSave(): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Clear the draft from storage
|
|
137
|
+
*/
|
|
138
|
+
clearDraft(): void;
|
|
139
|
+
/**
|
|
140
|
+
* Mark the current state as saved
|
|
141
|
+
*
|
|
142
|
+
* Updates the hash so the next saveIfDirty won't save unless there are new changes.
|
|
143
|
+
*/
|
|
144
|
+
markAsSaved(): void;
|
|
145
|
+
/**
|
|
146
|
+
* Update the storage key
|
|
147
|
+
*
|
|
148
|
+
* Useful when the workflow ID changes (e.g., after first save).
|
|
149
|
+
*
|
|
150
|
+
* @param newKey - The new storage key
|
|
151
|
+
*/
|
|
152
|
+
updateStorageKey(newKey: string): void;
|
|
153
|
+
/**
|
|
154
|
+
* Simple hash function for change detection
|
|
155
|
+
*
|
|
156
|
+
* Not cryptographically secure, just for detecting changes.
|
|
157
|
+
*
|
|
158
|
+
* @param workflow - The workflow to hash
|
|
159
|
+
* @returns A simple hash string
|
|
160
|
+
*/
|
|
161
|
+
private hashWorkflow;
|
|
162
|
+
/**
|
|
163
|
+
* Check if auto-save is currently running
|
|
164
|
+
*/
|
|
165
|
+
isRunning(): boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Get the current storage key
|
|
168
|
+
*/
|
|
169
|
+
getStorageKey(): string;
|
|
170
|
+
}
|
|
171
|
+
export {};
|