@@ -27,17 +27,6 @@ const catchReference = '/catch';
2727const branchReference = '/fork/branches' ;
2828const tryReference = '/try' ;
2929
30- /**
31- * Represents a generic within a graph.
32- * This serves as a base type for nodes, edges, and graphs.
33- */
34- export type GraphElement = {
35- /** A unique identifier for this graph element. */
36- id : string ;
37- /** An optional label to provide additional context or naming. */
38- label ?: string ;
39- } ;
40-
4130/**
4231 * Enumeration of possible node types in a graph.
4332 */
@@ -63,6 +52,17 @@ export enum GraphNodeType {
6352 Wait = 'wait' ,
6453}
6554
55+ /**
56+ * Represents a generic within a graph.
57+ * This serves as a base type for nodes, edges, and graphs.
58+ */
59+ export type GraphElement = {
60+ /** A unique identifier for this graph element. */
61+ id : string ;
62+ /** An optional label to provide additional context or naming. */
63+ label ?: string ;
64+ } ;
65+
6666/**
6767 * Represents a node within the graph.
6868 */
@@ -75,6 +75,14 @@ export type GraphNode = GraphElement & {
7575 task ?: Task ;
7676} ;
7777
78+ /**
79+ * Represents a flattened node within the graph.
80+ */
81+ export type FlatGraphNode = Omit < GraphNode , 'parent' > & {
82+ /** The id of parent graph, if any. */
83+ parentId ?: string ;
84+ } ;
85+
7886/**
7987 * Represents a directed edge connecting two nodes in the graph.
8088 */
@@ -90,7 +98,21 @@ export type GraphEdge = GraphElement & {
9098 */
9199export type Graph = GraphNode & {
92100 /** A collection of nodes that belong to this graph. */
93- nodes : GraphNode [ ] ;
101+ nodes : Array < Graph | GraphNode > ;
102+ /** A collection of edges that define relationships between nodes. */
103+ edges : GraphEdge [ ] ;
104+ /** The entry node of the graph, if any. */
105+ entryNode ?: GraphNode ;
106+ /** The exit node of the graph, if any. */
107+ exitNode ?: GraphNode ;
108+ } ;
109+
110+ /**
111+ * Represents a flattened graph.
112+ */
113+ export type FlatGraph = FlatGraphNode & {
114+ /** A collection of nodes that belong to this graph. */
115+ nodes : FlatGraphNode [ ] ;
94116 /** A collection of edges that define relationships between nodes. */
95117 edges : GraphEdge [ ] ;
96118 /** The entry node of the graph, if any. */
@@ -226,6 +248,7 @@ function getNextTask(
226248 let index : number = 0 ;
227249 if ( transition && transition != FlowDirective . Continue ) {
228250 index = Array . from ( tasksList . keys ( ) ) . indexOf ( transition ) ;
251+ if ( index === - 1 ) throw new Error ( `Unable to find task to transition to '${ transition } ' from '${ taskName } '` ) ;
229252 } else if ( currentTask ) {
230253 index = Array . from ( tasksList . values ( ) ) . indexOf ( currentTask ) + 1 ;
231254 if ( index >= tasksList . size ) {
@@ -363,7 +386,6 @@ function buildGenericTaskNode(task: Task, type: GraphNodeType, context: TaskCont
363386 */
364387function buildCallTaskNode ( task : CallTask , context : TaskContext ) : GraphNode {
365388 const node = buildGenericTaskNode ( task , GraphNodeType . Call , context ) ;
366- // TODO: add some details about the task?
367389 return node ;
368390}
369391
@@ -396,7 +418,6 @@ function buildDoTaskNode(task: DoTask, context: TaskContext): Graph {
396418 */
397419function buildEmitTaskNode ( task : EmitTask , context : TaskContext ) : GraphNode {
398420 const node = buildGenericTaskNode ( task , GraphNodeType . Emit , context ) ;
399- // TODO: add some details about the task?
400421 return node ;
401422}
402423
@@ -459,7 +480,6 @@ function buildForkTaskNode(task: ForkTask, context: TaskContext): Graph {
459480 */
460481function buildListenTaskNode ( task : ListenTask , context : TaskContext ) : GraphNode {
461482 const node = buildGenericTaskNode ( task , GraphNodeType . Listen , context ) ;
462- // TODO: add some details about the task?
463483 return node ;
464484}
465485
@@ -471,7 +491,6 @@ function buildListenTaskNode(task: ListenTask, context: TaskContext): GraphNode
471491 */
472492function buildRaiseTaskNode ( task : RaiseTask , context : TaskContext ) : GraphNode {
473493 const node = buildGenericTaskNode ( task , GraphNodeType . Raise , context ) ;
474- // TODO: add some details about the task?
475494 return node ;
476495}
477496
@@ -483,7 +502,6 @@ function buildRaiseTaskNode(task: RaiseTask, context: TaskContext): GraphNode {
483502 */
484503function buildRunTaskNode ( task : RunTask , context : TaskContext ) : GraphNode {
485504 const node = buildGenericTaskNode ( task , GraphNodeType . Run , context ) ;
486- // TODO: add some details about the task?
487505 return node ;
488506}
489507
@@ -495,7 +513,6 @@ function buildRunTaskNode(task: RunTask, context: TaskContext): GraphNode {
495513 */
496514function buildSetTaskNode ( task : SetTask , context : TaskContext ) : GraphNode {
497515 const node = buildGenericTaskNode ( task , GraphNodeType . Set , context ) ;
498- // TODO: add some details about the task?
499516 return node ;
500517}
501518
@@ -602,7 +619,6 @@ function buildTryCatchTaskNode(task: TryTask, context: TaskContext): Graph {
602619 */
603620function buildWaitTaskNode ( task : WaitTask , context : TaskContext ) : GraphNode {
604621 const node = buildGenericTaskNode ( task , GraphNodeType . Wait , context ) ;
605- // TODO: add some details about the task?
606622 return node ;
607623}
608624
@@ -692,13 +708,13 @@ export const flattenEdges = (graph: Graph): GraphEdge[] => [
692708 * @param graph The graph/node to flatten the nodes of
693709 * @returns All the nodes and subnodes declared in the graph
694710 */
695- export const flattenNodes = ( node : Graph | GraphNode ) : Array < Graph | GraphNode > => [
711+ export const flattenNodes = ( node : Graph | GraphNode ) : FlatGraphNode [ ] => [
696712 {
697- ... node ,
698- entryNode : undefined ,
699- exitNode : undefined ,
700- nodes : undefined ,
701- edges : undefined ,
713+ id : node . id ,
714+ label : node . label ,
715+ type : node . type ,
716+ task : node . task ,
717+ parentId : node . parent ?. id ,
702718 } ,
703719 ...( ( node as Graph ) . nodes || [ ] ) . flatMap ( flattenNodes ) ,
704720] ;
@@ -708,12 +724,12 @@ export const flattenNodes = (node: Graph | GraphNode): Array<Graph | GraphNode>
708724 * @param graph The target graph
709725 * @returns The modified graph
710726 */
711- export function flattenGraph ( graph : Graph ) : Graph {
727+ export function reshapeGraph ( graph : Graph ) : FlatGraph {
712728 const edges = remapEdges ( flattenEdges ( graph ) ) ;
713729 const nodes = graph . nodes
714730 . flatMap ( ( node ) => flattenNodes ( node ) )
715731 . filter ( ( node ) => node . type !== GraphNodeType . Entry && node . type !== GraphNodeType . Exit ) ;
716- const newGraph : Graph = {
732+ const newGraph : FlatGraph = {
717733 ...graph ,
718734 nodes,
719735 edges,
@@ -725,10 +741,15 @@ export function flattenGraph(graph: Graph): Graph {
725741 * Constructs a graph representation based on the given workflow.
726742 *
727743 * @param workflow The workflow to be converted into a graph structure.
728- * @param simplifyGraph A boolean indicating whether the graph nodes & edges should be flattened and free of internal entry/exit nodes.
744+ * @param flattenGraph A boolean indicating whether the graph nodes & edges should be flattened.
745+ * @param removePorts A boolean indicationg whether the port nodes should be removed.
729746 * @returns A graph representation of the workflow.
730747 */
731- export function buildGraph ( workflow : Workflow , simplifyGraph : boolean = false ) : Graph {
748+ export function buildGraph (
749+ workflow : Workflow ,
750+ flattenGraph : boolean = false ,
751+ removePorts : boolean = false ,
752+ ) : Graph | FlatGraph {
732753 const graph = initGraph ( GraphNodeType . Root ) ;
733754 if ( ! graph . entryNode ) throw new Error ( 'The root graph should have an entry node.' ) ;
734755 buildTransitions ( graph . entryNode , {
@@ -738,6 +759,17 @@ export function buildGraph(workflow: Workflow, simplifyGraph: boolean = false):
738759 taskReference : doReference ,
739760 knownEdges : [ ] ,
740761 } ) ;
741- if ( ! simplifyGraph ) return graph ;
742- return flattenGraph ( graph ) ;
762+ if ( removePorts && ! flattenGraph ) throw new Error ( `Ports can only be removed if the graph has been flattened.` ) ;
763+ if ( ! flattenGraph ) return graph ;
764+ const flatGraph = {
765+ ...graph ,
766+ edges : flattenEdges ( graph ) ,
767+ nodes : graph . nodes . flatMap ( flattenNodes ) ,
768+ } ;
769+ if ( ! removePorts ) return flatGraph ;
770+ return {
771+ ...flatGraph ,
772+ edges : remapEdges ( flatGraph . edges ) ,
773+ nodes : flatGraph . nodes . filter ( ( node ) => node . type !== GraphNodeType . Entry && node . type !== GraphNodeType . Exit ) ,
774+ } ;
743775}
0 commit comments