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, evitaloop, url, method, mydata, setAuthToken = false) { const userStore = useUserStore(); if (status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_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('', ''); const $router = useRouter() throw { code: toolsext.ERR_RETRY_LOGIN }; } } catch (err2) { console.error('Errore durante il refresh token:', err2); let mystatus = err2?.code || err2?.status if (mystatus === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN || 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_FORBIDDEN_INVALID_TOKEN} ; } } else if (status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) { userStore.setAuth('', ''); const $router = useRouter() throw { status: toolsext.ERR_RETRY_LOGIN }; } return null; }, // Base per la chiamata con gestione degli errori e retry async SendReqBase(url, method, mydata, setAuthToken = false, evitaloop = false, myformdata, responsedata, options) { 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_FORBIDDEN_INVALID_TOKEN) { userStore.setServerCode(toolsext.ERR_AUTHENTICATION); userStore.setAuth('', ''); throw { code: toolsext.ERR_AUTHENTICATION }; } // Verifica sul token (funzione custom) const ret = await this.checkTokenScaduto(res.status, evitaloop, url, method, mydata, setAuthToken); 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); const ret = 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, method, mydata, setAuthToken = false, evitaloop = false, retryCount = 1, retryDelay = 5000, myformdata = null, responsedata = null, options = null) { try { return await this.SendReqBase(url, method, mydata, setAuthToken, evitaloop, myformdata, responsedata, options); } catch (error) { // Se lo status non è 403 e sono rimasti tentativi, eseguo il retry const riprova = error.status !== 403 && 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 }, }