import merge from "deepmerge" import fetchRetry from "fetch-retry" import { env } from "@/env/server" import type { RequestOptionsWithJSONBody, RequestOptionsWithOutBody, } from "@/types/fetch" import type { Endpoint } from "./endpoints" export { endpoints } from "./endpoints" const defaultOptions: RequestInit = { cache: "no-store", headers: { Accept: "application/json", "Content-Type": "application/json", }, mode: "cors", } const wrappedFetch = fetchRetry(fetch, { retries: 3, retryDelay: function (attempt, error, response) { return Math.pow(2, attempt) * 150 // 150, 300, 600 }, }) export async function get( endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithOutBody, params = {} ) { const url = new URL(env.API_BASEURL) url.pathname = endpoint const searchParams = new URLSearchParams(params) if (searchParams.size) { searchParams.forEach((value, key) => { url.searchParams.set(key, value) }) url.searchParams.sort() } return wrappedFetch( url, merge.all([defaultOptions, { method: "GET" }, options]) ) } export async function patch( endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithJSONBody, params = {} ) { const { body, ...requestOptions } = options const url = new URL(env.API_BASEURL) url.pathname = endpoint const searchParams = new URLSearchParams(params) if (searchParams.size) { searchParams.forEach((value, key) => { url.searchParams.set(key, value) }) url.searchParams.sort() } return wrappedFetch( url, merge.all([ defaultOptions, { body: JSON.stringify(body), method: "PATCH" }, requestOptions, ]) ) } export async function post( endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithJSONBody, params = {} ) { const { body, ...requestOptions } = options const url = new URL(env.API_BASEURL) url.pathname = endpoint const searchParams = new URLSearchParams(params) if (searchParams.size) { searchParams.forEach((value, key) => { url.searchParams.set(key, value) }) url.searchParams.sort() } return wrappedFetch( url, merge.all([ defaultOptions, { body: JSON.stringify(body), method: "POST" }, requestOptions, ]) ) } export async function remove( endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithOutBody, params = {} ) { const url = new URL(env.API_BASEURL) url.pathname = endpoint const searchParams = new URLSearchParams(params) if (searchParams.size) { searchParams.forEach((value, key) => { url.searchParams.set(key, value) }) url.searchParams.sort() } return wrappedFetch( url, merge.all([defaultOptions, { method: "DELETE" }, options]) ) }