import { useGlobalStore } from '@store/globalStore'; import { useUserStore } from '@store/UserStore'; export * from './ApiTypes'; import axios from 'axios'; export { addAuthHeaders, API_URL } from './Instance'; // import {AlgoliaSearch} from './AlgoliaController' import Paths from '@paths'; import { tools } from '@src/store/Modules/tools'; import { toolsext } from '@src/store/Modules/toolsext'; import { serv_constants } from '@src/store/Modules/serv_constants'; import type * as Types from '@src/store/Api/ApiTypes'; import { costanti } from '@src/store/Modules/costanti'; import * as ApiTables from '@src/store/Modules/ApiTables'; import sendRequest from './Inst-Pao'; import Request from './Instance'; import globalroutines from '../../globalroutines/index'; import { useRouter } from 'vue-router'; function ReceiveResponsefromServer( tablesync: string, nametab: string, method: string, risdata: any ) { // console.log('ReceiveResponsefromServer', nametab, method, risdata) if (risdata) { // Updated somw data after Server arrived data. if (method === 'PATCH') { if (nametab === 'projects') { if (risdata.projectris) { const copyrec = tools.jsonCopy(risdata.projectris); // +*Todo conv: Projects.updateProject({ objproj: copyrec }) } } } } } // const algoliaApi = new AlgoliaSearch() export const Api = { async post(path: string, payload?: any, responsedata?: any, options?: any) { const globalStore = useGlobalStore(); globalStore.connData.downloading_server = 1; globalStore.connData.uploading_server = 1; return await Request('post', path, payload, responsedata, options); }, async postFormData(path: string, payload?: any, responsedata?: any) { const globalStore = useGlobalStore(); globalStore.connData.uploading_server = 1; globalStore.connData.downloading_server = 1; return await Request('postFormData', path, payload, responsedata); }, async get(path: string, payload?: any, responsedata?: any) { const globalStore = useGlobalStore(); globalStore.connData.downloading_server = 1; globalStore.connData.uploading_server = 0; return await Request('get', path, payload, responsedata); }, async put(path: string, payload?: any, responsedata?: any) { const globalStore = useGlobalStore(); globalStore.connData.uploading_server = 1; return await Request('put', path, payload, responsedata); }, async patch(path: string, payload?: any, responsedata?: any) { const globalStore = useGlobalStore(); globalStore.connData.uploading_server = 1; return await Request('patch', path, payload, responsedata); }, async Delete(path: string, payload: any, responsedata?: any) { const globalStore = useGlobalStore(); globalStore.connData.uploading_server = 1; return await Request('delete', path, payload, responsedata); }, async checkSession({ token, refresh_token }: any) { return await axios.post( import.meta.env.VITE_API_URL + Paths.TOKEN_REFRESH, { refresh_token, }, { headers: { Authorization: `Bearer ${token}`, }, } ); }, async refreshToken() { const userStore = useUserStore(); try { const refrTok = localStorage.getItem(toolsext.localStorage.refreshToken); if (!refrTok || refrTok === 'undefined') { //throw new Error('Refresh token non disponibile'); return false; } const response = await sendRequest('/users/newtok', 'POST', { refreshToken: refrTok, }); if (response && response.data) { // Salva il nuovo access token localStorage.setItem(toolsext.localStorage.token, response.data.token); // Aggiorna il refresh token se fornito dal server if (response.data.refreshToken) { userStore.setRefreshToken(response.data.refreshToken); localStorage.setItem( toolsext.localStorage.refreshToken, response.data.refreshToken ); } return response.data.token; } else { throw new Error('Risposta del server non valida durante il refresh token'); } } catch (error) { console.error('Errore durante il refresh token:', error); // Logout dell'utente in caso di errore critico // userStore.setAuth('', ''); // localStorage.removeItem(toolsext.localStorage.token); // localStorage.removeItem(toolsext.localStorage.refreshToken); throw error; } }, async checkTokenScaduto( status: number, evitaloop: boolean, url: string, method: string, mydata: any, setAuthToken: boolean = false, statuscode2: number = 0 ) { const userStore = useUserStore(); if ( status === serv_constants.RIS_CODE__HTTP_TOKEN_EXPIRED || statuscode2 === serv_constants.RIS_CODE__HTTP_TOKEN_EXPIRED ) { try { console.log('Token scaduto. Tentativo di refresh...'); const newAccessToken = await this.refreshToken(); if (newAccessToken) { userStore.setAuth(newAccessToken, userStore.refreshToken); if (!evitaloop) { console.log('Nuovo token ottenuto. Riprovo la richiesta...'); return await this.SendReq(url, method, mydata, setAuthToken, true); } } else { // Se il refresh token fallisce, logout dell'utente // userStore.setAuth('', ''); throw { code: toolsext.ERR_RETRY_LOGIN }; } } catch (err2) { console.error('Errore durante il check Token Scaduto:', err2); let mystatus = err2?.code || err2?.status; if ( mystatus === serv_constants.RIS_CODE__HTTP_INVALID_TOKEN || mystatus === serv_constants.RIS_CODE__HTTP_FORBIDDEN_PERMESSI || mystatus === toolsext.ERR_RETRY_LOGIN ) { userStore.setServerCode(toolsext.ERR_AUTHENTICATION); userStore.setAuth('', ''); throw { status: toolsext.ERR_RETRY_LOGIN }; } // Gestione di altri errori critici throw err2 || { status: serv_constants.RIS_CODE__HTTP_INVALID_TOKEN }; } } else if ( // status === serv_constants.RIS_CODE__HTTP_INVALID_TOKEN || status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_PERMESSI // || statuscode2 === serv_constants.RIS_CODE__HTTP_INVALID_TOKEN ) { userStore.setAuth('', ''); throw { status: toolsext.ERR_RETRY_LOGIN }; } return null; }, // Base per la chiamata con gestione degli errori e retry async SendReqBase( url: string, method: string, mydata: any, setAuthToken = false, evitaloop = false, myformdata: any, responsedata: any, options: any ) { const mydataout = { ...mydata, keyappid: import.meta.env.VITE_PAO_APP_ID, idapp: tools.getEnv('VITE_APP_ID'), }; const userStore = useUserStore(); const globalStore = useGlobalStore(); userStore.setServerCode(tools.EMPTY); userStore.setResStatus(0); try { const res = await sendRequest( url, method, mydataout, myformdata, responsedata, options ); // Aggiornamento dello stato della connessione dopo 1 secondo setTimeout(() => { if (method.toLowerCase() === 'get') { globalStore.connData.downloading_server = 0; } else { globalStore.connData.uploading_server = 0; globalStore.connData.downloading_server = 0; } }, 1000); if (res.status === serv_constants.RIS_CODE__HTTP_INVALID_TOKEN) { userStore.setServerCode(toolsext.ERR_AUTHENTICATION); userStore.setAuth('', ''); // throw { code: toolsext.ERR_AUTHENTICATION }; throw { status: toolsext.ERR_RETRY_LOGIN }; } // Verifica sul token (funzione custom) const ret: any = await this.checkTokenScaduto( res.status, evitaloop, url, method, mydata, setAuthToken, res.data!.statuscode2! ); if (ret) return ret; if (tools.isDebug()) console.log(' ----> ', res); return res; } catch (error) { setTimeout(() => { if (method.toLowerCase() === 'get') { globalStore.connData.downloading_server = -1; } else { globalStore.connData.uploading_server = -1; globalStore.connData.downloading_server = -1; } }, 1000); if (error.status === serv_constants.RIS_CODE__HTTP_INVALID_TOKEN) { userStore.setServerCode(toolsext.ERR_AUTHENTICATION); userStore.setAuth('', ''); // throw { code: toolsext.ERR_AUTHENTICATION }; throw { status: toolsext.ERR_RETRY_LOGIN }; } const ret: any = await this.checkTokenScaduto( error.status, evitaloop, url, method, mydataout, setAuthToken ); if (ret) return ret; console.error('Errore nella richiesta:', error); throw error; } }, /** * Creates a Promise that resolves after a specified number of milliseconds. * Useful for creating delayed operations or pause in async functions. * * @param ms - The number of milliseconds to delay * @returns A Promise that resolves after the specified delay * * @example * // Basic usage * await delay(1000); // waits for 1 second * * @example * // Usage in an async function * async function example() { * console.log('Start'); * await delay(2000); * console.log('2 seconds later'); * } * * @example * // Usage with Promise chaining * delay(1000).then(() => console.log('1 second passed')); */ async delay(ms: number): Promise { // Input validation if (ms < 0) { throw new Error('Delay time cannot be negative'); } return new Promise((resolve) => setTimeout(resolve, ms)); }, // Funzione che gestisce la chiamata con retry async SendReq( url: string, method: string, mydata: any, setAuthToken = false, evitaloop = false, retryCount = 1, retryDelay = 5000, myformdata: any = null, responsedata: any = null, options: any = null ) { try { return await this.SendReqBase( url, method, mydata, setAuthToken, evitaloop, myformdata, responsedata, options ); } catch (error) { // Se lo status non è 403 (RIS_CODE__HTTP_FORBIDDEN_PERMESSI) e sono rimasti tentativi, eseguo il retry const riprova = error && error.status !== serv_constants.RIS_CODE__HTTP_INVALID_TOKEN && error.status !== serv_constants.RIS_CODE__HTTP_FORBIDDEN_PERMESSI && error.status !== toolsext.ERR_RETRY_LOGIN; if (retryCount > 0 && riprova) { console.log(`❌❌❌ Retrying request. Attempts remaining: ${retryCount}`); await this.delay(retryDelay); return this.SendReq( url, method, mydata, setAuthToken, evitaloop, retryCount - 1, retryDelay, myformdata, responsedata ); } throw error; } }, async syncAlternative(mystrparam: string) { console.log('[ALTERNATIVE Background syncing', mystrparam); const multiparams = mystrparam.split('|'); if (multiparams) { if (multiparams.length > 3) { const cmd = multiparams[0]; const tablesync = multiparams[1]; const nametab = multiparams[2]; const method = multiparams[3]; // const token = multiparams[3] if (cmd === ApiTables.DB.CMD_SYNC) { let errorfromserver = false; let lettoqualcosa = false; // console.log('A1) INIZIO.............................................................') return globalroutines('readall', tablesync, null) .then((alldata) => { if (alldata === undefined) { console.log('alldata NON DEFINITA'); return true; } const myrecs = [...alldata]; const promises = myrecs.map((rec) => { let link = `/${ApiTables.getLinkByTableName(nametab)}`; if (method !== 'POST') { link += `/${rec._id}`; } console.log('----------------------- LEGGO QUALCOSA ', link); // Insert/Delete/Update table to the server return this.SendReq(link, method, rec) .then((ris) => { ReceiveResponsefromServer(tablesync, nametab, method, ris.data); lettoqualcosa = true; return globalroutines('delete', tablesync, null, rec._id); }) .then(() => { return globalroutines('delete', 'swmsg', null, mystrparam); }) .catch((err) => { if (err.msgerr) { if ( err.msgerr.message.includes('Failed to fetch') || err.msgerr.message.includes('Network Error') ) { errorfromserver = true; } } console.log( ' [Alternative] !!!!!!!!!!!!!!! Error while sending data', err, errorfromserver, 'lettoqualcosa', lettoqualcosa ); if (!errorfromserver) { return globalroutines('delete', 'swmsg', null, mystrparam); } }); }); // CALL ALL THE PROMISES return Promise.all(promises) .then(() => errorfromserver && !lettoqualcosa) .catch((err) => errorfromserver && !lettoqualcosa); }) .catch((error) => { console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ errorfromserver:', errorfromserver, error); return errorfromserver && !lettoqualcosa; }) .then((error) => { const mystate = error || errorfromserver ? 'offline' : 'online'; const globalStore = useGlobalStore(); globalStore.setStateConnection(mystate); globalStore.saveConfig({ _id: costanti.CONFIG_ID_STATE_CONN, value: mystate, }); }); } } } return null; }, };