@ditojs/utils 2.77.0 → 2.79.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 +2 -2
- package/src/object/asCallback.js +9 -0
- package/src/object/groupBy.js +2 -0
- package/src/object/groupBy.test.js +36 -0
- package/src/object/mapValues.js +3 -0
- package/src/object/mapValues.test.js +22 -0
- package/src/object/pickBy.js +3 -0
- package/src/object/pickBy.test.js +39 -0
- package/types/index.d.ts +107 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.79.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",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"typescript": "^5.9.3"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "f87ce5ce121a30830776774cd447014afef5b8ec"
|
|
43
43
|
}
|
package/src/object/groupBy.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { isArray } from '../base/index.js'
|
|
2
|
+
import { asCallback } from './asCallback.js'
|
|
2
3
|
|
|
3
4
|
export function groupBy(collection, callback) {
|
|
4
5
|
const array = isArray(collection)
|
|
5
6
|
? collection
|
|
6
7
|
: Object.values(collection)
|
|
8
|
+
callback = asCallback(callback)
|
|
7
9
|
return array.reduce((groups, item) => {
|
|
8
10
|
const key = callback(item)
|
|
9
11
|
const group = groups[key] || (groups[key] = [])
|
|
@@ -31,4 +31,40 @@ describe('groupBy()', () => {
|
|
|
31
31
|
const actual = groupBy({ a: 6.1, b: 4.2, c: 6.3 }, Math.floor)
|
|
32
32
|
expect(actual).toStrictEqual({ 4: [4.2], 6: [6.1, 6.3] })
|
|
33
33
|
})
|
|
34
|
+
|
|
35
|
+
it('should support string property accessor', () => {
|
|
36
|
+
const array = [
|
|
37
|
+
{ category: 'fruit', name: 'apple' },
|
|
38
|
+
{ category: 'vegetable', name: 'carrot' },
|
|
39
|
+
{ category: 'fruit', name: 'banana' }
|
|
40
|
+
]
|
|
41
|
+
const actual = groupBy(array, 'category')
|
|
42
|
+
expect(actual).toStrictEqual({
|
|
43
|
+
fruit: [
|
|
44
|
+
{ category: 'fruit', name: 'apple' },
|
|
45
|
+
{ category: 'fruit', name: 'banana' }
|
|
46
|
+
],
|
|
47
|
+
vegetable: [
|
|
48
|
+
{ category: 'vegetable', name: 'carrot' }
|
|
49
|
+
]
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('should group by string property with numbers', () => {
|
|
54
|
+
const array = [
|
|
55
|
+
{ id: 1, value: 'a' },
|
|
56
|
+
{ id: 2, value: 'b' },
|
|
57
|
+
{ id: 1, value: 'c' }
|
|
58
|
+
]
|
|
59
|
+
const actual = groupBy(array, 'id')
|
|
60
|
+
expect(actual).toStrictEqual({
|
|
61
|
+
1: [
|
|
62
|
+
{ id: 1, value: 'a' },
|
|
63
|
+
{ id: 1, value: 'c' }
|
|
64
|
+
],
|
|
65
|
+
2: [
|
|
66
|
+
{ id: 2, value: 'b' }
|
|
67
|
+
]
|
|
68
|
+
})
|
|
69
|
+
})
|
|
34
70
|
})
|
package/src/object/mapValues.js
CHANGED
|
@@ -13,4 +13,26 @@ describe('mapValues()', () => {
|
|
|
13
13
|
const actual = mapValues(array, String)
|
|
14
14
|
expect(actual).toStrictEqual({ 0: '1', 1: '2' })
|
|
15
15
|
})
|
|
16
|
+
|
|
17
|
+
it('should support string property accessor', () => {
|
|
18
|
+
const users = {
|
|
19
|
+
user1: { id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
20
|
+
user2: { id: 2, name: 'Bob', email: 'bob@example.com' }
|
|
21
|
+
}
|
|
22
|
+
const actual = mapValues(users, 'email')
|
|
23
|
+
expect(actual).toStrictEqual({
|
|
24
|
+
user1: 'alice@example.com',
|
|
25
|
+
user2: 'bob@example.com'
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should extract nested properties with string accessor', () => {
|
|
30
|
+
const data = {
|
|
31
|
+
a: { value: 10 },
|
|
32
|
+
b: { value: 20 },
|
|
33
|
+
c: { value: 30 }
|
|
34
|
+
}
|
|
35
|
+
const actual = mapValues(data, 'value')
|
|
36
|
+
expect(actual).toStrictEqual({ a: 10, b: 20, c: 30 })
|
|
37
|
+
})
|
|
16
38
|
})
|
package/src/object/pickBy.js
CHANGED
|
@@ -6,4 +6,43 @@ describe('pickBy()', () => {
|
|
|
6
6
|
const actual = pickBy(object, n => n === 1 || n === 3)
|
|
7
7
|
expect(actual).toStrictEqual({ a: 1, c: 3 })
|
|
8
8
|
})
|
|
9
|
+
|
|
10
|
+
it('should support string property accessor for truthy values', () => {
|
|
11
|
+
const users = {
|
|
12
|
+
user1: { name: 'Alice', active: true },
|
|
13
|
+
user2: { name: 'Bob', active: false },
|
|
14
|
+
user3: { name: 'Charlie', active: true }
|
|
15
|
+
}
|
|
16
|
+
const actual = pickBy(users, 'active')
|
|
17
|
+
expect(actual).toStrictEqual({
|
|
18
|
+
user1: { name: 'Alice', active: true },
|
|
19
|
+
user3: { name: 'Charlie', active: true }
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should filter by numeric property with string accessor', () => {
|
|
24
|
+
const items = {
|
|
25
|
+
a: { score: 0 },
|
|
26
|
+
b: { score: 5 },
|
|
27
|
+
c: { score: 10 }
|
|
28
|
+
}
|
|
29
|
+
const actual = pickBy(items, 'score')
|
|
30
|
+
expect(actual).toStrictEqual({
|
|
31
|
+
b: { score: 5 },
|
|
32
|
+
c: { score: 10 }
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should filter by string property with string accessor', () => {
|
|
37
|
+
const data = {
|
|
38
|
+
a: { label: '' },
|
|
39
|
+
b: { label: 'test' },
|
|
40
|
+
c: { label: 'value' }
|
|
41
|
+
}
|
|
42
|
+
const actual = pickBy(data, 'label')
|
|
43
|
+
expect(actual).toStrictEqual({
|
|
44
|
+
b: { label: 'test' },
|
|
45
|
+
c: { label: 'value' }
|
|
46
|
+
})
|
|
47
|
+
})
|
|
9
48
|
})
|
package/types/index.d.ts
CHANGED
|
@@ -142,9 +142,16 @@ export function clone<T>(value: T, options?: {
|
|
|
142
142
|
*/
|
|
143
143
|
export function equals(arg1: any, arg2: any): boolean
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Groups items in a collection by a key returned from the callback function,
|
|
147
|
+
* or by a property name when a string is provided.
|
|
148
|
+
*/
|
|
149
|
+
export function groupBy<T, K extends keyof T>(
|
|
150
|
+
collection: T[] | Record<string, T>,
|
|
151
|
+
callback: K
|
|
152
|
+
): Record<string, T[]>
|
|
146
153
|
export function groupBy<T, K extends string | number | symbol>(
|
|
147
|
-
|
|
154
|
+
collection: T[] | Record<string, T>,
|
|
148
155
|
callback: (item: T) => K
|
|
149
156
|
): Record<K, T[]>
|
|
150
157
|
|
|
@@ -217,10 +224,16 @@ export function pick<ArgA, ArgB, ArgC, ArgD, ArgE>(
|
|
|
217
224
|
export function pick(...args: any[]): any
|
|
218
225
|
/**
|
|
219
226
|
* Creates an object composed of the object properties predicate returns
|
|
220
|
-
* truthy for.
|
|
227
|
+
* truthy for. When a string is provided, filters by the truthiness of that
|
|
228
|
+
* property on each value.
|
|
221
229
|
* @param object The source object.
|
|
222
|
-
* @param callback Callback invoked with three arguments: (value, key, item)
|
|
230
|
+
* @param callback Callback invoked with three arguments: (value, key, item),
|
|
231
|
+
* or a property name string to check for truthiness.
|
|
223
232
|
*/
|
|
233
|
+
export function pickBy<T extends Dictionary<any>, K extends keyof T[keyof T]>(
|
|
234
|
+
object: T,
|
|
235
|
+
callback: K
|
|
236
|
+
): Partial<T>
|
|
224
237
|
export function pickBy<T extends Dictionary<any>>(
|
|
225
238
|
object: T,
|
|
226
239
|
callback?: (value: T[keyof T], key: keyof T, object: T) => any
|
|
@@ -231,6 +244,17 @@ export function mapKeys<T extends Dictionary<any>, K extends keyof any>(
|
|
|
231
244
|
callback?: (key: keyof T, value: T[keyof T], object: T) => K
|
|
232
245
|
): Record<K, T[keyof T]>
|
|
233
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Maps the values of an object using a callback function, or extracts a
|
|
249
|
+
* property when a string is provided.
|
|
250
|
+
*/
|
|
251
|
+
export function mapValues<
|
|
252
|
+
T extends Dictionary<any>,
|
|
253
|
+
K extends keyof T[keyof T]
|
|
254
|
+
>(
|
|
255
|
+
object: T,
|
|
256
|
+
callback: K
|
|
257
|
+
): Record<keyof T, T[keyof T][K]>
|
|
234
258
|
export function mapValues<T extends Dictionary<any>, K>(
|
|
235
259
|
object: T,
|
|
236
260
|
callback?: (value: T[keyof T], key: keyof T, object: T) => K
|
|
@@ -290,8 +314,12 @@ export function underscore(str: string): string
|
|
|
290
314
|
*/
|
|
291
315
|
export function deindent(
|
|
292
316
|
strings: OrArrayOf<string>,
|
|
293
|
-
...values: Array<
|
|
317
|
+
...values: Array<any>
|
|
294
318
|
): string
|
|
319
|
+
/**
|
|
320
|
+
* Escapes special characters in a string for use in a regular expression.
|
|
321
|
+
*/
|
|
322
|
+
export function escapeRegexp(string: string): string
|
|
295
323
|
/**
|
|
296
324
|
* Returns the longest prefix string that is common to the supplied strings.
|
|
297
325
|
*/
|
|
@@ -314,6 +342,11 @@ export function isAbsoluteUrl(str: string): boolean
|
|
|
314
342
|
* Determines whether the supplied string is a valid creditcard number.
|
|
315
343
|
*/
|
|
316
344
|
export function isCreditCard(str: string): boolean
|
|
345
|
+
/**
|
|
346
|
+
* Determines whether the supplied string is a valid domain name.
|
|
347
|
+
* Supports internationalized domain names with punycode.
|
|
348
|
+
*/
|
|
349
|
+
export function isDomain(str: string): boolean
|
|
317
350
|
/**
|
|
318
351
|
* Determines whether the supplied string is a valid email address.
|
|
319
352
|
*/
|
|
@@ -419,8 +452,37 @@ export function format(
|
|
|
419
452
|
number?: boolean | NumberFormat
|
|
420
453
|
}
|
|
421
454
|
): string
|
|
455
|
+
/**
|
|
456
|
+
* Formats a date value as a string. If the value is not a Date,
|
|
457
|
+
* attempts to convert it to a Date first.
|
|
458
|
+
*/
|
|
459
|
+
export function formatDate(
|
|
460
|
+
value: any,
|
|
461
|
+
options?: {
|
|
462
|
+
/**
|
|
463
|
+
* @default 'en-US'
|
|
464
|
+
*/
|
|
465
|
+
locale?: string
|
|
466
|
+
/**
|
|
467
|
+
* @default true
|
|
468
|
+
*/
|
|
469
|
+
date?: boolean | DateFormat
|
|
470
|
+
/**
|
|
471
|
+
* @default true
|
|
472
|
+
*/
|
|
473
|
+
time?: boolean | TimeFormat
|
|
474
|
+
}
|
|
475
|
+
): string
|
|
422
476
|
/* -------------------------------- function -------------------------------- */
|
|
423
477
|
|
|
478
|
+
/**
|
|
479
|
+
* Logs a deprecation warning message to the console. Each unique message
|
|
480
|
+
* is only logged once.
|
|
481
|
+
*
|
|
482
|
+
* @param message The deprecation message to log.
|
|
483
|
+
*/
|
|
484
|
+
export function deprecate(message: string): void
|
|
485
|
+
|
|
424
486
|
/**
|
|
425
487
|
* Creates a debounced function that delays invoking func until after wait
|
|
426
488
|
* milliseconds have elapsed since the last time the debounced function was
|
|
@@ -671,6 +733,21 @@ export function toPromiseCallback<T, R>(
|
|
|
671
733
|
|
|
672
734
|
/* -------------------------------- dataPath -------------------------------- */
|
|
673
735
|
|
|
736
|
+
/**
|
|
737
|
+
* Gets entries at a data path, supporting wildcards (* and **).
|
|
738
|
+
* Wildcard * matches direct children, ** matches recursively.
|
|
739
|
+
*
|
|
740
|
+
* @param obj The object to query.
|
|
741
|
+
* @param path The data path (supports wildcards).
|
|
742
|
+
* @param handleError Optional error handler called when path is invalid.
|
|
743
|
+
* @returns Object with normalized paths as keys and values at those paths.
|
|
744
|
+
*/
|
|
745
|
+
export function getEntriesAtDataPath(
|
|
746
|
+
obj: any,
|
|
747
|
+
path: OrArrayOf<string>,
|
|
748
|
+
handleError?: (obj: any, part: string, index: number) => any
|
|
749
|
+
): Record<string, any>
|
|
750
|
+
|
|
674
751
|
export function getValueAtDataPath(
|
|
675
752
|
obj: any,
|
|
676
753
|
path: OrArrayOf<string>,
|
|
@@ -681,12 +758,37 @@ export function normalizeDataPath(path: OrArrayOf<string>): string
|
|
|
681
758
|
|
|
682
759
|
export function parseDataPath(path: OrArrayOf<string>): string
|
|
683
760
|
|
|
761
|
+
/**
|
|
762
|
+
* Sets multiple values at data paths from an entries object.
|
|
763
|
+
*
|
|
764
|
+
* @param obj The object to modify.
|
|
765
|
+
* @param entries Object with data paths as keys and values to set.
|
|
766
|
+
* @returns The modified object.
|
|
767
|
+
*/
|
|
768
|
+
export function setDataPathEntries<O>(
|
|
769
|
+
obj: O,
|
|
770
|
+
entries: Record<string, any>
|
|
771
|
+
): O
|
|
772
|
+
|
|
684
773
|
export function setValueAtDataPath<O>(
|
|
685
774
|
obj: O,
|
|
686
775
|
path: OrArrayOf<string>,
|
|
687
776
|
value: any
|
|
688
777
|
): O
|
|
689
778
|
|
|
779
|
+
/* --------------------------------- class ---------------------------------- */
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Creates a mixin decorator that applies a mixin function to a class.
|
|
783
|
+
* Prevents duplicate application of the same mixin in the inheritance chain.
|
|
784
|
+
*
|
|
785
|
+
* @param mixinFunction Function that takes a class and returns a mixed class.
|
|
786
|
+
* @returns Decorator function that applies the mixin to a target class.
|
|
787
|
+
*/
|
|
788
|
+
export function mixin<T extends new (...args: any[]) => any>(
|
|
789
|
+
mixinFunction: (targetClass: T) => T
|
|
790
|
+
): (targetClass: T) => T
|
|
791
|
+
|
|
690
792
|
/* ---------------------------------- html ---------------------------------- */
|
|
691
793
|
|
|
692
794
|
/**
|