import merge from "deepmerge" import fetchRetry from "fetch-retry" import { env } from "../../env/server" import type { Endpoint } from "./endpoints" export { endpoints } from "./endpoints" interface RequestOptionsWithJSONBody extends Omit { body?: Record } interface RequestOptionsWithOutBody extends Omit {} const defaultOptions: RequestInit = { cache: "no-store", headers: { Accept: "application/json", "Content-Type": "application/json", }, mode: "cors", } const wrappedFetch = fetchRetry(fetch, { retries: 2, retryDelay: function (attempt) { return Math.pow(2, attempt) * 150 // 150, 300, 600 }, }) export async function get( endpoint: Endpoint, options: RequestOptionsWithOutBody, params = {} ) { const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() return wrappedFetch(url, { ...merge.all([defaultOptions, { method: "GET" }, options]), signal: AbortSignal.timeout(15_000), }) } 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 url.search = new URLSearchParams(params).toString() return wrappedFetch(url, { ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "PATCH" }, requestOptions, ]), signal: AbortSignal.timeout(30_000), }) } 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 url.search = new URLSearchParams(params).toString() return wrappedFetch(url, { ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "POST" }, requestOptions, ]), signal: AbortSignal.timeout(30_000), }) } export async function put( endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithJSONBody, params = {} ) { const { body, ...requestOptions } = options const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() return wrappedFetch(url, { ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "PUT" }, requestOptions, ]), signal: AbortSignal.timeout(30_000), }) } export async function remove( endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithJSONBody, params = {} ) { const { body, ...requestOptions } = options const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() return wrappedFetch(url, { ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "DELETE" }, requestOptions, ]), signal: AbortSignal.timeout(30_000), }) }