Merge pull request #3215 from n8n-io/n8n-3481-re-version-http-request-node

Re-version HTTP request node
This commit is contained in:
Alex Grozav 2022-04-28 16:31:36 +03:00 committed by GitHub
commit afe3c04e75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 423 additions and 74 deletions

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "n8n",
"version": "0.168.2",
"version": "0.174.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "n8n",
"version": "0.168.2",
"version": "0.174.0",
"dependencies": {
"@babel/core": "^7.14.6",
"@fontsource/open-sans": "^4.5.0",

View file

@ -342,6 +342,7 @@ export class CredentialsHelper extends ICredentialsHelper {
decryptedDataOriginal as INodeParameters,
true,
false,
null,
) as ICredentialDataDecryptedObject;
if (decryptedDataOriginal.oauthTokenData !== undefined) {
@ -436,8 +437,6 @@ export class CredentialsHelper extends ICredentialsHelper {
// Add special database related data
newCredentialsData.updatedAt = new Date();
// TODO: also add user automatically depending on who is logged in, if anybody is logged in
// Save the credentials in DB
const findQuery = {
id: credentials.id,
@ -562,7 +561,9 @@ export class CredentialsHelper extends ICredentialsHelper {
parameters: {},
name: 'Temp-Node',
type: nodeType.description.name,
typeVersion: nodeType.description.version,
typeVersion: Array.isArray(nodeType.description.version)
? nodeType.description.version.slice(-1)[0]
: nodeType.description.version,
position: [0, 0],
};

View file

@ -1298,6 +1298,7 @@ export async function getCredentials(
!NodeHelpers.displayParameter(
additionalData.currentNodeParameters || node.parameters,
nodeCredentialDescription,
node,
node.parameters,
)
) {

View file

@ -32,6 +32,7 @@
<script lang="ts">
import {
INodeUi,
IUpdateInformation,
} from '@/Interface';
@ -87,6 +88,9 @@ export default mixins(
return this.displayNodeParameter(option as INodeProperties);
});
},
node (): INodeUi {
return this.$store.getters.activeNode;
},
// Returns all the options which did not get added already
parameterOptions (): Array<INodePropertyOptions | INodeProperties> {
return (this.filteredOptions as Array<INodePropertyOptions | INodeProperties>).filter((option) => {
@ -127,7 +131,7 @@ export default mixins(
// If it is not defined no need to do a proper check
return true;
}
return this.displayParameter(this.nodeValues, parameter, this.path);
return this.displayParameter(this.nodeValues, parameter, this.path, this.node);
},
optionSelected (optionName: string) {
const options = this.getOptionProperties(optionName);

View file

@ -395,6 +395,7 @@ export default mixins(showMessage, nodeHelpers).extend({
this.credentialData as INodeParameters,
parameter,
'',
null,
);
},
getCredentialProperties(name: string): INodeProperties[] {
@ -598,6 +599,7 @@ export default mixins(showMessage, nodeHelpers).extend({
this.credentialData as INodeParameters,
false,
false,
null,
);
const credentialDetails: ICredentialsDecrypted = {

View file

@ -251,7 +251,7 @@ export default mixins(
// If it is not defined no need to do a proper check
return true;
}
return this.displayParameter(this.node.parameters, credentialTypeDescription, '');
return this.displayParameter(this.node.parameters, credentialTypeDescription, '', this.node);
},
getIssues (credentialTypeName: string): string[] {

View file

@ -379,7 +379,7 @@ export default mixins(
}
// Get only the parameters which are different to the defaults
let nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false);
let nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false, node);
const oldNodeParameters = Object.assign({}, nodeParameters);
// Copy the data because it is the data of vuex so make sure that
@ -415,7 +415,7 @@ export default mixins(
// Get the parameters with the now new defaults according to the
// from the user actually defined parameters
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false);
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false, node);
for (const key of Object.keys(nodeParameters as object)) {
if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) {

View file

@ -110,6 +110,7 @@
:size="inputSize"
filterable
:value="displayValue"
:placeholder="parameter.placeholder ? getPlaceholder() : $locale.baseText('parameterInput.select')"
:loading="remoteParameterOptionsLoading"
:disabled="isReadOnly || remoteParameterOptionsLoading"
:title="displayTitle"
@ -468,7 +469,7 @@ export default mixins(
const newPath = this.shortPath.split('.');
newPath.pop();
const issues = NodeHelpers.getParameterIssues(this.parameter, this.node.parameters, newPath.join('.'));
const issues = NodeHelpers.getParameterIssues(this.parameter, this.node.parameters, newPath.join('.'), this.node);
if (['options', 'multiOptions'].includes(this.parameter.type) && this.remoteParameterOptionsLoading === false && this.remoteParameterOptionsLoadingIssues === null) {
// Check if the value resolves to a valid option

View file

@ -89,7 +89,7 @@ import {
NodeParameterValue,
} from 'n8n-workflow';
import { IUpdateInformation } from '@/Interface';
import { INodeUi, IUpdateInformation } from '@/Interface';
import MultipleParameter from '@/components/MultipleParameter.vue';
import { genericHelpers } from '@/components/mixins/genericHelpers';
@ -124,6 +124,9 @@ export default mixins(
filteredParameterNames (): string[] {
return this.filteredParameters.map(parameter => parameter.name);
},
node (): INodeUi {
return this.$store.getters.activeNode;
},
},
methods: {
multipleValues (parameter: INodeProperties): boolean {
@ -213,13 +216,13 @@ export default mixins(
if (this.path) {
rawValues = JSON.parse(JSON.stringify(this.nodeValues));
set(rawValues, this.path, nodeValues);
return this.displayParameter(rawValues, parameter, this.path);
return this.displayParameter(rawValues, parameter, this.path, this.node);
} else {
return this.displayParameter(nodeValues, parameter, '');
return this.displayParameter(nodeValues, parameter, '', this.node);
}
}
return this.displayParameter(this.nodeValues, parameter, this.path);
return this.displayParameter(this.nodeValues, parameter, this.path, this.node);
},
valueChanged (parameterData: IUpdateInformation): void {
this.$emit('valueChanged', parameterData);

View file

@ -48,8 +48,8 @@ export const nodeHelpers = mixins(
},
// Returns if the given parameter should be displayed or not
displayParameter (nodeValues: INodeParameters, parameter: INodeProperties | INodeCredentialDescription, path: string) {
return NodeHelpers.displayParameterPath(nodeValues, parameter, path);
displayParameter (nodeValues: INodeParameters, parameter: INodeProperties | INodeCredentialDescription, path: string, node: INodeUi | null) {
return NodeHelpers.displayParameterPath(nodeValues, parameter, path, node);
},
// Returns all the issues of the node
@ -200,7 +200,7 @@ export const nodeHelpers = mixins(
let selectedCredentials: INodeCredentialsDetails;
for (const credentialTypeDescription of nodeType!.credentials!) {
// Check if credentials should be displayed else ignore
if (this.displayParameter(node.parameters, credentialTypeDescription, '') !== true) {
if (this.displayParameter(node.parameters, credentialTypeDescription, '', node) !== true) {
continue;
}

View file

@ -323,7 +323,7 @@ export const workflowHelpers = mixins(
if (nodeType !== null) {
// Node-Type is known so we can save the parameters correctly
const nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false);
const nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false, node);
nodeData.parameters = nodeParameters !== null ? nodeParameters : {};
// Add the node credentials if there are some set and if they should be displayed
@ -338,7 +338,7 @@ export const workflowHelpers = mixins(
continue;
}
if (this.displayParameter(node.parameters, credentialTypeDescription, '') === false) {
if (this.displayParameter(node.parameters, credentialTypeDescription, '', node) === false) {
// Credential should not be displayed so do also not save
continue;
}

View file

@ -645,7 +645,7 @@ export const store = new Vuex.Store({
},
updateNodeTypes (state, nodeTypes: INodeTypeDescription[]) {
const oldNodesToKeep = state.nodeTypes.filter(node => !nodeTypes.find(n => n.name === node.name && n.version === node.version));
const oldNodesToKeep = state.nodeTypes.filter(node => !nodeTypes.find(n => n.name === node.name && n.version.toString() === node.version.toString()));
const newNodesState = [...oldNodesToKeep, ...nodeTypes];
Vue.set(state, 'nodeTypes', newNodesState);
state.nodeTypes = newNodesState;
@ -852,7 +852,11 @@ export const store = new Vuex.Store({
nodeType: (state, getters) => (nodeType: string, typeVersion?: number): INodeTypeDescription | null => {
const foundType = state.nodeTypes.find(typeData => {
return typeData.name === nodeType && typeData.version === (typeVersion || typeData.defaultVersion || DEFAULT_NODETYPE_VERSION);
const typeVersion = Array.isArray(typeData.version)
? typeData.version
: [typeData.version];
return typeData.name === nodeType && typeVersion.some(versions => [typeVersion, typeData.defaultVersion, DEFAULT_NODETYPE_VERSION].includes(versions));
});
if (foundType === undefined) {

View file

@ -1356,7 +1356,9 @@ export default mixins(
const newNodeData: INodeUi = {
name: nodeTypeData.defaults.name as string,
type: nodeTypeData.name,
typeVersion: nodeTypeData.version,
typeVersion: Array.isArray(nodeTypeData.version)
? nodeTypeData.version.slice(-1)[0]
: nodeTypeData.version,
position: [0, 0],
parameters: {},
};
@ -2445,7 +2447,7 @@ export default mixins(
if (nodeType !== null) {
let nodeParameters = null;
try {
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, true, false);
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, true, false, node);
} catch (e) {
console.error(this.$locale.baseText('nodeView.thereWasAProblemLoadingTheNodeParametersOfNode') + `: "${node.name}"`); // eslint-disable-line no-console
console.error(e); // eslint-disable-line no-console
@ -2753,10 +2755,13 @@ export default mixins(
const nodesToBeFetched:INodeTypeNameVersion[] = [];
allNodes.forEach(node => {
if(!!nodeInfos.find(n => n.name === node.name && n.version === node.version) && !node.hasOwnProperty('properties')) {
const nodeVersions = Array.isArray(node.version) ? node.version : [node.version];
if(!!nodeInfos.find(n => n.name === node.name && nodeVersions.includes(n.version)) && !node.hasOwnProperty('properties')) {
nodesToBeFetched.push({
name: node.name,
version: node.version,
version: Array.isArray(node.version)
? node.version.slice(-1)[0]
: node.version,
});
}
});

View file

@ -1,10 +1,14 @@
import path from 'path';
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IAuthenticate,
IBinaryData,
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
INodePropertyOptions,
INodeType,
INodeTypeDescription,
NodeApiError,
@ -29,7 +33,7 @@ export class HttpRequest implements INodeType {
name: 'httpRequest',
icon: 'fa:at',
group: ['input'],
version: 1,
version: [1, 2],
subtitle: '={{$parameter["requestMethod"] + ": " + $parameter["url"]}}',
description: 'Makes an HTTP request and returns the response data',
defaults: {
@ -39,6 +43,97 @@ export class HttpRequest implements INodeType {
inputs: ['main'],
outputs: ['main'],
credentials: [
// ----------------------------------
// v2 creds
// ----------------------------------
{
name: 'httpBasicAuth',
required: true,
displayOptions: {
show: {
authenticateWith: [
'basicAuth',
],
'@version': [
2,
],
},
},
},
{
name: 'httpDigestAuth',
required: true,
displayOptions: {
show: {
authenticateWith: [
'digestAuth',
],
'@version': [
2,
],
},
},
},
{
name: 'httpHeaderAuth',
required: true,
displayOptions: {
show: {
authenticateWith: [
'headerAuth',
],
'@version': [
2,
],
},
},
},
{
name: 'httpQueryAuth',
required: true,
displayOptions: {
show: {
authenticateWith: [
'queryAuth',
],
'@version': [
2,
],
},
},
},
{
name: 'oAuth1Api',
required: true,
displayOptions: {
show: {
authenticateWith: [
'oAuth1',
],
'@version': [
2,
],
},
},
},
{
name: 'oAuth2Api',
required: true,
displayOptions: {
show: {
authenticateWith: [
'oAuth2',
],
'@version': [
2,
],
},
},
},
// ----------------------------------
// v1 creds
// ----------------------------------
{
name: 'httpBasicAuth',
required: true,
@ -47,6 +142,9 @@ export class HttpRequest implements INodeType {
authentication: [
'basicAuth',
],
'@version': [
1,
],
},
},
},
@ -58,6 +156,9 @@ export class HttpRequest implements INodeType {
authentication: [
'digestAuth',
],
'@version': [
1,
],
},
},
},
@ -69,6 +170,9 @@ export class HttpRequest implements INodeType {
authentication: [
'headerAuth',
],
'@version': [
1,
],
},
},
},
@ -80,6 +184,9 @@ export class HttpRequest implements INodeType {
authentication: [
'queryAuth',
],
'@version': [
1,
],
},
},
},
@ -91,6 +198,9 @@ export class HttpRequest implements INodeType {
authentication: [
'oAuth1',
],
'@version': [
1,
],
},
},
},
@ -107,6 +217,107 @@ export class HttpRequest implements INodeType {
},
],
properties: [
// ----------------------------------
// v2 params
// ----------------------------------
{
displayName: 'Authenticate with',
name: 'authenticateWith',
type: 'options',
required: true,
options: [
{
name: 'Node Credential',
value: 'nodeCredential',
description: 'Easiest. Use a credential from another node, like Google Sheets.',
},
{
name: 'Generic Auth',
value: 'genericAuth',
description: 'Fully customizable. Choose between Basic, Header, OAuth2 and more.',
},
{
name: 'None',
value: 'none',
},
],
default: 'none',
displayOptions: {
show: {
'@version': [
2,
],
},
},
},
{
displayName: 'Node Credential Type',
name: 'nodeCredentialType',
type: 'options',
required: true,
typeOptions: {
loadOptionsMethod: 'getNodeCredentialTypes',
},
default: '',
placeholder: 'None',
displayOptions: {
show: {
authenticateWith: [
'nodeCredential',
],
'@version': [
2,
],
},
},
},
{
displayName: 'Generic Auth Type',
name: 'genericAuthType',
type: 'options',
required: true,
options: [
{
name: 'Basic Auth',
value: 'basicAuth',
},
{
name: 'Digest Auth',
value: 'digestAuth',
},
{
name: 'Header Auth',
value: 'headerAuth',
},
{
name: 'Query Auth',
value: 'queryAuth',
},
{
name: 'OAuth1',
value: 'oAuth1',
},
{
name: 'OAuth2',
value: 'oAuth2',
},
],
default: 'basicAuth',
displayOptions: {
show: {
authenticateWith: [
'genericAuth',
],
'@version': [
2,
],
},
},
},
// ----------------------------------
// v1 params
// ----------------------------------
{
displayName: 'Authentication',
name: 'authentication',
@ -143,7 +354,18 @@ export class HttpRequest implements INodeType {
],
default: 'none',
description: 'The way to authenticate.',
displayOptions: {
show: {
'@version': [
1,
],
},
},
},
// ----------------------------------
// versionless params
// ----------------------------------
{
displayName: 'Request Method',
name: 'requestMethod',
@ -642,6 +864,13 @@ export class HttpRequest implements INodeType {
],
};
methods = {
loadOptions: {
getNodeCredentialTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
return Promise.resolve(CREDENTIAL_TYPES);
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
@ -653,47 +882,46 @@ export class HttpRequest implements INodeType {
'statusMessage',
];
// TODO: Should have a setting which makes clear that this parameter can not change for each item
const requestMethod = this.getNodeParameter('requestMethod', 0) as string;
const parametersAreJson = this.getNodeParameter('jsonParameters', 0) as boolean;
let authenticateWith;
const nodeVersion = this.getNode().typeVersion;
const responseFormat = this.getNodeParameter('responseFormat', 0) as string;
try {
authenticateWith = this.getNodeParameter('authenticateWith', 0) as 'nodeCredential' | 'genericAuth' | 'none';
} catch (_) {}
let httpBasicAuth;
let httpDigestAuth;
let httpHeaderAuth;
let httpQueryAuth;
let oAuth1Api;
let oAuth2Api;
let nodeCredentialType;
try {
httpBasicAuth = await this.getCredentials('httpBasicAuth');
} catch (error) {
// Do nothing
}
try {
httpDigestAuth = await this.getCredentials('httpDigestAuth');
} catch (error) {
// Do nothing
}
try {
httpHeaderAuth = await this.getCredentials('httpHeaderAuth');
} catch (error) {
// Do nothing
}
try {
httpQueryAuth = await this.getCredentials('httpQueryAuth');
} catch (error) {
// Do nothing
}
try {
oAuth1Api = await this.getCredentials('oAuth1Api');
} catch (error) {
// Do nothing
}
try {
oAuth2Api = await this.getCredentials('oAuth2Api');
} catch (error) {
// Do nothing
if (authenticateWith === 'genericAuth' || nodeVersion === 1) {
try {
httpBasicAuth = await this.getCredentials('httpBasicAuth');
} catch (_) {}
try {
httpDigestAuth = await this.getCredentials('httpDigestAuth');
} catch (_) {}
try {
httpHeaderAuth = await this.getCredentials('httpHeaderAuth');
} catch (_) {}
try {
httpQueryAuth = await this.getCredentials('httpQueryAuth');
} catch (_) {}
try {
oAuth1Api = await this.getCredentials('oAuth1Api');
} catch (_) {}
try {
oAuth2Api = await this.getCredentials('oAuth2Api');
} catch (_) {}
} else if (authenticateWith === 'nodeCredential') {
try {
nodeCredentialType = this.getNodeParameter('nodeCredentialType', 0) as string;
} catch (_) {}
}
let requestOptions: OptionsWithUri;
@ -723,6 +951,9 @@ export class HttpRequest implements INodeType {
const returnItems: INodeExecutionData[] = [];
const requestPromises = [];
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
const requestMethod = this.getNodeParameter('requestMethod', itemIndex) as string;
const parametersAreJson = this.getNodeParameter('jsonParameters', itemIndex) as boolean;
const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
const url = this.getNodeParameter('url', itemIndex) as string;
@ -983,13 +1214,30 @@ export class HttpRequest implements INodeType {
this.sendMessageToUI(sendRequest);
} catch (e) { }
// Now that the options are all set make the actual http request
if (oAuth1Api !== undefined) {
requestPromises.push(this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions));
} else if (oAuth2Api !== undefined) {
requestPromises.push(this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, { tokenType: 'Bearer' }));
} else {
requestPromises.push(this.helpers.request(requestOptions));
if (
authenticateWith === 'genericAuth' ||
authenticateWith === 'none' ||
nodeVersion === 1
) {
if (oAuth1Api) {
requestPromises.push(
this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions),
);
} else if (oAuth2Api) {
requestPromises.push(
this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, { tokenType: 'Bearer' }),
);
} else {
// bearerAuth, queryAuth, headerAuth, digestAuth, none
requestPromises.push(
this.helpers.request(requestOptions),
);
}
} else if (authenticateWith === 'nodeCredential' && nodeCredentialType) {
// service-specific cred: OAuth1, OAuth2, plain
requestPromises.push(
this.helpers.requestWithAuthentication.call(this, nodeCredentialType, requestOptions),
);
}
}
@ -1121,3 +1369,56 @@ export class HttpRequest implements INodeType {
return this.prepareOutputData(returnItems);
}
}
const NODES_BASE_ROOT: Readonly<string> = path.resolve(__dirname, '..', '..', '..');
/**
* Credential types shown as options for `Node Credential Type` parameter.
*/
const CREDENTIAL_TYPES = getCredPaths().reduce<INodePropertyOptions[]>((acc, credPath) => {
const credential = new (getCredClass(credPath))();
if (!isSupportedByHttpRequestNode(credential)) return acc;
return [
...acc,
{
name: credential.displayName,
value: credential.name,
},
];
}, []);
function getCredPaths(root = NODES_BASE_ROOT): string[] {
const packageJson = require(path.resolve(root, 'package.json'));
return deduplicate(packageJson.n8n.credentials);
}
function deduplicate<T>(array: T[]) {
return [...new Set(array)];
}
function getCredClass(credPath: string, root = NODES_BASE_ROOT): { new(): Credential } {
const match = credPath.match(/(^dist\/credentials\/(?<credClassName>.*)\.credentials\.js$)/);
if (!match?.groups) {
throw new Error(`Failed to extract credential class name from: ${credPath}`);
}
const fullCredPath = path.resolve(root, credPath);
return require(fullCredPath)[match.groups.credClassName];
}
function isSupportedByHttpRequestNode(cred: Credential) {
if (cred.name.slice(0, -4).endsWith('OAuth')) return true;
return cred.authenticate !== undefined;
}
type Credential = {
displayName: string;
name: string;
authenticate?: IAuthenticate;
};

View file

@ -271,7 +271,6 @@
"dist/credentials/SplunkApi.credentials.js",
"dist/credentials/SpontitApi.credentials.js",
"dist/credentials/SpotifyOAuth2Api.credentials.js",
"dist/credentials/SpotifyOAuth2Api.credentials.js",
"dist/credentials/SshPassword.credentials.js",
"dist/credentials/SshPrivateKey.credentials.js",
"dist/credentials/StackbyApi.credentials.js",

View file

@ -1113,7 +1113,7 @@ export interface IRequestOptionsFromParameters {
}
export interface INodeTypeDescription extends INodeTypeBaseDescription {
version: number;
version: number | number[];
defaults: INodeParameters;
eventTriggerDescription?: string;
activationMessage?: string;

View file

@ -265,6 +265,7 @@ export function getSpecialNodeParameters(nodeType: INodeType): INodeProperties[]
export function displayParameter(
nodeValues: INodeParameters,
parameter: INodeProperties | INodeCredentialDescription,
node: INode | null, // Allow null as it does also get used by credentials and they do not have versioning yet
nodeValuesRoot?: INodeParameters,
) {
if (!parameter.displayOptions) {
@ -282,6 +283,8 @@ export function displayParameter(
if (propertyName.charAt(0) === '/') {
// Get the value from the root of the node
value = get(nodeValuesRoot, propertyName.slice(1));
} else if (propertyName === '@version') {
value = node?.typeVersion || 0;
} else {
// Get the value from current level
value = get(nodeValues, propertyName);
@ -313,6 +316,8 @@ export function displayParameter(
if (propertyName.charAt(0) === '/') {
// Get the value from the root of the node
value = get(nodeValuesRoot, propertyName.slice(1));
} else if (propertyName === '@version') {
value = node?.typeVersion || 0;
} else {
// Get the value from current level
value = get(nodeValues, propertyName);
@ -352,6 +357,7 @@ export function displayParameterPath(
nodeValues: INodeParameters,
parameter: INodeProperties | INodeCredentialDescription,
path: string,
node: INode | null,
) {
let resolvedNodeValues = nodeValues;
if (path !== '') {
@ -364,7 +370,7 @@ export function displayParameterPath(
nodeValuesRoot = get(nodeValues, 'parameters') as INodeParameters;
}
return displayParameter(resolvedNodeValues, parameter, nodeValuesRoot);
return displayParameter(resolvedNodeValues, parameter, node, nodeValuesRoot);
}
/**
@ -433,6 +439,10 @@ export function getParamterDependencies(
// @ts-ignore
for (parameterName of Object.keys(nodeProperties.displayOptions[displayRule])) {
if (!dependencies[nodeProperties.name].includes(parameterName)) {
if (parameterName.charAt(0) === '@') {
// Is a special parameter so can be skipped
continue;
}
dependencies[nodeProperties.name].push(parameterName);
}
}
@ -532,6 +542,7 @@ export function getNodeParameters(
nodeValues: INodeParameters,
returnDefaults: boolean,
returnNoneDisplayed: boolean,
node: INode | null,
onlySimpleTypes = false,
dataIsResolved = false,
nodeValuesRoot?: INodeParameters,
@ -566,6 +577,7 @@ export function getNodeParameters(
nodeValues,
true,
true,
node,
true,
true,
nodeValuesRoot,
@ -594,7 +606,7 @@ export function getNodeParameters(
if (
!returnNoneDisplayed &&
!displayParameter(nodeValuesDisplayCheck, nodeProperties, nodeValuesRoot)
!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)
) {
if (!returnNoneDisplayed || !returnDefaults) {
continue;
@ -605,7 +617,7 @@ export function getNodeParameters(
// Is a simple property so can be set as it is
if (duplicateParameterNames.includes(nodeProperties.name)) {
if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, nodeValuesRoot)) {
if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)) {
continue;
}
}
@ -677,6 +689,7 @@ export function getNodeParameters(
nodeValues[nodeProperties.name] as INodeParameters,
returnDefaults,
returnNoneDisplayed,
node,
false,
false,
nodeValuesRoot,
@ -737,6 +750,7 @@ export function getNodeParameters(
nodeValue,
returnDefaults,
returnNoneDisplayed,
node,
false,
false,
nodeValuesRoot,
@ -764,6 +778,7 @@ export function getNodeParameters(
(nodeValues[nodeProperties.name] as INodeParameters)[itemName] as INodeParameters,
returnDefaults,
returnNoneDisplayed,
node,
false,
false,
nodeValuesRoot,
@ -1021,7 +1036,7 @@ export function getNodeParametersIssues(
}
for (const nodeProperty of nodePropertiesArray) {
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '');
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '', node);
mergeIssues(foundIssues, propertyIssues);
}
@ -1135,12 +1150,13 @@ export function getParameterIssues(
nodeProperties: INodeProperties,
nodeValues: INodeParameters,
path: string,
node: INode,
): INodeIssues {
const foundIssues: INodeIssues = {};
let value;
if (nodeProperties.required === true) {
if (displayParameterPath(nodeValues, nodeProperties, path)) {
if (displayParameterPath(nodeValues, nodeProperties, path, node)) {
value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
if (
@ -1235,7 +1251,7 @@ export function getParameterIssues(
let propertyIssues;
for (const optionData of checkChildNodeProperties) {
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath);
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath, node);
mergeIssues(foundIssues, propertyIssues);
}

View file

@ -586,7 +586,14 @@ export class RoutingNode {
};
let basePath = path ? `${path}.` : '';
if (!NodeHelpers.displayParameter(this.node.parameters, nodeProperties, this.node.parameters)) {
if (
!NodeHelpers.displayParameter(
this.node.parameters,
nodeProperties,
this.node,
this.node.parameters,
)
) {
return undefined;
}
if (nodeProperties.routing) {

View file

@ -110,6 +110,7 @@ export class Workflow {
node.parameters,
true,
false,
node,
);
node.parameters = nodeParameters !== null ? nodeParameters : {};
}

View file

@ -3018,6 +3018,7 @@ describe('Workflow', () => {
testData.input.nodeValues,
false,
false,
null,
);
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsFalse);
@ -3027,6 +3028,7 @@ describe('Workflow', () => {
testData.input.nodeValues,
true,
false,
null,
);
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsTrue);
@ -3036,6 +3038,7 @@ describe('Workflow', () => {
testData.input.nodeValues,
false,
true,
null,
);
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsFalse);
@ -3045,6 +3048,7 @@ describe('Workflow', () => {
testData.input.nodeValues,
true,
true,
null,
);
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsTrue);
});