@ditojs/utils 2.1.1 → 2.3.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.1.1",
3
+ "version": "2.3.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": "b4ff87b7ffa812092a27b6c28a8ab3c5d7d7094d",
35
+ "gitHead": "81398b333e755f30b2c3c1998c8879a3e87f7873",
36
36
  "scripts": {
37
37
  "types": "tsc --noEmit types/index.d.ts"
38
38
  },
@@ -2,28 +2,40 @@ 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 _merge = (target, source, cloneTarget) => {
6
- if (
7
- target &&
8
- source &&
9
- target !== source && (
10
- isArray(target) && isArray(source) ||
11
- isPlainObject(target) && isPlainObject(source)
12
- )
13
- ) {
14
- const result = cloneTarget
15
- ? clone(target)
16
- : target
17
- for (const key of Object.keys(source)) {
18
- result[key] = _merge(target[key], source[key], true)
5
+ const mergeIteratively = (target, source, cloneTarget, concat) => {
6
+ const result = cloneTarget
7
+ ? clone(target, { shallow: true })
8
+ : target
9
+ for (const key of Object.keys(source)) {
10
+ const to = target[key]
11
+ const from = source[key]
12
+ if (
13
+ !concat ||
14
+ isArray(to) && isArray(from) ||
15
+ isPlainObject(to) && isPlainObject(from)
16
+ ) {
17
+ result[key] = mergeValues(to, from, true)
18
+ } else {
19
+ // Append non-mergeable values to the end of results.
20
+ result.push(from)
21
+ }
22
+ }
23
+ return result
24
+ }
25
+
26
+ const mergeValues = (target, source, cloneTarget) => {
27
+ if (target && source && target !== source) {
28
+ if (isArray(target) && isArray(source)) {
29
+ return mergeIteratively(target, source, cloneTarget, true)
30
+ } else if (isPlainObject(target) && isPlainObject(source)) {
31
+ return mergeIteratively(target, source, cloneTarget, false)
19
32
  }
20
- return result
21
33
  }
22
34
  return source
23
35
  }
24
36
 
25
37
  for (const source of sources) {
26
- _merge(target, source, false)
38
+ mergeValues(target, source, false)
27
39
  }
28
40
  return target
29
41
  }
@@ -77,7 +77,7 @@ describe('merge()', () => {
77
77
 
78
78
  expect(source3.a).toStrictEqual([[1, 2, 3]])
79
79
  expect(source4.a).toStrictEqual([[4, 5]])
80
- expect(actual2.a).toStrictEqual([[4, 5, 3]])
80
+ expect(actual2.a).toStrictEqual([[1, 2, 3, 4, 5]])
81
81
  })
82
82
 
83
83
  it('should overwrite existing values with `undefined` in objects', () => {
@@ -85,15 +85,15 @@ describe('merge()', () => {
85
85
  expect(actual).toStrictEqual({ a: undefined, b: undefined })
86
86
  })
87
87
 
88
- it('should overwrite existing values with `undefined` in arrays', () => {
89
- const array1 = [1]
90
- array1[2] = 3
88
+ it('should not overwrite existing values with `undefined` in arrays', () => {
89
+ const array1 = [1, undefined, 3]
91
90
  const actual1 = merge([4, 5, 6], array1)
92
- expect(actual1).toStrictEqual([1, 5, 3])
91
+ expect(actual1).toStrictEqual([4, 5, 6, 1, undefined, 3])
93
92
 
94
- const array2 = [1, undefined, 3]
93
+ // eslint-disable-next-line no-sparse-arrays
94
+ const array2 = [1, , 3]
95
95
  const actual2 = merge([4, 5, 6], array2)
96
- expect(actual2).toStrictEqual([1, undefined, 3])
96
+ expect(actual2).toStrictEqual([4, 5, 6, 1, 3])
97
97
  })
98
98
 
99
99
  it('should merge regexps', () => {
@@ -19,7 +19,7 @@ describe('format()', () => {
19
19
  it('should use the en-US locale by default', () => {
20
20
  expect(format(integer)).toBe('123,456,789')
21
21
  expect(format(float)).toBe('123,456.789')
22
- expect(format(date)).toBe('June 9, 2012 at 10:45:30 PM')
22
+ expect(format(date)).toMatch(/^June 9, 2012 at 10:45:30\sPM$/)
23
23
  })
24
24
 
25
25
  it('should format numbers with different locale and default options', () => {
@@ -88,7 +88,7 @@ describe('format()', () => {
88
88
  currency: 'EUR'
89
89
  }
90
90
  })
91
- ).toBe('123.456.789,00 €')
91
+ ).toMatch(/^123\.456\.789,00\s€$/)
92
92
  expect(
93
93
  format(integer, {
94
94
  locale: 'de-CH',
@@ -97,7 +97,7 @@ describe('format()', () => {
97
97
  currency: 'CHF'
98
98
  }
99
99
  })
100
- ).toBe('CHF 123’456’789.00')
100
+ ).toMatch(/^CHF\s123’456’789\.00$/)
101
101
  expect(
102
102
  format(float, {
103
103
  locale: 'de-DE',
@@ -106,7 +106,7 @@ describe('format()', () => {
106
106
  currency: 'EUR'
107
107
  }
108
108
  })
109
- ).toBe('123.456,79 €')
109
+ ).toMatch(/^123\.456,79\s€$/)
110
110
  expect(
111
111
  format(float, {
112
112
  locale: 'de-CH',
@@ -115,7 +115,7 @@ describe('format()', () => {
115
115
  currency: 'CHF'
116
116
  }
117
117
  })
118
- ).toBe('CHF 123’456.79')
118
+ ).toMatch(/^CHF\s123’456\.79$/)
119
119
  })
120
120
 
121
121
  it('should support fine-grained control of `options.date`', () => {
@@ -188,7 +188,7 @@ describe('format()', () => {
188
188
  ).toBe('May 24, 2016')
189
189
  expect(
190
190
  format('2016-05-24T15:54:14.876Z', { date: true, time: true })
191
- ).toBe('May 24, 2016 at 05:54:14 PM')
191
+ ).toMatch(/^May 24, 2016 at 05:54:14\sPM$/)
192
192
  expect(format('123456789', { number: true })).toBe('123,456,789')
193
193
  expect(format('123456.789', { number: true })).toBe('123,456.789')
194
194
  expect(format('Hello World')).toBe('Hello World')
@@ -8,8 +8,8 @@ describe('formatDate()', () => {
8
8
  })
9
9
 
10
10
  it('should use the en-US locale by default', () => {
11
- expect(formatDate(date)).toBe('June 9, 2012 at 10:45:30 PM')
12
- expect(formatDate(date, {})).toBe('June 9, 2012 at 10:45:30 PM')
11
+ expect(formatDate(date)).toMatch(/^June 9, 2012 at 10:45:30\sPM$/)
12
+ expect(formatDate(date, {})).toMatch(/^June 9, 2012 at 10:45:30\sPM$/)
13
13
  })
14
14
 
15
15
  it('should format dates with different locale and default options', () => {