123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- const _ = require('lodash');
- function getObjDiff(oldObj, newObj, opts = {}) {
- const {
- exclude = [],
- excludeAdd = [],
- excludeDel = [],
- } = opts;
- const ex = new Set(exclude);
- const exAdd = new Set(excludeAdd);
- const exDel = new Set(excludeDel);
- const makeObjDiff = (oldObj, newObj, keyPath) => {
- const result = {__isDiff: true, change: {}, add: {}, del: []};
- keyPath = `${keyPath}${keyPath ? '/' : ''}`;
- for (const key of Object.keys(oldObj)) {
- const kp = `${keyPath}${key}`;
- if (newObj.hasOwnProperty(key)) {
- if (ex.has(kp))
- continue;
- if (!_.isEqual(oldObj[key], newObj[key])) {
- if (_.isObject(oldObj[key]) && _.isObject(newObj[key])) {
- result.change[key] = makeObjDiff(oldObj[key], newObj[key], kp);
- } else {
- result.change[key] = _.cloneDeep(newObj[key]);
- }
- }
- } else {
- if (exDel.has(kp))
- continue;
- result.del.push(key);
- }
- }
- for (const key of Object.keys(newObj)) {
- const kp = `${keyPath}${key}`;
- if (exAdd.has(kp))
- continue;
- if (!oldObj.hasOwnProperty(key)) {
- result.add[key] = _.cloneDeep(newObj[key]);
- }
- }
- return result;
- }
- return makeObjDiff(oldObj, newObj, '');
- }
- function isObjDiff(diff) {
- return (_.isObject(diff) && diff.__isDiff && diff.change && diff.add && diff.del);
- }
- function isEmptyObjDiff(diff) {
- return (!isObjDiff(diff) ||
- !(Object.keys(diff.change).length ||
- Object.keys(diff.add).length ||
- diff.del.length
- )
- );
- }
- function isEmptyObjDiffDeep(diff, opts = {}) {
- if (!isObjDiff(diff))
- return true;
- const {
- isApplyChange = true,
- isApplyAdd = true,
- isApplyDel = true,
- } = opts;
- let notEmptyDeep = false;
- const change = diff.change;
- for (const key of Object.keys(change)) {
- if (_.isObject(change[key]))
- notEmptyDeep |= !isEmptyObjDiffDeep(change[key], opts);
- else if (isApplyChange)
- notEmptyDeep = true;
- }
- return !(
- notEmptyDeep ||
- (isApplyAdd && Object.keys(diff.add).length) ||
- (isApplyDel && diff.del.length)
- );
- }
- function applyObjDiff(obj, diff, opts = {}) {
- const {
- isAddChanged = false,
- isApplyChange = true,
- isApplyAdd = true,
- isApplyDel = true,
- } = opts;
- let result = _.cloneDeep(obj);
- if (!diff.__isDiff)
- return result;
- const change = diff.change;
- for (const key of Object.keys(change)) {
- if (result.hasOwnProperty(key)) {
- if (_.isObject(change[key])) {
- result[key] = applyObjDiff(result[key], change[key], opts);
- } else {
- if (isApplyChange)
- result[key] = _.cloneDeep(change[key]);
- }
- } else if (isAddChanged) {
- result[key] = _.cloneDeep(change[key]);
- }
- }
- if (isApplyAdd) {
- for (const key of Object.keys(diff.add)) {
- result[key] = _.cloneDeep(diff.add[key]);
- }
- }
- if (isApplyDel && diff.del.length) {
- for (const key of diff.del) {
- delete result[key];
- }
- if (_.isArray(result))
- result = result.filter(v => v);
- }
- return result;
- }
- module.exports = {
- getObjDiff,
- isObjDiff,
- isEmptyObjDiff,
- applyObjDiff,
- }
|