-
-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathcommon.ts
More file actions
152 lines (121 loc) · 3.46 KB
/
Copy pathcommon.ts
File metadata and controls
152 lines (121 loc) · 3.46 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import {
$meta,
Selection,
castNotSkeleton,
castNotSkeletonDeep,
getArrayFields,
getFields,
prepass,
selectFields,
type FetchOptions,
type GQtyError,
} from 'gqty';
import * as React from 'react';
export const IS_BROWSER =
typeof window !== 'undefined' ||
globalThis.navigator?.product === 'ReactNative';
export const useIsomorphicLayoutEffect = IS_BROWSER
? React.useLayoutEffect
: React.useEffect;
export type LegacyFetchPolicy =
| 'cache-and-network'
| 'cache-first'
| 'network-only'
| 'no-cache';
export const legacyFetchPolicyMap: Record<
LegacyFetchPolicy,
FetchOptions['cachePolicy']
> = {
'cache-first': 'force-cache',
'network-only': 'no-cache',
'cache-and-network': 'default',
'no-cache': 'no-store',
};
export const translateFetchPolicy = (
fetchPolicy: LegacyFetchPolicy
): FetchOptions['cachePolicy'] =>
legacyFetchPolicyMap[fetchPolicy] ?? 'default';
export type SelectionsOrProxy<T> = (Selection | T)[];
export const useExtractedSelections = <T extends object>(
input?: SelectionsOrProxy<T>
): Set<Selection> => {
const [selections] = React.useState(() => new Set<Selection>());
React.useEffect(() => {
selections.clear();
if (input === undefined) return;
for (const it of input) {
(it instanceof Selection ? it : $meta(it)?.selection)
?.getLeafNodes()
.forEach((selection) => selections.add(selection));
}
}, [input, input?.length]);
return selections;
};
export type List<T> = Set<T> | Array<T>;
export function toSetIfNeeded<T>(list: List<T>): Set<T> {
return Array.isArray(list) ? new Set(list) : list;
}
export function isSelectionIncluded(
selection: Selection,
selectionList: List<Selection>
) {
const setSelectionList = toSetIfNeeded(selectionList);
if (setSelectionList.has(selection)) return true;
for (const listValue of selectionList) {
if (setSelectionList.has(listValue)) return true;
}
return false;
}
export function isAnySelectionIncluded(
selectionsToCheck: List<Selection>,
selectionsList: List<Selection>
) {
const setSelectionList = toSetIfNeeded(selectionsList);
for (const selection of selectionsToCheck) {
if (isSelectionIncluded(selection, setSelectionList)) return true;
}
return false;
}
export function isAnySelectionIncludedInMatrix(
selectionsToCheck: List<Selection>,
selectionsMatrix: List<List<Selection>>
) {
const selectionsToCheckSet = toSetIfNeeded(selectionsToCheck);
for (const group of selectionsMatrix) {
if (isAnySelectionIncluded(selectionsToCheckSet, group)) return true;
}
return false;
}
export type OnErrorHandler = (error: GQtyError) => void;
export const coreHelpers = {
prepass,
getFields,
getArrayFields,
selectFields,
castNotSkeleton,
castNotSkeletonDeep,
};
export function uniqBy<TNode>(
list: TNode[],
cb?: (node: TNode) => unknown
): TNode[] {
const uniqList = new Map<unknown, TNode>();
for (const value of list) {
const key: unknown = cb ? cb(value) : value;
if (uniqList.has(key)) continue;
uniqList.set(key, value);
}
return Array.from(uniqList.values());
}
const compare = (a: string | number, b: string | number) =>
a < b ? -1 : a > b ? 1 : 0;
export function sortBy<TNode>(
list: TNode[],
cb: (node: TNode) => number | string,
order: 'asc' | 'desc' = 'asc'
): TNode[] {
const orderedList = Array.from(list);
orderedList.sort((a, b) => compare(cb(a), cb(b)));
if (order === 'desc') orderedList.reverse();
return orderedList;
}