import { get , isEqual } from 'lodash' ; import { IContextObject , INode , INodeCredentialDescription , INodeExecutionData , INodeIssueObjectProperty , INodeIssues , INodeParameters , INodeProperties , INodePropertyCollection , INodeType , INodeVersionedType , IParameterDependencies , IRunExecutionData , IWebhookData , IWorkflowExecuteAdditionalData , NodeParameterValue , WebhookHttpMethod , } from './Interfaces' ; import { Workflow } from './Workflow' ; export param { INodeType } nodeType returns export function getSpecialNodeParameters ( nodeType ) { if ( nodeType . description . polling === true ) { return [ { displayName : 'Poll Times' , name : 'pollTimes' , type : 'fixedCollection' , typeOptions : { multipleValues : true , multipleValueButtonText : 'Add Poll Time' , } , default : { } , description : 'Time at which polling should occur' , placeholder : 'Add Poll Time' , options : [ { name : 'item' , displayName : 'Item' , values : [ { displayName : 'Mode' , name : 'mode' , type : 'options' , options : [ { name : 'Every Minute' , value : 'everyMinute' , } , { name : 'Every Hour' , value : 'everyHour' , } , { name : 'Every Day' , value : 'everyDay' , } , { name : 'Every Week' , value : 'everyWeek' , } , { name : 'Every Month' , value : 'everyMonth' , } , { name : 'Every X' , value : 'everyX' , } , { name : 'Custom' , value : 'custom' , } , ] , default : 'everyDay' , description : 'How often to trigger.' , } , { displayName : 'Hour' , name : 'hour' , type : 'number' , typeOptions : { minValue : 0 , maxValue : 23 , } , displayOptions : { hide : { mode : [ 'custom' , 'everyHour' , 'everyMinute' , 'everyX' ] , } , } , default : 14 , description : 'The hour of the day to trigger (24h format)' , } , { displayName : 'Minute' , name : 'minute' , type : 'number' , typeOptions : { minValue : 0 , maxValue : 59 , } , displayOptions : { hide : { mode : [ 'custom' , 'everyMinute' , 'everyX' ] , } , } , default : 0 , description : 'The minute of the day to trigger' , } , { displayName : 'Day of Month' , name : 'dayOfMonth' , type : 'number' , displayOptions : { show : { mode : [ 'everyMonth' ] , } , } , typeOptions : { minValue : 1 , maxValue : 31 , } , default : 1 , description : 'The day of the month to trigger' , } , { displayName : 'Weekday' , name : 'weekday' , type : 'options' , displayOptions : { show : { mode : [ 'everyWeek' ] , } , } , options : [ { name : 'Monday' , value : '1' , } , { name : 'Tuesday' , value : '2' , } , { name : 'Wednesday' , value : '3' , } , { name : 'Thursday' , value : '4' , } , { name : 'Friday' , value : '5' , } , { name : 'Saturday' , value : '6' , } , { name : 'Sunday' , value : '0' , } , ] , default : '1' , description : 'The weekday to trigger' , } , { displayName : 'Cron Expression' , name : 'cronExpression' , type : 'string' , displayOptions : { show : { mode : [ 'custom' ] , } , } , default : '* * * * * *' , description : 'Use custom cron expression. Values and ranges as follows:<ul><li>Seconds: 0-59</li><li>Minutes: 0 - 59</li><li>Hours: 0 - 23</li><li>Day of Month: 1 - 31</li><li>Months: 0 - 11 (Jan - Dec)</li><li>Day of Week: 0 - 6 (Sun - Sat)</li></ul>' , } , { displayName : 'Value' , name : 'value' , type : 'number' , typeOptions : { minValue : 0 , maxValue : 1000 , } , displayOptions : { show : { mode : [ 'everyX' ] , } , } , default : 2 , description : 'All how many X minutes/hours it should trigger' , } , { displayName : 'Unit' , name : 'unit' , type : 'options' , displayOptions : { show : { mode : [ 'everyX' ] , } , } , options : [ { name : 'Minutes' , value : 'minutes' , } , { name : 'Hours' , value : 'hours' , } , ] , default : 'hours' , description : 'If it should trigger all X minutes or hours' , } , ] , } , ] , } , ] ; } return [ ] ; } export param { INodeParameters } nodeValues param { ( INodeProperties | INodeCredentialDescription ) } parameter param { INodeParameters } nodeValuesRoot returns export function displayParameter ( nodeValues , parameter , nodeValuesRoot ? ) { if ( ! parameter . displayOptions ) { return true ; } nodeValuesRoot = nodeValuesRoot || nodeValues ; let value ; const values = [ ] ; if ( parameter . displayOptions . show ) { for ( const propertyName of Object . keys ( parameter . displayOptions . show ) ) { if ( propertyName . charAt ( 0 ) === '/' ) { value = get ( nodeValuesRoot , propertyName . slice ( 1 ) ) ; } else { value = get ( nodeValues , propertyName ) ; } values . length = 0 ; if ( ! Array . isArray ( value ) ) { values . push ( value ) ; } else { values . push . apply ( values , value ) ; } if ( values . some ( ( v ) => typeof v === 'string' && v . charAt ( 0 ) === '=' ) ) { return true ; } if ( values . length === 0 || ! parameter . displayOptions . show [ propertyName ] ! . some ( ( v ) => values . includes ( v ) ) ) { return false ; } } } if ( parameter . displayOptions . hide ) { for ( const propertyName of Object . keys ( parameter . displayOptions . hide ) ) { if ( propertyName . charAt ( 0 ) === '/' ) { value = get ( nodeValuesRoot , propertyName . slice ( 1 ) ) ; } else { value = get ( nodeValues , propertyName ) ; } values . length = 0 ; if ( ! Array . isArray ( value ) ) { values . push ( value ) ; } else { values . push . apply ( values , value ) ; } if ( values . length !== 0 && parameter . displayOptions . hide [ propertyName ] ! . some ( ( v ) => values . includes ( v ) ) ) { return false ; } } } return true ; } export param { INodeParameters } nodeValues param { ( INodeProperties | INodeCredentialDescription ) } parameter param { string } path returns export function displayParameterPath ( nodeValues , parameter , path ) { let resolvedNodeValues = nodeValues ; if ( path !== '' ) { resolvedNodeValues = get ( nodeValues , path ) as INodeParameters ; } let nodeValuesRoot = nodeValues ; if ( path && path . split ( '.' ) . indexOf ( 'parameters' ) === 0 ) { nodeValuesRoot = get ( nodeValues , 'parameters' ) as INodeParameters ; } return displayParameter ( resolvedNodeValues , parameter , nodeValuesRoot ) ; } export param { IRunExecutionData } runExecutionData param { string } type param { INode } node returns { IContextObject } export function getContext ( runExecutionData , type , node ? ) { if ( runExecutionData . executionData === undefined ) { throw new Error ( 'The "executionData" is not initialized!' ) ; } let key ; if ( type === 'flow' ) { key = 'flow' ; } else if ( type === 'node' ) { if ( node === undefined ) { throw new Error ( `The request data of context type "node" the node parameter has to be set!` ) ; } key = `node:${ node . name }` ; } else { throw new Error ( `The context type "${ type }" is not know. Only "flow" and node" are supported!` ) ; } if ( runExecutionData . executionData . contextData [ key ] === undefined ) { runExecutionData . executionData . contextData [ key ] = { } ; } return runExecutionData . executionData . contextData [ key ] ; } export param { INodeProperties [ ] } nodePropertiesArray returns { IParameterDependencies } export function getParamterDependencies ( nodePropertiesArray ) { const dependencies = { } ; let displayRule ; let parameterName ; for ( const nodeProperties of nodePropertiesArray ) { if ( dependencies [ nodeProperties . name ] === undefined ) { dependencies [ nodeProperties . name ] = [ ] ; } if ( nodeProperties . displayOptions === undefined ) { continue ; } for ( displayRule of Object . keys ( nodeProperties . displayOptions ) ) { for ( parameterName of Object . keys ( nodeProperties . displayOptions [ displayRule ] ) ) { if ( ! dependencies [ nodeProperties . name ] . includes ( parameterName ) ) { dependencies [ nodeProperties . name ] . push ( parameterName ) ; } } } } return dependencies ; } export param { INodeProperties [ ] } nodePropertiesArray param { IParameterDependencies } parameterDependencies returns { number [ ] } export function getParamterResolveOrder ( nodePropertiesArray , parameterDependencies ) { const executionOrder = [ ] ; const indexToResolve = Array . from ( { length : nodePropertiesArray . length } , ( v , k ) => k ) ; const resolvedParamters = [ ] ; let index ; let property ; let lastIndexLength = indexToResolve . length ; let lastIndexReduction = - 1 ; let iterations = 0 ; while ( indexToResolve . length !== 0 ) { iterations += 1 ; index = indexToResolve . shift ( ) as number ; property = nodePropertiesArray [ index ] ; if ( parameterDependencies [ property . name ] . length === 0 ) { executionOrder . push ( index ) ; resolvedParamters . push ( property . name ) ; continue ; } for ( const dependency of parameterDependencies [ property . name ] ) { if ( ! resolvedParamters . includes ( dependency ) ) { if ( dependency . charAt ( 0 ) === '/' ) { continue ; } indexToResolve . push ( index ) ; continue ; } } executionOrder . push ( index ) ; resolvedParamters . push ( property . name ) ; if ( indexToResolve . length < lastIndexLength ) { lastIndexReduction = iterations ; } if ( iterations > lastIndexReduction + nodePropertiesArray . length ) { throw new Error ( 'Could not resolve parameter depenencies. Max iterations reached! Hint: If `displayOptions` are specified in any child parameter of a parent `collection` or `fixedCollection`, remove the `displayOptions` from the child parameter.' ) ; } lastIndexLength = indexToResolve . length ; } return executionOrder ; } export param { INodeProperties [ ] } nodePropertiesArray param { INodeParameters } nodeValues param { boolean } returnDefaults param { boolean } returnNoneDisplayed param { boolean } onlySimpleTypes param { boolean } dataIsResolved param { INodeParameters } nodeValuesRoot returns { ( INodeParameters | null ) } export function getNodeParameters ( nodePropertiesArray , nodeValues , returnDefaults , returnNoneDisplayed , onlySimpleTypes = false , dataIsResolved = false , nodeValuesRoot ? , parentType ? , parameterDependencies ? ) { if ( parameterDependencies === undefined ) { parameterDependencies = getParamterDependencies ( nodePropertiesArray ) ; } const duplicateParameterNames = [ ] ; const parameterNames = [ ] ; for ( const nodeProperties of nodePropertiesArray ) { if ( parameterNames . includes ( nodeProperties . name ) ) { if ( ! duplicateParameterNames . includes ( nodeProperties . name ) ) { duplicateParameterNames . push ( nodeProperties . name ) ; } } else { parameterNames . push ( nodeProperties . name ) ; } } const nodeParameters = { } ; const nodeParametersFull = { } ; let nodeValuesDisplayCheck = nodeParametersFull ; if ( ! dataIsResolved && ! returnNoneDisplayed ) { nodeValuesDisplayCheck = getNodeParameters ( nodePropertiesArray , nodeValues , true , true , true , true , nodeValuesRoot , parentType , parameterDependencies ) as INodeParameters ; } nodeValuesRoot = nodeValuesRoot || nodeValuesDisplayCheck ; const parameterItterationOrderIndex = getParamterResolveOrder ( nodePropertiesArray , parameterDependencies ) ; for ( const parameterIndex of parameterItterationOrderIndex ) { const nodeProperties = nodePropertiesArray [ parameterIndex ] ; if ( nodeValues [ nodeProperties . name ] === undefined && ( ! returnDefaults || parentType === 'collection' ) ) { continue ; } if ( ! returnNoneDisplayed && ! displayParameter ( nodeValuesDisplayCheck , nodeProperties , nodeValuesRoot ) ) { if ( ! returnNoneDisplayed || ! returnDefaults ) { continue ; } } if ( ! [ 'collection' , 'fixedCollection' ] . includes ( nodeProperties . type ) ) { if ( duplicateParameterNames . includes ( nodeProperties . name ) ) { if ( ! displayParameter ( nodeValuesDisplayCheck , nodeProperties , nodeValuesRoot ) ) { continue ; } } if ( returnDefaults ) { if ( [ 'boolean' , 'number' , 'options' ] . includes ( nodeProperties . type ) ) { nodeParameters [ nodeProperties . name ] = nodeValues [ nodeProperties . name ] !== undefined ? nodeValues [ nodeProperties . name ] : nodeProperties . default ; } else { nodeParameters [ nodeProperties . name ] = nodeValues [ nodeProperties . name ] || nodeProperties . default ; } nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; } else if ( ( nodeValues [ nodeProperties . name ] !== nodeProperties . default && typeof nodeValues [ nodeProperties . name ] !== 'object' ) || ( typeof nodeValues [ nodeProperties . name ] === 'object' && ! isEqual ( nodeValues [ nodeProperties . name ] , nodeProperties . default ) ) || ( nodeValues [ nodeProperties . name ] !== undefined && parentType === 'collection' ) ) { nodeParameters [ nodeProperties . name ] = nodeValues [ nodeProperties . name ] ; nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; continue ; } } if ( onlySimpleTypes ) { continue ; } let tempValue ; if ( nodeProperties . type === 'collection' ) { if ( nodeProperties . typeOptions !== undefined && nodeProperties . typeOptions . multipleValues === true ) { if ( nodeValues [ nodeProperties . name ] !== undefined ) { nodeParameters [ nodeProperties . name ] = nodeValues [ nodeProperties . name ] ; } else if ( returnDefaults ) { if ( Array . isArray ( nodeProperties . default ) ) { nodeParameters [ nodeProperties . name ] = JSON . parse ( JSON . stringify ( nodeProperties . default ) ) ; } else { nodeParameters [ nodeProperties . name ] = [ ] ; } } nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; } else if ( nodeValues [ nodeProperties . name ] !== undefined ) { const tempNodeParameters = getNodeParameters ( nodeProperties . options as INodeProperties [ ] , nodeValues [ nodeProperties . name ] as INodeParameters , returnDefaults , returnNoneDisplayed , false , false , nodeValuesRoot , nodeProperties . type ) ; if ( tempNodeParameters !== null ) { nodeParameters [ nodeProperties . name ] = tempNodeParameters ; nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; } } else if ( returnDefaults ) { nodeParameters [ nodeProperties . name ] = JSON . parse ( JSON . stringify ( nodeProperties . default ) ) ; nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; } } else if ( nodeProperties . type === 'fixedCollection' ) { const collectionValues = { } ; let tempNodeParameters ; let tempNodePropertiesArray ; let nodePropertyOptions ; let propertyValues = nodeValues [ nodeProperties . name ] ; if ( returnDefaults ) { if ( propertyValues === undefined ) { propertyValues = JSON . parse ( JSON . stringify ( nodeProperties . default ) ) ; } } for ( const itemName of Object . keys ( propertyValues || { } ) ) { if ( nodeProperties . typeOptions !== undefined && nodeProperties . typeOptions . multipleValues === true ) { const tempArrayValue = [ ] ; for ( const nodeValue of ( propertyValues as INodeParameters ) [ itemName ] as INodeParameters [ ] ) { nodePropertyOptions = nodeProperties . options ! . find ( ( nodePropertyOptions ) => nodePropertyOptions . name === itemName ) as INodePropertyCollection ; if ( nodePropertyOptions === undefined ) { throw new Error ( `Could not find property option "${ itemName }" for "${ nodeProperties . name }"` ) ; } tempNodePropertiesArray = nodePropertyOptions . values ! ; tempValue = getNodeParameters ( tempNodePropertiesArray , nodeValue , returnDefaults , returnNoneDisplayed , false , false , nodeValuesRoot , nodeProperties . type ) ; if ( tempValue !== null ) { tempArrayValue . push ( tempValue ) ; } } collectionValues [ itemName ] = tempArrayValue ; } else { tempNodeParameters = { } ; const nodePropertyOptions = nodeProperties . options ! . find ( ( data ) => data . name === itemName ) ; if ( nodePropertyOptions !== undefined ) { tempNodePropertiesArray = ( nodePropertyOptions as INodePropertyCollection ) . values ! ; tempValue = getNodeParameters ( tempNodePropertiesArray , ( nodeValues [ nodeProperties . name ] as INodeParameters ) [ itemName ] as INodeParameters , returnDefaults , returnNoneDisplayed , false , false , nodeValuesRoot , nodeProperties . type ) ; if ( tempValue !== null ) { Object . assign ( tempNodeParameters , tempValue ) ; } } if ( Object . keys ( tempNodeParameters ) . length !== 0 ) { collectionValues [ itemName ] = tempNodeParameters ; } } } if ( Object . keys ( collectionValues ) . length !== 0 || returnDefaults ) { if ( returnDefaults ) { if ( collectionValues === undefined ) { nodeParameters [ nodeProperties . name ] = JSON . parse ( JSON . stringify ( nodeProperties . default ) ) ; } else { nodeParameters [ nodeProperties . name ] = collectionValues ; } nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; } else if ( collectionValues !== nodeProperties . default ) { nodeParameters [ nodeProperties . name ] = collectionValues ; nodeParametersFull [ nodeProperties . name ] = nodeParameters [ nodeProperties . name ] ; } } } } return nodeParameters ; } export param { INodeExecutionData [ ] } outputData param { number } outputIndex returns { Promise < INodeExecutionData [ ] [ ] > } export async function prepareOutputData ( outputData , outputIndex = 0 ) { const returnData = [ ] ; for ( let i = 0 ; i < outputIndex ; i ++ ) { returnData . push ( [ ] ) ; } returnData . push ( outputData ) ; return returnData ; } export param { INode } node returns { IWebhookData [ ] } export function getNodeWebhooks ( workflow , node , additionalData , ignoreRestartWehbooks = false ) { if ( node . disabled === true ) { return [ ] ; } const nodeType = workflow . nodeTypes . getByNameAndVersion ( node . type , node . typeVersion ) as INodeType ; if ( nodeType . description . webhooks === undefined ) { return [ ] ; } const workflowId = workflow . id || '__UNSAVED__' ; const mode = 'internal' ; const returnData = [ ] ; for ( const webhookDescription of nodeType . description . webhooks ) { if ( ignoreRestartWehbooks && webhookDescription . restartWebhook === true ) { continue ; } let nodeWebhookPath = workflow . expression . getSimpleParameterValue ( node , webhookDescription . path , mode , { } ) ; if ( nodeWebhookPath === undefined ) { console . error ( `No webhook path could be found for node "${ node . name }" in workflow "${ workflowId }".` ) ; continue ; } nodeWebhookPath = nodeWebhookPath . toString ( ) ; if ( nodeWebhookPath . startsWith ( '/' ) ) { nodeWebhookPath = nodeWebhookPath . slice ( 1 ) ; } if ( nodeWebhookPath . endsWith ( '/' ) ) { nodeWebhookPath = nodeWebhookPath . slice ( 0 , - 1 ) ; } const isFullPath = workflow . expression . getSimpleParameterValue ( node , webhookDescription . isFullPath , 'internal' , { } , false ) as boolean ; const restartWebhook = workflow . expression . getSimpleParameterValue ( node , webhookDescription . restartWebhook , 'internal' , { } , false ) as boolean ; const path = getNodeWebhookPath ( workflowId , node , nodeWebhookPath , isFullPath , restartWebhook ) ; const httpMethod = workflow . expression . getSimpleParameterValue ( node , webhookDescription . httpMethod , mode , { } , 'GET' ) ; if ( httpMethod === undefined ) { console . error ( `The webhook "${ path }" for node "${ node . name }" in workflow "${ workflowId }" could not be added because the httpMethod is not defined.` ) ; continue ; } let webhookId ; if ( ( path . startsWith ( ':' ) || path . includes ( '/:' ) ) && node . webhookId ) { webhookId = node . webhookId ; } returnData . push ( { httpMethod : httpMethod . toString ( ) as WebhookHttpMethod , node : node . name , path , webhookDescription , workflowId , workflowExecuteAdditionalData : additionalData , webhookId , } ) ; } return returnData ; } export function getNodeWebhooksBasic ( workflow , node ) { if ( node . disabled === true ) { return [ ] ; } const nodeType = workflow . nodeTypes . getByNameAndVersion ( node . type , node . typeVersion ) as INodeType ; if ( nodeType . description . webhooks === undefined ) { return [ ] ; } const workflowId = workflow . id || '__UNSAVED__' ; const mode = 'internal' ; const returnData = [ ] ; for ( const webhookDescription of nodeType . description . webhooks ) { let nodeWebhookPath = workflow . expression . getSimpleParameterValue ( node , webhookDescription . path , mode , { } ) ; if ( nodeWebhookPath === undefined ) { console . error ( `No webhook path could be found for node "${ node . name }" in workflow "${ workflowId }".` ) ; continue ; } nodeWebhookPath = nodeWebhookPath . toString ( ) ; if ( nodeWebhookPath . startsWith ( '/' ) ) { nodeWebhookPath = nodeWebhookPath . slice ( 1 ) ; } if ( nodeWebhookPath . endsWith ( '/' ) ) { nodeWebhookPath = nodeWebhookPath . slice ( 0 , - 1 ) ; } const isFullPath = workflow . expression . getSimpleParameterValue ( node , webhookDescription . isFullPath , mode , { } , false ) as boolean ; const path = getNodeWebhookPath ( workflowId , node , nodeWebhookPath , isFullPath ) ; const httpMethod = workflow . expression . getSimpleParameterValue ( node , webhookDescription . httpMethod , mode , { } ) ; if ( httpMethod === undefined ) { console . error ( `The webhook "${ path }" for node "${ node . name }" in workflow "${ workflowId }" could not be added because the httpMethod is not defined.` ) ; continue ; } returnData . push ( { httpMethod : httpMethod . toString ( ) as WebhookHttpMethod , node : node . name , path , webhookDescription , workflowId , } ) ; } return returnData ; } export param { string } workflowId param { string } nodeTypeName param { string } path returns { string } export function getNodeWebhookPath ( workflowId , node , path , isFullPath ? , restartWebhook ? ) { let webhookPath = '' ; if ( restartWebhook === true ) { return path ; } if ( node . webhookId === undefined ) { webhookPath = `${ workflowId }/${ encodeURIComponent ( node . name . toLowerCase ( ) ) }/${ path }` ; } else { if ( isFullPath === true ) { return path ; } webhookPath = `${ node . webhookId }/${ path }` ; } return webhookPath ; } export param { string } baseUrl param { string } workflowId param { string } nodeTypeName param { string } path param { boolean } isFullPath returns { string } export function getNodeWebhookUrl ( baseUrl , workflowId , node , path , isFullPath ? ) { if ( ( path . startsWith ( ':' ) || path . includes ( '/:' ) ) && node . webhookId ) { isFullPath = false ; } if ( path . startsWith ( '/' ) ) { path = path . slice ( 1 ) ; } return `${ baseUrl }/${ getNodeWebhookPath ( workflowId , node , path , isFullPath ) }` ; } export param { INodeProperties [ ] } nodePropertiesArray param { INode } node returns { ( INodeIssues | null ) } export function getNodeParametersIssues ( nodePropertiesArray , node ) { const foundIssues = { } ; let propertyIssues ; if ( node . disabled === true ) { return null ; } for ( const nodeProperty of nodePropertiesArray ) { propertyIssues = getParameterIssues ( nodeProperty , node . parameters , '' ) ; mergeIssues ( foundIssues , propertyIssues ) ; } if ( Object . keys ( foundIssues ) . length === 0 ) { return null ; } return foundIssues ; } export param { INodeIssues } issues param { INode } node returns { string [ ] } export function nodeIssuesToString ( issues , node ? ) { const nodeIssues = [ ] ; if ( issues . execution !== undefined ) { nodeIssues . push ( `Execution Error.` ) ; } const objectProperties = [ 'parameters' , 'credentials' ] ; let issueText ; let parameterName ; for ( const propertyName of objectProperties ) { if ( issues [ propertyName ] !== undefined ) { for ( parameterName of Object . keys ( issues [ propertyName ] as object ) ) { for ( issueText of ( issues [ propertyName ] as INodeIssueObjectProperty ) [ parameterName ] ) { nodeIssues . push ( issueText ) ; } } } } if ( issues . typeUnknown !== undefined ) { if ( node !== undefined ) { nodeIssues . push ( `Node Type "${ node . type }" is not known.` ) ; } else { nodeIssues . push ( `Node Type is not known.` ) ; } } return nodeIssues ; } export param { INodeIssues } foundIssues param { INodeProperties } nodeProperties param { NodeParameterValue } value export function addToIssuesIfMissing ( foundIssues , nodeProperties , value ) { if ( ( nodeProperties . type === 'string' && ( value === '' || value === undefined ) ) || ( nodeProperties . type === 'multiOptions' && Array . isArray ( value ) && value . length === 0 ) || ( nodeProperties . type === 'dateTime' && value === undefined ) ) { if ( foundIssues . parameters === undefined ) { foundIssues . parameters = { } ; } if ( foundIssues . parameters [ nodeProperties . name ] === undefined ) { foundIssues . parameters [ nodeProperties . name ] = [ ] ; } foundIssues . parameters [ nodeProperties . name ] . push ( `Parameter "${ nodeProperties . displayName }" is required.` ) ; } } export param { INodeParameters } nodeValues param { string } parameterName param { string } path returns export function getParameterValueByPath ( nodeValues , parameterName , path ) { return get ( nodeValues , path ? `${ path }.${ parameterName }` : parameterName ) ; } export param { INodeProperties } nodeProperties param { INodeParameters } nodeValues param { string } path returns { INodeIssues } export function getParameterIssues ( nodeProperties , nodeValues , path ) { const foundIssues = { } ; let value ; if ( nodeProperties . required === true ) { if ( displayParameterPath ( nodeValues , nodeProperties , path ) ) { value = getParameterValueByPath ( nodeValues , nodeProperties . name , path ) ; if ( nodeProperties . typeOptions !== undefined && nodeProperties . typeOptions . multipleValues !== undefined ) { if ( Array . isArray ( value ) ) { for ( const singleValue of value as NodeParameterValue [ ] ) { addToIssuesIfMissing ( foundIssues , nodeProperties , singleValue ) ; } } } else { addToIssuesIfMissing ( foundIssues , nodeProperties , value as NodeParameterValue ) ; } } } if ( nodeProperties . options === undefined ) { return foundIssues ; } let basePath = path ? `${ path }.` : '' ; const checkChildNodeProperties = [ ] ; if ( nodeProperties . type === 'collection' ) { for ( const option of nodeProperties . options ) { checkChildNodeProperties . push ( { basePath , data : option as INodeProperties , } ) ; } } else if ( nodeProperties . type === 'fixedCollection' ) { basePath = basePath ? `${ basePath }.` : `${ nodeProperties . name }.` ; let propertyOptions ; for ( propertyOptions of nodeProperties . options as INodePropertyCollection [ ] ) { value = getParameterValueByPath ( nodeValues , propertyOptions . name , basePath . slice ( 0 , - 1 ) ) ; if ( value === undefined ) { continue ; } if ( nodeProperties . typeOptions !== undefined && nodeProperties . typeOptions . multipleValues !== undefined ) { if ( Array . isArray ( value ) ) { for ( let i = 0 ; i < ( value as INodeParameters [ ] ) . length ; i ++ ) { for ( const option of propertyOptions . values ) { checkChildNodeProperties . push ( { basePath : `${ basePath }${ propertyOptions . name }[${ i }]` , data : option , } ) ; } } } } else { for ( const option of propertyOptions . values ) { checkChildNodeProperties . push ( { basePath : basePath + propertyOptions . name , data : option , } ) ; } } } } else { return foundIssues ; } let propertyIssues ; for ( const optionData of checkChildNodeProperties ) { propertyIssues = getParameterIssues ( optionData . data , nodeValues , optionData . basePath ) ; mergeIssues ( foundIssues , propertyIssues ) ; } return foundIssues ; } export param { INodeIssues } destination param { ( INodeIssues | null ) } source returns export function mergeIssues ( destination , source ) { if ( source === null ) { return ; } if ( source . execution === true ) { destination . execution = true ; } const objectProperties = [ 'parameters' , 'credentials' ] ; let destinationProperty ; for ( const propertyName of objectProperties ) { if ( source [ propertyName ] !== undefined ) { if ( destination [ propertyName ] === undefined ) { destination [ propertyName ] = { } ; } let parameterName ; for ( parameterName of Object . keys ( source [ propertyName ] as INodeIssueObjectProperty ) ) { destinationProperty = destination [ propertyName ] as INodeIssueObjectProperty ; if ( destinationProperty [ parameterName ] === undefined ) { destinationProperty [ parameterName ] = [ ] ; } destinationProperty [ parameterName ] . push . apply ( destinationProperty [ parameterName ] , ( source [ propertyName ] as INodeIssueObjectProperty ) [ parameterName ] ) ; } } } if ( source . typeUnknown === true ) { destination . typeUnknown = true ; } } export param { INodeProperties [ ] } mainProperties param { INodeProperties [ ] } addProperties export function mergeNodeProperties ( mainProperties , addProperties ) { let existingIndex ; for ( const property of addProperties ) { existingIndex = mainProperties . findIndex ( ( element ) => element . name === property . name ) ; if ( existingIndex === - 1 ) { mainProperties . push ( property ) ; } else { mainProperties [ existingIndex ] = property ; } } } export function getVersionedNodeType ( object , version ? ) { if ( isNodeTypeVersioned ( object ) ) { return ( object as INodeVersionedType ) . getNodeType ( version ) ; } return object as INodeType ; } export function getVersionedNodeTypeAll ( object ) { if ( isNodeTypeVersioned ( object ) ) { return Object . values ( ( object as INodeVersionedType ) . nodeVersions ) . map ( ( element ) => { element . description . name = object . description . name ; return element ; } ) ; } return [ object as INodeType ] ; } export function isNodeTypeVersioned ( object ) { return ! ! ( 'getNodeType' in object ) ; }