@sequencemedia/dupe 0.0.2 → 0.0.3
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/README.md +34 -2
- package/package.json +11 -5
- package/src/index.d.mts +6 -0
- package/src/index.mjs +147 -0
- package/{index.d.mts → src/node/index.d.mts} +0 -0
- package/{index.mjs → src/node/index.mjs} +8 -8
package/README.md
CHANGED
|
@@ -4,6 +4,38 @@ Produces a duplicate (or deep clone) of an object or array, preserving circular
|
|
|
4
4
|
|
|
5
5
|
Primitives are returned as-is
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```javascript
|
|
8
|
+
import dupe from '@sequencemedia/dupe'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
const a = [1, 2, 3]
|
|
11
|
+
|
|
12
|
+
a.push(a)
|
|
13
|
+
|
|
14
|
+
const o = { a: 4, b: 5, c: 6, func () { } }
|
|
15
|
+
|
|
16
|
+
o.o = o
|
|
17
|
+
|
|
18
|
+
a.push(o)
|
|
19
|
+
|
|
20
|
+
const array = dupe(a)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
These types as well as `Buffer` instances can be duplicated using `@sequencemedia/dupe/node`
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import dupe from '@sequencemedia/dupe/node'
|
|
27
|
+
|
|
28
|
+
const a = [1, 2, 3, Buffer.from('x')]
|
|
29
|
+
|
|
30
|
+
a.push(a)
|
|
31
|
+
|
|
32
|
+
const o = { a: 4, b: 5, c: 6, func () { }, buff: Buffer.from('y') }
|
|
33
|
+
|
|
34
|
+
o.o = o
|
|
35
|
+
|
|
36
|
+
a.push(o)
|
|
37
|
+
|
|
38
|
+
const array = dupe(a)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For most values (i.e., except functions) `structuredClone` is preferable
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sequencemedia/dupe",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"dupe",
|
|
6
6
|
"duplicate",
|
|
7
7
|
"clone",
|
|
8
8
|
"deep clone",
|
|
9
|
-
"deep"
|
|
9
|
+
"deep",
|
|
10
|
+
"structured clone"
|
|
10
11
|
],
|
|
11
|
-
"main": "./index.mjs",
|
|
12
|
+
"main": "./src/index.mjs",
|
|
12
13
|
"type": "module",
|
|
13
|
-
"types": "./index.d.mts",
|
|
14
|
+
"types": "./src/index.d.mts",
|
|
14
15
|
"author": {
|
|
15
16
|
"name": "Jonathan Perry for Sequence Media Limited",
|
|
16
17
|
"email": "sequencemedia@sequencemedia.net",
|
|
@@ -42,7 +43,12 @@
|
|
|
42
43
|
"globals": "^15.13.0",
|
|
43
44
|
"husky": "^9.1.7"
|
|
44
45
|
},
|
|
46
|
+
"imports": {
|
|
47
|
+
"#dupe": "./src/index.mjs",
|
|
48
|
+
"#dupe/node": "./src/node/index.mjs"
|
|
49
|
+
},
|
|
45
50
|
"exports": {
|
|
46
|
-
".": "./index.mjs"
|
|
51
|
+
".": "./src/index.mjs",
|
|
52
|
+
"./node": "./src/node/index.mjs"
|
|
47
53
|
}
|
|
48
54
|
}
|
package/src/index.d.mts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type ArrayLiteralType = unknown[] | never[]
|
|
2
|
+
type ObjectLiteralType = Record<PropertyKey, unknown> | Record<PropertyKey, never>
|
|
3
|
+
|
|
4
|
+
type ValueType = string | number | ArrayLiteralType | ObjectLiteralType | null | undefined
|
|
5
|
+
|
|
6
|
+
export default function dupe (v: ValueType | ValueType[]): ValueType | ValueType[]
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {unknown[] | never[]} ArrayLiteralType
|
|
3
|
+
*
|
|
4
|
+
* @typedef {Record<PropertyKey, unknown> | Record<PropertyKey, never>} ObjectLiteralType
|
|
5
|
+
*
|
|
6
|
+
* @typedef {string | number | ArrayLiteralType | ObjectLiteralType | null | undefined} ValueType
|
|
7
|
+
*
|
|
8
|
+
* @typedef {WeakMap<WeakKey, ArrayLiteralType | ObjectLiteralType>} WeakMapType
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {ValueType | ValueType[]} v
|
|
13
|
+
* @returns {boolean}
|
|
14
|
+
*/
|
|
15
|
+
export function isArray (v) {
|
|
16
|
+
return Array.isArray(v)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {ValueType | ValueType[]} v
|
|
21
|
+
* @returns {boolean}
|
|
22
|
+
*/
|
|
23
|
+
export function isObject (v) {
|
|
24
|
+
return (v || false) instanceof Object && !Array.isArray(v)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {ValueType | ValueType[]} v
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
export function isFunction (v) {
|
|
32
|
+
return v instanceof Function
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @param {ValueType | ValueType[]} v
|
|
36
|
+
* @returns {boolean}
|
|
37
|
+
*/
|
|
38
|
+
function isPrimitive (v) {
|
|
39
|
+
return !(
|
|
40
|
+
isObject(v) ||
|
|
41
|
+
isArray(v) ||
|
|
42
|
+
isFunction(v)
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {ArrayLiteralType} v
|
|
48
|
+
* @param {WeakMapType} weakMap
|
|
49
|
+
* @returns {ArrayLiteralType}
|
|
50
|
+
*/
|
|
51
|
+
function getArray (v, weakMap) {
|
|
52
|
+
const a = []
|
|
53
|
+
|
|
54
|
+
weakMap.set(v, a)
|
|
55
|
+
|
|
56
|
+
return v.reduce(getReduceArray(weakMap), a)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {ObjectLiteralType} v
|
|
61
|
+
* @param {WeakMapType} weakMap
|
|
62
|
+
* @returns {ObjectLiteralType}
|
|
63
|
+
*/
|
|
64
|
+
function getObject (v, weakMap) {
|
|
65
|
+
const o = {}
|
|
66
|
+
|
|
67
|
+
weakMap.set(v, o)
|
|
68
|
+
|
|
69
|
+
return Object.assign(o, Object.fromEntries(Object.entries(v).map(getMapEntries(weakMap))))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {WeakMapType} weakMap
|
|
74
|
+
* @returns {(a: ArrayLiteralType, v: ValueType | ValueType[]) => ArrayLiteralType}
|
|
75
|
+
*/
|
|
76
|
+
function getReduceArray (weakMap) {
|
|
77
|
+
/**
|
|
78
|
+
* @param {ArrayLiteralType} a
|
|
79
|
+
* @param {ValueType | ValueType[]} v
|
|
80
|
+
* @returns {ArrayLiteralType}
|
|
81
|
+
*/
|
|
82
|
+
return function reduceArray (a, v) {
|
|
83
|
+
if (isPrimitive(v) || isFunction(v)) {
|
|
84
|
+
a.push(v)
|
|
85
|
+
return a
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (weakMap.has(v)) {
|
|
89
|
+
a.push(weakMap.get(v))
|
|
90
|
+
return a
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (isArray(v)) {
|
|
94
|
+
a.push(getArray(v, weakMap))
|
|
95
|
+
return a
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (isObject(v)) {
|
|
99
|
+
a.push(getObject(v, weakMap))
|
|
100
|
+
return a
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @param {WeakMapType} weakMap
|
|
107
|
+
* @returns {(entry: [PropertyKey, ValueType | ValueType[]]) => [PropertyKey, ValueType | ValueType[]]}
|
|
108
|
+
*/
|
|
109
|
+
function getMapEntries (weakMap) {
|
|
110
|
+
/**
|
|
111
|
+
* @param {[PropertyKey, ValueType | ValueType[]]} entry
|
|
112
|
+
* @returns {[PropertyKey, ValueType | ValueType[]]}
|
|
113
|
+
*/
|
|
114
|
+
return function mapEntries ([k, v]) {
|
|
115
|
+
if (isPrimitive(v) || isFunction(v)) return [k, v]
|
|
116
|
+
|
|
117
|
+
if (weakMap.has(v)) {
|
|
118
|
+
return [k, weakMap.get(v)]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (isArray(v)) {
|
|
122
|
+
return [k, getArray(v, weakMap)]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (isObject(v)) {
|
|
126
|
+
return [k, getObject(v, weakMap)]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Duplicate a value
|
|
133
|
+
*
|
|
134
|
+
* @param {ValueType | ValueType[]} v
|
|
135
|
+
* @returns {ValueType | ValueType[]}
|
|
136
|
+
*/
|
|
137
|
+
export default function toDuplicate (v) {
|
|
138
|
+
if (isPrimitive(v) || isFunction(v)) return v
|
|
139
|
+
|
|
140
|
+
if (isArray(v)) {
|
|
141
|
+
return getArray(v, new WeakMap())
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (isObject(v)) {
|
|
145
|
+
return getObject(v, new WeakMap())
|
|
146
|
+
}
|
|
147
|
+
}
|
|
File without changes
|
|
@@ -32,6 +32,14 @@ function isFunction (v) {
|
|
|
32
32
|
return v instanceof Function
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {ValueType | ValueType[]} v
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isBuffer (v) {
|
|
40
|
+
return Buffer.isBuffer(v)
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
/**
|
|
36
44
|
* @param {ValueType | ValueType[]} v
|
|
37
45
|
* @returns {boolean}
|
|
@@ -45,14 +53,6 @@ function isPrimitive (v) {
|
|
|
45
53
|
)
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
/**
|
|
49
|
-
* @param {ValueType | ValueType[]} v
|
|
50
|
-
* @returns {boolean}
|
|
51
|
-
*/
|
|
52
|
-
function isBuffer (v) {
|
|
53
|
-
return Buffer.isBuffer(v)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
56
|
/**
|
|
57
57
|
* function isArrayBuffer (v) {
|
|
58
58
|
* return v instanceof ArrayBuffer
|