@hemia/workflow-core
v0.0.6
Published
Core del sistema de orquestación de workflows de Hemia. Permite definir, ejecutar y probar flujos personalizados.
Readme
@hemia/workflow-core
@hemia/workflow-core es el núcleo de un sistema de orquestación de flujos (workflows), pensado para ser modular, extensible y fácilmente integrable. Define los tipos, utilidades y herramientas necesarias para ejecutar, probar e interpolar pasos dentro de un workflow.
🚀 Características
- Definición estructurada de workflows y pasos
- Soporte para triggers manuales, por webhook y programados (cron)
- Evaluación dinámica de parámetros mediante expresiones (
jexl) - Utilidades para manejar contexto de ejecución, variables y logs
- Herramientas para pruebas unitarias de nodos
- Mecanismo de salida e interpolación entre pasos
📦 Instalación
npm install @hemia/workflow-core🧩 Estructura de un Workflow
const workflow: Workflow = {
id: 'order-approval',
name: 'Aprobación de Pedido',
trigger: { type: 'manual' },
steps: [
{
id: 'start',
name: 'Inicio',
type: 'noop',
next: [{ id: 'validate' }],
params: {},
},
{
id: 'validate',
name: 'Validar Pedido',
type: 'http',
next: [{ id: 'log' }],
params: {
method: 'POST',
url: 'https://api.example.com/validate',
body: {
orderId: '{{variables.orderId}}'
}
}
},
{
id: 'log',
name: 'Registrar resultado',
type: 'log',
params: {
message: 'Resultado: {{output_validate.status}}'
}
}
],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};⚙️ Tipos clave
Workflow
Define el flujo general, los pasos y cómo se activa (manual, webhook o cron).
WorkflowStep
Cada paso define su tipo, parámetros (params), y los pasos siguientes (next).
ExecutionContext
Contexto disponible durante la ejecución. Permite:
- Guardar y obtener variables
- Registrar logs
- Recuperar resultados (
output_{{stepId}})
🔧 Utilidades principales
📌 interpolate(template, context)
Evalúa expresiones dentro de strings usando {{}} y el contexto de ejecución:
await interpolate('Pedido ID: {{variables.orderId}}', context);🧮 interpolateStepParams(params, context)
Evalúa todos los valores de params dinámicamente:
const resolved = await interpolateStepParams(step.params, context);📤 setOutput(stepId, data, context)
Guarda el resultado de un paso:
setOutput('validate', { status: 'approved' }, context);📥 getOutput(stepId, context)
Obtiene la salida de un paso anterior:
const result = getOutput('validate', context);📚 contextHelpers
Funciones auxiliares para variables y logs:
setVar('foo', 123, context);
const value = getVar('foo', context, 0);
logInfo(context, 'Mensaje informativo');🔧 Interpolación avanzada: ${config.*} y transforms JEXL
El core soporta interpolación de:
- Variables con
{{ ... }}usando JEXL sobrecontext.variables. - Placeholders de configuración
${config.*}en strings. El engine inyectavariables.configdesdeworkflow.config(oworkflow.metadata.config).
Ejemplos:
// String con ${config.*}
const url = "${config.apiUrl}/vacations"; // resuelve desde variables.config.apiUrl
// Expresiones JEXL
"{{ input.employeeId }}"
"{{ output_checkVacationBalance.data.availableDays }}"Transforms de JEXL (funciones en templates con pipe)
Puedes registrar funciones globales para usarlas en templates con la sintaxis de pipe:
import { registerJexlTransforms, addJexlTransform } from '@hemia/workflow-core';
registerJexlTransforms({
getManagerEmail: (employeeId: string) => lookupEmail(employeeId),
generateApprovalUrl: (requestId: string) => `${process.env.APP_URL}/approve/${requestId}`,
});
// O individualmente
addJexlTransform('safeLower', (s: any) => (s ?? '').toString().toLowerCase());Uso en templates:
{
"to": "{{ input.employeeId | getManagerEmail }}",
"approvalUrl": "{{ input.requestId | generateApprovalUrl }}",
"slug": "{{ input.name | safeLower }}"
}Notas:
- Los transforms son globales al proceso y no requieren inyección por ejecución.
- Mantén las funciones puras y rápidas; se ejecutan durante la interpolación.
${config.*}solo resuelve claves bajoconfig.
🧪 Testing
Puedes testear tus nodos individualmente usando testNode:
import { testNode } from '@hemia/workflow-core';
const myNode: WorkflowNode = {
type: 'noop',
async execute(params, context) {
return { success: true, output: { test: true } };
}
};
const { result, context } = await testNode(myNode, { foo: '{{1 + 1}}' });🧱 Extender con nodos personalizados
const CustomNode: WorkflowNode = {
type: 'custom',
async execute(params, context) {
context.log('Ejecutando nodo personalizado');
return { success: true, output: { done: true } };
}
};🧨 Manejo de errores
WorkflowValidationError: estructura inválida del workflowWorkflowExecutionError: error durante la ejecución de un pasoExecutionResult.error: detalles específicos del nodo
🧰 Exports
// Tipos
import { Workflow, WorkflowStep, ExecutionContext, WorkflowNode } from '@hemia/workflow-core';
// Utilidades de interpolación y contexto
import {
interpolate,
interpolateStepParams,
interpolateOutput,
setOutput,
getOutput,
contextHelpers,
testNode,
MockExecutionContext
} from '@hemia/workflow-core';🧰 Utilidades de inspección y evaluación de expresiones
Estas funciones ayudan a detectar y trabajar con expresiones interpoladas y condiciones dentro de los workflows.
Detección de expresiones interpolables
isInterpolatable(value): boolean
Indica si un valor puede contener expresiones interpoladas (string,arrayuobject).isStringInterpolatable(value): boolean
Indica si un string contiene una expresión{{ ... }}.isArrayInterpolatable(value): boolean
Indica si algún elemento de un array es interpolable.isObjectInterpolatable(value): boolean
Indica si algún valor de un objeto es interpolable.isTemplateInterpolatable(template): boolean
Indica si un template (string, array u objeto) es interpolable.isVariableExpression(expression): boolean
Indica si un string es una expresión de variable simple, como{{foo.bar}}.
Ejemplo
isInterpolatable({ foo: '{{bar}}' }); // true
isStringInterpolatable('Hola {{nombre}}'); // true
isArrayInterpolatable(['a', '{{b}}']); // true
isObjectInterpolatable({ a: 1, b: '{{x}}' }); // true
isTemplateInterpolatable(['{{x}}', 2]); // true
isVariableExpression('{{foo.bar}}'); // true
--
🧠 Contribuye
¿Quieres agregar nodos, validaciones o mejoras al motor de ejecución? Este paquete es el corazón del sistema, y puede ser extendido fácilmente.
📄 Licencia
MIT © Hemia Technologies
