wallet-core/packages/merchant-backoffice-ui/src/hooks/backend.ts
2023-02-10 09:52:01 -03:00

322 lines
8.8 KiB
TypeScript

/*
This file is part of GNU Taler
(C) 2021-2023 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/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { useSWRConfig } from "swr";
import { MerchantBackend } from "../declaration.js";
import { useBackendContext } from "../context/backend.js";
import { useCallback, useEffect, useState } from "preact/hooks";
import { useInstanceContext } from "../context/instance.js";
import {
HttpResponse,
HttpResponseOk,
RequestOptions,
} from "@gnu-taler/web-util/lib/index.browser";
import { useApiContext } from "@gnu-taler/web-util/lib/index.browser";
export function useMatchMutate(): (
re: RegExp,
value?: unknown,
) => Promise<any> {
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, value?: unknown) {
const allKeys = Array.from(cache.keys());
const keys = allKeys.filter((key) => re.test(key));
const mutations = keys.map((key) => {
return mutate(key, value, true);
});
return Promise.all(mutations);
};
}
export function useBackendInstancesTestForAdmin(): HttpResponse<
MerchantBackend.Instances.InstancesResponse,
MerchantBackend.ErrorDetail
> {
const { request } = useBackendBaseRequest();
type Type = MerchantBackend.Instances.InstancesResponse;
const [result, setResult] = useState<
HttpResponse<Type, MerchantBackend.ErrorDetail>
>({ loading: true });
useEffect(() => {
request<Type>(`/management/instances`)
.then((data) => setResult(data))
.catch((error) => setResult(error));
}, [request]);
return result;
}
export function useBackendConfig(): HttpResponse<
MerchantBackend.VersionResponse,
MerchantBackend.ErrorDetail
> {
const { request } = useBackendBaseRequest();
type Type = MerchantBackend.VersionResponse;
const [result, setResult] = useState<
HttpResponse<Type, MerchantBackend.ErrorDetail>
>({ loading: true });
useEffect(() => {
request<Type>(`/config`)
.then((data) => setResult(data))
.catch((error) => setResult(error));
}, [request]);
return result;
}
interface useBackendInstanceRequestType {
request: <T>(
endpoint: string,
options?: RequestOptions,
) => Promise<HttpResponseOk<T>>;
fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
reserveDetailFetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
tipsDetailFetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
multiFetcher: <T>(url: string[]) => Promise<HttpResponseOk<T>[]>;
orderFetcher: <T>(
endpoint: string,
paid?: YesOrNo,
refunded?: YesOrNo,
wired?: YesOrNo,
searchDate?: Date,
delta?: number,
) => Promise<HttpResponseOk<T>>;
transferFetcher: <T>(
endpoint: string,
payto_uri?: string,
verified?: string,
position?: string,
delta?: number,
) => Promise<HttpResponseOk<T>>;
templateFetcher: <T>(
endpoint: string,
position?: string,
delta?: number,
) => Promise<HttpResponseOk<T>>;
webhookFetcher: <T>(
endpoint: string,
position?: string,
delta?: number,
) => Promise<HttpResponseOk<T>>;
}
interface useBackendBaseRequestType {
request: <T>(
endpoint: string,
options?: RequestOptions,
) => Promise<HttpResponseOk<T>>;
}
type YesOrNo = "yes" | "no";
/**
*
* @param root the request is intended to the base URL and no the instance URL
* @returns request handler to
*/
export function useBackendBaseRequest(): useBackendBaseRequestType {
const { url: backend, token } = useBackendContext();
const { request: requestHandler } = useApiContext();
const request = useCallback(
function requestImpl<T>(
endpoint: string,
options: RequestOptions = {},
): Promise<HttpResponseOk<T>> {
return requestHandler<T>(backend, endpoint, { token, ...options });
},
[backend, token],
);
return { request };
}
export function useBackendInstanceRequest(): useBackendInstanceRequestType {
const { url: rootBackendUrl, token: rootToken } = useBackendContext();
const { token: instanceToken, id, admin } = useInstanceContext();
const { request: requestHandler } = useApiContext();
const { baseUrl, token } = !admin
? { baseUrl: rootBackendUrl, token: rootToken }
: { baseUrl: `${rootBackendUrl}/instances/${id}`, token: instanceToken };
const request = useCallback(
function requestImpl<T>(
endpoint: string,
options: RequestOptions = {},
): Promise<HttpResponseOk<T>> {
return requestHandler<T>(baseUrl, endpoint, { token, ...options });
},
[baseUrl, token],
);
const multiFetcher = useCallback(
function multiFetcherImpl<T>(
endpoints: string[],
): Promise<HttpResponseOk<T>[]> {
return Promise.all(
endpoints.map((endpoint) =>
requestHandler<T>(baseUrl, endpoint, { token }),
),
);
},
[baseUrl, token],
);
const fetcher = useCallback(
function fetcherImpl<T>(endpoint: string): Promise<HttpResponseOk<T>> {
return requestHandler<T>(baseUrl, endpoint, { token });
},
[baseUrl, token],
);
const orderFetcher = useCallback(
function orderFetcherImpl<T>(
endpoint: string,
paid?: YesOrNo,
refunded?: YesOrNo,
wired?: YesOrNo,
searchDate?: Date,
delta?: number,
): Promise<HttpResponseOk<T>> {
const date_ms =
delta && delta < 0 && searchDate
? searchDate.getTime() + 1
: searchDate?.getTime();
const params: any = {};
if (paid !== undefined) params.paid = paid;
if (delta !== undefined) params.delta = delta;
if (refunded !== undefined) params.refunded = refunded;
if (wired !== undefined) params.wired = wired;
if (date_ms !== undefined) params.date_ms = date_ms;
return requestHandler<T>(baseUrl, endpoint, { params, token });
},
[baseUrl, token],
);
const reserveDetailFetcher = useCallback(
function reserveDetailFetcherImpl<T>(
endpoint: string,
): Promise<HttpResponseOk<T>> {
return requestHandler<T>(baseUrl, endpoint, {
params: {
tips: "yes",
},
token,
});
},
[baseUrl, token],
);
const tipsDetailFetcher = useCallback(
function tipsDetailFetcherImpl<T>(
endpoint: string,
): Promise<HttpResponseOk<T>> {
return requestHandler<T>(baseUrl, endpoint, {
params: {
pickups: "yes",
},
token,
});
},
[baseUrl, token],
);
const transferFetcher = useCallback(
function transferFetcherImpl<T>(
endpoint: string,
payto_uri?: string,
verified?: string,
position?: string,
delta?: number,
): Promise<HttpResponseOk<T>> {
const params: any = {};
if (payto_uri !== undefined) params.payto_uri = payto_uri;
if (verified !== undefined) params.verified = verified;
if (delta !== undefined) {
params.limit = delta;
}
if (position !== undefined) params.offset = position;
return requestHandler<T>(baseUrl, endpoint, { params, token });
},
[baseUrl, token],
);
const templateFetcher = useCallback(
function templateFetcherImpl<T>(
endpoint: string,
position?: string,
delta?: number,
): Promise<HttpResponseOk<T>> {
const params: any = {};
if (delta !== undefined) {
params.limit = delta;
}
if (position !== undefined) params.offset = position;
return requestHandler<T>(baseUrl, endpoint, { params, token });
},
[baseUrl, token],
);
const webhookFetcher = useCallback(
function webhookFetcherImpl<T>(
endpoint: string,
position?: string,
delta?: number,
): Promise<HttpResponseOk<T>> {
const params: any = {};
if (delta !== undefined) {
params.limit = delta;
}
if (position !== undefined) params.offset = position;
return requestHandler<T>(baseUrl, endpoint, { params, token });
},
[baseUrl, token],
);
return {
request,
fetcher,
multiFetcher,
orderFetcher,
reserveDetailFetcher,
tipsDetailFetcher,
transferFetcher,
templateFetcher,
webhookFetcher,
};
}