@zenwave360/vistas-eventflow 0.1.0
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/FLOWVIEWMODEL_EXAMPLES.md +896 -0
- package/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/EventFlowVisualizer.d.ts +25 -0
- package/dist/EventFlowVisualizer.d.ts.map +1 -0
- package/dist/ServiceMapVisualizer.d.ts +14 -0
- package/dist/ServiceMapVisualizer.d.ts.map +1 -0
- package/dist/components/CausationEdge.d.ts +8 -0
- package/dist/components/CausationEdge.d.ts.map +1 -0
- package/dist/components/CommandNode.d.ts +10 -0
- package/dist/components/CommandNode.d.ts.map +1 -0
- package/dist/components/EndNode.d.ts +10 -0
- package/dist/components/EndNode.d.ts.map +1 -0
- package/dist/components/EventNode.d.ts +10 -0
- package/dist/components/EventNode.d.ts.map +1 -0
- package/dist/components/OutcomeNode.d.ts +7 -0
- package/dist/components/OutcomeNode.d.ts.map +1 -0
- package/dist/components/PolicyNode.d.ts +16 -0
- package/dist/components/PolicyNode.d.ts.map +1 -0
- package/dist/components/ServiceGroupNode.d.ts +10 -0
- package/dist/components/ServiceGroupNode.d.ts.map +1 -0
- package/dist/components/ServiceMapNode.d.ts +8 -0
- package/dist/components/ServiceMapNode.d.ts.map +1 -0
- package/dist/components/StartNode.d.ts +10 -0
- package/dist/components/StartNode.d.ts.map +1 -0
- package/dist/components/SystemGroupNode.d.ts +7 -0
- package/dist/components/SystemGroupNode.d.ts.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +645 -0
- package/dist/index.js.map +1 -0
- package/dist/labelFormatting.d.ts +6 -0
- package/dist/labelFormatting.d.ts.map +1 -0
- package/dist/styles.css +1 -0
- package/dist/types/FlowViewModel-updated.d.ts +114 -0
- package/dist/types/FlowViewModel-updated.d.ts.map +1 -0
- package/dist/types/FlowViewModel.d.ts +124 -0
- package/dist/types/FlowViewModel.d.ts.map +1 -0
- package/dist/types/ServiceViewModel.d.ts +64 -0
- package/dist/types/ServiceViewModel.d.ts.map +1 -0
- package/event-flow-architecture-and-contracts.md +1067 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/components/CommandNode.tsx","../src/components/EventNode.tsx","../src/components/PolicyNode.tsx","../src/components/StartNode.tsx","../src/components/EndNode.tsx","../src/components/OutcomeNode.tsx","../src/types/FlowViewModel.ts","../src/components/CausationEdge.tsx","../src/labelFormatting.ts","../src/EventFlowVisualizer.tsx","../src/components/ServiceGroupNode.tsx","../src/components/ServiceMapNode.tsx","../src/types/ServiceViewModel.ts","../src/ServiceMapVisualizer.tsx"],"sourcesContent":["import { Handle, NodeProps, Position } from 'reactflow';\nimport { SourceRef } from '../types/FlowViewModel';\n\nexport interface CommandNodeData {\n label: string;\n endOutcomeLabels?: string[];\n sourceRef?: SourceRef;\n title?: string;\n}\n\nexport function CommandNode({ data }: NodeProps<CommandNodeData>) {\n return (\n <div className=\"eventflow-command-node\" title={data.title}>\n {data.endOutcomeLabels && data.endOutcomeLabels.length > 0 ? (\n <div className=\"node-role-badge node-role-badge-end-outcome\">\n {data.endOutcomeLabels.join(', ')}\n </div>\n ) : null}\n <Handle type=\"target\" position={Position.Left} />\n <div className=\"node-header\">\n <strong>{data.label}</strong>\n </div>\n <Handle type=\"source\" position={Position.Right} />\n </div>\n );\n}\n","import { Handle, NodeProps, Position } from 'reactflow';\nimport { SourceRef } from '../types/FlowViewModel';\n\nexport interface EventNodeData {\n label: string;\n endOutcomeLabels?: string[];\n sourceRef?: SourceRef;\n title?: string;\n}\n\nexport function EventNode({ data }: NodeProps<EventNodeData>) {\n return (\n <div className=\"eventflow-event-node\" title={data.title}>\n {data.endOutcomeLabels && data.endOutcomeLabels.length > 0 ? (\n <div className=\"node-role-badge node-role-badge-end-outcome\">\n {data.endOutcomeLabels.join(', ')}\n </div>\n ) : null}\n <Handle type=\"target\" position={Position.Left} />\n <div className=\"node-header\">\n <strong>{data.label}</strong>\n </div>\n <Handle type=\"source\" position={Position.Right} />\n </div>\n );\n}\n","import { Handle, NodeProps, Position } from 'reactflow';\nimport { SourceRef } from '../types/FlowViewModel';\n\nexport interface PolicyNodeData {\n label: string;\n endOutcomeLabels?: string[];\n sourceRef?: SourceRef;\n title?: string;\n policyLabelParts?: {\n when: string;\n condition: string;\n do: string;\n action: string;\n };\n}\n\nexport function PolicyNode({ data }: NodeProps<PolicyNodeData>) {\n return (\n <div className=\"eventflow-policy-node\" title={data.title}>\n {data.endOutcomeLabels && data.endOutcomeLabels.length > 0 ? (\n <div className=\"node-role-badge node-role-badge-end-outcome\">\n {data.endOutcomeLabels.join(', ')}\n </div>\n ) : null}\n <Handle type=\"target\" position={Position.Left} />\n {data.policyLabelParts ? (\n <div className=\"node-header eventflow-policy-label\">\n <span className=\"eventflow-policy-keyword\">{data.policyLabelParts.when}</span>\n <strong className=\"eventflow-policy-condition\">{data.policyLabelParts.condition}</strong>\n <span className=\"eventflow-policy-keyword\">{data.policyLabelParts.do}</span>\n <strong className=\"eventflow-policy-action\">{data.policyLabelParts.action}</strong>\n </div>\n ) : (\n <div className=\"node-header\">\n <strong>{data.label}</strong>\n </div>\n )}\n <Handle type=\"source\" position={Position.Right} />\n </div>\n );\n}\n","import { Handle, NodeProps, Position } from 'reactflow';\nimport { SourceRef } from '../types/FlowViewModel';\n\nexport interface StartNodeData {\n label: string;\n endOutcomeLabels?: string[];\n sourceRef?: SourceRef;\n title?: string;\n}\n\nexport function StartNode({ data }: NodeProps<StartNodeData>) {\n return (\n <div className=\"eventflow-start-node-shell\" title={data.title}>\n <div className=\"node-role-badge node-role-badge-start\">START</div>\n {data.endOutcomeLabels && data.endOutcomeLabels.length > 0 ? (\n <div className=\"node-role-badge node-role-badge-end-outcome\">\n {data.endOutcomeLabels.join(', ')}\n </div>\n ) : null}\n <div className=\"eventflow-start-node\">\n <div className=\"node-header\">\n <strong>{data.label}</strong>\n </div>\n <Handle type=\"source\" position={Position.Right} />\n </div>\n </div>\n );\n}\n","import { Handle, NodeProps, Position } from 'reactflow';\nimport { SourceRef } from '../types/FlowViewModel';\n\nexport interface EndNodeData {\n label: string;\n endOutcomeLabels?: string[];\n sourceRef?: SourceRef;\n title?: string;\n}\n\nexport function EndNode({ data }: NodeProps<EndNodeData>) {\n return (\n <div className=\"eventflow-end-node\" title={data.title}>\n {data.endOutcomeLabels && data.endOutcomeLabels.length > 0 ? (\n <div className=\"node-role-badge node-role-badge-end-outcome\">\n {data.endOutcomeLabels.join(', ')}\n </div>\n ) : null}\n <Handle type=\"target\" position={Position.Left} />\n <div className=\"node-header\">\n <strong>{data.label}</strong>\n </div>\n </div>\n );\n}\n","import { Handle, NodeProps, Position } from 'reactflow';\n\nexport interface OutcomeNodeData {\n label: string;\n synthetic: true;\n}\n\nexport function OutcomeNode({ data }: NodeProps<OutcomeNodeData>) {\n return (\n <div className=\"eventflow-outcome-node\">\n <Handle type=\"target\" position={Position.Left} />\n <div className=\"node-header\">{data.label}</div>\n <Handle type=\"source\" position={Position.Right} />\n </div>\n );\n}\n","/**\n * TypeScript interfaces mirroring the JSON serialization of\n * io.zenwave360.language.eventflow.view.FlowViewModel.\n *\n * The viewer consumes positioned flow data when layout is available, but the\n * model also allows pre-layout values where position and dimensions are null.\n */\n\n/**\n * Represents a precise location in a source file.\n * Lines and columns are 1-based.\n */\nexport interface SourceRef {\n file: string;\n line: number;\n column: number;\n}\n\n/**\n * Semantic types of nodes in an event flow.\n */\nexport enum FlowNodeType {\n START = \"START\",\n COMMAND = \"COMMAND\",\n EVENT = \"EVENT\",\n POLICY = \"POLICY\",\n END = \"END\"\n}\n\n/**\n * Semantic meaning of a relationship between nodes.\n */\nexport enum FlowEdgeType {\n CAUSATION = \"CAUSATION\",\n CALL = \"CALL\",\n OUTCOME_HANDLER = \"OUTCOME_HANDLER\",\n TRIGGER = \"TRIGGER\",\n CONDITIONAL = \"CONDITIONAL\",\n ERROR = \"ERROR\"\n}\n\n/**\n * Layout direction produced by the source layout engine.\n */\nexport enum Direction {\n LR = \"LR\",\n TB = \"TB\"\n}\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Dimensions {\n width: number;\n height: number;\n}\n\nexport interface FlowBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * A node in an event-driven flow.\n *\n * Layout properties are null until the layout engine has been applied.\n */\nexport interface FlowNode {\n id: string;\n type: FlowNodeType;\n label: string;\n endOutcome?: string[] | null;\n system: string | null;\n service: string | null;\n sourceRef: SourceRef;\n position: Point | null;\n dimensions: Dimensions | null;\n}\n\n/**\n * Directed relationship between two flow nodes.\n */\nexport interface FlowEdge {\n id: string;\n source: string;\n target: string;\n type: FlowEdgeType;\n outcome: string | null;\n label: string | null;\n sourceRef: SourceRef | null;\n}\n\nexport interface FlowSystemGroupView {\n systemName: string;\n bounds: FlowBounds;\n}\n\nexport interface LayoutMetadata {\n engine: string;\n direction: Direction;\n rankSpacing: number;\n nodeSpacing: number;\n}\n\nexport interface FlowIR {\n nodes: FlowNode[];\n edges: FlowEdge[];\n}\n\n/**\n * Unified view model for an event-driven flow diagram.\n */\nexport interface FlowViewModel {\n schema: string;\n nodes: FlowNode[];\n edges: FlowEdge[];\n layout: LayoutMetadata | null;\n bounds: FlowBounds | null;\n systemGroups: FlowSystemGroupView[] | null;\n}\n\n/**\n * Backward-compatible aliases used by the demo and external consumers.\n */\nexport type FlowNodeView = FlowNode;\nexport type FlowEdgeView = FlowEdge;\n\n/**\n * Factory function to create a FlowViewModel with default values.\n */\nexport function createFlowViewModel(\n partial: Partial<FlowViewModel> & {\n nodes: FlowNode[];\n edges: FlowEdge[];\n }\n): FlowViewModel {\n return {\n schema: \"zfl.eventflow.view@1\",\n layout: null,\n bounds: null,\n systemGroups: null,\n ...partial\n };\n}\n","import { BaseEdge, EdgeLabelRenderer, EdgeProps, getBezierPath } from 'reactflow';\nimport { FlowEdgeType } from '../types/FlowViewModel';\n\ninterface EventFlowEdgeData {\n edgeType?: FlowEdgeType;\n}\n\nfunction getEdgeStroke(edgeType: FlowEdgeType | undefined): string {\n if (edgeType === FlowEdgeType.ERROR) return '#dc2626';\n if (edgeType === FlowEdgeType.CALL) return '#2563eb';\n if (edgeType === FlowEdgeType.OUTCOME_HANDLER) return '#ea580c';\n if (edgeType === FlowEdgeType.TRIGGER) return '#7c3aed';\n if (edgeType === FlowEdgeType.CONDITIONAL) return '#0f766e';\n return '#64748b';\n}\n\nfunction getEdgeDasharray(edgeType: FlowEdgeType | undefined): string | undefined {\n if (edgeType === FlowEdgeType.CALL) return '14 8';\n if (edgeType === FlowEdgeType.OUTCOME_HANDLER) return '3 6';\n if (edgeType === FlowEdgeType.TRIGGER) return '6 4';\n if (edgeType === FlowEdgeType.CONDITIONAL) return '10 6';\n if (edgeType === FlowEdgeType.ERROR) return '3 3';\n return undefined;\n}\n\nexport function CausationEdge(props: EdgeProps<EventFlowEdgeData>) {\n const [edgePath, labelX, labelY] = getBezierPath(props);\n const edgeType = props.data?.edgeType;\n const stroke = getEdgeStroke(edgeType);\n const dasharray = getEdgeDasharray(edgeType);\n\n return (\n <>\n <BaseEdge\n id={props.id}\n path={edgePath}\n markerEnd={props.markerEnd}\n style={{\n stroke,\n strokeWidth: 2.5,\n strokeDasharray: dasharray,\n }}\n />\n {props.label && (\n <EdgeLabelRenderer>\n <div\n className=\"eventflow-edge-label\"\n style={{\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n }}\n >\n {props.label}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n}\n","export interface DiagramDisplaySettings {\n humanizeLabels?: boolean;\n}\n\nfunction splitIdentifierWords(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nexport function humanizeLabel(label: string): string {\n return label\n .split(':')\n .map((segment) => splitIdentifierWords(segment))\n .join(': ');\n}\n\nexport function humanizeMultilineLabel(label: string): string {\n return label\n .split('\\n')\n .map((line) => humanizeLabel(line))\n .join('\\n');\n}\n","/**\n * EventFlow Visualizer - React Flow visualizer for FlowViewModel\n *\n * The component renders pre-computed flow positions and supports interactive\n * drag-based layout editing without performing automatic layout locally.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ReactFlow, {\n applyNodeChanges,\n Background,\n Controls,\n Edge,\n MarkerType,\n MiniMap,\n Node,\n NodeChange,\n} from 'reactflow';\nimport 'reactflow/dist/style.css';\nimport './styles/eventflow.css';\n\nimport { CommandNode } from './components/CommandNode';\nimport { EventNode } from './components/EventNode';\nimport { PolicyNode } from './components/PolicyNode';\nimport { StartNode } from './components/StartNode';\nimport { EndNode } from './components/EndNode';\nimport { OutcomeNode } from './components/OutcomeNode';\nimport { CausationEdge } from './components/CausationEdge';\nimport { DiagramDisplaySettings, humanizeLabel } from './labelFormatting';\n\nimport {\n Dimensions,\n FlowBounds,\n FlowEdgeType,\n FlowNode,\n FlowNodeType,\n FlowViewModel,\n Point,\n SourceRef,\n} from './types/FlowViewModel';\n\nexport interface EventFlowVisualizerProps {\n flowViewModel: FlowViewModel;\n theme?: 'light' | 'dark';\n editable?: boolean;\n displaySettings?: EventFlowDisplaySettings;\n highlightedNodeIds?: string[];\n onNodeClick?: (nodeId: string, sourceRef?: SourceRef) => void;\n onSelectionChange?: (selectedNodes: string[], selectedEdges: string[]) => void;\n onFlowViewModelChange?: (updatedFlowViewModel: FlowViewModel) => void;\n}\n\nexport interface EventFlowDisplaySettings extends DiagramDisplaySettings {}\n\ninterface EventFlowNodeData {\n label: string;\n endOutcomeLabels?: string[];\n sourceRef?: SourceRef;\n title?: string;\n synthetic?: boolean;\n policyLabelParts?: {\n when: string;\n condition: string;\n do: string;\n action: string;\n };\n}\n\ninterface LegacyFlowNodeEndOutcome {\n endOutcomeLabels?: string[] | null;\n}\n\nconst MIN_NODE_WIDTH = 180;\nconst MIN_NODE_HEIGHT = 112;\nconst OUTCOME_NODE_HEIGHT = 32;\nconst OUTCOME_NODE_MIN_WIDTH = 72;\nconst OUTCOME_NODE_MAX_WIDTH = 180;\nconst OUTCOME_NODE_MARGIN = 24;\n\ntype EventFlowReactNode = Node<EventFlowNodeData>;\n\ninterface SyntheticOutcomeRouting {\n nodes: EventFlowReactNode[];\n edges: Edge[];\n groupedEdgeIds: Set<string>;\n}\n\nfunction getRenderedDimensions(node: FlowNode): Dimensions {\n const baseWidth = node.dimensions?.width ?? MIN_NODE_WIDTH;\n const baseHeight = node.dimensions?.height ?? MIN_NODE_HEIGHT;\n\n return {\n width: Math.max(baseWidth, MIN_NODE_WIDTH),\n height: Math.max(baseHeight, MIN_NODE_HEIGHT),\n };\n}\n\nfunction getRenderedPosition(node: FlowNode, renderedDimensions: Dimensions): Point {\n const position = node.position ?? { x: 0, y: 0 };\n const originalDimensions = node.dimensions;\n\n if (!originalDimensions) {\n return position;\n }\n\n return {\n x: position.x - ((renderedDimensions.width - originalDimensions.width) / 2),\n y: position.y - ((renderedDimensions.height - originalDimensions.height) / 2),\n };\n}\n\nfunction getNodeType(nodeType: FlowNodeType): string {\n switch (nodeType) {\n case FlowNodeType.START:\n return 'startNode';\n case FlowNodeType.COMMAND:\n return 'commandNode';\n case FlowNodeType.EVENT:\n return 'eventNode';\n case FlowNodeType.POLICY:\n return 'policyNode';\n case FlowNodeType.END:\n return 'endNode';\n default:\n return 'eventNode';\n }\n}\n\nfunction getNodeColor(nodeType?: string): string {\n if (nodeType === 'startNode') return '#22c55e';\n if (nodeType === 'commandNode') return '#3b82f6';\n if (nodeType === 'eventNode') return '#f97316';\n if (nodeType === 'policyNode') return '#a855f7';\n if (nodeType === 'endNode') return '#ef4444';\n if (nodeType === 'outcomeNode') return '#e2e8f0';\n return '#cbd5e1';\n}\n\nfunction getEdgeMarkerColor(edgeType: FlowEdgeType): string {\n if (edgeType === FlowEdgeType.CALL) return '#2563eb';\n if (edgeType === FlowEdgeType.OUTCOME_HANDLER) return '#ea580c';\n if (edgeType === FlowEdgeType.ERROR) return '#dc2626';\n return '#64748b';\n}\n\nfunction getNodeTitle(system: string | null, service: string | null): string | undefined {\n const metadata = [system, service].filter(Boolean).join(' / ');\n return metadata || undefined;\n}\n\nfunction getPolicyLabelParts(label: string): EventFlowNodeData['policyLabelParts'] | undefined {\n const match = label.match(/^\\s*(when)\\s+(.+?)\\s+(do)\\s+(.+)\\s*$/i);\n\n if (!match) {\n return undefined;\n }\n\n return {\n when: match[1].toLowerCase(),\n condition: match[2],\n do: match[3].toLowerCase(),\n action: match[4],\n };\n}\n\nfunction getNodeEndOutcome(node: FlowNode): string[] | null | undefined {\n return node.endOutcome ?? (node as FlowNode & LegacyFlowNodeEndOutcome).endOutcomeLabels;\n}\n\nfunction toEditableReactFlowNodes(\n flowViewModel: FlowViewModel,\n displaySettings?: EventFlowDisplaySettings,\n highlightedNodeIds?: Set<string>\n): {\n nodes: EventFlowReactNode[];\n missingLayoutNodeIds: string[];\n} {\n const missingLayoutNodeIds: string[] = [];\n const shouldHumanizeLabels = displaySettings?.humanizeLabels ?? true;\n\n const nodes = flowViewModel.nodes.flatMap((node) => {\n if (!node.position || !node.dimensions) {\n missingLayoutNodeIds.push(node.id);\n return [];\n }\n\n const renderedDimensions = getRenderedDimensions(node);\n\n const label = shouldHumanizeLabels ? humanizeLabel(node.label) : node.label;\n const endOutcomeLabels = getNodeEndOutcome(node)\n ?.filter((outcomeLabel) => outcomeLabel != null && outcomeLabel.trim().length > 0)\n .map((outcomeLabel) => shouldHumanizeLabels ? humanizeLabel(outcomeLabel) : outcomeLabel);\n\n return [{\n id: node.id,\n type: getNodeType(node.type),\n position: getRenderedPosition(node, renderedDimensions),\n className: highlightedNodeIds?.has(node.id) ? 'eventflow-node-highlighted' : undefined,\n data: {\n label,\n endOutcomeLabels,\n sourceRef: node.sourceRef,\n title: getNodeTitle(node.system, node.service),\n policyLabelParts: node.type === FlowNodeType.POLICY ? getPolicyLabelParts(label) : undefined,\n },\n style: {\n width: renderedDimensions.width,\n height: renderedDimensions.height,\n },\n }];\n });\n\n return { nodes, missingLayoutNodeIds };\n}\n\nfunction getNodeDimensions(node: Node<EventFlowNodeData>, fallback?: Dimensions | null): Dimensions | null {\n const style = node.style as { width?: number | string; height?: number | string } | undefined;\n const width = typeof style?.width === 'number' ? style.width : fallback?.width ?? null;\n const height = typeof style?.height === 'number' ? style.height : fallback?.height ?? null;\n\n if (width === null || height === null) {\n return null;\n }\n\n return { width, height };\n}\n\nfunction getNodeCenter(node: EventFlowReactNode, fallback?: Dimensions | null): Point | null {\n const dimensions = getNodeDimensions(node, fallback);\n\n if (!dimensions) {\n return null;\n }\n\n return {\n x: node.position.x + (dimensions.width / 2),\n y: node.position.y + (dimensions.height / 2),\n };\n}\n\nfunction getOutcomeNodeWidth(label: string): number {\n return Math.min(Math.max((label.length * 7) + 24, OUTCOME_NODE_MIN_WIDTH), OUTCOME_NODE_MAX_WIDTH);\n}\n\nfunction buildEdge(\n id: string,\n source: string,\n target: string,\n edgeType: FlowEdgeType,\n label?: string,\n sourceRef?: SourceRef | null\n): Edge {\n return {\n id,\n source,\n target,\n type: 'causationEdge',\n label: label || undefined,\n data: {\n edgeType,\n sourceRef: sourceRef ?? undefined,\n },\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 18,\n height: 18,\n color: getEdgeMarkerColor(edgeType),\n },\n };\n}\n\nfunction buildSyntheticOutcomeRouting(\n flowViewModel: FlowViewModel,\n realNodes: EventFlowReactNode[],\n displaySettings?: EventFlowDisplaySettings\n): SyntheticOutcomeRouting {\n const realNodeById = new Map(realNodes.map((node) => [node.id, node]));\n const flowNodeById = new Map(flowViewModel.nodes.map((node) => [node.id, node]));\n const shouldHumanizeLabels = displaySettings?.humanizeLabels ?? true;\n const groupedEdges = new Map<string, typeof flowViewModel.edges>();\n\n flowViewModel.edges.forEach((edge) => {\n const outcome = edge.outcome?.trim();\n\n if (!outcome) {\n return;\n }\n\n if (!realNodeById.has(edge.source) || !realNodeById.has(edge.target)) {\n return;\n }\n\n if (flowNodeById.get(edge.source)?.type !== FlowNodeType.COMMAND) {\n return;\n }\n\n const groupKey = `${edge.source}::${outcome}`;\n const existingEdges = groupedEdges.get(groupKey);\n\n if (existingEdges) {\n existingEdges.push(edge);\n return;\n }\n\n groupedEdges.set(groupKey, [edge]);\n });\n\n const syntheticNodes: EventFlowReactNode[] = [];\n const syntheticEdges: Edge[] = [];\n const groupedEdgeIds = new Set<string>();\n\n groupedEdges.forEach((edges, groupKey) => {\n if (edges.length < 2) {\n return;\n }\n\n const sourceNode = realNodeById.get(edges[0].source);\n\n if (!sourceNode) {\n return;\n }\n\n const sourceCenter = getNodeCenter(sourceNode, null);\n\n if (!sourceCenter) {\n return;\n }\n\n const targetNodes = edges\n .map((edge) => realNodeById.get(edge.target))\n .filter((node): node is EventFlowReactNode => Boolean(node));\n\n if (targetNodes.length < 2) {\n return;\n }\n\n const targetCenters = targetNodes\n .map((node) => getNodeCenter(node, null))\n .filter((point): point is Point => Boolean(point));\n\n if (targetCenters.length < 2) {\n return;\n }\n\n const outcome = edges[0].outcome!.trim();\n const label = shouldHumanizeLabels ? humanizeLabel(outcome) : outcome;\n const width = getOutcomeNodeWidth(label);\n const averageTargetCenterX = targetCenters.reduce((sum, point) => sum + point.x, 0) / targetCenters.length;\n const averageTargetCenterY = targetCenters.reduce((sum, point) => sum + point.y, 0) / targetCenters.length;\n const sourceDimensions = getNodeDimensions(sourceNode, null);\n const minTargetLeft = Math.min(...targetNodes.map((node) => node.position.x));\n const minX = sourceDimensions\n ? sourceNode.position.x + sourceDimensions.width + OUTCOME_NODE_MARGIN\n : sourceNode.position.x + OUTCOME_NODE_MARGIN;\n const maxX = minTargetLeft - width - OUTCOME_NODE_MARGIN;\n let x = ((sourceCenter.x + averageTargetCenterX) / 2) - (width / 2);\n\n if (maxX >= minX) {\n x = Math.min(Math.max(x, minX), maxX);\n }\n\n const syntheticNodeId = `synthetic:outcome:${groupKey}`;\n const syntheticNode: EventFlowReactNode = {\n id: syntheticNodeId,\n type: 'outcomeNode',\n position: {\n x,\n y: averageTargetCenterY - (OUTCOME_NODE_HEIGHT / 2),\n },\n draggable: false,\n selectable: false,\n connectable: false,\n data: {\n label,\n synthetic: true,\n },\n style: {\n width,\n height: OUTCOME_NODE_HEIGHT,\n },\n };\n\n syntheticNodes.push(syntheticNode);\n syntheticEdges.push(\n buildEdge(\n `${syntheticNodeId}:in`,\n edges[0].source,\n syntheticNodeId,\n edges[0].type,\n undefined,\n edges[0].sourceRef\n )\n );\n\n edges.forEach((edge) => {\n groupedEdgeIds.add(edge.id);\n syntheticEdges.push(\n buildEdge(\n `${syntheticNodeId}:${edge.id}`,\n syntheticNodeId,\n edge.target,\n edge.type,\n undefined,\n edge.sourceRef\n )\n );\n });\n });\n\n return {\n nodes: syntheticNodes,\n edges: syntheticEdges,\n groupedEdgeIds,\n };\n}\n\nfunction getFlowBounds(nodes: FlowNode[], fallback: FlowBounds | null): FlowBounds | null {\n const positionedNodes = nodes.filter((node) => node.position && node.dimensions);\n\n if (positionedNodes.length === 0) {\n return fallback;\n }\n\n const minX = Math.min(...positionedNodes.map((node) => node.position!.x));\n const minY = Math.min(...positionedNodes.map((node) => node.position!.y));\n const maxX = Math.max(...positionedNodes.map((node) => node.position!.x + node.dimensions!.width));\n const maxY = Math.max(...positionedNodes.map((node) => node.position!.y + node.dimensions!.height));\n\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n };\n}\n\nfunction mergeEditableNodesIntoFlowViewModel(\n flowViewModel: FlowViewModel,\n reactFlowNodes: Node<EventFlowNodeData>[]\n): FlowViewModel {\n const editableNodesById = new Map(reactFlowNodes.map((node) => [node.id, node]));\n\n const nodes = flowViewModel.nodes.map<FlowNode>((node) => {\n const editableNode = editableNodesById.get(node.id);\n\n if (!editableNode) {\n return node;\n }\n\n return {\n ...node,\n position: {\n x: editableNode.position.x,\n y: editableNode.position.y,\n } satisfies Point,\n dimensions: getNodeDimensions(editableNode, node.dimensions),\n };\n });\n\n return {\n ...flowViewModel,\n nodes,\n bounds: getFlowBounds(nodes, flowViewModel.bounds),\n };\n}\n\nexport function EventFlowVisualizer({\n flowViewModel,\n theme = 'light',\n editable = true,\n displaySettings,\n highlightedNodeIds,\n onNodeClick,\n onSelectionChange,\n onFlowViewModelChange,\n}: EventFlowVisualizerProps) {\n const nodeTypes = useMemo(() => ({\n startNode: StartNode,\n commandNode: CommandNode,\n eventNode: EventNode,\n policyNode: PolicyNode,\n endNode: EndNode,\n outcomeNode: OutcomeNode,\n }), []);\n\n const edgeTypes = useMemo(() => ({\n causationEdge: CausationEdge,\n }), []);\n\n const highlightedNodeIdSet = useMemo(\n () => new Set(highlightedNodeIds ?? []),\n [highlightedNodeIds]\n );\n\n const initialNodeState = useMemo(\n () => toEditableReactFlowNodes(flowViewModel, displaySettings, highlightedNodeIdSet),\n [displaySettings, flowViewModel, highlightedNodeIdSet]\n );\n const [nodes, setNodes] = useState<EventFlowReactNode[]>(initialNodeState.nodes);\n const latestFlowViewModelRef = useRef(flowViewModel);\n\n useEffect(() => {\n latestFlowViewModelRef.current = flowViewModel;\n setNodes(initialNodeState.nodes);\n\n if (initialNodeState.missingLayoutNodeIds.length > 0 && import.meta.env.DEV) {\n console.warn(\n '[EventFlowVisualizer] Skipping nodes without layout information:',\n initialNodeState.missingLayoutNodeIds\n );\n }\n }, [flowViewModel, initialNodeState]);\n\n const syntheticOutcomeRouting = useMemo(\n () => buildSyntheticOutcomeRouting(flowViewModel, nodes, displaySettings),\n [displaySettings, flowViewModel, nodes]\n );\n\n const renderNodes = useMemo(\n () => [...nodes, ...syntheticOutcomeRouting.nodes],\n [nodes, syntheticOutcomeRouting.nodes]\n );\n\n const edges = useMemo<Edge[]>(() => {\n const visibleNodeIds = new Set(renderNodes.map((node) => node.id));\n const danglingEdgeIds: string[] = [];\n\n const visibleEdges = flowViewModel.edges.flatMap((edge) => {\n if (syntheticOutcomeRouting.groupedEdgeIds.has(edge.id)) {\n return [];\n }\n\n if (!visibleNodeIds.has(edge.source) || !visibleNodeIds.has(edge.target)) {\n danglingEdgeIds.push(edge.id);\n return [];\n }\n\n const outcomeLabel = edge.outcome?.trim();\n\n return [buildEdge(\n edge.id,\n edge.source,\n edge.target,\n edge.type,\n outcomeLabel || edge.label || undefined,\n edge.sourceRef\n )];\n });\n\n if (danglingEdgeIds.length > 0 && import.meta.env.DEV) {\n console.warn(\n '[EventFlowVisualizer] Skipping dangling edges whose source or target node is missing:',\n danglingEdgeIds\n );\n }\n\n return [...visibleEdges, ...syntheticOutcomeRouting.edges];\n }, [flowViewModel.edges, renderNodes, syntheticOutcomeRouting.edges, syntheticOutcomeRouting.groupedEdgeIds]);\n\n const emitUpdatedFlowViewModel = useCallback((nextNodes: Node<EventFlowNodeData>[]) => {\n if (!onFlowViewModelChange) {\n return;\n }\n\n onFlowViewModelChange(\n mergeEditableNodesIntoFlowViewModel(latestFlowViewModelRef.current, nextNodes)\n );\n }, [onFlowViewModelChange]);\n\n const handleNodesChange = useCallback((changes: NodeChange[]) => {\n setNodes((currentNodes) => {\n const nextNodes = applyNodeChanges(changes, currentNodes);\n return nextNodes;\n });\n }, []);\n\n const handleNodeDragStop = useCallback((\n _event: React.MouseEvent,\n _node: EventFlowReactNode,\n nextNodes: EventFlowReactNode[]\n ) => {\n emitUpdatedFlowViewModel(nextNodes);\n }, [emitUpdatedFlowViewModel]);\n\n const handleNodeClick = useCallback((_event: React.MouseEvent, node: EventFlowReactNode) => {\n if (onNodeClick && !node.data.synthetic && node.data.sourceRef) {\n onNodeClick(node.id, node.data.sourceRef);\n }\n }, [onNodeClick]);\n\n const handleSelectionChange = useCallback(({ nodes, edges }: { nodes: Node[]; edges: Edge[] }) => {\n if (onSelectionChange) {\n onSelectionChange(\n nodes.map((node) => node.id),\n edges.map((edge) => edge.id)\n );\n }\n }, [onSelectionChange]);\n\n return (\n <div className={`eventflow-visualizer theme-${theme}`} style={{ width: '100%', height: '100%' }}>\n <ReactFlow\n nodes={renderNodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n proOptions={{ hideAttribution: true }}\n onNodesChange={handleNodesChange}\n onNodeDragStop={handleNodeDragStop}\n onNodeClick={handleNodeClick}\n onSelectionChange={handleSelectionChange}\n fitView\n nodesDraggable={editable}\n nodesConnectable={false}\n elementsSelectable\n >\n <Background gap={24} color={theme === 'dark' ? '#334155' : '#e2e8f0'} />\n <Controls />\n <MiniMap nodeColor={(node) => getNodeColor(node.type)} />\n </ReactFlow>\n </div>\n );\n}\n\nexport default EventFlowVisualizer;\n","import type { NodeProps } from 'reactflow';\n\nexport interface ServiceGroupNodeData {\n legendLabel: string;\n centerLabel: string;\n centerX?: number;\n centerWidth?: number;\n title?: string;\n}\n\nexport function ServiceGroupNode({ data }: NodeProps<ServiceGroupNodeData>) {\n return (\n <div className=\"service-map-group-node\">\n <div className=\"service-map-group-shell\">\n <div className=\"service-map-group-legend\" title={data.title}>{data.legendLabel}</div>\n <div\n className=\"service-map-group-label\"\n title={data.title}\n style={{\n left: data.centerX,\n width: data.centerWidth,\n }}\n >\n {data.centerLabel}\n </div>\n </div>\n </div>\n );\n}\n","import type { NodeProps } from 'reactflow';\n\nexport interface ServiceMapNodeData {\n label: string;\n title?: string;\n}\n\nexport function ServiceCommandNode({ data }: NodeProps<ServiceMapNodeData>) {\n return (\n <div className=\"service-map-note service-map-note-command\" title={data.title}>\n <strong>{data.label}</strong>\n </div>\n );\n}\n\nexport function ServiceEventNode({ data }: NodeProps<ServiceMapNodeData>) {\n return (\n <div className=\"service-map-note service-map-note-event\" title={data.title}>\n <strong>{data.label}</strong>\n </div>\n );\n}\n","export interface SourceRef {\n file: string;\n line: number;\n column: number;\n}\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Dimensions {\n width: number;\n height: number;\n}\n\nexport interface FlowBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport enum ServiceNodeType {\n COMMAND = 'COMMAND',\n EVENT = 'EVENT',\n}\n\nexport enum Direction {\n LR = 'LR',\n TB = 'TB',\n}\n\nexport interface LayoutMetadata {\n engine: string;\n direction: Direction;\n rankSpacing: number;\n nodeSpacing: number;\n}\n\nexport interface ServiceGroupView {\n id: string;\n label: string;\n path: string;\n position: Point | null;\n dimensions: Dimensions | null;\n}\n\nexport interface ServiceNodeView {\n id: string;\n type: ServiceNodeType;\n label: string;\n groupId: string;\n system: string | null;\n service: string | null;\n servicePath: string | null;\n sourceRef: SourceRef;\n position: Point | null;\n dimensions: Dimensions | null;\n}\n\nexport interface ServiceViewModel {\n schema: string;\n groups: ServiceGroupView[];\n nodes: ServiceNodeView[];\n layout: LayoutMetadata | null;\n bounds: FlowBounds | null;\n}\n\nexport function createServiceViewModel(\n partial: Partial<ServiceViewModel> & {\n groups: ServiceGroupView[];\n nodes: ServiceNodeView[];\n }\n): ServiceViewModel {\n return {\n schema: 'zfl.services.view@1',\n layout: null,\n bounds: null,\n ...partial,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ReactFlow, {\n applyNodeChanges,\n Background,\n Controls,\n Node,\n NodeChange,\n} from 'reactflow';\nimport 'reactflow/dist/style.css';\nimport './styles/eventflow.css';\n\nimport { ServiceGroupNode } from './components/ServiceGroupNode';\nimport { ServiceCommandNode, ServiceEventNode } from './components/ServiceMapNode';\nimport { DiagramDisplaySettings, humanizeLabel } from './labelFormatting';\nimport type {\n Dimensions,\n Point,\n ServiceGroupView,\n ServiceNodeView,\n ServiceViewModel,\n} from './types/ServiceViewModel';\nimport { ServiceNodeType } from './types/ServiceViewModel';\n\nexport interface ServiceMapVisualizerProps {\n serviceViewModel: ServiceViewModel;\n theme?: 'light' | 'dark';\n editable?: boolean;\n displaySettings?: DiagramDisplaySettings;\n onServiceViewModelChange?: (updatedServiceViewModel: ServiceViewModel) => void;\n}\n\ninterface ServiceMapNodeData {\n label: string;\n title?: string;\n}\n\ninterface ServiceGroupNodeData {\n legendLabel: string;\n centerLabel: string;\n centerX?: number;\n centerWidth?: number;\n title?: string;\n}\n\nfunction getNodeTitle(system: string | null, servicePath: string | null): string | undefined {\n const metadata = [system, servicePath].filter(Boolean).join(' / ');\n return metadata || undefined;\n}\n\nfunction getGroupTitle(path: string): string {\n return humanizeLabel(path.replace(/\\//g, ' / '));\n}\n\nfunction getGroupLabels(path: string, shouldHumanizeLabels: boolean): Pick<ServiceGroupNodeData, 'legendLabel' | 'centerLabel'> {\n const segments = path.split('/').filter(Boolean);\n const system = segments[0] ?? 'Unbounded';\n const service = segments[1] ?? system;\n\n return {\n legendLabel: shouldHumanizeLabels ? humanizeLabel(system) : system,\n centerLabel: shouldHumanizeLabels ? humanizeLabel(service) : service,\n };\n}\n\nfunction getCenterLabelLayout(\n group: ServiceGroupView,\n childNodes: ServiceNodeView[]\n): Pick<ServiceGroupNodeData, 'centerX' | 'centerWidth'> {\n const groupWidth = group.dimensions?.width ?? 0;\n const nodesWithBox = childNodes.filter((node) => node.position && node.dimensions);\n\n if (groupWidth <= 0 || nodesWithBox.length === 0) {\n return { centerX: groupWidth / 2, centerWidth: undefined };\n }\n\n const commandNodes = nodesWithBox.filter((node) => node.type === ServiceNodeType.COMMAND);\n const eventNodes = nodesWithBox.filter((node) => node.type === ServiceNodeType.EVENT);\n const leftEdge = commandNodes.length > 0\n ? Math.max(...commandNodes.map((node) => (node.position!.x - (group.position?.x ?? 0)) + node.dimensions!.width))\n : 24;\n const rightEdge = eventNodes.length > 0\n ? Math.min(...eventNodes.map((node) => node.position!.x - (group.position?.x ?? 0)))\n : groupWidth - 24;\n const gapWidth = Math.max(rightEdge - leftEdge, 0);\n const usableWidth = gapWidth > 0 ? Math.max(gapWidth - 20, 120) : Math.min(groupWidth - 48, 196);\n const centerX = gapWidth > 0 ? leftEdge + (gapWidth / 2) : groupWidth / 2;\n\n return {\n centerX,\n centerWidth: Math.min(usableWidth, 220),\n };\n}\n\nfunction getNodeDimensions(node: Node, fallback?: Dimensions | null): Dimensions | null {\n const style = node.style as { width?: number | string; height?: number | string } | undefined;\n const width = typeof style?.width === 'number' ? style.width : fallback?.width ?? null;\n const height = typeof style?.height === 'number' ? style.height : fallback?.height ?? null;\n\n if (width === null || height === null) {\n return null;\n }\n\n return { width, height };\n}\n\nfunction toReactFlowNodes(\n serviceViewModel: ServiceViewModel,\n displaySettings?: DiagramDisplaySettings\n): Node<ServiceMapNodeData | ServiceGroupNodeData>[] {\n const shouldHumanizeLabels = displaySettings?.humanizeLabels ?? true;\n const groupsById = new Map(serviceViewModel.groups.map((group) => [group.id, group]));\n const nodesByGroupId = new Map(serviceViewModel.groups.map((group) => [\n group.id,\n serviceViewModel.nodes.filter((node) => node.groupId === group.id),\n ]));\n\n const groupNodes: Node<ServiceGroupNodeData>[] = serviceViewModel.groups.flatMap((group) => {\n if (!group.position || !group.dimensions) {\n return [];\n }\n\n const labels = getGroupLabels(group.path, shouldHumanizeLabels);\n const centerLayout = getCenterLabelLayout(group, nodesByGroupId.get(group.id) ?? []);\n\n return [{\n id: group.id,\n type: 'serviceGroupNode',\n position: group.position,\n data: {\n legendLabel: labels.legendLabel,\n centerLabel: labels.centerLabel,\n centerX: centerLayout.centerX,\n centerWidth: centerLayout.centerWidth,\n title: shouldHumanizeLabels ? getGroupTitle(group.path) : group.path,\n },\n style: {\n width: group.dimensions.width,\n height: group.dimensions.height,\n },\n }];\n });\n\n const childNodes: Node<ServiceMapNodeData>[] = serviceViewModel.nodes.flatMap((node) => {\n if (!node.position || !node.dimensions) {\n return [];\n }\n\n const group = groupsById.get(node.groupId);\n if (!group?.position) {\n return [];\n }\n\n return [{\n id: node.id,\n type: node.type === ServiceNodeType.COMMAND ? 'serviceCommandNode' : 'serviceEventNode',\n parentNode: node.groupId,\n extent: 'parent',\n position: {\n x: node.position.x - group.position.x,\n y: node.position.y - group.position.y,\n },\n data: {\n label: shouldHumanizeLabels ? humanizeLabel(node.label) : node.label,\n title: getNodeTitle(node.system, node.servicePath),\n },\n style: {\n width: node.dimensions.width,\n height: node.dimensions.height,\n },\n }];\n });\n\n return [...groupNodes, ...childNodes];\n}\n\nfunction mergeNodesIntoServiceViewModel(\n serviceViewModel: ServiceViewModel,\n reactFlowNodes: Node<ServiceMapNodeData | ServiceGroupNodeData>[]\n): ServiceViewModel {\n const groupsById = new Map<string, ServiceGroupView>();\n const childrenById = new Map<string, Node<ServiceMapNodeData | ServiceGroupNodeData>>();\n\n reactFlowNodes.forEach((node) => {\n if (node.id.startsWith('group:')) {\n const existing = serviceViewModel.groups.find((group) => group.id === node.id);\n if (!existing) {\n return;\n }\n\n groupsById.set(node.id, {\n ...existing,\n position: { x: node.position.x, y: node.position.y },\n dimensions: getNodeDimensions(node, existing.dimensions),\n });\n return;\n }\n\n childrenById.set(node.id, node);\n });\n\n const groups = serviceViewModel.groups.map((group) => groupsById.get(group.id) ?? group);\n const groupPositions = new Map(groups.map((group) => [group.id, group.position]));\n\n const nodes = serviceViewModel.nodes.map<ServiceNodeView>((node) => {\n const updated = childrenById.get(node.id);\n if (!updated) {\n return node;\n }\n\n const groupPosition = groupPositions.get(node.groupId);\n const absolutePosition: Point = {\n x: (groupPosition?.x ?? 0) + updated.position.x,\n y: (groupPosition?.y ?? 0) + updated.position.y,\n };\n\n return {\n ...node,\n position: absolutePosition,\n dimensions: getNodeDimensions(updated, node.dimensions),\n };\n });\n\n const positionedGroups = groups.filter((group) => group.position && group.dimensions);\n const bounds = positionedGroups.length === 0 ? serviceViewModel.bounds : {\n x: 0,\n y: 0,\n width: Math.max(...positionedGroups.map((group) => group.position!.x + group.dimensions!.width)),\n height: Math.max(...positionedGroups.map((group) => group.position!.y + group.dimensions!.height)),\n };\n\n return {\n ...serviceViewModel,\n groups,\n nodes,\n bounds,\n };\n}\n\nexport function ServiceMapVisualizer({\n serviceViewModel,\n theme = 'light',\n editable = false,\n displaySettings,\n onServiceViewModelChange,\n}: ServiceMapVisualizerProps) {\n const reactFlowNodes = useMemo(\n () => toReactFlowNodes(serviceViewModel, displaySettings),\n [displaySettings, serviceViewModel]\n );\n const [nodes, setNodes] = useState<Node<ServiceMapNodeData | ServiceGroupNodeData>[]>(reactFlowNodes);\n const latestServiceViewModelRef = useRef(serviceViewModel);\n\n useEffect(() => {\n latestServiceViewModelRef.current = serviceViewModel;\n setNodes(reactFlowNodes);\n }, [reactFlowNodes, serviceViewModel]);\n\n const emitUpdatedServiceViewModel = useCallback((nextNodes: Node<ServiceMapNodeData | ServiceGroupNodeData>[]) => {\n if (!onServiceViewModelChange) {\n return;\n }\n\n onServiceViewModelChange(\n mergeNodesIntoServiceViewModel(latestServiceViewModelRef.current, nextNodes)\n );\n }, [onServiceViewModelChange]);\n\n const onNodesChange = useCallback((changes: NodeChange[]) => {\n setNodes((currentNodes) => {\n const nextNodes = applyNodeChanges(changes, currentNodes);\n emitUpdatedServiceViewModel(nextNodes);\n return nextNodes;\n });\n }, [emitUpdatedServiceViewModel]);\n\n return (\n <div className={`eventflow-visualizer service-map-visualizer ${theme === 'dark' ? 'theme-dark' : ''}`}>\n <ReactFlow\n fitView\n nodes={nodes}\n edges={[]}\n onNodesChange={editable ? onNodesChange : undefined}\n nodeTypes={{\n serviceGroupNode: ServiceGroupNode,\n serviceCommandNode: ServiceCommandNode,\n serviceEventNode: ServiceEventNode,\n }}\n nodesDraggable={editable}\n nodesConnectable={false}\n elementsSelectable={true}\n minZoom={0.15}\n maxZoom={1.5}\n >\n <Background gap={24} size={1} color={theme === 'dark' ? '#334155' : '#d6d3d1'} />\n <Controls showInteractive={false} />\n </ReactFlow>\n </div>\n );\n}\n\nexport default ServiceMapVisualizer;\n"],"names":["CommandNode","data","jsx","Handle","Position","EventNode","PolicyNode","jsxs","StartNode","EndNode","OutcomeNode","FlowNodeType","FlowEdgeType","Direction","createFlowViewModel","partial","getEdgeStroke","edgeType","getEdgeDasharray","CausationEdge","props","edgePath","labelX","labelY","getBezierPath","stroke","dasharray","Fragment","BaseEdge","EdgeLabelRenderer","splitIdentifierWords","value","humanizeLabel","label","segment","humanizeMultilineLabel","line","MIN_NODE_WIDTH","MIN_NODE_HEIGHT","OUTCOME_NODE_HEIGHT","OUTCOME_NODE_MIN_WIDTH","OUTCOME_NODE_MAX_WIDTH","OUTCOME_NODE_MARGIN","getRenderedDimensions","node","baseWidth","baseHeight","getRenderedPosition","renderedDimensions","position","originalDimensions","getNodeType","nodeType","getNodeColor","getEdgeMarkerColor","getNodeTitle","system","service","getPolicyLabelParts","match","getNodeEndOutcome","toEditableReactFlowNodes","flowViewModel","displaySettings","highlightedNodeIds","missingLayoutNodeIds","shouldHumanizeLabels","endOutcomeLabels","outcomeLabel","getNodeDimensions","fallback","style","width","height","getNodeCenter","dimensions","getOutcomeNodeWidth","buildEdge","id","source","target","sourceRef","MarkerType","buildSyntheticOutcomeRouting","realNodes","realNodeById","flowNodeById","groupedEdges","edge","outcome","groupKey","existingEdges","syntheticNodes","syntheticEdges","groupedEdgeIds","edges","sourceNode","sourceCenter","targetNodes","targetCenters","point","averageTargetCenterX","sum","averageTargetCenterY","sourceDimensions","minTargetLeft","minX","maxX","x","syntheticNodeId","syntheticNode","getFlowBounds","nodes","positionedNodes","minY","maxY","mergeEditableNodesIntoFlowViewModel","reactFlowNodes","editableNodesById","editableNode","EventFlowVisualizer","theme","editable","onNodeClick","onSelectionChange","onFlowViewModelChange","nodeTypes","useMemo","edgeTypes","highlightedNodeIdSet","initialNodeState","setNodes","useState","latestFlowViewModelRef","useRef","useEffect","syntheticOutcomeRouting","renderNodes","visibleNodeIds","danglingEdgeIds","emitUpdatedFlowViewModel","useCallback","nextNodes","handleNodesChange","changes","currentNodes","applyNodeChanges","handleNodeDragStop","_event","_node","handleNodeClick","handleSelectionChange","ReactFlow","Background","Controls","MiniMap","ServiceGroupNode","ServiceCommandNode","ServiceEventNode","ServiceNodeType","createServiceViewModel","servicePath","getGroupTitle","path","getGroupLabels","segments","getCenterLabelLayout","group","childNodes","groupWidth","nodesWithBox","commandNodes","eventNodes","leftEdge","rightEdge","gapWidth","usableWidth","toReactFlowNodes","serviceViewModel","groupsById","nodesByGroupId","groupNodes","labels","centerLayout","mergeNodesIntoServiceViewModel","childrenById","existing","groups","groupPositions","updated","groupPosition","absolutePosition","positionedGroups","bounds","ServiceMapVisualizer","onServiceViewModelChange","latestServiceViewModelRef","emitUpdatedServiceViewModel","onNodesChange"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labelFormatting.d.ts","sourceRoot":"","sources":["../src/labelFormatting.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAWD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK5D"}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.react-flow{direction:ltr}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;cursor:-webkit-grab;cursor:grab}.react-flow__pane.selection{cursor:pointer}.react-flow__pane.dragging{cursor:-webkit-grabbing;cursor:grabbing}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow .react-flow__edges{pointer-events:none;overflow:visible}.react-flow__edge-path,.react-flow__connection-path{stroke:#b1b1b7;stroke-width:1;fill:none}.react-flow__edge{pointer-events:visibleStroke;cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;-webkit-animation:dashdraw .5s linear infinite;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;-webkit-animation:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge:focus .react-flow__edge-path,.react-flow__edge:focus-visible .react-flow__edge-path{stroke:#555}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge-textbg{fill:#fff}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;-webkit-animation:dashdraw .5s linear infinite;animation:dashdraw .5s linear infinite}.react-flow__connectionline{z-index:1001}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:-webkit-grab;cursor:grab}.react-flow__node.dragging{cursor:-webkit-grabbing;cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:-webkit-grab;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background:#1a192b;border:1px solid white;border-radius:100%}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:-4px;transform:translate(-50%)}.react-flow__handle-top{left:50%;top:-4px;transform:translate(-50%)}.react-flow__handle-left{top:50%;left:-4px;transform:translateY(-50%)}.react-flow__handle-right{right:-4px;top:50%;transform:translateY(-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.center{left:50%;transform:translate(-50%)}.react-flow__attribution{font-size:10px;background:#ffffff80;padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@-webkit-keyframes dashdraw{0%{stroke-dashoffset:10}}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-default,.react-flow__node-input,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:3px;width:150px;font-size:12px;color:#222;text-align:center;border-width:1px;border-style:solid;border-color:#1a192b;background-color:#fff}.react-flow__node-default.selectable:hover,.react-flow__node-input.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:0 1px 4px 1px #00000014}.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:0 0 0 .5px #1a192b}.react-flow__node-group{background-color:#f0f0f040}.react-flow__nodesselection-rect,.react-flow__selection{background:#0059dc14;border:1px dotted rgba(0,89,220,.8)}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls{box-shadow:0 0 2px 1px #00000014}.react-flow__controls-button{border:none;background:#fefefe;border-bottom:1px solid #eee;box-sizing:content-box;display:flex;justify-content:center;align-items:center;width:16px;height:16px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:5px}.react-flow__controls-button:hover{background:#f4f4f4}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__minimap{background-color:#fff}.react-flow__minimap svg{display:block}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:4px;height:4px;border:1px solid #fff;border-radius:1px;background-color:#3367d9;transform:translate(-50%,-50%)}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:#3367d9;border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.eventflow-visualizer{--eventflow-node-width: 180px;--eventflow-node-height: 124px;--eventflow-policy-node-height: 124px;--eventflow-node-padding-x: 18px;--eventflow-node-padding-y: 22px;width:100%;height:100%;background:radial-gradient(circle at top left,rgba(34,197,94,.08),transparent 22%),radial-gradient(circle at bottom right,rgba(249,115,22,.08),transparent 24%),#fff}.eventflow-visualizer.theme-dark{background:radial-gradient(circle at top left,rgba(34,197,94,.12),transparent 22%),radial-gradient(circle at bottom right,rgba(249,115,22,.12),transparent 24%),#0f172a}.eventflow-start-node-shell,.eventflow-start-node,.eventflow-command-node,.eventflow-event-node,.eventflow-policy-node,.eventflow-end-node{color:#fff;font-family:Georgia,Times New Roman,serif;font-size:18px;font-weight:600;letter-spacing:.01em;box-shadow:0 14px 32px #0f172a24;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease}.eventflow-policy-node{font-size:16px}.eventflow-start-node-shell:hover,.eventflow-start-node:hover,.eventflow-command-node:hover,.eventflow-event-node:hover,.eventflow-policy-node:hover,.eventflow-end-node:hover{transform:translateY(-1px);box-shadow:0 18px 40px #0f172a2e}.eventflow-start-node-shell{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:visible}.eventflow-start-node{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-width:var(--eventflow-node-width);min-height:var(--eventflow-node-height);padding:var(--eventflow-node-padding-y) calc(var(--eventflow-node-padding-x) + 6px);background:linear-gradient(135deg,#374151,#6b7280);border:3px solid #111827;text-align:center;clip-path:polygon(14% 0%,86% 0%,100% 50%,86% 100%,14% 100%,0% 50%);position:relative;z-index:1;color:#f9fafb;box-shadow:0 16px 36px #0f172a2e,0 0 0 4px #0000001a}.eventflow-command-node{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-width:var(--eventflow-node-width);min-height:var(--eventflow-node-height);padding:var(--eventflow-node-padding-y) var(--eventflow-node-padding-x);background:#3b82f6;border:2px solid #1d4ed8;border-radius:14px;text-align:center;position:relative;overflow:visible}.eventflow-event-node{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-width:var(--eventflow-node-width);min-height:var(--eventflow-node-height);padding:var(--eventflow-node-padding-y) var(--eventflow-node-padding-x);background:#f97316;border:2px solid #c2410c;border-radius:999px;text-align:center;position:relative;overflow:visible}.eventflow-policy-node{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-width:var(--eventflow-node-width);min-height:var(--eventflow-policy-node-height);padding:var(--eventflow-node-padding-y) var(--eventflow-node-padding-x);background:#a855f7;border:2px dashed #7e22ce;border-radius:16px;text-align:center;position:relative;overflow:visible}.eventflow-end-node{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-width:var(--eventflow-node-width);min-height:var(--eventflow-node-height);padding:var(--eventflow-node-padding-y) var(--eventflow-node-padding-x);background:#ef4444;border:3px solid #b91c1c;border-radius:12px;text-align:center;position:relative;overflow:visible}.eventflow-outcome-node{display:flex;align-items:center;justify-content:center;width:100%;height:100%;padding:4px 10px;border:1px solid #cbd5e1;border-radius:999px;background:#fffffff5;color:#334155;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:11px;font-weight:600;line-height:1.1;text-align:center;box-shadow:0 2px 8px #0f172a14;cursor:default}.theme-dark .eventflow-outcome-node{background:#e2e8f0f5;color:#0f172a;border-color:#94a3b8}.node-header{display:block;width:100%;max-width:100%;line-height:1.2;white-space:normal;overflow-wrap:anywhere;word-break:break-word;overflow:hidden}.node-header strong{display:block;width:100%}.eventflow-command-node .node-header,.eventflow-event-node .node-header,.eventflow-policy-node .node-header,.eventflow-end-node .node-header{max-height:calc(1.2em * 3)}.eventflow-start-node .node-header{display:block;max-width:128px;font-size:14px;line-height:1.15;max-height:calc(1.15em * 3)}.eventflow-event-node .node-header{max-width:calc(100% - 6px)}.eventflow-policy-node .node-header{max-height:calc(1.1em * 6)}.eventflow-policy-label{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px}.eventflow-policy-keyword{display:block;font-size:10px;font-weight:700;line-height:1;letter-spacing:.08em;font-style:italic;text-transform:none;color:#fde68a;opacity:.95}.eventflow-policy-condition,.eventflow-policy-action{display:block;width:100%;font-size:14px;line-height:1.05;overflow-wrap:anywhere;word-break:break-word}.node-role-badge{padding:2px 8px;border-radius:999px;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase}.node-role-badge-start{position:absolute;top:-34px;left:50%;transform:translate(-50%);background:#f3f4f6;color:#374151;border:3px solid #000000;z-index:3;white-space:nowrap;box-shadow:0 6px 14px #0f172a2e;padding:3px 10px;font-size:11px;letter-spacing:.16em}.node-role-badge-end-outcome{position:absolute;bottom:-18px;right:-6px;background:#f8fafc;color:#334155;border:2px solid #0f172a;z-index:3;white-space:nowrap;box-shadow:0 6px 14px #0f172a2e;padding:3px 10px;font-size:11px;letter-spacing:.02em;text-transform:none;max-width:160px;overflow:hidden;text-overflow:ellipsis}.eventflow-start-node-shell .node-role-badge-end-outcome{bottom:-18px;right:-6px}.theme-dark .node-role-badge-end-outcome{background:#e2e8f0;color:#0f172a;border-color:#0f172a}.eventflow-start-node .react-flow__handle,.eventflow-command-node .react-flow__handle,.eventflow-event-node .react-flow__handle,.eventflow-policy-node .react-flow__handle,.eventflow-end-node .react-flow__handle,.eventflow-outcome-node .react-flow__handle{top:50%}.eventflow-start-node .react-flow__handle-right,.eventflow-command-node .react-flow__handle-right,.eventflow-event-node .react-flow__handle-right,.eventflow-policy-node .react-flow__handle-right,.eventflow-end-node .react-flow__handle-right,.eventflow-outcome-node .react-flow__handle-right{right:0;transform:translate(50%,-50%)}.eventflow-start-node .react-flow__handle-left,.eventflow-command-node .react-flow__handle-left,.eventflow-event-node .react-flow__handle-left,.eventflow-policy-node .react-flow__handle-left,.eventflow-end-node .react-flow__handle-left,.eventflow-outcome-node .react-flow__handle-left{left:0;transform:translate(-50%,-50%)}.eventflow-outcome-node .react-flow__handle{width:8px;height:8px;background:#94a3b8;border:1px solid #ffffff}.eventflow-edge-label{position:absolute;padding:4px 8px;border:1px solid #cbd5e1;border-radius:999px;background:#fffffff5;color:#334155;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:11px;font-weight:600;white-space:nowrap;pointer-events:none}.react-flow__node.eventflow-node-highlighted{filter:drop-shadow(0 0 .75rem rgba(59,130,246,.55));z-index:20}.theme-dark .eventflow-start-node{background:linear-gradient(135deg,#1f2937,#4b5563);border-color:#000;color:#f9fafb;box-shadow:0 18px 40px #02061747,0 0 0 4px #00000024}.theme-dark .eventflow-command-node{background:#2563eb;border-color:#1e40af}.theme-dark .eventflow-event-node{background:#ea580c;border-color:#9a3412}.theme-dark .eventflow-policy-node{background:#9333ea;border-color:#6b21a8}.theme-dark .eventflow-end-node{background:#dc2626;border-color:#991b1b}.theme-dark .eventflow-edge-label{background:#0f172af5;border-color:#334155;color:#e2e8f0}.service-map-visualizer{background:radial-gradient(circle at top left,rgba(14,165,233,.08),transparent 26%),radial-gradient(circle at bottom right,rgba(249,115,22,.08),transparent 22%),linear-gradient(180deg,#f8fafc,#f5f5f4)}.service-map-visualizer.theme-dark{background:radial-gradient(circle at top left,rgba(14,165,233,.12),transparent 26%),radial-gradient(circle at bottom right,rgba(249,115,22,.14),transparent 22%),linear-gradient(180deg,#111827,#0f172a)}.service-map-group-node{width:100%;height:100%}.service-map-group-shell{position:relative;width:100%;height:100%;border:2px dashed rgba(148,163,184,.7);border-radius:28px;background:linear-gradient(180deg,#ffffffdb,#ffffffb8),repeating-linear-gradient(-45deg,#f8fafc8c,#f8fafc8c 12px,#f1f5f98c 12px 24px);box-shadow:0 18px 38px #0f172a14}.service-map-group-label{position:absolute;top:50%;transform:translate(-50%,-50%);padding:24px 22px;min-width:132px;max-width:220px;border-radius:18px;background:linear-gradient(135deg,#f9a8d4f5,#fbcfe8f5);color:#3f3f46;font-family:Georgia,Times New Roman,serif;font-size:19px;line-height:1.08;text-align:center;box-shadow:0 16px 34px #f472b642;z-index:0;opacity:.94;pointer-events:none}.service-map-group-legend{position:absolute;right:22px;bottom:22px;padding:4px 10px;border-radius:999px;background:#ffffffeb;border:1px solid rgba(148,163,184,.75);color:#334155;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;box-shadow:0 6px 14px #0f172a14;pointer-events:none}.service-map-note{display:flex;align-items:center;justify-content:center;width:100%;height:100%;padding:18px;border-radius:10px;color:#0f172a;font-family:Trebuchet MS,Segoe UI,sans-serif;font-size:15px;font-weight:600;line-height:1.2;text-align:center;position:relative;z-index:1;box-shadow:0 12px 22px #0f172a1f,inset 0 1px #fff9}.service-map-note strong{display:block;width:100%;overflow-wrap:anywhere;word-break:break-word}.service-map-note-command{border:1px solid #60a5fa;background:linear-gradient(180deg,#ffffff73,#fff0),#93c5fd}.service-map-note-event{border:1px solid #fb923c;background:linear-gradient(180deg,#ffffff73,#fff0),#fdba74}.theme-dark .service-map-group-shell{border-color:#94a3b88c;background:linear-gradient(180deg,#0f172aeb,#0f172ac2),repeating-linear-gradient(-45deg,#1e293ba6,#1e293ba6 12px,#0f172aa6 12px 24px)}.theme-dark .service-map-group-label{color:#111827}.theme-dark .service-map-group-legend{background:#e2e8f0eb;border-color:#94a3b8b3;color:#0f172a}.theme-dark .service-map-note-command{background:linear-gradient(180deg,#ffffff29,#fff0),#60a5fa}.theme-dark .service-map-note-event{background:linear-gradient(180deg,#ffffff29,#fff0),#fb923c}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces mirroring the JSON serialization of
|
|
3
|
+
* io.zenwave360.language.eventflow.view.FlowViewModel (and its dependencies).
|
|
4
|
+
*
|
|
5
|
+
* No behaviour — structure only. Communication between Kotlin and TypeScript
|
|
6
|
+
* is done by passing JSON objects whose shape is defined here.
|
|
7
|
+
*/
|
|
8
|
+
/** Precise location in a source file. Lines and columns are 1-based. */
|
|
9
|
+
export interface SourceRef {
|
|
10
|
+
file: string;
|
|
11
|
+
line: number;
|
|
12
|
+
column: number;
|
|
13
|
+
}
|
|
14
|
+
/** Semantic type of a node in an event flow. */
|
|
15
|
+
export declare enum FlowNodeType {
|
|
16
|
+
START = "START",
|
|
17
|
+
COMMAND = "COMMAND",
|
|
18
|
+
EVENT = "EVENT",
|
|
19
|
+
POLICY = "POLICY",
|
|
20
|
+
END = "END"
|
|
21
|
+
}
|
|
22
|
+
/** Semantic meaning of a relationship between two flow nodes. */
|
|
23
|
+
export declare enum FlowEdgeType {
|
|
24
|
+
CAUSATION = "CAUSATION",
|
|
25
|
+
CALL = "CALL",
|
|
26
|
+
OUTCOME_HANDLER = "OUTCOME_HANDLER",
|
|
27
|
+
TRIGGER = "TRIGGER",
|
|
28
|
+
CONDITIONAL = "CONDITIONAL",
|
|
29
|
+
ERROR = "ERROR"
|
|
30
|
+
}
|
|
31
|
+
/** Layout direction produced by the layout engine. */
|
|
32
|
+
export declare enum Direction {
|
|
33
|
+
LR = "LR",
|
|
34
|
+
TB = "TB"
|
|
35
|
+
}
|
|
36
|
+
/** Absolute (x, y) position in the canvas. */
|
|
37
|
+
export interface Point {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
}
|
|
41
|
+
/** Width and height of a node. */
|
|
42
|
+
export interface Dimensions {
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
}
|
|
46
|
+
/** Axis-aligned bounding box. */
|
|
47
|
+
export interface FlowBounds {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A node in an event-driven flow.
|
|
55
|
+
*
|
|
56
|
+
* Semantic properties are always present. Layout properties (position,
|
|
57
|
+
* dimensions) are null until the layout engine has been applied.
|
|
58
|
+
*/
|
|
59
|
+
export interface FlowNode {
|
|
60
|
+
id: string;
|
|
61
|
+
type: FlowNodeType;
|
|
62
|
+
label: string;
|
|
63
|
+
endOutcome?: string[] | null;
|
|
64
|
+
system: string | null;
|
|
65
|
+
service: string | null;
|
|
66
|
+
sourceRef: SourceRef;
|
|
67
|
+
/** Null until layout is applied. */
|
|
68
|
+
position: Point | null;
|
|
69
|
+
/** Null until layout is applied. */
|
|
70
|
+
dimensions: Dimensions | null;
|
|
71
|
+
}
|
|
72
|
+
/** Directed relationship between two flow nodes. */
|
|
73
|
+
export interface FlowEdge {
|
|
74
|
+
id: string;
|
|
75
|
+
source: string;
|
|
76
|
+
target: string;
|
|
77
|
+
type: FlowEdgeType;
|
|
78
|
+
outcome: string | null;
|
|
79
|
+
label: string | null;
|
|
80
|
+
sourceRef: SourceRef | null;
|
|
81
|
+
}
|
|
82
|
+
/** Visual grouping of nodes that belong to the same system (swim lane). */
|
|
83
|
+
export interface FlowSystemGroupView {
|
|
84
|
+
systemName: string;
|
|
85
|
+
bounds: FlowBounds;
|
|
86
|
+
}
|
|
87
|
+
/** Metadata describing the algorithm used to position the flow. */
|
|
88
|
+
export interface LayoutMetadata {
|
|
89
|
+
engine: string;
|
|
90
|
+
direction: Direction;
|
|
91
|
+
rankSpacing: number;
|
|
92
|
+
nodeSpacing: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Unified view model for an event-driven flow diagram.
|
|
96
|
+
*
|
|
97
|
+
* Before layout: nodes and edges are populated; layout, bounds, and
|
|
98
|
+
* systemGroups are null.
|
|
99
|
+
* After layout: all fields are populated and every node has position and
|
|
100
|
+
* dimensions set.
|
|
101
|
+
*/
|
|
102
|
+
export interface FlowViewModel {
|
|
103
|
+
/** Schema version, e.g. "zfl.eventflow.view@1". */
|
|
104
|
+
schema: string;
|
|
105
|
+
nodes: FlowNode[];
|
|
106
|
+
edges: FlowEdge[];
|
|
107
|
+
/** Null until layout is applied. */
|
|
108
|
+
layout: LayoutMetadata | null;
|
|
109
|
+
/** Null until layout is applied. */
|
|
110
|
+
bounds: FlowBounds | null;
|
|
111
|
+
/** Null until layout is applied. */
|
|
112
|
+
systemGroups: FlowSystemGroupView[] | null;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=FlowViewModel-updated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlowViewModel-updated.d.ts","sourceRoot":"","sources":["../../src/types/FlowViewModel-updated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD,gDAAgD;AAChD,oBAAY,YAAY;IACtB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,GAAG,QAAQ;CACZ;AAED,iEAAiE;AACjE,oBAAY,YAAY;IACtB,SAAS,cAAc;IACvB,IAAI,SAAS;IACb,eAAe,oBAAoB;IACnC,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;CAChB;AAED,sDAAsD;AACtD,oBAAY,SAAS;IACnB,EAAE,OAAO;IACT,EAAE,OAAO;CACV;AAMD,8CAA8C;AAC9C,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,kCAAkC;AAClC,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iCAAiC;AACjC,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB,oCAAoC;IACpC,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,oCAAoC;IACpC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;CAC/B;AAED,oDAAoD;AACpD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CAC7B;AAED,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,oCAAoC;IACpC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,oCAAoC;IACpC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,oCAAoC;IACpC,YAAY,EAAE,mBAAmB,EAAE,GAAG,IAAI,CAAC;CAC5C"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces mirroring the JSON serialization of
|
|
3
|
+
* io.zenwave360.language.eventflow.view.FlowViewModel.
|
|
4
|
+
*
|
|
5
|
+
* The viewer consumes positioned flow data when layout is available, but the
|
|
6
|
+
* model also allows pre-layout values where position and dimensions are null.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Represents a precise location in a source file.
|
|
10
|
+
* Lines and columns are 1-based.
|
|
11
|
+
*/
|
|
12
|
+
export interface SourceRef {
|
|
13
|
+
file: string;
|
|
14
|
+
line: number;
|
|
15
|
+
column: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Semantic types of nodes in an event flow.
|
|
19
|
+
*/
|
|
20
|
+
export declare enum FlowNodeType {
|
|
21
|
+
START = "START",
|
|
22
|
+
COMMAND = "COMMAND",
|
|
23
|
+
EVENT = "EVENT",
|
|
24
|
+
POLICY = "POLICY",
|
|
25
|
+
END = "END"
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Semantic meaning of a relationship between nodes.
|
|
29
|
+
*/
|
|
30
|
+
export declare enum FlowEdgeType {
|
|
31
|
+
CAUSATION = "CAUSATION",
|
|
32
|
+
CALL = "CALL",
|
|
33
|
+
OUTCOME_HANDLER = "OUTCOME_HANDLER",
|
|
34
|
+
TRIGGER = "TRIGGER",
|
|
35
|
+
CONDITIONAL = "CONDITIONAL",
|
|
36
|
+
ERROR = "ERROR"
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Layout direction produced by the source layout engine.
|
|
40
|
+
*/
|
|
41
|
+
export declare enum Direction {
|
|
42
|
+
LR = "LR",
|
|
43
|
+
TB = "TB"
|
|
44
|
+
}
|
|
45
|
+
export interface Point {
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
}
|
|
49
|
+
export interface Dimensions {
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}
|
|
53
|
+
export interface FlowBounds {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A node in an event-driven flow.
|
|
61
|
+
*
|
|
62
|
+
* Layout properties are null until the layout engine has been applied.
|
|
63
|
+
*/
|
|
64
|
+
export interface FlowNode {
|
|
65
|
+
id: string;
|
|
66
|
+
type: FlowNodeType;
|
|
67
|
+
label: string;
|
|
68
|
+
endOutcome?: string[] | null;
|
|
69
|
+
system: string | null;
|
|
70
|
+
service: string | null;
|
|
71
|
+
sourceRef: SourceRef;
|
|
72
|
+
position: Point | null;
|
|
73
|
+
dimensions: Dimensions | null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Directed relationship between two flow nodes.
|
|
77
|
+
*/
|
|
78
|
+
export interface FlowEdge {
|
|
79
|
+
id: string;
|
|
80
|
+
source: string;
|
|
81
|
+
target: string;
|
|
82
|
+
type: FlowEdgeType;
|
|
83
|
+
outcome: string | null;
|
|
84
|
+
label: string | null;
|
|
85
|
+
sourceRef: SourceRef | null;
|
|
86
|
+
}
|
|
87
|
+
export interface FlowSystemGroupView {
|
|
88
|
+
systemName: string;
|
|
89
|
+
bounds: FlowBounds;
|
|
90
|
+
}
|
|
91
|
+
export interface LayoutMetadata {
|
|
92
|
+
engine: string;
|
|
93
|
+
direction: Direction;
|
|
94
|
+
rankSpacing: number;
|
|
95
|
+
nodeSpacing: number;
|
|
96
|
+
}
|
|
97
|
+
export interface FlowIR {
|
|
98
|
+
nodes: FlowNode[];
|
|
99
|
+
edges: FlowEdge[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Unified view model for an event-driven flow diagram.
|
|
103
|
+
*/
|
|
104
|
+
export interface FlowViewModel {
|
|
105
|
+
schema: string;
|
|
106
|
+
nodes: FlowNode[];
|
|
107
|
+
edges: FlowEdge[];
|
|
108
|
+
layout: LayoutMetadata | null;
|
|
109
|
+
bounds: FlowBounds | null;
|
|
110
|
+
systemGroups: FlowSystemGroupView[] | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Backward-compatible aliases used by the demo and external consumers.
|
|
114
|
+
*/
|
|
115
|
+
export type FlowNodeView = FlowNode;
|
|
116
|
+
export type FlowEdgeView = FlowEdge;
|
|
117
|
+
/**
|
|
118
|
+
* Factory function to create a FlowViewModel with default values.
|
|
119
|
+
*/
|
|
120
|
+
export declare function createFlowViewModel(partial: Partial<FlowViewModel> & {
|
|
121
|
+
nodes: FlowNode[];
|
|
122
|
+
edges: FlowEdge[];
|
|
123
|
+
}): FlowViewModel;
|
|
124
|
+
//# sourceMappingURL=FlowViewModel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlowViewModel.d.ts","sourceRoot":"","sources":["../../src/types/FlowViewModel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface SourceRef {
|
|
2
|
+
file: string;
|
|
3
|
+
line: number;
|
|
4
|
+
column: number;
|
|
5
|
+
}
|
|
6
|
+
export interface Point {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
}
|
|
10
|
+
export interface Dimensions {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}
|
|
14
|
+
export interface FlowBounds {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
}
|
|
20
|
+
export declare enum ServiceNodeType {
|
|
21
|
+
COMMAND = "COMMAND",
|
|
22
|
+
EVENT = "EVENT"
|
|
23
|
+
}
|
|
24
|
+
export declare enum Direction {
|
|
25
|
+
LR = "LR",
|
|
26
|
+
TB = "TB"
|
|
27
|
+
}
|
|
28
|
+
export interface LayoutMetadata {
|
|
29
|
+
engine: string;
|
|
30
|
+
direction: Direction;
|
|
31
|
+
rankSpacing: number;
|
|
32
|
+
nodeSpacing: number;
|
|
33
|
+
}
|
|
34
|
+
export interface ServiceGroupView {
|
|
35
|
+
id: string;
|
|
36
|
+
label: string;
|
|
37
|
+
path: string;
|
|
38
|
+
position: Point | null;
|
|
39
|
+
dimensions: Dimensions | null;
|
|
40
|
+
}
|
|
41
|
+
export interface ServiceNodeView {
|
|
42
|
+
id: string;
|
|
43
|
+
type: ServiceNodeType;
|
|
44
|
+
label: string;
|
|
45
|
+
groupId: string;
|
|
46
|
+
system: string | null;
|
|
47
|
+
service: string | null;
|
|
48
|
+
servicePath: string | null;
|
|
49
|
+
sourceRef: SourceRef;
|
|
50
|
+
position: Point | null;
|
|
51
|
+
dimensions: Dimensions | null;
|
|
52
|
+
}
|
|
53
|
+
export interface ServiceViewModel {
|
|
54
|
+
schema: string;
|
|
55
|
+
groups: ServiceGroupView[];
|
|
56
|
+
nodes: ServiceNodeView[];
|
|
57
|
+
layout: LayoutMetadata | null;
|
|
58
|
+
bounds: FlowBounds | null;
|
|
59
|
+
}
|
|
60
|
+
export declare function createServiceViewModel(partial: Partial<ServiceViewModel> & {
|
|
61
|
+
groups: ServiceGroupView[];
|
|
62
|
+
nodes: ServiceNodeView[];
|
|
63
|
+
}): ServiceViewModel;
|
|
64
|
+
//# sourceMappingURL=ServiceViewModel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceViewModel.d.ts","sourceRoot":"","sources":["../../src/types/ServiceViewModel.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,eAAe;IACzB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,oBAAY,SAAS;IACnB,EAAE,OAAO;IACT,EAAE,OAAO;CACV;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG;IACnC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B,GACA,gBAAgB,CAOlB"}
|