diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts')
-rw-r--r-- | packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts | 96 |
1 files changed, 73 insertions, 23 deletions
diff --git a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts index 2131d45cb..bd430f2ef 100644 --- a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts +++ b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts @@ -1,48 +1,98 @@ /* - This file is part of TALER - (C) 2016 GNUnet e.V. + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. - TALER is free software; you can redistribute it and/or modify it under the + GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. - TALER is distributed in the hope that it will be useful, but WITHOUT ANY + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { ExchangesListRespose } from "@gnu-taler/taler-util"; -import { useEffect, useState } from "preact/hooks"; -import * as wxApi from "../wxApi"; +import { TalerErrorDetail, TalerError } from "@gnu-taler/taler-util"; +import { useEffect, useMemo, useState } from "preact/hooks"; +import { BackgroundError } from "../wxApi.js"; -interface HookOk<T> { +export interface HookOk<T> { hasError: false; response: T; } -interface HookError { +export type HookError = HookGenericError | HookOperationalError; + +export interface HookGenericError { hasError: true; + type: "error"; message: string; } +export interface HookOperationalError { + hasError: true; + type: "taler"; + message: string; + details: TalerErrorDetail; +} + +interface WithRetry { + retry: () => void; +} + export type HookResponse<T> = HookOk<T> | HookError | undefined; +export type HookResponseWithRetry<T> = + | ((HookOk<T> | HookError) & WithRetry) + | undefined; -export function useAsyncAsHook<T> (fn: (() => Promise<T>)): HookResponse<T> { +export function useAsyncAsHook<T>( + fn: () => Promise<T | false>, + deps?: unknown[], +): HookResponseWithRetry<T> { const [result, setHookResponse] = useState<HookResponse<T>>(undefined); - useEffect(() => { - async function doAsync() { - try { - const response = await fn(); - setHookResponse({ hasError: false, response }); - } catch (e) { - if (e instanceof Error) { - setHookResponse({ hasError: true, message: e.message }); - } + + const args = useMemo( + () => ({ + fn, + }), + deps || [], + ); + + async function doAsync(): Promise<void> { + try { + const response = await args.fn(); + if (response === false) return; + setHookResponse({ hasError: false, response }); + } catch (e) { + if (e instanceof TalerError) { + setHookResponse({ + hasError: true, + type: "taler", + message: e.message, + details: e.errorDetail, + }); + } else if (e instanceof BackgroundError) { + setHookResponse({ + hasError: true, + type: "taler", + message: e.message, + details: e.errorDetail, + }); + } else if (e instanceof Error) { + setHookResponse({ + hasError: true, + type: "error", + message: e.message, + }); } } - doAsync() - }, []); - return result; + } + + useEffect(() => { + doAsync(); + }, [args]); + + if (!result) return undefined; + return { ...result, retry: doAsync }; } |