n8n-nodes-base
Version:
Base nodes of n8n
334 lines • 14.3 kB
JavaScript
;
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