Files
myprojplanet_vite/src/store/Api/index.ts
2025-11-21 20:47:35 +01:00

468 lines
14 KiB
TypeScript
Executable File

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<void> {
// 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;
},
};