diff --git a/packages/nodes-base/nodes/CompareDatasets/CompareDatasets.node.ts b/packages/nodes-base/nodes/CompareDatasets/CompareDatasets.node.ts index 96aff7586f..69cb9c633b 100644 --- a/packages/nodes-base/nodes/CompareDatasets/CompareDatasets.node.ts +++ b/packages/nodes-base/nodes/CompareDatasets/CompareDatasets.node.ts @@ -5,7 +5,12 @@ import type { INodeType, INodeTypeDescription, } from 'n8n-workflow'; -import { checkInput, checkMatchFieldsInput, findMatches } from './GenericFunctions'; +import { + checkInput, + checkInputAndThrowError, + checkMatchFieldsInput, + findMatches, +} from './GenericFunctions'; export class CompareDatasets implements INodeType { description: INodeTypeDescription = { @@ -13,7 +18,7 @@ export class CompareDatasets implements INodeType { name: 'compareDatasets', icon: 'file:compare.svg', group: ['transform'], - version: [1, 2, 2.1], + version: [1, 2, 2.1, 2.2], description: 'Compare two inputs for changes', defaults: { name: 'Compare Datasets' }, // eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node @@ -254,19 +259,26 @@ export class CompareDatasets implements INodeType { options.fuzzyCompare = this.getNodeParameter('fuzzyCompare', 0, false) as boolean; } - const input1 = checkInput( - this.getInputData(0), - matchFields.map((pair) => pair.field1), - (options.disableDotNotation as boolean) || false, - 'Input A', - ); + let input1 = this.getInputData(0); + let input2 = this.getInputData(1); + if (options.nodeVersion < 2.2) { + input1 = checkInputAndThrowError( + input1, + matchFields.map((pair) => pair.field1), + (options.disableDotNotation as boolean) || false, + 'Input A', + ); - const input2 = checkInput( - this.getInputData(1), - matchFields.map((pair) => pair.field2), - (options.disableDotNotation as boolean) || false, - 'Input B', - ); + input2 = checkInputAndThrowError( + input2, + matchFields.map((pair) => pair.field2), + (options.disableDotNotation as boolean) || false, + 'Input B', + ); + } else { + input1 = checkInput(input1); + input2 = checkInput(input2); + } const resolve = this.getNodeParameter('resolve', 0, '') as string; options.resolve = resolve; diff --git a/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts b/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts index 144f52725f..cce9f22307 100644 --- a/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts +++ b/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts @@ -414,7 +414,15 @@ export function checkMatchFieldsInput(data: IDataObject[]) { return data as PairToMatch[]; } -export function checkInput( +export function checkInput(input: INodeExecutionData[]) { + if (!input) return []; + if (input.some((item) => isEmpty(item.json))) { + input = input.filter((item) => !isEmpty(item.json)); + } + return input; +} + +export function checkInputAndThrowError( input: INodeExecutionData[], fields: string[], disableDotNotation: boolean, diff --git a/packages/nodes-base/nodes/CompareDatasets/test/node/workflow.update_2_2.json b/packages/nodes-base/nodes/CompareDatasets/test/node/workflow.update_2_2.json new file mode 100644 index 0000000000..708614c644 --- /dev/null +++ b/packages/nodes-base/nodes/CompareDatasets/test/node/workflow.update_2_2.json @@ -0,0 +1,212 @@ +{ + "name": "do not error on missing keys", + "nodes": [ + { + "parameters": {}, + "id": "c7c0cf66-790a-4da7-81c8-ba9e4bbcec9a", + "name": "When clicking \"Execute Workflow\"", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [720, 300] + }, + { + "parameters": { + "jsCode": "return [\n {id: 1},\n {id: 2},\n {id: 3},\n {id: 4},\n];" + }, + "id": "cec18624-ced0-4de1-8987-d4b184b136b9", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 1, + "position": [1020, 200] + }, + { + "parameters": { + "jsCode": "return [\n];" + }, + "id": "754d549c-82ce-4625-ba2b-6f8edcbf715e", + "name": "Code1", + "type": "n8n-nodes-base.code", + "typeVersion": 1, + "position": [1020, 400] + }, + { + "parameters": { + "mergeByFields": { + "values": [ + { + "field1": "idd", + "field2": "idd" + } + ] + }, + "options": {} + }, + "id": "1b3660a2-a490-4524-a8ac-cd42fa2b340b", + "name": "Compare Datasets", + "type": "n8n-nodes-base.compareDatasets", + "typeVersion": 2.2, + "position": [1300, 420] + }, + { + "parameters": { + "mergeByFields": { + "values": [ + { + "field1": "idd", + "field2": "idd" + } + ] + }, + "options": {} + }, + "id": "17e9b83b-828c-41a0-a7ba-e33cc66d37ad", + "name": "Any skipped", + "type": "n8n-nodes-base.compareDatasets", + "typeVersion": 2.1, + "position": [1300, 180], + "continueOnFail": true + }, + { + "parameters": {}, + "id": "551ed574-607a-4d98-9b06-350df92c805e", + "name": "No Operation, do nothing", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1540, 200] + }, + { + "parameters": {}, + "id": "00e75760-d88e-413c-b276-c759db72411f", + "name": "No Operation, do nothing1", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1540, 360] + } + ], + "pinData": { + "No Operation, do nothing": [ + { + "json": { + "id": 1 + } + }, + { + "json": { + "id": 2 + } + }, + { + "json": { + "id": 3 + } + }, + { + "json": { + "id": 4 + } + } + ], + "No Operation, do nothing1": [ + { + "json": { + "id": 1 + } + }, + { + "json": { + "id": 2 + } + }, + { + "json": { + "id": 3 + } + }, + { + "json": { + "id": 4 + } + } + ] + }, + "connections": { + "When clicking \"Execute Workflow\"": { + "main": [ + [ + { + "node": "Code", + "type": "main", + "index": 0 + }, + { + "node": "Code1", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code": { + "main": [ + [ + { + "node": "Compare Datasets", + "type": "main", + "index": 0 + }, + { + "node": "Any skipped", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code1": { + "main": [ + [ + { + "node": "Compare Datasets", + "type": "main", + "index": 1 + }, + { + "node": "Any skipped", + "type": "main", + "index": 1 + } + ] + ] + }, + "Any skipped": { + "main": [ + [ + { + "node": "No Operation, do nothing", + "type": "main", + "index": 0 + } + ] + ] + }, + "Compare Datasets": { + "main": [ + [ + { + "node": "No Operation, do nothing1", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": {}, + "versionId": "11347bae-96af-4b28-80d7-fe272a165790", + "id": "8", + "meta": { + "instanceId": "6ebec4953fe56f1c009e7c3b107578b375137523af057073c0b5da17350651bd" + }, + "tags": [] +} diff --git a/packages/nodes-base/nodes/CompareDatasets/test/utils/utils.test.ts b/packages/nodes-base/nodes/CompareDatasets/test/utils/utils.test.ts new file mode 100644 index 0000000000..6af3b2f294 --- /dev/null +++ b/packages/nodes-base/nodes/CompareDatasets/test/utils/utils.test.ts @@ -0,0 +1,32 @@ +import type { INodeExecutionData } from 'n8n-workflow'; +import { checkInput } from '../../GenericFunctions'; + +describe('Test Compare Datasets Node utils', () => { + it('test checkInput', () => { + const input1 = [ + { json: {} }, + { + json: { + name: 'Test', + age: 30, + }, + }, + { + json: { + name: 'Test2', + age: 30, + }, + }, + ]; + + expect(checkInput(input1).length).toEqual(2); + + const input2: INodeExecutionData[] = [{ json: {} }]; + + expect(checkInput(input2).length).toEqual(0); + + const input3 = undefined; + + expect(checkInput(input3 as unknown as INodeExecutionData[]).length).toEqual(0); + }); +}); diff --git a/packages/nodes-base/nodes/ItemLists/ItemLists.node.ts b/packages/nodes-base/nodes/ItemLists/ItemLists.node.ts index 25a6405280..255c459fd7 100644 --- a/packages/nodes-base/nodes/ItemLists/ItemLists.node.ts +++ b/packages/nodes-base/nodes/ItemLists/ItemLists.node.ts @@ -14,12 +14,13 @@ export class ItemLists extends VersionedNodeType { group: ['input'], subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: 'Helper for working with lists of items and transforming arrays', - defaultVersion: 2, + defaultVersion: 2.1, }; const nodeVersions: IVersionedNodeType['nodeVersions'] = { 1: new ItemListsV1(baseDescription), 2: new ItemListsV2(baseDescription), + 2.1: new ItemListsV2(baseDescription), }; super(nodeVersions, baseDescription); diff --git a/packages/nodes-base/nodes/ItemLists/V2/ItemListsV2.node.ts b/packages/nodes-base/nodes/ItemLists/V2/ItemListsV2.node.ts index 1c46130df2..53bfeb8659 100644 --- a/packages/nodes-base/nodes/ItemLists/V2/ItemListsV2.node.ts +++ b/packages/nodes-base/nodes/ItemLists/V2/ItemListsV2.node.ts @@ -68,7 +68,7 @@ export class ItemListsV2 implements INodeType { constructor(baseDescription: INodeTypeBaseDescription) { this.description = { ...baseDescription, - version: 2, + version: [2, 2.1], defaults: { name: 'Item Lists', }, @@ -803,6 +803,8 @@ return 0;`, const returnData: INodeExecutionData[] = []; const resource = this.getNodeParameter('resource', 0); const operation = this.getNodeParameter('operation', 0); + const nodeVersion = this.getNode().typeVersion; + if (resource === 'itemList') { if (operation === 'splitOutItems') { for (let i = 0; i < length; i++) { @@ -827,21 +829,25 @@ return 0;`, } if (arrayToSplit === undefined) { - if (fieldToSplitOut.includes('.') && disableDotNotation) { - throw new NodeOperationError( - this.getNode(), - `Couldn't find the field '${fieldToSplitOut}' in the input data`, - { - description: - "If you're trying to use a nested field, make sure you turn off 'disable dot notation' in the node options", - }, - ); + if (nodeVersion < 2.1) { + if (fieldToSplitOut.includes('.') && disableDotNotation) { + throw new NodeOperationError( + this.getNode(), + `Couldn't find the field '${fieldToSplitOut}' in the input data`, + { + description: + "If you're trying to use a nested field, make sure you turn off 'disable dot notation' in the node options", + }, + ); + } else { + throw new NodeOperationError( + this.getNode(), + `Couldn't find the field '${fieldToSplitOut}' in the input data`, + { itemIndex: i }, + ); + } } else { - throw new NodeOperationError( - this.getNode(), - `Couldn't find the field '${fieldToSplitOut}' in the input data`, - { itemIndex: i }, - ); + arrayToSplit = []; } } @@ -950,36 +956,39 @@ return 0;`, description: 'Please add a field to aggregate', }); } - for (const { fieldToAggregate } of fieldsToAggregate) { - let found = false; - for (const item of items) { - if (fieldToAggregate === '') { - throw new NodeOperationError(this.getNode(), 'Field to aggregate is blank', { - description: 'Please add a field to aggregate', - }); - } - if (!disableDotNotation) { - if (get(item.json, fieldToAggregate) !== undefined) { + + if (nodeVersion < 2.1) { + for (const { fieldToAggregate } of fieldsToAggregate) { + let found = false; + for (const item of items) { + if (fieldToAggregate === '') { + throw new NodeOperationError(this.getNode(), 'Field to aggregate is blank', { + description: 'Please add a field to aggregate', + }); + } + if (!disableDotNotation) { + if (get(item.json, fieldToAggregate) !== undefined) { + found = true; + } + } else if (item.json.hasOwnProperty(fieldToAggregate)) { found = true; } - } else if (item.json.hasOwnProperty(fieldToAggregate)) { - found = true; } - } - if (!found && disableDotNotation && fieldToAggregate.includes('.')) { - throw new NodeOperationError( - this.getNode(), - `Couldn't find the field '${fieldToAggregate}' in the input data`, - { - description: - "If you're trying to use a nested field, make sure you turn off 'disable dot notation' in the node options", - }, - ); - } else if (!found && !keepMissing) { - throw new NodeOperationError( - this.getNode(), - `Couldn't find the field '${fieldToAggregate}' in the input data`, - ); + if (!found && disableDotNotation && fieldToAggregate.includes('.')) { + throw new NodeOperationError( + this.getNode(), + `Couldn't find the field '${fieldToAggregate}' in the input data`, + { + description: + "If you're trying to use a nested field, make sure you turn off 'disable dot notation' in the node options", + }, + ); + } else if (!found && !keepMissing) { + throw new NodeOperationError( + this.getNode(), + `Couldn't find the field '${fieldToAggregate}' in the input data`, + ); + } } } diff --git a/packages/nodes-base/nodes/ItemLists/V2/summarize.operation.ts b/packages/nodes-base/nodes/ItemLists/V2/summarize.operation.ts index 72347b4cb4..50c320b2db 100644 --- a/packages/nodes-base/nodes/ItemLists/V2/summarize.operation.ts +++ b/packages/nodes-base/nodes/ItemLists/V2/summarize.operation.ts @@ -571,7 +571,11 @@ export async function execute( const getValue = fieldValueGetter(options.disableDotNotation); - checkIfFieldExists.call(this, newItems, fieldsToSummarize, getValue); + const nodeVersion = this.getNode().typeVersion; + + if (nodeVersion < 2.1) { + checkIfFieldExists.call(this, newItems, fieldsToSummarize, getValue); + } const aggregationResult = splitData( fieldsToSplitBy, diff --git a/packages/nodes-base/nodes/ItemLists/test/node/workflow.update_2_1.json b/packages/nodes-base/nodes/ItemLists/test/node/workflow.update_2_1.json new file mode 100644 index 0000000000..283ce35d14 --- /dev/null +++ b/packages/nodes-base/nodes/ItemLists/test/node/workflow.update_2_1.json @@ -0,0 +1,695 @@ +{ + "name": "My workflow 4", + "nodes": [ + { + "parameters": {}, + "id": "037f477b-6775-47e9-b735-71c1d984ceb6", + "name": "When clicking \"Execute Workflow\"", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [440, 1300] + }, + { + "parameters": { + "fieldToSplitOut": "dataa", + "options": {} + }, + "id": "b9f156e1-ffb0-4121-abf3-8813b8cc738e", + "name": "Item Lists4", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2, + "position": [920, 260], + "continueOnFail": true + }, + { + "parameters": { + "fieldToSplitOut": "dataa", + "options": {} + }, + "id": "c8ed5ebc-18f2-4d94-8f19-c019278e5d0d", + "name": "Item Lists5", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2.1, + "position": [920, 420], + "alwaysOutputData": true + }, + { + "parameters": {}, + "id": "e2c1fc7c-3333-4849-a084-dac2c6edc1a7", + "name": "No Operation, do nothing", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 240] + }, + { + "parameters": {}, + "id": "c8c9727d-232d-4ae2-a7cc-3dcf00b32474", + "name": "No Operation, do nothing1", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 420] + }, + { + "parameters": { + "operation": "aggregateItems", + "fieldsToAggregate": { + "fieldToAggregate": [ + { + "fieldToAggregate": "idd" + } + ] + }, + "options": {} + }, + "id": "88c02d0a-0680-4564-8b2e-48ebfabe4864", + "name": "Item Lists", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2, + "position": [920, 1080], + "continueOnFail": true + }, + { + "parameters": { + "operation": "aggregateItems", + "fieldsToAggregate": { + "fieldToAggregate": [ + { + "fieldToAggregate": "idd" + } + ] + }, + "options": {} + }, + "id": "327ace17-571f-4aea-98bf-3cad71449f56", + "name": "Item Lists6", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2.1, + "position": [920, 1240] + }, + { + "parameters": {}, + "id": "38a5b83a-0f71-4788-983b-9f7719d59190", + "name": "No Operation, do nothing2", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 1060] + }, + { + "parameters": {}, + "id": "aa76c9fb-5a15-4239-903f-570aeca80453", + "name": "No Operation, do nothing3", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 1240] + }, + { + "parameters": { + "operation": "summarize", + "fieldsToSummarize": { + "values": [ + { + "field": "idd" + } + ] + }, + "options": {} + }, + "id": "246e42b2-62ab-4ef4-acf1-031ac6236052", + "name": "Item Lists7", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2, + "position": [920, 1880], + "continueOnFail": true + }, + { + "parameters": { + "operation": "summarize", + "fieldsToSummarize": { + "values": [ + { + "field": "idd" + } + ] + }, + "options": {} + }, + "id": "3145a0dd-035a-477b-8d5a-98a2106b46c8", + "name": "Item Lists8", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2.1, + "position": [920, 2040] + }, + { + "parameters": {}, + "id": "71bc9c78-cf27-4628-9f64-19a9bef353c3", + "name": "No Operation, do nothing4", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 1860] + }, + { + "parameters": {}, + "id": "1ee8497c-e721-4741-b059-ff4b85cb0e73", + "name": "No Operation, do nothing5", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 2040] + }, + { + "parameters": { + "jsCode": "return {data:[\n {id: 1},\n {id: 2},\n {id: 3},\n {id: 4},\n]};" + }, + "id": "b97e2dd3-8934-4f61-a217-e4251c3c018f", + "name": "Code2", + "type": "n8n-nodes-base.code", + "typeVersion": 1, + "position": [600, 500] + }, + { + "parameters": { + "jsCode": "return [\n {id: 1},\n {id: 2},\n {id: 3},\n {id: 4},\n];" + }, + "id": "cc63d7e0-0ecb-4aa8-ae15-69c6b32ce6d9", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 1, + "position": [660, 1260] + }, + { + "parameters": { + "operation": "summarize", + "fieldsToSummarize": { + "values": [ + { + "field": "id" + } + ] + }, + "options": {} + }, + "id": "50df7038-52d2-4b07-a729-a683ebbd769d", + "name": "Item Lists9", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2, + "position": [920, 2260], + "continueOnFail": true + }, + { + "parameters": { + "operation": "summarize", + "fieldsToSummarize": { + "values": [ + { + "field": "id" + } + ] + }, + "options": {} + }, + "id": "15347d3e-0e4a-4c48-ad24-80730f7015c8", + "name": "Item Lists10", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2.1, + "position": [920, 2420] + }, + { + "parameters": {}, + "id": "aa2bfbc8-bdfd-41fd-83f8-181bcd2fa9be", + "name": "No Operation, do nothing6", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 2240] + }, + { + "parameters": {}, + "id": "9ca712dc-dd5a-474e-808b-224bf4149f85", + "name": "No Operation, do nothing7", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 2420] + }, + { + "parameters": { + "operation": "aggregateItems", + "fieldsToAggregate": { + "fieldToAggregate": [ + { + "fieldToAggregate": "id" + } + ] + }, + "options": {} + }, + "id": "1cf43271-c87b-4523-9d8d-ed72b4ad49fa", + "name": "Item Lists1", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2, + "position": [920, 1460], + "continueOnFail": true + }, + { + "parameters": { + "operation": "aggregateItems", + "fieldsToAggregate": { + "fieldToAggregate": [ + { + "fieldToAggregate": "id" + } + ] + }, + "options": {} + }, + "id": "d1153bd8-a546-4ae2-a7ba-6f3ed4c41ba5", + "name": "Item Lists11", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2.1, + "position": [920, 1620] + }, + { + "parameters": {}, + "id": "32fa0e78-35ef-4a84-bc09-b94141db2bab", + "name": "No Operation, do nothing8", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 1440] + }, + { + "parameters": {}, + "id": "d3c43cd0-7544-4cb9-8fad-6e8e8c8676bc", + "name": "No Operation, do nothing9", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 1620] + }, + { + "parameters": { + "fieldToSplitOut": "data", + "options": {} + }, + "id": "94c419a1-a941-472b-8142-39ca1c428390", + "name": "Item Lists12", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2, + "position": [920, 660], + "continueOnFail": true + }, + { + "parameters": { + "fieldToSplitOut": "dataa", + "options": {} + }, + "id": "482d5523-a4d1-4bee-8717-c5949674a246", + "name": "Item Lists13", + "type": "n8n-nodes-base.itemLists", + "typeVersion": 2.1, + "position": [920, 820], + "alwaysOutputData": true + }, + { + "parameters": {}, + "id": "9dd44dc5-3525-4a22-b1dd-5d369db28759", + "name": "No Operation, do nothing10", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 640] + }, + { + "parameters": {}, + "id": "f23f7fed-e7e9-4e9d-abdd-056973fc0bbc", + "name": "No Operation, do nothing11", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1140, 820] + } + ], + "pinData": { + "No Operation, do nothing1": [ + { + "json": {} + } + ], + "No Operation, do nothing": [ + { + "json": { + "data": [ + { + "id": 1 + }, + { + "id": 2 + }, + { + "id": 3 + }, + { + "id": 4 + } + ] + } + } + ], + "No Operation, do nothing10": [ + { + "json": { + "id": 1 + } + }, + { + "json": { + "id": 2 + } + }, + { + "json": { + "id": 3 + } + }, + { + "json": { + "id": 4 + } + } + ], + "No Operation, do nothing11": [ + { + "json": {} + } + ], + "No Operation, do nothing2": [ + { + "json": { + "id": 1 + } + }, + { + "json": { + "id": 2 + } + }, + { + "json": { + "id": 3 + } + }, + { + "json": { + "id": 4 + } + } + ], + "No Operation, do nothing3": [ + { + "json": { + "idd": [] + } + } + ], + "No Operation, do nothing8": [ + { + "json": { + "id": [1, 2, 3, 4] + } + } + ], + "No Operation, do nothing9": [ + { + "json": { + "id": [1, 2, 3, 4] + } + } + ], + "No Operation, do nothing4": [ + { + "json": { + "id": 1 + } + }, + { + "json": { + "id": 2 + } + }, + { + "json": { + "id": 3 + } + }, + { + "json": { + "id": 4 + } + } + ], + "No Operation, do nothing5": [ + { + "json": { + "count_idd": 0 + } + } + ], + "No Operation, do nothing6": [ + { + "json": { + "count_id": 4 + } + } + ], + "No Operation, do nothing7": [ + { + "json": { + "count_id": 4 + } + } + ] + }, + "connections": { + "Item Lists4": { + "main": [ + [ + { + "node": "No Operation, do nothing", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists5": { + "main": [ + [ + { + "node": "No Operation, do nothing1", + "type": "main", + "index": 0 + } + ] + ] + }, + "When clicking \"Execute Workflow\"": { + "main": [ + [ + { + "node": "Code2", + "type": "main", + "index": 0 + }, + { + "node": "Code", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists": { + "main": [ + [ + { + "node": "No Operation, do nothing2", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists6": { + "main": [ + [ + { + "node": "No Operation, do nothing3", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists7": { + "main": [ + [ + { + "node": "No Operation, do nothing4", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists8": { + "main": [ + [ + { + "node": "No Operation, do nothing5", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code2": { + "main": [ + [ + { + "node": "Item Lists4", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists5", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists12", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists13", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code": { + "main": [ + [ + { + "node": "Item Lists", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists6", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists7", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists8", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists9", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists10", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists1", + "type": "main", + "index": 0 + }, + { + "node": "Item Lists11", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists9": { + "main": [ + [ + { + "node": "No Operation, do nothing6", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists10": { + "main": [ + [ + { + "node": "No Operation, do nothing7", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists1": { + "main": [ + [ + { + "node": "No Operation, do nothing8", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists11": { + "main": [ + [ + { + "node": "No Operation, do nothing9", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists12": { + "main": [ + [ + { + "node": "No Operation, do nothing10", + "type": "main", + "index": 0 + } + ] + ] + }, + "Item Lists13": { + "main": [ + [ + { + "node": "No Operation, do nothing11", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": {}, + "versionId": "5d3c6a6b-df81-42e6-ae4c-2b297024a298", + "id": "9", + "meta": { + "instanceId": "6ebec4953fe56f1c009e7c3b107578b375137523af057073c0b5da17350651bd" + }, + "tags": [] +} diff --git a/packages/nodes-base/nodes/Merge/Merge.node.ts b/packages/nodes-base/nodes/Merge/Merge.node.ts index e00220f260..9801b5838b 100644 --- a/packages/nodes-base/nodes/Merge/Merge.node.ts +++ b/packages/nodes-base/nodes/Merge/Merge.node.ts @@ -13,12 +13,13 @@ export class Merge extends VersionedNodeType { group: ['transform'], subtitle: '={{$parameter["mode"]}}', description: 'Merges data of multiple streams once data from both is available', - defaultVersion: 2, + defaultVersion: 2.1, }; const nodeVersions: IVersionedNodeType['nodeVersions'] = { 1: new MergeV1(baseDescription), 2: new MergeV2(baseDescription), + 2.1: new MergeV2(baseDescription), }; super(nodeVersions, baseDescription); diff --git a/packages/nodes-base/nodes/Merge/test/node/workflow.update_2_1.json b/packages/nodes-base/nodes/Merge/test/node/workflow.update_2_1.json new file mode 100644 index 0000000000..a728473e27 --- /dev/null +++ b/packages/nodes-base/nodes/Merge/test/node/workflow.update_2_1.json @@ -0,0 +1,201 @@ +{ + "name": "do not error on missing keys", + "nodes": [ + { + "parameters": {}, + "id": "c7c0cf66-790a-4da7-81c8-ba9e4bbcec9a", + "name": "When clicking \"Execute Workflow\"", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [720, 300] + }, + { + "parameters": { + "jsCode": "return [\n {id: 1},\n {id: 2},\n {id: 3},\n {id: 4},\n];" + }, + "id": "cec18624-ced0-4de1-8987-d4b184b136b9", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 1, + "position": [1020, 200] + }, + { + "parameters": { + "jsCode": "return [\n];" + }, + "id": "754d549c-82ce-4625-ba2b-6f8edcbf715e", + "name": "Code1", + "type": "n8n-nodes-base.code", + "typeVersion": 1, + "position": [1020, 400] + }, + { + "parameters": {}, + "id": "551ed574-607a-4d98-9b06-350df92c805e", + "name": "No Operation, do nothing", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1540, 200] + }, + { + "parameters": {}, + "id": "00e75760-d88e-413c-b276-c759db72411f", + "name": "No Operation, do nothing1", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [1540, 380] + }, + { + "parameters": { + "mode": "combine", + "mergeByFields": { + "values": [ + { + "field1": "idd", + "field2": "idd" + } + ] + }, + "options": {} + }, + "id": "2d412290-4c43-40a6-be78-946602749aa1", + "name": "Merge1", + "type": "n8n-nodes-base.merge", + "typeVersion": 2.1, + "position": [1340, 520], + "alwaysOutputData": true + }, + { + "parameters": { + "mode": "combine", + "mergeByFields": { + "values": [ + { + "field1": "idd", + "field2": "idd" + } + ] + }, + "options": {} + }, + "id": "b6f05b31-3ca0-48c4-a5ec-c7f81dc7957f", + "name": "Merge2", + "type": "n8n-nodes-base.merge", + "typeVersion": 2, + "position": [1320, 160], + "continueOnFail": true + } + ], + "pinData": { + "No Operation, do nothing1": [ + { + "json": {} + } + ], + "No Operation, do nothing": [ + { + "json": { + "id": 1 + } + }, + { + "json": { + "id": 2 + } + }, + { + "json": { + "id": 3 + } + }, + { + "json": { + "id": 4 + } + } + ] + }, + "connections": { + "When clicking \"Execute Workflow\"": { + "main": [ + [ + { + "node": "Code", + "type": "main", + "index": 0 + }, + { + "node": "Code1", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code": { + "main": [ + [ + { + "node": "Merge1", + "type": "main", + "index": 0 + }, + { + "node": "Merge2", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code1": { + "main": [ + [ + { + "node": "Merge1", + "type": "main", + "index": 1 + }, + { + "node": "Merge2", + "type": "main", + "index": 1 + } + ] + ] + }, + "No Operation, do nothing1": { + "main": [[]] + }, + "Merge1": { + "main": [ + [ + { + "node": "No Operation, do nothing1", + "type": "main", + "index": 0 + } + ] + ] + }, + "Merge2": { + "main": [ + [ + { + "node": "No Operation, do nothing", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": {}, + "versionId": "d0ebcbdd-b57d-495e-8f84-b9500d25c384", + "id": "8", + "meta": { + "instanceId": "6ebec4953fe56f1c009e7c3b107578b375137523af057073c0b5da17350651bd" + }, + "tags": [] +} diff --git a/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts b/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts index 5b8593bd9e..5f7b9c2adc 100644 --- a/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts +++ b/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts @@ -35,7 +35,7 @@ const versionDescription: INodeTypeDescription = { name: 'merge', icon: 'fa:code-branch', group: ['transform'], - version: 2, + version: [2, 2.1], subtitle: '={{$parameter["mode"]}}', description: 'Merges data of multiple streams once data from both is available', defaults: { @@ -450,20 +450,28 @@ export class MergeV2 implements INodeType { options.joinMode = joinMode; options.outputDataFrom = outputDataFrom; - const input1 = checkInput( - this.getInputData(0), - matchFields.map((pair) => pair.field1), - options.disableDotNotation || false, - 'Input 1', - ); - if (!input1) return [returnData]; + const nodeVersion = this.getNode().typeVersion; - const input2 = checkInput( - this.getInputData(1), - matchFields.map((pair) => pair.field2), - options.disableDotNotation || false, - 'Input 2', - ); + let input1 = this.getInputData(0); + let input2 = this.getInputData(1); + if (nodeVersion < 2.1) { + input1 = checkInput( + this.getInputData(0), + matchFields.map((pair) => pair.field1), + options.disableDotNotation || false, + 'Input 1', + ); + if (!input1) return [returnData]; + + input2 = checkInput( + this.getInputData(1), + matchFields.map((pair) => pair.field2), + options.disableDotNotation || false, + 'Input 2', + ); + } else { + if (!input1) return [returnData]; + } if (!input2 || !matchFields.length) { if (