Flow Hooks API
Flow Hooks API
Section titled “Flow Hooks API”The Flow component exposes a comprehensive API through window.$useFlowCore that allows external JavaScript to configure, control, and interact with the flow editor.
Accessing Hooks
Section titled “Accessing Hooks”// Hooks are available after flow.js is loadedconst { configure, getApp, getFlow, setFlow, pushingNode, pushNode, reset, clear, theme, setTheme, onMapperPreview, setMapperPreviewResult, setStore, setWorkflows, setWorkflow,} = window.$useFlowCore;Available Hooks
Section titled “Available Hooks”Configuration
Section titled “Configuration”| Hook | Signature | Description |
|---|---|---|
configure | (signature: string, apps: App[]) => void | Register available action modules |
getApp | (module: string) => App | undefined | Get app configuration by module name |
Flow State
Section titled “Flow State”| Hook | Signature | Description |
|---|---|---|
getFlow | () => WorkFlow | Get current flow data (nodes, edges, variables) |
setFlow | (flow: WorkFlow) => void | Load a flow into the editor |
clear | () => void | Clear the entire flow |
reset | (nodeId?: string) => void | Reset execution state |
Execution
Section titled “Execution”| Hook | Signature | Description |
|---|---|---|
pushingNode | (params: Response) => void | Signal that a node is executing |
pushNode | (params: Result) => void | Report node execution result |
| Hook | Signature | Description |
|---|---|---|
theme | Ref<'light' | 'dark'> | Current theme value (reactive) |
setTheme | (theme: 'light' | 'dark') => void | Change the theme |
Mapper Preview
Section titled “Mapper Preview”| Hook | Signature | Description |
|---|---|---|
onMapperPreview | (fn: Function) => void | Register mapper preview callback |
setMapperPreviewResult | (logs: any) => void | Report mapper preview results |
SubFlows
Section titled “SubFlows”| Hook | Signature | Description |
|---|---|---|
setWorkflows | (workflows: any) => void | Set available subflow workflows |
setWorkflow | (workflow: any) => void | Set a specific subflow |
| Hook | Signature | Description |
|---|---|---|
setStore | (data: any) => void | Set additional store data |
Configuration
Section titled “Configuration”configure(signature, apps)
Section titled “configure(signature, apps)”Register the available action modules that users can add to the flow:
const { configure } = window.$useFlowCore;
configure('ion.action', [ { module: 'ion.action.http', label: 'HTTP Request', icon: 'globe', group: 'core', color: '#3B82F6', spec: { type: 'collection', spec: [ { type: 'select', name: 'method', label: 'Method', options: [ { label: 'GET', value: 'GET' }, { label: 'POST', value: 'POST' }, { label: 'PUT', value: 'PUT' }, { label: 'DELETE', value: 'DELETE' }, ], }, { type: 'url', name: 'url', label: 'URL', required: true }, { type: 'text', name: 'body', label: 'Body', multiline: true }, ], }, }, { module: 'ion.action.condition', label: 'Condition', icon: 'git-branch', group: 'logic', color: '#8B5CF6', spec: { type: 'collection', spec: [ { type: 'text', name: 'expression', label: 'Condition Expression' }, ], }, },]);getApp(module)
Section titled “getApp(module)”Retrieve an app’s configuration by its module identifier:
const { getApp } = window.$useFlowCore;
const httpApp = getApp('ion.action.http');if (httpApp) { console.log('HTTP app label:', httpApp.label); console.log('HTTP app spec:', httpApp.spec);}Flow State Management
Section titled “Flow State Management”getFlow()
Section titled “getFlow()”Get the current flow state including all nodes, edges, and variables:
const { getFlow } = window.$useFlowCore;
const flowData = getFlow();// {// nodes: [...],// edges: [...],// variables: {...}// }
// Save to backendawait api.saveFlow(flowId, flowData);setFlow(flow)
Section titled “setFlow(flow)”Load a flow into the editor:
const { setFlow } = window.$useFlowCore;
const savedFlow = await api.getFlow(flowId);
setFlow({ nodes: savedFlow.nodes || [], edges: savedFlow.edges || [], variables: savedFlow.variables || {},});clear()
Section titled “clear()”Clear all nodes and edges from the flow:
const { clear } = window.$useFlowCore;
function handleNewFlow() { if (confirm('Create new flow? All changes will be lost.')) { clear(); }}reset(nodeId?)
Section titled “reset(nodeId?)”Reset execution state. If nodeId is provided, only reset that node’s context:
const { reset } = window.$useFlowCore;
// Reset all execution statereset();
// Reset specific nodereset('node_123');Execution Feedback
Section titled “Execution Feedback”pushingNode(params)
Section titled “pushingNode(params)”Signal that a node has started executing. This animates the incoming edge:
const { pushingNode } = window.$useFlowCore;
pushingNode({ node: 'node_123', queue: { edge_id: 'edge_456', // Edge being traversed target: 'node_123', // Target node data: { input: 'data' }, // Input data }, message: null, // Error message if any});pushNode(params)
Section titled “pushNode(params)”Report the result of node execution:
const { pushNode } = window.$useFlowCore;
// Success casepushNode({ node: { id: 'node_123', data: { /* node config */ } }, status: 'success', message: null, edges: ['edge_789', 'edge_790'], // Outgoing edges outputs: [ { data: { response: 'data' } }, ],});
// Error casepushNode({ node: { id: 'node_123' }, status: 'error', message: 'Connection timeout after 30s', edges: [], outputs: [],});Complete Execution Example
Section titled “Complete Execution Example”async function executeNode(nodeId: string) { const { getFlow, pushingNode, pushNode, reset } = window.$useFlowCore;
// 1. Reset any previous state for this node reset(nodeId);
// 2. Get current flow state const flow = getFlow(); const node = flow.nodes.find(n => n.id === nodeId);
if (!node) { console.error('Node not found:', nodeId); return; }
// 3. Find the edge coming into this node const incomingEdge = flow.edges.find(e => e.target === nodeId);
// 4. Signal execution start pushingNode({ node: nodeId, queue: { edge_id: incomingEdge?.id ?? null, target: nodeId, data: node.data, }, });
try { // 5. Execute on backend const result = await fetch('/api/execute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ flowId: currentFlowId, nodeId, nodeType: node.type, nodeData: node.data, context: getExecutionContext(), }), }).then(r => r.json());
// 6. Report success const outgoingEdges = flow.edges .filter(e => e.source === nodeId) .map(e => e.id);
pushNode({ node, status: 'success', message: null, edges: outgoingEdges, outputs: [{ data: result.output }], });
} catch (error) { // 6. Report error pushNode({ node, status: 'error', message: error.message, edges: [], outputs: [], }); }}Theme Control
Section titled “Theme Control”const { theme, setTheme } = window.$useFlowCore;
// Read current theme (this is a Vue ref)console.log('Current theme:', theme.value);
// Change themesetTheme('dark');
// Toggle themefunction toggleTheme() { setTheme(theme.value === 'light' ? 'dark' : 'light');}SubFlows
Section titled “SubFlows”SubFlows allow embedding other workflows as nodes:
const { setWorkflows, setWorkflow } = window.$useFlowCore;
// Load all available subflowsconst subflows = await api.getSubflows();setWorkflows(subflows);
// Set a specific subflow for a nodesetWorkflow({ id: 'subflow_123', name: 'Order Processing', nodes: [...], edges: [...],});Mapper Preview Integration
Section titled “Mapper Preview Integration”When using the mapper within nodes:
const { onMapperPreview, setMapperPreviewResult } = window.$useFlowCore;
// Register callback for when user clicks "Preview" in mapperonMapperPreview(async (flow, params) => { const result = await api.post('/mapper/preview', { flow, params, });
setMapperPreviewResult(result.logs);});TypeScript Declarations
Section titled “TypeScript Declarations”import type { Field } from '@ion-components/ui/types';import type { Ref } from 'vue';
interface App { module: string; label: string; icon?: string; group?: string; color?: string; spec?: Field;}
interface WorkFlow { nodes: Array<{ id: string; type: string; position: { x: number; y: number }; data: Record<string, any>; }>; edges: Array<{ id: string; source: string; target: string; sourceHandle?: string; targetHandle?: string; }>; variables?: Record<string, any>;}
interface Response { node: string; queue: { edge_id: string | null; target: string; data?: any; }; message?: string | null;}
interface Result { node: { id: string; data?: any }; status: 'success' | 'error'; message?: string | null; edges?: string[]; outputs?: Array<{ data: any }>;}
declare global { interface Window { $useFlowCore: { configure: (signature: string, apps: App[]) => void; getApp: (module: string) => App | undefined; getFlow: () => WorkFlow; setFlow: (flow: WorkFlow) => void; clear: () => void; reset: (nodeId?: string) => void; pushingNode: (params: Response) => void; pushNode: (params: Result) => void; theme: Ref<'light' | 'dark'>; setTheme: (theme: 'light' | 'dark') => void; onMapperPreview: (fn: (flow: any, params: any) => void) => void; setMapperPreviewResult: (logs: any) => void; setStore: (data: any) => void; setWorkflows: (workflows: any) => void; setWorkflow: (workflow: any) => void; }; }}
export {};