mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 18:33:12 +00:00
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import ky, { type HTTPError, type KyInstance, type Options } from "ky";
|
|
import { env } from "@/lib/env";
|
|
import { resolveApiPrefixUrl } from "@/lib/resolve-api-prefix-url";
|
|
import { API_PATHS } from "@/api/api-paths";
|
|
import { createApiErrorFromResponse, mapHttpStatusToMessage } from "@/api/api-error";
|
|
import { queryKeys } from "@/infra/query-key/query-key";
|
|
import queryClient from "@/lib/query/query-client";
|
|
import { isAuthBypassEnabled } from "@/lib/auth/auth-bypass";
|
|
import { clearAuth, getAccessToken } from "@/lib/auth/auth-storage";
|
|
|
|
function clearSessionAndRedirectToLogin(): void {
|
|
clearAuth();
|
|
queryClient.setQueryData(queryKeys.auth.session(), null);
|
|
|
|
if (typeof window !== "undefined" && window.location.pathname !== "/login") {
|
|
window.location.replace("/login");
|
|
}
|
|
}
|
|
|
|
function isAuthLoginRequest(request: Request): boolean {
|
|
return request.url.includes(API_PATHS.authentication.login);
|
|
}
|
|
|
|
export const api: KyInstance = ky.create({
|
|
prefixUrl: resolveApiPrefixUrl(env.apiUrl),
|
|
headers: {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
},
|
|
hooks: {
|
|
beforeRequest: [
|
|
(request) => {
|
|
const token = getAccessToken();
|
|
if (token) {
|
|
request.headers.set("Authorization", token);
|
|
}
|
|
},
|
|
],
|
|
beforeError: [
|
|
async (error: HTTPError) => {
|
|
const { response } = error;
|
|
|
|
if (!response) {
|
|
error.message = "No response from server. Please check your connection.";
|
|
return error;
|
|
}
|
|
|
|
const apiError = await createApiErrorFromResponse(response);
|
|
error.message = apiError.message;
|
|
return error;
|
|
},
|
|
],
|
|
afterResponse: [
|
|
async (request, _options, response) => {
|
|
if (response.status !== 401 || isAuthLoginRequest(request) || isAuthBypassEnabled()) {
|
|
return response;
|
|
}
|
|
|
|
clearSessionAndRedirectToLogin();
|
|
return response;
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
export async function apiGet<T>(url: string, options?: Options): Promise<T> {
|
|
return api.get(url, options).json<T>();
|
|
}
|
|
|
|
export async function apiPost<T>(url: string, body?: unknown, options?: Options): Promise<T> {
|
|
return api.post(url, { ...options, json: body }).json<T>();
|
|
}
|
|
|
|
export async function apiPut<T>(url: string, body?: unknown, options?: Options): Promise<T> {
|
|
return api.put(url, { ...options, json: body }).json<T>();
|
|
}
|
|
|
|
export async function apiDelete<T>(url: string, options?: Options): Promise<T> {
|
|
return api.delete(url, options).json<T>();
|
|
}
|
|
|
|
export async function apiPostNoContent(
|
|
url: string,
|
|
body?: unknown,
|
|
options?: Options,
|
|
): Promise<void> {
|
|
const response = await api.post(url, { ...options, json: body });
|
|
if (response.status === 204) {
|
|
return;
|
|
}
|
|
|
|
const text = await response.text();
|
|
if (!text.trim()) {
|
|
return;
|
|
}
|
|
|
|
JSON.parse(text);
|
|
}
|
|
|
|
export async function apiDeleteNoContent(url: string, options?: Options): Promise<void> {
|
|
const response = await api.delete(url, options);
|
|
if (response.status === 204) {
|
|
return;
|
|
}
|
|
|
|
const text = await response.text();
|
|
if (!text.trim()) {
|
|
return;
|
|
}
|
|
|
|
JSON.parse(text);
|
|
}
|
|
|
|
export { mapHttpStatusToMessage };
|