@ditojs/utils 2.4.1 → 2.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/utils",
3
- "version": "2.4.1",
3
+ "version": "2.6.0",
4
4
  "type": "module",
5
5
  "description": "Dito.js Utility Functions – Dito.js is a declarative and modern web framework, based on Objection.js, Koa.js and Vue.js",
6
6
  "repository": "https://github.com/ditojs/dito/tree/master/packages/utils",
@@ -32,7 +32,7 @@
32
32
  "typescript": "^5.0.4"
33
33
  },
34
34
  "types": "types",
35
- "gitHead": "aa24e36fb6be2ad0113d13a1bda6d8d8b04bd77e",
35
+ "gitHead": "ce98ce03662c08e040ad7f9cb93cc0f48e11edb9",
36
36
  "scripts": {
37
37
  "types": "tsc --noEmit types/index.d.ts"
38
38
  },
@@ -2,10 +2,10 @@ import { isArray, isPlainObject } from '../base/index.js'
2
2
  import { clone } from './clone.js'
3
3
 
4
4
  export function merge(target, ...sources) {
5
- const mergeIteratively = (target, source, cloneTarget, concat) => {
6
- const result = cloneTarget
7
- ? clone(target, { shallow: true })
8
- : target
5
+ const mergeIteratively = (target, source, root, concat) => {
6
+ const result = root
7
+ ? target
8
+ : clone(target, { shallow: true })
9
9
  for (const key of Object.keys(source)) {
10
10
  const to = target[key]
11
11
  const from = source[key]
@@ -14,7 +14,7 @@ export function merge(target, ...sources) {
14
14
  isArray(to) && isArray(from) ||
15
15
  isPlainObject(to) && isPlainObject(from)
16
16
  ) {
17
- result[key] = mergeValues(to, from, true)
17
+ result[key] = mergeValues(to, from, false)
18
18
  } else {
19
19
  // Append non-mergeable values to the end of results.
20
20
  result.push(from)
@@ -23,19 +23,19 @@ export function merge(target, ...sources) {
23
23
  return result
24
24
  }
25
25
 
26
- const mergeValues = (target, source, cloneTarget) => {
26
+ const mergeValues = (target, source, root) => {
27
27
  if (target && source && target !== source) {
28
28
  if (isArray(target) && isArray(source)) {
29
- return mergeIteratively(target, source, cloneTarget, true)
29
+ return mergeIteratively(target, source, root, true)
30
30
  } else if (isPlainObject(target) && isPlainObject(source)) {
31
- return mergeIteratively(target, source, cloneTarget, false)
31
+ return mergeIteratively(target, source, root, false)
32
32
  }
33
33
  }
34
- return source
34
+ return root ? source ?? target : source
35
35
  }
36
36
 
37
37
  for (const source of sources) {
38
- mergeValues(target, source, false)
38
+ target = mergeValues(target, source, true)
39
39
  }
40
40
  return target
41
41
  }
@@ -55,6 +55,20 @@ describe('merge()', () => {
55
55
  expect(merge(names, ages, heights)).toEqual(expected)
56
56
  })
57
57
 
58
+ it('should handle plain values', () => {
59
+ expect(merge(true, false)).toEqual(false)
60
+ expect(merge(10, 0)).toEqual(0)
61
+ expect(merge(0, 10)).toEqual(10)
62
+ expect(merge('foo', 'bar')).toEqual('bar')
63
+ })
64
+
65
+ it('should not override values with nullish values at root level', () => {
66
+ expect(merge({}, null)).toEqual({})
67
+ expect(merge([], null)).toEqual([])
68
+ expect(merge(10, null)).toEqual(10)
69
+ expect(merge(false, null)).toEqual(false)
70
+ })
71
+
58
72
  it('should work with multiple arguments', () => {
59
73
  const expected = { a: 4 }
60
74
  const actual = merge({ a: 1 }, { a: 2 }, { a: 3 }, expected)