@oscarpalmer/atoms 0.185.0 → 0.186.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/dist/array/difference.d.mts +29 -0
- package/dist/array/exists.d.mts +35 -0
- package/dist/array/filter.d.mts +72 -2
- package/dist/array/find.d.mts +70 -0
- package/dist/array/first.d.mts +77 -2
- package/dist/array/flatten.d.mts +6 -0
- package/dist/array/flatten.mjs +6 -0
- package/dist/array/from.d.mts +36 -0
- package/dist/array/get.d.mts +21 -13
- package/dist/array/group-by.d.mts +142 -0
- package/dist/array/insert.d.mts +16 -0
- package/dist/array/intersection.d.mts +29 -0
- package/dist/array/last.d.mts +75 -2
- package/dist/array/match.d.mts +161 -32
- package/dist/array/move.d.mts +78 -8
- package/dist/array/move.mjs +10 -0
- package/dist/array/partition.d.mts +35 -0
- package/dist/array/push.d.mts +8 -0
- package/dist/array/push.mjs +8 -0
- package/dist/array/reverse.d.mts +1 -0
- package/dist/array/reverse.mjs +1 -0
- package/dist/array/select.d.mts +94 -8
- package/dist/array/single.d.mts +29 -0
- package/dist/array/slice.d.mts +106 -16
- package/dist/array/sort.d.mts +21 -0
- package/dist/array/splice.d.mts +48 -0
- package/dist/array/splice.mjs +2 -1
- package/dist/array/swap.d.mts +113 -8
- package/dist/array/swap.mjs +1 -0
- package/dist/array/to-map.d.mts +124 -0
- package/dist/array/to-record.d.mts +124 -0
- package/dist/array/to-set.d.mts +24 -0
- package/dist/array/toggle.d.mts +38 -3
- package/dist/array/union.d.mts +29 -0
- package/dist/array/unique.d.mts +24 -0
- package/dist/array/update.d.mts +38 -3
- package/dist/index.d.mts +1892 -135
- package/dist/index.mjs +64 -18
- package/dist/internal/array/chunk.d.mts +6 -0
- package/dist/internal/array/chunk.mjs +6 -0
- package/dist/internal/array/compact.d.mts +12 -0
- package/dist/internal/array/index-of.d.mts +70 -0
- package/dist/internal/math/aggregate.d.mts +29 -0
- package/dist/internal/value/get.d.mts +25 -3
- package/dist/internal/value/has.d.mts +4 -4
- package/dist/models.d.mts +14 -1
- package/dist/value/collection.d.mts +1 -1
- package/dist/value/merge.d.mts +28 -25
- package/dist/value/merge.mjs +29 -18
- package/dist/value/transform.d.mts +1 -1
- package/dist/value/unsmush.d.mts +1 -5
- package/package.json +5 -5
- package/src/array/difference.ts +29 -0
- package/src/array/exists.ts +35 -0
- package/src/array/filter.ts +72 -2
- package/src/array/find.ts +70 -0
- package/src/array/first.ts +77 -3
- package/src/array/flatten.ts +6 -0
- package/src/array/from.ts +36 -0
- package/src/array/get.ts +21 -15
- package/src/array/group-by.ts +142 -0
- package/src/array/insert.ts +16 -2
- package/src/array/intersection.ts +29 -0
- package/src/array/last.ts +75 -2
- package/src/array/match.ts +171 -42
- package/src/array/move.ts +82 -12
- package/src/array/partition.ts +35 -0
- package/src/array/push.ts +8 -2
- package/src/array/reverse.ts +1 -0
- package/src/array/select.ts +94 -13
- package/src/array/single.ts +29 -0
- package/src/array/slice.ts +114 -24
- package/src/array/sort.ts +21 -0
- package/src/array/splice.ts +52 -4
- package/src/array/swap.ts +117 -12
- package/src/array/to-map.ts +124 -0
- package/src/array/to-record.ts +124 -0
- package/src/array/to-set.ts +24 -0
- package/src/array/toggle.ts +38 -3
- package/src/array/union.ts +29 -0
- package/src/array/unique.ts +24 -0
- package/src/array/update.ts +38 -3
- package/src/internal/array/chunk.ts +6 -0
- package/src/internal/array/compact.ts +12 -0
- package/src/internal/array/index-of.ts +70 -0
- package/src/internal/math/aggregate.ts +29 -0
- package/src/internal/string.ts +0 -2
- package/src/internal/value/get.ts +25 -3
- package/src/internal/value/has.ts +4 -4
- package/src/models.ts +18 -0
- package/src/value/collection.ts +1 -1
- package/src/value/merge.ts +88 -66
- package/src/value/transform.ts +1 -1
- package/src/value/unsmush.ts +1 -10
|
@@ -5,10 +5,20 @@ import type {PlainObject} from '../../models';
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Get the index of the first matching item by callback
|
|
8
|
+
*
|
|
8
9
|
* @param array Array to search in
|
|
9
10
|
* @param callback Callback to get an item's value
|
|
10
11
|
* @param value Value to match against
|
|
11
12
|
* @returns Index of the first matching item, or `-1` if no match is found
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* indexOf(
|
|
17
|
+
* [{id: 1}, {id: 2}, {id: 3}],
|
|
18
|
+
* item => item.id,
|
|
19
|
+
* 2,
|
|
20
|
+
* ); // => 1
|
|
21
|
+
* ```
|
|
12
22
|
*/
|
|
13
23
|
export function indexOf<
|
|
14
24
|
Item,
|
|
@@ -17,10 +27,20 @@ export function indexOf<
|
|
|
17
27
|
|
|
18
28
|
/**
|
|
19
29
|
* Get the index of the first matching item by key
|
|
30
|
+
*
|
|
20
31
|
* @param array Array to search in
|
|
21
32
|
* @param key Key to match items by
|
|
22
33
|
* @param value Value to match against
|
|
23
34
|
* @returns Index of the first matching item, or `-1` if no match is found
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* indexOf(
|
|
39
|
+
* [{id: 1}, {id: 2}, {id: 3}],
|
|
40
|
+
* 'id',
|
|
41
|
+
* 2,
|
|
42
|
+
* ); // => 1
|
|
43
|
+
* ```
|
|
24
44
|
*/
|
|
25
45
|
export function indexOf<Item extends PlainObject, ItemKey extends keyof Item>(
|
|
26
46
|
array: Item[],
|
|
@@ -30,9 +50,18 @@ export function indexOf<Item extends PlainObject, ItemKey extends keyof Item>(
|
|
|
30
50
|
|
|
31
51
|
/**
|
|
32
52
|
* Get the index of the first item matching the filter
|
|
53
|
+
*
|
|
33
54
|
* @param array Array to search in
|
|
34
55
|
* @param filter Filter callback to match items
|
|
35
56
|
* @returns Index of the first matching item, or `-1` if no match is found
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* indexOf(
|
|
61
|
+
* [{id: 1}, {id: 2}, {id: 3}],
|
|
62
|
+
* item => item.id === 2,
|
|
63
|
+
* ); // => 1
|
|
64
|
+
* ```
|
|
36
65
|
*/
|
|
37
66
|
export function indexOf<Item>(
|
|
38
67
|
array: Item[],
|
|
@@ -41,9 +70,15 @@ export function indexOf<Item>(
|
|
|
41
70
|
|
|
42
71
|
/**
|
|
43
72
|
* Get the index of the first item matching the given item
|
|
73
|
+
*
|
|
44
74
|
* @param array Array to search in
|
|
45
75
|
* @param item Item to match against
|
|
46
76
|
* @returns Index of the first matching item, or `-1` if no match is found
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* indexOf([1, 2, 3, 4, 5], 3); // => 2
|
|
81
|
+
* ```
|
|
47
82
|
*/
|
|
48
83
|
export function indexOf<Item>(array: Item[], item: Item): number;
|
|
49
84
|
|
|
@@ -57,10 +92,20 @@ indexOf.last = lastIndexOf;
|
|
|
57
92
|
* Get the index of the last matching item by callback
|
|
58
93
|
*
|
|
59
94
|
* Available as `lastIndexOf` and `indexOf.last`
|
|
95
|
+
*
|
|
60
96
|
* @param array Array to search in
|
|
61
97
|
* @param callback Callback to get an item's value
|
|
62
98
|
* @param value Value to match against
|
|
63
99
|
* @returns Index of the last matching item, or `-1` if no match is found
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* lastIndexOf(
|
|
104
|
+
* [{id: 1}, {id: 2}, {id: 3}, {id: 2}],
|
|
105
|
+
* item => item.id,
|
|
106
|
+
* 2,
|
|
107
|
+
* ); // => 3
|
|
108
|
+
* ```
|
|
64
109
|
*/
|
|
65
110
|
export function lastIndexOf<
|
|
66
111
|
Item,
|
|
@@ -71,10 +116,20 @@ export function lastIndexOf<
|
|
|
71
116
|
* Get the index of the last matching item by key
|
|
72
117
|
*
|
|
73
118
|
* Available as `lastIndexOf` and `indexOf.last`
|
|
119
|
+
*
|
|
74
120
|
* @param array Array to search in
|
|
75
121
|
* @param key Key to match items by
|
|
76
122
|
* @param value Value to match against
|
|
77
123
|
* @returns Index of the last matching item, or `-1` if no match is found
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* lastIndexOf(
|
|
128
|
+
* [{id: 1}, {id: 2}, {id: 3}, {id: 2}],
|
|
129
|
+
* 'id',
|
|
130
|
+
* 2,
|
|
131
|
+
* ); // => 3
|
|
132
|
+
* ```
|
|
78
133
|
*/
|
|
79
134
|
export function lastIndexOf<Item extends PlainObject, ItemKey extends keyof Item>(
|
|
80
135
|
array: Item[],
|
|
@@ -86,9 +141,18 @@ export function lastIndexOf<Item extends PlainObject, ItemKey extends keyof Item
|
|
|
86
141
|
* Get the index of the last item matching the filter
|
|
87
142
|
*
|
|
88
143
|
* Available as `lastIndexOf` and `indexOf.last`
|
|
144
|
+
*
|
|
89
145
|
* @param array Array to search in
|
|
90
146
|
* @param filter Filter callback to match items
|
|
91
147
|
* @returns Index of the last matching item, or `-1` if no match is found
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* lastIndexOf(
|
|
152
|
+
* [{id: 1}, {id: 2}, {id: 3}, {id: 2}],
|
|
153
|
+
* item => item.id === 2,
|
|
154
|
+
* ); // => 3
|
|
155
|
+
* ```
|
|
92
156
|
*/
|
|
93
157
|
export function lastIndexOf<Item>(
|
|
94
158
|
array: Item[],
|
|
@@ -99,9 +163,15 @@ export function lastIndexOf<Item>(
|
|
|
99
163
|
* Get the index of the last item matching the given item
|
|
100
164
|
*
|
|
101
165
|
* Available as `lastIndexOf` and `indexOf.last`
|
|
166
|
+
*
|
|
102
167
|
* @param array Array to search in
|
|
103
168
|
* @param item Item to match against
|
|
104
169
|
* @returns Index of the last matching item, or `-1` if no match is found
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* lastIndexOf([1, 2, 3, 2, 1], 2); // => 3
|
|
174
|
+
* ```
|
|
105
175
|
*/
|
|
106
176
|
export function lastIndexOf<Item>(array: Item[], item: Item): number;
|
|
107
177
|
|
|
@@ -66,6 +66,17 @@ export function getAggregateCallback(key: unknown): Function | undefined {
|
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
68
|
* Get the maximum value from a list of items
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* max(
|
|
73
|
+
* [{id: 1, value: 10}, {id: 2, value: 20}],
|
|
74
|
+
* item => item.value,
|
|
75
|
+
* ); // 20
|
|
76
|
+
*
|
|
77
|
+
* max([], item => item.value); // Number.NaN
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
69
80
|
* @param items List of items
|
|
70
81
|
* @param callback Callback to get an item's value
|
|
71
82
|
* @returns Maximum value, or `NaN` if no maximum can be found
|
|
@@ -77,6 +88,17 @@ export function max<Item>(
|
|
|
77
88
|
|
|
78
89
|
/**
|
|
79
90
|
* Get the maximum value from a list of items
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* max(
|
|
95
|
+
* [{id: 1, value: 10}, {id: 2, value: 20}],
|
|
96
|
+
* 'value',
|
|
97
|
+
* ); // 20
|
|
98
|
+
*
|
|
99
|
+
* max([], 'value'); // Number.NaN
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
80
102
|
* @param items List of items
|
|
81
103
|
* @param key Key to use for value
|
|
82
104
|
* @returns Maximum value, or `NaN` if no maximum can be found
|
|
@@ -88,6 +110,13 @@ export function max<Item extends PlainObject, ItemKey extends keyof NumericalVal
|
|
|
88
110
|
|
|
89
111
|
/**
|
|
90
112
|
* Get the maximum value from a list of numbers
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* max([10, 20]); // 20
|
|
117
|
+
* max([]); // Number.NaN
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
91
120
|
* @param values List of numbers
|
|
92
121
|
* @returns Maximum value, or `NaN` if no maximum can be found
|
|
93
122
|
*/
|
package/src/internal/string.ts
CHANGED
|
@@ -19,11 +19,9 @@ export function getString(value: unknown): string {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
if (typeof value !== 'object') {
|
|
22
|
-
// oxlint-disable-next-line typescript/no-base-to-string: the whole point of this function is to get a string representation of any value, so calling `String` on it is fine
|
|
23
22
|
return String(value);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
// oxlint-disable-next-line typescript/no-base-to-string: ditto
|
|
27
25
|
const asString = String(value.valueOf?.() ?? value);
|
|
28
26
|
|
|
29
27
|
return asString.startsWith('[object ') ? JSON.stringify(value) : asString;
|
|
@@ -6,8 +6,19 @@ import {getNestedValue} from './misc';
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Get the value from an object using a known path
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const data = {foo: {bar: {baz: 42}}};
|
|
13
|
+
*
|
|
14
|
+
* getValue(data, 'foo'); // {bar: {baz: 42}}
|
|
15
|
+
* getValue(data, 'foo.bar'); // {baz: 42}
|
|
16
|
+
* getValue(data, 'foo.bar.baz'); // 42
|
|
17
|
+
* getValue(data, 'foo.nope'); // undefined
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
9
20
|
* @param data Object to get value from
|
|
10
|
-
* @param path Path for value
|
|
21
|
+
* @param path Path for value
|
|
11
22
|
* @returns Found value, or `undefined`
|
|
12
23
|
*/
|
|
13
24
|
export function getValue<Data extends PlainObject, Path extends NestedKeys<Data>>(
|
|
@@ -17,9 +28,20 @@ export function getValue<Data extends PlainObject, Path extends NestedKeys<Data>
|
|
|
17
28
|
|
|
18
29
|
/**
|
|
19
30
|
* Get the value from an object using an unknown path
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const data = {foo: {bar: {baz: 42}}};
|
|
35
|
+
*
|
|
36
|
+
* getValue(data, 'foo'); // {bar: {baz: 42}}
|
|
37
|
+
* getValue(data, 'foo.bar'); // {baz: 42}
|
|
38
|
+
* getValue(data, 'Foo.Bar.Baz', true); // 42
|
|
39
|
+
* getValue(data, 'foo.nope'); // undefined
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
20
42
|
* @param data Object to get value from
|
|
21
|
-
* @param path Path for value
|
|
22
|
-
* @param ignoreCase If `true`,
|
|
43
|
+
* @param path Path for value
|
|
44
|
+
* @param ignoreCase If `true`, path matching is case-insensitive
|
|
23
45
|
* @returns Found value, or `undefined`
|
|
24
46
|
*/
|
|
25
47
|
export function getValue<Data extends PlainObject>(
|
|
@@ -8,7 +8,7 @@ import {getNestedValue} from './misc';
|
|
|
8
8
|
* Check if a nested property is defined in an object
|
|
9
9
|
* @param data Object to check in
|
|
10
10
|
* @param path Path for property
|
|
11
|
-
* @
|
|
11
|
+
* @returns `true` if the property exists, `false` otherwise
|
|
12
12
|
*/
|
|
13
13
|
export function hasValue<Data extends PlainObject, Path extends NestedKeys<Data>>(
|
|
14
14
|
data: Data,
|
|
@@ -20,7 +20,7 @@ export function hasValue<Data extends PlainObject, Path extends NestedKeys<Data>
|
|
|
20
20
|
* @param data Object to check in
|
|
21
21
|
* @param path Path for property
|
|
22
22
|
* @param ignoreCase If `true`, the path matching is case-insensitive
|
|
23
|
-
* @
|
|
23
|
+
* @returns `true` if the property exists, `false` otherwise
|
|
24
24
|
*/
|
|
25
25
|
export function hasValue<Data extends PlainObject>(
|
|
26
26
|
data: Data,
|
|
@@ -41,7 +41,7 @@ hasValue.get = hasValueResult;
|
|
|
41
41
|
* @param data Object to check in
|
|
42
42
|
* @param path Path for property
|
|
43
43
|
* @param ignoreCase If `true`, the path matching is case-insensitive
|
|
44
|
-
* @
|
|
44
|
+
* @returns Result object
|
|
45
45
|
*/
|
|
46
46
|
export function hasValueResult<Data extends PlainObject, Path extends NestedKeys<Data>>(
|
|
47
47
|
data: Data,
|
|
@@ -56,7 +56,7 @@ export function hasValueResult<Data extends PlainObject, Path extends NestedKeys
|
|
|
56
56
|
* @param data Object to check in
|
|
57
57
|
* @param path Path for property
|
|
58
58
|
* @param ignoreCase If `true`, the path matching is case-insensitive
|
|
59
|
-
* @
|
|
59
|
+
* @returns Result object
|
|
60
60
|
*/
|
|
61
61
|
export function hasValueResult<Data extends PlainObject>(
|
|
62
62
|
data: Data,
|
package/src/models.ts
CHANGED
|
@@ -260,4 +260,22 @@ export type TypedArray =
|
|
|
260
260
|
| BigInt64Array
|
|
261
261
|
| BigUint64Array;
|
|
262
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Converts a union type to an intersection type
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* type A = {a: string};
|
|
269
|
+
* type B = {b: number};
|
|
270
|
+
* type C = UnionToIntersection<A | B>; // {a: string} & {b: number}
|
|
271
|
+
* ```
|
|
272
|
+
*
|
|
273
|
+
* Thanks, type-fest!
|
|
274
|
+
*/
|
|
275
|
+
export type UnionToIntersection<Union> = (
|
|
276
|
+
Union extends unknown ? (distributedUnion: Union) => void : never
|
|
277
|
+
) extends (mergedIntersection: infer Intersection) => void
|
|
278
|
+
? Intersection & Union
|
|
279
|
+
: never;
|
|
280
|
+
|
|
263
281
|
// #endregion
|
package/src/value/collection.ts
CHANGED
|
@@ -13,7 +13,7 @@ export function inMap<Value>(map: Map<unknown, Value>, value: Value): boolean;
|
|
|
13
13
|
* @param map Map to check in
|
|
14
14
|
* @param value Value to check for
|
|
15
15
|
* @param key To return the key for the value
|
|
16
|
-
* @
|
|
16
|
+
* @returns The key for the value if it exists, otherwise `undefined`
|
|
17
17
|
*/
|
|
18
18
|
export function inMap<Key, Value>(map: Map<Key, Value>, value: Value, key: true): Key;
|
|
19
19
|
|
package/src/value/merge.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {isArrayOrPlainObject} from '../internal/is';
|
|
2
|
-
import {
|
|
3
|
-
import type {ArrayOrPlainObject, NestedPartial, PlainObject} from '../models';
|
|
2
|
+
import type {ArrayOrPlainObject, NestedPartial, PlainObject, UnionToIntersection} from '../models';
|
|
4
3
|
|
|
5
4
|
// #region Types
|
|
6
5
|
|
|
@@ -9,16 +8,19 @@ import type {ArrayOrPlainObject, NestedPartial, PlainObject} from '../models';
|
|
|
9
8
|
*/
|
|
10
9
|
export type AssignOptions = Omit<MergeOptions, 'assignValues'>;
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
export type Assigner = {
|
|
12
|
+
/**
|
|
13
|
+
* Assign values from one or more objects to the first one
|
|
14
|
+
*
|
|
15
|
+
* @param to Value to assign to
|
|
16
|
+
* @param from Values to assign
|
|
17
|
+
* @returns Assigned value
|
|
18
|
+
*/
|
|
19
|
+
<To extends PlainObject, From extends PlainObject[]>(
|
|
20
|
+
to: To,
|
|
21
|
+
from: [...From],
|
|
22
|
+
): To & UnionToIntersection<From[number]>;
|
|
23
|
+
};
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* Options for merging values
|
|
@@ -54,14 +56,17 @@ export type MergeOptions = {
|
|
|
54
56
|
skipNullableInArrays?: boolean;
|
|
55
57
|
};
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
export type Merger = {
|
|
60
|
+
/**
|
|
61
|
+
* Merge multiple arrays or objects into a single one
|
|
62
|
+
*
|
|
63
|
+
* @param values Values to merge
|
|
64
|
+
* @returns Merged value
|
|
65
|
+
*/
|
|
66
|
+
<Values extends ArrayOrPlainObject[]>(
|
|
67
|
+
values: NestedPartial<Values[number]>[],
|
|
68
|
+
): UnionToIntersection<Values[number]>;
|
|
69
|
+
};
|
|
65
70
|
|
|
66
71
|
type Options = {
|
|
67
72
|
assignValues: boolean;
|
|
@@ -77,22 +82,23 @@ type ReplaceableObjectsCallback = (name: string) => boolean;
|
|
|
77
82
|
// #region Functions
|
|
78
83
|
|
|
79
84
|
/**
|
|
80
|
-
* Assign values from
|
|
85
|
+
* Assign values from one or more objects to the first one
|
|
86
|
+
*
|
|
81
87
|
* @param to Value to assign to
|
|
82
88
|
* @param from Values to assign
|
|
83
89
|
* @param options Assigning options
|
|
84
90
|
* @returns Assigned value
|
|
85
91
|
*/
|
|
86
|
-
export function assign<
|
|
87
|
-
to:
|
|
88
|
-
from:
|
|
92
|
+
export function assign<To extends PlainObject, From extends PlainObject[]>(
|
|
93
|
+
to: To,
|
|
94
|
+
from: [...From],
|
|
89
95
|
options?: AssignOptions,
|
|
90
|
-
):
|
|
96
|
+
): To & UnionToIntersection<From[number]> {
|
|
91
97
|
const actual = getMergeOptions(options);
|
|
92
98
|
|
|
93
99
|
actual.assignValues = true;
|
|
94
100
|
|
|
95
|
-
return mergeValues([to, ...from], actual
|
|
101
|
+
return mergeValues([to, ...from], actual) as To & UnionToIntersection<From[number]>;
|
|
96
102
|
}
|
|
97
103
|
|
|
98
104
|
assign.initialize = initializeAssigner;
|
|
@@ -129,69 +135,50 @@ function getReplaceableObjects(value: unknown): ReplaceableObjectsCallback | und
|
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
|
|
132
|
-
function handleMerge(values: ArrayOrPlainObject[], options: Options): ArrayOrPlainObject {
|
|
133
|
-
return !Array.isArray(values) || values.length === 0 ? {} : mergeValues(values, options, true);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
138
|
/**
|
|
137
139
|
* Create an assigner with predefined options
|
|
138
140
|
*
|
|
139
141
|
* Available as `initializeAssigner` and `assign.initialize`
|
|
142
|
+
*
|
|
140
143
|
* @param options Assigning options
|
|
141
144
|
* @returns Assigner function
|
|
142
145
|
*/
|
|
143
|
-
export function initializeAssigner
|
|
144
|
-
options?: AssignOptions,
|
|
145
|
-
): Assigner<Model> {
|
|
146
|
+
export function initializeAssigner(options?: AssignOptions): Assigner {
|
|
146
147
|
const actual = getMergeOptions(options);
|
|
147
148
|
|
|
148
149
|
actual.assignValues = true;
|
|
149
150
|
|
|
150
|
-
return ((to:
|
|
151
|
-
mergeValues([to, ...from], actual
|
|
151
|
+
return ((to: PlainObject, from: PlainObject[]): PlainObject =>
|
|
152
|
+
mergeValues([to, ...from], actual) as PlainObject) as Assigner;
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
/**
|
|
155
156
|
* Create a merger with predefined options
|
|
156
157
|
*
|
|
157
158
|
* Available as `initializeMerger` and `merge.initialize`
|
|
159
|
+
*
|
|
158
160
|
* @param options Merging options
|
|
159
161
|
* @returns Merger function
|
|
160
162
|
*/
|
|
161
163
|
export function initializeMerger(options?: MergeOptions): Merger {
|
|
162
164
|
const actual = getMergeOptions(options);
|
|
163
165
|
|
|
164
|
-
return
|
|
165
|
-
|
|
166
|
+
return ((values: NestedPartial<ArrayOrPlainObject>[]): ArrayOrPlainObject =>
|
|
167
|
+
mergeValues(values, actual)) as Merger;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
/**
|
|
169
171
|
* Merge multiple arrays or objects into a single one
|
|
172
|
+
*
|
|
170
173
|
* @param values Values to merge
|
|
171
174
|
* @param options Merging options
|
|
172
175
|
* @returns Merged value
|
|
173
176
|
*/
|
|
174
|
-
export function merge<
|
|
175
|
-
values:
|
|
176
|
-
options?: MergeOptions,
|
|
177
|
-
): Model;
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Merge multiple arrays or objects into a single one
|
|
181
|
-
* @param values Values to merge
|
|
182
|
-
* @param options Merging options
|
|
183
|
-
* @returns Merged value
|
|
184
|
-
*/
|
|
185
|
-
export function merge(
|
|
186
|
-
values: NestedPartial<ArrayOrPlainObject>[],
|
|
177
|
+
export function merge<Values extends ArrayOrPlainObject[]>(
|
|
178
|
+
values: [...Values],
|
|
187
179
|
options?: MergeOptions,
|
|
188
|
-
):
|
|
189
|
-
|
|
190
|
-
export function merge(
|
|
191
|
-
values: NestedPartial<ArrayOrPlainObject>[],
|
|
192
|
-
options?: MergeOptions,
|
|
193
|
-
): ArrayOrPlainObject {
|
|
194
|
-
return handleMerge(values, getMergeOptions(options));
|
|
180
|
+
): UnionToIntersection<Values[number]> {
|
|
181
|
+
return mergeValues(values, getMergeOptions(options)) as UnionToIntersection<Values[number]>;
|
|
195
182
|
}
|
|
196
183
|
|
|
197
184
|
merge.initialize = initializeMerger;
|
|
@@ -199,20 +186,23 @@ merge.initialize = initializeMerger;
|
|
|
199
186
|
function mergeObjects(
|
|
200
187
|
values: ArrayOrPlainObject[],
|
|
201
188
|
options: Options,
|
|
189
|
+
destination?: ArrayOrPlainObject,
|
|
202
190
|
prefix?: string,
|
|
203
191
|
): ArrayOrPlainObject {
|
|
204
192
|
const {length} = values;
|
|
205
|
-
const isArray = values.every(Array.isArray);
|
|
206
|
-
const merged = (options.assignValues ? values[0] : isArray ? [] : {}) as PlainObject;
|
|
207
193
|
|
|
208
|
-
|
|
194
|
+
const isArray = Array.isArray(destination ?? values[0]);
|
|
195
|
+
const merged = (destination ?? (isArray ? [] : {})) as PlainObject;
|
|
196
|
+
|
|
197
|
+
const offset = destination == null ? 0 : 1;
|
|
198
|
+
|
|
199
|
+
for (let outerIndex = offset; outerIndex < length; outerIndex += 1) {
|
|
209
200
|
const item = values[outerIndex] as PlainObject;
|
|
210
201
|
const keys = Object.keys(item);
|
|
211
202
|
const size = keys.length;
|
|
212
203
|
|
|
213
204
|
for (let innerIndex = 0; innerIndex < size; innerIndex += 1) {
|
|
214
205
|
const key = keys[innerIndex];
|
|
215
|
-
const full = join([prefix, key], '.');
|
|
216
206
|
|
|
217
207
|
const next = item[key];
|
|
218
208
|
const previous = merged[key];
|
|
@@ -221,12 +211,20 @@ function mergeObjects(
|
|
|
221
211
|
continue;
|
|
222
212
|
}
|
|
223
213
|
|
|
214
|
+
const full =
|
|
215
|
+
options.replaceableObjects == null ? undefined : prefix == null ? key : `${prefix}.${key}`;
|
|
216
|
+
|
|
224
217
|
if (
|
|
225
218
|
isArrayOrPlainObject(next) &&
|
|
226
219
|
isArrayOrPlainObject(previous) &&
|
|
227
|
-
!(options.replaceableObjects?.(full) ?? false)
|
|
220
|
+
!(options.replaceableObjects?.(full!) ?? false)
|
|
228
221
|
) {
|
|
229
|
-
merged[key] =
|
|
222
|
+
merged[key] = mergeObjects(
|
|
223
|
+
[previous, next],
|
|
224
|
+
options,
|
|
225
|
+
(destination == null ? undefined : merged[key]) as ArrayOrPlainObject,
|
|
226
|
+
full,
|
|
227
|
+
);
|
|
230
228
|
} else {
|
|
231
229
|
merged[key] = next;
|
|
232
230
|
}
|
|
@@ -239,12 +237,36 @@ function mergeObjects(
|
|
|
239
237
|
function mergeValues(
|
|
240
238
|
values: ArrayOrPlainObject[],
|
|
241
239
|
options: Options,
|
|
242
|
-
validate: boolean,
|
|
243
240
|
prefix?: string,
|
|
244
241
|
): ArrayOrPlainObject {
|
|
245
|
-
|
|
242
|
+
if (!Array.isArray(values)) {
|
|
243
|
+
return {};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const actual = values.filter(isArrayOrPlainObject);
|
|
247
|
+
|
|
248
|
+
if (actual.length === 0) {
|
|
249
|
+
return {};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (
|
|
253
|
+
options.assignValues &&
|
|
254
|
+
actual.length === 2 &&
|
|
255
|
+
!Array.isArray(actual[0]) &&
|
|
256
|
+
Object.keys(actual[0]).length === 0
|
|
257
|
+
) {
|
|
258
|
+
return Object.assign(actual[0], actual[1]);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (actual.length > 1) {
|
|
262
|
+
return mergeObjects(actual, options, options.assignValues ? actual[0] : undefined, prefix);
|
|
263
|
+
}
|
|
246
264
|
|
|
247
|
-
return
|
|
265
|
+
return options.assignValues
|
|
266
|
+
? actual[0]
|
|
267
|
+
: Array.isArray(actual[0])
|
|
268
|
+
? actual[0].slice()
|
|
269
|
+
: {...actual[0]};
|
|
248
270
|
}
|
|
249
271
|
|
|
250
272
|
// #endregion
|
package/src/value/transform.ts
CHANGED
|
@@ -75,7 +75,7 @@ export function initializeTransformer<Value extends PlainObject>(
|
|
|
75
75
|
*
|
|
76
76
|
* Available as `initializeTransformer` and `transform.initialize`
|
|
77
77
|
* @param transformers Keyed transformer functions
|
|
78
|
-
* @
|
|
78
|
+
* @returns Transformer
|
|
79
79
|
*/
|
|
80
80
|
export function initializeTransformer<Value extends PlainObject>(
|
|
81
81
|
transformers: TransformCallbacks<Value>,
|
package/src/value/unsmush.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {isArrayOrPlainObject} from '../internal/is';
|
|
2
2
|
import {setValue} from '../internal/value/set';
|
|
3
|
-
import type {PlainObject, Simplify} from '../models';
|
|
3
|
+
import type {PlainObject, Simplify, UnionToIntersection} from '../models';
|
|
4
4
|
|
|
5
5
|
// #region Types
|
|
6
6
|
|
|
@@ -16,15 +16,6 @@ type OrderedKey = {
|
|
|
16
16
|
value: string;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* Thanks, type-fest!
|
|
21
|
-
*/
|
|
22
|
-
type UnionToIntersection<Union> = (
|
|
23
|
-
Union extends unknown ? (distributedUnion: Union) => void : never
|
|
24
|
-
) extends (mergedIntersection: infer Intersection) => void
|
|
25
|
-
? Intersection & Union
|
|
26
|
-
: never;
|
|
27
|
-
|
|
28
19
|
/**
|
|
29
20
|
* An unsmushed object, with all dot notation keys turned into nested keys
|
|
30
21
|
*/
|