import { AxiosError, AxiosResponse } from 'axios'; export const apiBaseUrl = '/api'; export function base64(blob: Blob): Promise { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = function () { resolve((reader.result as string).replace(/^data:.+;base64,/, '')); }; reader.readAsDataURL(blob); }); } export function extractStatusCode(error: AxiosError): number | null { if (error.isAxiosError) { const code = error?.response?.status; if (typeof code === 'number') { return code; } } return null; } export interface CommonErrorResponse { code: number; message: string; } export function extractErrorCode( error: AxiosError ): number | null { if (error.isAxiosError) { const code = error.response?.data?.code; if (typeof code === 'number') { return code; } } return null; } export class HttpNetworkError extends Error { constructor(public innerError?: AxiosError) { super(); } } export class HttpForbiddenError extends Error { constructor(public innerError?: AxiosError) { super(); } } export class NotModified {} export interface BlobWithEtag { data: Blob; etag: string; } export function extractResponseData(res: AxiosResponse): T { return res.data; } export function catchIfStatusCodeIs< TResult, TErrorHandlerResult extends TResult | PromiseLike | null | undefined >( statusCode: number, errorHandler: (error: AxiosError) => TErrorHandlerResult ): (error: AxiosError) => TErrorHandlerResult { return (error: AxiosError) => { if (extractStatusCode(error) == statusCode) { return errorHandler(error); } else { throw error; } }; } export function convertToIfStatusCodeIs( statusCode: number, newErrorType: { new (innerError: AxiosError): NewError; } ): (error: AxiosError) => never { return catchIfStatusCodeIs(statusCode, (error) => { throw new newErrorType(error); }); } export function catchIfErrorCodeIs< TResult, TErrorHandlerResult extends TResult | PromiseLike | null | undefined >( errorCode: number, errorHandler: (error: AxiosError) => TErrorHandlerResult ): (error: AxiosError) => TErrorHandlerResult { return (error: AxiosError) => { if (extractErrorCode(error) == errorCode) { return errorHandler(error); } else { throw error; } }; } export function convertToIfErrorCodeIs( errorCode: number, newErrorType: { new (innerError: AxiosError): NewError; } ): (error: AxiosError) => never { return catchIfErrorCodeIs(errorCode, (error) => { throw new newErrorType(error); }); } export function convertToNetworkError( error: AxiosError ): never { if (error.isAxiosError && error.response == null) { throw new HttpNetworkError(error); } else { throw error; } } export function convertToForbiddenError( error: AxiosError ): never { if ( error.isAxiosError && error.response != null && (error.response.status == 401 || error.response.status == 403) ) { throw new HttpForbiddenError(error); } else { throw error; } } export function convertToNotModified( error: AxiosError ): NotModified { if ( error.isAxiosError && error.response != null && error.response.status == 304 ) { return new NotModified(); } else { throw error; } } export function convertToBlobWithEtag(res: AxiosResponse): BlobWithEtag { return { data: res.data, etag: (res.headers as Record<'etag', string>)['etag'], }; }