@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/lake",
3
- "version": "7.4.6",
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.1.1",
31
+ "@swan-io/boxed": "^2.2.1",
32
32
  "@swan-io/chicane": "^2.0.0",
33
- "@swan-io/use-form": "^2.0.0",
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 { isNotNullish, isNotNullishOrEmpty, isNullish } from "../utils/nullish";
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 })] })), isCombinedError(error) && isNotNullish(error.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"
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((_a = error.requestId) !== null && _a !== void 0 ? _a : "");
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: ", error.requestId] })] }) })] })) : null] }), _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] }] })] }))] }) }));
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
- .getWithDefault(defaultValue);
9
+ .getOr(defaultValue);
10
10
  });
11
11
  const setPersistedState = useCallback((state) => {
12
12
  setState(state);
@@ -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 {};
@@ -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);
@@ -0,0 +1,8 @@
1
+ import { Result } from "@swan-io/boxed";
2
+ export declare const filterRejectionsToResult: <T extends {
3
+ __typename: string;
4
+ }>(input: T) => Result<Exclude<T, {
5
+ __typename: `${string}Rejection`;
6
+ }>, Extract<T, {
7
+ __typename: `${string}Rejection`;
8
+ }>>;
@@ -0,0 +1,2 @@
1
+ import { Result } from "@swan-io/boxed";
2
+ export const filterRejectionsToResult = (input) => (input.__typename.endsWith("Rejection") ? Result.Error(input) : Result.Ok(input));
@@ -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
- };
@@ -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));