function diff (a,b,path='') {
if (path != '') {
for (const p of path.split('.')) {
a = a[p]
b = b[p]
}
}
if (_.isEqual(a,b)) return md`${path} is equal in both states !`
const akeys = _.keys(a)
const bkeys = _.keys(b)
const changed_values = []
const changed_row_count = []
const changed = []
const equalKeys = _.intersection(akeys,bkeys)
const deleted = _.difference(akeys,bkeys)
const added = _.difference(bkeys,akeys)
let candidates = equalKeys.filter(key => !_.isEqual(a[key],b[key]))
for (const key of candidates) {
if (Array.isArray(a[key]) && Array.isArray(b[key])) {
const arra = a[key]
const arrb = b[key]
if (arra.length == arrb.length) {
const n = arra.length
for (const i in _.range(n)) {
if (arra[i] != arrb[i] && changed_values.length<5) {
changed_values.push([key,i,arra[i],arrb[i]])
}
}
} else {
changed_row_count.push(key)
}
} else {
changed.push(key)
}
}
const result = {DIFF:path}
deleted.forEach(key => result['DEL ' + key] = a[key])
added.forEach(key => result['ADD ' + key] = b[key])
changed.forEach(key => result['CHG ' + key] = diff2(a[key],b[key]))
changed_row_count.forEach(key => result['ROW count changed for ' + key] = {old:a[key],new:b[key]})
for (const [key,i,a,b] of changed_values) result['CELL changed for ' + key + ' at index ' + i] = {old:a,new:b}
return result
}