Jaraxa — Librería Visual de Flow Orchestration¶
Tipo: Arquitectura de Librería
Audiencia: Equipo de Desarrollo
Fecha: 25 de marzo de 2026
Estado: 🟡 En diseño
1. Qué es Jaraxa¶
Una librería npm frontend interna que abstrae React Flow (@xyflow/react) en una capa de alto nivel para "pintar flujos". Proporciona todas las primitivas visuales, tipos de nodos, conectores, canvas interactivo y monitor de ejecución.
[!IMPORTANT] Jaraxa es una librería interna (IP propia), no se publica al mundo. Se distribuye como dependencia local (
npm linko npm workspaces) entre los proyectos que la consumen (DKV Pet Flows, IEO).
Stack frontend unificado: ambos proyectos usan React — esto es un hecho, no una propuesta.
2. Alcance (solo frontend)¶
| EN Jaraxa | FUERA de Jaraxa |
|---|---|
| Canvas React Flow (zoom, pan, minimap, grid) | Backend Quarkus / Dapr |
| Todos los tipos de nodos visuales (primitivas) | Lógica de ejecución de nodos |
| Sistema de conectores / aristas | Base de datos / persistencia |
| Panel de configuración de nodos (framework) | APIs REST específicas |
| Monitor de ejecución (UI) | Theming de marca (DKV / IEO) |
| Serialización visual del grafo (JSON) | Nodos de dominio específico |
| Drag & drop, validación de puertos | Autenticación / RBAC |
| Sistema de iconos 3 capas (L1/L2/L3) | Iconos de dominio (L3 → paquete aparte) |
| Conexión por proximidad (Proximity Connect) | — |
| Menú contextual (edge, nodo, canvas) | — |
3. Estructura de Paquetes¶
workspace.jaraxa/
├── package.json # @jaraxa scope, npm workspaces
├── packages/
│ ├── flow-canvas/ # @jaraxa/flow-canvas
│ │ └── src/
│ │ ├── FlowCanvas.tsx # ReactFlow wrapper, canvas, minimap, controls
│ │ ├── useProximityLink.ts # Hook de conexión por proximidad
│ │ ├── useContextMenu.ts # Hook de menú contextual
│ │ └── index.ts
│ ├── flow-nodes/ # @jaraxa/flow-nodes
│ │ └── src/
│ │ ├── primitives/ # Trigger, Action, Wait, Condition, Branch, etc.
│ │ ├── IconRegistry.ts # Resolución L1 → L2 → L3
│ │ └── index.ts
│ ├── flow-edges/ # @jaraxa/flow-edges
│ │ └── src/ # Tipos de arista: default, animated, conditional, filtered
│ ├── flow-config/ # @jaraxa/flow-config
│ │ └── src/ # Panel lateral de configuración de nodos (slideover)
│ ├── flow-monitor/ # @jaraxa/flow-monitor
│ │ └── src/ # Consola de ejecución, trazas, timeline
│ └── flow-icons/ # @jaraxa/flow-icons
│ └── src/ # Iconos base L1 (lucide) + L2 (categoría)
└── README.md
4. Cómo se Consume¶
// En dkv-pet-flows-admin o ieo/apps/web
import { FlowCanvas, useFlowStore } from '@jaraxa/flow-canvas';
import { TriggerNode, WaitNode, ActionNode } from '@jaraxa/flow-nodes';
import { ConfigPanel } from '@jaraxa/flow-config';
import { ExecutionMonitor } from '@jaraxa/flow-monitor';
import { registerDomainPack } from '@jaraxa/flow-icons';
// Cada proyecto registra sus nodos de dominio
const dkvNodeTypes = {
trigger: TriggerNode,
wait: WaitNode,
action: ActionNode,
pushNotification: DkvPushNode, // DKV-específico
notificareSync: DkvNotificareNode, // DKV-específico
};
// Registrar pack de iconos de dominio
registerDomainPack(petHealthPack);
<FlowCanvas nodeTypes={dkvNodeTypes} theme={dkvTheme} />
5. Proximity Connect — API de React Flow¶
React Flow tiene un ejemplo oficial de Proximity Connect:
| API | Rol |
|---|---|
onNodeDrag |
Callback continuo durante drag; recibe evento + nodo |
getIntersectingNodes |
Utilidad de useReactFlow() que detecta nodos intersectando un área |
onNodeDragStop |
Momento de crear el edge si proximidad se mantiene |
addEdge |
Función de utilidad para añadir edge al estado |
MIN_DISTANCE |
Constante: distancia euclídea mínima para conectar |
Implementación en Jaraxa: Hook useProximityLink en @jaraxa/flow-canvas:
// @jaraxa/flow-canvas/src/useProximityLink.ts
export function useProximityLink(threshold = 120) {
const { getIntersectingNodes } = useReactFlow();
const onNodeDrag = useCallback((event, node) => {
const intersecting = getIntersectingNodes(node, { partially: true });
// Mostrar ghost-edge animado hacia el nodo más cercano
// Calcular distancia euclídea y comparar con threshold
}, [getIntersectingNodes, threshold]);
const onNodeDragStop = useCallback((event, node) => {
// Si distancia < threshold → addEdge()
}, [threshold]);
return { onNodeDrag, onNodeDragStop };
}
[!WARNING] El parámetro
nodeenonNodeDragpuede tener la posición ligeramente desfasada respecto a la visual durante el drag. Usar coordenadas del evento para precisión.
6. Sistema de Iconos — 3 Capas¶
┌──────────────────────────────────────────────────────────┐
│ L3: ICONOS DE DOMINIO (Vertical-Specific) │
│ "Pet Health", "Telemedicina", "Oceanografía" │
│ → Se cargan dinámicamente según el proyecto │
├──────────────────────────────────────────────────────────┤
│ L2: ICONOS DE CATEGORÍA (Node Type) │
│ Triggers ⚡ · Lógica 🔀 · Acciones ▶️ · IA 🧠 · Datos 🗄️ │
│ → Fijos, parte del core de @jaraxa/flow-icons │
├──────────────────────────────────────────────────────────┤
│ L1: ICONOS DE SISTEMA (UI Chrome) │
│ Play, Stop, Zoom, Settings, Menu... │
│ → lucide-react (framework UI genérico) │
└──────────────────────────────────────────────────────────┘
Interface DomainIconPack¶
interface DomainIconPack {
id: string; // "pet-health", "oceanography"
name: string; // "DKV Pet Health"
version: string; // semver
icons: Record<string, React.ComponentType<IconProps>>;
nodeIconMap: Record<string, string>; // nodeType → iconKey
}
Resolución de icono¶
1. ¿Tiene icono en DomainIconPack? → Usar L3
2. ¿No? → Usar icono de categoría L2
3. ¿Ni L2? → Fallback a lucide L1
Distribución npm (interna)¶
- Formato principal: React Components vía SVGR
"sideEffects": falseenpackage.json- ESM obligatorio, nunca CommonJS
- SVGR con
viewBoxpreservado,width/heightremovidos - Un componente por archivo
Fuentes de iconos de dominio¶
| Dominio | Fuente | Cantidad | Licencia |
|---|---|---|---|
| Salud general | Health Icons | 2.024 iconos | MIT |
| Veterinaria | SVG Repo + The Noun Project | 50–1.720 | MIT/CC |
| Oceanografía | IconScout | 49 iconos (6 estilos) | Royalty-free |
7. Menú Contextual¶
Sobre conexión (edge)¶
| Opción | Descripción | Prioridad |
|---|---|---|
| Configurar filtro | Añade condición al edge | 🔴 P0 |
| Desconectar | Elimina la conexión | 🔴 P0 |
| Seleccionar rama completa | Selecciona subárbol downstream | 🔴 P0 |
| Insertar bifurcación | Inserta router entre nodos | 🟡 P1 |
| Insertar bloque | Inserta nodo entre los conectados | 🟡 P1 |
| Añadir nota | Comentario visual al edge | 🟢 P2 |
Sobre nodo¶
| Opción | Prioridad |
|---|---|
| Configurar, Duplicar, Eliminar | 🔴 P0 |
| Renombrar, Copiar config, Desactivar, Ver logs | 🟡 P1 |
Sobre canvas (vacío)¶
| Opción | Prioridad |
|---|---|
| Pegar nodo, Zoom to fit | 🔴 P0 |
| Añadir nota, Seleccionar todo | 🟡 P1 |
8. Fases de Desarrollo¶
Fase 1 — Primitivas (Sprint 0 + 1A)¶
- [ ] Inicializar workspace con npm workspaces
- [ ]
@jaraxa/flow-canvas: ReactFlow wrapper con grid, zoom, minimap, proximity connect - [ ]
@jaraxa/flow-nodes: 8 tipos base del catálogo funcional - [ ]
@jaraxa/flow-icons: Iconos L1 (lucide) + L2 (5 categorías) - [ ] Consumir desde
dkv-pet-flows-adminvíanpm link
Fase 2 — Interactividad¶
- [ ]
@jaraxa/flow-edges: aristas animadas, condicionales, con filtro visual - [ ]
@jaraxa/flow-config: panel de configuración genérico (slideover) - [ ] Menú contextual (edge, nodo, canvas)
- [ ] Drag & drop desde catálogo al canvas
- [ ] Serialización/deserialización JSON del grafo
Fase 3 — Monitorización¶
- [ ]
@jaraxa/flow-monitor: consola de ejecución con SSE - [ ] Timeline visual de nodos ejecutados
- [ ] Consumir desde
workspace.ieo/apps/web
Fase 4 — Domain Packs¶
- [ ] Crear
@dkv/flow-icons(pack Pet Health: vacunación, consulta, póliza, etc.) - [ ] Crear
@ieo/flow-icons(pack Oceanografía: boya, satélite, muestra, etc.) - [ ] Documentar cómo crear un
DomainIconPackcustom
Documentos Relacionados¶
| Nivel | Documento | Descripción |
|---|---|---|
| Especificación | Flow Builder | Requisitos técnicos del editor visual |
| Negocio | Catálogo de Funcionalidades | Descripción funcional para DKV |
| Arquitectura | Arquitectura del Sistema | Diseño técnico (Dapr, Quarkus) |