Files
production-evyos-systems-an…/ServicesWeb/customer/src/fetchers/fecther.ts
2025-06-02 13:47:46 +03:00

203 lines
5.1 KiB
TypeScript

"use server";
import {
DEFAULT_RESPONSE,
defaultHeaders,
DEFAULT_TIMEOUT,
nextCrypto,
} from "./base";
import { FetchOptions, HttpMethod, ApiResponse } from "./types";
import { retrieveAccessToken } from "./mutual/cookies/token";
import { cookies } from "next/headers";
import { cookieObject } from "@/fetchers/base";
/**
* Retrieves user selection from cookies with graceful fallback
* @returns User selection object or default selection if not found
*/
const functionRetrieveUserSelection = async () => {
try {
const cookieStore = await cookies();
const encrpytUserSelection = cookieStore.get("eys-sel")?.value || "";
if (!encrpytUserSelection) {
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString(),
};
}
try {
const decrpytUserSelection = await nextCrypto.decrypt(
encrpytUserSelection
);
if (!decrpytUserSelection) {
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString(),
};
}
return JSON.parse(decrpytUserSelection);
} catch (decryptError) {
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString(),
};
}
} catch (error) {
return {
redisKey: "default",
uuid: "",
timestamp: new Date().toISOString(),
};
}
};
const functionSetUserSelection = async (userSelection: any) => {
const cookieStore = await cookies();
const encrpytUserSelection = await nextCrypto.encrypt(
JSON.stringify(userSelection)
);
if (!encrpytUserSelection) throw new Error("No user selection found");
cookieStore.set({
name: "eys-sel",
value: encrpytUserSelection,
...cookieObject,
} as any);
};
const functionRemoveUserSelection = async () => {
const cookieStore = await cookies();
cookieStore.delete("eys-sel");
};
/**
* Creates a promise that rejects after a specified timeout
* @param ms Timeout in milliseconds
* @param controller AbortController to abort the fetch request
* @returns A promise that rejects after the timeout
*/
const createTimeoutPromise = (
ms: number,
controller: AbortController
): Promise<never> => {
return new Promise((_, reject) => {
setTimeout(() => {
controller.abort();
reject(new Error(`Request timed out after ${ms}ms`));
}, ms);
});
};
/**
* Core fetch function with timeout and error handling
* @param url The URL to fetch
* @param options Fetch options
* @param headers Request headers
* @param payload Request payload
* @returns API response
*/
async function coreFetch<T>(
url: string,
options: FetchOptions = {},
headers: Record<string, string> = defaultHeaders,
payload?: any
): Promise<ApiResponse<T>> {
const { method = "POST", cache = false, timeout = DEFAULT_TIMEOUT } = options;
try {
const controller = new AbortController();
const fetchOptions: RequestInit = {
method,
headers,
cache: cache ? "force-cache" : "no-cache",
signal: controller.signal,
};
if (method !== "GET" && payload) {
fetchOptions.body = JSON.stringify(
payload.payload ? payload.payload : payload
);
}
const timeoutPromise = createTimeoutPromise(timeout, controller);
const response = await Promise.race([
fetch(url, fetchOptions),
timeoutPromise,
]);
const responseData = await response.json();
return {
status: response.status,
data: responseData || ({} as T),
};
} catch (error) {
console.error(`API Error (${url}):`, error);
return {
...DEFAULT_RESPONSE,
error: error instanceof Error ? error.message : "Network error",
} as ApiResponse<T>;
}
}
/**
* Fetch data without authentication
*/
async function fetchData<T>(
endpoint: string,
payload?: any,
method: HttpMethod = "POST",
cache: boolean = false,
timeout: number = DEFAULT_TIMEOUT
): Promise<ApiResponse<T>> {
return coreFetch<T>(
endpoint,
{ method, cache, timeout },
defaultHeaders,
payload
);
}
/**
* Fetch data with authentication token
*/
async function fetchDataWithToken<T>(
endpoint: string,
payload?: any,
method: HttpMethod = "POST",
cache: boolean = false,
timeout: number = DEFAULT_TIMEOUT
): Promise<ApiResponse<T>> {
const accessToken = await retrieveAccessToken();
const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken };
return coreFetch<T>(endpoint, { method, cache, timeout }, headers, payload);
}
/**
* Update data with authentication token and UUID
*/
async function updateDataWithToken<T>(
endpoint: string,
uuid: string,
payload?: any,
method: HttpMethod = "POST",
cache: boolean = false,
timeout: number = DEFAULT_TIMEOUT
): Promise<ApiResponse<T>> {
const accessToken = await retrieveAccessToken();
const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken };
return coreFetch<T>(
`${endpoint}/${uuid}`,
{ method, cache, timeout },
headers,
payload
);
}
export {
fetchData,
fetchDataWithToken,
updateDataWithToken,
functionRetrieveUserSelection,
functionSetUserSelection,
functionRemoveUserSelection,
};