forked from TanStack/query
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.ts
122 lines (105 loc) · 3.08 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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { isRef, unref } from 'vue-demi'
import type { MaybeRefDeep } from './types'
export const VUE_QUERY_CLIENT = 'VUE_QUERY_CLIENT'
export function getClientKey(key?: string) {
const suffix = key ? `:${key}` : ''
return `${VUE_QUERY_CLIENT}${suffix}`
}
export function updateState(
state: Record<string, any>,
update: Record<string, any>,
): void {
Object.keys(state).forEach((key) => {
state[key] = update[key]
})
}
// Helper function for cloning deep objects where
// the level and key is provided to the callback function.
function _cloneDeep<T>(
value: MaybeRefDeep<T>,
customize?: (
val: MaybeRefDeep<T>,
key: string,
level: number,
) => T | undefined,
currentKey: string = '',
currentLevel: number = 0,
): T {
if (customize) {
const result = customize(value, currentKey, currentLevel)
if (result === undefined && isRef(value)) {
return result as T
}
if (result !== undefined) {
return result
}
}
if (Array.isArray(value)) {
return value.map((val, index) =>
_cloneDeep(val, customize, String(index), currentLevel + 1),
) as unknown as T
}
if (typeof value === 'object' && isPlainObject(value)) {
const entries = Object.entries(value).map(([key, val]) => [
key,
_cloneDeep(val, customize, key, currentLevel + 1),
])
return Object.fromEntries(entries)
}
return value as T
}
export function cloneDeep<T>(
value: MaybeRefDeep<T>,
customize?: (
val: MaybeRefDeep<T>,
key: string,
level: number,
) => T | undefined,
): T {
return _cloneDeep(value, customize)
}
export function cloneDeepUnref<T>(
obj: MaybeRefDeep<T>,
unrefGetters = false,
): T {
return cloneDeep(obj, (val, key, level) => {
// Check if we're at the top level and the key is 'queryKey'
//
// If so, take the recursive descent where we resolve
// getters to values as well as refs.
if (level === 1 && key === 'queryKey') {
return cloneDeepUnref(val, true)
}
// Resolve getters to values if specified.
if (unrefGetters && isFunction(val)) {
// Cast due to older TS versions not allowing calling
// on certain intersection types.
return cloneDeepUnref((val as Function)(), unrefGetters)
}
// Unref refs and continue to recurse into the value.
if (isRef(val)) {
return cloneDeepUnref(unref(val), unrefGetters)
}
return undefined
})
}
function isPlainObject(value: unknown): value is Object {
if (Object.prototype.toString.call(value) !== '[object Object]') {
return false
}
const prototype = Object.getPrototypeOf(value)
return prototype === null || prototype === Object.prototype
}
function isFunction(value: unknown): value is Function {
return typeof value === 'function'
}
export function shouldThrowError<T extends (...args: Array<any>) => boolean>(
throwOnError: boolean | T | undefined,
params: Parameters<T>,
): boolean {
// Allow throwOnError function to override throwing behavior on a per-error basis
if (typeof throwOnError === 'function') {
return throwOnError(...params)
}
return !!throwOnError
}