@visulima/deep-clone 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## @visulima/deep-clone [1.0.4](https://github.com/visulima/visulima/compare/@visulima/deep-clone@1.0.3...@visulima/deep-clone@1.0.4) (2023-11-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* added node 21 support ([#226](https://github.com/visulima/visulima/issues/226)) ([bc2e6f2](https://github.com/visulima/visulima/commit/bc2e6f2ca6652c11c9fde8d52912492b5fcc502e))
|
|
7
|
+
|
|
8
|
+
## @visulima/deep-clone [1.0.3](https://github.com/visulima/visulima/compare/@visulima/deep-clone@1.0.2...@visulima/deep-clone@1.0.3) (2023-10-30)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* update dependencies in pnpm-lock.yaml ([d3a5626](https://github.com/visulima/visulima/commit/d3a5626d2c751c3e14f592db62b583b28046dcc7))
|
|
14
|
+
|
|
1
15
|
## @visulima/deep-clone [1.0.2](https://github.com/visulima/visulima/compare/@visulima/deep-clone@1.0.1...@visulima/deep-clone@1.0.2) (2023-10-24)
|
|
2
16
|
|
|
3
17
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["canValueHaveProperties","value","copyBuffer","current","typeHandlers","newBuffer","origView","Ctor","arrayCheckerHandlers","object","regexClone","key","desc","deepClone","error","objectCheckerHandlers","useProto","beforeIteration","onIteration","afterIteration","cloneArray","clone","getPropertyKeys","array","function_","cloned","index","handlerData","ch","invalidCloneTypeCheckers","data","invalidTypeChecker","clonedObject","propertyKey","objectPrototype","cloneCircles","originalData","references","object_","propertyDescriptor","options","propertyValue"],"mappings":"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","sourcesContent":["import type { TypedArray, UnknownRecord } from \"type-fest\";\n\ntype OnIteration = (function_: (oData: any) => unknown, levelData: unknown[] | UnknownRecord, clonedData: unknown[] | UnknownRecord, key: PropertyKey) => void;\n\ntype DataType = \"buffer\" | \"date\" | \"error\" | \"jsdom\" | \"map\" | \"object\" | \"primitive\" | \"regex\" | \"set\" | \"unknown\";\n\ntype DataTypeChecker = (object: any) => boolean;\n\ntype ObjectDataTypeHandler = (\n object: any,\n useProto: boolean,\n beforeIteration: (data: unknown, clonedData: unknown) => void,\n onIteration: OnIteration,\n afterIteration: () => void,\n) => any;\n\ninterface ArrayDataTypeMapping {\n checker: DataTypeChecker;\n handler: (object: any) => any;\n type: DataType;\n}\n\ninterface ObjectDataTypeMapping {\n checker: DataTypeChecker;\n handler: ObjectDataTypeHandler;\n type: DataType;\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nconst canValueHaveProperties = (value: unknown): value is NonNullable<Function | object> =>\n (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n\n/**\n * Copy buffer function for cloning ArrayBuffer, ArrayBufferView, Buffer, or TypedArray objects.\n *\n * @param current - The buffer object to be copied. The type of `current` is `ArrayBuffer | ArrayBufferView | Buffer | TypedArray`.\n * @returns The copied buffer object. The return type of the function is `ArrayBuffer | ArrayBufferView | Buffer | TypedArray`.\n */\nconst copyBuffer = (current: ArrayBuffer | ArrayBufferView | Buffer | TypedArray): ArrayBuffer | ArrayBufferView | Buffer | TypedArray => {\n const typeHandlers: Record<string, new (buffer: any) => any> = {\n BigInt64Array,\n BigUint64Array,\n // @ts-expect-error - Buffer has no constructor\n // eslint-disable-next-line @typescript-eslint/unbound-method\n Buffer: Buffer.from,\n Float32Array,\n Float64Array,\n Int8Array,\n Int16Array,\n Int32Array,\n Uint8Array,\n Uint8ClampedArray,\n Uint16Array,\n Uint32Array,\n };\n\n if (current instanceof ArrayBuffer) {\n const newBuffer = new ArrayBuffer(current.byteLength);\n const origView = new Uint8Array(current);\n const newView = new Uint8Array(newBuffer);\n\n newView.set(origView);\n\n return newBuffer;\n }\n\n const Ctor = typeHandlers[current.constructor.name];\n\n if (Ctor) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return new Ctor(current);\n }\n\n // @ts-expect-error - Fallback to ArrayBufferView\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return new (current as ArrayBufferView).constructor([...current.buffer], current.byteOffset, current.length);\n};\n\ninterface FakeJSDOM {\n cloneNode?: (check: boolean) => unknown;\n nodeType?: unknown;\n}\n\ntype ExtendedError = Error & { code?: any; errno?: any; syscall?: any };\n\n/**\n * An Array of checker and handler mappings for different data types.\n */\nconst arrayCheckerHandlers: ArrayDataTypeMapping[] = [\n {\n checker: (object: any) => object instanceof Date,\n handler: (object: any) => new Date(object as Date),\n type: \"date\",\n },\n {\n checker: (object: any) => object instanceof RegExp,\n handler: (object: RegExp | string) => {\n // eslint-disable-next-line require-unicode-regexp,@rushstack/security/no-unsafe-regexp,security/detect-non-literal-regexp\n const regexClone = new RegExp(object);\n\n // Any enumerable properties...\n if (typeof object !== \"string\") {\n Object.keys(object).forEach((key) => {\n const desc = Object.getOwnPropertyDescriptor(object, key);\n\n if (desc) {\n // eslint-disable-next-line no-prototype-builtins\n if (desc.hasOwnProperty(\"value\")) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n desc.value = deepClone(object[key as keyof RegExp]);\n }\n\n Object.defineProperty(regexClone, key, desc);\n }\n });\n }\n\n return regexClone;\n },\n type: \"regex\",\n },\n {\n checker: (object: any) => object instanceof Error,\n handler: (object: EvalError | ExtendedError | RangeError | ReferenceError | SyntaxError | TypeError | URIError) => {\n // @ts-expect-error - We don't know the type of the object, can be an error\n const error = new object.constructor(object.message) as\n | EvalError\n | ExtendedError\n | RangeError\n | ReferenceError\n | SyntaxError\n | TypeError\n | URIError;\n\n // If a `stack` property is present, copy it over...\n if (object.stack) {\n error.stack = object.stack;\n }\n\n // Node.js specific (system errors)...\n if ((object as ExtendedError).code) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n (error as ExtendedError).code = (object as ExtendedError).code;\n }\n\n if ((object as ExtendedError).errno) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n (error as ExtendedError).errno = (object as ExtendedError).errno;\n }\n\n if ((object as ExtendedError).syscall) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n (error as ExtendedError).syscall = (object as ExtendedError).syscall;\n }\n\n // Any enumerable properties...\n Object.keys(object).forEach((key) => {\n const desc = Object.getOwnPropertyDescriptor(object, key);\n\n if (desc) {\n // eslint-disable-next-line no-prototype-builtins\n if (desc.hasOwnProperty(\"value\")) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n desc.value = deepClone(object[key as keyof Error]);\n }\n\n Object.defineProperty(error, key, desc);\n }\n });\n\n return error;\n },\n type: \"error\",\n },\n {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n checker: (object: FakeJSDOM): object is FakeJSDOM => object?.nodeType !== undefined && object.cloneNode !== undefined,\n handler: (object: Required<FakeJSDOM>) => object.cloneNode(true),\n type: \"jsdom\",\n },\n {\n checker: (object: any) => ArrayBuffer.isView(object),\n handler: (object: ArrayBuffer | ArrayBufferView | Buffer | TypedArray) => copyBuffer(object),\n type: \"buffer\",\n },\n {\n checker: (object: any) => typeof object !== \"object\" || object === null,\n // eslint-disable-next-line @typescript-eslint/ban-types\n handler: (object: Function | bigint | boolean | number | string | symbol | null | undefined) => {\n if (typeof object === \"number\" || typeof object === \"boolean\" || typeof object === \"string\") {\n return object.valueOf();\n }\n\n return object;\n },\n type: \"primitive\",\n },\n];\n\nconst objectCheckerHandlers: ObjectDataTypeMapping[] = [\n ...(arrayCheckerHandlers as unknown as ObjectDataTypeMapping[]),\n {\n checker: (object: any) => object instanceof Map,\n handler: (\n object: any,\n useProto: boolean,\n beforeIteration: (data: unknown, clonedData: unknown) => void,\n onIteration: OnIteration,\n afterIteration: () => void,\n ) =>\n new Map(\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n cloneArray([...(object as [])], onIteration, clone(useProto, beforeIteration, onIteration, afterIteration)) as ReadonlyArray<\n [unknown, unknown]\n >,\n ),\n type: \"map\",\n },\n {\n checker: (object) => object instanceof Set,\n handler: (\n object: any,\n useProto: boolean,\n beforeIteration: (data: unknown, clonedData: unknown) => void,\n onIteration: OnIteration,\n afterIteration: () => void,\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n ) => new Set(cloneArray([...(object as [])], onIteration, clone(useProto, beforeIteration, onIteration, afterIteration))),\n type: \"set\",\n },\n];\n\nconst getPropertyKeys = (object: any): (string | symbol)[] => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)];\n\n/**\n * Clones an array by iterating through its elements and applying a function to each element.\n * If an element matches a defined checker function, the element is handled by a corresponding handler function.\n * Otherwise, the element is passed to the provided function for further processing.\n *\n * @param array - The array to clone. The type of `array` is `unknown[]`.\n * @param onIteration - A callback function called for each iteration. It is invoked with the provided function,\n * the original array, the cloned array, and the index of the current element. The type of `onIteration` is a function\n * that accepts four parameters: the provided function of type `(element: unknown) => unknown`, the original array of type `unknown[]`,\n * the cloned array of type `unknown[]`, and the index of the current element of type `number`.\n * @param function_ - The function to apply to each element that does not match a checker function. The type of `function_` is\n * a function that accepts one parameter of type `unknown`.\n * @returns A new array containing the cloned elements. The return type of the function is `unknown[]`.\n */\nconst cloneArray = (array: any[], onIteration: OnIteration, function_: (values: unknown) => unknown): unknown[] => {\n const cloned = Array.from({ length: array.length });\n\n // eslint-disable-next-line no-plusplus,no-loops/no-loops\n for (let index = 0; index < array.length; index++) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const current = array[index];\n const handlerData = arrayCheckerHandlers.find((ch) => ch.checker(current));\n\n if (handlerData) {\n cloned[index] = handlerData.handler(current);\n } else {\n onIteration(function_, array, cloned, index);\n }\n }\n\n return cloned;\n};\n\nconst invalidCloneTypeCheckers: ((object: any) => boolean)[] = [\n (object: any) => object instanceof WeakMap,\n (object: any) => object instanceof WeakSet,\n (object: any) => object instanceof SharedArrayBuffer,\n (object: any) => object instanceof DataView,\n (object: any) => object instanceof Promise,\n (object: any) => object instanceof Blob,\n];\n\n/**\n * Function that clones a given object with optional configuration parameters.\n * It creates a deep clone of the object, including arrays and nested objects.\n * It applies handlers for specific object types, before and after iteration functions,\n * and provides a callback function for each iteration step.\n *\n * @param useProto - Flag indicating whether to use the prototype of the object. The type of `useProto` is `boolean`.\n * @param beforeIteration - Function to be called before each iteration step with the current data\n * being iterated and the cloned data object. The type of `beforeIteration` is a function that\n * accepts two parameters of type `unknown`.\n * @param onIteration - Function to be called for each iteration step with the current data being\n * iterated, the cloned data object, and the property key. The type of `onIteration` is a function\n * that accepts two parameters of type `unknown[] | UnknownRecord` and one parameter of type `string | number`.\n * @param afterIteration - Function to be called after all iterations have completed. The type\n * of `afterIteration` is a function that accepts no parameters.\n * @returns The cloned object. The return type of the function is `unknown`.\n */\nconst clone =\n (useProto: boolean | undefined, beforeIteration: (data: unknown, clonedData: unknown) => void, onIteration: OnIteration, afterIteration: () => void) =>\n // eslint-disable-next-line sonarjs/cognitive-complexity\n (data: any): unknown => {\n if (typeof data !== \"object\" || data === null || typeof data === \"function\") {\n return data;\n }\n\n // eslint-disable-next-line no-restricted-syntax,no-loops/no-loops\n for (const handlerData of objectCheckerHandlers) {\n if (handlerData.checker(data)) {\n return handlerData.handler(data, useProto ?? false, beforeIteration, onIteration, afterIteration);\n }\n }\n\n // eslint-disable-next-line no-restricted-syntax,no-loops/no-loops\n for (const invalidTypeChecker of invalidCloneTypeCheckers) {\n if (invalidTypeChecker(data)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n throw new TypeError(`${data.constructor.name} objects cannot be cloned`);\n }\n }\n\n if (Array.isArray(data)) {\n return cloneArray(data, onIteration, clone(useProto, beforeIteration, onIteration, afterIteration));\n }\n\n const clonedObject: UnknownRecord = {};\n\n beforeIteration(data, clonedObject);\n\n // eslint-disable-next-line no-restricted-syntax,no-loops/no-loops\n for (const propertyKey of getPropertyKeys(data)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const current = (Object.getOwnPropertyDescriptor(data, propertyKey) as PropertyDescriptor).value;\n\n if (typeof current !== \"object\" || current === null) {\n clonedObject[propertyKey] = current;\n } else {\n const handlerData = objectCheckerHandlers.find((ch) => ch.checker(current));\n\n if (handlerData) {\n clonedObject[propertyKey] = handlerData.handler(current, useProto ?? false, beforeIteration, onIteration, afterIteration);\n } else {\n onIteration(clone(useProto, beforeIteration, onIteration, afterIteration), data as unknown[] | UnknownRecord, clonedObject, propertyKey);\n }\n }\n }\n\n if (useProto) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const objectPrototype: object | null = Object.getPrototypeOf(data);\n\n if (Object.getPrototypeOf(clonedObject) !== objectPrototype) {\n Object.setPrototypeOf(clonedObject, objectPrototype);\n }\n }\n\n afterIteration();\n\n if (!Object.isExtensible(data)) {\n Object.preventExtensions(clonedObject);\n }\n\n if (Object.isSealed(data)) {\n Object.seal(clonedObject);\n }\n\n if (Object.isFrozen(data)) {\n Object.freeze(clonedObject);\n }\n\n return clonedObject;\n };\n\n/**\n * Function that clones the given data object, including circular references.\n *\n * @template T - The type of the original data.\n * @param originalData - The original data object to clone. It uses the generic parameter `T`.\n * @param useProto - Optional. Whether to use `__proto__` when cloning objects. The type of `useProto` is `boolean`.\n * @returns The cloned data object. The return type is defined by the generic parameter `T`.\n */\nconst cloneCircles = <T>(originalData: T, useProto: boolean | undefined) => {\n const references = new Map<unknown, unknown>();\n\n return clone(\n useProto,\n (object_, clonedObject) => {\n references.set(object_, clonedObject);\n },\n (function_, data, clonedObject, key) => {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n if (references.has(data[key])) {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line no-param-reassign\n (clonedObject as unknown[] | UnknownRecord)[key] = references.get(data[key]);\n } else if (Array.isArray(data)) {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line no-param-reassign\n clonedObject[key as number] = function_(data[key]);\n } else {\n const propertyDescriptor = Object.getOwnPropertyDescriptor(data, key);\n\n if (propertyDescriptor?.value) {\n propertyDescriptor.value = function_(propertyDescriptor.value);\n\n Object.defineProperty(clonedObject, key, propertyDescriptor);\n }\n }\n },\n () => {\n references.delete(originalData);\n },\n )(originalData);\n};\n\ntype DeepReadwrite<T> = T extends object | [] ? { -readonly [P in keyof T]: DeepReadwrite<T[P]> } : T;\n\ninterface Options {\n circles?: boolean;\n proto?: boolean;\n}\n\n/**\n * Function that creates a deep clone of an object or array.\n *\n * @template T - The type of the original data.\n * @param originalData - The original data to be cloned. It uses the generic parameter `T`.\n * @param options - Optional. The cloning options. Type of this parameter is `Options`.\n * @returns The deep cloned data with its type as `DeepReadwrite<T>`.\n */\n// eslint-disable-next-line import/prefer-default-export,import/no-unused-modules\nexport const deepClone = <T = unknown>(originalData: T, options?: Options): DeepReadwrite<T> => {\n if (!canValueHaveProperties(originalData)) {\n return originalData as DeepReadwrite<T>;\n }\n\n if (options?.circles) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return cloneCircles<T>(originalData, options?.proto) as DeepReadwrite<T>;\n }\n\n return clone(\n options?.proto,\n () => {},\n (function_, data, clonedObject, key) => {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const propertyValue = data[key];\n\n if (Array.isArray(data)) {\n // eslint-disable-next-line no-param-reassign\n clonedObject[key as number] = function_(propertyValue);\n } else {\n // Assign properties if possible to avoid expensive operations\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line no-param-reassign\n clonedObject[key] = function_(propertyValue);\n }\n },\n () => {},\n )(originalData) as DeepReadwrite<T>;\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["canValueHaveProperties","value","copyBuffer","current","typeHandlers","newBuffer","origView","Ctor","arrayCheckerHandlers","object","regexClone","key","desc","deepClone","error","objectCheckerHandlers","useProto","beforeIteration","onIteration","afterIteration","cloneArray","clone","getPropertyKeys","array","function_","cloned","index","handlerData","ch","invalidCloneTypeCheckers","data","invalidTypeChecker","clonedObject","propertyKey","objectPrototype","cloneCircles","originalData","references","object_","propertyDescriptor","options","propertyValue"],"mappings":"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","sourcesContent":["import type { TypedArray, UnknownRecord } from \"type-fest\";\n\ntype OnIteration = (function_: (oData: any) => unknown, levelData: unknown[] | UnknownRecord, clonedData: unknown[] | UnknownRecord, key: PropertyKey) => void;\n\ntype DataType = \"buffer\" | \"date\" | \"error\" | \"jsdom\" | \"map\" | \"object\" | \"primitive\" | \"regex\" | \"set\" | \"unknown\";\n\ntype DataTypeChecker = (object: any) => boolean;\n\ntype ObjectDataTypeHandler = (\n object: any,\n useProto: boolean,\n beforeIteration: (data: unknown, clonedData: unknown) => void,\n onIteration: OnIteration,\n afterIteration: () => void,\n) => any;\n\ninterface ArrayDataTypeMapping {\n checker: DataTypeChecker;\n handler: (object: any) => any;\n type: DataType;\n}\n\ninterface ObjectDataTypeMapping {\n checker: DataTypeChecker;\n handler: ObjectDataTypeHandler;\n type: DataType;\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nconst canValueHaveProperties = (value: unknown): value is NonNullable<Function | object> =>\n (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n\n/**\n * Copy buffer function for cloning ArrayBuffer, ArrayBufferView, Buffer, or TypedArray objects.\n *\n * @param current - The buffer object to be copied. The type of `current` is `ArrayBuffer | ArrayBufferView | Buffer | TypedArray`.\n * @returns The copied buffer object. The return type of the function is `ArrayBuffer | ArrayBufferView | Buffer | TypedArray`.\n */\nconst copyBuffer = (current: ArrayBuffer | ArrayBufferView | Buffer | TypedArray): ArrayBuffer | ArrayBufferView | Buffer | TypedArray => {\n const typeHandlers: Record<string, new (buffer: any) => any> = {\n BigInt64Array,\n BigUint64Array,\n // @ts-expect-error - Buffer has no constructor\n // eslint-disable-next-line @typescript-eslint/unbound-method\n Buffer: Buffer.from,\n Float32Array,\n Float64Array,\n Int8Array,\n Int16Array,\n Int32Array,\n Uint8Array,\n Uint8ClampedArray,\n Uint16Array,\n Uint32Array,\n };\n\n if (current instanceof ArrayBuffer) {\n const newBuffer = new ArrayBuffer(current.byteLength);\n const origView = new Uint8Array(current);\n const newView = new Uint8Array(newBuffer);\n\n newView.set(origView);\n\n return newBuffer;\n }\n\n const Ctor = typeHandlers[current.constructor.name];\n\n if (Ctor) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return new Ctor(current);\n }\n\n // @ts-expect-error - Fallback to ArrayBufferView\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return new (current as ArrayBufferView).constructor([...current.buffer], current.byteOffset, current.length);\n};\n\ninterface FakeJSDOM {\n cloneNode?: (check: boolean) => unknown;\n nodeType?: unknown;\n}\n\ntype ExtendedError = Error & { code?: any; errno?: any; syscall?: any };\n\n/**\n * An Array of checker and handler mappings for different data types.\n */\nconst arrayCheckerHandlers: ArrayDataTypeMapping[] = [\n {\n checker: (object: any) => object instanceof Date,\n handler: (object: any) => new Date(object as Date),\n type: \"date\",\n },\n {\n checker: (object: any) => object instanceof RegExp,\n handler: (object: RegExp | string) => {\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp,security/detect-non-literal-regexp\n const regexClone = new RegExp(object);\n\n // Any enumerable properties...\n if (typeof object !== \"string\") {\n Object.keys(object).forEach((key) => {\n const desc = Object.getOwnPropertyDescriptor(object, key);\n\n if (desc) {\n // eslint-disable-next-line no-prototype-builtins\n if (desc.hasOwnProperty(\"value\")) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n desc.value = deepClone(object[key as keyof RegExp]);\n }\n\n Object.defineProperty(regexClone, key, desc);\n }\n });\n }\n\n return regexClone;\n },\n type: \"regex\",\n },\n {\n checker: (object: any) => object instanceof Error,\n handler: (object: EvalError | ExtendedError | RangeError | ReferenceError | SyntaxError | TypeError | URIError) => {\n // @ts-expect-error - We don't know the type of the object, can be an error\n const error = new object.constructor(object.message) as\n | EvalError\n | ExtendedError\n | RangeError\n | ReferenceError\n | SyntaxError\n | TypeError\n | URIError;\n\n // If a `stack` property is present, copy it over...\n if (object.stack) {\n error.stack = object.stack;\n }\n\n // Node.js specific (system errors)...\n if ((object as ExtendedError).code) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n (error as ExtendedError).code = (object as ExtendedError).code;\n }\n\n if ((object as ExtendedError).errno) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n (error as ExtendedError).errno = (object as ExtendedError).errno;\n }\n\n if ((object as ExtendedError).syscall) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n (error as ExtendedError).syscall = (object as ExtendedError).syscall;\n }\n\n // Any enumerable properties...\n Object.keys(object).forEach((key) => {\n const desc = Object.getOwnPropertyDescriptor(object, key);\n\n if (desc) {\n // eslint-disable-next-line no-prototype-builtins\n if (desc.hasOwnProperty(\"value\")) {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n desc.value = deepClone(object[key as keyof Error]);\n }\n\n Object.defineProperty(error, key, desc);\n }\n });\n\n return error;\n },\n type: \"error\",\n },\n {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n checker: (object: FakeJSDOM): object is FakeJSDOM => object?.nodeType !== undefined && object.cloneNode !== undefined,\n handler: (object: Required<FakeJSDOM>) => object.cloneNode(true),\n type: \"jsdom\",\n },\n {\n checker: (object: any) => ArrayBuffer.isView(object),\n handler: (object: ArrayBuffer | ArrayBufferView | Buffer | TypedArray) => copyBuffer(object),\n type: \"buffer\",\n },\n {\n checker: (object: any) => typeof object !== \"object\" || object === null,\n // eslint-disable-next-line @typescript-eslint/ban-types\n handler: (object: Function | bigint | boolean | number | string | symbol | null | undefined) => {\n if (typeof object === \"number\" || typeof object === \"boolean\" || typeof object === \"string\") {\n return object.valueOf();\n }\n\n return object;\n },\n type: \"primitive\",\n },\n];\n\nconst objectCheckerHandlers: ObjectDataTypeMapping[] = [\n ...(arrayCheckerHandlers as unknown as ObjectDataTypeMapping[]),\n {\n checker: (object: any) => object instanceof Map,\n handler: (\n object: any,\n useProto: boolean,\n beforeIteration: (data: unknown, clonedData: unknown) => void,\n onIteration: OnIteration,\n afterIteration: () => void,\n ) =>\n new Map(\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n cloneArray([...(object as [])], onIteration, clone(useProto, beforeIteration, onIteration, afterIteration)) as ReadonlyArray<\n [unknown, unknown]\n >,\n ),\n type: \"map\",\n },\n {\n checker: (object) => object instanceof Set,\n handler: (\n object: any,\n useProto: boolean,\n beforeIteration: (data: unknown, clonedData: unknown) => void,\n onIteration: OnIteration,\n afterIteration: () => void,\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n ) => new Set(cloneArray([...(object as [])], onIteration, clone(useProto, beforeIteration, onIteration, afterIteration))),\n type: \"set\",\n },\n];\n\nconst getPropertyKeys = (object: any): (string | symbol)[] => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)];\n\n/**\n * Clones an array by iterating through its elements and applying a function to each element.\n * If an element matches a defined checker function, the element is handled by a corresponding handler function.\n * Otherwise, the element is passed to the provided function for further processing.\n *\n * @param array - The array to clone. The type of `array` is `unknown[]`.\n * @param onIteration - A callback function called for each iteration. It is invoked with the provided function,\n * the original array, the cloned array, and the index of the current element. The type of `onIteration` is a function\n * that accepts four parameters: the provided function of type `(element: unknown) => unknown`, the original array of type `unknown[]`,\n * the cloned array of type `unknown[]`, and the index of the current element of type `number`.\n * @param function_ - The function to apply to each element that does not match a checker function. The type of `function_` is\n * a function that accepts one parameter of type `unknown`.\n * @returns A new array containing the cloned elements. The return type of the function is `unknown[]`.\n */\nconst cloneArray = (array: any[], onIteration: OnIteration, function_: (values: unknown) => unknown): unknown[] => {\n const cloned = Array.from({ length: array.length });\n\n // eslint-disable-next-line no-plusplus,no-loops/no-loops\n for (let index = 0; index < array.length; index++) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const current = array[index];\n const handlerData = arrayCheckerHandlers.find((ch) => ch.checker(current));\n\n if (handlerData) {\n cloned[index] = handlerData.handler(current);\n } else {\n onIteration(function_, array, cloned, index);\n }\n }\n\n return cloned;\n};\n\nconst invalidCloneTypeCheckers: ((object: any) => boolean)[] = [\n (object: any) => object instanceof WeakMap,\n (object: any) => object instanceof WeakSet,\n (object: any) => object instanceof SharedArrayBuffer,\n (object: any) => object instanceof DataView,\n (object: any) => object instanceof Promise,\n (object: any) => object instanceof Blob,\n];\n\n/**\n * Function that clones a given object with optional configuration parameters.\n * It creates a deep clone of the object, including arrays and nested objects.\n * It applies handlers for specific object types, before and after iteration functions,\n * and provides a callback function for each iteration step.\n *\n * @param useProto - Flag indicating whether to use the prototype of the object. The type of `useProto` is `boolean`.\n * @param beforeIteration - Function to be called before each iteration step with the current data\n * being iterated and the cloned data object. The type of `beforeIteration` is a function that\n * accepts two parameters of type `unknown`.\n * @param onIteration - Function to be called for each iteration step with the current data being\n * iterated, the cloned data object, and the property key. The type of `onIteration` is a function\n * that accepts two parameters of type `unknown[] | UnknownRecord` and one parameter of type `string | number`.\n * @param afterIteration - Function to be called after all iterations have completed. The type\n * of `afterIteration` is a function that accepts no parameters.\n * @returns The cloned object. The return type of the function is `unknown`.\n */\nconst clone =\n (useProto: boolean | undefined, beforeIteration: (data: unknown, clonedData: unknown) => void, onIteration: OnIteration, afterIteration: () => void) =>\n // eslint-disable-next-line sonarjs/cognitive-complexity\n (data: any): unknown => {\n if (typeof data !== \"object\" || data === null || typeof data === \"function\") {\n return data;\n }\n\n // eslint-disable-next-line no-restricted-syntax,no-loops/no-loops\n for (const handlerData of objectCheckerHandlers) {\n if (handlerData.checker(data)) {\n return handlerData.handler(data, useProto ?? false, beforeIteration, onIteration, afterIteration);\n }\n }\n\n // eslint-disable-next-line no-restricted-syntax,no-loops/no-loops\n for (const invalidTypeChecker of invalidCloneTypeCheckers) {\n if (invalidTypeChecker(data)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n throw new TypeError(`${data.constructor.name} objects cannot be cloned`);\n }\n }\n\n if (Array.isArray(data)) {\n return cloneArray(data, onIteration, clone(useProto, beforeIteration, onIteration, afterIteration));\n }\n\n const clonedObject: UnknownRecord = {};\n\n beforeIteration(data, clonedObject);\n\n // eslint-disable-next-line no-restricted-syntax,no-loops/no-loops\n for (const propertyKey of getPropertyKeys(data)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const current = (Object.getOwnPropertyDescriptor(data, propertyKey) as PropertyDescriptor).value;\n\n if (typeof current !== \"object\" || current === null) {\n clonedObject[propertyKey] = current;\n } else {\n const handlerData = objectCheckerHandlers.find((ch) => ch.checker(current));\n\n if (handlerData) {\n clonedObject[propertyKey] = handlerData.handler(current, useProto ?? false, beforeIteration, onIteration, afterIteration);\n } else {\n onIteration(clone(useProto, beforeIteration, onIteration, afterIteration), data as unknown[] | UnknownRecord, clonedObject, propertyKey);\n }\n }\n }\n\n if (useProto) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const objectPrototype: object | null = Object.getPrototypeOf(data);\n\n if (Object.getPrototypeOf(clonedObject) !== objectPrototype) {\n Object.setPrototypeOf(clonedObject, objectPrototype);\n }\n }\n\n afterIteration();\n\n if (!Object.isExtensible(data)) {\n Object.preventExtensions(clonedObject);\n }\n\n if (Object.isSealed(data)) {\n Object.seal(clonedObject);\n }\n\n if (Object.isFrozen(data)) {\n Object.freeze(clonedObject);\n }\n\n return clonedObject;\n };\n\n/**\n * Function that clones the given data object, including circular references.\n *\n * @template T - The type of the original data.\n * @param originalData - The original data object to clone. It uses the generic parameter `T`.\n * @param useProto - Optional. Whether to use `__proto__` when cloning objects. The type of `useProto` is `boolean`.\n * @returns The cloned data object. The return type is defined by the generic parameter `T`.\n */\nconst cloneCircles = <T>(originalData: T, useProto: boolean | undefined) => {\n const references = new Map<unknown, unknown>();\n\n return clone(\n useProto,\n (object_, clonedObject) => {\n references.set(object_, clonedObject);\n },\n (function_, data, clonedObject, key) => {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n if (references.has(data[key])) {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line no-param-reassign\n (clonedObject as unknown[] | UnknownRecord)[key] = references.get(data[key]);\n } else if (Array.isArray(data)) {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line no-param-reassign\n clonedObject[key as number] = function_(data[key]);\n } else {\n const propertyDescriptor = Object.getOwnPropertyDescriptor(data, key);\n\n if (propertyDescriptor?.value) {\n propertyDescriptor.value = function_(propertyDescriptor.value);\n\n Object.defineProperty(clonedObject, key, propertyDescriptor);\n }\n }\n },\n () => {\n references.delete(originalData);\n },\n )(originalData);\n};\n\ntype DeepReadwrite<T> = T extends object | [] ? { -readonly [P in keyof T]: DeepReadwrite<T[P]> } : T;\n\ninterface Options {\n circles?: boolean;\n proto?: boolean;\n}\n\n/**\n * Function that creates a deep clone of an object or array.\n *\n * @template T - The type of the original data.\n * @param originalData - The original data to be cloned. It uses the generic parameter `T`.\n * @param options - Optional. The cloning options. Type of this parameter is `Options`.\n * @returns The deep cloned data with its type as `DeepReadwrite<T>`.\n */\n// eslint-disable-next-line import/prefer-default-export,import/no-unused-modules\nexport const deepClone = <T = unknown>(originalData: T, options?: Options): DeepReadwrite<T> => {\n if (!canValueHaveProperties(originalData)) {\n return originalData as DeepReadwrite<T>;\n }\n\n if (options?.circles) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return cloneCircles<T>(originalData, options?.proto) as DeepReadwrite<T>;\n }\n\n return clone(\n options?.proto,\n () => {},\n (function_, data, clonedObject, key) => {\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const propertyValue = data[key];\n\n if (Array.isArray(data)) {\n // eslint-disable-next-line no-param-reassign\n clonedObject[key as number] = function_(propertyValue);\n } else {\n // Assign properties if possible to avoid expensive operations\n // @ts-expect-error - We don't know the type of the data, can be an object or array\n // eslint-disable-next-line no-param-reassign\n clonedObject[key] = function_(propertyValue);\n }\n },\n () => {},\n )(originalData) as DeepReadwrite<T>;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/deep-clone",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Fastest deep clone implementation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anolilab",
|
|
@@ -94,14 +94,14 @@
|
|
|
94
94
|
"test:watch": "vitest"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@anolilab/eslint-config": "^
|
|
98
|
-
"@anolilab/prettier-config": "^5.0.
|
|
99
|
-
"@anolilab/semantic-release-preset": "^8.0.
|
|
97
|
+
"@anolilab/eslint-config": "^15.0.2",
|
|
98
|
+
"@anolilab/prettier-config": "^5.0.13",
|
|
99
|
+
"@anolilab/semantic-release-preset": "^8.0.2",
|
|
100
100
|
"@mfederczuk/deeptools": "2.1.0-indev01",
|
|
101
101
|
"@rushstack/eslint-plugin-security": "^0.7.1",
|
|
102
102
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
103
103
|
"@types/lodash.clonedeep": "^4.5.8",
|
|
104
|
-
"@types/node": "18.
|
|
104
|
+
"@types/node": "18.18.8",
|
|
105
105
|
"@ungap/structured-clone": "^1.2.0",
|
|
106
106
|
"@vitest/coverage-v8": "^0.34.6",
|
|
107
107
|
"clone-deep": "^4.0.1",
|
|
@@ -125,16 +125,16 @@
|
|
|
125
125
|
"ramda": "^0.29.1",
|
|
126
126
|
"rfdc": "^1.3.0",
|
|
127
127
|
"rimraf": "^5.0.5",
|
|
128
|
-
"semantic-release": "^22.0.
|
|
128
|
+
"semantic-release": "^22.0.6",
|
|
129
129
|
"sort-package-json": "^2.6.0",
|
|
130
130
|
"standard": "^17.1.0",
|
|
131
131
|
"tsup": "^7.2.0",
|
|
132
|
-
"type-fest": "^4.
|
|
132
|
+
"type-fest": "^4.6.0",
|
|
133
133
|
"typescript": "^5.2.2",
|
|
134
134
|
"vitest": "^0.34.6"
|
|
135
135
|
},
|
|
136
136
|
"engines": {
|
|
137
|
-
"node": ">=18.* <=
|
|
137
|
+
"node": ">=18.* <=21.*"
|
|
138
138
|
},
|
|
139
139
|
"publishConfig": {
|
|
140
140
|
"access": "public",
|