ff-admin/src/serverCom.ts

136 lines
3.7 KiB
TypeScript

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<void> {
return new Promise<void>(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 };