@magic/deep 0.1.15 → 0.1.17
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 +51 -19
- package/package.json +11 -6
- package/src/flatten.js +33 -0
- package/src/{index.mjs → index.js} +3 -3
- package/src/loop.js +94 -0
- package/src/{merge.mjs → merge.js} +14 -5
- package/src/flatten.mjs +0 -9
- package/src/loop.mjs +0 -35
package/README.md
CHANGED
|
@@ -23,11 +23,13 @@ Work with deeply nested objects and arrays.
|
|
|
23
23
|
[snyk-url]: https://snyk.io/test/github/magic/deep
|
|
24
24
|
|
|
25
25
|
##### install
|
|
26
|
+
|
|
26
27
|
```bash
|
|
27
28
|
npm i --save --save-exact @magic/deep
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
##### import
|
|
32
|
+
|
|
31
33
|
```javascript
|
|
32
34
|
// single function
|
|
33
35
|
import { equal, flatten, loop, merge } from '@magic/deep'
|
|
@@ -39,27 +41,29 @@ import deep from '@magic/deep'
|
|
|
39
41
|
Currently implemented:
|
|
40
42
|
|
|
41
43
|
##### deep.equal
|
|
44
|
+
|
|
42
45
|
```javascript
|
|
43
46
|
// test equality
|
|
44
47
|
deep.equal(['shallow', ['deep']], ['shallow', ['deep']])
|
|
45
48
|
// true
|
|
46
49
|
|
|
47
50
|
// alias
|
|
48
|
-
deep.equals, deep.eq
|
|
51
|
+
// deep.equals, deep.eq
|
|
49
52
|
```
|
|
50
53
|
|
|
51
54
|
##### deep.different
|
|
55
|
+
|
|
52
56
|
```javascript
|
|
53
57
|
// test difference
|
|
54
58
|
deep.different(['shallow', ['deep']], ['shallow', ['deep']])
|
|
55
59
|
// false
|
|
56
60
|
|
|
57
61
|
// alias
|
|
58
|
-
deep.diff
|
|
62
|
+
// deep.diff
|
|
59
63
|
```
|
|
60
64
|
|
|
61
|
-
|
|
62
65
|
##### deep.flatten
|
|
66
|
+
|
|
63
67
|
```javascript
|
|
64
68
|
// flatten a deeply nested array
|
|
65
69
|
deep.flatten(['shallow', ['deep']])
|
|
@@ -67,6 +71,7 @@ deep.flatten(['shallow', ['deep']])
|
|
|
67
71
|
```
|
|
68
72
|
|
|
69
73
|
##### deep.loop
|
|
74
|
+
|
|
70
75
|
```javascript
|
|
71
76
|
// apply function add
|
|
72
77
|
const add = e => e + 1
|
|
@@ -82,11 +87,12 @@ deep.loop(items, add)
|
|
|
82
87
|
```
|
|
83
88
|
|
|
84
89
|
##### deep.merge
|
|
90
|
+
|
|
85
91
|
```javascript
|
|
86
92
|
// merge objects and arrays, with infinite recursion if needed.
|
|
87
93
|
// this can be slow...
|
|
88
94
|
|
|
89
|
-
deep.merge({ obj1Key: { val: 1 } }, { obj2Key: { val: 2 } }
|
|
95
|
+
deep.merge({ obj1Key: { val: 1 } }, { obj2Key: { val: 2 } })
|
|
90
96
|
|
|
91
97
|
// { obj1Key: { val: 1}, obj2Key: { val: 2 } }
|
|
92
98
|
|
|
@@ -98,56 +104,82 @@ deep.merge({ key: { val: 1, str: 'test' } }, { key: { val: 2, str: 'overwritten'
|
|
|
98
104
|
### Changelog
|
|
99
105
|
|
|
100
106
|
#### 0.1.0
|
|
107
|
+
|
|
101
108
|
use ecmascript modules instead of commonjs.
|
|
102
109
|
|
|
103
110
|
#### 0.1.1
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
|
|
112
|
+
- update readme
|
|
113
|
+
- also export deep.eq alias for deep.equal
|
|
106
114
|
|
|
107
115
|
#### 0.1.2
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
|
|
117
|
+
- require node 13.5.0
|
|
118
|
+
- use deep.equal and deep.different from @magic/types
|
|
110
119
|
|
|
111
120
|
#### 0.1.3
|
|
121
|
+
|
|
112
122
|
bump required node version to 14.2.0
|
|
113
123
|
|
|
114
|
-
#### 0.1.4
|
|
124
|
+
#### 0.1.4
|
|
125
|
+
|
|
115
126
|
update dependencies
|
|
116
127
|
|
|
117
128
|
#### 0.1.5
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
|
|
130
|
+
- bump required node version to 14.15.4
|
|
131
|
+
- update dependencies
|
|
120
132
|
|
|
121
133
|
##### 0.1.6
|
|
122
|
-
* merge now checks if o2.hasOwnProperty is a function before using it to check if we should overwrite keys of o1 or not.
|
|
123
134
|
|
|
124
|
-
|
|
135
|
+
- merge now checks if o2.hasOwnProperty is a function before using it to check if we should overwrite keys of o1 or not.
|
|
136
|
+
|
|
137
|
+
##### 0.1.7
|
|
138
|
+
|
|
125
139
|
update @magic/types to avoid circular dependency
|
|
126
140
|
|
|
127
141
|
##### 0.1.8
|
|
128
|
-
|
|
129
|
-
|
|
142
|
+
|
|
143
|
+
- update dependencies
|
|
144
|
+
- use @magic/types for all type comparisons
|
|
130
145
|
|
|
131
146
|
##### 0.1.9
|
|
147
|
+
|
|
132
148
|
update dependencies
|
|
133
149
|
|
|
134
150
|
##### 0.1.10
|
|
151
|
+
|
|
135
152
|
update dependencies
|
|
136
153
|
|
|
137
154
|
##### 0.1.11
|
|
155
|
+
|
|
138
156
|
update dependencies
|
|
139
157
|
|
|
140
158
|
##### 0.1.12
|
|
159
|
+
|
|
141
160
|
update dependencies
|
|
142
161
|
|
|
143
|
-
##### 0.
|
|
162
|
+
##### 0.1.13
|
|
163
|
+
|
|
144
164
|
update dependencies
|
|
145
165
|
|
|
146
|
-
##### 0.
|
|
166
|
+
##### 0.1.14
|
|
167
|
+
|
|
147
168
|
update dependencies
|
|
148
169
|
|
|
149
|
-
##### 0.
|
|
170
|
+
##### 0.1.15
|
|
171
|
+
|
|
172
|
+
update dependencies
|
|
173
|
+
|
|
174
|
+
##### 0.1.16
|
|
175
|
+
|
|
150
176
|
update dependencies
|
|
151
177
|
|
|
152
|
-
##### 0.
|
|
178
|
+
##### 0.1.17
|
|
179
|
+
|
|
180
|
+
- add typescript types
|
|
181
|
+
- update dependencies
|
|
182
|
+
|
|
183
|
+
##### 0.1.18 - unreleased
|
|
184
|
+
|
|
153
185
|
...
|
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magic/deep",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"author": "Wizards & Witches",
|
|
5
5
|
"description": "manipulate nested objects and arrays",
|
|
6
6
|
"homepage": "https://github.com/magic/deep",
|
|
7
7
|
"license": "AGPL-3.0",
|
|
8
|
-
"main": "src/index.
|
|
9
|
-
"
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"types": "types/index.d.ts",
|
|
10
|
+
"module": "src/index.js",
|
|
10
11
|
"type": "module",
|
|
11
12
|
"scripts": {
|
|
12
13
|
"start": "t",
|
|
14
|
+
"build": "tsc && npm run format",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
13
16
|
"test": "t",
|
|
14
17
|
"format": "f -w",
|
|
15
18
|
"format:check": "f",
|
|
@@ -30,11 +33,13 @@
|
|
|
30
33
|
"src"
|
|
31
34
|
],
|
|
32
35
|
"dependencies": {
|
|
33
|
-
"@magic/types": "0.1.
|
|
36
|
+
"@magic/types": "0.1.26"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
|
-
"@magic/format": "0.0.
|
|
37
|
-
"@magic/test": "0.2.
|
|
39
|
+
"@magic/format": "0.0.68",
|
|
40
|
+
"@magic/test": "0.2.20",
|
|
41
|
+
"@types/node": "24.5.2",
|
|
42
|
+
"typescript": "5.9.2"
|
|
38
43
|
},
|
|
39
44
|
"contributors": [
|
|
40
45
|
{
|
package/src/flatten.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import is from '@magic/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Flattens one level of an array if input is an array, otherwise returns the input as-is.
|
|
5
|
+
*
|
|
6
|
+
* @template T
|
|
7
|
+
* @param {T | T[]} flat - An array or value to flatten.
|
|
8
|
+
* @returns {T[]} The flattened value or array.
|
|
9
|
+
*/
|
|
10
|
+
export const shallow = flat => (is.array(flat) ? flatten(...flat) : [flat])
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Concatenates a flat array with another deep value or array.
|
|
14
|
+
*
|
|
15
|
+
* @template T
|
|
16
|
+
* @param {T[]} flat - The flat array to concatenate into.
|
|
17
|
+
* @param {T | T[]} deep - A value or array to be flattened and concatenated.
|
|
18
|
+
* @returns {T[]} The concatenated array.
|
|
19
|
+
*/
|
|
20
|
+
export const concat = (flat, deep) => flat.concat(shallow(deep))
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Recursively flattens one or more arrays into a single-level array.
|
|
24
|
+
*
|
|
25
|
+
* @template T
|
|
26
|
+
* @param {...(T | T[])} arr - The arrays or values to flatten.
|
|
27
|
+
* @returns {T[]} The flattened array.
|
|
28
|
+
*/
|
|
29
|
+
export const flatten = (...arr) =>
|
|
30
|
+
/** @type {T[]} */ (arr.reduce(/** @type {any} */ (concat), /** @type {T[]} */ ([])))
|
|
31
|
+
|
|
32
|
+
/** @type {(arr: any[]) => any[]} */
|
|
33
|
+
export default flatten
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import is from '@magic/types'
|
|
2
2
|
|
|
3
|
-
import { loop as lo } from './loop.
|
|
4
|
-
import { merge as me } from './merge.
|
|
5
|
-
import { flatten as fl } from './flatten.
|
|
3
|
+
import { loop as lo } from './loop.js'
|
|
4
|
+
import { merge as me } from './merge.js'
|
|
5
|
+
import { flatten as fl } from './flatten.js'
|
|
6
6
|
|
|
7
7
|
export const equal = is.deep.equal
|
|
8
8
|
export const equals = is.deep.equal
|
package/src/loop.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import is from '@magic/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Recursively applies a function to items or transforms items based on conditions.
|
|
5
|
+
*
|
|
6
|
+
* @template T, R
|
|
7
|
+
* @param {((item: T) => R) | T} fn - Function to apply or the first item.
|
|
8
|
+
* @param {...any} items - Items to loop over (can be nested arrays).
|
|
9
|
+
* @returns {any} The transformed result, array of results, or undefined.
|
|
10
|
+
*/
|
|
11
|
+
export const loop = (fn, ...items) => {
|
|
12
|
+
// If no arguments, return undefined
|
|
13
|
+
if (!fn && items.length === 0) {
|
|
14
|
+
return undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// If only function provided, return undefined
|
|
18
|
+
if (is.function(fn) && items.length === 0) {
|
|
19
|
+
return undefined
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let targets = items
|
|
23
|
+
|
|
24
|
+
// Check for argument swapping: if fn is not a function but we have items and one of them is a function
|
|
25
|
+
if (!is.function(fn) && items.length > 0) {
|
|
26
|
+
const functionIndex = items.findIndex(item => is.function(item))
|
|
27
|
+
if (functionIndex !== -1) {
|
|
28
|
+
// Swap: fn becomes the target, and the function becomes fn
|
|
29
|
+
const actualFn = items[functionIndex]
|
|
30
|
+
targets = [fn, ...items.slice(0, functionIndex), ...items.slice(functionIndex + 1)]
|
|
31
|
+
fn = actualFn
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Handle the case where we have multiple items but one of them is an object (options)
|
|
36
|
+
if (is.array(targets) && targets.length > 1) {
|
|
37
|
+
// Check if any item is an object (options pattern)
|
|
38
|
+
const hasOptions = targets.some(item => is.object(item) && !is.array(item))
|
|
39
|
+
|
|
40
|
+
if (hasOptions && is.function(fn)) {
|
|
41
|
+
// Apply function to each item
|
|
42
|
+
return targets.map(item => {
|
|
43
|
+
if (is.array(item)) {
|
|
44
|
+
return item.map(subItem => loop(fn, subItem))
|
|
45
|
+
}
|
|
46
|
+
return is.object(item) && !is.array(item)
|
|
47
|
+
? item
|
|
48
|
+
: /** @type {(item: any) => any} */ (fn)(item)
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!is.function(fn)) {
|
|
53
|
+
return [fn, ...targets]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Apply function to multiple items
|
|
57
|
+
return targets.map(item => {
|
|
58
|
+
if (is.array(item)) {
|
|
59
|
+
return item.map(subItem => loop(fn, subItem))
|
|
60
|
+
}
|
|
61
|
+
return /** @type {(item: any) => any} */ (fn)(item)
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Single item case - if targets is an array with one element, unwrap it
|
|
66
|
+
if (is.array(targets) && targets.length === 1) {
|
|
67
|
+
targets = /** @type {any} */ (targets[0])
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// If fn is not a function, return tuple
|
|
71
|
+
if (!is.function(fn)) {
|
|
72
|
+
return [fn, targets]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// If targets is null/undefined, apply function directly
|
|
76
|
+
if (!targets) {
|
|
77
|
+
return fn(targets)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// If targets has map method (is array-like), map over it
|
|
81
|
+
if (is.array(targets)) {
|
|
82
|
+
return targets.map(item => {
|
|
83
|
+
if (is.array(item)) {
|
|
84
|
+
return loop(fn, item)
|
|
85
|
+
}
|
|
86
|
+
return /** @type {(item: any) => any} */ (fn)(item)
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// For non-array targets, apply function directly
|
|
91
|
+
return /** @type {(item: any) => any} */ (fn)(targets)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default loop
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import is from '@magic/types'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Recursively merges two values or objects.
|
|
5
|
+
*
|
|
6
|
+
* @template T
|
|
7
|
+
* @template U
|
|
8
|
+
* @param {T} o1 - First value or object.
|
|
9
|
+
* @param {U} o2 - Second value or object.
|
|
10
|
+
* @returns {any} Merged result.
|
|
11
|
+
*/
|
|
3
12
|
export const merge = (o1, o2) => {
|
|
4
13
|
if (is.undefined(o1)) {
|
|
5
14
|
return o2
|
|
@@ -8,15 +17,16 @@ export const merge = (o1, o2) => {
|
|
|
8
17
|
}
|
|
9
18
|
|
|
10
19
|
if (is.array(o1)) {
|
|
11
|
-
return
|
|
20
|
+
return is.array(o2)
|
|
21
|
+
? /** @type {any[]} */ (o1).concat(/** @type {any[]} */ (o2))
|
|
22
|
+
: /** @type {any[]} */ (o1).concat([o2])
|
|
12
23
|
} else if (is.array(o2)) {
|
|
13
|
-
return [].concat(
|
|
24
|
+
return [o1].concat(/** @type {any[]} */ (o2))
|
|
14
25
|
}
|
|
15
26
|
|
|
16
27
|
if (is.mergeable(o1) && is.mergeable(o2)) {
|
|
17
28
|
const keys = Object.keys({ ...o1, ...o2 })
|
|
18
|
-
const final = {}
|
|
19
|
-
|
|
29
|
+
const final = /** @type {Record<string, any>} */ ({})
|
|
20
30
|
keys.forEach(key => {
|
|
21
31
|
if (!is.function(o2.hasOwnProperty) || !o2.hasOwnProperty(key)) {
|
|
22
32
|
final[key] = o1[key]
|
|
@@ -24,7 +34,6 @@ export const merge = (o1, o2) => {
|
|
|
24
34
|
final[key] = merge(o1[key], o2[key])
|
|
25
35
|
}
|
|
26
36
|
})
|
|
27
|
-
|
|
28
37
|
return final
|
|
29
38
|
}
|
|
30
39
|
|
package/src/flatten.mjs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import is from '@magic/types'
|
|
2
|
-
|
|
3
|
-
export const shallow = flat => (is.array(flat) ? flatten(...flat) : flat)
|
|
4
|
-
|
|
5
|
-
export const concat = (flat, deep) => flat.concat(shallow(deep))
|
|
6
|
-
|
|
7
|
-
export const flatten = (...arr) => arr.reduce(concat, [])
|
|
8
|
-
|
|
9
|
-
export default flatten
|
package/src/loop.mjs
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import is from '@magic/types'
|
|
2
|
-
|
|
3
|
-
export const loop = (fn, ...items) => {
|
|
4
|
-
if (is.empty(items)) {
|
|
5
|
-
if (is.fn(fn)) {
|
|
6
|
-
return fn(...items)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
return
|
|
10
|
-
} else if (items.length === 1) {
|
|
11
|
-
items = items[0]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (!is.function(fn) && is.function(items)) {
|
|
15
|
-
const oldFn = fn
|
|
16
|
-
fn = items
|
|
17
|
-
items = oldFn
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (!is.function(fn)) {
|
|
21
|
-
return [fn, items]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (!items) {
|
|
25
|
-
return fn(items)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!is.function(items.map)) {
|
|
29
|
-
return fn(items)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return items.map(item => loop(fn, item))
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default loop
|