@sequencemedia/dupe 0.0.1 → 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 +24 -18
- package/{index.mjs → src/index.mjs} +8 -5
- package/src/node/index.d.mts +6 -0
- package/src/node/index.mjs +188 -0
- /package/{index.d.mts → src/index.d.mts} +0 -0
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,48 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sequencemedia/dupe",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "./index.mjs",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"types": "./index.d.mts",
|
|
7
|
-
"author": {
|
|
8
|
-
"name": "Jonathan Perry for Sequence Media Limited",
|
|
9
|
-
"email": "sequencemedia@sequencemedia.net",
|
|
10
|
-
"url": "https://sequencemedia.net"
|
|
11
|
-
},
|
|
3
|
+
"version": "0.0.3",
|
|
12
4
|
"keywords": [
|
|
13
5
|
"dupe",
|
|
14
6
|
"duplicate",
|
|
15
7
|
"clone",
|
|
16
8
|
"deep clone",
|
|
17
|
-
"deep"
|
|
9
|
+
"deep",
|
|
10
|
+
"structured clone"
|
|
18
11
|
],
|
|
12
|
+
"main": "./src/index.mjs",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"types": "./src/index.d.mts",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Jonathan Perry for Sequence Media Limited",
|
|
17
|
+
"email": "sequencemedia@sequencemedia.net",
|
|
18
|
+
"url": "https://sequencemedia.net"
|
|
19
|
+
},
|
|
19
20
|
"license": "ISC",
|
|
20
21
|
"scripts": {
|
|
21
22
|
"lint": "eslint .",
|
|
22
23
|
"lint:fix": "npm run lint -- --fix",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
24
|
+
"prepare": "husky",
|
|
25
|
+
"test": "cross-env NODE_ENV=test mocha test --recursive"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"
|
|
28
|
-
"chai": "^5.1.2",
|
|
29
|
-
"D": "^1.0.0",
|
|
30
|
-
"debug": "^4.4.0",
|
|
31
|
-
"mocha": "^11.0.1"
|
|
28
|
+
"debug": "^4.4.0"
|
|
32
29
|
},
|
|
33
30
|
"devDependencies": {
|
|
31
|
+
"chai": "^5.1.2",
|
|
32
|
+
"mocha": "^11.0.1",
|
|
34
33
|
"@babel/core": "^7.26.0",
|
|
35
34
|
"@babel/preset-env": "^7.26.0",
|
|
36
35
|
"@sequencemedia/eslint-config-standard": "^0.2.2",
|
|
37
36
|
"@sequencemedia/eslint-config-typescript": "^0.1.2",
|
|
38
37
|
"@types/debug": "^4.1.12",
|
|
38
|
+
"@types/mocha": "^10.0.10",
|
|
39
|
+
"@types/node": "^22.10.1",
|
|
39
40
|
"core-js": "^3.39.0",
|
|
40
41
|
"cross-env": "^7.0.3",
|
|
41
42
|
"eslint": "^9.16.0",
|
|
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
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @param {ValueType | ValueType[]} v
|
|
13
13
|
* @returns {boolean}
|
|
14
14
|
*/
|
|
15
|
-
function isArray (v) {
|
|
15
|
+
export function isArray (v) {
|
|
16
16
|
return Array.isArray(v)
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ function isArray (v) {
|
|
|
20
20
|
* @param {ValueType | ValueType[]} v
|
|
21
21
|
* @returns {boolean}
|
|
22
22
|
*/
|
|
23
|
-
function isObject (v) {
|
|
23
|
+
export function isObject (v) {
|
|
24
24
|
return (v || false) instanceof Object && !Array.isArray(v)
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -28,16 +28,19 @@ function isObject (v) {
|
|
|
28
28
|
* @param {ValueType | ValueType[]} v
|
|
29
29
|
* @returns {boolean}
|
|
30
30
|
*/
|
|
31
|
-
function isFunction (v) {
|
|
31
|
+
export function isFunction (v) {
|
|
32
32
|
return v instanceof Function
|
|
33
33
|
}
|
|
34
|
-
|
|
35
34
|
/**
|
|
36
35
|
* @param {ValueType | ValueType[]} v
|
|
37
36
|
* @returns {boolean}
|
|
38
37
|
*/
|
|
39
38
|
function isPrimitive (v) {
|
|
40
|
-
return !
|
|
39
|
+
return !(
|
|
40
|
+
isObject(v) ||
|
|
41
|
+
isArray(v) ||
|
|
42
|
+
isFunction(v)
|
|
43
|
+
)
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
/**
|
|
@@ -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 | Buffer | null | undefined
|
|
5
|
+
|
|
6
|
+
export default function dupe (v: ValueType | ValueType[]): ValueType | ValueType[]
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {unknown[] | never[]} ArrayLiteralType
|
|
3
|
+
*
|
|
4
|
+
* @typedef {Record<PropertyKey, unknown> | Record<PropertyKey, never>} ObjectLiteralType
|
|
5
|
+
*
|
|
6
|
+
* @typedef {string | number | ArrayLiteralType | ObjectLiteralType | Buffer | null | undefined} ValueType
|
|
7
|
+
*
|
|
8
|
+
* @typedef {WeakMap<WeakKey, ArrayLiteralType | ObjectLiteralType>} WeakMapType
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {ValueType | ValueType[]} v
|
|
13
|
+
* @returns {boolean}
|
|
14
|
+
*/
|
|
15
|
+
function isArray (v) {
|
|
16
|
+
return Array.isArray(v)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {ValueType | ValueType[]} v
|
|
21
|
+
* @returns {boolean}
|
|
22
|
+
*/
|
|
23
|
+
function isObject (v) {
|
|
24
|
+
return (v || false) instanceof Object && !Array.isArray(v) && !Buffer.isBuffer(v)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {ValueType | ValueType[]} v
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
function isFunction (v) {
|
|
32
|
+
return v instanceof Function
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {ValueType | ValueType[]} v
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isBuffer (v) {
|
|
40
|
+
return Buffer.isBuffer(v)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {ValueType | ValueType[]} v
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
function isPrimitive (v) {
|
|
48
|
+
return !(
|
|
49
|
+
isObject(v) ||
|
|
50
|
+
isArray(v) ||
|
|
51
|
+
isFunction(v) ||
|
|
52
|
+
isBuffer(v)
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* function isArrayBuffer (v) {
|
|
58
|
+
* return v instanceof ArrayBuffer
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {ArrayLiteralType} v
|
|
64
|
+
* @param {WeakMapType} weakMap
|
|
65
|
+
* @returns {ArrayLiteralType}
|
|
66
|
+
*/
|
|
67
|
+
function getArray (v, weakMap) {
|
|
68
|
+
const a = []
|
|
69
|
+
|
|
70
|
+
weakMap.set(v, a)
|
|
71
|
+
|
|
72
|
+
return v.reduce(getReduceArray(weakMap), a)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {ObjectLiteralType} v
|
|
77
|
+
* @param {WeakMapType} weakMap
|
|
78
|
+
* @returns {ObjectLiteralType}
|
|
79
|
+
*/
|
|
80
|
+
function getObject (v, weakMap) {
|
|
81
|
+
const o = {}
|
|
82
|
+
|
|
83
|
+
weakMap.set(v, o)
|
|
84
|
+
|
|
85
|
+
return Object.assign(o, Object.fromEntries(Object.entries(v).map(getMapEntries(weakMap))))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param {Buffer} v
|
|
90
|
+
* @param {WeakMapType} weakMap
|
|
91
|
+
* @returns {Buffer}
|
|
92
|
+
*/
|
|
93
|
+
function getBuffer (v, weakMap) {
|
|
94
|
+
const b = Buffer.from(v)
|
|
95
|
+
|
|
96
|
+
weakMap.set(v, b)
|
|
97
|
+
return b
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {WeakMapType} weakMap
|
|
102
|
+
* @returns {(a: ArrayLiteralType, v: ValueType | ValueType[]) => ArrayLiteralType}
|
|
103
|
+
*/
|
|
104
|
+
function getReduceArray (weakMap) {
|
|
105
|
+
/**
|
|
106
|
+
* @param {ArrayLiteralType} a
|
|
107
|
+
* @param {ValueType | ValueType[]} v
|
|
108
|
+
* @returns {ArrayLiteralType}
|
|
109
|
+
*/
|
|
110
|
+
return function reduceArray (a, v) {
|
|
111
|
+
if (isPrimitive(v) || isFunction(v)) {
|
|
112
|
+
a.push(v)
|
|
113
|
+
return a
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (weakMap.has(v)) {
|
|
117
|
+
a.push(weakMap.get(v))
|
|
118
|
+
return a
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (isArray(v)) {
|
|
122
|
+
a.push(getArray(v, weakMap))
|
|
123
|
+
return a
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (isObject(v)) {
|
|
127
|
+
a.push(getObject(v, weakMap))
|
|
128
|
+
return a
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (isBuffer(v)) {
|
|
132
|
+
a.push(getBuffer(v, weakMap))
|
|
133
|
+
return a
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @param {WeakMapType} weakMap
|
|
140
|
+
* @returns {(entry: [PropertyKey, ValueType | ValueType[]]) => [PropertyKey, ValueType | ValueType[]]}
|
|
141
|
+
*/
|
|
142
|
+
function getMapEntries (weakMap) {
|
|
143
|
+
/**
|
|
144
|
+
* @param {[PropertyKey, ValueType | ValueType[]]} entry
|
|
145
|
+
* @returns {[PropertyKey, ValueType | ValueType[]]}
|
|
146
|
+
*/
|
|
147
|
+
return function mapEntries ([k, v]) {
|
|
148
|
+
if (isPrimitive(v) || isFunction(v)) return [k, v]
|
|
149
|
+
|
|
150
|
+
if (weakMap.has(v)) {
|
|
151
|
+
return [k, weakMap.get(v)]
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (isArray(v)) {
|
|
155
|
+
return [k, getArray(v, weakMap)]
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (isObject(v)) {
|
|
159
|
+
return [k, getObject(v, weakMap)]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (isBuffer(v)) {
|
|
163
|
+
return [k, getBuffer(v, weakMap)]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Duplicate a value
|
|
170
|
+
*
|
|
171
|
+
* @param {ValueType | ValueType[]} v
|
|
172
|
+
* @returns {ValueType | ValueType[]}
|
|
173
|
+
*/
|
|
174
|
+
export default function toDuplicate (v) {
|
|
175
|
+
if (isPrimitive(v) || isFunction(v)) return v
|
|
176
|
+
|
|
177
|
+
if (isArray(v)) {
|
|
178
|
+
return getArray(v, new WeakMap())
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (isObject(v)) {
|
|
182
|
+
return getObject(v, new WeakMap())
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (isBuffer(v)) {
|
|
186
|
+
return getBuffer(v, new WeakMap())
|
|
187
|
+
}
|
|
188
|
+
}
|
|
File without changes
|