some fixes afte testing demobank with ms
This commit is contained in:
parent
dd2599ff94
commit
1723f16b9c
@ -33,7 +33,7 @@ const useSWR = _useSWR as unknown as SWRHook;
|
|||||||
export function useAdminAccountAPI(): AdminAccountAPI {
|
export function useAdminAccountAPI(): AdminAccountAPI {
|
||||||
const { request } = useAuthenticatedBackend();
|
const { request } = useAuthenticatedBackend();
|
||||||
const mutateAll = useMatchMutate();
|
const mutateAll = useMatchMutate();
|
||||||
const { state } = useBackendContext();
|
const { state, logIn } = useBackendContext();
|
||||||
if (state.status === "loggedOut") {
|
if (state.status === "loggedOut") {
|
||||||
throw Error("access-api can't be used when the user is not logged In");
|
throw Error("access-api can't be used when the user is not logged In");
|
||||||
}
|
}
|
||||||
@ -81,6 +81,13 @@ export function useAdminAccountAPI(): AdminAccountAPI {
|
|||||||
data,
|
data,
|
||||||
contentType: "json",
|
contentType: "json",
|
||||||
});
|
});
|
||||||
|
if (account === state.username) {
|
||||||
|
await mutateAll(/.*/)
|
||||||
|
logIn({
|
||||||
|
username: account,
|
||||||
|
password: data.new_password
|
||||||
|
})
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -288,6 +295,12 @@ export function useRatiosAndFeeConfig(): HttpResponse<
|
|||||||
keepPreviousData: true,
|
keepPreviousData: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
// data.data.ratios_and_fees.sell_out_fee = 2
|
||||||
|
if (!data.data.ratios_and_fees.fiat_currency) {
|
||||||
|
data.data.ratios_and_fees.fiat_currency = "FIAT"
|
||||||
|
}
|
||||||
|
}
|
||||||
if (data) return data;
|
if (data) return data;
|
||||||
if (error) return error.info;
|
if (error) return error.info;
|
||||||
return { loading: true };
|
return { loading: true };
|
||||||
|
@ -28,7 +28,9 @@ import { PaymentOptions } from "./PaymentOptions.js";
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
account: string;
|
account: string;
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Query account information and show QR code if there is pending withdrawal
|
* Query account information and show QR code if there is pending withdrawal
|
||||||
|
@ -59,7 +59,9 @@ function randomPassword(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Query account information and show QR code if there is pending withdrawal
|
* Query account information and show QR code if there is pending withdrawal
|
||||||
@ -109,6 +111,11 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
|
|||||||
if (showCashouts) {
|
if (showCashouts) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<div>
|
||||||
|
<h1 class="nav welcome-text">
|
||||||
|
<i18n.Translate>Cashout for account {showCashouts}</i18n.Translate>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<Cashouts
|
<Cashouts
|
||||||
account={showCashouts}
|
account={showCashouts}
|
||||||
onSelected={(id) => {
|
onSelected={(id) => {
|
||||||
@ -116,15 +123,17 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
|
|||||||
setShowCashouts(undefined);
|
setShowCashouts(undefined);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<input
|
<p>
|
||||||
class="pure-button"
|
<input
|
||||||
type="submit"
|
class="pure-button"
|
||||||
value={i18n.str`Close`}
|
type="submit"
|
||||||
onClick={async (e) => {
|
value={i18n.str`Close`}
|
||||||
e.preventDefault();
|
onClick={async (e) => {
|
||||||
setShowCashouts(undefined);
|
e.preventDefault();
|
||||||
}}
|
setShowCashouts(undefined);
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -184,7 +193,7 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
|
|||||||
onClose={() => setCreateAccount(false)}
|
onClose={() => setCreateAccount(false)}
|
||||||
onCreateSuccess={(password) => {
|
onCreateSuccess={(password) => {
|
||||||
showInfoMessage(
|
showInfoMessage(
|
||||||
i18n.str`Account created with password "${password}"`,
|
i18n.str`Account created with password "${password}". The user must change the password on the next login.`,
|
||||||
);
|
);
|
||||||
setCreateAccount(false);
|
setCreateAccount(false);
|
||||||
}}
|
}}
|
||||||
@ -326,7 +335,9 @@ export function UpdateAccountPassword({
|
|||||||
onUpdateSuccess,
|
onUpdateSuccess,
|
||||||
onLoadNotOk,
|
onLoadNotOk,
|
||||||
}: {
|
}: {
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
onUpdateSuccess: () => void;
|
onUpdateSuccess: () => void;
|
||||||
account: string;
|
account: string;
|
||||||
@ -521,7 +532,9 @@ export function ShowAccountDetails({
|
|||||||
onLoadNotOk,
|
onLoadNotOk,
|
||||||
onChangePassword,
|
onChangePassword,
|
||||||
}: {
|
}: {
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
onClear?: () => void;
|
onClear?: () => void;
|
||||||
onChangePassword: () => void;
|
onChangePassword: () => void;
|
||||||
onUpdateSuccess: () => void;
|
onUpdateSuccess: () => void;
|
||||||
@ -628,7 +641,9 @@ function RemoveAccount({
|
|||||||
onUpdateSuccess,
|
onUpdateSuccess,
|
||||||
onLoadNotOk,
|
onLoadNotOk,
|
||||||
}: {
|
}: {
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
onUpdateSuccess: () => void;
|
onUpdateSuccess: () => void;
|
||||||
account: string;
|
account: string;
|
||||||
@ -806,7 +821,7 @@ function AccountForm({
|
|||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label>{i18n.str`IBAN`}</label>
|
<label>{i18n.str`Internal IBAN`}</label>
|
||||||
<input
|
<input
|
||||||
disabled={purpose !== "create"}
|
disabled={purpose !== "create"}
|
||||||
value={form.iban ?? ""}
|
value={form.iban ?? ""}
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
TranslatedString,
|
TranslatedString,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
|
ErrorType,
|
||||||
HttpResponsePaginated,
|
HttpResponsePaginated,
|
||||||
RequestError,
|
RequestError,
|
||||||
useTranslationContext,
|
useTranslationContext,
|
||||||
@ -44,7 +45,9 @@ import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js";
|
|||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onRegister: () => void;
|
onRegister: () => void;
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
export function BusinessAccount({
|
export function BusinessAccount({
|
||||||
onClose,
|
onClose,
|
||||||
@ -79,6 +82,9 @@ export function BusinessAccount({
|
|||||||
setNewcashout(false);
|
setNewcashout(false);
|
||||||
}}
|
}}
|
||||||
onComplete={(id) => {
|
onComplete={(id) => {
|
||||||
|
showInfoMessage(
|
||||||
|
i18n.str`Cashout created. You need to confirm the operation to complete the transaction.`,
|
||||||
|
);
|
||||||
setNewcashout(false);
|
setNewcashout(false);
|
||||||
setShowCashoutDetails(id);
|
setShowCashoutDetails(id);
|
||||||
}}
|
}}
|
||||||
@ -156,7 +162,9 @@ interface PropsCashout {
|
|||||||
account: string;
|
account: string;
|
||||||
onComplete: (id: string) => void;
|
onComplete: (id: string) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
type FormType = {
|
type FormType = {
|
||||||
@ -180,7 +188,7 @@ function CreateCashout({
|
|||||||
const result = useAccountDetails(account);
|
const result = useAccountDetails(account);
|
||||||
const [error, saveError] = useState<ErrorMessage | undefined>();
|
const [error, saveError] = useState<ErrorMessage | undefined>();
|
||||||
|
|
||||||
const [form, setForm] = useState<Partial<FormType>>({});
|
const [form, setForm] = useState<Partial<FormType>>({ isDebit: true });
|
||||||
|
|
||||||
const { createCashout } = useCircuitAccountAPI();
|
const { createCashout } = useCircuitAccountAPI();
|
||||||
if (!result.ok) return onLoadNotOk(result);
|
if (!result.ok) return onLoadNotOk(result);
|
||||||
@ -277,10 +285,14 @@ function CreateCashout({
|
|||||||
type="text"
|
type="text"
|
||||||
readonly
|
readonly
|
||||||
class="currency-indicator"
|
class="currency-indicator"
|
||||||
size={balance.currency.length}
|
size={
|
||||||
maxLength={balance.currency.length}
|
!form.isDebit ? fiatCurrency.length : balance.currency.length
|
||||||
|
}
|
||||||
|
maxLength={
|
||||||
|
!form.isDebit ? fiatCurrency.length : balance.currency.length
|
||||||
|
}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
value={balance.currency}
|
value={!form.isDebit ? fiatCurrency : balance.currency}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@ -389,16 +401,16 @@ function CreateCashout({
|
|||||||
{Amounts.isZero(sellFee) ? undefined : (
|
{Amounts.isZero(sellFee) ? undefined : (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label>{i18n.str`Transfer before fee`}</label>
|
<label>{i18n.str`Amount after conversion`}</label>
|
||||||
<div style={{ width: "max-content" }}>
|
<div style={{ width: "max-content" }}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
readonly
|
readonly
|
||||||
class="currency-indicator"
|
class="currency-indicator"
|
||||||
size={balance.currency.length}
|
size={fiatCurrency.length}
|
||||||
maxLength={balance.currency.length}
|
maxLength={fiatCurrency.length}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
value={balance.currency}
|
value={fiatCurrency}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@ -417,10 +429,10 @@ function CreateCashout({
|
|||||||
type="text"
|
type="text"
|
||||||
readonly
|
readonly
|
||||||
class="currency-indicator"
|
class="currency-indicator"
|
||||||
size={balance.currency.length}
|
size={fiatCurrency.length}
|
||||||
maxLength={balance.currency.length}
|
maxLength={fiatCurrency.length}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
value={balance.currency}
|
value={fiatCurrency}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@ -442,10 +454,10 @@ function CreateCashout({
|
|||||||
type="text"
|
type="text"
|
||||||
readonly
|
readonly
|
||||||
class="currency-indicator"
|
class="currency-indicator"
|
||||||
size={balance.currency.length}
|
size={fiatCurrency.length}
|
||||||
maxLength={balance.currency.length}
|
maxLength={fiatCurrency.length}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
value={balance.currency}
|
value={fiatCurrency}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@ -543,34 +555,69 @@ function CreateCashout({
|
|||||||
onComplete(res.data.uuid);
|
onComplete(res.data.uuid);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof RequestError) {
|
if (error instanceof RequestError) {
|
||||||
const errorData: SandboxBackend.SandboxError =
|
const e = error as RequestError<SandboxBackend.SandboxError>;
|
||||||
error.info.error;
|
switch (e.cause.type) {
|
||||||
if (error.info.status === HttpStatusCode.PreconditionFailed) {
|
case ErrorType.TIMEOUT: {
|
||||||
saveError({
|
saveError({
|
||||||
title: i18n.str`The account does not have sufficient funds`,
|
title: i18n.str`Request timeout, try again later.`,
|
||||||
description: errorData.error.description,
|
});
|
||||||
debug: JSON.stringify(error.info),
|
break;
|
||||||
});
|
}
|
||||||
} else if (
|
case ErrorType.CLIENT: {
|
||||||
error.info.status === HttpStatusCode.ServiceUnavailable
|
const errorData = e.cause.error;
|
||||||
) {
|
|
||||||
saveError({
|
if (
|
||||||
title: i18n.str`The bank does not support the TAN channel for this operation`,
|
e.cause.status === HttpStatusCode.PreconditionFailed
|
||||||
description: errorData.error.description,
|
) {
|
||||||
debug: JSON.stringify(error.info),
|
saveError({
|
||||||
});
|
title: i18n.str`The account does not have sufficient funds`,
|
||||||
} else if (error.info.status === HttpStatusCode.Conflict) {
|
description: errorData.error.description,
|
||||||
saveError({
|
debug: JSON.stringify(error.info),
|
||||||
title: i18n.str`No contact information for this channel`,
|
});
|
||||||
description: errorData.error.description,
|
} else if (e.cause.status === HttpStatusCode.Conflict) {
|
||||||
debug: JSON.stringify(error.info),
|
saveError({
|
||||||
});
|
title: i18n.str`No contact information for this channel`,
|
||||||
} else {
|
description: errorData.error.description,
|
||||||
saveError({
|
debug: JSON.stringify(error.info),
|
||||||
title: i18n.str`New cashout gave response error`,
|
});
|
||||||
description: errorData.error.description,
|
} else {
|
||||||
debug: JSON.stringify(error.info),
|
saveError({
|
||||||
});
|
title: i18n.str`New cashout gave response error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.info),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.SERVER: {
|
||||||
|
const errorData = e.cause.error;
|
||||||
|
if (
|
||||||
|
e.cause.status === HttpStatusCode.ServiceUnavailable
|
||||||
|
) {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`The bank does not support the TAN channel for this operation`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.info),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Creating cashout returned with a server error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.UNEXPECTED: {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Unexpected error trying to create cashout.`,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertUnreachable(e.cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (error instanceof Error) {
|
} else if (error instanceof Error) {
|
||||||
saveError({
|
saveError({
|
||||||
@ -592,7 +639,9 @@ function CreateCashout({
|
|||||||
interface ShowCashoutProps {
|
interface ShowCashoutProps {
|
||||||
id: string;
|
id: string;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
export function ShowCashoutDetails({
|
export function ShowCashoutDetails({
|
||||||
id,
|
id,
|
||||||
@ -699,22 +748,59 @@ export function ShowCashoutDetails({
|
|||||||
onCancel();
|
onCancel();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof RequestError) {
|
if (error instanceof RequestError) {
|
||||||
const errorData: SandboxBackend.SandboxError =
|
const e =
|
||||||
error.info.error;
|
error as RequestError<SandboxBackend.SandboxError>;
|
||||||
if (
|
switch (e.cause.type) {
|
||||||
error.info.status === HttpStatusCode.PreconditionFailed
|
case ErrorType.TIMEOUT: {
|
||||||
) {
|
saveError({
|
||||||
saveError({
|
title: i18n.str`Request timeout, try again later.`,
|
||||||
title: i18n.str`Cashout was already aborted`,
|
});
|
||||||
description: errorData.error.description,
|
break;
|
||||||
debug: JSON.stringify(error.info),
|
}
|
||||||
});
|
case ErrorType.CLIENT: {
|
||||||
} else {
|
const errorData = e.cause.error;
|
||||||
saveError({
|
if (
|
||||||
title: i18n.str`Aborting cashout gave response error`,
|
e.cause.status === HttpStatusCode.PreconditionFailed
|
||||||
description: errorData.error.description,
|
) {
|
||||||
debug: JSON.stringify(error.info),
|
saveError({
|
||||||
});
|
title: i18n.str`Cashout was already aborted`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.info),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Aborting cashout gave response error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.info),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Aborting cashout gave response error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.SERVER: {
|
||||||
|
const errorData = e.cause.error;
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Aborting cashout returned with a server error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.UNEXPECTED: {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Unexpected error trying to abort cashout.`,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertUnreachable(e.cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (error instanceof Error) {
|
} else if (error instanceof Error) {
|
||||||
saveError({
|
saveError({
|
||||||
@ -741,13 +827,44 @@ export function ShowCashoutDetails({
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof RequestError) {
|
if (error instanceof RequestError) {
|
||||||
const errorData: SandboxBackend.SandboxError =
|
const e =
|
||||||
error.info.error;
|
error as RequestError<SandboxBackend.SandboxError>;
|
||||||
saveError({
|
switch (e.cause.type) {
|
||||||
title: i18n.str`Confirmation of cashout gave response error`,
|
case ErrorType.TIMEOUT: {
|
||||||
description: errorData.error.description,
|
saveError({
|
||||||
debug: JSON.stringify(error.info),
|
title: i18n.str`Request timeout, try again later.`,
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.CLIENT: {
|
||||||
|
const errorData = e.cause.error;
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Confirmation of cashout gave response error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.SERVER: {
|
||||||
|
const errorData = e.cause.error;
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Confirmation of cashout gave response error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.UNEXPECTED: {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Unexpected error trying to cashout.`,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertUnreachable(e.cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (error instanceof Error) {
|
} else if (error instanceof Error) {
|
||||||
saveError({
|
saveError({
|
||||||
title: i18n.str`Confirmation failed, please report`,
|
title: i18n.str`Confirmation failed, please report`,
|
||||||
@ -767,3 +884,7 @@ export function ShowCashoutDetails({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertUnreachable(x: never): never {
|
||||||
|
throw new Error("Didn't expect to get here");
|
||||||
|
}
|
||||||
|
@ -14,9 +14,11 @@
|
|||||||
GNU 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 { Logger } from "@gnu-taler/taler-util";
|
import { HttpStatusCode, Logger } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
|
ErrorType,
|
||||||
HttpResponsePaginated,
|
HttpResponsePaginated,
|
||||||
|
RequestError,
|
||||||
useTranslationContext,
|
useTranslationContext,
|
||||||
} from "@gnu-taler/web-util/lib/index.browser";
|
} from "@gnu-taler/web-util/lib/index.browser";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
@ -119,9 +121,9 @@ function handleNotOkResult(
|
|||||||
onErrorHandler: (state: PageStateType["error"]) => void,
|
onErrorHandler: (state: PageStateType["error"]) => void,
|
||||||
i18n: ReturnType<typeof useTranslationContext>["i18n"],
|
i18n: ReturnType<typeof useTranslationContext>["i18n"],
|
||||||
onRegister: () => void,
|
onRegister: () => void,
|
||||||
): <T, E>(result: HttpResponsePaginated<T, E>) => VNode {
|
): <T>(result: HttpResponsePaginated<T, SandboxBackend.SandboxError>) => VNode {
|
||||||
return function handleNotOkResult2<T, E>(
|
return function handleNotOkResult2<T>(
|
||||||
result: HttpResponsePaginated<T, E>,
|
result: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
): VNode {
|
): VNode {
|
||||||
if (result.clientError && result.isUnauthorized) {
|
if (result.clientError && result.isUnauthorized) {
|
||||||
onErrorHandler({
|
onErrorHandler({
|
||||||
@ -137,13 +139,49 @@ function handleNotOkResult(
|
|||||||
}
|
}
|
||||||
if (result.loading) return <Loading />;
|
if (result.loading) return <Loading />;
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
onErrorHandler({
|
switch (result.type) {
|
||||||
title: i18n.str`The backend reported a problem: HTTP status #${result.status}`,
|
case ErrorType.TIMEOUT: {
|
||||||
description: `Diagnostic from ${result.info?.url} is "${result.message}"`,
|
onErrorHandler({
|
||||||
debug: JSON.stringify(result.error),
|
title: i18n.str`Request timeout, try again later.`,
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.CLIENT: {
|
||||||
|
const errorData = result.error;
|
||||||
|
onErrorHandler({
|
||||||
|
title: i18n.str`Could not load due to a client error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(result),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.SERVER: {
|
||||||
|
const errorData = result.error;
|
||||||
|
onErrorHandler({
|
||||||
|
title: i18n.str`Server returned with error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(result),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.UNEXPECTED: {
|
||||||
|
onErrorHandler({
|
||||||
|
title: i18n.str`Unexpected error.`,
|
||||||
|
description: `Diagnostic from ${result.info?.url} is "${result.message}"`,
|
||||||
|
debug: JSON.stringify(result.error),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertUnreachable(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return <LoginForm onRegister={onRegister} />;
|
return <LoginForm onRegister={onRegister} />;
|
||||||
}
|
}
|
||||||
return <div />;
|
return <div />;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
export function assertUnreachable(x: never): never {
|
||||||
|
throw new Error("Didn't expect to get here");
|
||||||
|
}
|
||||||
|
@ -48,7 +48,7 @@ export function PaytoWireTransferForm({
|
|||||||
onSuccess: () => void;
|
onSuccess: () => void;
|
||||||
currency: string;
|
currency: string;
|
||||||
}): VNode {
|
}): VNode {
|
||||||
const backend = useBackendContext();
|
// const backend = useBackendContext();
|
||||||
// const { pageState, pageStateSetter } = usePageContext(); // NOTE: used for go-back button?
|
// const { pageState, pageStateSetter } = usePageContext(); // NOTE: used for go-back button?
|
||||||
|
|
||||||
const [isRawPayto, setIsRawPayto] = useState(false);
|
const [isRawPayto, setIsRawPayto] = useState(false);
|
||||||
@ -188,17 +188,7 @@ export function PaytoWireTransferForm({
|
|||||||
paytoUri,
|
paytoUri,
|
||||||
amount: `${currency}:${amount}`,
|
amount: `${currency}:${amount}`,
|
||||||
});
|
});
|
||||||
// return await createTransactionCall(
|
onSuccess();
|
||||||
// transactionData,
|
|
||||||
// backend.state,
|
|
||||||
// pageStateSetter,
|
|
||||||
// () => {
|
|
||||||
// setAmount(undefined);
|
|
||||||
// setIban(undefined);
|
|
||||||
// setSubject(undefined);
|
|
||||||
// },
|
|
||||||
// i18n,
|
|
||||||
// );
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
|
@ -36,7 +36,9 @@ const logger = new Logger("PublicHistoriesPage");
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
import { HttpStatusCode, Logger } from "@gnu-taler/taler-util";
|
import { HttpStatusCode, Logger } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
|
ErrorType,
|
||||||
RequestError,
|
RequestError,
|
||||||
useTranslationContext,
|
useTranslationContext,
|
||||||
} from "@gnu-taler/web-util/lib/index.browser";
|
} from "@gnu-taler/web-util/lib/index.browser";
|
||||||
@ -176,26 +177,52 @@ function RegistrationForm({
|
|||||||
onComplete();
|
onComplete();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof RequestError) {
|
if (error instanceof RequestError) {
|
||||||
const errorData: SandboxBackend.SandboxError =
|
const e =
|
||||||
error.info.error;
|
error as RequestError<SandboxBackend.SandboxError>;
|
||||||
if (error.info.status === HttpStatusCode.Conflict) {
|
switch (e.cause.type) {
|
||||||
onError({
|
case ErrorType.TIMEOUT: {
|
||||||
title: i18n.str`That username is already taken`,
|
onError({
|
||||||
description: errorData.error.description,
|
title: i18n.str`Request timeout, try again later.`,
|
||||||
debug: JSON.stringify(error.info),
|
});
|
||||||
});
|
break;
|
||||||
} else {
|
}
|
||||||
onError({
|
case ErrorType.CLIENT: {
|
||||||
title: i18n.str`New registration gave response error`,
|
const errorData = e.cause.error;
|
||||||
description: errorData.error.description,
|
if (e.cause.status === HttpStatusCode.Conflict) {
|
||||||
debug: JSON.stringify(error.info),
|
onError({
|
||||||
});
|
title: i18n.str`That username is already taken`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
onError({
|
||||||
|
title: i18n.str`New registration gave response error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.SERVER: {
|
||||||
|
const errorData = e.cause.error;
|
||||||
|
onError({
|
||||||
|
title: i18n.str`New registration gave response error`,
|
||||||
|
description: errorData?.error?.description,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.UNEXPECTED: {
|
||||||
|
onError({
|
||||||
|
title: i18n.str`Unexpected error doing the registration.`,
|
||||||
|
debug: JSON.stringify(error.cause),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertUnreachable(e.cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (error instanceof Error) {
|
|
||||||
onError({
|
|
||||||
title: i18n.str`Registration failed, please report`,
|
|
||||||
description: error.message,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -222,3 +249,7 @@ function RegistrationForm({
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertUnreachable(x: never): never {
|
||||||
|
throw new Error("Didn't expect to get here");
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
ErrorType,
|
||||||
HttpResponsePaginated,
|
HttpResponsePaginated,
|
||||||
useTranslationContext,
|
useTranslationContext,
|
||||||
} from "@gnu-taler/web-util/lib/index.browser";
|
} from "@gnu-taler/web-util/lib/index.browser";
|
||||||
@ -34,9 +35,9 @@ function handleNotOkResult(
|
|||||||
safe: string,
|
safe: string,
|
||||||
saveError: (state: PageStateType["error"]) => void,
|
saveError: (state: PageStateType["error"]) => void,
|
||||||
i18n: ReturnType<typeof useTranslationContext>["i18n"],
|
i18n: ReturnType<typeof useTranslationContext>["i18n"],
|
||||||
): <T, E>(result: HttpResponsePaginated<T, E>) => VNode {
|
): <T>(result: HttpResponsePaginated<T, SandboxBackend.SandboxError>) => VNode {
|
||||||
return function handleNotOkResult2<T, E>(
|
return function handleNotOkResult2<T>(
|
||||||
result: HttpResponsePaginated<T, E>,
|
result: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
): VNode {
|
): VNode {
|
||||||
if (result.clientError && result.isUnauthorized) {
|
if (result.clientError && result.isUnauthorized) {
|
||||||
route(safe);
|
route(safe);
|
||||||
@ -50,12 +51,45 @@ function handleNotOkResult(
|
|||||||
}
|
}
|
||||||
if (result.loading) return <Loading />;
|
if (result.loading) return <Loading />;
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
saveError({
|
switch (result.type) {
|
||||||
title: i18n.str`The backend reported a problem: HTTP status #${result.status}`,
|
case ErrorType.TIMEOUT: {
|
||||||
description: i18n.str`Diagnostic from ${result.info?.url} is "${result.message}"`,
|
saveError({
|
||||||
debug: JSON.stringify(result.error),
|
title: i18n.str`Request timeout, try again later.`,
|
||||||
});
|
});
|
||||||
route(safe);
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.CLIENT: {
|
||||||
|
const errorData = result.error;
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Could not load due to a client error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(result),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.SERVER: {
|
||||||
|
const errorData = result.error;
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Server returned with error`,
|
||||||
|
description: errorData.error.description,
|
||||||
|
debug: JSON.stringify(result),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorType.UNEXPECTED: {
|
||||||
|
saveError({
|
||||||
|
title: i18n.str`Unexpected error.`,
|
||||||
|
description: `Diagnostic from ${result.info?.url} is "${result.message}"`,
|
||||||
|
debug: JSON.stringify(result.error),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
assertUnreachable(result);
|
||||||
|
}
|
||||||
|
route(safe);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return <div />;
|
return <div />;
|
||||||
};
|
};
|
||||||
@ -137,3 +171,7 @@ function Redirect({ to }: { to: string }): VNode {
|
|||||||
}, []);
|
}, []);
|
||||||
return <div>being redirected to {to}</div>;
|
return <div>being redirected to {to}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertUnreachable(x: never): never {
|
||||||
|
throw new Error("Didn't expect to get here");
|
||||||
|
}
|
||||||
|
@ -33,7 +33,9 @@ interface Props {
|
|||||||
withdrawalId: string;
|
withdrawalId: string;
|
||||||
talerWithdrawUri: string;
|
talerWithdrawUri: string;
|
||||||
onAbort: () => void;
|
onAbort: () => void;
|
||||||
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
|
onLoadNotOk: <T>(
|
||||||
|
error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
|
||||||
|
) => VNode;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Offer the QR code (and a clickable taler://-link) to
|
* Offer the QR code (and a clickable taler://-link) to
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
import {
|
import {
|
||||||
useTranslationContext,
|
useTranslationContext,
|
||||||
HttpError,
|
HttpError,
|
||||||
|
ErrorType,
|
||||||
} from "@gnu-taler/web-util/lib/index.browser";
|
} from "@gnu-taler/web-util/lib/index.browser";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { Fragment, FunctionComponent, h, VNode } from "preact";
|
import { Fragment, FunctionComponent, h, VNode } from "preact";
|
||||||
@ -163,16 +164,25 @@ export function InstanceRoutes({
|
|||||||
return function ServerErrorRedirectToImpl(
|
return function ServerErrorRedirectToImpl(
|
||||||
error: HttpError<MerchantBackend.ErrorDetail>,
|
error: HttpError<MerchantBackend.ErrorDetail>,
|
||||||
) {
|
) {
|
||||||
setGlobalNotification({
|
if (error.type === ErrorType.TIMEOUT) {
|
||||||
message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
|
setGlobalNotification({
|
||||||
description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
|
message: i18n.str`The request to the backend take too long and was cancelled`,
|
||||||
details:
|
description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
|
||||||
error.clientError || error.serverError
|
type: "ERROR",
|
||||||
? error.error?.detail
|
to,
|
||||||
: undefined,
|
});
|
||||||
type: "ERROR",
|
} else {
|
||||||
to,
|
setGlobalNotification({
|
||||||
});
|
message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
|
||||||
|
description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
|
||||||
|
details:
|
||||||
|
error.clientError || error.serverError
|
||||||
|
? error.error?.detail
|
||||||
|
: undefined,
|
||||||
|
type: "ERROR",
|
||||||
|
to,
|
||||||
|
});
|
||||||
|
}
|
||||||
return <Redirect to={to} />;
|
return <Redirect to={to} />;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -572,19 +582,25 @@ function AdminInstanceUpdatePage({
|
|||||||
{...rest}
|
{...rest}
|
||||||
instanceId={id}
|
instanceId={id}
|
||||||
onLoadError={(error: HttpError<MerchantBackend.ErrorDetail>) => {
|
onLoadError={(error: HttpError<MerchantBackend.ErrorDetail>) => {
|
||||||
return (
|
const notif =
|
||||||
<Fragment>
|
error.type === ErrorType.TIMEOUT
|
||||||
<NotificationCard
|
? {
|
||||||
notification={{
|
message: i18n.str`The request to the backend take too long and was cancelled`,
|
||||||
|
description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
|
||||||
|
type: "ERROR" as const,
|
||||||
|
}
|
||||||
|
: {
|
||||||
message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
|
message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
|
||||||
description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
|
description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
|
||||||
details:
|
details:
|
||||||
error.clientError || error.serverError
|
error.clientError || error.serverError
|
||||||
? error.error?.detail
|
? error.error?.detail
|
||||||
: undefined,
|
: undefined,
|
||||||
type: "ERROR",
|
type: "ERROR" as const,
|
||||||
}}
|
};
|
||||||
/>
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<NotificationCard notification={notif} />
|
||||||
<LoginPage onConfirm={updateLoginStatus} />
|
<LoginPage onConfirm={updateLoginStatus} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
import { HttpStatusCode } from "@gnu-taler/taler-util";
|
import { HttpStatusCode } from "@gnu-taler/taler-util";
|
||||||
import { base64encode } from "./base64.js";
|
import { base64encode } from "./base64.js";
|
||||||
|
|
||||||
|
export enum ErrorType {
|
||||||
|
CLIENT, SERVER, TIMEOUT, UNEXPECTED
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param baseUrl URL where the service is located
|
* @param baseUrl URL where the service is located
|
||||||
@ -39,7 +43,7 @@ export async function defaultRequestHandler<T>(
|
|||||||
|
|
||||||
const requestMethod = options?.method ?? "GET";
|
const requestMethod = options?.method ?? "GET";
|
||||||
const requestBody = options?.data;
|
const requestBody = options?.data;
|
||||||
const requestTimeout = options?.timeout ?? 2 * 1000;
|
const requestTimeout = options?.timeout ?? 5 * 1000;
|
||||||
const requestParams = options.params ?? {};
|
const requestParams = options.params ?? {};
|
||||||
|
|
||||||
const _url = new URL(`${baseUrl}${endpoint}`);
|
const _url = new URL(`${baseUrl}${endpoint}`);
|
||||||
@ -85,10 +89,13 @@ export async function defaultRequestHandler<T>(
|
|||||||
hasToken: !!options.token,
|
hasToken: !!options.token,
|
||||||
status: 0,
|
status: 0,
|
||||||
};
|
};
|
||||||
const error: HttpResponseUnexpectedError = {
|
const error: HttpRequestTimeoutError = {
|
||||||
|
clientError: true,
|
||||||
|
isNotfound: false,
|
||||||
|
isUnauthorized: false,
|
||||||
|
error: undefined,
|
||||||
info,
|
info,
|
||||||
status: 0,
|
type: ErrorType.TIMEOUT,
|
||||||
error: ex,
|
|
||||||
message: "Request timeout",
|
message: "Request timeout",
|
||||||
};
|
};
|
||||||
throw new RequestError(error);
|
throw new RequestError(error);
|
||||||
@ -166,32 +173,50 @@ export interface WithPagination {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type HttpError<ErrorDetail> =
|
export type HttpError<ErrorDetail> =
|
||||||
|
| HttpRequestTimeoutError
|
||||||
| HttpResponseClientError<ErrorDetail>
|
| HttpResponseClientError<ErrorDetail>
|
||||||
| HttpResponseServerError<ErrorDetail>
|
| HttpResponseServerError<ErrorDetail>
|
||||||
| HttpResponseUnexpectedError;
|
| HttpResponseUnexpectedError;
|
||||||
|
|
||||||
|
|
||||||
export interface HttpResponseServerError<ErrorDetail> {
|
export interface HttpResponseServerError<ErrorDetail> {
|
||||||
ok?: false;
|
ok?: false;
|
||||||
loading?: false;
|
loading?: false;
|
||||||
clientError?: false;
|
clientError?: false;
|
||||||
serverError: true;
|
serverError: true;
|
||||||
|
type: ErrorType.SERVER,
|
||||||
|
|
||||||
error?: ErrorDetail;
|
error: ErrorDetail;
|
||||||
status: HttpStatusCode;
|
status: HttpStatusCode;
|
||||||
message: string;
|
message: string;
|
||||||
info?: RequestInfo;
|
info?: RequestInfo;
|
||||||
}
|
}
|
||||||
|
interface HttpRequestTimeoutError {
|
||||||
|
ok?: false;
|
||||||
|
loading?: false;
|
||||||
|
clientError: true;
|
||||||
|
serverError?: false;
|
||||||
|
type: ErrorType.TIMEOUT,
|
||||||
|
|
||||||
|
info?: RequestInfo;
|
||||||
|
error: undefined,
|
||||||
|
|
||||||
|
isUnauthorized: false;
|
||||||
|
isNotfound: false;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
interface HttpResponseClientError<ErrorDetail> {
|
interface HttpResponseClientError<ErrorDetail> {
|
||||||
ok?: false;
|
ok?: false;
|
||||||
loading?: false;
|
loading?: false;
|
||||||
clientError: true;
|
clientError: true;
|
||||||
serverError?: false;
|
serverError?: false;
|
||||||
|
type: ErrorType.CLIENT,
|
||||||
|
|
||||||
info?: RequestInfo;
|
info?: RequestInfo;
|
||||||
isUnauthorized: boolean;
|
isUnauthorized: boolean;
|
||||||
isNotfound: boolean;
|
isNotfound: boolean;
|
||||||
status: HttpStatusCode;
|
status: HttpStatusCode;
|
||||||
error?: ErrorDetail;
|
error: ErrorDetail;
|
||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +225,7 @@ interface HttpResponseUnexpectedError {
|
|||||||
loading?: false;
|
loading?: false;
|
||||||
clientError?: false;
|
clientError?: false;
|
||||||
serverError?: false;
|
serverError?: false;
|
||||||
|
type: ErrorType.UNEXPECTED,
|
||||||
|
|
||||||
info?: RequestInfo;
|
info?: RequestInfo;
|
||||||
status?: HttpStatusCode;
|
status?: HttpStatusCode;
|
||||||
@ -208,10 +234,15 @@ interface HttpResponseUnexpectedError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RequestError<ErrorDetail> extends Error {
|
export class RequestError<ErrorDetail> extends Error {
|
||||||
|
/**
|
||||||
|
* @deprecated use cause
|
||||||
|
*/
|
||||||
info: HttpError<ErrorDetail>;
|
info: HttpError<ErrorDetail>;
|
||||||
|
cause: HttpError<ErrorDetail>;
|
||||||
constructor(d: HttpError<ErrorDetail>) {
|
constructor(d: HttpError<ErrorDetail>) {
|
||||||
super(d.message)
|
super(d.message)
|
||||||
this.info = d
|
this.info = d
|
||||||
|
this.cause = d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,6 +308,7 @@ async function buildRequestFailed<ErrorDetail>(
|
|||||||
clientError: true,
|
clientError: true,
|
||||||
isNotfound: status === 404,
|
isNotfound: status === 404,
|
||||||
isUnauthorized: status === 401,
|
isUnauthorized: status === 401,
|
||||||
|
type: ErrorType.CLIENT,
|
||||||
status,
|
status,
|
||||||
info,
|
info,
|
||||||
message: data?.hint,
|
message: data?.hint,
|
||||||
@ -287,6 +319,7 @@ async function buildRequestFailed<ErrorDetail>(
|
|||||||
if (status && status >= 500 && status < 600) {
|
if (status && status >= 500 && status < 600) {
|
||||||
const error: HttpResponseServerError<ErrorDetail> = {
|
const error: HttpResponseServerError<ErrorDetail> = {
|
||||||
serverError: true,
|
serverError: true,
|
||||||
|
type: ErrorType.SERVER,
|
||||||
status,
|
status,
|
||||||
info,
|
info,
|
||||||
message: `${data?.hint} (code ${data?.code})`,
|
message: `${data?.hint} (code ${data?.code})`,
|
||||||
@ -296,6 +329,7 @@ async function buildRequestFailed<ErrorDetail>(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
info,
|
info,
|
||||||
|
type: ErrorType.UNEXPECTED,
|
||||||
status,
|
status,
|
||||||
error: {},
|
error: {},
|
||||||
message: "NOT DEFINED",
|
message: "NOT DEFINED",
|
||||||
@ -304,6 +338,7 @@ async function buildRequestFailed<ErrorDetail>(
|
|||||||
const error: HttpResponseUnexpectedError = {
|
const error: HttpResponseUnexpectedError = {
|
||||||
info,
|
info,
|
||||||
status,
|
status,
|
||||||
|
type: ErrorType.UNEXPECTED,
|
||||||
error: ex,
|
error: ex,
|
||||||
message: "NOT DEFINED",
|
message: "NOT DEFINED",
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user