"use strict"; const defaultValue = require("default-value"); const syncpipe = require("syncpipe"); const arrayUnique = require("../util/array-unique"); const pickTaskResult = require("./pick-task-result"); function taskResultsToObject(taskResults) { return syncpipe(taskResults, [ (_) => _.map((result) => [ result.taskName, result.metadata ]), (_) => Object.fromEntries(_) ]); } module.exports = function mergeItems({ fromObj, intoObj, merge, mergeMetadata }) { let mergedData = merge(intoObj.data, fromObj.data); let fromTaskResults = taskResultsToObject(fromObj.taskResults); let intoTaskResults = taskResultsToObject(intoObj.taskResults); let allTaskKeys = arrayUnique([ ... Object.keys(fromTaskResults), ... Object.keys(intoTaskResults) ]); // TODO: Use merge-by-template here instead? let mergedTaskResults = allTaskKeys.map((key) => { let merger = mergeMetadata[key]; let fromTask = fromTaskResults[key]; let intoTask = intoTaskResults[key]; if (merger != null) { // Generate a new TaskResult that includes data combined from both let newMetadata = merger( defaultValue(intoTask.metadata, {}), defaultValue(fromTask.metadata, {}) ); return { ... intoTask, metadata: newMetadata, updatedAt: Date.now() }; } else { // Take the newest known TaskResult and just make sure that it is pointing at the correct ID // TODO: Does this really belong in the semantics module? Or is this database-specific? return { ... pickTaskResult(intoTask, fromTask), itemId: intoObj.id }; } }); return { id: intoObj.id, data: mergedData, taskResults: mergedTaskResults }; };