diff options
author | Sebastian <sebasjm@gmail.com> | 2024-03-21 12:11:31 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-03-26 16:57:55 -0300 |
commit | 8aa9ce6d20b41b7eb9b438a56ccd34cb0da35f80 (patch) | |
tree | 5cec8219a136469f2c689c47a74b28e52eb5992b /packages/web-util/src/context/bank-api.ts | |
parent | 5a1f528d8806bcb15d5c4c8364554502c11931a7 (diff) | |
download | wallet-core-8aa9ce6d20b41b7eb9b438a56ccd34cb0da35f80.tar.xz |
wip
Diffstat (limited to 'packages/web-util/src/context/bank-api.ts')
-rw-r--r-- | packages/web-util/src/context/bank-api.ts | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/packages/web-util/src/context/bank-api.ts b/packages/web-util/src/context/bank-api.ts new file mode 100644 index 000000000..645eda183 --- /dev/null +++ b/packages/web-util/src/context/bank-api.ts @@ -0,0 +1,202 @@ +/* + This file is part of GNU Taler + (C) 2022-2024 Taler Systems S.A. + + 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. + + 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 + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { + CacheEvictor, + LibtoolVersion, + ObservabilityEvent, + ObservableHttpClientLibrary, + TalerAuthenticationHttpClient, + TalerBankConversionCacheEviction, + TalerBankConversionHttpClient, + TalerCoreBankCacheEviction, + TalerCoreBankHttpClient, + TalerCorebankApi, + TalerError +} from "@gnu-taler/taler-util"; +import { + ComponentChildren, + FunctionComponent, + VNode, + createContext, + h, +} from "preact"; +import { useContext, useEffect, useState } from "preact/hooks"; +import { APIClient, ActiviyTracker, BankLib, Suscriber } from "./activity.js"; +import { useTranslationContext } from "./translation.js"; +import { BrowserFetchHttpLib, ErrorLoading } from "../index.browser.js"; + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ + +export type BankContextType = { + url: URL; + config: TalerCorebankApi.Config; + lib: BankLib; + hints: VersionHint[]; + onActivity: Suscriber<ObservabilityEvent>; + cancelRequest: (eventId: string) => void; +}; + +// @ts-expect-error default value to undefined, should it be another thing? +const BankContext = createContext<BankContextType>(undefined); + +export const useBankCoreApiContext = (): BankContextType => useContext(BankContext); + +enum VersionHint { + NONE, +} + +type Evictors = { + conversion?: CacheEvictor<TalerBankConversionCacheEviction>; + bank?: CacheEvictor<TalerCoreBankCacheEviction>; +} + +type ConfigResult<T> = + | undefined + | { type: "ok"; config: T; hints: VersionHint[] } + | { type: "incompatible"; result: T; supported: string } + | { type: "error"; error: TalerError }; + +export const BankApiProvider = ({ + baseUrl, + children, + frameOnError, + evictors = {}, +}: { + baseUrl: URL; + children: ComponentChildren; + evictors?: Evictors, + frameOnError: FunctionComponent<{ children: ComponentChildren }>; +}): VNode => { + const [checked, setChecked] = useState<ConfigResult<TalerCorebankApi.Config>>(); + const { i18n } = useTranslationContext(); + + const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } = buildBankApiClient(baseUrl, evictors); + + useEffect(() => { + getRemoteConfig() + .then((config) => { + if (LibtoolVersion.compare(VERSION, config.version)) { + setChecked({ type: "ok", config, hints: [] }); + } else { + setChecked({ + type: "incompatible", + result: config, + supported: VERSION, + }); + } + }) + .catch((error: unknown) => { + if (error instanceof TalerError) { + setChecked({ type: "error", error }); + } + }); + }, []); + + if (checked === undefined) { + return h(frameOnError, { children: h("div", {}, "checking compatibility with server...") }); + } + if (checked.type === "error") { + return h(frameOnError, { + children: h(ErrorLoading, { error: checked.error, showDetail: true }), + }); + } + if (checked.type === "incompatible") { + return h(frameOnError, { + children: h( + "div", + {}, + i18n.str`The server version is not supported. Supported version "${checked.supported}", server version "${checked.result.version}"`, + ), + }); + } + + const value: BankContextType = { + url: baseUrl, + config: checked.config, + onActivity: onActivity, + lib, + cancelRequest, + hints: checked.hints, + }; + return h(BankContext.Provider, { + value, + children, + }); +}; + +function buildBankApiClient(url: URL, evictors: Evictors, +): APIClient<BankLib, TalerCorebankApi.Config> { + const httpFetch = new BrowserFetchHttpLib({ + enableThrottling: true, + requireTls: false, + }); + const tracker = new ActiviyTracker<ObservabilityEvent>(); + const httpLib = new ObservableHttpClientLibrary(httpFetch, { + observe(ev) { + tracker.notify(ev); + }, + }); + + const bank = new TalerCoreBankHttpClient( + url.href, + httpLib, + evictors.bank, + ); + const conversion = new TalerBankConversionHttpClient( + bank.getConversionInfoAPI().href, + httpLib, + evictors.conversion, + ); + const auth = (user: string) => + new TalerAuthenticationHttpClient( + bank.getAuthenticationAPI(user).href, + user, + httpLib, + ); + + async function getRemoteConfig() { + const resp = await bank.getConfig() + return resp.body + } + + return { + getRemoteConfig, + VERSION: bank.PROTOCOL_VERSION, + lib: { + bank, conversion, auth + }, + onActivity: tracker.subscribe, + cancelRequest: httpLib.cancelRequest, + }; +} + + +export const BankApiProviderTesting = ({ + children, + value, +}: { + value: BankContextType + children: ComponentChildren; +}): VNode => { + return h(BankContext.Provider, { + value, + children, + }); +} |