diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index b50a607..7bb5cd2 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -1,23 +1,44 @@ -import type { Endpoints } from '@/types/axios.type'; +import { buildFullUrls } from '@/api/utils'; + +import type { Endpoints, SuccessOutput } from '@/types/axios.type'; const endpoints = { - login: { - method: 'POST', - url: '/auth/login', - manageToast: (res) => !!res.message, - }, - getProfile: { - method: 'GET', - url: '/user/profile/me', + // Auth endpoints + auth: { + prefix: 'auth', + login: { + method: 'POST', + url: 'login', + manageToast: (res: SuccessOutput) => !!res.message, + }, }, - logout: { - method: 'POST', - url: '/user/profile/logout', + + // User endpoints + user: { + prefix: 'user', + profile: { + prefix: 'profile', + me: { + method: 'GET', + url: 'me', + manageToast: (res: SuccessOutput) => !!res.message, + }, + logout: { + method: 'POST', + url: 'logout', + manageToast: (res: SuccessOutput) => !!res.message, + }, + }, }, - getAllUsers: { + + // Users endpoints + users: { method: 'GET', - url: '/users', + url: 'users', + manageToast: (res: SuccessOutput) => !!res.message, }, } satisfies Endpoints; -export default endpoints; +const finalEndpoints = buildFullUrls(endpoints); + +export default finalEndpoints; diff --git a/src/api/index.ts b/src/api/index.ts index a05a034..4d40c38 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,16 +1,17 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import axios from '@/api/axios'; -import endpoints from '@/api/endpoints'; +import finalEndpoints from '@/api/endpoints'; import type { AxiosOutput, AxiosPaginatedOutput } from '@/types/axios.type'; const nonPaginatedApis = { - login: async (data) => axios({ ...endpoints.login, ...data }), + login: async (data) => axios({ ...(finalEndpoints.auth as any).login, ...data }), - getProfile: async (data) => axios({ ...endpoints.getProfile, ...data }), + getProfile: async (data) => axios({ ...(finalEndpoints.user as any).profile.me, ...data }), - logout: async (data) => axios({ ...endpoints.logout, ...data }), + logout: async (data) => axios({ ...(finalEndpoints.user as any).profile.logout, ...data }), - getAllUsers: async (data) => axios({ ...endpoints.getAllUsers, ...data }), + getAllUsers: async (data) => axios({ ...finalEndpoints.users, ...data }), } satisfies Record; const paginatedApis = {} satisfies Record; diff --git a/src/api/utils.ts b/src/api/utils.ts index 57d78ee..5385fcc 100644 --- a/src/api/utils.ts +++ b/src/api/utils.ts @@ -3,7 +3,13 @@ import { toast } from 'react-toastify'; import { AppError } from '@/api/appError'; -import type { AxiosErrConfig, ShowToast, SuccessOutput, ThrowAxiosError } from '@/types/axios.type'; +import type { + AxiosErrConfig, + Endpoints, + ShowToast, + SuccessOutput, + ThrowAxiosError, +} from '@/types/axios.type'; export class AxiosErr extends AxiosError { config?: AxiosErrConfig; @@ -44,3 +50,30 @@ export const showToast: ShowToast = (res) => { const call = isError ? 'error' : 'success'; toast[call](toastMessage); }; + +export function buildFullUrls(obj: Endpoints, parentPrefix = ''): Endpoints { + const result: Endpoints = {}; + + for (const key in obj) { + if (Object.hasOwn(obj, key)) { + const value = obj[key]; + + if (typeof value === 'object' && !Array.isArray(value)) { + const currentPrefix = + parentPrefix + ('prefix' in value && value.prefix ? `/${value.prefix}` : ''); + + result[key] = + 'method' in value && 'url' in value + ? { + ...value, + url: `${currentPrefix}/${value.url}`, + } + : buildFullUrls(value as Endpoints, currentPrefix); + } else { + result[key] = value; + } + } + } + + return result; +} diff --git a/src/types/axios.type.ts b/src/types/axios.type.ts index 32d4e2b..b43a68c 100644 --- a/src/types/axios.type.ts +++ b/src/types/axios.type.ts @@ -21,7 +21,12 @@ export type AxiosRequestConfigWithExtraProps = AxiosRequestConfig & AxiosExtraPr type AxiosRequestInput = Pick & ManageToast; -export type Endpoints = Record; +interface NestedEndpoint { + prefix?: string; + [key: string]: NestedEndpoint | AxiosRequestInput | string | undefined; +} + +export type Endpoints = Record; export type InternalAxiosRequestConfigWithExtraProps = InternalAxiosRequestConfig & AxiosExtraProps;