diff options
author | Sebastian <sebasjm@gmail.com> | 2023-01-09 20:20:09 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-01-09 20:20:09 -0300 |
commit | 4a781bd0dd8828ce152f6ab2c3f1bbd6b5e826f7 (patch) | |
tree | 5c16976f99eb973ff62d78ed64107ca01df57b99 /packages/taler-wallet-webextension/src/context/alert.ts | |
parent | 8a70edb2f8e235c3462127b0aa4e1b65aa1aee0b (diff) | |
download | wallet-core-4a781bd0dd8828ce152f6ab2c3f1bbd6b5e826f7.tar.xz |
fix #7153: more error handling
if handler do not trap error then fail at compile time,
all safe handlers push alert on error
errors are typed so they render good information
Diffstat (limited to 'packages/taler-wallet-webextension/src/context/alert.ts')
-rw-r--r-- | packages/taler-wallet-webextension/src/context/alert.ts | 98 |
1 files changed, 80 insertions, 18 deletions
diff --git a/packages/taler-wallet-webextension/src/context/alert.ts b/packages/taler-wallet-webextension/src/context/alert.ts index cc98ec1e0..e67d94671 100644 --- a/packages/taler-wallet-webextension/src/context/alert.ts +++ b/packages/taler-wallet-webextension/src/context/alert.ts @@ -19,19 +19,26 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { TranslatedString } from "@gnu-taler/taler-util"; +import { TalerErrorDetail, TranslatedString } from "@gnu-taler/taler-util"; import { ComponentChildren, createContext, h, VNode } from "preact"; import { useContext, useState } from "preact/hooks"; +import { HookError } from "../hooks/useAsyncAsHook.js"; +import { SafeHandler, withSafe } from "../mui/handlers.js"; +import { BackgroundError } from "../wxApi.js"; export type AlertType = "info" | "warning" | "error" | "success"; -export interface Alert { +export interface InfoAlert { message: TranslatedString; description: TranslatedString | VNode; - type: AlertType; + type: "info" | "warning" | "success"; } -export interface ErrorAlert extends Alert { +export type Alert = InfoAlert | ErrorAlert; + +export interface ErrorAlert { + message: TranslatedString; + description: TranslatedString | VNode; type: "error"; context: object; cause: any; @@ -41,10 +48,14 @@ type Type = { alerts: Alert[]; pushAlert: (n: Alert) => void; removeAlert: (n: Alert) => void; + pushAlertOnError: <T>(h: (p: T) => Promise<void>) => SafeHandler<T>; }; const initial: Type = { alerts: [], + pushAlertOnError: () => { + throw Error("alert context not initialized"); + }, pushAlert: () => { null; }, @@ -80,8 +91,17 @@ export const AlertProvider = ({ children }: Props): VNode => { setAlerts((ns: AlertWithDate[]) => ns.filter((n) => n !== alert)); }; + function pushAlertOnError<T>( + handler: (p: T) => Promise<void>, + ): SafeHandler<T> { + return withSafe(handler, (e) => { + const a = alertFromError(e.message as TranslatedString, e); + pushAlert(a); + }); + } + return h(Context.Provider, { - value: { alerts, pushAlert, removeAlert }, + value: { alerts, pushAlert, removeAlert, pushAlertOnError }, children, }); }; @@ -90,29 +110,71 @@ export const useAlertContext = (): Type => useContext(Context); export function alertFromError( message: TranslatedString, - error: unknown, + error: HookError, ...context: any[] -): ErrorAlert { - let description = "" as TranslatedString; +): ErrorAlert; - const isObject = typeof error === "object" && - error !== null; - const hasMessage = - isObject && - "message" in error && - typeof error.message === "string"; +export function alertFromError( + message: TranslatedString, + error: Error, + ...context: any[] +): ErrorAlert; - if (hasMessage) { - description = error.message as TranslatedString; +export function alertFromError( + message: TranslatedString, + error: TalerErrorDetail, + ...context: any[] +): ErrorAlert; + +export function alertFromError( + message: TranslatedString, + error: HookError | TalerErrorDetail | Error, + ...context: any[] +): ErrorAlert { + let description: TranslatedString; + let cause: any; + + if (typeof error === "object" && error !== null) { + if ("code" in error) { + //TalerErrorDetail + description = (error.hint ?? + `Error code: ${error.code}`) as TranslatedString; + cause = { + details: error, + }; + } else if ("hasError" in error) { + //HookError + description = error.message as TranslatedString; + if (error.type === "taler") { + cause = { + details: error.details, + }; + } + } else { + if (error instanceof BackgroundError) { + description = (error.errorDetail.hint ?? + `Error code: ${error.errorDetail.code}`) as TranslatedString; + cause = { + details: error.errorDetail, + stack: error.stack, + }; + } else { + description = error.message as TranslatedString; + cause = { + stack: error.stack, + }; + } + } } else { - description = `Unknown error: ${String(error)}` as TranslatedString; + description = "" as TranslatedString; + cause = error; } return { type: "error", message, description, - cause: error, + cause, context, }; } |