0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-23 20:33:16 -05:00
logto/packages/console/src/hooks/use-swr-fetcher.ts
2022-10-21 14:03:35 +08:00

55 lines
1.6 KiB
TypeScript

import type { RequestErrorBody } from '@logto/schemas';
import { HTTPError } from 'ky';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import type { BareFetcher } from 'swr';
import useApi, { RequestError } from './use-api';
type withTotalNumber<T> = Array<Awaited<T> | number>;
type useSwrFetcherHook = {
<T>(): BareFetcher<T>;
<T extends unknown[]>(): BareFetcher<withTotalNumber<T>>;
};
const useSwrFetcher: useSwrFetcherHook = <T>() => {
const api = useApi({ hideErrorToast: true });
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const fetcher = useCallback<BareFetcher<T | withTotalNumber<T>>>(
async (resource, init) => {
try {
const response = await api.get(resource, init);
const data = await response.json<T>();
if (typeof resource === 'string' && resource.includes('?')) {
const parameters = new URLSearchParams(resource.split('?')[1]);
if (parameters.get('page') && parameters.get('page_size')) {
const number = response.headers.get('Total-Number');
if (!number) {
throw new Error(t('errors.missing_total_number'));
}
return [data, Number(number)];
}
}
return data;
} catch (error: unknown) {
if (error instanceof HTTPError) {
const { response } = error;
const metadata = await response.json<RequestErrorBody>();
throw new RequestError(response.status, metadata);
}
throw error;
}
},
[api, t]
);
return fetcher;
};
export default useSwrFetcher;