api.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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,
  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. const response = await fetchApi(`/user/${id}`, ApiMethods.PUT, body);
  67. switch (response.state) {
  68. case ApiResulState.SUCCESS: {
  69. return {
  70. ...response,
  71. user: {
  72. ...response.user,
  73. id: id,
  74. },
  75. };
  76. }
  77. default:
  78. return response;
  79. }
  80. };
  81. const fetchUsers = async (): Promise<Array<User>> => {
  82. const response = await fetch("/api/users");
  83. if (response.ok) {
  84. return response.json();
  85. } else {
  86. return Promise.resolve([]);
  87. }
  88. };
  89. const fetchUserData = async (email: string): Promise<User> => {
  90. const users = await fetchUsers();
  91. const user = users.find((user) => user.email === email);
  92. assert(user);
  93. return user;
  94. };
  95. const apiPaths = {
  96. login,
  97. register,
  98. updateUser,
  99. };
  100. export default apiPaths;