/*
This file is part of GNU Taler
(C) 2021-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
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
* @author Nic Eigel
*/
import {
HttpResponse,
HttpResponseOk,
RequestError,
RequestOptions,
useApiContext,
} from "@gnu-taler/web-util/browser";
import {useCallback, useEffect, useState} from "preact/hooks";
import {useSWRConfig} from "swr";
import { useBackendContext } from "../context/backend.js";
import { AuditorBackend } from "../declaration.js";
export function useMatchMutate(): (
re?: RegExp,
value?: unknown,
) => Promise {
const {cache, mutate} = useSWRConfig();
if (!(cache instanceof Map)) {
throw new Error(
"matchMutate requires the cache provider to be a Map instance",
);
}
return function matchRegexMutate(re?: RegExp) {
return mutate((key) => {
// evict if no key or regex === all
if (!key || !re) return true
// match string
if (typeof key === 'string' && re.test(key)) return true
// record or object have the path at [0]
if (typeof key === 'object' && re.test(key[0])) return true
//key didn't match regex
return false
}, undefined, {
revalidate: true,
});
};
}
const CHECK_CONFIG_INTERVAL_OK = 5 * 60 * 1000;
const CHECK_CONFIG_INTERVAL_FAIL = 2 * 1000;
export function useBackendConfig(): HttpResponse<
AuditorBackend.VersionResponse | undefined,
RequestError
> {
const {request} = useBackendBaseRequest();
type Type = AuditorBackend.VersionResponse;
type State = { data: HttpResponse>, timer: number }
const [result, setResult] = useState({data: {loading: true}, timer: 0});
useEffect(() => {
if (result.timer) {
clearTimeout(result.timer);
}
function tryConfig(): void {
request(`/config`)
.then((data) => {
const timer: any = setTimeout(() => {
tryConfig();
}, CHECK_CONFIG_INTERVAL_OK);
setResult({data, timer});
})
.catch((error) => {
const timer: any = setTimeout(() => {
tryConfig();
}, CHECK_CONFIG_INTERVAL_FAIL);
const data = error.cause;
setResult({data, timer});
});
}
tryConfig();
}, [request]);
return result.data;
}
export function useBackendToken(): HttpResponse<
AuditorBackend.VersionResponse,
RequestError
> {
const {request} = useBackendBaseRequest();
type Type = AuditorBackend.VersionResponse;
type State = { data: HttpResponse>, timer: number }
const [result, setResult] = useState({data: {loading: true}, timer: 0});
useEffect(() => {
if (result.timer) {
clearTimeout(result.timer);
}
function tryToken(): void {
request(`/monitoring/balances`)
.then((data) => {
const timer: any = setTimeout(() => {
tryToken();
}, CHECK_CONFIG_INTERVAL_OK);
setResult({data, timer});
})
.catch((error) => {
const timer: any = setTimeout(() => {
tryToken();
}, CHECK_CONFIG_INTERVAL_FAIL);
const data = error.cause;
setResult({data, timer});
});
}
tryToken();
}, [request]);
return result.data;
}
interface useBackendInstanceRequestType {
request: (
endpoint: string,
options?: RequestOptions,
) => Promise>;
fetcher: (endpoint: string) => Promise>;
multiFetcher: (params: string[]) => Promise[]>;
depositConfirmationFetcher: (
params: [
endpoint: string,
],
) => Promise>;
}
interface useBackendBaseRequestType {
request: (
endpoint: string,
options?: RequestOptions
) => Promise>;
}
type YesOrNo = "yes" | "no";
/**
*
* @param root the request is intended to the base URL and no the instance URL
* @returns request handler to
*/
//TODO: Add token
export function useBackendBaseRequest(): useBackendBaseRequestType {
const {url: backend} = useBackendContext();
const {request: requestHandler} = useApiContext();
//const { token } = useBackendTokenContext();
const token = "D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0";
const request = useCallback(
function requestImpl(
endpoint: string,
//todo: remove
options: RequestOptions = {},
): Promise> {
return requestHandler(backend, endpoint, {...options, token}).then(res => {
return res;
}).catch(err => {
throw err;
});
},
[backend],
);
return {request};
}
export function useBackendRequest(): useBackendInstanceRequestType {
const {url: rootBackendUrl} = useBackendContext();
// const {id} = useInstanceContext();
const {request: requestHandler} = useApiContext();
//TODO: check
const baseUrl = "http://localhost:8083/";
const token = "D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0";
const request = useCallback(
function requestImpl(
endpoint: string,
options: RequestOptions = {},
): Promise> {
return requestHandler(baseUrl, endpoint, {...options, token});
},
[baseUrl],
);
const multiFetcher = useCallback(
function multiFetcherImpl(
params: string[],
options: RequestOptions = {},
): Promise[]> {
return Promise.all(
params.map((endpoint) =>
requestHandler(baseUrl, endpoint, {...options, token}),
),
);
},
[baseUrl],
);
const fetcher = useCallback(
function fetcherImpl(endpoint: string): Promise> {
return requestHandler(baseUrl, endpoint, {token});
},
[baseUrl],
);
const depositConfirmationFetcher = useCallback(
function orderFetcherImpl(
args: [endpoint: string,
],
): Promise> {
const [endpoint] = args;
const params: any = {"token": "D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0"};
return requestHandler(baseUrl, endpoint, {params, token});
},
[baseUrl],
);
return {
request,
fetcher,
depositConfirmationFetcher,
multiFetcher
};
}