api.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import assert from "assert";
  2. const API = process.env.NEXT_PUBLIC_API || "/api";
  3. export enum ApiMethods {
  4. GET = "GET",
  5. POST = "POST",
  6. PUT = "PUT",
  7. }
  8. export enum ApiResulState {
  9. SUCCESS,
  10. ERROR,
  11. }
  12. type SuccessApiResult = {
  13. state: ApiResulState.SUCCESS;
  14. message: string;
  15. user: User;
  16. };
  17. type FailureApiResult = { state: ApiResulState.ERROR; error: string };
  18. export type FetchApiResult = SuccessApiResult | FailureApiResult;
  19. type FetchApi = <T>(
  20. path: string,
  21. method: ApiMethods,
  22. body: T
  23. ) => Promise<FetchApiResult>;
  24. const fetchApi: FetchApi = async (path, method, body) => {
  25. const response = await fetch(`${API}${path}`, {
  26. method: method,
  27. body: JSON.stringify(body),
  28. });
  29. const { message, ...result } = await response.json();
  30. if (response.ok) {
  31. return { state: ApiResulState.SUCCESS, message, user: result };
  32. } else {
  33. return {
  34. state: ApiResulState.ERROR,
  35. error: message.replace("Incorect", "Incorrect"),
  36. };
  37. }
  38. };
  39. export interface FetchApiInterface<T> {
  40. (body: T): Promise<FetchApiResult>;
  41. }
  42. export const login: FetchApiInterface<
  43. Pick<User, "email" | "password">
  44. > = async (body) => {
  45. const response = await fetchApi("/login", ApiMethods.POST, body);
  46. switch (response.state) {
  47. case ApiResulState.SUCCESS: {
  48. const user = await fetchUserData(body.email);
  49. return {
  50. ...response,
  51. user: user,
  52. };
  53. }
  54. default:
  55. return response;
  56. }
  57. };
  58. export const register: FetchApiInterface<
  59. Pick<User, "email" | "password">
  60. > = async (body) => {
  61. return fetchApi("/register", ApiMethods.POST, body);
  62. };
  63. export const updateUser: FetchApiInterface<
  64. Partial<User> & Pick<User, "id">
  65. > = async ({ id, ...body }) => {
  66. return fetchApi(`/user/${JSON.stringify(id)}`, ApiMethods.PUT, body);
  67. };
  68. const fetchUsers = async (): Promise<Array<User>> => {
  69. const response = await fetch("/api/users");
  70. if (response.ok) {
  71. return response.json();
  72. } else {
  73. return Promise.resolve([]);
  74. }
  75. };
  76. const fetchUserData = async (email: string): Promise<User> => {
  77. const users = await fetchUsers();
  78. const user = users.find((user) => user.email === email);
  79. assert(user);
  80. return user;
  81. };
  82. const apiPaths = {
  83. login,
  84. register,
  85. updateUser,
  86. };
  87. export default apiPaths;