All files / web/src/composables/editor useWorkflowConverter.ts

100% Statements 60/60
69.56% Branches 16/23
100% Functions 3/3
100% Lines 60/60

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82            1x   1x 1x 9x 9x 9x 9x       9x 9x 4x 5x   9x 9x 9x 9x 9x 9x 9x   9x 9x 3x 3x 3x 3x 9x   9x 9x   1x 10x 10x 10x 10x 10x       8x 8x 5x 3x   8x 8x 8x 8x 8x 8x 10x   10x 3x 3x 10x   10x 10x 10x 10x 10x 10x 10x   1x 1x 1x 1x 1x  
import type { Edge as BackendEdge } from '@/types/generated/Edge'
import type { Node as BackendNode } from '@/types/generated/Node'
import type { NodeType } from '@/types/generated/NodeType'
import type { Workflow } from '@/types/generated/Workflow'
import type { Edge as VueFlowEdge, Node as VueFlowNode } from '@vue-flow/core'
 
const TRIGGER_NODE_TYPES = ['ManualTrigger', 'WebhookTrigger', 'ScheduleTrigger']
 
export function useWorkflowConverter() {
  const convertFromBackendFormat = (
    workflow: Workflow,
  ): { nodes: VueFlowNode[]; edges: VueFlowEdge[] } => {
    const nodes: VueFlowNode[] =
      workflow.nodes?.map((node) => {
        // Extract data from nested structure for trigger nodes
        // Backend format: {"type": "WebhookTrigger", "data": {"path": "...", "method": "..."}}
        // Frontend format: {"path": "...", "method": "..."}
        const isTriggerNode = TRIGGER_NODE_TYPES.includes(node.node_type)
        const data = isTriggerNode && node.config?.data
          ? node.config.data
          : node.config || {}
 
        return {
          id: node.id,
          type: node.node_type,
          position: node.position || { x: 100 + Math.random() * 500, y: 100 + Math.random() * 400 },
          data,
        }
      }) || []
 
    const edges: VueFlowEdge[] =
      workflow.edges?.map((edge) => ({
        id: `e${edge.from}-${edge.to}`,
        source: edge.from,
        target: edge.to,
        animated: true,
      })) || []
 
    return { nodes, edges }
  }
 
  const convertToBackendFormat = (
    nodes: VueFlowNode[],
    edges: VueFlowEdge[],
    meta?: Partial<Workflow>,
  ): Workflow => {
    const workflowNodes: BackendNode[] = nodes.map((node) => {
      // Wrap flattened data back into typed structure for trigger nodes
      // Frontend format: {"path": "...", "method": "..."}
      // Backend format: {"type": "WebhookTrigger", "data": {"path": "...", "method": "..."}}
      const isTriggerNode = TRIGGER_NODE_TYPES.includes(node.type as string)
      const config = isTriggerNode
        ? { type: node.type, data: node.data || {} }
        : node.data || {}
 
      return {
        id: node.id,
        node_type: node.type as NodeType,
        config,
        position: node.position ? { x: node.position.x, y: node.position.y } : null,
      }
    })
 
    const workflowEdges: BackendEdge[] = edges.map((edge) => ({
      from: edge.source,
      to: edge.target,
    }))
 
    return {
      id: meta?.id || `workflow-${Date.now()}`,
      name: meta?.name || 'My Workflow',
      nodes: workflowNodes,
      edges: workflowEdges,
    }
  }
 
  return {
    convertFromBackendFormat,
    convertToBackendFormat,
  }
}