Files
web/lib/api/index.ts
2024-09-24 09:47:31 +02:00

119 lines
2.8 KiB
TypeScript

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])
)
}