/
utils.ts
96 lines (85 loc) · 2.93 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { SortOptions } from '../../types'
/**
* Retrive nested value from object by path
*/
export const get = (obj: any, path: string): any => path.split('.').reduce((acc, part) => acc && acc[part], obj)
const _pick = (obj: any, condition: (item: any) => boolean) =>
Object.keys(obj)
.filter(condition)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
/**
* Returns a new object with the specified keys
**/
export const pick = (keys?: string[]) => (obj: any) => keys && keys.length ? _pick(obj, key => keys.includes(key)) : obj
/**
* Returns a new object with all the keys of the original object execept the ones specified.
**/
export const omit = (keys?: string[]) => (obj: any) =>
keys && keys.length ? _pick(obj, key => !keys.includes(key)) : obj
/**
* Apply a function to each element of an array
*/
export const apply = (fn: (d: any) => any) => (data: any) => Array.isArray(data) ? data.map(item => fn(item)) : fn(data)
export const detectProperties = (keys: string[]) => {
const prefixes = []
const properties = []
for (const key of keys) {
if (['$', '_'].includes(key)) {
prefixes.push(key)
} else {
properties.push(key)
}
}
return { prefixes, properties }
}
export const withoutKeys = (keys: string[] = []) => (obj: any) => {
if (keys.length === 0) {
return obj
}
const { prefixes, properties } = detectProperties(keys)
return _pick(obj, key => !properties.includes(key) && !prefixes.includes(key[0]))
}
export const withKeys = (keys: string[] = []) => (obj: any) => {
if (keys.length === 0) {
return obj
}
const { prefixes, properties } = detectProperties(keys)
return _pick(obj, key => properties.includes(key) || prefixes.includes(key[0]))
}
/**
* Sort list of items by givin options
*/
export const sortList = (data: any[], params: SortOptions) => {
const comperable = new Intl.Collator(params.$locale as string, {
numeric: params.$numeric as boolean,
caseFirst: params.$caseFirst as string,
sensitivity: params.$sensitivity as string
})
const keys = Object.keys(params).filter(key => !key.startsWith('$'))
for (const key of keys) {
data = data.sort((a, b) => {
const values = [get(a, key), get(b, key)]
// `null` values are treated as `"null"` strings and ordered alphabetically
// Turn `null` values into `undefined` so they place at the end of the list
.map(value => value === null ? undefined : value)
if (params[key] === -1) {
values.reverse()
}
return comperable.compare(values[0], values[1])
})
}
return data
}
/**
* Raise TypeError if value is not an array
*/
export const assertArray = (value: any, message = 'Expected an array') => {
if (!Array.isArray(value)) {
throw new TypeError(message)
}
}
/**
* Ensure result is an array
*/
export const ensureArray = <T>(value: T) =>
(Array.isArray(value) ? value : value ? [value] : []) as T extends Array<any> ? T : T[]