import assert from "assert"; const API = process.env.NEXT_PUBLIC_API || "/api"; export enum ApiMethods { GET = "GET", POST = "POST", PUT = "PUT", } export enum ApiResulState { SUCCESS, ERROR, } type SuccessApiResult = { state: ApiResulState.SUCCESS; message: string; user: User; }; type FailureApiResult = { state: ApiResulState.ERROR; error: string }; export type FetchApiResult = SuccessApiResult | FailureApiResult; type FetchApi = ( path: string, method: ApiMethods, body: T ) => Promise; const fetchApi: FetchApi = async (path, method, body) => { const response = await fetch(`${API}${path}`, { method: method, body: JSON.stringify(body), }); const { message, ...result } = await response.json(); if (response.ok) { return { state: ApiResulState.SUCCESS, message, user: result }; } else { return { state: ApiResulState.ERROR, error: message.replace("Incorect", "Incorrect"), }; } }; export interface FetchApiInterface { (body: T): Promise; } export const login: FetchApiInterface< Pick > = async (body) => { const response = await fetchApi("/login", ApiMethods.POST, body); switch (response.state) { case ApiResulState.SUCCESS: { const user = await fetchUserData(body.email); return { ...response, user, }; } default: return response; } }; export const register: FetchApiInterface< Pick > = async (body) => { return fetchApi("/register", ApiMethods.POST, body); }; export const updateUser: FetchApiInterface< Partial & Pick > = async ({ id, ...body }) => { const response = await fetchApi(`/user/${id}`, ApiMethods.PUT, body); switch (response.state) { case ApiResulState.SUCCESS: { return { ...response, user: { ...response.user, id: id, }, }; } default: return response; } }; const fetchUsers = async (): Promise> => { const response = await fetch("/api/users"); if (response.ok) { return response.json(); } else { return Promise.resolve([]); } }; const fetchUserData = async (email: string): Promise => { const users = await fetchUsers(); const user = users.find((user) => user.email === email); assert(user); return user; }; const apiPaths = { login, register, updateUser, }; export default apiPaths;