{"version":3,"file":"deep-clone.mjs","names":[],"sources":["../src/deep-clone.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n                       🗲 Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website:                  https://stormsoftware.com\n Repository:               https://github.com/storm-software/stryke\n Documentation:            https://docs.stormsoftware.com/projects/stryke\n Contact:                  https://stormsoftware.com/contact\n\n SPDX-License-Identifier:  Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { isPrimitive, isTypedArray } from \"@stryke/type-checks\";\n\nexport type Resolved<T> =\n  Equal<T, ResolvedMain<T>> extends true ? T : ResolvedMain<T>;\n\ntype Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;\n\ntype ResolvedMain<T> = T extends [never]\n  ? never // (special trick for jsonable | null) type\n  : ValueOf<T> extends boolean | number | bigint | string\n    ? ValueOf<T>\n    : T extends (...args: any[]) => any\n      ? never\n      : T extends object\n        ? ResolvedObject<T>\n        : ValueOf<T>;\n\ntype ResolvedObject<T extends object> = T extends (infer U)[]\n  ? IsTuple<T> extends true\n    ? ResolvedTuple<T>\n    : ResolvedMain<U>[]\n  : T extends Set<infer U>\n    ? Set<ResolvedMain<U>>\n    : T extends Map<infer K, infer V>\n      ? Map<ResolvedMain<K>, ResolvedMain<V>>\n      : T extends WeakSet<any> | WeakMap<any, any>\n        ? never\n        : T extends\n              | Date\n              | Uint8Array\n              | Uint8ClampedArray\n              | Uint16Array\n              | Uint32Array\n              | BigUint64Array\n              | Int8Array\n              | Int16Array\n              | Int32Array\n              | BigInt64Array\n              | Float32Array\n              | Float64Array\n              | ArrayBuffer\n              | SharedArrayBuffer\n              | DataView\n              | Blob\n              | File\n          ? T\n          : {\n              [P in keyof T]: ResolvedMain<T[P]>;\n            };\n\ntype ResolvedTuple<T extends readonly any[]> = T extends []\n  ? []\n  : T extends [infer F]\n    ? [ResolvedMain<F>]\n    : T extends [infer F, ...infer Rest extends readonly any[]]\n      ? [ResolvedMain<F>, ...ResolvedTuple<Rest>]\n      : T extends [(infer F)?]\n        ? [ResolvedMain<F>?]\n        : T extends [(infer F)?, ...infer Rest extends readonly any[]]\n          ? [ResolvedMain<F>?, ...ResolvedTuple<Rest>]\n          : [];\n\ntype IsTuple<T extends readonly any[] | { length: number }> = [T] extends [\n  never\n]\n  ? false\n  : T extends readonly any[]\n    ? number extends T[\"length\"]\n      ? false\n      : true\n    : false;\n\ntype ValueOf<Instance> =\n  IsValueOf<Instance, boolean> extends true\n    ? boolean\n    : IsValueOf<Instance, number> extends true\n      ? number\n      : IsValueOf<Instance, string> extends true\n        ? string\n        : Instance;\n\ntype IsValueOf<Instance, O extends ValueOfInterface<any>> = Instance extends O\n  ? O extends ValueOfInterface<infer Primitive>\n    ? Instance extends Primitive\n      ? false\n      : true // not Primitive, but Object\n    : false // cannot be\n  : false;\n\ninterface ValueOfInterface<T> {\n  valueOf: () => T;\n}\n\n/**\n * Creates a deep clone of the given object.\n *\n * @remarks\n * This function creates a deep clone of the given object, including nested objects and arrays. The resulting output will be of type `Resolved<T>`, which is a type that resolves to the most specific type possible for the given input type `T`. **If you are just looking for a way to copy an object deeply, use {@link deepCopy} instead.**\n *\n * @example\n * ```typescript\n * // Clone a primitive values\n * const num = 29;\n * const clonedNum = clone(num);\n * console.log(clonedNum); // 29\n * console.log(clonedNum === num) ; // true\n *\n * // Clone an array\n * const arr = [1, 2, 3];\n * const clonedArr = clone(arr);\n * console.log(clonedArr); // [1, 2, 3]\n * console.log(clonedArr === arr); // false\n *\n * // Clone an array with nested objects\n * const arr = [1, { a: 1 }, [1, 2, 3]];\n * const clonedArr = clone(arr);\n * arr[1].a = 2;\n * console.log(arr); // [2, { a: 2 }, [1, 2, 3]]\n * console.log(clonedArr); // [1, { a: 1 }, [1, 2, 3]]\n * console.log(clonedArr === arr); // false\n *\n * // Clone an object\n * const obj = { a: 1, b: 'es-toolkit', c: [1, 2, 3] };\n * const clonedObj = clone(obj);\n * console.log(clonedObj); // { a: 1, b: 'es-toolkit', c: [1, 2, 3] }\n * console.log(clonedObj === obj); // false\n *\n *\n * // Clone an object with nested objects\n * const obj = { a: 1, b: { c: 1 } };\n * const clonedObj = clone(obj);\n * obj.b.c = 2;\n * console.log(obj); // { a: 1, b: { c: 2 } }\n * console.log(clonedObj); // { a: 1, b: { c: 1 } }\n * console.log(clonedObj === obj); // false\n * ```\n *\n * @param obj - The object to clone.\n * @returns A deep clone of the given object.\n */\nexport function deepClone<T>(obj: T): Resolved<T> {\n  if (isPrimitive(obj)) {\n    return obj as Resolved<T>;\n  }\n\n  if (Array.isArray(obj)) {\n    return obj.map(item => deepClone(item)) as Resolved<T>;\n  }\n\n  if (obj instanceof Date) {\n    return new Date(obj.getTime()) as Resolved<T>;\n  }\n\n  if (obj instanceof RegExp) {\n    return new RegExp(obj.source, obj.flags) as Resolved<T>;\n  }\n\n  if (obj instanceof Map) {\n    const result = new Map();\n    for (const [key, value] of obj.entries()) {\n      result.set(key, deepClone(value));\n    }\n    return result as Resolved<T>;\n  }\n\n  if (obj instanceof Set) {\n    const result = new Set();\n    for (const value of obj.values()) {\n      result.add(deepClone(value));\n    }\n    return result as Resolved<T>;\n  }\n\n  if (isTypedArray(obj)) {\n    // eslint-disable-next-line ts/no-unsafe-call\n    const result = new (Object.getPrototypeOf(obj).constructor)(obj.length);\n\n    for (const [i, element] of obj.entries()) {\n      result[i] = deepClone(element);\n    }\n    return result as Resolved<T>;\n  }\n\n  if (\n    obj instanceof ArrayBuffer ||\n    (typeof SharedArrayBuffer !== \"undefined\" &&\n      obj instanceof SharedArrayBuffer)\n  ) {\n    return [...(obj as any)] as Resolved<T>;\n  }\n\n  if (obj instanceof DataView) {\n    const result = new DataView([...(obj.buffer as any)] as any);\n    cloneDeepHelper(obj, result);\n    return result as Resolved<T>;\n  }\n\n  // For legacy NodeJS support\n  if (typeof File !== \"undefined\" && obj instanceof File) {\n    const result = new File([obj], obj.name, { type: obj.type });\n    cloneDeepHelper(obj, result);\n    return result as Resolved<T>;\n  }\n\n  if (obj instanceof Blob) {\n    const result = new Blob([obj], { type: obj.type });\n    cloneDeepHelper(obj, result);\n    return result as Resolved<T>;\n  }\n\n  if (obj instanceof Error) {\n    const result = new (obj.constructor as new () => Error)();\n    result.message = obj.message;\n    result.name = obj.name;\n    result.stack = obj.stack;\n    result.cause = obj.cause;\n    cloneDeepHelper(obj, result);\n    return result as Resolved<T>;\n  }\n\n  if (typeof obj === \"object\" && obj !== null) {\n    const result = {};\n    cloneDeepHelper(obj, result);\n    return result as Resolved<T>;\n  }\n\n  return obj as Resolved<T>;\n}\n\nfunction cloneDeepHelper(obj: any, clonedObj: any): void {\n  const keys = Object.keys(obj);\n\n  for (const key of keys) {\n    const descriptor = Object.getOwnPropertyDescriptor(obj, key);\n\n    if (descriptor?.writable || descriptor?.set) {\n      clonedObj[key] = deepClone(obj[key]);\n    }\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8JA,SAAgB,UAAa,KAAqB;AAChD,KAAI,YAAY,IAAI,CAClB,QAAO;AAGT,KAAI,MAAM,QAAQ,IAAI,CACpB,QAAO,IAAI,KAAI,SAAQ,UAAU,KAAK,CAAC;AAGzC,KAAI,eAAe,KACjB,QAAO,IAAI,KAAK,IAAI,SAAS,CAAC;AAGhC,KAAI,eAAe,OACjB,QAAO,IAAI,OAAO,IAAI,QAAQ,IAAI,MAAM;AAG1C,KAAI,eAAe,KAAK;EACtB,MAAM,yBAAS,IAAI,KAAK;AACxB,OAAK,MAAM,CAAC,KAAK,UAAU,IAAI,SAAS,CACtC,QAAO,IAAI,KAAK,UAAU,MAAM,CAAC;AAEnC,SAAO;;AAGT,KAAI,eAAe,KAAK;EACtB,MAAM,yBAAS,IAAI,KAAK;AACxB,OAAK,MAAM,SAAS,IAAI,QAAQ,CAC9B,QAAO,IAAI,UAAU,MAAM,CAAC;AAE9B,SAAO;;AAGT,KAAI,aAAa,IAAI,EAAE;EAErB,MAAM,SAAS,KAAK,OAAO,eAAe,IAAI,EAAC,YAAa,IAAI,OAAO;AAEvE,OAAK,MAAM,CAAC,GAAG,YAAY,IAAI,SAAS,CACtC,QAAO,KAAK,UAAU,QAAQ;AAEhC,SAAO;;AAGT,KACE,eAAe,eACd,OAAO,sBAAsB,eAC5B,eAAe,kBAEjB,QAAO,CAAC,GAAI,IAAY;AAG1B,KAAI,eAAe,UAAU;EAC3B,MAAM,SAAS,IAAI,SAAS,CAAC,GAAI,IAAI,OAAe,CAAQ;AAC5D,kBAAgB,KAAK,OAAO;AAC5B,SAAO;;AAIT,KAAI,OAAO,SAAS,eAAe,eAAe,MAAM;EACtD,MAAM,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC;AAC5D,kBAAgB,KAAK,OAAO;AAC5B,SAAO;;AAGT,KAAI,eAAe,MAAM;EACvB,MAAM,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,IAAI,MAAM,CAAC;AAClD,kBAAgB,KAAK,OAAO;AAC5B,SAAO;;AAGT,KAAI,eAAe,OAAO;EACxB,MAAM,SAAS,IAAK,IAAI,aAAiC;AACzD,SAAO,UAAU,IAAI;AACrB,SAAO,OAAO,IAAI;AAClB,SAAO,QAAQ,IAAI;AACnB,SAAO,QAAQ,IAAI;AACnB,kBAAgB,KAAK,OAAO;AAC5B,SAAO;;AAGT,KAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;EAC3C,MAAM,SAAS,EAAE;AACjB,kBAAgB,KAAK,OAAO;AAC5B,SAAO;;AAGT,QAAO;;AAGT,SAAS,gBAAgB,KAAU,WAAsB;CACvD,MAAM,OAAO,OAAO,KAAK,IAAI;AAE7B,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,aAAa,OAAO,yBAAyB,KAAK,IAAI;AAE5D,MAAI,YAAY,YAAY,YAAY,IACtC,WAAU,OAAO,UAAU,IAAI,KAAK"}