@magic/deep 0.1.16 → 0.1.18

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 CHANGED
@@ -48,7 +48,7 @@ deep.equal(['shallow', ['deep']], ['shallow', ['deep']])
48
48
  // true
49
49
 
50
50
  // alias
51
- deep.equals, deep.eq
51
+ // deep.equals, deep.eq
52
52
  ```
53
53
 
54
54
  ##### deep.different
@@ -59,7 +59,7 @@ deep.different(['shallow', ['deep']], ['shallow', ['deep']])
59
59
  // false
60
60
 
61
61
  // alias
62
- deep.diff
62
+ // deep.diff
63
63
  ```
64
64
 
65
65
  ##### deep.flatten
@@ -159,22 +159,31 @@ update dependencies
159
159
 
160
160
  update dependencies
161
161
 
162
- ##### 0.0.13
162
+ ##### 0.1.13
163
163
 
164
164
  update dependencies
165
165
 
166
- ##### 0.0.14
166
+ ##### 0.1.14
167
167
 
168
168
  update dependencies
169
169
 
170
- ##### 0.0.15
170
+ ##### 0.1.15
171
171
 
172
172
  update dependencies
173
173
 
174
- ##### 0.0.16
174
+ ##### 0.1.16
175
175
 
176
176
  update dependencies
177
177
 
178
- ##### 0.0.17 - unreleased
178
+ ##### 0.1.17
179
+
180
+ - add typescript types
181
+ - update dependencies
182
+
183
+ ##### 0.1.18
184
+
185
+ - actually add types to pkg files array
186
+
187
+ ##### 0.0.19 - unreleased
179
188
 
180
189
  ...
package/package.json CHANGED
@@ -1,15 +1,18 @@
1
1
  {
2
2
  "name": "@magic/deep",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
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.mjs",
9
- "module": "src/index.mjs",
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",
@@ -27,14 +30,17 @@
27
30
  "url": "https://github.com/magic/deep/issues"
28
31
  },
29
32
  "files": [
30
- "src"
33
+ "src",
34
+ "types"
31
35
  ],
32
36
  "dependencies": {
33
- "@magic/types": "0.1.23"
37
+ "@magic/types": "0.1.26"
34
38
  },
35
39
  "devDependencies": {
36
- "@magic/format": "0.0.50",
37
- "@magic/test": "0.2.15"
40
+ "@magic/format": "0.0.68",
41
+ "@magic/test": "0.2.20",
42
+ "@types/node": "24.5.2",
43
+ "typescript": "5.9.2"
38
44
  },
39
45
  "contributors": [
40
46
  {
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.mjs'
4
- import { merge as me } from './merge.mjs'
5
- import { flatten as fl } from './flatten.mjs'
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 o1.concat(o2)
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(o1, ...o2)
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
 
@@ -0,0 +1,4 @@
1
+ export function shallow<T>(flat: T | T[]): T[]
2
+ export function concat<T>(flat: T[], deep: T | T[]): T[]
3
+ export function flatten<T>(...arr: (T | T[])[]): T[]
4
+ export default flatten
@@ -0,0 +1,34 @@
1
+ export const equal: {
2
+ (a: unknown, b: unknown): boolean
3
+ (a: unknown): (c: unknown) => boolean
4
+ }
5
+ export const equals: {
6
+ (a: unknown, b: unknown): boolean
7
+ (a: unknown): (c: unknown) => boolean
8
+ }
9
+ export const eq: {
10
+ (a: unknown, b: unknown): boolean
11
+ (a: unknown): (c: unknown) => boolean
12
+ }
13
+ export const different: {
14
+ (a: unknown, b: unknown): boolean
15
+ (a: unknown): (c: unknown) => boolean
16
+ }
17
+ export const diff: {
18
+ (a: unknown, b: unknown): boolean
19
+ (a: unknown): (c: unknown) => boolean
20
+ }
21
+ export const flatten: <T>(...arr: (T | T[])[]) => T[]
22
+ export const loop: <T, R>(fn: ((item: T) => R) | T, ...items: any[]) => any
23
+ export const merge: <T, U>(o1: T, o2: U) => any
24
+ declare namespace _default {
25
+ export { equal }
26
+ export { equals }
27
+ export { eq }
28
+ export { different }
29
+ export { diff }
30
+ export { flatten }
31
+ export { loop }
32
+ export { merge }
33
+ }
34
+ export default _default
@@ -0,0 +1,2 @@
1
+ export function loop<T, R>(fn: ((item: T) => R) | T, ...items: any[]): any
2
+ export default loop
@@ -0,0 +1,2 @@
1
+ export function merge<T, U>(o1: T, o2: U): any
2
+ export default merge
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