Store System
FlowDrop uses Svelte 5 runes for reactive state management. Stores are module-level singletons that hold the editor’s state. While most developers won’t need to interact with stores directly, they’re essential for advanced integrations.
Workflow Store
Section titled “Workflow Store”The central store holding the current workflow state.
Reading State
Section titled “Reading State”import { getWorkflowStore, getIsDirty, getWorkflowNodes, getWorkflowEdges, getWorkflowName, getWorkflowValidation} from '@flowdrop/flowdrop/editor';
// Reactive getters (re-evaluate when state changes)const workflow = getWorkflowStore(); // Workflow | nullconst isDirty = getIsDirty(); // booleanconst nodes = getWorkflowNodes(); // WorkflowNode[]const edges = getWorkflowEdges(); // WorkflowEdge[]const name = getWorkflowName(); // stringconst validation = getWorkflowValidation();// { hasNodes, hasEdges, nodeCount, edgeCount, isValid }Modifying State
Section titled “Modifying State”import { workflowActions } from '@flowdrop/flowdrop/editor';
// Initialize with a loaded workflowworkflowActions.initialize(workflow);
// Node operationsworkflowActions.addNode(newNode);workflowActions.removeNode('node-id');workflowActions.updateNode('node-id', { data: { ...updates } });
// Edge operationsworkflowActions.addEdge(newEdge);workflowActions.removeEdge('edge-id');
// MetadataworkflowActions.updateName('New Workflow Name');workflowActions.updateMetadata({ tags: ['production'] });
// Batch update (single history entry)workflowActions.batchUpdate({ nodes: updatedNodes, edges: updatedEdges, name: 'Updated Name'});
// Clear everythingworkflowActions.clear();Dirty State
Section titled “Dirty State”import { markAsSaved, isDirty } from '@flowdrop/flowdrop/editor';
// Check dirty state (non-reactive)if (isDirty()) { console.log('There are unsaved changes');}
// Clear dirty flag after savingmarkAsSaved();History Store
Section titled “History Store”Manages undo/redo with snapshot-based history.
import { getCanUndo, getCanRedo, historyActions } from '@flowdrop/flowdrop/editor';
// Check availability (reactive)const canUndo = getCanUndo(); // booleanconst canRedo = getCanRedo(); // boolean
// Perform undo/redohistoryActions.undo(); // returns boolean (success)historyActions.redo(); // returns boolean (success)
// Manual history managementhistoryActions.pushState(workflow, { description: 'Bulk import' });historyActions.clear(currentWorkflow);
// Transactions (group multiple changes into one undo step)historyActions.startTransaction(workflow, 'Rearrange nodes');// ... make multiple changes ...historyActions.commitTransaction();// or: historyActions.cancelTransaction();Settings Store
Section titled “Settings Store”User preferences for theme, editor behavior, and UI.
import { getSettings, getThemeSettings, getEditorSettings, getUiSettings, updateSettings, resetSettings} from '@flowdrop/flowdrop/settings';
// Read settings (reactive)const settings = getSettings(); // FlowDropSettingsconst theme = getThemeSettings(); // ThemeSettingsconst editor = getEditorSettings(); // EditorSettingsconst ui = getUiSettings(); // UISettings
// Update settingsupdateSettings({ theme: { preference: 'dark' }, editor: { snapToGrid: true, gridSize: 20 }});
// Reset to defaultsresetSettings(); // reset allresetSettings(['theme']); // reset only theme
// Subscribe to changesconst unsubscribe = onSettingsChange((newSettings, oldSettings) => { console.log('Settings changed:', newSettings);});// Later: unsubscribe();Theme Control
Section titled “Theme Control”import { getTheme, getResolvedTheme, setTheme, toggleTheme, cycleTheme} from '@flowdrop/flowdrop/core';
getTheme(); // 'light' | 'dark' | 'auto'getResolvedTheme(); // 'light' | 'dark' (actual applied theme)setTheme('dark');toggleTheme(); // light ↔ darkcycleTheme(); // light → dark → auto → lightPlayground Store
Section titled “Playground Store”Manages interactive testing sessions and messages.
import { getCurrentSession, getSessions, getMessages, getChatMessages, getLogMessages, getIsExecuting, playgroundActions} from '@flowdrop/flowdrop/playground';
// Read state (reactive)const session = getCurrentSession(); // PlaygroundSession | nullconst sessions = getSessions(); // PlaygroundSession[]const messages = getMessages(); // PlaygroundMessage[]const chatMsgs = getChatMessages(); // PlaygroundMessage[] (user/assistant only)const logMsgs = getLogMessages(); // PlaygroundMessage[] (system only)const isRunning = getIsExecuting(); // booleanInterrupt Store
Section titled “Interrupt Store”Manages human-in-the-loop interrupt state.
import { getPendingInterrupts, getResolvedInterrupts, interruptActions} from '@flowdrop/flowdrop/playground';
// Read state (reactive)const pending = getPendingInterrupts(); // Interrupt[]const resolved = getResolvedInterrupts(); // Interrupt[]Using Stores in Svelte Components
Section titled “Using Stores in Svelte Components”Since stores use Svelte 5 runes, you can use them directly in .svelte files with $derived:
<script> import { getWorkflowNodes, getIsDirty } from '@flowdrop/flowdrop/editor';
const nodes = $derived(getWorkflowNodes()); const isDirty = $derived(getIsDirty());</script>
<p>Nodes: {nodes.length}</p><p>Unsaved: {isDirty ? 'Yes' : 'No'}</p>Using Stores Outside Svelte
Section titled “Using Stores Outside Svelte”For vanilla JS or other frameworks, call the getter functions directly. They return the current value at call time:
// Polling patternsetInterval(() => { const workflow = getWorkflowStore(); const dirty = getIsDirty(); externalUI.update({ workflow, dirty });}, 1000);For event-driven updates, use the event system instead of polling:
eventHandlers: { onWorkflowChange: (workflow) => externalUI.update(workflow), onDirtyStateChange: (isDirty) => externalUI.setDirty(isDirty)}