import { PLACEHOLDER_FILLED_AT_EXECUTION_TIME , } from '@/constants' ; import { IBinaryKeyData , ICredentialType , INodeCredentialDescription , NodeHelpers , INodeCredentialsDetails , INodeExecutionData , INodeIssues , INodeIssueData , INodeIssueObjectProperty , INodeParameters , INodeProperties , INodeTypeDescription , IRunData , IRunExecutionData , ITaskDataConnections , INode , INodePropertyOptions , } from 'n8n-workflow' ; import { ICredentialsResponse , INodeUi , } from '../../Interface' ; import { restApi } from '@/components/mixins/restApi' ; import { get } from 'lodash' ; import mixins from 'vue-typed-mixins' ; export const nodeHelpers = mixins ( restApi ) . extend ( { methods : { getParameterValue ( nodeValues , parameterName , path ) { return get ( nodeValues , path ? path + '.' + parameterName : parameterName ) ; } , displayParameter ( nodeValues , parameter , path ) { return NodeHelpers . displayParameterPath ( nodeValues , parameter , path ) ; } , getNodeIssues ( nodeType , node , ignoreIssues ? ) { let nodeIssues = null ; ignoreIssues = ignoreIssues || [ ] ; if ( node . disabled === true ) { return null ; } if ( nodeType === null ) { if ( ! ignoreIssues . includes ( 'typeUnknown' ) ) { nodeIssues = { typeUnknown : true , } ; } } else { if ( ! ignoreIssues . includes ( 'parameters' ) ) { nodeIssues = NodeHelpers . getNodeParametersIssues ( nodeType . properties , node ) ; } if ( ! ignoreIssues . includes ( 'credentials' ) ) { const nodeCredentialIssues = this . getNodeCredentialIssues ( node , nodeType ) ; if ( nodeIssues === null ) { nodeIssues = nodeCredentialIssues ; } else { NodeHelpers . mergeIssues ( nodeIssues , nodeCredentialIssues ) ; } } } if ( this . hasNodeExecutionIssues ( node ) === true && ! ignoreIssues . includes ( 'execution' ) ) { if ( nodeIssues === null ) { nodeIssues = { } ; } nodeIssues . execution = true ; } return nodeIssues ; } , hasNodeExecutionIssues ( node ) { const workflowResultData = this . $store . getters . getWorkflowRunData ; if ( workflowResultData === null || ! workflowResultData . hasOwnProperty ( node . name ) ) { return false ; } for ( const taskData of workflowResultData [ node . name ] ) { if ( taskData . error !== undefined ) { return true ; } } return false ; } , updateNodesExecutionIssues ( ) { const nodes = this . $store . getters . allNodes ; for ( const node of nodes ) { this . $store . commit ( 'setNodeIssue' , { node : node . name , type : 'execution' , value : this . hasNodeExecutionIssues ( node ) ? true : null , } ) ; } } , updateNodeCredentialIssues ( node ) { const fullNodeIssues = this . getNodeCredentialIssues ( node ) ; let newIssues = null ; if ( fullNodeIssues !== null ) { newIssues = fullNodeIssues . credentials ! ; } this . $store . commit ( 'setNodeIssue' , { node : node . name , type : 'credentials' , value : newIssues , } as INodeIssueData ) ; } , updateNodeParameterIssues ( node , nodeType ? ) { if ( nodeType === undefined ) { nodeType = this . $store . getters . nodeType ( node . type ) ; } if ( nodeType === null ) { return ; } const fullNodeIssues = NodeHelpers . getNodeParametersIssues ( nodeType ! . properties , node ) ; let newIssues = null ; if ( fullNodeIssues !== null ) { newIssues = fullNodeIssues . parameters ! ; } this . $store . commit ( 'setNodeIssue' , { node : node . name , type : 'parameters' , value : newIssues , } as INodeIssueData ) ; } , getNodeCredentialIssues ( node , nodeType ? ) { if ( node . disabled === true ) { return null ; } if ( nodeType === undefined ) { nodeType = this . $store . getters . nodeType ( node . type ) ; } if ( nodeType === null || nodeType ! . credentials === undefined ) { return null ; } if ( nodeType ! . credentials === undefined ) { return null ; } const foundIssues = { } ; let userCredentials ; let credentialType ; let credentialDisplayName ; let selectedCredentials ; for ( const credentialTypeDescription of nodeType ! . credentials ! ) { if ( this . displayParameter ( node . parameters , credentialTypeDescription , '' ) !== true ) { continue ; } credentialType = this . $store . getters [ 'credentials/getCredentialTypeByName' ] ( credentialTypeDescription . name ) ; if ( credentialType === null ) { credentialDisplayName = credentialTypeDescription . name ; } else { credentialDisplayName = credentialType . displayName ; } if ( node . credentials === undefined || node . credentials [ credentialTypeDescription . name ] === undefined ) { if ( credentialTypeDescription . required === true ) { foundIssues [ credentialTypeDescription . name ] = [ `Credentials for "${ credentialDisplayName }" are not set.` ] ; } } else { selectedCredentials = node . credentials [ credentialTypeDescription . name ] as INodeCredentialsDetails ; if ( typeof selectedCredentials === 'string' ) { selectedCredentials = { id : null , name : selectedCredentials , } ; } userCredentials = this . $store . getters [ 'credentials/getCredentialsByType' ] ( credentialTypeDescription . name ) ; if ( userCredentials === null ) { userCredentials = [ ] ; } if ( selectedCredentials . id ) { const idMatch = userCredentials . find ( ( credentialData ) => credentialData . id === selectedCredentials . id ) ; if ( idMatch ) { continue ; } } const nameMatches = userCredentials . filter ( ( credentialData ) => credentialData . name === selectedCredentials . name ) ; if ( nameMatches . length > 1 ) { foundIssues [ credentialTypeDescription . name ] = [ `Credentials with name "${ selectedCredentials . name }" exist for "${ credentialDisplayName }"` , "Credentials are not clearly identified. Please select the correct credentials." ] ; continue ; } if ( nameMatches . length === 0 ) { foundIssues [ credentialTypeDescription . name ] = [ `Credentials with name "${ selectedCredentials . name }" do not exist for "${ credentialDisplayName }".` , "You can create credentials with the exact name and then they get auto-selected on refresh." ] ; } } } if ( Object . keys ( foundIssues ) . length === 0 ) { return null ; } return { credentials : foundIssues , } ; } , updateNodesCredentialsIssues ( ) { const nodes = this . $store . getters . allNodes ; let issues ; for ( const node of nodes ) { issues = this . getNodeCredentialIssues ( node ) ; this . $store . commit ( 'setNodeIssue' , { node : node . name , type : 'credentials' , value : issues === null ? null : issues . credentials , } ) ; } } , getNodeInputData ( node , runIndex = 0 , outputIndex = 0 ) { if ( node === null ) { return [ ] ; } if ( this . $store . getters . getWorkflowExecution === null ) { return [ ] ; } const executionData = this . $store . getters . getWorkflowExecution . data ; const runData = executionData . resultData . runData ; if ( runData === null || runData [ node . name ] === undefined || ! runData [ node . name ] [ runIndex ] . data || runData [ node . name ] [ runIndex ] . data === undefined ) { return [ ] ; } return this . getMainInputData ( runData [ node . name ] [ runIndex ] . data ! , outputIndex ) ; } , getMainInputData ( connectionsData , outputIndex ) { if ( ! connectionsData || ! connectionsData . hasOwnProperty ( 'main' ) || connectionsData . main === undefined || connectionsData . main . length < outputIndex || connectionsData . main [ outputIndex ] === null ) { return [ ] ; } return connectionsData . main [ outputIndex ] as INodeExecutionData [ ] ; } , getBinaryData ( workflowRunData , node , runIndex , outputIndex ) { if ( node === null ) { return [ ] ; } const runData = workflowRunData ; if ( runData === null || ! runData [ node ] || ! runData [ node ] [ runIndex ] || ! runData [ node ] [ runIndex ] . data ) { return [ ] ; } const inputData = this . getMainInputData ( runData [ node ] [ runIndex ] . data ! , outputIndex ) ; const returnData = [ ] ; for ( let i = 0 ; i < inputData . length ; i ++ ) { if ( inputData [ i ] . hasOwnProperty ( 'binary' ) && inputData [ i ] . binary !== undefined ) { returnData . push ( inputData [ i ] . binary ! ) ; } } return returnData ; } , disableNodes ( nodes ) { for ( const node of nodes ) { const updateInformation = { name : node . name , properties : { disabled : ! node . disabled , } , } ; this . $telemetry . track ( 'User set node enabled status' , { node_type : node . type , is_enabled : node . disabled , workflow_id : this . $store . getters . workflowId } ) ; this . $store . commit ( 'updateNodeProperties' , updateInformation ) ; this . $store . commit ( 'clearNodeExecutionData' , node . name ) ; this . updateNodeParameterIssues ( node ) ; this . updateNodeCredentialIssues ( node ) ; } } , getNodeSubtitle ( data , nodeType , workflow ) { if ( data . notesInFlow ) { return data . notes ; } if ( nodeType !== null && nodeType . subtitle !== undefined ) { return workflow . expression . getSimpleParameterValue ( data as INode , nodeType . subtitle , 'internal' , PLACEHOLDER_FILLED_AT_EXECUTION_TIME ) as string | undefined ; } if ( data . parameters . operation !== undefined ) { const operation = data . parameters . operation as string ; if ( nodeType === null ) { return operation ; } const operationData = nodeType . properties . find ( ( property ) => { return property . name === 'operation' ; } ) ; if ( operationData === undefined ) { return operation ; } if ( operationData . options === undefined ) { return operation ; } const optionData = operationData . options . find ( ( option ) => { return ( option as INodePropertyOptions ) . value === data . parameters . operation ; } ) ; if ( optionData === undefined ) { return operation ; } return optionData . name ; } return undefined ; } , } , } ) ;