@web3r/flowerkit
Version:
Tree-shakable JavaScript and TypeScript utility library for frontend/browser apps: DOM, events, arrays, objects, strings, date, JSON, and network helpers (ESM/CJS, SSR-friendly).
1 lines • 8.86 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":[""],"sourcesContent":["import { isObjHasOwnProp } from \"../isObjHasOwnProp/index.ts\";\r\n\r\nexport type TGetMergedObjArgs = Parameters<typeof getMergedObj>;\r\n\r\nexport type TGetMergedObjReturn = ReturnType<typeof getMergedObj>;\r\n\r\n/**\r\n * Gets one deeply merged object from two objects\r\n * @template TTarget,TSource\r\n * @param {TTarget} [target={}] Target object (cloned internally)\r\n * @param {TSource} [source={}] Source object\r\n * @param {{ isMergeArrays?: boolean; arrayStrategy?: \"concat\" | \"target\" | \"replace\" | \"unique\"; }} [options={}] Merge options\r\n * @param {boolean} [options.isMergeArrays=true] Concat nested arrays or keep target arrays (deprecated; use arrayStrategy)\r\n * @param {\"concat\"|\"target\"|\"replace\"|\"unique\"} [options.arrayStrategy=\"concat\"] Array merge strategy\r\n * @returns {TTarget & TSource} Deeply merged object\r\n * @example\r\n * // How to deeply merge two objects?\r\n * const targetObj = { first: [ \"foo\" ] };\r\n * const sourceObj = { first: [ \"moo\" ], boo: 12 };\r\n * getMergedObj(targetObj, sourceObj) // => { first: [ \"foo\", \"moo\" ], boo: 12 }\r\n */\r\nexport const getMergedObj = <\r\n TTarget extends Record<string, any> = Record<string, any>,\r\n TSource extends Record<string, any> = Record<string, any>\r\n>(\r\n target: TTarget = {} as TTarget,\r\n source: TSource = {} as TSource,\r\n options: { isMergeArrays?: boolean; arrayStrategy?: \"concat\" | \"target\" | \"replace\" | \"unique\"; } = {}\r\n): TTarget & TSource => {\r\n\r\n const settings = {\r\n arrayStrategy: \"concat\" as const,\r\n ...options,\r\n };\r\n\r\n if (options?.isMergeArrays !== undefined) {\r\n settings.arrayStrategy = options.isMergeArrays ? \"concat\" : \"target\";\r\n }\r\n\r\n const isPlainObject = (obj: unknown): obj is Record<string, unknown> => {\r\n if (!obj || typeof obj !== \"object\") {\r\n return false;\r\n }\r\n const proto = Object.getPrototypeOf(obj);\r\n return (proto === Object.prototype || proto === null) && !Array.isArray(obj);\r\n };\r\n\r\n const deepClone = (val: any, visited = new Map()): any => {\r\n if (val && typeof val === \"object\") {\r\n if (visited.has(val)) {\r\n return visited.get(val);\r\n }\r\n\r\n if (Array.isArray(val)) {\r\n visited.set(val, []);\r\n const result = val.map((item) => deepClone(item, visited));\r\n visited.set(val, result);\r\n return result;\r\n }\r\n\r\n if (isPlainObject(val)) {\r\n visited.set(val, {});\r\n const result = Object.fromEntries(\r\n Object.entries(val).map(([ k, v ]) => [ k, deepClone(v, visited) ])\r\n );\r\n visited.set(val, result);\r\n return result;\r\n }\r\n\r\n if (val instanceof Date) {\r\n return new Date(val);\r\n }\r\n if (val instanceof Map) {\r\n const result = new Map();\r\n visited.set(val, result);\r\n val.forEach((v, k) => result.set(k, deepClone(v, visited)));\r\n return result;\r\n }\r\n if (val instanceof Set) {\r\n const result = new Set();\r\n visited.set(val, result);\r\n val.forEach((v) => result.add(deepClone(v, visited)));\r\n return result;\r\n }\r\n\r\n return val;\r\n }\r\n\r\n return val;\r\n };\r\n\r\n const mergeArrays = (a: any[], b: any[]): any[] => {\r\n switch (settings.arrayStrategy) {\r\n case \"target\": return deepClone(a);\r\n case \"replace\": return deepClone(b);\r\n case \"unique\": {\r\n const seen = new Set<any>();\r\n const out: any[] = [];\r\n\r\n const addToOut = (item: any) => {\r\n const cloned = deepClone(item);\r\n const key = typeof cloned === \"object\" && cloned !== null\r\n ? JSON.stringify(cloned)\r\n : cloned;\r\n if (!seen.has(key)) {\r\n seen.add(key);\r\n out.push(cloned);\r\n }\r\n };\r\n\r\n a.forEach(addToOut);\r\n b.forEach(addToOut);\r\n return out;\r\n }\r\n case \"concat\":\r\n default:\r\n return [ ...deepClone(a), ...deepClone(b) ];\r\n }\r\n };\r\n\r\n const merge = (t: any, s: any, visited = new Map()): any => {\r\n if (t && typeof t === \"object\" && s && typeof s === \"object\") {\r\n if (visited.has(t) && visited.get(t) === s) {\r\n return visited.get(t);\r\n }\r\n visited.set(t, s);\r\n }\r\n\r\n if (Array.isArray(t) && Array.isArray(s)) {\r\n return mergeArrays(t, s);\r\n }\r\n\r\n if (!isPlainObject(t) || !isPlainObject(s)) {\r\n return deepClone(s);\r\n }\r\n\r\n const out: Record<string, any> = deepClone(t);\r\n\r\n for (const k in s) {\r\n if (isObjHasOwnProp(s, k)) {\r\n const tv = out[k];\r\n const sv = s[k];\r\n\r\n if (Array.isArray(tv) && Array.isArray(sv)) {\r\n out[k] = mergeArrays(tv, sv);\r\n } else if (isPlainObject(tv) && isPlainObject(sv)) {\r\n out[k] = merge(tv, sv, visited);\r\n } else {\r\n out[k] = deepClone(sv);\r\n }\r\n }\r\n }\r\n\r\n const sourceSymbols = Object.getOwnPropertySymbols(s);\r\n for (const sym of sourceSymbols) {\r\n const tv = out[sym as any];\r\n const sv = s[sym as any];\r\n\r\n if (Array.isArray(tv) && Array.isArray(sv)) {\r\n out[sym as any] = mergeArrays(tv, sv);\r\n } else if (isPlainObject(tv) && isPlainObject(sv)) {\r\n out[sym as any] = merge(tv, sv, visited);\r\n } else {\r\n out[sym as any] = deepClone(sv);\r\n }\r\n }\r\n\r\n return out;\r\n };\r\n\r\n return merge(target, source);\r\n};\r\n"],"names":["getMergedObj","target","source","options","settings","arrayStrategy","isMergeArrays","undefined","isPlainObject","obj","proto","Object","getPrototypeOf","prototype","Array","isArray","deepClone","val","visited","Map","has","get","set","result","map","item","fromEntries","entries","k","v","Date","forEach","Set","add","mergeArrays","a","b","seen","out","addToOut","cloned","key","JSON","stringify","push","merge","t","s","isObjHasOwnProp","tv","sv","sourceSymbols","getOwnPropertySymbols","sym"],"mappings":"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"}