UNPKG

@open-kappa/myjson

Version:

A simple JSON management library.

180 lines 5.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mergeJson = exports.JsonMergePolicy = void 0; /* eslint-disable no-shadow */ /** * @brief Enum to list possible behaviors in case of conflicting values * during JSON merge. */ var JsonMergePolicy; (function (JsonMergePolicy) { JsonMergePolicy[JsonMergePolicy["KEEP_LEFT"] = 0] = "KEEP_LEFT"; JsonMergePolicy[JsonMergePolicy["KEEP_RIGHT"] = 1] = "KEEP_RIGHT"; JsonMergePolicy[JsonMergePolicy["CONFLICT"] = 2] = "CONFLICT"; })(JsonMergePolicy || (JsonMergePolicy = {})); exports.JsonMergePolicy = JsonMergePolicy; /* eslint-enable no-shadow */ /** * @brief Merge two arrays. * @private * @param {Array<any>} a1 The left array. * @param {Array<any>} a2 The right array. * @param {JsonMergePolicy} policy The merge policy. * @param {(j1: any, j2: any) => boolean} arrayComparator The element * comparator. * @return {Error | null} null in case of success. */ function _mergeTwoArrays(a1, a2, policy, arrayComparator) { for (let i = 0; i < a2.length; ++i) { const e2 = a2[i]; let found = false; let j = 0; for (; j < a1.length; ++j) { const e1 = a1[j]; found = arrayComparator(e1, e2); if (found) break; } if (!found) { a1.push(e2); } else { const e1 = a1[j]; // eslint-disable-next-line no-use-before-define const ret = _mergeObjectHelper(a1, j, e1, e2, policy, arrayComparator); if (ret !== null) return ret; } } return null; } /** * @brief Merge two objects. * @private * @param {any} o1 The left parent object. * @param {string | number} k The key under merging. * @param {any} v1 The left value. * @param {any} v2 The right value. * @param {JsonMergePolicy} policy The merge policy. * @param {(j1: any, j2: any) => boolean} arrayComparator The element * comparator. * @return {Error | null} null in case of success. */ function _mergeObjectHelper(o1, k, v1, v2, policy, arrayComparator) { const t1 = typeof v1; const t2 = typeof v2; if (Array.isArray(v1) && Array.isArray(v2)) { return _mergeTwoArrays(v1, v2, policy, arrayComparator); } else if (t1 !== t2) { // Keep one: switch (policy) { case JsonMergePolicy.KEEP_LEFT: return null; case JsonMergePolicy.KEEP_RIGHT: o1[k] = v2; return null; case JsonMergePolicy.CONFLICT: return new Error("Conflict on key " + k); default: } } else if (t1 === "object") { // eslint-disable-next-line no-use-before-define return _mergeTwoObjects(v1, v2, policy, arrayComparator); } else if (t1 === "number" || t1 === "string" || t1 === "boolean") { // Keep one: switch (policy) { case JsonMergePolicy.KEEP_LEFT: return null; case JsonMergePolicy.KEEP_RIGHT: o1[k] = v2; return null; case JsonMergePolicy.CONFLICT: if (v1 !== v2) { return new Error("Conflict on key " + k); } return null; default: } } return new Error("Cannot merge type " + t1 + " with type " + t2); } /** * @brief Merge two objects. * @private * @param {any} o1 The left value. * @param {any} o2 The right value. * @param {JsonMergePolicy} policy The merge policy. * @param {(j1: any, j2: any) => boolean} arrayComparator The element * comparator. * @return {Error | null} null in case of success. */ function _mergeTwoObjects(o1, o2, policy, arrayComparator) { const keys2 = Object.keys(o2); for (let i = 0; i < keys2.length; ++i) { const k = keys2[i]; const v1 = o1[k]; const v2 = o2[k]; if (typeof v1 === "undefined") { o1[k] = v2; continue; } const res = _mergeObjectHelper(o1, k, v1, v2, policy, arrayComparator); if (res !== null) return res; } return null; } /** * @brief Default comparator. * @param {any} _j1 The first object. * @param {any} _j2 The second object. * @return {boolean} Always false. */ function appendArrayComparator(_j1, _j2) { return false; } /** * @brief Merge all the given JSONs. * @param {Array<any>} jsons The list of JSONs to merge. * @param {JsonMergePolicy} policy The merge policy. * @param {(j1: any, j2: any) => boolean} arrayComparator The comparator to use. * Default is appendArrayComparator. * @return {Promise<any>} A new JSON, as result. */ function mergeJson(jsons, policy = JsonMergePolicy.KEEP_LEFT, arrayComparator = appendArrayComparator) { if (jsons.length === 0) return Promise.resolve({}); const first = jsons[0]; if (Array.isArray(first)) { const ret = []; for (let i = 0; i < jsons.length; ++i) { const res = _mergeTwoArrays(ret, jsons[i], policy, arrayComparator); if (res !== null) return Promise.reject(res); } return Promise.resolve(ret); } else if (typeof first === "object") { const ret = {}; for (let i = 0; i < jsons.length; ++i) { const res = _mergeTwoObjects(ret, jsons[i], policy, arrayComparator); if (res !== null) return Promise.reject(res); } return Promise.resolve(ret); } else if (jsons.length === 1 && (typeof jsons[0] === "number" || typeof jsons[0] === "string" || typeof jsons[0] === "boolean")) { return Promise.resolve(jsons[0]); } return Promise.reject(new Error("Unable to perform the merge.")); } exports.mergeJson = mergeJson; //# sourceMappingURL=mergeJson.js.map