Initial commit

This commit is contained in:
dahoud
2025-10-01 01:39:07 +00:00
commit b430bf3b96
826 changed files with 255287 additions and 0 deletions

157
services/cacheService.ts Normal file
View File

@@ -0,0 +1,157 @@
/**
* Service de cache pour optimiser les performances
*/
export interface CacheEntry<T> {
data: T;
timestamp: number;
ttl: number; // Time to live en millisecondes
}
export class CacheService {
private static cache = new Map<string, CacheEntry<any>>();
private static readonly DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes par défaut
/**
* Stocke une valeur dans le cache
*/
static set<T>(key: string, data: T, ttl: number = this.DEFAULT_TTL): void {
const entry: CacheEntry<T> = {
data,
timestamp: Date.now(),
ttl
};
this.cache.set(key, entry);
}
/**
* Récupère une valeur du cache
*/
static get<T>(key: string): T | null {
const entry = this.cache.get(key);
if (!entry) {
return null;
}
// Vérifier si l'entrée a expiré
if (Date.now() - entry.timestamp > entry.ttl) {
this.cache.delete(key);
return null;
}
return entry.data as T;
}
/**
* Supprime une entrée du cache
*/
static delete(key: string): boolean {
return this.cache.delete(key);
}
/**
* Vide tout le cache
*/
static clear(): void {
this.cache.clear();
}
/**
* Nettoie les entrées expirées
*/
static cleanup(): void {
const now = Date.now();
for (const [key, entry] of this.cache.entries()) {
if (now - entry.timestamp > entry.ttl) {
this.cache.delete(key);
}
}
}
/**
* Récupère ou exécute une fonction avec mise en cache
*/
static async getOrSet<T>(
key: string,
fetchFunction: () => Promise<T>,
ttl: number = this.DEFAULT_TTL
): Promise<T> {
// Essayer de récupérer depuis le cache
const cached = this.get<T>(key);
if (cached !== null) {
return cached;
}
// Exécuter la fonction et mettre en cache
try {
const data = await fetchFunction();
this.set(key, data, ttl);
return data;
} catch (error) {
// Ne pas mettre en cache les erreurs
throw error;
}
}
/**
* Invalide le cache pour un pattern de clés
*/
static invalidatePattern(pattern: string): void {
const regex = new RegExp(pattern);
for (const key of this.cache.keys()) {
if (regex.test(key)) {
this.cache.delete(key);
}
}
}
/**
* Obtient les statistiques du cache
*/
static getStats(): {
size: number;
keys: string[];
expired: number;
} {
const now = Date.now();
let expired = 0;
for (const [key, entry] of this.cache.entries()) {
if (now - entry.timestamp > entry.ttl) {
expired++;
}
}
return {
size: this.cache.size,
keys: Array.from(this.cache.keys()),
expired
};
}
}
// Nettoyage automatique toutes les 10 minutes
if (typeof window !== 'undefined') {
setInterval(() => {
CacheService.cleanup();
}, 10 * 60 * 1000);
}
// Clés de cache prédéfinies
export const CacheKeys = {
CLIENTS: 'clients',
CHANTIERS: 'chantiers',
DEVIS: 'devis',
FACTURES: 'factures',
DASHBOARD_STATS: 'dashboard_stats',
USER_PROFILE: 'user_profile',
// Fonctions utilitaires pour générer des clés
clientById: (id: string) => `client_${id}`,
chantierId: (id: string) => `chantier_${id}`,
devisById: (id: string) => `devis_${id}`,
factureById: (id: string) => `facture_${id}`,
devisByClient: (clientId: string) => `devis_client_${clientId}`,
facturesByClient: (clientId: string) => `factures_client_${clientId}`,
} as const;