Files
workavia-calendar-front/src/utils/apiUtils.ts
T
Camille Moussu 83fae6f1c2 [#448] added reconnection logic to websocket (#472)
* [#448] added reconnection logic to websocket

* [#448] added test

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-27 14:54:03 +01:00

106 lines
2.7 KiB
TypeScript

import { Auth } from "@/features/User/oidcAuth";
import ky from "ky";
import { getRetryDelay } from "./getRetryDelay";
const RETRY_CONFIG = {
maxRetries: 10,
initialDelay: 1000,
maxDelay: 120000,
};
export const api = ky.extend({
prefixUrl: (window as any).CALENDAR_BASE_URL,
retry: {
limit: RETRY_CONFIG.maxRetries,
backoffLimit: RETRY_CONFIG.maxDelay,
delay: (attemptCount) =>
getRetryDelay(attemptCount - 1, {
initialDelay: RETRY_CONFIG.initialDelay,
maxDelay: RETRY_CONFIG.maxDelay,
}),
},
hooks: {
beforeRequest: [
async (request) => {
const saved = sessionStorage.getItem("tokenSet")
? JSON.parse(sessionStorage.getItem("tokenSet")!)
: null;
const access_token = saved?.access_token;
if (access_token) {
request.headers.set("Authorization", `Bearer ${access_token}`);
}
return request;
},
],
beforeRetry: [
async ({ request, error, retryCount }) => {
console.warn(
`[API Retry] Attempt ${retryCount}/${RETRY_CONFIG.maxRetries}`,
{
url: request.url,
error: error?.message,
}
);
},
],
afterResponse: [
async (request, options, response) => {
if (response.status === 401) {
// Check if we're already on login flow to prevent redirect loop
const currentPath = window.location.pathname;
if (currentPath === "/" || currentPath === "/callback") {
return response;
}
// Check if we have a token in the request
const hasAuthHeader = request.headers.has("Authorization");
if (!hasAuthHeader) {
return response;
}
// Only redirect to SSO if we're sure token is invalid (not just missing)
const loginurl = await Auth();
sessionStorage.setItem(
"redirectState",
JSON.stringify({
code_verifier: loginurl.code_verifier,
state: loginurl.state,
})
);
redirectTo(loginurl.redirectTo);
}
return response;
},
],
},
});
export function redirectTo(url: URL) {
window.location.assign(url);
}
export function getLocation() {
return window.location.href;
}
export function isValidUrl(string?: string) {
let url;
try {
url = new URL(string ?? "");
} catch (_) {
return false;
}
return url;
}
export async function importFile(file: File) {
const response = await api.post(
`api/files?mimetype=${file.type}&name=${file.name}&size=${file.size}`,
{ body: await file.text() }
);
return await response.json();
}