UNPKG

@vtex/api

Version:
138 lines (137 loc) 5.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MineWinsConflictsResolver = void 0; const js_base64_1 = require("js-base64"); const ramda_1 = require("ramda"); const util_1 = require("util"); class MineWinsConflictsResolver { constructor(client, bucket, filePath, comparableKeys) { this.client = client; this.bucket = bucket; this.filePath = filePath; this.comparableKeys = comparableKeys; } async resolve(logger) { return await this.client.getConflicts(this.bucket).then((data) => { const { data: conflicts } = data; const selectedConflict = conflicts.find((conflict) => conflict.path === this.filePath); if (!selectedConflict) { throw { message: 'No conflict could be found.', status: 404, }; } selectedConflict.base.parsedContent = this.parseConflict(selectedConflict.base); selectedConflict.master.parsedContent = this.parseConflict(selectedConflict.master); selectedConflict.mine.parsedContent = this.parseConflict(selectedConflict.mine); const resolved = this.resolveConflictMineWins(selectedConflict); return resolved; }); } async resolveAll() { const conflictsResponse = await this.client.getConflicts(this.bucket); const { data: conflicts } = conflictsResponse; const resolvedConflicts = conflicts.map((conflict) => { conflict.base.parsedContent = this.parseConflict(conflict.base); conflict.master.parsedContent = this.parseConflict(conflict.master); conflict.mine.parsedContent = this.parseConflict(conflict.mine); return this.resolveConflictMineWins(conflict); }); return resolvedConflicts; } mergeMineWins(base, master, mine) { if ((0, util_1.isArray)(master)) { return this.mergeMineWinsArray((base || []), master, (mine || [])); } else if ((0, util_1.isObject)(master)) { return this.mergeMineWinsObject((base || {}), master, (mine || {})); } return mine ? mine : master; } parseConflict(conflict) { if (!conflict || !conflict.content) { return {}; } return this.parseContentByMimetype(js_base64_1.Base64.decode(conflict.content), conflict.mimeType); } serializeContentByMimetype(content, mimetype) { if (mimetype === 'application/json') { return JSON.stringify(content); } return content; } parseContentByMimetype(content, mimetype) { if (mimetype === 'application/json') { return JSON.parse(content); } return content; } resolveConflictMineWins(conflict) { if (!conflict) { throw { message: 'No conflict could be found.', status: 404, }; } const { base, master, mine, path } = conflict; const merged = this.mergeMineWins(base.parsedContent, master.parsedContent, mine.parsedContent); const mergedContent = { content: js_base64_1.Base64.encode(this.serializeContentByMimetype(merged, conflict.mine.mimeType)), mimeType: conflict.mine.mimeType, }; this.client.resolveConflict(this.bucket, path, mergedContent); return merged; } mergeMineWinsObject(base, master, mine) { const merged = { ...master, ...mine }; Object.entries(merged).forEach(([key, value]) => { if (master[key] == null && base && base[key] != null && (0, ramda_1.equals)(value, base[key])) { delete merged[key]; // value deleted from master with no conflict } else if (base[key] && master[key] && !mine[key]) { delete merged[key]; // value deleted from mine } else if ((0, util_1.isArray)(value)) { merged[key] = this.mergeMineWinsArray((base[key] || []), (master[key] || []), value); } else if ((0, util_1.isObject)(value)) { merged[key] = this.mergeMineWins((base[key] || {}), (master[key] || {}), (value || {})); } }); return merged; } mergeMineWinsArray(base, master, mine) { this.removeMasterDeletedElements(base, master, mine); this.appendMasterAddedElements(base, master, mine); return mine; } removeMasterDeletedElements(base, master, mine) { base.forEach((baseItem) => { const foundInMaster = this.isObjectInArray(baseItem, master); if (!foundInMaster) { const foundInMine = mine.findIndex((mineItem) => (0, ramda_1.equals)(mineItem, baseItem)); if (foundInMine > -1) { mine.splice(foundInMine, 1); } } }); } isObjectInArray(obj, array) { return array.find((item) => (0, ramda_1.equals)(item, obj)); } appendMasterAddedElements(base, master, mine) { master.forEach((item) => { if (this.shouldAddToMine(item, base, mine)) { mine.push(item); } }); } shouldAddToMine(item, base, mine) { if (this.comparableKeys && Object.keys(item).some((key) => this.comparableKeys.includes(key))) { return (!mine.some((mineItem) => this.comparableKeys.some((key) => (0, ramda_1.eqProps)(key, item, mineItem))) && !base.some((baseItem) => (0, ramda_1.equals)(baseItem, item))); } return !mine.some((mineItem) => (0, ramda_1.equals)(mineItem, item)) && !base.some((baseItem) => (0, ramda_1.equals)(baseItem, item)); } } exports.MineWinsConflictsResolver = MineWinsConflictsResolver;