1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-22 01:16:07 +02:00
unleash.unleash/frontend/src/hooks/api/actions/useApi/useApi.ts
Fredrik Strand Oseberg c99decf5e0 remove: redux (#696)
* remove: redux

* fix: add sass back

* fix: update lock

* fix: remove fake access store import

'
2022-02-11 11:19:55 +01:00

194 lines
5.0 KiB
TypeScript

import { useState, Dispatch, SetStateAction } from 'react';
import {
BAD_REQUEST,
FORBIDDEN,
NOT_FOUND,
OK,
UNAUTHORIZED,
} from '../../../../constants/statusCodes';
import {
AuthenticationError,
BadRequestError,
ForbiddenError,
headers,
NotFoundError,
} from '../../../../utils/api-utils';
import { formatApiPath } from '../../../../utils/format-path';
interface IUseAPI {
handleBadRequest?: (
setErrors?: Dispatch<SetStateAction<{}>>,
res?: Response,
requestId?: string
) => void;
handleNotFound?: (
setErrors?: Dispatch<SetStateAction<{}>>,
res?: Response,
requestId?: string
) => void;
handleUnauthorized?: (
setErrors?: Dispatch<SetStateAction<{}>>,
res?: Response,
requestId?: string
) => void;
handleForbidden?: (
setErrors?: Dispatch<SetStateAction<{}>>,
res?: Response,
requestId?: string
) => void;
propagateErrors?: boolean;
}
const useAPI = ({
handleBadRequest,
handleNotFound,
handleForbidden,
handleUnauthorized,
propagateErrors = false,
}: IUseAPI) => {
const [errors, setErrors] = useState<Record<string, string>>({});
const [loading, setLoading] = useState(false);
const defaultOptions: RequestInit = {
headers,
credentials: 'include',
};
const makeRequest = async (
apiCaller: any,
requestId?: string,
loadingOn: boolean = true
): Promise<Response> => {
if (loadingOn) {
setLoading(true);
}
try {
const res = await apiCaller();
setLoading(false);
if (res.status > 299) {
await handleResponses(res, requestId);
}
if (res.status === OK) {
setErrors({});
}
return res;
} catch (e) {
setLoading(false);
throw e;
}
};
const createRequest = (
path: string,
options: any,
requestId: string = ''
) => {
return {
caller: () => {
return fetch(formatApiPath(path), {
...defaultOptions,
...options,
});
},
id: requestId,
};
};
const handleResponses = async (res: Response, requestId?: string) => {
if (res.status === BAD_REQUEST) {
if (handleBadRequest) {
return handleBadRequest(setErrors, res, requestId);
} else {
setErrors(prev => ({
...prev,
badRequest: 'Bad request format',
}));
}
if (propagateErrors) {
const response = await res.json();
throw new BadRequestError(res.status, response);
}
}
if (res.status === NOT_FOUND) {
if (handleNotFound) {
return handleNotFound(setErrors, res, requestId);
} else {
setErrors(prev => ({
...prev,
notFound: 'Could not find the requested resource',
}));
}
if (propagateErrors) {
throw new NotFoundError(res.status);
}
}
if (res.status === UNAUTHORIZED) {
if (handleUnauthorized) {
return handleUnauthorized(setErrors, res, requestId);
} else {
setErrors(prev => ({
...prev,
unauthorized:
'You are not authorized to perform this operation',
}));
}
if (propagateErrors) {
throw new AuthenticationError(res.status);
}
}
if (res.status === FORBIDDEN) {
if (handleForbidden) {
return handleForbidden(setErrors);
} else {
setErrors(prev => ({
...prev,
forbidden: 'This operation is forbidden',
}));
}
if (propagateErrors) {
const response = await res.json();
throw new ForbiddenError(res.status, response);
}
}
if (res.status > 399) {
const response = await res.json();
if (response?.details?.length > 0 && propagateErrors) {
const error = response.details[0];
if (propagateErrors) {
throw new Error(error.message || error.msg);
}
return error;
}
if (response?.length > 0 && propagateErrors) {
const error = response[0];
throw new Error(error.message || error.msg);
}
if (propagateErrors) {
throw new Error('Action could not be performed');
}
}
};
return {
loading,
makeRequest,
createRequest,
errors,
};
};
export default useAPI;