import axios from "axios"; import { isAuthenticatedPromise, type Payload } from "./router/authGuard"; import router from "./router"; import { useNotificationStore } from "./stores/notification"; import { EventSourcePolyfill } from "event-source-polyfill"; import { config } from "./config"; let devMode = process.env.NODE_ENV === "development"; let host = devMode ? "localhost:5000" : (config.server_address ?? "").replace(/(^\w+:|^)\/\//, ""); let url = devMode ? "http://" + host : config.server_address; const http = axios.create({ baseURL: url + "/api", headers: { "Cache-Control": "no-cache", Pragma: "no-cache", Expires: "0", }, }); http.interceptors.request.use( (config) => { const token = localStorage.getItem("accessToken"); if (token) { if (config.headers) { config.headers.Authorization = `Bearer ${token}`; } } const isPWA = window.matchMedia("(display-mode: standalone)").matches || window.matchMedia("(display-mode: fullscreen)").matches; if (isPWA) { if (config.headers) { config.headers["X-PWA-Client"] = isPWA ? "true" : "false"; } } return config; }, (error) => { return Promise.reject(error); } ); http.interceptors.response.use( (response) => { return response; }, async (error) => { if (!error.config.url.includes("/admin") && !error.config.url.includes("/user")) { return Promise.reject(error); } const originalRequest = error.config; // Handle token expiration and retry the request with a refreshed token if (error.response && error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; return await refreshToken() .then(() => { return http(originalRequest); }) .catch(() => {}); } const notificationStore = useNotificationStore(); if (error.toString().includes("Network Error")) { notificationStore.push("Netzwerkfehler", "Server nicht erreichbar!", "error"); } else { notificationStore.push("Fehler", error.response.data, "error"); } return Promise.reject(error); } ); export async function refreshToken(): Promise { return new Promise(async (resolve, reject) => { await http .post(`/auth/refresh`, { accessToken: localStorage.getItem("accessToken"), refreshToken: localStorage.getItem("refreshToken"), }) .then(async (response) => { const { accessToken, refreshToken } = response.data; localStorage.setItem("accessToken", accessToken); localStorage.setItem("refreshToken", refreshToken); await isAuthenticatedPromise().catch((err: string) => { router.push({ name: err ?? "login" }); reject(err); }); resolve(); }) .catch((error) => { console.error("Error refreshing token:", error); reject("login"); }); }); } function newEventSource(path: string) { const token = localStorage.getItem("accessToken"); return new EventSourcePolyfill(url + "/api" + path, { headers: { Authorization: `Bearer ${token}`, }, }); } async function* streamingFetch(path: string, abort?: AbortController) { await refreshToken() .then(() => {}) .catch(() => {}); const token = localStorage.getItem("accessToken"); const response = await fetch(url + "/api" + path, { signal: abort?.signal, headers: { Authorization: `Bearer ${token}`, }, }); const reader = response.body?.getReader(); while (true && reader) { const { done, value } = await reader.read(); if (done) break; yield new TextDecoder().decode(value); } } export { http, newEventSource, streamingFetch, host };