UNPKG

n8n-nodes-base

Version:

Base nodes of n8n

334 lines 14.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.findMatches = findMatches; exports.checkMatchFieldsInput = checkMatchFieldsInput; exports.checkInput = checkInput; exports.checkInputAndThrowError = checkInputAndThrowError; const cloneDeep_1 = __importDefault(require("lodash/cloneDeep")); const difference_1 = __importDefault(require("lodash/difference")); const get_1 = __importDefault(require("lodash/get")); const intersection_1 = __importDefault(require("lodash/intersection")); const isEmpty_1 = __importDefault(require("lodash/isEmpty")); const omit_1 = __importDefault(require("lodash/omit")); const set_1 = __importDefault(require("lodash/set")); const union_1 = __importDefault(require("lodash/union")); const unset_1 = __importDefault(require("lodash/unset")); const n8n_workflow_1 = require("n8n-workflow"); const utilities_1 = require("../../utils/utilities"); const processNullishValueFunction = (version) => { if (version >= 2) { return (value) => (value === undefined ? null : value); } return (value) => value || null; }; function compareItems(item1, item2, fieldsToMatch, options, skipFields, isEntriesEqual) { const keys = {}; fieldsToMatch.forEach((field) => { keys[field.field1] = item1.json[field.field1]; }); const keys1 = Object.keys(item1.json); const keys2 = Object.keys(item2.json); const allUniqueKeys = (0, union_1.default)(keys1, keys2); let keysToCompare; if (options.fuzzyCompare && options.nodeVersion >= 2.1) { keysToCompare = allUniqueKeys; } else { keysToCompare = (0, intersection_1.default)(keys1, keys2); } const same = keysToCompare.reduce((acc, key) => { if (isEntriesEqual(item1.json[key], item2.json[key])) { acc[key] = item1.json[key]; } return acc; }, {}); const sameKeys = Object.keys(same); const differentKeys = (0, difference_1.default)(allUniqueKeys, sameKeys); const different = {}; const skipped = {}; differentKeys.forEach((key, i) => { const processNullishValue = processNullishValueFunction(options.nodeVersion); switch (options.resolve) { case 'preferInput1': different[key] = processNullishValue(item1.json[key]); break; case 'preferInput2': different[key] = processNullishValue(item2.json[key]); break; default: let input1 = processNullishValue(item1.json[key]); let input2 = processNullishValue(item2.json[key]); let [firstInputName, secondInputName] = ['input1', 'input2']; if (options.nodeVersion >= 2) { [firstInputName, secondInputName] = ['inputA', 'inputB']; } if (options.nodeVersion >= 2.1 && !options.disableDotNotation && !skipFields.some((field) => field === key)) { const skippedFieldsWithDotNotation = skipFields.filter((field) => field.startsWith(key) && field.includes('.')); input1 = (0, cloneDeep_1.default)(input1); input2 = (0, cloneDeep_1.default)(input2); if (skippedFieldsWithDotNotation.length && (typeof input1 !== 'object' || typeof input2 !== 'object')) { throw new n8n_workflow_1.ApplicationError(`The field \'${key}\' in item ${i} is not an object. It is not possible to use dot notation.`, { level: 'warning' }); } if (skipped[key] === undefined && skippedFieldsWithDotNotation.length) { skipped[key] = { [firstInputName]: {}, [secondInputName]: {} }; } for (const skippedField of skippedFieldsWithDotNotation) { const nestedField = skippedField.replace(`${key}.`, ''); (0, set_1.default)(skipped[key][firstInputName], nestedField, (0, get_1.default)(input1, nestedField)); (0, set_1.default)(skipped[key][secondInputName], nestedField, (0, get_1.default)(input2, nestedField)); (0, unset_1.default)(input1, nestedField); (0, unset_1.default)(input2, nestedField); } different[key] = { [firstInputName]: input1, [secondInputName]: input2 }; } else { if (skipFields.includes(key)) { skipped[key] = { [firstInputName]: input1, [secondInputName]: input2 }; } else { different[key] = { [firstInputName]: input1, [secondInputName]: input2 }; } } } }); return { json: { keys, same, different, ...(!(0, isEmpty_1.default)(skipped) && { skipped }) }, pairedItem: [ ...(0, utilities_1.preparePairedItemDataArray)(item1.pairedItem), ...(0, utilities_1.preparePairedItemDataArray)(item2.pairedItem), ], }; } function combineItems(item1, item2, prefer, except, disableDotNotation) { let exceptFields; const [entry, match] = prefer === 'input1' ? [item1, item2] : [item2, item1]; if (except && Array.isArray(except) && except.length) { exceptFields = except; } else { exceptFields = except ? except.split(',').map((field) => field.trim()) : []; } exceptFields.forEach((field) => { entry.json[field] = match.json[field]; if (disableDotNotation) { entry.json[field] = match.json[field]; } else { const value = (0, get_1.default)(match.json, field) || null; (0, set_1.default)(entry, ['json', field], value); } }); return entry; } function findAllMatches(data, lookup, disableDotNotation, isEntriesEqual) { return data.reduce((acc, entry2, i) => { if (entry2 === undefined) return acc; for (const key of Object.keys(lookup)) { const excpectedValue = lookup[key]; let entry2FieldValue; if (disableDotNotation) { entry2FieldValue = entry2.json[key]; } else { entry2FieldValue = (0, get_1.default)(entry2.json, key); } if (!isEntriesEqual(excpectedValue, entry2FieldValue)) { return acc; } } return acc.concat({ entry: entry2, index: i, }); }, []); } function findFirstMatch(data, lookup, disableDotNotation, isEntriesEqual) { const index = data.findIndex((entry2) => { if (entry2 === undefined) return false; for (const key of Object.keys(lookup)) { const excpectedValue = lookup[key]; let entry2FieldValue; if (disableDotNotation) { entry2FieldValue = entry2.json[key]; } else { entry2FieldValue = (0, get_1.default)(entry2.json, key); } if (!isEntriesEqual(excpectedValue, entry2FieldValue)) { return false; } } return true; }); if (index === -1) return []; return [{ entry: data[index], index }]; } function findMatches(input1, input2, fieldsToMatch, options) { const data1 = [...input1]; const data2 = [...input2]; const isEntriesEqual = (0, utilities_1.fuzzyCompare)(options.fuzzyCompare, options.nodeVersion); const disableDotNotation = options.disableDotNotation || false; const multipleMatches = options.multipleMatches || 'first'; const skipFields = (options.skipFields || '').split(',').map((field) => field.trim()); if (disableDotNotation && skipFields.some((field) => field.includes('.'))) { const fieldToSkip = skipFields.find((field) => field.includes('.')); const msg = `Dot notation is disabled, but field to skip comparing '${fieldToSkip}' contains dot`; throw new n8n_workflow_1.ApplicationError(msg, { level: 'warning' }); } const filteredData = { matched: [], unmatched1: [], unmatched2: [], }; const matchedInInput2 = new Set(); matchesLoop: for (const entry of data1) { const lookup = {}; fieldsToMatch.forEach((matchCase) => { let valueToCompare; if (disableDotNotation) { valueToCompare = entry.json[matchCase.field1]; } else { valueToCompare = (0, get_1.default)(entry.json, matchCase.field1); } lookup[matchCase.field2] = valueToCompare; }); for (const fieldValue of Object.values(lookup)) { if (fieldValue === undefined) { filteredData.unmatched1.push(entry); continue matchesLoop; } } const foundedMatches = multipleMatches === 'all' ? findAllMatches(data2, lookup, disableDotNotation, isEntriesEqual) : findFirstMatch(data2, lookup, disableDotNotation, isEntriesEqual); const matches = foundedMatches.map((match) => match.entry); foundedMatches.map((match) => matchedInInput2.add(match.index)); if (matches.length) { filteredData.matched.push({ entry, matches }); } else { filteredData.unmatched1.push(entry); } } data2.forEach((entry, i) => { if (!matchedInInput2.has(i)) { filteredData.unmatched2.push(entry); } }); const same = []; const different = []; filteredData.matched.forEach((entryMatches) => { let entryCopy; entryMatches.matches.forEach((match) => { let entryFromInput1 = entryMatches.entry.json; let entryFromInput2 = match.json; if (skipFields.length) { if (disableDotNotation || !skipFields.some((field) => field.includes('.'))) { entryFromInput1 = (0, omit_1.default)(entryFromInput1, skipFields); entryFromInput2 = (0, omit_1.default)(entryFromInput2, skipFields); } else { entryFromInput1 = (0, cloneDeep_1.default)(entryFromInput1); entryFromInput2 = (0, cloneDeep_1.default)(entryFromInput2); skipFields.forEach((field) => { (0, unset_1.default)(entryFromInput1, field); (0, unset_1.default)(entryFromInput2, field); }); } } let isItemsEqual = true; if (options.fuzzyCompare) { for (const key of Object.keys(entryFromInput1)) { if (!isEntriesEqual(entryFromInput1[key], entryFromInput2[key])) { isItemsEqual = false; break; } } } else { isItemsEqual = isEntriesEqual(entryFromInput1, entryFromInput2); } if (isItemsEqual) { if (!entryCopy) { if (options.fuzzyCompare && options.resolve === 'preferInput2') { entryCopy = match; } else { entryCopy = entryMatches.entry; } } } else { switch (options.resolve) { case 'preferInput1': different.push(entryMatches.entry); break; case 'preferInput2': different.push(match); break; case 'mix': different.push(combineItems(entryMatches.entry, match, options.preferWhenMix, options.exceptWhenMix, disableDotNotation)); break; default: different.push(compareItems(entryMatches.entry, match, fieldsToMatch, options, skipFields, isEntriesEqual)); } } }); if (!(0, isEmpty_1.default)(entryCopy)) { same.push(entryCopy); } }); return [filteredData.unmatched1, same, different, filteredData.unmatched2]; } function checkMatchFieldsInput(data) { if (data.length === 1 && data[0].field1 === '' && data[0].field2 === '') { throw new n8n_workflow_1.ApplicationError('You need to define at least one pair of fields in "Fields to Match" to match on', { level: 'warning' }); } for (const [index, pair] of data.entries()) { if (pair.field1 === '' || pair.field2 === '') { throw new n8n_workflow_1.ApplicationError(`You need to define both fields in "Fields to Match" for pair ${index + 1}, field 1 = '${pair.field1}' field 2 = '${pair.field2}'`, { level: 'warning' }); } } return data; } function checkInput(input) { if (!input) return []; if (input.some((item) => (0, isEmpty_1.default)(item.json))) { input = input.filter((item) => !(0, isEmpty_1.default)(item.json)); } return input; } function checkInputAndThrowError(input, fields, disableDotNotation, inputLabel) { if (input.some((item) => (0, isEmpty_1.default)(item.json))) { input = input.filter((item) => !(0, isEmpty_1.default)(item.json)); } if (input.length === 0) { return input; } for (const field of fields) { const isPresent = (input || []).some((entry) => { if (disableDotNotation) { return entry.json.hasOwnProperty(field); } return (0, get_1.default)(entry.json, field, undefined) !== undefined; }); if (!isPresent) { throw new n8n_workflow_1.ApplicationError(`Field '${field}' is not present in any of items in '${inputLabel}'`, { level: 'warning' }); } } return input; } //# sourceMappingURL=GenericFunctions.js.map