arrays.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { transform, isEqual, isObject, get } from 'lodash'
  2. type Dict = {
  3. [key: string]: boolean | Dict
  4. }
  5. export function diff(newObject: any = {}, oldObject: any = {}, ignore?: Dict) {
  6. const currentIgnoreList = ignore
  7. ? Object.entries(ignore).reduce(
  8. (accumulator, [key, value]) =>
  9. typeof value === 'boolean' ? [...accumulator, key] : accumulator,
  10. [] as string[]
  11. )
  12. : []
  13. const transformResult = transform(
  14. newObject,
  15. (result: any, value: any, key: string) => {
  16. if (!currentIgnoreList.includes(key) && !isEqual(value, oldObject[key])) {
  17. const child = ignore && ignore[key]
  18. let childIgnoreList
  19. if (result instanceof Array) {
  20. childIgnoreList = ignore
  21. } else if (typeof child !== 'boolean') {
  22. childIgnoreList = child
  23. } else {
  24. childIgnoreList = undefined
  25. }
  26. const newValue =
  27. isObject(value) && isObject(oldObject[key])
  28. ? diff(value, oldObject[key], childIgnoreList)
  29. : value
  30. if (newValue !== undefined && newValue !== null) result[key] = newValue
  31. }
  32. }
  33. )
  34. return Object.keys(transformResult).length > 0 ? transformResult : undefined
  35. }
  36. export function deepDiff(
  37. newObject: any = {},
  38. oldObject: any = {},
  39. ignore?: Dict
  40. ) {
  41. return {
  42. added: diff(newObject, oldObject, ignore),
  43. removed: diff(oldObject, newObject, ignore)
  44. }
  45. }
  46. interface IcompareOptions<T> {
  47. compareKeys: (keyof T)[]
  48. diffIgnore?: Dict
  49. keyNames?: {
  50. inA: string
  51. inB: string
  52. }
  53. }
  54. export function compare<T>(
  55. objectsA: T[],
  56. objectsB: T[],
  57. compareOptions: IcompareOptions<T>
  58. ) {
  59. const { keyNames, diffIgnore, compareKeys } = compareOptions
  60. const { inA, inB } = keyNames || { inA: 'inFile', inB: 'inDb' }
  61. let copyB = [...objectsB]
  62. let copyA: T[] = []
  63. for (let objectA of objectsA) {
  64. const idxObjectB = copyB.findIndex(objectB =>
  65. compareKeys.reduce((accumulator, value) => {
  66. console.log(get)
  67. return accumulator && get(objectA, value, 1) === get(objectB, value, 2)
  68. }, true as boolean)
  69. )
  70. const objectB = copyB[idxObjectB]
  71. copyB = [...copyB.slice(0, idxObjectB), ...copyB.slice(idxObjectB + 1)]
  72. copyA = [
  73. ...copyA,
  74. {
  75. ...objectA,
  76. changes: deepDiff(objectA, objectB, diffIgnore),
  77. [inA]: true,
  78. [inB]: !!objectB
  79. }
  80. ]
  81. }
  82. for (let objectB of copyB) {
  83. copyA = [
  84. ...copyA,
  85. {
  86. ...objectB,
  87. changes: deepDiff(undefined, objectB, diffIgnore),
  88. [inA]: false,
  89. [inB]: true
  90. }
  91. ]
  92. }
  93. return copyA
  94. }