/** * Module: generic API for backend REST communications using axios library. */ import axios from 'axios'; import { AxiosError, AxiosRequestConfig } from 'axios'; import { toast } from 'react-toastify'; import { buildConstants } from '@/utils/buildConstants'; import { extractErrorMessage } from '@/utils/utils'; const defaultOptions = { xsrfCookieName: 'csrftoken', xsrfHeaderName: 'x-csrftoken', baseURL: `${buildConstants.backend}`, withCredentials: true }; const axiosInstance = axios.create(defaultOptions); axiosInstance.interceptors.request.use(config => { const token = document.cookie .split('; ') .find(row => row.startsWith('csrftoken=')) ?.split('=')[1]; if (token) { config.headers['x-csrftoken'] = token; } return config; }); // ================ Data transfer types ================ export type DataCallback = (data: ResponseData) => void; export interface IFrontRequest { data?: RequestData; successMessage?: string | ((data: ResponseData) => string); } export interface IAxiosRequest { endpoint: string; request?: IFrontRequest; options?: AxiosRequestConfig; } export interface IAxiosGetRequest { endpoint: string; options?: AxiosRequestConfig; signal?: AbortSignal; } // ================ Transport API calls ================ export function axiosGet({ endpoint, options }: IAxiosGetRequest) { return axiosInstance .get(endpoint, options) .then(response => response.data) .catch((error: Error | AxiosError) => { if (error.name !== 'CanceledError') { // Note: Ignore cancellation errors toast.error(extractErrorMessage(error)); console.error(error); } throw error; }); } export function axiosPost({ endpoint, request, options }: IAxiosRequest) { return axiosInstance .post(endpoint, request?.data, options) .then(response => { if (request?.successMessage) { if (typeof request.successMessage === 'string') { toast.success(request.successMessage); } else { toast.success(request.successMessage(response.data)); } } return response.data; }) .catch((error: Error | AxiosError) => { toast.error(extractErrorMessage(error)); console.error(error); throw error; }); } export function axiosDelete({ endpoint, request, options }: IAxiosRequest) { return axiosInstance .delete(endpoint, options) .then(response => { if (request?.successMessage) { if (typeof request.successMessage === 'string') { toast.success(request.successMessage); } else { toast.success(request.successMessage(response.data)); } } return response.data; }) .catch((error: Error | AxiosError) => { toast.error(extractErrorMessage(error)); console.error(error); throw error; }); } export function axiosPatch({ endpoint, request, options }: IAxiosRequest) { return axiosInstance .patch(endpoint, request?.data, options) .then(response => { if (request?.successMessage) { if (typeof request.successMessage === 'string') { toast.success(request.successMessage); } else { toast.success(request.successMessage(response.data)); } } return response.data; }) .catch((error: Error | AxiosError) => { toast.error(extractErrorMessage(error)); console.error(error); throw error; }); }