import { IDataObject , INodeExecutionData , INodeParameters , IRunExecutionData , IWorkflowDataProxyAdditionalKeys , IWorkflowDataProxyData , NodeHelpers , NodeParameterValue , Workflow , WorkflowExecuteMode , } from '.' ; export class WorkflowDataProxy { private workflow : Workflow ; private runExecutionData : IRunExecutionData | null ; private defaultReturnRunIndex : number ; private runIndex : number ; private itemIndex : number ; private activeNodeName : string ; private connectionInputData : INodeExecutionData [ ] ; private siblingParameters : INodeParameters ; private mode : WorkflowExecuteMode ; private selfData : IDataObject ; private additionalKeys : IWorkflowDataProxyAdditionalKeys ; constructor ( workflow , runExecutionData , runIndex , itemIndex , activeNodeName , connectionInputData , siblingParameters , mode , additionalKeys , defaultReturnRunIndex = - 1 , selfData = { } ) { this . workflow = workflow ; this . runExecutionData = runExecutionData ; this . defaultReturnRunIndex = defaultReturnRunIndex ; this . runIndex = runIndex ; this . itemIndex = itemIndex ; this . activeNodeName = activeNodeName ; this . connectionInputData = connectionInputData ; this . siblingParameters = siblingParameters ; this . mode = mode ; this . selfData = selfData ; this . additionalKeys = additionalKeys ; } private param { string } nodeName returns memberof private nodeContextGetter ( nodeName ) { const that = this ; const node = this . workflow . nodes [ nodeName ] ; return new Proxy ( { } , { ownKeys ( target ) { if ( Reflect . ownKeys ( target ) . length === 0 ) { Object . assign ( target , NodeHelpers . getContext ( that . runExecutionData ! , 'node' , node ) ) ; } return Reflect . ownKeys ( target ) ; } , getOwnPropertyDescriptor ( k ) { return { enumerable : true , configurable : true , } ; } , get ( target , name , receiver ) { name = name . toString ( ) ; const contextData = NodeHelpers . getContext ( that . runExecutionData ! , 'node' , node ) ; if ( ! contextData . hasOwnProperty ( name ) ) { throw new Error ( `Could not find parameter "${ name }" on context of node "${ nodeName }"` ) ; } return contextData [ name ] ; } , } ) ; } private selfGetter ( ) { const that = this ; return new Proxy ( { } , { ownKeys ( target ) { return Reflect . ownKeys ( target ) ; } , get ( target , name , receiver ) { name = name . toString ( ) ; return that . selfData [ name ] ; } , } ) ; } private param { string } nodeName returns memberof private nodeParameterGetter ( nodeName ) { const that = this ; const node = this . workflow . nodes [ nodeName ] ; return new Proxy ( node . parameters , { ownKeys ( target ) { return Reflect . ownKeys ( target ) ; } , getOwnPropertyDescriptor ( k ) { return { enumerable : true , configurable : true , } ; } , get ( target , name , receiver ) { name = name . toString ( ) ; let returnValue ; if ( name [ 0 ] === '&' ) { const key = name . slice ( 1 ) ; if ( ! that . siblingParameters . hasOwnProperty ( key ) ) { throw new Error ( `Could not find sibling parameter "${ key }" on node "${ nodeName }"` ) ; } returnValue = that . siblingParameters [ key ] ; } else { if ( ! node . parameters . hasOwnProperty ( name ) ) { throw new Error ( `Could not find parameter "${ name }" on node "${ nodeName }"` ) ; } returnValue = node . parameters [ name ] ; } if ( typeof returnValue === 'string' && returnValue . charAt ( 0 ) === '=' ) { return that . workflow . expression . getParameterValue ( returnValue , that . runExecutionData , that . runIndex , that . itemIndex , that . activeNodeName , that . connectionInputData , that . mode , that . additionalKeys ) ; } return returnValue ; } , } ) ; } private param { string } nodeName param { boolean } shortSyntax param { number } outputIndex param { number } runIndex returns { INodeExecutionData [ ] } memberof private getNodeExecutionData ( nodeName , shortSyntax = false , outputIndex ? , runIndex ? ) { const that = this ; let executionData ; if ( ! shortSyntax ) { if ( that . runExecutionData === null ) { throw new Error ( `Workflow did not run so do not have any execution-data.` ) ; } if ( ! that . runExecutionData . resultData . runData . hasOwnProperty ( nodeName ) ) { throw new Error ( `No execution data found for node "${ nodeName }"` ) ; } runIndex = runIndex === undefined ? that . defaultReturnRunIndex : runIndex ; runIndex = runIndex === - 1 ? that . runExecutionData . resultData . runData [ nodeName ] . length - 1 : runIndex ; if ( that . runExecutionData . resultData . runData [ nodeName ] . length < runIndex ) { throw new Error ( `No execution data found for run "${ runIndex }" of node "${ nodeName }"` ) ; } const taskData = that . runExecutionData . resultData . runData [ nodeName ] [ runIndex ] . data ! ; if ( taskData . main === null || ! taskData . main . length || taskData . main [ 0 ] === null ) { throw new Error ( `No data found from "main" input.` ) ; } if ( outputIndex === undefined ) { const outputIndex = that . workflow . getNodeConnectionOutputIndex ( that . activeNodeName , nodeName , 'main' ) ; if ( outputIndex === undefined ) { throw new Error ( `The node "${ that . activeNodeName }" is not connected with node "${ nodeName }" so no data can get returned from it.` ) ; } } if ( outputIndex === undefined ) { outputIndex = 0 ; } if ( taskData . main . length < outputIndex ) { throw new Error ( `No data found from "main" input with index "${ outputIndex }" via which node is connected with.` ) ; } executionData = taskData . main [ outputIndex ] as INodeExecutionData [ ] ; } else { executionData = that . connectionInputData ; } return executionData ; } private param { string } nodeName param { boolean } shortSyntax returns memberof private nodeDataGetter ( nodeName , shortSyntax = false ) { const that = this ; const node = this . workflow . nodes [ nodeName ] ; if ( ! node ) { throw new Error ( `The node "${ nodeName }" does not exist!` ) ; } return new Proxy ( { } , { get ( target , name , receiver ) { name = name . toString ( ) ; if ( [ 'binary' , 'data' , 'json' ] . includes ( name ) ) { const executionData = that . getNodeExecutionData ( nodeName , shortSyntax , undefined ) ; if ( executionData . length <= that . itemIndex ) { throw new Error ( `No data found for item-index: "${ that . itemIndex }"` ) ; } if ( [ 'data' , 'json' ] . includes ( name ) ) { return executionData [ that . itemIndex ] . json ; } if ( name === 'binary' ) { const returnData = { } ; if ( ! executionData [ that . itemIndex ] . binary ) { return returnData ; } const binaryKeyData = executionData [ that . itemIndex ] . binary ! ; for ( const keyName of Object . keys ( binaryKeyData ) ) { returnData [ keyName ] = { } ; const binaryData = binaryKeyData [ keyName ] ; for ( const propertyName in binaryData ) { if ( propertyName === 'data' ) { continue ; } ( returnData [ keyName ] as IDataObject ) [ propertyName ] = binaryData [ propertyName ] ; } } return returnData ; } } else if ( name === 'context' ) { return that . nodeContextGetter ( nodeName ) ; } else if ( name === 'parameter' ) { return that . nodeParameterGetter ( nodeName ) ; } else if ( name === 'runIndex' ) { if ( that . runExecutionData === null || ! that . runExecutionData . resultData . runData [ nodeName ] ) { return - 1 ; } return that . runExecutionData . resultData . runData [ nodeName ] . length - 1 ; } return Reflect . get ( target , name , receiver ) ; } , } ) ; } private returns memberof private envGetter ( ) { return new Proxy ( { } , { get ( target , name , receiver ) { return process . env [ name . toString ( ) ] ; } , } ) ; } private returns memberof private workflowGetter ( ) { const allowedValues = [ 'active' , 'id' , 'name' ] ; const that = this ; return new Proxy ( { } , { ownKeys ( target ) { return allowedValues ; } , getOwnPropertyDescriptor ( k ) { return { enumerable : true , configurable : true , } ; } , get ( target , name , receiver ) { if ( ! allowedValues . includes ( name . toString ( ) ) ) { throw new Error ( `The key "${ name . toString ( ) }" is not supported!` ) ; } return that . workflow [ name . toString ( ) ] ; } , } ) ; } private returns memberof private nodeGetter ( ) { const that = this ; return new Proxy ( { } , { get ( target , name , receiver ) { return that . nodeDataGetter ( name . toString ( ) ) ; } , } ) ; } returns memberof getDataProxy ( ) { const that = this ; const base = { $binary : { } , $data : { } , $env : this . envGetter ( ) , $evaluateExpression : ( expression , itemIndex ? ) => { itemIndex = itemIndex || that . itemIndex ; return that . workflow . expression . getParameterValue ( `=${ expression }` , that . runExecutionData , that . runIndex , itemIndex , that . activeNodeName , that . connectionInputData , that . mode , that . additionalKeys ) ; } , $item : ( itemIndex , runIndex ? ) => { const defaultReturnRunIndex = runIndex === undefined ? - 1 : runIndex ; const dataProxy = new WorkflowDataProxy ( this . workflow , this . runExecutionData , this . runIndex , itemIndex , this . activeNodeName , this . connectionInputData , that . siblingParameters , that . mode , that . additionalKeys , defaultReturnRunIndex ) ; return dataProxy . getDataProxy ( ) ; } , $items : ( nodeName ? , outputIndex ? , runIndex ? ) => { let executionData ; if ( nodeName === undefined ) { executionData = that . connectionInputData ; } else { outputIndex = outputIndex || 0 ; runIndex = runIndex === undefined ? - 1 : runIndex ; executionData = that . getNodeExecutionData ( nodeName , false , outputIndex , runIndex ) ; } return executionData ; } , $json : { } , $node : this . nodeGetter ( ) , $self : this . selfGetter ( ) , $parameter : this . nodeParameterGetter ( this . activeNodeName ) , $position : this . itemIndex , $runIndex : this . runIndex , $mode : this . mode , $workflow : this . workflowGetter ( ) , ... that . additionalKeys , } ; return new Proxy ( base , { get ( target , name , receiver ) { if ( [ '$data' , '$json' ] . includes ( name as string ) ) { return that . nodeDataGetter ( that . activeNodeName , true ) . json ; } if ( name === '$binary' ) { return that . nodeDataGetter ( that . activeNodeName , true ) . binary ; } return Reflect . get ( target , name , receiver ) ; } , } ) ; } }