mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-13 16:14:07 -08:00
✨ Allow to define which nodes change incoming data and which
not to not copy data which does not have to get copied
This commit is contained in:
parent
1d42a16d25
commit
47c2ef54d1
|
@ -599,8 +599,57 @@ export class WorkflowExecute {
|
|||
break;
|
||||
}
|
||||
|
||||
let nodeInputData = executionData.data;
|
||||
const changesIncomingData = workflow.getNodeChangesData(executionData.node);
|
||||
|
||||
if (executionData.node.disabled !== true) {
|
||||
|
||||
if (changesIncomingData.value !== false) {
|
||||
// Data has to be copied
|
||||
|
||||
// Copy only the data which is needed
|
||||
const copyKeys = changesIncomingData.keys!.split(',');
|
||||
|
||||
const allInputsData = executionData.data.main;
|
||||
let inputData: INodeExecutionData[] | null;
|
||||
const newAllInputsData: Array<INodeExecutionData[] | null> = [];
|
||||
let newEntries: INodeExecutionData[];
|
||||
let newEntry: INodeExecutionData;
|
||||
for (let inputIndex = 0; inputIndex < allInputsData.length; inputIndex++) {
|
||||
inputData = allInputsData[inputIndex];
|
||||
if (inputData === null) {
|
||||
newAllInputsData.push(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
newEntries = [];
|
||||
for (const entry of inputData) {
|
||||
newEntry = {
|
||||
json: {},
|
||||
};
|
||||
for (const key of Object.keys(entry)) {
|
||||
if (copyKeys.includes(key)) {
|
||||
newEntry[key] = JSON.parse(JSON.stringify(entry[key]));
|
||||
} else {
|
||||
// Data does NOT have to get copied
|
||||
newEntry[key] = entry[key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newEntries.push(newEntry);
|
||||
}
|
||||
newAllInputsData.push(newEntries);
|
||||
}
|
||||
|
||||
nodeInputData = {
|
||||
main: newAllInputsData,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
runExecutionData.resultData.lastNodeExecuted = executionData.node.name;
|
||||
nodeSuccessData = await workflow.runNode(executionData.node, JSON.parse(JSON.stringify(executionData.data)), runExecutionData, runIndex, this.additionalData, NodeExecuteFunctions, this.mode);
|
||||
nodeSuccessData = await workflow.runNode(executionData.node, nodeInputData, runExecutionData, runIndex, this.additionalData, NodeExecuteFunctions, this.mode);
|
||||
|
||||
if (nodeSuccessData === null) {
|
||||
// If null gets returned it means that the node did succeed
|
||||
|
|
|
@ -157,7 +157,7 @@ Property overview
|
|||
|
||||
The following properties can be set in the node description:
|
||||
|
||||
- **credentials** [optional]: Credentials the node requests access to
|
||||
- **changesIncomingData** [optional]: Object with "keys" and "value" If value is set to true it means that incomign data gets changed. If that is the case then "keys" can additionally be set to define which data (binary,json) gets changed.
|
||||
- **defaults** [required]: Default "name" and "color" to set on node when it gets created
|
||||
- **displayName** [required]: Name to display users in Editor UI
|
||||
- **description** [required]: Description to display users in Editor UI
|
||||
|
|
|
@ -31,6 +31,9 @@ export class Cron implements INodeType {
|
|||
},
|
||||
inputs: [],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Trigger Times',
|
||||
|
|
|
@ -30,6 +30,9 @@ export class EmailReadImap implements INodeType {
|
|||
required: true,
|
||||
}
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Mailbox Name',
|
||||
|
|
|
@ -31,6 +31,9 @@ export class EmailSend implements INodeType {
|
|||
required: true,
|
||||
}
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
// TODO: Add cc, bcc and choice for text as text or html (maybe also from name)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,9 @@ export class ErrorTrigger implements INodeType {
|
|||
},
|
||||
inputs: [],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: []
|
||||
};
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ export class ExecuteCommand implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Execute Once',
|
||||
|
|
|
@ -21,6 +21,10 @@ export class Function implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json,binary',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Function',
|
||||
|
|
|
@ -23,6 +23,10 @@ export class FunctionItem implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json,binary',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Function',
|
||||
|
|
|
@ -27,6 +27,9 @@ export class GoogleSheets implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'googleApi',
|
||||
|
|
|
@ -32,6 +32,9 @@ export class HttpRequest implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'httpBasicAuth',
|
||||
|
|
|
@ -23,6 +23,9 @@ export class If implements INodeType {
|
|||
inputs: ['main'],
|
||||
outputs: ['main', 'main'],
|
||||
outputNames: ['true', 'false'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Conditions',
|
||||
|
|
|
@ -20,6 +20,9 @@ export class Interval implements INodeType {
|
|||
},
|
||||
inputs: [],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Interval',
|
||||
|
|
|
@ -22,6 +22,10 @@ export class Merge implements INodeType {
|
|||
},
|
||||
inputs: ['main', 'main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: '={{$parameter["mode"] === "merge"}}',
|
||||
keys: 'json',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Mode',
|
||||
|
|
|
@ -20,6 +20,9 @@ export class NoOp implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
],
|
||||
};
|
||||
|
|
|
@ -30,6 +30,9 @@ export class OpenWeatherMap implements INodeType {
|
|||
required: true,
|
||||
}
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
|
|
|
@ -27,6 +27,10 @@ export class ReadBinaryFile implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'binary',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'File Path',
|
||||
|
|
|
@ -29,6 +29,9 @@ export class ReadBinaryFiles implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'File Selector',
|
||||
|
|
|
@ -21,6 +21,10 @@ export class ReadFileFromUrl implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'binary',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'URL',
|
||||
|
|
|
@ -25,6 +25,10 @@ export class ReadPdf implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Binary Property',
|
||||
|
|
|
@ -30,6 +30,10 @@ export class RenameKeys implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Keys',
|
||||
|
|
|
@ -22,6 +22,9 @@ export class RssFeedRead implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'URL',
|
||||
|
|
|
@ -20,6 +20,10 @@ export class Set implements INodeType {
|
|||
name: 'Set',
|
||||
color: '#0000FF',
|
||||
},
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json',
|
||||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
properties: [
|
||||
|
|
|
@ -33,6 +33,9 @@ export class Slack implements INodeType {
|
|||
required: true,
|
||||
}
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
|
|
|
@ -20,6 +20,10 @@ export class SplitInBatches implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Batch Size',
|
||||
|
|
|
@ -58,6 +58,9 @@ export class SpreadsheetFile implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
|
|
|
@ -21,6 +21,9 @@ export class Start implements INodeType {
|
|||
},
|
||||
inputs: [],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
],
|
||||
};
|
||||
|
|
|
@ -33,6 +33,9 @@ export class Trello implements INodeType {
|
|||
required: true,
|
||||
}
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
|
|
|
@ -37,6 +37,9 @@ export class TrelloTrigger implements INodeType {
|
|||
required: true,
|
||||
},
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
webhooks: [
|
||||
{
|
||||
name: 'setup',
|
||||
|
|
|
@ -33,6 +33,9 @@ export class Twilio implements INodeType {
|
|||
required: true,
|
||||
}
|
||||
],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
|
|
|
@ -43,6 +43,9 @@ export class Webhook implements INodeType {
|
|||
},
|
||||
inputs: [],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'httpBasicAuth',
|
||||
|
|
|
@ -31,6 +31,9 @@ export class WriteBinaryFile implements INodeType {
|
|||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'File Name',
|
||||
|
|
|
@ -394,6 +394,11 @@ export interface IWorfklowIssues {
|
|||
[key: string]: INodeIssues;
|
||||
}
|
||||
|
||||
export interface IChangesIncomingData {
|
||||
value?: string | boolean;
|
||||
keys?: string;
|
||||
}
|
||||
|
||||
export interface INodeTypeDescription {
|
||||
displayName: string;
|
||||
name: string;
|
||||
|
@ -409,6 +414,7 @@ export interface INodeTypeDescription {
|
|||
credentials?: INodeCredentialDescription[];
|
||||
maxNodes?: number; // How many nodes of that type can be created in a workflow
|
||||
subtitle?: string;
|
||||
changesIncomingData?: IChangesIncomingData;
|
||||
hooks?: {
|
||||
[key: string]: INodeHookDescription[] | undefined;
|
||||
activate?: INodeHookDescription[];
|
||||
|
|
|
@ -1,33 +1,36 @@
|
|||
|
||||
import {
|
||||
IChangesIncomingData,
|
||||
IConnection,
|
||||
IConnections,
|
||||
IDataObject,
|
||||
INode,
|
||||
NodeHelpers,
|
||||
INodes,
|
||||
INodeExecuteFunctions,
|
||||
INodeExecutionData,
|
||||
INodeParameters,
|
||||
INodeIssues,
|
||||
NodeParameterValue,
|
||||
INodeType,
|
||||
INodeTypes,
|
||||
ObservableObject,
|
||||
IObservableObject,
|
||||
IRunExecutionData,
|
||||
ITaskDataConnections,
|
||||
ITriggerResponse,
|
||||
IWebhookData,
|
||||
IWebhookResonseData,
|
||||
WebhookSetupMethodNames,
|
||||
WorkflowDataProxy,
|
||||
IWorfklowIssues,
|
||||
IWorkflowExecuteAdditionalData,
|
||||
WorkflowExecuteMode,
|
||||
IWorkflowSettings,
|
||||
NodeHelpers,
|
||||
NodeParameterValue,
|
||||
ObservableObject,
|
||||
WebhookSetupMethodNames,
|
||||
WorkflowDataProxy,
|
||||
WorkflowExecuteMode,
|
||||
} from './';
|
||||
|
||||
// @ts-ignore
|
||||
import * as tmpl from 'riot-tmpl';
|
||||
import { IConnection, IDataObject, IObservableObject } from './Interfaces';
|
||||
|
||||
// Set it to use double curly brackets instead of single ones
|
||||
tmpl.brackets.set('{{ }}');
|
||||
|
@ -329,6 +332,77 @@ export class Workflow {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns if the node with the given name changes the
|
||||
* incoming data
|
||||
*
|
||||
* @param {INode} node The node to get the data of
|
||||
* @returns {boolean}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getNodeChangesData(node: INode): IChangesIncomingData {
|
||||
const nodeType = this.nodeTypes.getByName(node.type);
|
||||
if (nodeType === undefined) {
|
||||
throw new Error(`The node type "${node.type}" of node "${node.name}" does not known.`);
|
||||
}
|
||||
|
||||
const returnData: IChangesIncomingData = {
|
||||
value: true,
|
||||
keys: 'binary,json',
|
||||
};
|
||||
|
||||
if (nodeType.description.changesIncomingData === undefined) {
|
||||
// If not specifially defined that it does not change the data
|
||||
// assume that it does as it would mess up everything afterwards
|
||||
// if it returns "false" and then would still change data.
|
||||
return returnData;
|
||||
}
|
||||
|
||||
// Get the value for "value"
|
||||
if (typeof nodeType.description.changesIncomingData.value === 'boolean') {
|
||||
returnData.value = nodeType.description.changesIncomingData.value;
|
||||
} else if (nodeType.description.changesIncomingData.value !== undefined) {
|
||||
const changesIncomingDataValue = this.getSimpleParameterValue(node, nodeType.description.changesIncomingData.value, 'true') as boolean | string;
|
||||
|
||||
if (typeof changesIncomingDataValue === 'boolean') {
|
||||
returnData.value = changesIncomingDataValue;
|
||||
} else {
|
||||
returnData.value = !(changesIncomingDataValue.toString().toLowerCase() === 'false');
|
||||
}
|
||||
}
|
||||
|
||||
// Get the value for "keys"
|
||||
if (returnData.value === true && nodeType.description.changesIncomingData.keys !== undefined) {
|
||||
const changesIncomingDataKeys = this.getSimpleParameterValue(node, nodeType.description.changesIncomingData.keys, 'binary,json') as string;
|
||||
|
||||
// Check if data is valid
|
||||
if (typeof changesIncomingDataKeys !== 'string') {
|
||||
throw new Error(`The data "${changesIncomingDataKeys}" for "changesIncomingData.keys" is not of type string.`);
|
||||
}
|
||||
|
||||
const dataKeys = changesIncomingDataKeys.split(',');
|
||||
const validKeys = ['binary', 'json'];
|
||||
for (const key of dataKeys) {
|
||||
if (!validKeys.includes(key)) {
|
||||
throw new Error(`The key "${key}" for "changesIncomingData.keys" is not valid. Only the following keys are allowed: ${validKeys.join(',')}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Data is valid so set it
|
||||
returnData.keys = changesIncomingDataKeys;
|
||||
}
|
||||
|
||||
if (returnData.value === false) {
|
||||
return {
|
||||
value: false,
|
||||
};
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Renames nodes in expressions
|
||||
*
|
||||
|
|
|
@ -3,6 +3,9 @@ import {
|
|||
INode,
|
||||
INodeExecutionData,
|
||||
INodeParameters,
|
||||
INodeType,
|
||||
INodeTypes,
|
||||
INodeTypesObject,
|
||||
IRunExecutionData,
|
||||
Workflow,
|
||||
} from '../src';
|
||||
|
@ -149,6 +152,238 @@ describe('Workflow', () => {
|
|||
});
|
||||
|
||||
|
||||
describe('getNodeChangesData', () => {
|
||||
|
||||
const tests = [
|
||||
{
|
||||
description: 'should return boolean false if boolean false is set',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean false if string false is set',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: 'false',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return only boolean false if boolean false is set with keys',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: false,
|
||||
keys: 'binary,json',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean true with all keys if boolean true is set',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: true,
|
||||
keys: 'binary,json',
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean true with defined keys if boolean true is set',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: true,
|
||||
keys: 'json',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: true,
|
||||
keys: 'json',
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean true with all keys if string true is set',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: 'true',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: true,
|
||||
keys: 'binary,json',
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean false when expression returns boolean false',
|
||||
input: {
|
||||
nodeParameters: {},
|
||||
changesIncomingData: {
|
||||
value: '={{false}}',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean false when parameter-expression to boolean parameter returns boolean false',
|
||||
input: {
|
||||
nodeParameters: {
|
||||
nodeBooleanParameter: false,
|
||||
},
|
||||
changesIncomingData: {
|
||||
value: '={{$parameter["nodeBooleanParameter"]}}',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean false when parameter-expression to boolean parameter returns boolean false',
|
||||
input: {
|
||||
nodeParameters: {
|
||||
nodeBooleanParameter: true,
|
||||
},
|
||||
changesIncomingData: {
|
||||
value: '={{$parameter["nodeBooleanParameter"]}}',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: true,
|
||||
keys: 'binary,json',
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean false when parameter-expression to string parameter returns string false',
|
||||
input: {
|
||||
nodeParameters: {
|
||||
nodeStringParameter: 'false',
|
||||
},
|
||||
changesIncomingData: {
|
||||
value: '={{$parameter["nodeStringParameter"]}}',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'should return boolean true when parameter-expression to string parameter returns string true',
|
||||
input: {
|
||||
nodeParameters: {
|
||||
nodeStringParameter: 'true',
|
||||
},
|
||||
changesIncomingData: {
|
||||
value: '={{$parameter["nodeStringParameter"]}}',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
value: true,
|
||||
keys: 'binary,json',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
for (const testData of tests) {
|
||||
test(testData.description, async () => {
|
||||
|
||||
const node: INode = {
|
||||
name: 'Test node',
|
||||
parameters: {},
|
||||
type: 'test.set',
|
||||
typeVersion: 1,
|
||||
position: [
|
||||
100,
|
||||
100,
|
||||
],
|
||||
};
|
||||
|
||||
class NodeTypesClass implements INodeTypes {
|
||||
nodeTypes: INodeTypesObject = {};
|
||||
|
||||
async init(nodeTypes: INodeTypesObject): Promise<void> {
|
||||
this.nodeTypes = nodeTypes;
|
||||
}
|
||||
|
||||
getAll(): INodeType[] {
|
||||
return Object.values(this.nodeTypes);
|
||||
}
|
||||
|
||||
getByName(nodeType: string): INodeType {
|
||||
return this.nodeTypes[nodeType];
|
||||
}
|
||||
}
|
||||
|
||||
const nodeTypeData: INodeType = {
|
||||
description: {
|
||||
displayName: 'Set',
|
||||
name: 'set',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
description: 'Sets a value',
|
||||
defaults: {
|
||||
name: 'Set',
|
||||
color: '#0000FF',
|
||||
},
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Node String Parameter',
|
||||
name: 'nodeStringParameter',
|
||||
type: 'string',
|
||||
default: 'default-value',
|
||||
},
|
||||
{
|
||||
displayName: 'Node Boolean Parameter',
|
||||
name: 'nodeBooleanParameter',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
Object.assign(nodeTypeData.description, { changesIncomingData: testData.input.changesIncomingData });
|
||||
Object.assign(node.parameters, testData.input.nodeParameters);
|
||||
|
||||
const nodeTypesData: INodeTypesObject = {
|
||||
'test.set': nodeTypeData,
|
||||
};
|
||||
|
||||
const nodeTypes = new NodeTypesClass();
|
||||
await nodeTypes.init(nodeTypesData);
|
||||
|
||||
const workflow = new Workflow(undefined, [ node ], {}, false, nodeTypes);
|
||||
const nodeChangesData = workflow.getNodeChangesData(node);
|
||||
|
||||
expect(nodeChangesData).toEqual(testData.output);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
describe('renameNode', () => {
|
||||
|
||||
const tests = [
|
||||
|
|
Loading…
Reference in a new issue