{"version":3,"file":"object-changes.mjs","names":[],"sources":["../../../src/common/data/object-changes.ts"],"sourcesContent":["import { arrayMinus } from './array'\nimport { deepEqual } from './deep'\nimport { isRecord } from './is'\nimport { cloneObject } from './utils'\n\n/**\n * Selective in place update, as minimal as possible.\n * Ideal for reactive objects lie Vue's `reactive`.\n */\nexport function objectAssignDeepInPlace(toObject: any, fromObject: any) {\n  if (isRecord(toObject) && isRecord(fromObject)) {\n    // Remove not existing ones\n    const fromKeys = Object.keys(fromObject)\n    for (const key of arrayMinus(Object.keys(toObject), fromKeys))\n      delete toObject[key]\n\n    // Changes\n    for (const key of fromKeys) {\n      const from = fromObject[key]\n      const to = toObject[key]\n      if (isRecord(from)) {\n        if (isRecord(to))\n          objectAssignDeepInPlace(to, from)\n        else\n          toObject[key] = cloneObject(from)\n      }\n      else if (from !== to) {\n        toObject[key] = from\n      }\n    }\n  }\n  return toObject\n}\n\n/**\n * Create a minimal change set. Results in a new object, with only the\n * new or changed entries. Deleted entries are marked by value `null`.\n */\nexport function objectDescribeChange(fromObject: any, toObject: any): any {\n  const change: any = {}\n\n  // Deleted attributes\n  for (const key of arrayMinus(Object.keys(fromObject), Object.keys(toObject)))\n    change[key] = null\n\n  // Changes\n  for (const [key, value] of Object.entries(toObject)) {\n    const from = fromObject[key]\n    if (isRecord(value)) {\n      const subChange = objectDescribeChange(from ?? {}, value)\n      if (subChange != null)\n        change[key] = subChange\n    }\n    else if (!(value == null && from == null)) {\n      if (!deepEqual(value, from))\n        change[key] = value == null ? null : value // avoid undefined\n    }\n  }\n\n  return Object.keys(change).length > 0 ? change : undefined\n}\n\n/**\n * Apply the description of changes created by `objectDescribeChange` to the object.\n */\nexport function objectAssignDescriptionInPlace(toObject: any, fromObject: any) {\n  if (isRecord(toObject) && isRecord(fromObject)) {\n    const fromKeys = Object.keys(fromObject) \n    for (const key of fromKeys) {\n      const from = fromObject[key]\n      const to = toObject[key]\n      if (from === null) {\n        if (to != null) {\n          delete toObject[key]\n        }\n      }\n      else if (isRecord(from)) {\n        if (isRecord(to))\n          objectAssignDescriptionInPlace(to, from)\n        else\n          toObject[key] = cloneObject(from)\n      }\n      else if (from !== to) {\n        toObject[key] = from\n      }\n    }\n  }\n  return toObject\n}\n\n"],"mappings":";;;;;;;;;;AASA,SAAgB,wBAAwB,UAAe,YAAiB;AACtE,KAAI,SAAS,SAAS,IAAI,SAAS,WAAW,EAAE;EAE9C,MAAM,WAAW,OAAO,KAAK,WAAW;AACxC,OAAK,MAAM,OAAO,WAAW,OAAO,KAAK,SAAS,EAAE,SAAS,CAC3D,QAAO,SAAS;AAGlB,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,OAAO,WAAW;GACxB,MAAM,KAAK,SAAS;AACpB,OAAI,SAAS,KAAK,CAChB,KAAI,SAAS,GAAG,CACd,yBAAwB,IAAI,KAAK;OAEjC,UAAS,OAAO,YAAY,KAAK;YAE5B,SAAS,GAChB,UAAS,OAAO;;;AAItB,QAAO;;;;;;AAOT,SAAgB,qBAAqB,YAAiB,UAAoB;CACxE,MAAM,SAAc,EAAE;AAGtB,MAAK,MAAM,OAAO,WAAW,OAAO,KAAK,WAAW,EAAE,OAAO,KAAK,SAAS,CAAC,CAC1E,QAAO,OAAO;AAGhB,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,EAAE;EACnD,MAAM,OAAO,WAAW;AACxB,MAAI,SAAS,MAAM,EAAE;GACnB,MAAM,YAAY,qBAAqB,QAAQ,EAAE,EAAE,MAAM;AACzD,OAAI,aAAa,KACf,QAAO,OAAO;aAET,EAAE,SAAS,QAAQ,QAAQ,OAClC;OAAI,CAAC,UAAU,OAAO,KAAK,CACzB,QAAO,OAAO,SAAS,OAAO,OAAO;;;AAI3C,QAAO,OAAO,KAAK,OAAO,CAAC,SAAS,IAAI,SAAS;;;;;AAMnD,SAAgB,+BAA+B,UAAe,YAAiB;AAC7E,KAAI,SAAS,SAAS,IAAI,SAAS,WAAW,EAAE;EAC9C,MAAM,WAAW,OAAO,KAAK,WAAW;AACxC,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,OAAO,WAAW;GACxB,MAAM,KAAK,SAAS;AACpB,OAAI,SAAS,MACX;QAAI,MAAM,KACR,QAAO,SAAS;cAGX,SAAS,KAAK,CACrB,KAAI,SAAS,GAAG,CACd,gCAA+B,IAAI,KAAK;OAExC,UAAS,OAAO,YAAY,KAAK;YAE5B,SAAS,GAChB,UAAS,OAAO;;;AAItB,QAAO"}