import { FrontendVariables } from "@Front/Config/VariablesFront"; import CookieService from "@Front/Services/CookieService/CookieService"; import jwt_decode from "jwt-decode"; import JwtService, { ICustomerJwtPayload, IUserJwtPayload } from "@Front/Services/JwtService/JwtService"; import { NextResponse } from "next/server"; export enum ContentType { JSON = "application/json", PDF = "application/pdf", FORM_DATA = "multipart/form-data;", PNG = "image/png", } export type IRef = { response?: Response; }; export default abstract class BaseApiService { private static baseUrl: string; protected readonly variables = FrontendVariables.getInstance(); protected constructor() { BaseApiService.baseUrl ??= this.variables.BACK_API_PROTOCOL + this.variables.BACK_API_HOST + this.variables.BACK_API_ROOT_URL + this.variables.BACK_API_VERSION; } protected getBaseUrl(): string { return BaseApiService.baseUrl; } protected buildHeaders(contentType: ContentType) { const token = CookieService.getInstance().getCookie("leCoffreAccessToken"); const headers = new Headers(); if (contentType === ContentType.JSON || contentType === ContentType.PDF) { headers.set("Content-Type", contentType); } headers.set("Authorization", `Bearer ${token}`); return headers; } protected buildBody(body: { [key: string]: unknown }): string { return JSON.stringify(body); } protected async getRequest(url: URL, token?: string, contentType?: ContentType, ref?: IRef, fileName?: string) { await this.checkJwtToken(); const request = async () => await fetch(url, { method: "GET", headers: this.buildHeaders(contentType ?? ContentType.JSON), }); return this.sendRequest(request, ref, fileName); } protected async postRequest(url: URL, body: { [key: string]: unknown } = {}, token?: string) { await this.checkJwtToken(); return this.sendRequest( async () => await fetch(url, { method: "POST", headers: this.buildHeaders(ContentType.JSON), body: this.buildBody(body), }), ); } protected async postRequestFormData(url: URL, body: FormData) { await this.checkJwtToken(); return this.sendRequest( async () => await fetch(url, { method: "POST", headers: this.buildHeaders(ContentType.FORM_DATA), body, }), ); } protected async putRequest(url: URL, body: { [key: string]: unknown } = {}, token?: string) { await this.checkJwtToken(); const request = async () => await fetch(url, { method: "PUT", headers: this.buildHeaders(ContentType.JSON), body: this.buildBody(body), }); return this.sendRequest(request); } protected async patchRequest(url: URL, body: { [key: string]: unknown } = {}) { await this.checkJwtToken(); const request = async () => await fetch(url, { method: "PATCH", headers: this.buildHeaders(ContentType.JSON), body: this.buildBody(body), }); return this.sendRequest(request); } protected async deleteRequest(url: URL, body: { [key: string]: unknown } = {}, token?: string) { await this.checkJwtToken(); const request = async () => await fetch(url, { method: "DELETE", headers: this.buildHeaders(ContentType.JSON), body: this.buildBody(body), }); return this.sendRequest(request); } protected async putFormDataRequest(url: URL, body: FormData, token?: string) { await this.checkJwtToken(); const request = async () => await fetch(url, { method: "PUT", headers: this.buildHeaders(ContentType.FORM_DATA), body, }); return this.sendRequest(request); } private async sendRequest(request: () => Promise, ref?: IRef, fileName?: string): Promise { const response = await request(); return this.processResponse(response, request, ref, fileName); } private async checkJwtToken() { const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken"); if (!accessToken) { return; } const userDecodedToken = jwt_decode(accessToken) as IUserJwtPayload; const customerDecodedToken = jwt_decode(accessToken) as ICustomerJwtPayload; if (!userDecodedToken && !customerDecodedToken) return NextResponse.redirect(new URL("/login")); const now = Math.floor(Date.now() / 1000); if (userDecodedToken.userId && userDecodedToken.exp < now) { const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken"); if (!refreshToken) { return NextResponse.redirect(new URL("/authorized-client")); } const decodedRefreshToken = jwt_decode(refreshToken) as IUserJwtPayload | ICustomerJwtPayload; if (decodedRefreshToken.exp < now) { return NextResponse.redirect(new URL("/authorized-client")); } await JwtService.getInstance().refreshToken(refreshToken); } if (userDecodedToken.userId && userDecodedToken.exp < now) { const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken"); if (!refreshToken) { return NextResponse.redirect(new URL("/id360/customer-callback")); } const decodedRefreshToken = jwt_decode(refreshToken) as IUserJwtPayload | ICustomerJwtPayload; if (decodedRefreshToken.exp < now) { return NextResponse.redirect(new URL("/id360/customer-callback")); } await JwtService.getInstance().refreshToken(refreshToken); } return; } protected async processResponse(response: Response, request: () => Promise, ref?: IRef, fileName?: string): Promise { let responseContent: T; ref && (ref["response"] = response); if (response.ok) { // Check the Content-Type header to determine the response type const contentType = response.headers.get("Content-Type"); if (contentType && !contentType.includes("application/json")) { responseContent = (await response.blob()) as T; } else { // Handle JSON response try { responseContent = await response.json(); } catch (err) { return Promise.reject(err); } } } else { // Handle error response const responseCopy = response.clone(); try { const responseJson = await response.json(); return Promise.reject(responseJson); } catch (err) { const responseText = await responseCopy.text(); return Promise.reject({ http_status: response.status, message: responseText, }); } } return responseContent; } protected onError(error: unknown) { //console.error(error); } } export interface IResponse { http_status: number; }