@swan-io/lake 7.4.5 → 8.0.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 +2 -2
- package/src/components/ToastStack.js +24 -8
- 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.0.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=18.0.0",
|
|
6
6
|
"yarn": "^1.22.0"
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@react-three/fiber": "^8.16.1",
|
|
31
31
|
"@swan-io/boxed": "^2.1.1",
|
|
32
32
|
"@swan-io/chicane": "^2.0.0",
|
|
33
|
+
"@swan-io/graphql-client": "^0.1.0",
|
|
33
34
|
"@swan-io/use-form": "^2.0.0",
|
|
34
35
|
"dayjs": "^1.11.10",
|
|
35
36
|
"polished": "^4.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": {
|
|
@@ -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();
|
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));
|