@swan-io/lake 7.4.6 → 8.1.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 +4 -4
- package/src/components/LakeTextInput.d.ts +2 -0
- package/src/components/LakeTextInput.js +3 -2
- package/src/components/ToastStack.js +24 -8
- package/src/hooks/usePersistedState.js +1 -1
- package/src/state/toasts.d.ts +2 -0
- package/src/state/toasts.js +7 -0
- package/src/utils/gql.d.ts +8 -0
- package/src/utils/gql.js +2 -0
- package/src/hooks/useUrqlMutation.d.ts +0 -3
- package/src/hooks/useUrqlMutation.js +0 -30
- package/src/hooks/useUrqlQuery.d.ts +0 -26
- package/src/hooks/useUrqlQuery.js +0 -105
- package/src/utils/urql.d.ts +0 -21
- package/src/utils/urql.js +0 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swan-io/lake",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=18.0.0",
|
|
6
6
|
"yarn": "^1.22.0"
|
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@react-three/drei": "^9.104.1",
|
|
30
30
|
"@react-three/fiber": "^8.16.1",
|
|
31
|
-
"@swan-io/boxed": "^2.
|
|
31
|
+
"@swan-io/boxed": "^2.2.1",
|
|
32
32
|
"@swan-io/chicane": "^2.0.0",
|
|
33
|
-
"@swan-io/
|
|
33
|
+
"@swan-io/graphql-client": "^0.1.1",
|
|
34
|
+
"@swan-io/use-form": "^2.0.2",
|
|
34
35
|
"dayjs": "^1.11.10",
|
|
35
36
|
"polished": "^4.3.1",
|
|
36
37
|
"prism-react-renderer": "^2.3.1",
|
|
@@ -42,7 +43,6 @@
|
|
|
42
43
|
"three": "^0.163.0",
|
|
43
44
|
"ts-dedent": "^2.2.0",
|
|
44
45
|
"ts-pattern": "^5.1.0",
|
|
45
|
-
"urql": "^4.0.7",
|
|
46
46
|
"uuid": "^9.0.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
@@ -26,6 +26,7 @@ export type LakeTextInputProps = Except<TextInputProps, "editable" | "keyboardTy
|
|
|
26
26
|
onUnitChange?: (value: string) => void;
|
|
27
27
|
maxCharCount?: number;
|
|
28
28
|
help?: string;
|
|
29
|
+
warning?: boolean;
|
|
29
30
|
renderEnd?: () => ReactNode;
|
|
30
31
|
containerRef?: Ref<View>;
|
|
31
32
|
};
|
|
@@ -242,6 +243,7 @@ export declare const LakeTextInput: import("react").ForwardRefExoticComponent<{
|
|
|
242
243
|
onUnitChange?: ((value: string) => void) | undefined;
|
|
243
244
|
maxCharCount?: number | undefined;
|
|
244
245
|
help?: string | undefined;
|
|
246
|
+
warning?: boolean | undefined;
|
|
245
247
|
renderEnd?: (() => ReactNode) | undefined;
|
|
246
248
|
containerRef?: Ref<View> | undefined;
|
|
247
249
|
} & import("react").RefAttributes<TextInput | null>>;
|
|
@@ -128,7 +128,7 @@ export const LakeTextInput = forwardRef(({ ariaExpanded, ariaControls, error, di
|
|
|
128
128
|
//maxCharCount is different from maxLength(props inherited of TextInput)
|
|
129
129
|
//maxLength truncates the text in the limitation asked,
|
|
130
130
|
//maxCharCount doesn't have limitation but displays a counter of characters
|
|
131
|
-
maxCharCount, help, renderEnd, ...props }, forwardRef) => {
|
|
131
|
+
maxCharCount, help, warning = false, renderEnd, ...props }, forwardRef) => {
|
|
132
132
|
const inputRef = useRef(null);
|
|
133
133
|
const [isHovered, setIsHovered] = useState(false);
|
|
134
134
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -158,6 +158,7 @@ maxCharCount, help, renderEnd, ...props }, forwardRef) => {
|
|
|
158
158
|
readOnly && styles.readOnly,
|
|
159
159
|
isFocused && styles.focused,
|
|
160
160
|
isNotNullish(unit !== null && unit !== void 0 ? unit : units) && styles.inputWithUnit,
|
|
161
|
+
warning && { borderColor: colors.warning[500] },
|
|
161
162
|
hasError && styles.error,
|
|
162
163
|
valid && styles.valid,
|
|
163
164
|
stylesFromProps,
|
|
@@ -167,5 +168,5 @@ maxCharCount, help, renderEnd, ...props }, forwardRef) => {
|
|
|
167
168
|
readOnly && hasError && styles.readOnlyError,
|
|
168
169
|
disabled && styles.disabled,
|
|
169
170
|
readOnly && styles.readOnly,
|
|
170
|
-
] }), isNotNullish(renderEnd) && _jsx(View, { style: styles.endComponents, children: renderEnd() }), validating && (_jsx(ActivityIndicator, { size: "small", style: styles.endIcon, color: colors.current[500] })), !validating && hasError && (_jsx(Icon, { name: "warning-regular", size: 20, color: colors.negative[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] })), !validating && !hasError && valid && (_jsx(Icon, { name: "checkmark-filled", size: 20, color: colors.positive[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] }))] }), isNotNullish(units) && isNotNullish(onUnitChange) ? (_jsx(Box, { children: _jsx(LakeSelect, { value: unit, onValueChange: onUnitChange, items: units.map(value => ({ name: value, value })), disabled: disabled, style: [styles.unit, (disabled || readOnly) && styles.unitDisabled], mode: "borderless", hideErrors: true }) })) : isNotNullish(unit) ? (_jsx(LakeText, { color: colors.gray[900], style: [styles.unit, (disabled || readOnly) && styles.unitDisabled], children: unit })) : null] }), children] }), !hideErrors && (_jsxs(Box, { direction: "row", style: styles.errorContainer, children: [isNotNullish(error) ? (_jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error })) : (_jsx(LakeText, { variant: "smallRegular", color: colors.gray[500], children: help !== null && help !== void 0 ? help : " " })), isNotNullish(maxCharCount) && (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 4 }), _jsxs(LakeText, { variant: "smallRegular", color: charCount > maxCharCount ? colors.negative[500] : colors.gray[400], style: styles.descriptionLimitation, children: [charCount, " / ", maxCharCount] })] }))] }))] }));
|
|
171
|
+
] }), isNotNullish(renderEnd) && _jsx(View, { style: styles.endComponents, children: renderEnd() }), validating && (_jsx(ActivityIndicator, { size: "small", style: styles.endIcon, color: colors.current[500] })), !validating && hasError && (_jsx(Icon, { name: "warning-regular", size: 20, color: colors.negative[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] })), !validating && warning && !hasError && (_jsx(Icon, { name: "warning-regular", size: 20, color: colors.warning[500], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] })), !validating && !hasError && valid && (_jsx(Icon, { name: "checkmark-filled", size: 20, color: colors.positive[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] }))] }), isNotNullish(units) && isNotNullish(onUnitChange) ? (_jsx(Box, { children: _jsx(LakeSelect, { value: unit, onValueChange: onUnitChange, items: units.map(value => ({ name: value, value })), disabled: disabled, style: [styles.unit, (disabled || readOnly) && styles.unitDisabled], mode: "borderless", hideErrors: true }) })) : isNotNullish(unit) ? (_jsx(LakeText, { color: colors.gray[900], style: [styles.unit, (disabled || readOnly) && styles.unitDisabled], children: unit })) : null] }), children] }), !hideErrors && (_jsxs(Box, { direction: "row", style: styles.errorContainer, children: [isNotNullish(error) ? (_jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error })) : (_jsx(LakeText, { variant: "smallRegular", color: colors.gray[500], children: help !== null && help !== void 0 ? help : " " })), isNotNullish(maxCharCount) && (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 4 }), _jsxs(LakeText, { variant: "smallRegular", color: charCount > maxCharCount ? colors.negative[500] : colors.gray[400], style: styles.descriptionLimitation, children: [charCount, " / ", maxCharCount] })] }))] }))] }));
|
|
171
172
|
});
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Array, Option } from "@swan-io/boxed";
|
|
3
|
+
import { ClientError } from "@swan-io/graphql-client";
|
|
2
4
|
import { t } from "@swan-io/shared-business/src/utils/i18n";
|
|
3
5
|
import { memo, useEffect, useRef, useState } from "react";
|
|
4
6
|
import { Clipboard, StyleSheet, View } from "react-native";
|
|
5
|
-
import { match } from "ts-pattern";
|
|
7
|
+
import { P, match } from "ts-pattern";
|
|
6
8
|
import { animations, colors, shadows } from "../constants/design";
|
|
7
|
-
import { hideToast, useToasts } from "../state/toasts";
|
|
8
|
-
import {
|
|
9
|
-
import { isCombinedError } from "../utils/urql";
|
|
9
|
+
import { getErrorToRequestId, hideToast, useToasts } from "../state/toasts";
|
|
10
|
+
import { isNotNullishOrEmpty, isNullish } from "../utils/nullish";
|
|
10
11
|
import { Box } from "./Box";
|
|
11
12
|
import { Icon } from "./Icon";
|
|
12
13
|
import { LakeText } from "./LakeText";
|
|
@@ -69,6 +70,19 @@ const Toast = memo(({ variant, uid, title, description, error, progress, onClose
|
|
|
69
70
|
const progressBarRef = useRef(null);
|
|
70
71
|
const [visibleState, setVisibleState] = useState("copy");
|
|
71
72
|
const hasDescription = isNotNullishOrEmpty(description);
|
|
73
|
+
const [requestId] = useState(() => {
|
|
74
|
+
if (error == undefined) {
|
|
75
|
+
return Option.None();
|
|
76
|
+
}
|
|
77
|
+
return Array.findMap(ClientError.toArray(error), error => {
|
|
78
|
+
if (error instanceof Error) {
|
|
79
|
+
return Option.fromNullable(getErrorToRequestId().get(error));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
return Option.None();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
72
86
|
const colorVariation = match(variant)
|
|
73
87
|
.returnType()
|
|
74
88
|
.with("success", () => "positive")
|
|
@@ -99,15 +113,17 @@ const Toast = memo(({ variant, uid, title, description, error, progress, onClose
|
|
|
99
113
|
.with("error", () => (_jsx(Icon, { name: "dismiss-circle-regular", size: 20, color: colors[colorVariation][700] })))
|
|
100
114
|
.with("info", () => (_jsx(Icon, { name: "info-regular", size: 20, color: colors[colorVariation][700] })))
|
|
101
115
|
.with("warning", () => (_jsx(Icon, { name: "warning-regular", size: 20, color: colors[colorVariation][700] })))
|
|
102
|
-
.exhaustive(), _jsx(Space, { width: 12 }), _jsx(LakeText, { variant: "regular", color: colors[colorVariation][700], children: title })] }), hasDescription && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 8 }), _jsx(LakeText, { variant: "smallRegular", color: colors.gray[700], children: description })] })),
|
|
116
|
+
.exhaustive(), _jsx(Space, { width: 12 }), _jsx(LakeText, { variant: "regular", color: colors[colorVariation][700], children: title })] }), hasDescription && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 8 }), _jsx(LakeText, { variant: "smallRegular", color: colors.gray[700], children: description })] })), match(requestId)
|
|
117
|
+
.with(Option.P.None, () => null)
|
|
118
|
+
.with(Option.P.Some(P.select()), requestId => (_jsxs(_Fragment, { children: [_jsx(Space, { height: hasDescription ? 4 : 8 }), _jsx(LakeTooltip, { describedBy: "copy", onHide: () => setVisibleState("copy"), togglableOnFocus: true, placement: "center", containerStyle: styles.copyTooltip, content: visibleState === "copy"
|
|
103
119
|
? t("copyButton.copyTooltip")
|
|
104
120
|
: t("copyButton.copiedTooltip"), children: _jsxs(Pressable, { style: styles.copyButton, onPress: event => {
|
|
105
|
-
var _a;
|
|
106
121
|
event.stopPropagation();
|
|
107
122
|
event.preventDefault();
|
|
108
|
-
Clipboard.setString(
|
|
123
|
+
Clipboard.setString(requestId !== null && requestId !== void 0 ? requestId : "");
|
|
109
124
|
setVisibleState("copied");
|
|
110
|
-
}, children: [_jsx(Icon, { color: colors.gray[700], size: 14, name: "copy-regular" }), _jsx(Space, { width: 4 }), _jsxs(LakeText, { numberOfLines: 1, variant: "smallRegular", color: colors.gray[700], children: ["ID: ",
|
|
125
|
+
}, children: [_jsx(Icon, { color: colors.gray[700], size: 14, name: "copy-regular" }), _jsx(Space, { width: 4 }), _jsxs(LakeText, { numberOfLines: 1, variant: "smallRegular", color: colors.gray[700], children: ["ID: ", requestId] })] }) })] })))
|
|
126
|
+
.exhaustive()] }), _jsx(Pressable, { onPress: () => onClose(uid), style: styles.closeButton, children: _jsx(Icon, { name: "lake-close", size: 24, color: colors.gray[500] }) }), progress != null && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 24 }), _jsx(View, { ref: progressBarRef, role: "progressbar", style: [styles.progressBar, { backgroundColor: colors[colorVariation][500] }] })] }))] }) }));
|
|
111
127
|
});
|
|
112
128
|
export const ToastStack = () => {
|
|
113
129
|
const toasts = useToasts();
|
|
@@ -6,7 +6,7 @@ export const usePersistedState = (key, defaultValue) => {
|
|
|
6
6
|
.toOption()
|
|
7
7
|
.flatMap(Option.fromNullable)
|
|
8
8
|
.map(value => JSON.parse(value))
|
|
9
|
-
.
|
|
9
|
+
.getOr(defaultValue);
|
|
10
10
|
});
|
|
11
11
|
const setPersistedState = useCallback((state) => {
|
|
12
12
|
setState(state);
|
package/src/state/toasts.d.ts
CHANGED
|
@@ -19,5 +19,7 @@ type Toast = {
|
|
|
19
19
|
};
|
|
20
20
|
export declare const useToasts: () => Toast[];
|
|
21
21
|
export declare const hideToast: (uid: string) => void;
|
|
22
|
+
export declare const registerErrorToRequestId: (value: WeakMap<WeakKey, string>) => void;
|
|
23
|
+
export declare const getErrorToRequestId: () => WeakMap<WeakKey, string>;
|
|
22
24
|
export declare const showToast: ({ variant, title, description, error, autoClose }: ToastContent) => string;
|
|
23
25
|
export {};
|
package/src/state/toasts.js
CHANGED
|
@@ -13,6 +13,13 @@ export const hideToast = (uid) => {
|
|
|
13
13
|
(_b = toast.progress) === null || _b === void 0 ? void 0 : _b.stopAnimation();
|
|
14
14
|
toasts.set(toasts => toasts.filter(toast => toast.uid !== uid));
|
|
15
15
|
};
|
|
16
|
+
let errorToRequestId = new WeakMap();
|
|
17
|
+
export const registerErrorToRequestId = (value) => {
|
|
18
|
+
errorToRequestId = value;
|
|
19
|
+
};
|
|
20
|
+
export const getErrorToRequestId = () => {
|
|
21
|
+
return errorToRequestId;
|
|
22
|
+
};
|
|
16
23
|
export const showToast = ({ variant, title, description, error, autoClose }) => {
|
|
17
24
|
const uid = `${variant} - ${title} - ${description !== null && description !== void 0 ? description : ""}`;
|
|
18
25
|
const toast = toasts.get().find(toast => toast.uid === uid);
|
package/src/utils/gql.js
ADDED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { AsyncData, Future, Result } from "@swan-io/boxed";
|
|
2
|
-
import { AnyVariables, CombinedError, OperationContext, TypedDocumentNode } from "urql";
|
|
3
|
-
export declare const useUrqlMutation: <Data, Variables extends AnyVariables>(query: TypedDocumentNode<Data, Variables>) => readonly [AsyncData<Result<Data, CombinedError>>, (variables: Variables, context?: Partial<OperationContext>) => Future<Result<Data, CombinedError>>];
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { AsyncData, Future, Result } from "@swan-io/boxed";
|
|
2
|
-
import { useCallback, useMemo } from "react";
|
|
3
|
-
import { CombinedError, useMutation, } from "urql";
|
|
4
|
-
import { isNotNullish, isNullish } from "../utils/nullish";
|
|
5
|
-
const toResult = ({ data, error, }) => {
|
|
6
|
-
if (isNotNullish(error)) {
|
|
7
|
-
return Result.Error(error);
|
|
8
|
-
}
|
|
9
|
-
if (isNullish(data)) {
|
|
10
|
-
return Result.Error(new CombinedError({ networkError: new Error("No Content") }));
|
|
11
|
-
}
|
|
12
|
-
return Result.Ok(data);
|
|
13
|
-
};
|
|
14
|
-
export const useUrqlMutation = (query) => {
|
|
15
|
-
const [{ fetching, data, error }, execute] = useMutation(query);
|
|
16
|
-
return [
|
|
17
|
-
useMemo(() => {
|
|
18
|
-
if (fetching) {
|
|
19
|
-
return AsyncData.Loading();
|
|
20
|
-
}
|
|
21
|
-
if (isNullish(data) && isNullish(error)) {
|
|
22
|
-
return AsyncData.NotAsked();
|
|
23
|
-
}
|
|
24
|
-
return AsyncData.Done(toResult({ data, error }));
|
|
25
|
-
}, [fetching, data, error]),
|
|
26
|
-
useCallback((variables, context) => Future.fromPromise(execute(variables, context))
|
|
27
|
-
.mapError(error => error)
|
|
28
|
-
.mapOkToResult(toResult), [execute]),
|
|
29
|
-
];
|
|
30
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { AsyncData, Future, Result } from "@swan-io/boxed";
|
|
2
|
-
import { DependencyList } from "react";
|
|
3
|
-
import { AnyVariables, CombinedError, DocumentInput, UseQueryArgs } from "urql";
|
|
4
|
-
type Query<Data> = {
|
|
5
|
-
isForceReloading: boolean;
|
|
6
|
-
data: AsyncData<Result<Data, CombinedError>>;
|
|
7
|
-
nextData: AsyncData<Result<Data, CombinedError>>;
|
|
8
|
-
reload: () => void;
|
|
9
|
-
refresh: () => void;
|
|
10
|
-
};
|
|
11
|
-
export declare const useUrqlQuery: <Data, Variables extends AnyVariables>(args: UseQueryArgs<Variables, Data>, dependencyList?: DependencyList) => Query<Data>;
|
|
12
|
-
type PaginatedQuery<Data> = {
|
|
13
|
-
isForceReloading: boolean;
|
|
14
|
-
data: AsyncData<Result<Data, CombinedError>>;
|
|
15
|
-
nextData: AsyncData<Result<Data, CombinedError>>;
|
|
16
|
-
reload: () => void;
|
|
17
|
-
setAfter: (cursor: string | undefined) => void;
|
|
18
|
-
};
|
|
19
|
-
export declare const useUrqlPaginatedQuery: <Data, Variables extends AnyVariables>(args: UseQueryArgs<Variables, Data>, dependencyList?: DependencyList) => PaginatedQuery<Data>;
|
|
20
|
-
type DeferredQuery<Data, Variables extends AnyVariables> = {
|
|
21
|
-
data: AsyncData<Result<Data, CombinedError>>;
|
|
22
|
-
query: (args: Variables) => Future<Result<Data, CombinedError>>;
|
|
23
|
-
reset: () => void;
|
|
24
|
-
};
|
|
25
|
-
export declare const useDeferredUrqlQuery: <Data, Variables extends AnyVariables>(document: DocumentInput<Data, Variables>) => DeferredQuery<Data, Variables>;
|
|
26
|
-
export {};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { AsyncData, Future, Result } from "@swan-io/boxed";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
|
-
import { useClient, useQuery, } from "urql";
|
|
4
|
-
import { isNotNullish, isNullish } from "../utils/nullish";
|
|
5
|
-
import { parseOperationResult } from "../utils/urql";
|
|
6
|
-
const EMPTY_DEPENDENCY_LIST = [];
|
|
7
|
-
export const useUrqlQuery = (args, dependencyList = EMPTY_DEPENDENCY_LIST) => {
|
|
8
|
-
const hasDependencyList = dependencyList !== EMPTY_DEPENDENCY_LIST;
|
|
9
|
-
const [isDepsListUpdate, setIsDepsListUpdate] = useState(hasDependencyList);
|
|
10
|
-
const [isForceReloading, setIsForceReloading] = useState(false);
|
|
11
|
-
const [{ data, fetching, error }, reexecute] = useQuery({
|
|
12
|
-
...args,
|
|
13
|
-
context: useMemo(() => ({ ...args.context, suspense: false }), [args.context]),
|
|
14
|
-
});
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (hasDependencyList) {
|
|
17
|
-
setIsDepsListUpdate(true);
|
|
18
|
-
}
|
|
19
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
20
|
-
}, dependencyList);
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!fetching) {
|
|
23
|
-
setIsDepsListUpdate(false);
|
|
24
|
-
setIsForceReloading(false);
|
|
25
|
-
}
|
|
26
|
-
}, [fetching]);
|
|
27
|
-
const reload = useCallback(() => {
|
|
28
|
-
setIsForceReloading(true);
|
|
29
|
-
reexecute({ requestPolicy: "network-only" });
|
|
30
|
-
}, [reexecute]);
|
|
31
|
-
const refresh = useCallback(() => {
|
|
32
|
-
reexecute({ requestPolicy: "cache-and-network" });
|
|
33
|
-
}, [reexecute]);
|
|
34
|
-
const okResult = useMemo(() => (isNullish(data) ? null : AsyncData.Done(Result.Ok(data))), [data]);
|
|
35
|
-
const errorResult = useMemo(() => (isNullish(error) ? null : AsyncData.Done(Result.Error(error))), [error]);
|
|
36
|
-
const initialFetching = isNullish(okResult) && isNullish(errorResult);
|
|
37
|
-
const shouldResetState = isDepsListUpdate || isForceReloading;
|
|
38
|
-
if (fetching && (initialFetching || shouldResetState)) {
|
|
39
|
-
return {
|
|
40
|
-
isForceReloading,
|
|
41
|
-
data: AsyncData.Loading(),
|
|
42
|
-
nextData: AsyncData.Loading(),
|
|
43
|
-
reload,
|
|
44
|
-
refresh,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
if (isNotNullish(errorResult)) {
|
|
48
|
-
return {
|
|
49
|
-
isForceReloading,
|
|
50
|
-
data: errorResult,
|
|
51
|
-
nextData: errorResult,
|
|
52
|
-
reload,
|
|
53
|
-
refresh,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
if (isNotNullish(okResult)) {
|
|
57
|
-
return {
|
|
58
|
-
isForceReloading,
|
|
59
|
-
data: okResult,
|
|
60
|
-
nextData: fetching ? AsyncData.Loading() : okResult,
|
|
61
|
-
reload,
|
|
62
|
-
refresh,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
isForceReloading,
|
|
67
|
-
data: AsyncData.NotAsked(),
|
|
68
|
-
nextData: AsyncData.NotAsked(),
|
|
69
|
-
reload,
|
|
70
|
-
refresh,
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
export const useUrqlPaginatedQuery = (args, dependencyList = EMPTY_DEPENDENCY_LIST) => {
|
|
74
|
-
const [after, setAfter] = useState();
|
|
75
|
-
const { isForceReloading, data, nextData, reload: baseReload, } = useUrqlQuery({ ...args, variables: { ...args.variables, after } }, dependencyList);
|
|
76
|
-
useEffect(() => {
|
|
77
|
-
setAfter(undefined);
|
|
78
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
|
-
}, dependencyList);
|
|
80
|
-
const reload = useCallback(() => {
|
|
81
|
-
setAfter(undefined);
|
|
82
|
-
baseReload();
|
|
83
|
-
}, [baseReload]);
|
|
84
|
-
return {
|
|
85
|
-
isForceReloading,
|
|
86
|
-
data,
|
|
87
|
-
nextData,
|
|
88
|
-
reload,
|
|
89
|
-
setAfter,
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
export const useDeferredUrqlQuery = (document) => {
|
|
93
|
-
const [data, setData] = useState(AsyncData.NotAsked());
|
|
94
|
-
const client = useClient();
|
|
95
|
-
const query = useCallback((args) => {
|
|
96
|
-
setData(AsyncData.Loading());
|
|
97
|
-
return Future.fromPromise(client.query(document, args).toPromise().then(parseOperationResult)).tap(data => {
|
|
98
|
-
setData(AsyncData.Done(data));
|
|
99
|
-
});
|
|
100
|
-
}, [client, document]);
|
|
101
|
-
const reset = useCallback(() => {
|
|
102
|
-
setData(AsyncData.NotAsked());
|
|
103
|
-
}, []);
|
|
104
|
-
return { data, query, reset };
|
|
105
|
-
};
|
package/src/utils/urql.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Result } from "@swan-io/boxed";
|
|
2
|
-
import { Except, SetRequired } from "type-fest";
|
|
3
|
-
import { AnyVariables, CombinedError, OperationResult, UseQueryArgs, UseQueryResponse, UseQueryState } from "urql";
|
|
4
|
-
export declare const isCombinedError: (error: unknown) => error is CombinedError;
|
|
5
|
-
export declare const parseOperationResult: <T>({ error, data }: OperationResult<T>) => T;
|
|
6
|
-
export declare const useQueryWithErrorBoundary: <Data = unknown, Variables extends AnyVariables = AnyVariables>(options: UseQueryArgs<Variables, Data>) => [
|
|
7
|
-
SetRequired<Except<UseQueryState<Data, Variables>, "fetching" | "error">, "data">,
|
|
8
|
-
UseQueryResponse[1]
|
|
9
|
-
];
|
|
10
|
-
export declare const filterRejectionsToPromise: <T extends {
|
|
11
|
-
__typename: string;
|
|
12
|
-
}>(input: T) => Promise<Exclude<T, {
|
|
13
|
-
__typename: `${string}Rejection`;
|
|
14
|
-
}>>;
|
|
15
|
-
export declare const filterRejectionsToResult: <T extends {
|
|
16
|
-
__typename: string;
|
|
17
|
-
}>(input: T) => Result<Exclude<T, {
|
|
18
|
-
__typename: `${string}Rejection`;
|
|
19
|
-
}>, Extract<T, {
|
|
20
|
-
__typename: `${string}Rejection`;
|
|
21
|
-
}>>;
|
package/src/utils/urql.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Result } from "@swan-io/boxed";
|
|
2
|
-
import { CombinedError, useQuery, } from "urql";
|
|
3
|
-
import { isNotNullish, isNullish } from "./nullish";
|
|
4
|
-
export const isCombinedError = (error) => error instanceof CombinedError;
|
|
5
|
-
export const parseOperationResult = ({ error, data }) => {
|
|
6
|
-
if (isNotNullish(error)) {
|
|
7
|
-
throw error;
|
|
8
|
-
}
|
|
9
|
-
if (isNullish(data)) {
|
|
10
|
-
throw new CombinedError({
|
|
11
|
-
networkError: new Error("No Content"),
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
return data;
|
|
15
|
-
};
|
|
16
|
-
export const useQueryWithErrorBoundary = (options) => {
|
|
17
|
-
const [{ fetching, data, error, ...rest }, reexecuteQuery] = useQuery(options);
|
|
18
|
-
if (isNotNullish(error)) {
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
21
|
-
if (isNullish(data)) {
|
|
22
|
-
throw new CombinedError({
|
|
23
|
-
networkError: new Error("No Content"),
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
return [{ data, ...rest }, reexecuteQuery];
|
|
27
|
-
};
|
|
28
|
-
export const filterRejectionsToPromise = (input) => (input.__typename.endsWith("Rejection")
|
|
29
|
-
? Promise.reject(new Error(input.__typename))
|
|
30
|
-
: Promise.resolve(input));
|
|
31
|
-
export const filterRejectionsToResult = (input) => (input.__typename.endsWith("Rejection") ? Result.Error(input) : Result.Ok(input));
|