Untitled
unknown
javascript
10 months ago
4.8 kB
7
Indexable
import { error, type NumericRange } from "@sveltejs/kit" import Cookie from "cookie" import { setCookie } from "./cookie" import { isDev } from "~config" type RecursiveUrlParams = { [key: string]: RecursiveUrlParams | string | boolean | unknown } interface FetchOptions { method?: "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "HEAD" | "PATCH" headers?: Record<string, string> body?: BodyInit | null | undefined data?: unknown mode?: "cors" | "no-cors" | "same-origin" credentials?: "include" | "omit" | "same-origin" withCredentials?: boolean // eslint-disable-next-line @typescript-eslint/no-explicit-any params?: Record<string, RecursiveUrlParams | string> | any cache?: "default" | "no-store" | "reload" | "no-cache" | "force-cache" | "only-if-cached" redirect?: "follow" | "error" | "manual" referrer?: string referrerPolicy?: | "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin" | "unsafe-url" integrity?: string keepalive?: boolean signal?: AbortSignal | null baseURL?: string url?: string fetch?: typeof fetch } export const isObject = (value: unknown): value is Record<string, unknown> => { return typeof value === "object" && value !== null && !Array.isArray(value) } export const encodeQueryParams = (params: Record<string, unknown>): string => { const customEncodeURIComponent = (str: string): string => { return encodeURIComponent(str) .replace(/[!'()*~]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`) .replace(/%20/g, "%20") } const encode = (key: string, value: unknown): string => { if (value === undefined) { return "" } if (Array.isArray(value)) { if (value.length === 0) { return `${customEncodeURIComponent(key)}%5B%5D=` } return value .map((v, i) => encode(`${key}[${i}]`, v)) .filter(Boolean) .join("&") } if (isObject(value)) { return Object.entries(value) .map(([k, v]) => encode(`${key}[${k}]`, v)) .filter(Boolean) .join("&") } return `${customEncodeURIComponent(key)}=${customEncodeURIComponent(String(value))}` } return Object.entries(params) .map(([k, v]) => encode(k, v)) .filter(Boolean) .join("&") } export async function fetcher<T>(options: FetchOptions = {}) { const defaultOptions = { method: "GET", } as FetchOptions let response if (["POST", "PUT"].includes(options.method || "") && !options.headers?.["Content-Type"]) { defaultOptions.headers = { "Content-Type": "application/json", } } const mergedOptions = { // credentials: "include" as RequestCredentials, ...defaultOptions, ...options, headers: { ...defaultOptions.headers, ...options.headers, }, } // Map withCredentials to the fetch credentials option if (options.withCredentials) { mergedOptions.credentials = "include" } if (options.data) { if (options.headers?.["Content-Type"] === "application/x-www-form-urlencoded") { const formBody = [] for (const [key, value] of Object.entries(options.data)) { const encodedKey = encodeURIComponent(key) const encodedValue = encodeURIComponent(value as string) formBody.push(encodedKey + "=" + encodedValue) } mergedOptions.body = formBody.join("&") } else { mergedOptions.body = JSON.stringify(options.data) } delete mergedOptions.data } const urlObject = new URL(`${options.baseURL || ""}${options.url || ""}`) if (options.params) { const queryString = encodeQueryParams(options.params as Record<string, unknown>) urlObject.search = queryString } const fullUrl = urlObject.toString() try { const fetchingHandler = isDev ? fetch : options?.fetch || fetch response = await fetchingHandler?.(fullUrl, mergedOptions) const setCookieHeader = response.headers.get("Set-Cookie") try { if (setCookieHeader) { const parsedCookie = Cookie.parse(setCookieHeader) if (parsedCookie.id_token) setCookie("id_token", parsedCookie.id_token) if (parsedCookie.access_token) setCookie("access_token", parsedCookie.access_token) } } catch (error) { console.log("setCookieHeader error :>> ", error) } if (+response?.status >= 400) { const errorData = await response?.json() console.log("errorData :>> ", fullUrl, errorData) error(response?.status as NumericRange<400, 599>, errorData || "Fetch error") } const data = (await response?.json()) as T return { data } as { data: T } } catch (err: unknown) { console.error("Fetch error:", fullUrl, JSON.stringify(err)) // console.error("error response", response); let status if (response?.status) status = +response?.status < 400 ? 400 : +response?.status error( (status as NumericRange<400, 599>) || 500, ((err as ErrorEvent).message || err || "Fetch error") as Error, ) } }
Editor is loading...
Leave a Comment