n8n-nodes-base
Version:
Base nodes of n8n
207 lines • 8.22 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.description = void 0;
exports.execute = execute;
const get_1 = __importDefault(require("lodash/get"));
const isEqual_1 = __importDefault(require("lodash/isEqual"));
const lt_1 = __importDefault(require("lodash/lt"));
const pick_1 = __importDefault(require("lodash/pick"));
const n8n_workflow_1 = require("n8n-workflow");
const utilities_1 = require("../../../../../utils/utilities");
const utils_1 = require("../../helpers/utils");
const common_descriptions_1 = require("../common.descriptions");
const properties = [
{
displayName: 'Compare',
name: 'compare',
type: 'options',
options: [
{
name: 'All Fields',
value: 'allFields',
},
{
name: 'All Fields Except',
value: 'allFieldsExcept',
},
{
name: 'Selected Fields',
value: 'selectedFields',
},
],
default: 'allFields',
description: 'The fields of the input items to compare to see if they are the same',
},
{
displayName: 'Fields To Exclude',
name: 'fieldsToExclude',
type: 'string',
placeholder: 'e.g. email, name',
requiresDataPath: 'multiple',
description: 'Fields in the input to exclude from the comparison',
default: '',
displayOptions: {
show: {
compare: ['allFieldsExcept'],
},
},
},
{
displayName: 'Fields To Compare',
name: 'fieldsToCompare',
type: 'string',
placeholder: 'e.g. email, name',
requiresDataPath: 'multiple',
description: 'Fields in the input to add to the comparison',
default: '',
displayOptions: {
show: {
compare: ['selectedFields'],
},
},
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
compare: ['allFieldsExcept', 'selectedFields'],
},
},
options: [
common_descriptions_1.disableDotNotationBoolean,
{
displayName: 'Remove Other Fields',
name: 'removeOtherFields',
type: 'boolean',
default: false,
description: 'Whether to remove any fields that are not being compared. If disabled, will keep the values from the first of the duplicates.',
},
],
},
];
const displayOptions = {
show: {
resource: ['itemList'],
operation: ['removeDuplicates'],
},
};
exports.description = (0, utilities_1.updateDisplayOptions)(displayOptions, properties);
async function execute(items) {
const compare = this.getNodeParameter('compare', 0);
const disableDotNotation = this.getNodeParameter('options.disableDotNotation', 0, false);
const removeOtherFields = this.getNodeParameter('options.removeOtherFields', 0, false);
const nodeVersion = this.getNode().typeVersion;
let keys = disableDotNotation
? Object.keys(items[0].json)
: Object.keys((0, utilities_1.flattenKeys)(items[0].json));
for (const item of items) {
for (const key of disableDotNotation
? Object.keys(item.json)
: Object.keys((0, utilities_1.flattenKeys)(item.json))) {
if (!keys.includes(key)) {
keys.push(key);
}
}
}
if (compare === 'allFieldsExcept') {
const fieldsToExclude = (0, utils_1.prepareFieldsArray)(this.getNodeParameter('fieldsToExclude', 0, ''), 'Fields To Exclude');
if (!fieldsToExclude.length) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No fields specified. Please add a field to exclude from comparison');
}
if (!disableDotNotation) {
keys = Object.keys((0, utilities_1.flattenKeys)(items[0].json));
}
keys = keys.filter((key) => !fieldsToExclude.includes(key));
}
if (compare === 'selectedFields') {
const fieldsToCompare = (0, utils_1.prepareFieldsArray)(this.getNodeParameter('fieldsToCompare', 0, ''), 'Fields To Compare');
if (!fieldsToCompare.length) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No fields specified. Please add a field to compare on');
}
if (!disableDotNotation) {
keys = Object.keys((0, utilities_1.flattenKeys)(items[0].json));
}
keys = fieldsToCompare.map((key) => key.trim());
}
// This solution is O(nlogn)
// add original index to the items
const newItems = items.map((item, index) => ({
json: { ...item.json, __INDEX: index },
pairedItem: { item: index },
}));
//sort items using the compare keys
newItems.sort((a, b) => {
let result = 0;
for (const key of keys) {
const a_value = disableDotNotation ? a.json[key] : (0, get_1.default)(a.json, key);
const b_value = disableDotNotation ? b.json[key] : (0, get_1.default)(b.json, key);
if (nodeVersion >= 3.1) {
const a_value_tnum = (0, utils_1.typeToNumber)(a_value);
const b_value_tnum = (0, utils_1.typeToNumber)(b_value);
if (a_value_tnum !== b_value_tnum) {
result = a_value_tnum - b_value_tnum;
break;
}
}
const equal = (0, isEqual_1.default)(a_value, b_value);
if (!equal) {
const lessThan = (0, lt_1.default)(a_value, b_value);
result = lessThan ? -1 : 1;
break;
}
}
return result;
});
for (const key of keys) {
let type = undefined;
for (const item of newItems) {
if (key === '') {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Name of field to compare is blank');
}
const value = !disableDotNotation ? (0, get_1.default)(item.json, key) : item.json[key];
if (value === undefined && disableDotNotation && key.includes('.')) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `'${key}' field is missing from some input items`, {
description: "If you're trying to use a nested field, make sure you turn off 'disable dot notation' in the node options",
});
}
else if (value === undefined) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `'${key}' field is missing from some input items`);
}
if (nodeVersion < 3.1 && type !== undefined && value !== undefined && type !== typeof value) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `'${key}' isn't always the same type`, {
description: 'The type of this field varies between items',
});
}
else {
type = typeof value;
}
}
}
// collect the original indexes of items to be removed
const removedIndexes = [];
let temp = newItems[0];
for (let index = 1; index < newItems.length; index++) {
if ((0, utilities_1.compareItems)(newItems[index], temp, keys, disableDotNotation)) {
removedIndexes.push(newItems[index].json.__INDEX);
}
else {
temp = newItems[index];
}
}
let returnData = items.filter((_, index) => !removedIndexes.includes(index));
if (removeOtherFields) {
returnData = returnData.map((item, index) => ({
json: (0, pick_1.default)(item.json, ...keys),
pairedItem: { item: index },
}));
}
return returnData;
}
//# sourceMappingURL=removeDuplicates.operation.js.map