commit 96c42335e8551e5d84284f4c06ce30b9e2259a85 parent b133f5233738442ac98092f914a728ae7ed578a1 Author: Florian Dold <florian@dold.me> Date: Fri, 29 May 2026 19:58:50 +0200 work around typing issues in some UI packages Diffstat:
27 files changed, 140 insertions(+), 76 deletions(-)
diff --git a/packages/aml-backoffice-ui/src/hooks/decisions.ts b/packages/aml-backoffice-ui/src/hooks/decisions.ts @@ -13,17 +13,21 @@ You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { useState } from "preact/hooks"; // FIX default import https://github.com/microsoft/TypeScript/issues/49189 import { AmlDecision, CustomerAccountSummary, + HttpStatusCode, OfficerSession, + OperationFail, + OperationOk, opFixedSuccess, + TalerError, TalerExchangeResultByMethod2, TalerHttpError, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { buildPaginatedResult, ListPointer, @@ -219,7 +223,18 @@ export function useAccountDecisions(accountStr: string) { * @param args * @returns */ -export function useAccountActiveDecision(accountStr?: string) { +export function useAccountActiveDecision(accountStr?: string): + | OperationFail< + | HttpStatusCode.Forbidden + | HttpStatusCode.NotFound + | HttpStatusCode.Conflict + > + | TalerError<{ + requestUrl: string; + requestMethod: string; + }> + | OperationOk<AmlDecision | undefined> + | undefined { const officer = useOfficer(); const session = accountStr !== undefined && officer.state === "ready" @@ -251,6 +266,8 @@ export function useAccountActiveDecision(accountStr?: string) { if (data === undefined) return undefined; if (data.type !== "ok") return data; - if (!data.body.records.length) return opFixedSuccess(undefined); - return opFixedSuccess(data.body.records[0]); + if (!data.body.records.length) { + return opFixedSuccess(dummyHttpResponse, undefined); + } + return opFixedSuccess(dummyHttpResponse, data.body.records[0]); } diff --git a/packages/aml-backoffice-ui/src/hooks/officer.ts b/packages/aml-backoffice-ui/src/hooks/officer.ts @@ -20,21 +20,22 @@ import { EddsaPrivP, HttpStatusCode, LockedAccount, - OfficerSession, OfficerId, + OfficerSession, OperationFail, OperationOk, buildCodecForObject, codecForAbsoluteTime, codecForString, + codecOptional, createNewOfficerAccount, decodeCrock, encodeCrock, opFixedSuccess, opKnownFailure, unlockOfficerAccount, - codecOptional, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { buildStorageKey, useExchangeApiContext, @@ -155,7 +156,8 @@ export function useOfficer(): OfficerState { const strKey = encodeCrock(signingKey); sessionStorage.update({ id, strKey, unlocked: AbsoluteTime.now() }); - return opFixedSuccess(id); + // FIXME: This is really not the right type to use here. + return opFixedSuccess(dummyHttpResponse, id); }, }; } else if (officer?.session === undefined) { @@ -172,7 +174,7 @@ export function useOfficer(): OfficerState { state: "locked", forget: () => { officerStorage.reset(); - return opFixedSuccess(undefined); + return opFixedSuccess(dummyHttpResponse, undefined); }, tryUnlock: async (pwd: string) => { try { @@ -183,9 +185,9 @@ export function useOfficer(): OfficerState { strKey: encodeCrock(ac.signingKey), unlocked: AbsoluteTime.now(), }); - return opFixedSuccess(undefined); + return opFixedSuccess(dummyHttpResponse, undefined); } catch (e) { - const d = opKnownFailure(HttpStatusCode.Forbidden); + const d = opKnownFailure(dummyHttpResponse, HttpStatusCode.Forbidden); return d; } }, @@ -203,12 +205,12 @@ export function useOfficer(): OfficerState { expiration, lock: () => { sessionStorage.reset(); - return opFixedSuccess(undefined); + return opFixedSuccess(dummyHttpResponse, undefined); }, forget: () => { officerStorage.reset(); sessionStorage.reset(); - return opFixedSuccess(undefined); + return opFixedSuccess(dummyHttpResponse, undefined); }, }; } diff --git a/packages/aml-backoffice-ui/src/hooks/server-info.ts b/packages/aml-backoffice-ui/src/hooks/server-info.ts @@ -27,6 +27,7 @@ import { TalerHttpError, } from "@gnu-taler/taler-util"; // FIX default import https://github.com/microsoft/TypeScript/issues/49189 +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { useExchangeApiContext } from "@gnu-taler/web-util/browser"; import { endOfYear, setYear, startOfYear } from "date-fns"; import _useSWR, { SWRHook } from "swr"; @@ -76,7 +77,7 @@ export function useTopsServerStatistics() { async function fetcher([officer]: [OfficerSession]) { const final = await fetchTopsInfoFromServer(api, officer); - return opFixedSuccess(final); + return opFixedSuccess(dummyHttpResponse, final); } const { data, error } = useSWR< @@ -114,7 +115,7 @@ export function useVqfServerStatistics(year: number) { const final = await fetchVqfInfoFromServer(api, officer, jan_1st, dec_31st); - return opFixedSuccess(final); + return opFixedSuccess(dummyHttpResponse, final); } const { data, error } = useSWR< diff --git a/packages/aml-backoffice-ui/src/pages/decision/Summary.tsx b/packages/aml-backoffice-ui/src/pages/decision/Summary.tsx @@ -23,6 +23,7 @@ import { TalerError, TOPS_AmlEventsName, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { Attention, ButtonBetter, @@ -171,7 +172,8 @@ export function Summary({ async (req) => { if (requiresConfirmation && !submitConfirmation) { setSubmitConfirmation(true); - return opEmptySuccess(); + // FIXME: This is not the right type to use here. + return opEmptySuccess(dummyHttpResponse); } return lib.exchange.makeAmlDesicion(session, req); }, diff --git a/packages/bank-ui/src/hooks/account.ts b/packages/bank-ui/src/hooks/account.ts @@ -18,7 +18,6 @@ import { AccessToken, HttpStatusCode, OperationFail, - OperationOk, TalerCorebankApi, TalerCoreBankResultByMethod, TalerError, @@ -28,6 +27,7 @@ import { useState } from "preact/hooks"; import { useSessionState } from "./session.js"; // FIX default import https://github.com/microsoft/TypeScript/issues/49189 +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { PaginatedResult, useAsync, @@ -246,6 +246,7 @@ export function buildPaginatedResult<DataType, OffsetId>( type: "ok", case: "ok", body: result, + response: dummyHttpResponse, loadNext: isLastPage ? undefined : () => { diff --git a/packages/bank-ui/src/hooks/regional.ts b/packages/bank-ui/src/hooks/regional.ts @@ -33,6 +33,7 @@ import { assertUnreachable, opFixedSuccess, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { useBankCoreApiContext } from "@gnu-taler/web-util/browser"; import { useState } from "preact/hooks"; import _useSWR, { SWRHook, mutate } from "swr"; @@ -184,7 +185,7 @@ function buildEstimatorWithTheBackend( const debit = Amounts.parseOrThrow(resp.body.amount_debit); const beforeFee = Amounts.add(credit, fee).amount; - return opFixedSuccess({ + return opFixedSuccess(dummyHttpResponse, { debit, beforeFee, credit, @@ -360,7 +361,7 @@ export function useOnePendingCashouts(account: string) { } const pendingCashout = list.body.cashouts.length > 0 ? list.body.cashouts[0] : undefined; - if (!pendingCashout) return opFixedSuccess(undefined); + if (!pendingCashout) return opFixedSuccess(dummyHttpResponse, undefined); const cashoutInfo = await api.getCashoutById( { username, token }, pendingCashout.cashout_id, @@ -368,7 +369,7 @@ export function useOnePendingCashouts(account: string) { if (cashoutInfo.type !== "ok") { return cashoutInfo; } - return opFixedSuccess({ + return opFixedSuccess(dummyHttpResponse, { ...cashoutInfo.body, id: pendingCashout.cashout_id, }); @@ -431,7 +432,7 @@ export function useCashouts(account: string) { }), ); const cashouts = all.filter(notUndefined); - return opFixedSuccess({ cashouts }); + return opFixedSuccess(dummyHttpResponse, { cashouts }); } const { data, error } = useSWR< | OperationOk<{ cashouts: CashoutWithId[] }> diff --git a/packages/bank-ui/src/pages/ConversionRateClassDetails.tsx b/packages/bank-ui/src/pages/ConversionRateClassDetails.tsx @@ -27,6 +27,13 @@ import { Fragment, h, VNode } from "preact"; import { useEffect, useState } from "preact/hooks"; import { + AccessToken, + AmountJson, + opFixedSuccess, + TalerErrorCode, +} from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; +import { FormErrors, FormStatus, FormValues, @@ -47,10 +54,6 @@ import { RecursivePartial, undefinedIfEmpty } from "../utils.js"; import { DescribeConversion } from "./admin/ConversionClassList.js"; import { doAutoFocus, InputAmount } from "./PaytoWireTransferForm.js"; import { ConversionForm } from "./regional/ConversionConfig.js"; -import { AccessToken } from "@gnu-taler/taler-util"; -import { TalerErrorCode } from "@gnu-taler/taler-util"; -import { opFixedSuccess } from "@gnu-taler/taler-util"; -import { AmountJson } from "@gnu-taler/taler-util"; const TALER_SCREEN_ID = 11; interface Props { @@ -924,7 +927,7 @@ function TestConversionClass({ return respCashout; } const cashout = respCashout.body; - return opFixedSuccess({ cashin, cashout }); + return opFixedSuccess(dummyHttpResponse, { cashin, cashout }); }, !in_amount || !!error ? undefined : [in_amount], ); diff --git a/packages/bank-ui/src/pages/LoginForm.tsx b/packages/bank-ui/src/pages/LoginForm.tsx @@ -22,7 +22,9 @@ import { TokenRequest, assertUnreachable, createRFC8959AccessTokenEncoded, + opEmptySuccess, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { Attention, ButtonBetter, @@ -41,7 +43,6 @@ import { undefinedIfEmpty } from "../utils.js"; import { doAutoFocus } from "./PaytoWireTransferForm.js"; import { USERNAME_REGEX } from "./RegistrationPage.js"; import { SolveMFAChallenges } from "./SolveMFA.js"; -import { opEmptySuccess } from "@gnu-taler/taler-util"; const TALER_SCREEN_ID = 104; @@ -95,7 +96,7 @@ export function LoginForm({ i18n.str`logout`, async () => { session.logOut(); - return opEmptySuccess(); + return opEmptySuccess(dummyHttpResponse); }, [], ); diff --git a/packages/bank-ui/src/pages/SolveMFA.tsx b/packages/bank-ui/src/pages/SolveMFA.tsx @@ -9,6 +9,7 @@ import { TanChannel, TranslatedString, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { ButtonBetter, LocalNotificationBanner, @@ -323,7 +324,7 @@ export function SolveMFAChallenges({ ch, expiration: AbsoluteTime.never(), }); - return opEmptySuccess(); + return opEmptySuccess(dummyHttpResponse); }, ); selectChallenge.onFail = (fail) => { diff --git a/packages/bank-ui/src/pages/admin/DownloadStats.tsx b/packages/bank-ui/src/pages/admin/DownloadStats.tsx @@ -22,6 +22,7 @@ import { TalerCorebankApi, opFixedSuccess, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { Attention, ButtonBetter, @@ -553,7 +554,7 @@ async function fetchAllStatus( return acc + row.join(",") + "\n"; }, ""); - return opFixedSuccess(csv); + return opFixedSuccess(dummyHttpResponse, csv); } type JustData = Omit<Omit<Omit<TableRow, "metric">, "date">, "reference">; diff --git a/packages/bank-ui/src/pages/regional/ConversionConfig.tsx b/packages/bank-ui/src/pages/regional/ConversionConfig.tsx @@ -59,6 +59,7 @@ import { InputAmount } from "../PaytoWireTransferForm.js"; import { ProfileNavigation } from "../ProfileNavigation.js"; import { TalerErrorCode, opFixedSuccess } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { DescribeConversion } from "../admin/ConversionClassList.js"; const TALER_SCREEN_ID = 126; @@ -188,7 +189,7 @@ function useComponentState({ return respCashout; } const cashout = respCashout.body; - return opFixedSuccess({ cashin, cashout }); + return opFixedSuccess(dummyHttpResponse, { cashin, cashout }); }, !in_amount || status.status === "fail" ? undefined : [in_amount], ); diff --git a/packages/bank-ui/src/pages/regional/CreateCashout.tsx b/packages/bank-ui/src/pages/regional/CreateCashout.tsx @@ -48,6 +48,7 @@ import { TalerCorebankApi, opFixedSuccess, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { useAccountDetails } from "../../hooks/account.js"; import { TransCalc, @@ -276,7 +277,7 @@ function CreateCashoutInternal({ ? calculateFromDebit(input, fee) : calculateFromCredit(input, fee); } else { - return opFixedSuccess(zeroCalc); + return opFixedSuccess(dummyHttpResponse, zeroCalc); } }, [form.isDebit ?? false, inputAmount, sellFee], diff --git a/packages/kyc-ui/src/hooks/kyc.ts b/packages/kyc-ui/src/hooks/kyc.ts @@ -16,16 +16,16 @@ import { AccessToken, HttpStatusCode, - KycProcessClientInformationWithEtag, opFixedSuccess, TalerError, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { useAsync, useExchangeApiContext, useLongPolling, } from "@gnu-taler/web-util/browser"; -import _useSWR, { SWRHook, mutate } from "swr"; +import _useSWR, { mutate, SWRHook } from "swr"; const useSWR = _useSWR as unknown as SWRHook; export function revalidateKycInfo() { @@ -67,7 +67,7 @@ export function useKycInfo(token?: AccessToken) { timeoutMs: 5000, }); if (res.type === "fail" && res.case === HttpStatusCode.NotModified) { - return opFixedSuccess(result.body); + return opFixedSuccess(dummyHttpResponse, result.body); } return res; }, diff --git a/packages/kyc-ui/src/pages/TriggerKyc.tsx b/packages/kyc-ui/src/pages/TriggerKyc.tsx @@ -42,6 +42,7 @@ import { import { Fragment, h, VNode } from "preact"; import { useMemo } from "preact/hooks"; import { useFormMeta } from "../../../web-util/src/hooks/useForm.js"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; type FormType = { amount: AmountJson; @@ -111,7 +112,7 @@ export function TriggerKyc({ onKycStarted }: Props): VNode { }; const resp = await lib.exchange.notifyKycBalanceLimit(limit); if (resp.type === "ok") { - return opKnownFailure(HttpStatusCode.NoContent); + return opKnownFailure(dummyHttpResponse, HttpStatusCode.NoContent); } if (resp.case === HttpStatusCode.UnavailableForLegalReasons) { const paytoHash = resp.body.h_payto; @@ -125,7 +126,7 @@ export function TriggerKyc({ onKycStarted }: Props): VNode { }); switch (statusRes.case) { case HttpStatusCode.Accepted: - return opFixedSuccess(statusRes.body); + return opFixedSuccess(dummyHttpResponse, statusRes.body); } return statusRes; } diff --git a/packages/merchant-backoffice-ui/src/hooks/order.ts b/packages/merchant-backoffice-ui/src/hooks/order.ts @@ -26,6 +26,7 @@ import { TalerHttpError, TalerMerchantManagementResultByMethod, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { buildPaginatedResult, LONG_POLL_DELAY, @@ -177,7 +178,7 @@ export function useInstanceOrders(args?: InstanceOrderFilter) { ? latestStatus.body.orders : [...result.body.orders, ...latestStatus.body.orders]; - const newResult = opFixedSuccess({ orders: merged }); + const newResult = opFixedSuccess(dummyHttpResponse, { orders: merged }); mutate(newResult, { revalidate: false }); return newResult; }, diff --git a/packages/merchant-backoffice-ui/src/hooks/product.ts b/packages/merchant-backoffice-ui/src/hooks/product.ts @@ -32,6 +32,7 @@ import { import _useSWR, { SWRHook, mutate } from "swr"; import { useSessionContext } from "../context/session.js"; import { PAGINATED_LIST_REQUEST } from "../utils/constants.js"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; const useSWR = _useSWR as unknown as SWRHook; export type ProductWithId = TalerMerchantApi.ProductDetailResponse & { @@ -76,7 +77,7 @@ export function useInstanceProducts() { ); const products = all.filter(notUndefined); - return opFixedSuccess({ products }); + return opFixedSuccess(dummyHttpResponse, { products }); } const { data, error } = useSWR< @@ -112,7 +113,7 @@ export function useInstanceProductsFromIds(ids: string[]) { ); const products = all.filter(notUndefined); - return opFixedSuccess(products); + return opFixedSuccess(dummyHttpResponse, products); } const { data, error } = useSWR< diff --git a/packages/merchant-backoffice-ui/src/hooks/statistics.ts b/packages/merchant-backoffice-ui/src/hooks/statistics.ts @@ -25,6 +25,7 @@ import { TalerHttpError, TalerMerchantManagementErrorsByMethod, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import _useSWR, { mutate, SWRHook } from "swr"; import { useSessionContext } from "../context/session.js"; const useSWR = _useSWR as unknown as SWRHook; @@ -89,7 +90,7 @@ export function useInstanceStatisticsCounter() { result.set(r, resp[idx].body); } }); - return opFixedSuccess(result); + return opFixedSuccess(dummyHttpResponse, result); } const { data, error } = useSWR< @@ -137,7 +138,7 @@ export function useInstanceStatisticsAmount() { result.set(r, resp[idx].body); } }); - return opFixedSuccess(result); + return opFixedSuccess(dummyHttpResponse, result); } const { data, error } = useSWR< diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx @@ -29,6 +29,7 @@ import { opFixedSuccess, TalerMerchantApi, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { ButtonBetterBulma, LocalNotificationBannerBulma, @@ -205,9 +206,9 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode { } return tokenResp; } - return opFixedSuccess(tokenResp.body); + return opFixedSuccess(dummyHttpResponse, tokenResp.body); } - return opEmptySuccess(); + return opEmptySuccess(dummyHttpResponse); }, hasErrors ? undefined : [session.token, data, []], ); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx @@ -29,6 +29,7 @@ import { assertUnreachable, opEmptySuccess, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { ButtonBetterBulma, LocalNotificationBannerBulma, @@ -389,7 +390,7 @@ export function CreatePage({ onCreated, onBack }: Props): VNode { payto_uri: Paytos.toFullString(revenuePayto), }); setRevenuePayto(undefined); - return opEmptySuccess(); + return opEmptySuccess(dummyHttpResponse); }, [], )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx @@ -31,7 +31,10 @@ import { TalerRevenueHttpClient, opFixedSuccess, } from "@gnu-taler/taler-util"; -import { type HttpRequestLibrary } from "@gnu-taler/taler-util/http"; +import { + dummyHttpResponse, + type HttpRequestLibrary, +} from "@gnu-taler/taler-util/http"; import { BrowserFetchHttpLib } from "@gnu-taler/web-util/browser"; import { Fragment, VNode, h } from "preact"; import { CreatePage } from "./CreatePage.js"; @@ -105,6 +108,7 @@ export async function testRevenueAPI( type: "fail" as const, case: TestRevenueErrorType.CANT_VALIDATE, detail: undefined, + response: dummyHttpResponse, }; } const str = resp.body.credit_account as Paytos.FullPaytoString; @@ -114,9 +118,10 @@ export async function testRevenueAPI( type: "fail" as const, case: TestRevenueErrorType.BAD_PAYTO, detail: undefined, + response: dummyHttpResponse, }; } - return opFixedSuccess(uri.value); + return opFixedSuccess(dummyHttpResponse, uri.value); } catch (err) { // FIXME: should we return some other error code here? throw err; diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx @@ -29,6 +29,7 @@ import { assertUnreachable, opEmptySuccess, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { ButtonBetterBulma, LocalNotificationBanner, @@ -50,13 +51,13 @@ import { InputToggle } from "../../../../components/form/InputToggle.js"; import { FragmentPersonaFlag } from "../../../../components/menu/SideBar.js"; import { CompareAccountsModal } from "../../../../components/modal/index.js"; import { SolveMFAChallenges } from "../../../../components/SolveMFA.js"; +import { Tooltip } from "../../../../components/Tooltip.js"; import { useSessionContext } from "../../../../context/session.js"; import { WithId } from "../../../../declaration.js"; import { UIElement, usePreference } from "../../../../hooks/preference.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; -import { TestRevenueErrorType, testRevenueAPI } from "../create/index.js"; -import { Tooltip } from "../../../../components/Tooltip.js"; import { maybeTryFirstMFA } from "../create/CreatePage.js"; +import { TestRevenueErrorType, testRevenueAPI } from "../create/index.js"; import { UnableToUseBankAccountWarning } from "../list/index.js"; const TALER_SCREEN_ID = 36; @@ -219,7 +220,7 @@ export function UpdatePage({ account, onUpdated, onBack }: Props): VNode { const resp = await lib.instance.updateBankAccount(token, id, data); if (resp.type === "fail") return resp; } - return opEmptySuccess(); + return opEmptySuccess(dummyHttpResponse); } const mfa = useChallengeHandler(); @@ -472,7 +473,7 @@ export function UpdatePage({ account, onUpdated, onBack }: Props): VNode { payto_uri: Paytos.toFullString(revenuePayto), }); setRevenuePayto(undefined); - return opEmptySuccess(); + return opEmptySuccess(dummyHttpResponse); }, [], )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/password/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/password/index.tsx @@ -21,6 +21,7 @@ import { assertUnreachable, opKnownFailure, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { LocalNotificationBannerBulma, useChallengeHandler, @@ -38,8 +39,8 @@ import { } from "../../../hooks/instance.js"; import { LoginPage, TEMP_TEST_TOKEN } from "../../login/index.js"; import { NotFoundPageOrAdminCreate } from "../../notfound/index.js"; -import { DetailPage } from "./DetailPage.js"; import { maybeTryFirstMFA } from "../accounts/create/CreatePage.js"; +import { DetailPage } from "./DetailPage.js"; const TALER_SCREEN_ID = 54; @@ -90,7 +91,7 @@ export default function PasswordPage({ onCancel, onChange }: Props): VNode { if (created.type === "fail") { switch (created.case) { case HttpStatusCode.Unauthorized: - return opKnownFailure("bad-current-pwd"); + return opKnownFailure(dummyHttpResponse, "bad-current-pwd"); case HttpStatusCode.NotFound: return created; case HttpStatusCode.Accepted: diff --git a/packages/merchant-backoffice-ui/src/paths/instance/pots/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/pots/update/UpdatePage.tsx @@ -26,6 +26,7 @@ import { HttpStatusCode, InternationalizationAPI, PotDetailResponse, + Result, TalerMerchantApi, TranslatedString, } from "@gnu-taler/taler-util"; @@ -77,8 +78,10 @@ export function UpdatePage({ moneyPot, onUpdated, onBack }: Props): VNode { i18n: InternationalizationAPI, ): TranslatedString | undefined { const s = Amounts.parseWithError(a); - if (s.type === "ok") return undefined; - switch (s.case) { + if (Result.isOk(s)) { + return undefined; + } + switch (s.error) { case AmountParseError.MISSING_CURRENCY: return i18n.str`Missing currency name`; case AmountParseError.BAD_CURRENCY: @@ -89,6 +92,10 @@ export function UpdatePage({ moneyPot, onUpdated, onBack }: Props): VNode { return i18n.str`The value is too high`; case AmountParseError.TOO_PRECISE: return i18n.str`The value is too precise`; + case AmountParseError.CURRENCY_TOO_LONG: + return i18n.str`Currency is too long`; + default: + assertUnreachable(s.error); } } diff --git a/packages/taler-util/src/http-common.ts b/packages/taler-util/src/http-common.ts @@ -537,3 +537,22 @@ export function getDefaultHeaders(method: string): Record<string, string> { return headers; } + +/** + * Dummy response, do not use. + */ +export const dummyHttpResponse: HttpResponse = { + async bytes() { + return new Uint8Array(); + }, + headers: new HeadersImpl(), + async json() { + return {}; + }, + requestMethod: "dummy", + requestUrl: "dummy", + status: 0, + async text() { + return ""; + }, +}; diff --git a/packages/taler-wallet-webextension/src/wallet/AddContact/state.ts b/packages/taler-wallet-webextension/src/wallet/AddContact/state.ts @@ -14,13 +14,14 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { ContactEntry, opFixedSuccess, opKnownFailure, } from "@gnu-taler/taler-util"; -import { useCallback, useState } from "preact/hooks"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { useState } from "preact/hooks"; import { useBackendContext } from "../../context/backend.js"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { withSafe } from "../../mui/handlers.js"; @@ -55,8 +56,8 @@ export function useComponentState({ ); const result = found !== -1 - ? opKnownFailure("already-added" as const) - : opFixedSuccess("ok" as const); + ? opKnownFailure(dummyHttpResponse, "already-added" as const) + : opFixedSuccess(dummyHttpResponse, "ok" as const); const [inputError, setInputError] = useState<string>(); return { diff --git a/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts b/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts @@ -22,6 +22,7 @@ import { opKnownFailureWithBody, succeedOrThrow, } from "@gnu-taler/taler-util"; +import { dummyHttpResponse } from "@gnu-taler/taler-util/http"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { BrowserFetchHttpLib } from "@gnu-taler/web-util/browser"; import { useCallback, useEffect, useState } from "preact/hooks"; @@ -79,36 +80,24 @@ export function useComponentState({ async function checkExchangeBaseUrl(str: string) { const baseUrl = urlFromInput(str); if (baseUrl.protocol !== "http:" && baseUrl.protocol !== "https:") { - return opKnownFailure("invalid-protocol" as const); + return opKnownFailure( + dummyHttpResponse, + "invalid-protocol" as const, + ); } const found = used.findIndex( (e) => e.exchangeBaseUrl === baseUrl.href, ); if (found !== -1) { - return opKnownFailure("already-active" as const); + return opKnownFailure(dummyHttpResponse, "already-active" as const); } - - /** - * FIXME: For some reason typescript doesn't like the next BrowserFetchHttpLib - * - * │ src/wallet/AddExchange/state.ts(68,63): error TS2345: Argument of type 'BrowserFetchHttpLib' is not assignable to parameter of ty - * │ Types of property 'fetch' are incompatible. - * │ Type '(requestUrl: string, options?: HttpRequestOptions | undefined) => Promise<HttpResponse>' is not assignable to type '(ur - * │ Types of parameters 'options' and 'opt' are incompatible. - * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/http-common", { wi - * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/http-common", { - * │ Types of property 'cancellationToken' are incompatible. - * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/Cancellation - * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/Cancellati - * │ Types have separate declarations of a private property '_isCancelled'. - * - */ const api = new TalerExchangeHttpClient(baseUrl.href, { httpClient: new BrowserFetchHttpLib(), }); const config = succeedOrThrow(await api.getConfig()); if (currency !== undefined && currency !== config.currency) { return opKnownFailureWithBody( + dummyHttpResponse, "invalid-currency" as const, config.currency, ); diff --git a/packages/web-util/src/utils/buildPaginatedResult.ts b/packages/web-util/src/utils/buildPaginatedResult.ts @@ -1,5 +1,6 @@ import { assertUnreachable, OperationOk } from "@gnu-taler/taler-util"; import { useState } from "preact/hooks"; +import { dummyHttpResponse } from "../../../taler-util/src/http-common.js"; export type PaginationControl = { loadNext?(): void; @@ -28,10 +29,12 @@ export function buildPaginatedResult<R>( isLastPage, isFirstPage, } = __compute_for_ui(data, offset, PAGINATED_LIST_REQUEST); + // FIXME: This should *not* be an HTTP result. return { type: "ok", case: "ok", body, + response: dummyHttpResponse, loadNext: isLastPage ? undefined : () => {