@d34dman/flowdrop 0.0.42 → 0.0.44
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 +8 -8
- package/dist/api/enhanced-client.d.ts +3 -1
- package/dist/api/enhanced-client.js +35 -5
- package/dist/components/App.svelte +68 -34
- package/dist/components/ConfigForm.svelte +169 -142
- package/dist/components/ConfigForm.svelte.d.ts +4 -2
- package/dist/components/ConfigPanel.svelte +42 -15
- package/dist/components/LogsSidebar.svelte +20 -19
- package/dist/components/Navbar.svelte +150 -80
- package/dist/components/Navbar.svelte.d.ts +8 -0
- package/dist/components/NodeSidebar.svelte +330 -217
- package/dist/components/PipelineStatus.svelte +6 -1
- package/dist/components/ReadOnlyDetails.svelte +14 -14
- package/dist/components/SchemaForm.svelte +49 -30
- package/dist/components/SchemaForm.svelte.d.ts +11 -1
- package/dist/components/SettingsModal.svelte +279 -0
- package/dist/components/SettingsModal.svelte.d.ts +23 -0
- package/dist/components/SettingsPanel.svelte +615 -0
- package/dist/components/SettingsPanel.svelte.d.ts +21 -0
- package/dist/components/ThemeToggle.svelte +186 -0
- package/dist/components/ThemeToggle.svelte.d.ts +14 -0
- package/dist/components/WorkflowEditor.svelte +110 -36
- package/dist/components/form/FormArray.svelte +81 -81
- package/dist/components/form/FormAutocomplete.svelte +1014 -0
- package/dist/components/form/FormAutocomplete.svelte.d.ts +25 -0
- package/dist/components/form/FormCheckboxGroup.svelte +16 -16
- package/dist/components/form/FormCodeEditor.svelte +26 -26
- package/dist/components/form/FormField.svelte +52 -21
- package/dist/components/form/FormFieldLight.svelte +19 -19
- package/dist/components/form/FormFieldWrapper.svelte +4 -4
- package/dist/components/form/FormMarkdownEditor.svelte +124 -57
- package/dist/components/form/FormNumberField.svelte +13 -13
- package/dist/components/form/FormRangeField.svelte +16 -16
- package/dist/components/form/FormSelect.svelte +15 -15
- package/dist/components/form/FormTemplateEditor.svelte +34 -34
- package/dist/components/form/FormTextField.svelte +13 -13
- package/dist/components/form/FormTextarea.svelte +13 -13
- package/dist/components/form/FormToggle.svelte +8 -8
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.js +1 -0
- package/dist/components/form/types.d.ts +133 -8
- package/dist/components/form/types.js +50 -1
- package/dist/components/interrupt/ChoicePrompt.svelte +45 -38
- package/dist/components/interrupt/ConfirmationPrompt.svelte +35 -35
- package/dist/components/interrupt/FormPrompt.svelte +27 -20
- package/dist/components/interrupt/InterruptBubble.svelte +50 -50
- package/dist/components/interrupt/TextInputPrompt.svelte +39 -32
- package/dist/components/layouts/MainLayout.svelte +233 -34
- package/dist/components/layouts/MainLayout.svelte.d.ts +12 -0
- package/dist/components/nodes/GatewayNode.svelte +102 -73
- package/dist/components/nodes/IdeaNode.svelte +53 -52
- package/dist/components/nodes/NotesNode.svelte +120 -88
- package/dist/components/nodes/SimpleNode.svelte +67 -47
- package/dist/components/nodes/SquareNode.svelte +86 -49
- package/dist/components/nodes/TerminalNode.svelte +122 -72
- package/dist/components/nodes/ToolNode.svelte +96 -65
- package/dist/components/nodes/WorkflowNode.svelte +91 -67
- package/dist/components/playground/ChatPanel.svelte +76 -76
- package/dist/components/playground/ExecutionLogs.svelte +71 -69
- package/dist/components/playground/InputCollector.svelte +59 -59
- package/dist/components/playground/MessageBubble.svelte +111 -112
- package/dist/components/playground/Playground.svelte +184 -138
- package/dist/components/playground/PlaygroundModal.svelte +18 -19
- package/dist/components/playground/SessionManager.svelte +68 -67
- package/dist/config/defaultPortConfig.js +22 -22
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +1 -0
- package/dist/form/fieldRegistry.d.ts +17 -1
- package/dist/form/fieldRegistry.js +18 -2
- package/dist/form/index.d.ts +20 -2
- package/dist/form/index.js +19 -1
- package/dist/helpers/workflowEditorHelper.js +23 -11
- package/dist/index.d.ts +5 -0
- package/dist/index.js +13 -0
- package/dist/services/autoSaveService.d.ts +112 -0
- package/dist/services/autoSaveService.js +223 -0
- package/dist/services/settingsService.d.ts +92 -0
- package/dist/services/settingsService.js +202 -0
- package/dist/services/toastService.d.ts +9 -0
- package/dist/services/toastService.js +30 -1
- package/dist/stores/settingsStore.d.ts +128 -0
- package/dist/stores/settingsStore.js +488 -0
- package/dist/stores/themeStore.d.ts +68 -0
- package/dist/stores/themeStore.js +215 -0
- package/dist/styles/base.css +298 -621
- package/dist/styles/toast.css +33 -0
- package/dist/styles/tokens.css +366 -0
- package/dist/types/index.d.ts +78 -0
- package/dist/types/index.js +2 -0
- package/dist/types/interrupt.d.ts +2 -0
- package/dist/types/interrupt.js +8 -2
- package/dist/types/playground.d.ts +12 -0
- package/dist/types/settings.d.ts +185 -0
- package/dist/types/settings.js +101 -0
- package/dist/utils/colors.d.ts +100 -7
- package/dist/utils/colors.js +228 -67
- package/package.json +3 -3
|
@@ -153,20 +153,32 @@ export class EdgeStylingHelper {
|
|
|
153
153
|
: null;
|
|
154
154
|
// Determine edge category (loopback takes precedence)
|
|
155
155
|
const edgeCategory = this.getEdgeCategoryWithLoopback(edge, sourcePortDataType);
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
// Detect current theme for marker colors
|
|
157
|
+
// Marker colors are baked in at creation time, so we check the theme here
|
|
158
|
+
const isDarkMode = typeof document !== 'undefined' &&
|
|
159
|
+
document.documentElement.getAttribute('data-theme') === 'dark';
|
|
160
|
+
// Edge color constants for marker arrows - matched to CSS token values
|
|
161
|
+
// These match the --fd-edge-* tokens in tokens.css for consistency
|
|
162
|
+
const EDGE_COLORS = isDarkMode
|
|
163
|
+
? {
|
|
164
|
+
trigger: '#eaeaef', // --_gray-3 (light for dark mode visibility)
|
|
165
|
+
tool: '#fbbf24', // Brighter amber for dark mode
|
|
166
|
+
loopback: '#a3a3ad', // --_gray-5
|
|
167
|
+
data: '#a3a3ad' // --_gray-5
|
|
168
|
+
}
|
|
169
|
+
: {
|
|
170
|
+
trigger: '#18181c', // --_gray-9 (dark for light mode)
|
|
171
|
+
tool: '#f59e0b', // --_amber-2
|
|
172
|
+
loopback: '#71717b', // --_gray-6
|
|
173
|
+
data: '#a3a3ad' // --_gray-5
|
|
174
|
+
};
|
|
163
175
|
// Apply styling based on edge category
|
|
164
176
|
// CSS classes handle styling via tokens; inline styles are fallback
|
|
165
177
|
switch (edgeCategory) {
|
|
166
178
|
case 'loopback':
|
|
167
179
|
// Loopback edges: dashed gray line for loop iteration
|
|
168
180
|
edge.style =
|
|
169
|
-
'stroke: var(--
|
|
181
|
+
'stroke: var(--fd-edge-loopback); stroke-dasharray: var(--fd-edge-loopback-dasharray); stroke-width: var(--fd-edge-loopback-width); opacity: var(--fd-edge-loopback-opacity);';
|
|
170
182
|
edge.class = 'flowdrop--edge--loopback';
|
|
171
183
|
edge.markerEnd = {
|
|
172
184
|
type: MarkerType.ArrowClosed,
|
|
@@ -178,7 +190,7 @@ export class EdgeStylingHelper {
|
|
|
178
190
|
case 'trigger':
|
|
179
191
|
// Trigger edges: solid dark line for control flow
|
|
180
192
|
edge.style =
|
|
181
|
-
'stroke: var(--
|
|
193
|
+
'stroke: var(--fd-edge-trigger); stroke-width: var(--fd-edge-trigger-width);';
|
|
182
194
|
edge.class = 'flowdrop--edge--trigger';
|
|
183
195
|
edge.markerEnd = {
|
|
184
196
|
type: MarkerType.ArrowClosed,
|
|
@@ -189,7 +201,7 @@ export class EdgeStylingHelper {
|
|
|
189
201
|
break;
|
|
190
202
|
case 'tool':
|
|
191
203
|
// Tool edges: dashed amber line
|
|
192
|
-
edge.style = 'stroke: var(--
|
|
204
|
+
edge.style = 'stroke: var(--fd-edge-tool); stroke-dasharray: 5 3;';
|
|
193
205
|
edge.class = 'flowdrop--edge--tool';
|
|
194
206
|
edge.markerEnd = {
|
|
195
207
|
type: MarkerType.ArrowClosed,
|
|
@@ -201,7 +213,7 @@ export class EdgeStylingHelper {
|
|
|
201
213
|
case 'data':
|
|
202
214
|
default:
|
|
203
215
|
// Data edges: normal gray line
|
|
204
|
-
edge.style = 'stroke: var(--
|
|
216
|
+
edge.style = 'stroke: var(--fd-edge-data);';
|
|
205
217
|
edge.class = 'flowdrop--edge--data';
|
|
206
218
|
edge.markerEnd = {
|
|
207
219
|
type: MarkerType.ArrowClosed,
|
package/dist/index.d.ts
CHANGED
|
@@ -34,3 +34,8 @@ export * from './form/index.js';
|
|
|
34
34
|
export * from './display/index.js';
|
|
35
35
|
export * from './playground/index.js';
|
|
36
36
|
export * from './editor/index.js';
|
|
37
|
+
export { default as ThemeToggle } from './components/ThemeToggle.svelte';
|
|
38
|
+
export { default as SettingsPanel } from './components/SettingsPanel.svelte';
|
|
39
|
+
export { default as SettingsModal } from './components/SettingsModal.svelte';
|
|
40
|
+
export { settingsStore, themeSettings, editorSettings, uiSettings, behaviorSettings, apiSettings, syncStatusStore, theme, resolvedTheme, updateSettings, resetSettings, getSettings, setTheme, toggleTheme, cycleTheme, initializeTheme, initializeSettings, setSettingsService, syncSettingsToApi, loadSettingsFromApi, onSettingsChange } from './stores/settingsStore.js';
|
|
41
|
+
export { settingsApi, SettingsService, createSettingsService, setSettingsEndpointConfig, getSettingsEndpointConfig } from './services/settingsService.js';
|
package/dist/index.js
CHANGED
|
@@ -55,3 +55,16 @@ export * from './playground/index.js';
|
|
|
55
55
|
// Editor Exports (includes @xyflow/svelte and auto-registers builtin nodes)
|
|
56
56
|
// ============================================================================
|
|
57
57
|
export * from './editor/index.js';
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Theme Component Export
|
|
60
|
+
// ============================================================================
|
|
61
|
+
export { default as ThemeToggle } from './components/ThemeToggle.svelte';
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Settings Component & Store Exports
|
|
64
|
+
// ============================================================================
|
|
65
|
+
export { default as SettingsPanel } from './components/SettingsPanel.svelte';
|
|
66
|
+
export { default as SettingsModal } from './components/SettingsModal.svelte';
|
|
67
|
+
// Settings store exports
|
|
68
|
+
export { settingsStore, themeSettings, editorSettings, uiSettings, behaviorSettings, apiSettings, syncStatusStore, theme, resolvedTheme, updateSettings, resetSettings, getSettings, setTheme, toggleTheme, cycleTheme, initializeTheme, initializeSettings, setSettingsService, syncSettingsToApi, loadSettingsFromApi, onSettingsChange } from './stores/settingsStore.js';
|
|
69
|
+
// Settings service exports
|
|
70
|
+
export { settingsApi, SettingsService, createSettingsService, setSettingsEndpointConfig, getSettingsEndpointConfig } from './services/settingsService.js';
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-save Service for FlowDrop
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic saving of workflows based on user settings.
|
|
5
|
+
* Uses behaviorSettings for auto-save configuration.
|
|
6
|
+
*
|
|
7
|
+
* @module services/autoSaveService
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Auto-save configuration options
|
|
11
|
+
*/
|
|
12
|
+
interface AutoSaveOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Callback function to save the workflow
|
|
15
|
+
* Should return a promise that resolves when save is complete
|
|
16
|
+
*/
|
|
17
|
+
onSave: () => Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Optional callback for save errors
|
|
20
|
+
*/
|
|
21
|
+
onError?: (error: Error) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Optional callback for successful saves
|
|
24
|
+
*/
|
|
25
|
+
onSuccess?: () => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Initialize auto-save functionality based on user settings
|
|
29
|
+
*
|
|
30
|
+
* Creates an interval-based auto-save mechanism that:
|
|
31
|
+
* - Subscribes to behaviorSettings for auto-save configuration
|
|
32
|
+
* - Monitors the isDirtyStore to check for unsaved changes
|
|
33
|
+
* - Calls the provided save callback when dirty and auto-save is enabled
|
|
34
|
+
*
|
|
35
|
+
* @param options - Auto-save configuration options
|
|
36
|
+
* @returns Cleanup function to stop auto-save and unsubscribe from stores
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // In App.svelte onMount
|
|
41
|
+
* const cleanupAutoSave = initAutoSave({
|
|
42
|
+
* onSave: async () => {
|
|
43
|
+
* await saveWorkflow();
|
|
44
|
+
* },
|
|
45
|
+
* onError: (error) => {
|
|
46
|
+
* console.error("Auto-save failed:", error);
|
|
47
|
+
* },
|
|
48
|
+
* onSuccess: () => {
|
|
49
|
+
* console.log("Auto-saved workflow");
|
|
50
|
+
* }
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* // In onDestroy
|
|
54
|
+
* cleanupAutoSave();
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function initAutoSave(options: AutoSaveOptions): () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Create an auto-save manager with more control
|
|
60
|
+
*
|
|
61
|
+
* This is a class-based alternative to initAutoSave for cases where
|
|
62
|
+
* you need more fine-grained control over the auto-save behavior.
|
|
63
|
+
*/
|
|
64
|
+
export declare class AutoSaveManager {
|
|
65
|
+
private intervalId;
|
|
66
|
+
private isSaving;
|
|
67
|
+
private settingsUnsubscriber;
|
|
68
|
+
private onSave;
|
|
69
|
+
private onError?;
|
|
70
|
+
private onSuccess?;
|
|
71
|
+
/**
|
|
72
|
+
* Create a new AutoSaveManager
|
|
73
|
+
*
|
|
74
|
+
* @param options - Auto-save configuration options
|
|
75
|
+
*/
|
|
76
|
+
constructor(options: AutoSaveOptions);
|
|
77
|
+
/**
|
|
78
|
+
* Start the auto-save manager
|
|
79
|
+
*
|
|
80
|
+
* Subscribes to settings changes and starts the auto-save interval.
|
|
81
|
+
*/
|
|
82
|
+
start(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Stop the auto-save manager
|
|
85
|
+
*
|
|
86
|
+
* Clears the interval and unsubscribes from settings.
|
|
87
|
+
*/
|
|
88
|
+
stop(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Force an immediate save (if dirty)
|
|
91
|
+
*
|
|
92
|
+
* @returns Promise that resolves when save is complete
|
|
93
|
+
*/
|
|
94
|
+
saveNow(): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Check if auto-save is currently enabled
|
|
97
|
+
*/
|
|
98
|
+
isEnabled(): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Check if auto-save is currently running
|
|
101
|
+
*/
|
|
102
|
+
isRunning(): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Update the interval based on current settings
|
|
105
|
+
*/
|
|
106
|
+
private updateInterval;
|
|
107
|
+
/**
|
|
108
|
+
* Perform the save operation
|
|
109
|
+
*/
|
|
110
|
+
private performSave;
|
|
111
|
+
}
|
|
112
|
+
export {};
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-save Service for FlowDrop
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic saving of workflows based on user settings.
|
|
5
|
+
* Uses behaviorSettings for auto-save configuration.
|
|
6
|
+
*
|
|
7
|
+
* @module services/autoSaveService
|
|
8
|
+
*/
|
|
9
|
+
import { get } from "svelte/store";
|
|
10
|
+
import { behaviorSettings } from "../stores/settingsStore.js";
|
|
11
|
+
import { isDirtyStore, isDirty } from "../stores/workflowStore.js";
|
|
12
|
+
/**
|
|
13
|
+
* Initialize auto-save functionality based on user settings
|
|
14
|
+
*
|
|
15
|
+
* Creates an interval-based auto-save mechanism that:
|
|
16
|
+
* - Subscribes to behaviorSettings for auto-save configuration
|
|
17
|
+
* - Monitors the isDirtyStore to check for unsaved changes
|
|
18
|
+
* - Calls the provided save callback when dirty and auto-save is enabled
|
|
19
|
+
*
|
|
20
|
+
* @param options - Auto-save configuration options
|
|
21
|
+
* @returns Cleanup function to stop auto-save and unsubscribe from stores
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // In App.svelte onMount
|
|
26
|
+
* const cleanupAutoSave = initAutoSave({
|
|
27
|
+
* onSave: async () => {
|
|
28
|
+
* await saveWorkflow();
|
|
29
|
+
* },
|
|
30
|
+
* onError: (error) => {
|
|
31
|
+
* console.error("Auto-save failed:", error);
|
|
32
|
+
* },
|
|
33
|
+
* onSuccess: () => {
|
|
34
|
+
* console.log("Auto-saved workflow");
|
|
35
|
+
* }
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // In onDestroy
|
|
39
|
+
* cleanupAutoSave();
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function initAutoSave(options) {
|
|
43
|
+
const { onSave, onError, onSuccess } = options;
|
|
44
|
+
const state = {
|
|
45
|
+
intervalId: null,
|
|
46
|
+
isSaving: false,
|
|
47
|
+
settingsUnsubscriber: null,
|
|
48
|
+
dirtyUnsubscriber: null
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Perform auto-save if conditions are met
|
|
52
|
+
*/
|
|
53
|
+
async function performAutoSave() {
|
|
54
|
+
// Skip if already saving or not dirty
|
|
55
|
+
if (state.isSaving || !isDirty()) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
state.isSaving = true;
|
|
59
|
+
try {
|
|
60
|
+
await onSave();
|
|
61
|
+
onSuccess?.();
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
65
|
+
console.error("Auto-save failed:", err);
|
|
66
|
+
onError?.(err);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
state.isSaving = false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Start or restart the auto-save interval based on current settings
|
|
74
|
+
*/
|
|
75
|
+
function updateAutoSaveInterval() {
|
|
76
|
+
// Clear existing interval
|
|
77
|
+
if (state.intervalId) {
|
|
78
|
+
clearInterval(state.intervalId);
|
|
79
|
+
state.intervalId = null;
|
|
80
|
+
}
|
|
81
|
+
const settings = get(behaviorSettings);
|
|
82
|
+
// Start new interval if auto-save is enabled
|
|
83
|
+
if (settings.autoSave) {
|
|
84
|
+
state.intervalId = setInterval(() => {
|
|
85
|
+
performAutoSave();
|
|
86
|
+
}, settings.autoSaveInterval);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Subscribe to settings changes to react to auto-save toggle/interval changes
|
|
90
|
+
state.settingsUnsubscriber = behaviorSettings.subscribe(() => {
|
|
91
|
+
updateAutoSaveInterval();
|
|
92
|
+
});
|
|
93
|
+
// Initial setup
|
|
94
|
+
updateAutoSaveInterval();
|
|
95
|
+
/**
|
|
96
|
+
* Cleanup function to stop auto-save and unsubscribe from stores
|
|
97
|
+
*/
|
|
98
|
+
return function cleanup() {
|
|
99
|
+
// Clear the interval
|
|
100
|
+
if (state.intervalId) {
|
|
101
|
+
clearInterval(state.intervalId);
|
|
102
|
+
state.intervalId = null;
|
|
103
|
+
}
|
|
104
|
+
// Unsubscribe from stores
|
|
105
|
+
if (state.settingsUnsubscriber) {
|
|
106
|
+
state.settingsUnsubscriber();
|
|
107
|
+
state.settingsUnsubscriber = null;
|
|
108
|
+
}
|
|
109
|
+
if (state.dirtyUnsubscriber) {
|
|
110
|
+
state.dirtyUnsubscriber();
|
|
111
|
+
state.dirtyUnsubscriber = null;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Create an auto-save manager with more control
|
|
117
|
+
*
|
|
118
|
+
* This is a class-based alternative to initAutoSave for cases where
|
|
119
|
+
* you need more fine-grained control over the auto-save behavior.
|
|
120
|
+
*/
|
|
121
|
+
export class AutoSaveManager {
|
|
122
|
+
intervalId = null;
|
|
123
|
+
isSaving = false;
|
|
124
|
+
settingsUnsubscriber = null;
|
|
125
|
+
onSave;
|
|
126
|
+
onError;
|
|
127
|
+
onSuccess;
|
|
128
|
+
/**
|
|
129
|
+
* Create a new AutoSaveManager
|
|
130
|
+
*
|
|
131
|
+
* @param options - Auto-save configuration options
|
|
132
|
+
*/
|
|
133
|
+
constructor(options) {
|
|
134
|
+
this.onSave = options.onSave;
|
|
135
|
+
this.onError = options.onError;
|
|
136
|
+
this.onSuccess = options.onSuccess;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Start the auto-save manager
|
|
140
|
+
*
|
|
141
|
+
* Subscribes to settings changes and starts the auto-save interval.
|
|
142
|
+
*/
|
|
143
|
+
start() {
|
|
144
|
+
if (this.settingsUnsubscriber) {
|
|
145
|
+
return; // Already started
|
|
146
|
+
}
|
|
147
|
+
this.settingsUnsubscriber = behaviorSettings.subscribe(() => {
|
|
148
|
+
this.updateInterval();
|
|
149
|
+
});
|
|
150
|
+
this.updateInterval();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Stop the auto-save manager
|
|
154
|
+
*
|
|
155
|
+
* Clears the interval and unsubscribes from settings.
|
|
156
|
+
*/
|
|
157
|
+
stop() {
|
|
158
|
+
if (this.intervalId) {
|
|
159
|
+
clearInterval(this.intervalId);
|
|
160
|
+
this.intervalId = null;
|
|
161
|
+
}
|
|
162
|
+
if (this.settingsUnsubscriber) {
|
|
163
|
+
this.settingsUnsubscriber();
|
|
164
|
+
this.settingsUnsubscriber = null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Force an immediate save (if dirty)
|
|
169
|
+
*
|
|
170
|
+
* @returns Promise that resolves when save is complete
|
|
171
|
+
*/
|
|
172
|
+
async saveNow() {
|
|
173
|
+
await this.performSave();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Check if auto-save is currently enabled
|
|
177
|
+
*/
|
|
178
|
+
isEnabled() {
|
|
179
|
+
return get(behaviorSettings).autoSave;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Check if auto-save is currently running
|
|
183
|
+
*/
|
|
184
|
+
isRunning() {
|
|
185
|
+
return this.intervalId !== null;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Update the interval based on current settings
|
|
189
|
+
*/
|
|
190
|
+
updateInterval() {
|
|
191
|
+
if (this.intervalId) {
|
|
192
|
+
clearInterval(this.intervalId);
|
|
193
|
+
this.intervalId = null;
|
|
194
|
+
}
|
|
195
|
+
const settings = get(behaviorSettings);
|
|
196
|
+
if (settings.autoSave) {
|
|
197
|
+
this.intervalId = setInterval(() => {
|
|
198
|
+
this.performSave();
|
|
199
|
+
}, settings.autoSaveInterval);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Perform the save operation
|
|
204
|
+
*/
|
|
205
|
+
async performSave() {
|
|
206
|
+
if (this.isSaving || !isDirty()) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
this.isSaving = true;
|
|
210
|
+
try {
|
|
211
|
+
await this.onSave();
|
|
212
|
+
this.onSuccess?.();
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
216
|
+
console.error("Auto-save failed:", err);
|
|
217
|
+
this.onError?.(err);
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
this.isSaving = false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Service for FlowDrop
|
|
3
|
+
*
|
|
4
|
+
* Provides API operations for user preferences/settings using the
|
|
5
|
+
* configurable endpoint system. Integrates with settingsStore for
|
|
6
|
+
* hybrid localStorage + API persistence.
|
|
7
|
+
*
|
|
8
|
+
* @module services/settingsService
|
|
9
|
+
*/
|
|
10
|
+
import type { FlowDropSettings, PartialSettings } from "../types/settings.js";
|
|
11
|
+
import type { EndpointConfig } from "../config/endpoints.js";
|
|
12
|
+
/**
|
|
13
|
+
* Set the endpoint configuration for settings API calls
|
|
14
|
+
*
|
|
15
|
+
* @param config - Endpoint configuration
|
|
16
|
+
*/
|
|
17
|
+
export declare function setSettingsEndpointConfig(config: EndpointConfig): void;
|
|
18
|
+
/**
|
|
19
|
+
* Get the current endpoint configuration
|
|
20
|
+
*
|
|
21
|
+
* @returns Current endpoint configuration or null
|
|
22
|
+
*/
|
|
23
|
+
export declare function getSettingsEndpointConfig(): EndpointConfig | null;
|
|
24
|
+
/**
|
|
25
|
+
* Settings API namespace
|
|
26
|
+
*/
|
|
27
|
+
export declare const settingsApi: {
|
|
28
|
+
/**
|
|
29
|
+
* Get user preferences from the backend
|
|
30
|
+
*
|
|
31
|
+
* @returns User's saved preferences
|
|
32
|
+
*/
|
|
33
|
+
getPreferences(): Promise<FlowDropSettings>;
|
|
34
|
+
/**
|
|
35
|
+
* Save user preferences to the backend
|
|
36
|
+
*
|
|
37
|
+
* @param settings - Complete settings to save
|
|
38
|
+
*/
|
|
39
|
+
savePreferences(settings: FlowDropSettings): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Partially update user preferences
|
|
42
|
+
*
|
|
43
|
+
* @param partial - Partial settings to merge
|
|
44
|
+
*/
|
|
45
|
+
patchPreferences(partial: PartialSettings): Promise<FlowDropSettings>;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Settings service class for integration with settingsStore
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { SettingsService } from "@d34dman/flowdrop";
|
|
53
|
+
* import { setSettingsService } from "@d34dman/flowdrop";
|
|
54
|
+
*
|
|
55
|
+
* const service = new SettingsService(endpointConfig);
|
|
56
|
+
* setSettingsService(service);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare class SettingsService {
|
|
60
|
+
private config;
|
|
61
|
+
/**
|
|
62
|
+
* Create a new settings service instance
|
|
63
|
+
*
|
|
64
|
+
* @param config - Endpoint configuration
|
|
65
|
+
*/
|
|
66
|
+
constructor(config: EndpointConfig);
|
|
67
|
+
/**
|
|
68
|
+
* Get user preferences from the backend
|
|
69
|
+
*
|
|
70
|
+
* @returns User's saved preferences
|
|
71
|
+
*/
|
|
72
|
+
getPreferences(): Promise<FlowDropSettings>;
|
|
73
|
+
/**
|
|
74
|
+
* Save user preferences to the backend
|
|
75
|
+
*
|
|
76
|
+
* @param settings - Complete settings to save
|
|
77
|
+
*/
|
|
78
|
+
savePreferences(settings: FlowDropSettings): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Partially update user preferences
|
|
81
|
+
*
|
|
82
|
+
* @param partial - Partial settings to merge
|
|
83
|
+
*/
|
|
84
|
+
patchPreferences(partial: PartialSettings): Promise<FlowDropSettings>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create a settings service instance
|
|
88
|
+
*
|
|
89
|
+
* @param config - Endpoint configuration
|
|
90
|
+
* @returns SettingsService instance
|
|
91
|
+
*/
|
|
92
|
+
export declare function createSettingsService(config: EndpointConfig): SettingsService;
|