UNPKG

@fluxo-engine/core

Version:

fluxo workflow engine core

3 lines (2 loc) 11.7 kB
"use strict";let e=!1;function t(t){return function(...o){if(e)return console.log(t?[t]:[],...o)}}var o,n=((o={})[o.DEFAULT=0]="DEFAULT",o[o.LOOP=1]="LOOP",o[o.BRANCH=2]="BRANCH",o[o.WAIT=3]="WAIT",o);function r(e,t){let o=t.find((t=>t.type===e.type));return o?.behavior===n.LOOP}function i(e,t=[]){return t.length?`${e.id}_${t.join("_")}`:e.id}let d=t("Node");function a(e){let{currentNode:t,sortedNodes:o,nodeIndexMap:r,executedNodeOutputs:a,iterationContext:u,executorByType:s}={currentNode:e.node,...e},l=u?.at(-1),c=i(t,u);if(void 0!==l&&a.get(`branchCompleted_${c}`)?.completed)return void d(`getNextNode: branch already completed for node "${t.id}" in iteration ${l}`);if(void 0!==l&&a.get(`${t.id}_${l}`)?.branchHandled)return void d(`getNextNode: node "${t.id}" already handled (branchHandled) in iteration ${l}`);let p=s.get(t.type),g=a.get(t.id);if(p&&(p.behavior===n.BRANCH||p.behavior===n.LOOP)||g&&!0===g?.executedBranch)d(`getNextNode: current node "${t.id}" is branch/loop or marked executedBranch`);else{for(let e=r.get(t.id)+1;e<o.length;e++){let t=o[e],n=a.get(t.id);if(void 0===n||!0!==n.skipped){if(void 0!==l&&a.get(`${t.id}_${l}`)?.branchHandled)d(`getNextNode: node "${t.id}" is branchHandled for iteration ${l}, ignoring.`);else if(void 0===n)return d(`getNextNode: next candidate node found: "${t.id}"`),t}else d(`getNextNode: node "${t.id}" is marked as skipped, ignoring.`)}d(`getNextNode: no next candidate found after "${t.id}"`)}}function u({loopNode:e,sortedNodes:t,executors:o=[],outputEdgesMap:n,nodeIndexMap:i}){let d=[e],a=new Set,u=[];return function e(s){for(let l of(a.add(s.id),n.get(s.id)??[])){let n=t[i.get(l.target)];!n||a.has(n.id)||(d.push(n),r(n,o)||(e(n),u.push(n)))}}(e),d.sort(((e,t)=>i.get(e.id)-i.get(t.id))),{subFlowNodes:d,resumeNodes:u}}var s,l,c=((s={}).STRING="STRING",s.NUMBER="NUMBER",s.BOOLEAN="BOOLEAN",s.ARRAY="ARRAY",s.OBJECT="OBJECT",s.OBJECT_ARRAY="OBJECT_ARRAY",s);class p extends Error{constructor(e){super("FLOW_WAIT"),this.snapshot=e}}var g=((l={})[l.COMPLETED=0]="COMPLETED",l[l.WAITING=1]="WAITING",l);function f(e){return null!=e?.branch}function x({node:e,inputEdgesMap:t,executedNodeOutputs:o,iteration:n}){let r=t.get(e.id)??[],i={};for(let e of r){let t=o.get(e.source),r=Array.isArray(t)?n??t.length-1:void 0,d=function({aggregatedOutput:e,sourceValue:t,iteration:o}){if(Array.isArray(e)){let n=void 0!==o&&o<e.length?o:e.length-1;return e[n]?.[t||""]??null}return e?.[t||""]}({aggregatedOutput:t,sourceValue:e?.sourceValue,iteration:r});if(void 0===d)throw Error(`No output for ${e.source} (iter=${n}) key="${e.sourceValue}"`);i[e.targetValue||""]=d}return function(e){return 0===Object.keys(e).length}(i)?e.defaultInput||{}:i}function h(e){return Object.fromEntries(e)}let N=t("LoopNode"),y=t("WaitNode");async function O(e,t){let{node:o,inputEdgesMap:n,executor:r,executedNodeOutputs:i,initialNodeIds:d,iterationContext:u=[],key:s}=e;try{let l=x({node:o,inputEdgesMap:n,executedNodeOutputs:i,iteration:u.at(-1)}),c=await r.execute(l,o.data,{});i.set(s,c);let p=a(e);return p&&!d.includes(p.id)&&await t({...e,node:p}),c}catch(t){if(t instanceof p){let t={executedNodeOutputs:h(i),pending:[{nodeId:o.id,iteration:[...e.iterationContext||[]]}]};throw y("[DEBUG WAIT] gerando snapshot de pausa:",JSON.stringify(t,null,2)),new p(t)}throw t}}let E=t("Node");function $(e){return!!e&&"object"==typeof e&&!0===e.skipped}async function w(e){let{node:t,executedNodeOutputs:o,iterationContext:r=[],executorByType:d}=e,s=d.get(t.type);if(!s)throw Error(`No executor for ${t.type}`);E(`executing ${t.id}`,r);let l=i(t,r);if(s.behavior!==n.LOOP&&($(o.get(t.id))||$(o.get(l)))||e.edges.filter((e=>e.target===t.id)).some((e=>{let t=o.get(e.source),n=r.length>0?`${e.source}_${r.at(-1)}`:null;return $((n?o.get(n):void 0)??t)})))o.set(l,{skipped:!0});else{if(o.has(l)){if(s.behavior!==n.LOOP)return E(`Skipping ${l}`),o.get(l);{let e=o.get(`${t.id}_loopCompleted`);if(r.length>0)return E(`Skipping ${l} (loop iteration already done)`),o.get(l);if(e)return E(`Skipping ${l} (loop completed)`),o.get(l)}}if(s.behavior!==n.WAIT)return s.behavior===n.BRANCH?async function(e,t){let o,{node:n,edges:r,inputEdgesMap:d,currentExecutor:a,sortedNodes:u,executedNodeOutputs:s,iterationContext:l=[],branchEdgesMap:c}=e,p=c.get(n.id)??[],g=l.at(-1),h=x({node:n,inputEdgesMap:d,executedNodeOutputs:s,iteration:g});if("string"==typeof h.num0){let e=r.find((e=>f(e)&&e.source===n.id&&e.branch===a.getTrueKey()));if(!e)throw Error(`No true-branch edge found for node "${n.id}"`);let t=u.find((t=>t.id===e.target)).data.defaultValue;o=h.num0===t}else o=await a.executeBranch(h,n.data);let N=o?a.getTrueKey():a.getFalseKey(),y=p.find((e=>e.branch===N)),O=i(n,l);if(!y){for(let e of(s.set(O,{result:o,executedBranch:!0}),p)){let t=void 0!==g?`${e.target}_${g}`:e.target;s.set(t,{skipped:!0})}return o}let E=u.find((e=>e.id===y.target)),$={result:o,executedBranch:!0};for(let e of(void 0!==g?s.set(`${n.id}_${g}`,$):s.set(n.id,$),p))if(e.branch!==N){let t=void 0!==g?`${e.target}_${g}`:e.target;s.set(t,{skipped:!0})}return await t({...e,node:E}),o}({...e,currentExecutor:s},w):s.behavior===n.LOOP?async function(e,t){let{node:o,inputEdgesMap:n,currentExecutor:r,sortedNodes:d,executedNodeOutputs:s,iterationContext:l=[],executors:c,outputEdgesMap:g,nodeIndexMap:f}=e,y=`[LOOP ${o.id}]`,O=i(o,l),E=`${O}_loopCompleted`,$=e=>`${O}_${e}`,w=e=>`${O}_${e}_done`;if(s.has(E)){N(`${y} already completed`);let n=a({...e,node:o,iterationContext:l});return n&&await t({...e,node:n,iterationContext:l}),s.get(o.id)}let C=x({node:o,inputEdgesMap:n,executedNodeOutputs:s,iteration:l.at(-1)}),A=await r.getArray(C,o.data,l.at(-1));if(!Array.isArray(A))throw Error("Loop must return an array");s.set(o.id,A),N(`${y} array len ${A.length}`);let I=[],{subFlowNodes:M}=u({loopNode:o,sortedNodes:d,executors:c,outputEdgesMap:g,nodeIndexMap:f}),m=new Set(M.map((e=>e.id)));m.delete(o.id);let v=d.filter((e=>m.has(e.id)));N(`${y} body nodes:`,v.map((e=>e.id)));for(let o=0;o<A.length;o++){if(b=o,s.has(w(b))){N(`${y} iter ${o} already done, skipping`);continue}let n=[...l,o];s.set($(o),A[o]),N(`${y} iter ${o} start`);let r=!1;for(let o of v)try{await t({...e,node:o,iterationContext:n})}catch(e){if(e instanceof p){I.push({nodeId:o.id,iteration:n}),r=!0;break}throw e}!r&&(N(`${y} iter ${o} done`),s.set(w(o),!0))}var b;if(I.length>0){let e={executedNodeOutputs:h(s),pending:I};throw N(`${y} accumulated pending:`,JSON.stringify(I,null,2)),new p(e)}return s.set(E,!0),N(`${y} all iterations done — exiting loop`),A}({...e,currentExecutor:s},w):async function(e,t){let o,{node:n,inputEdgesMap:r,currentExecutor:d,executedNodeOutputs:u,initialNodeIds:s,iterationContext:l=[]}=e,c=l.at(-1);for(let e of r.get(n.id)??[]){let t=u.get(e.source);if(Array.isArray(t)){o=t.length;break}}if(void 0!==o&&void 0===c){let c=[];for(let e=0;e<o;e++){let t=x({node:n,inputEdgesMap:r,executedNodeOutputs:u,iteration:e}),o=await d.execute(t,n.data);c.push(o),u.set(i(n,[...l,e]),o)}u.set(n.id,c);let p=a({...e,node:n,iterationContext:l});return p&&!s.includes(p.id)&&await t({...e,node:p}),c}let p=x({node:n,inputEdgesMap:r,executedNodeOutputs:u,iteration:c}),g=await d.execute(p,n.data);if(void 0!==c){u.set(i(n,l),g);let e=Array.isArray(u.get(n.id))?[...u.get(n.id)]:[];e.push(g),u.set(n.id,e)}else u.set(n.id,g);let f=a({...e,node:n,iterationContext:l});return void 0===c&&f&&!s.includes(f.id)&&await t({...e,node:f}),g}({...e,currentExecutor:s},w);try{await O({...e,executor:s,key:l},w)}catch(e){throw e}}}let C=t("FlowHandler");async function A(e,t,o,n,r){try{return await async function({nodes:e,edges:t,executors:o,executedNodeOutputs:n,initialNodeIds:r,executionContextCache:i}){C("nodes",e),C("edges",t);let d=new Map(e.map((e=>[e.id,e]))),a=r??function(e,t){return e.filter((e=>!t.some((t=>t.target===e.id)))).map((e=>e.id))}(i?.sortedNodes,t);for(let e of(C("sortedNodes",i?.sortedNodes),C("initialNodeIds",a),a)){let r=d.get(e);await w({node:r,edges:t,executors:o,executedNodeOutputs:n,initialNodeIds:a,iterationContext:[],...i})}}({executors:e,nodes:t,edges:o,executedNodeOutputs:n,executionContextCache:r}),{status:g.COMPLETED,snapshot:null}}catch(e){if(e instanceof p)return{status:g.WAITING,snapshot:e.snapshot??{executedNodeOutputs:{},pending:[]}};throw e}}async function I({nodes:e,edges:t,executors:o,executedNodeOutputs:r,executionContextCache:i,resumeEntries:d,snapshot:u}){let s=new Map(e.map((e=>[e.id,e])));for(let e of d){let{nodeId:t,iterationContext:o=[],resumeData:d}=e,a=s.get(t),u=i.executorByType.get(a.type),l=o.length?`${t}_${o.join("_")}`:t;if(u.behavior===n.WAIT){let e,n=x({node:a,inputEdgesMap:i.inputEdgesMap,executedNodeOutputs:r,iteration:o.at(-1)});try{e=await u.execute(n,a.data,d)}catch(t){if(!(t instanceof p))throw t;e=n}if(r.set(l,e),o.length){let n=r.get(t),i=Array.isArray(n)?n:[];i[o.at(-1)]=e,r.set(t,i)}}}let l=new Set(d.map((e=>`${e.nodeId}|${e.iterationContext?.join(",")}`)));for(let{nodeId:e,iterationContext:n}of d){let d=a({node:s.get(e),edges:t,executors:o,executedNodeOutputs:r,initialNodeIds:[],iterationContext:n,...i});d&&await w({node:d,edges:t,executors:o,executedNodeOutputs:r,initialNodeIds:[],iterationContext:n,...i})}let c=u.pending.filter((e=>!l.has(`${e.nodeId}|${e.iteration.join(",")}`)));return c.length>0?{status:g.WAITING,snapshot:{executedNodeOutputs:h(r),pending:c}}:{status:g.COMPLETED,snapshot:null}}function M({nodes:e,edges:t,executors:o}){let n=function(e,t,o){let n=function(e,t,o=[]){let n={},i={};e.forEach((e=>{n[e.id]=[],i[e.id]=0})),t.forEach((e=>{n[e.source].push(e.target),i[e.target]+=1}));let d=new Set;for(let t of e)r(t,o)&&d.add(t.id);let a=(e,t)=>{let o=d.has(e);return o===d.has(t)?0:o?1:-1},u=e.filter((e=>0===i[e.id])).map((e=>e.id)).sort(a),s=[];for(;u.length>0;){let e=u.shift();for(let t of(s.push(e),n[e]))i[t]-=1,0===i[t]&&u.push(t);u.sort(a)}if(s.length!==e.length)throw Error("Graph contains cycles!");return s}(e,t,o),i=new Map(e.map((e=>[e.id,e])));return n.map((e=>i.get(e))).filter(Boolean)}(e,t,o),i=new Map(n.map(((e,t)=>[e.id,t]))),d=new Map(o?.map((e=>[e.type,e]))),a=new Map;for(let e of t)if(!f(e)){let t=a.get(e.target)??[];t.push(e),a.set(e.target,t)}let u=new Map,s=new Map;for(let e of t)if(f(e)){let t=s.get(e.source)??[];t.push(e),s.set(e.source,t)}else{let t=u.get(e.source)??[];t.push(e),u.set(e.source,t)}return{executorByType:d,inputEdgesMap:a,nodeIndexMap:i,sortedNodes:n,outputEdgesMap:u,branchEdgesMap:s}}exports.ExecutorBehavior=n,exports.FlowExecutionStatus=g,exports.ValueTypes=c,exports.WaitExecutor=class{stopExecution(){throw new p}constructor(){this.behavior=n.WAIT}},exports.executeFlow=A,exports.getFlowHandler=function({executors:t,enableLogger:o=!1}){return function(t){e=t}(o),{execute:async function({nodes:e,edges:o}){let n=new Map,r=M({nodes:e,edges:o,executors:t});return A(t,e,o,n,r)},resume:async function({nodes:e,edges:o,snapshot:n,resolved:r}){let i=function(e){return new Map(Object.entries(e))}(n.executedNodeOutputs),d=function({resolved:e,snapshot:t}){return e.map((({nodeId:e,iterationContext:o,resumeData:n})=>{let r=Array.isArray(o)?o:[];if(0===r.length){let o=t.pending.findIndex((t=>t.nodeId===e));o>=0&&(r=t.pending[o].iteration,t.pending.splice(o,1))}else{let o=t.pending.findIndex((t=>t.nodeId===e&&function(e,t){if(e.length!==t.length)return!1;for(let o=0;o<e.length;o++)if(e[o]!==t[o])return!1;return!0}(t.iteration,r)));o>=0&&t.pending.splice(o,1)}return{nodeId:e,iterationContext:r,resumeData:n}}))}({resolved:r,snapshot:n}),a=M({nodes:e,edges:o,executors:t});return I({nodes:e,edges:o,snapshot:n,executors:t,executionContextCache:a,executedNodeOutputs:i,resumeEntries:d})}}},exports.getSubFlow=u,exports.resumeFlow=I; //# sourceMappingURL=index.js.map