# circ-clone

> Simple lib to safely clone circular objects.

Latest version **2.7.11** (published 2024-01-28) · ISC license · 0 weekly downloads

## Install

```sh
npm install circ-clone
pnpm add circ-clone
yarn add circ-clone
bun add circ-clone
```

## Health

**Score 45/100 (D)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 2.7.11 |
| Published | 2024-01-28 |
| First published | 2023-03-04 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 3 |
| Unpacked size | 27.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | maximilianMairinger |
| Maintainers | zzrv |
| Keywords | circ, circular, cyclic, recursive, self-referencing, object, clone, copy, simple |

## Links

- npm: https://www.npmjs.com/package/circ-clone
- Repository: https://github.com/maximilianMairinger/circClone
- Homepage: https://github.com/maximilianMairinger/circClone#readme
- Issues: https://github.com/maximilianMairinger/circClone/issues
- npm.io page: https://npm.io/package/circ-clone

## Dependencies (3)

- [iterare](https://npm.io/package/iterare.md) ^1.2.1
- [object.hasown](https://npm.io/package/object.hasown.md) ^1.1.3
- [sanitize-against](https://npm.io/package/sanitize-against.md) ^1.5.4

## Alternatives

- [jsforce](https://npm.io/package/jsforce.md) — 851.2K weekly downloads
- [react-native-qrcode-svg](https://npm.io/package/react-native-qrcode-svg.md) — 693.5K weekly downloads
- [@salesforce/plugin-data](https://npm.io/package/@salesforce/plugin-data.md) — 394.9K weekly downloads
- [@backstage/plugin-search-common](https://npm.io/package/@backstage/plugin-search-common.md) — 308.5K weekly downloads
- [@chain-registry/types](https://npm.io/package/@chain-registry/types.md) — 38.4K weekly downloads

## Recent versions

- 2.7.11 (latest) — 2024-01-28
- 2.7.10 — 2024-01-08
- 2.7.9 — 2024-01-07
- 2.7.8 — 2024-01-07
- 2.7.7 — 2024-01-07
- 2.7.6 — 2024-01-07
- 2.7.5 — 2024-01-07
- 2.7.4 — 2024-01-07
- 2.7.3 — 2024-01-07
- 2.7.2 — 2024-01-07
- 2.7.1 — 2024-01-06
- 2.7.0 — 2024-01-06
- 2.6.0 — 2024-01-06
- 1.5.1 — 2023-10-13
- 2.5.1 — 2023-10-13
- … 21 more at https://npm.io/package/circ-clone/versions

## README

# Circ clone

Simple lib to safely (regarding [prototype poisoning](https://medium.com/intrinsic-blog/javascript-prototype-poisoning-vulnerabilities-in-the-wild-7bc15347c96)) clone circular (deep) objects. Exports three functions: `cloneKeys`, `mergeDeep` and `cloneKeysButKeepSym`, that do what they say and are not configurable. They are properly types and support tree-shaking. Each implementation is considerable simple (thus small). All functions that keep track of circular references, use `WeakMap` to do so.

## Installation

```shell
 $ npm i circ-clone
```

## Usage

### Clone keys

`cloneKeys<Ob extends Object>(ob: Ob): Ob`

```ts
import { cloneKeys } from "circ-clone"

const obj = { a: 1, b: { c: 3 } }
obj.b.d = obj

const cloned = cloneKeys(obj)
```

### Merge deep

`mergeDeep<Into extends object, From extends object>(from: From, into: Into): Into & From`

Merges the properties of `from` into `into` recursively with support for cyclic references. References from `from` to `into` (or any of its nested objects) are not supported, as the resulting behavior is not defined. Arrays are not treated specially (indexes are overwritten). The return value is `=== into` (thus not cloned), only sub-branches (nested objects) of from that are new to into are cloned.

```ts
import { mergeDeep } from "circ-clone"

const into = { a: 2, b: { c: 4, d: { doesntMatter: "whats in here", asItGets: "overriden" } } }
const from = { a: 1, b: { c: 3, d: "see one line below" } }
from.b.d = from


const merged = mergeDeep(into, from)
// merged = into = {
//   a: 1,
//   b: {
//     c: 3,
//     d: [Circular]
//   }
// }
```

> Importantly note, that the fields on `into.b.d` do not get copied over, as the reference to `from.b.d` is considered new. The reason for this decision is that it seems unintuitive for members of into to suddenly be written into a place of into. If you however need this behavior, please let me know by creating an issue.

### Merge deep but not cyclic

`mergeDeepButNotCyclic<Into extends object, From extends object>(from: From, into: Into): Into & From`

Merges the properties of `from` into `into` without considering cyclic references! This is faster than `mergeDeep`, but has the drawback that cyclic references in both `from` and `into` (exclusively if in both at the same place) terminate the function with an (stackoverflow) exception, similar to how `JSON.stringify` would. Also note that references from `from` to `into` (or any of its nested objects) are not supported, as the resulting behavior is not defined. The return value is `=== into` (thus not cloned), only sub-branches (nested objects) of from that are new to into are cloned.

```ts
import { mergeDeepButNotCyclic } from "circ-clone"

const into = { a: 2, b: { c: 4, e: 5 } }
const from = { a: 1, b: { c: 3 } }

const merged = mergeDeepButNotCyclic(into, from)
// merged = into = {
//   a: 1,
//   b: {
//     c: 3,
//     e: 5
//   }
// }
```

### Clone keys but keep symbols

`cloneKeysButKeepSym<Ob extends Object>(ob: Ob): Ob`

Similar to `cloneKeys` but keeps symbols uncloned!

```ts
import { cloneKeysButKeepSym } from "circ-clone"

const obj = { a: 1, b: { c: 3 } }
obj.b.d = obj
const sym = Symbol("foo")
obj[sym] = {  }


const cloned = cloneKeysButKeepSym(obj)
cloned[sym] === obj[sym] // true
```

## Contribute

All feedback is appreciated. Create a pull request or write an issue.

---
_Source: https://npm.io/package/circ-clone · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
