/
bytevalue
/
optimal
Обзор
Документация
Войти
/
bytevalue
/
optimal
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/main/resources/static/js/api.js
345 строк
10 KB
bytevalue
Edit chat title
08 дек 2025, 13:41
08 дек 2025, 13:41
768e132
Код
Авторство
О чём код?
class ApiService { constructor() { this.isHealthy = false; this.retryQueue = []; this.cache = new Map(); this.cacheTimestamps = new Map(); } /** * Generic fetch wrapper */ async fetch(url, options = {}) { const fullUrl = `${CONFIG.API.BASE_URL}${url}`; const headers = { 'Content-Type': 'application/json', 'X-User-Id': stateService.getState('userId'), ...options.headers, }; const config = { timeout: CONFIG.API.TIMEOUT, retries: options.retries ?? CONFIG.API.RETRY_ATTEMPTS, ...options, headers, }; let lastError; for (let i = 0; i <= config.retries; i++) { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), config.timeout); const fetchConfig = { ...config, signal: controller.signal }; const response = await fetch(fullUrl, fetchConfig); clearTimeout(timeoutId); if (!response.ok) { throw new Error( `HTTP ${response.status}: ${response.statusText}` ); } // For DELETE requests, return success status if (config.method === 'DELETE' && response.status === 200) { return { success: true }; } // For empty responses if (response.status === 204) { return { success: true }; } return await response.json(); } catch (error) { lastError = error; console.warn( `Request failed (attempt ${i + 1}/${config.retries + 1}):`, error.message ); if (i < config.retries) { await this.delay(CONFIG.API.RETRY_DELAY * Math.pow(2, i)); } } } throw this.handleError(lastError); } /** * Health check */ async checkHealth() { try { const response = await fetch( `${CONFIG.API.BASE_URL}${CONFIG.ENDPOINTS.HEALTH}`, { timeout: 5000 } ); this.isHealthy = response.ok; console.log('✅ Health check:', this.isHealthy ? 'OK' : 'FAILED'); return this.isHealthy; } catch (error) { console.error('❌ Health check failed:', error); this.isHealthy = false; return false; } } /** * Get active chats for user */ async getActiveChats() { try { console.log('📥 Fetching active chats...'); const response = await this.fetch(CONFIG.ENDPOINTS.GET_USER_CHATS); console.log('✅ Active chats fetched:', response); return response; } catch (error) { console.error('❌ Failed to fetch active chats:', error); throw error; } } /** * Get deleted chats for user */ async getDeletedChats() { try { console.log('📥 Fetching deleted chats...'); const response = await this.fetch(CONFIG.ENDPOINTS.GET_DELETED_CHATS); console.log('✅ Deleted chats fetched:', response); return response; } catch (error) { console.error('❌ Failed to fetch deleted chats:', error); throw error; } } /** * Get messages for specific chat */ async getMessages(chatId) { try { console.log(`📥 Fetching messages for chat ${chatId}...`); const response = await this.fetch( CONFIG.ENDPOINTS.CHAT_MESSAGES(chatId) ); console.log('✅ Messages fetched:', response); return response; } catch (error) { console.error('❌ Failed to fetch messages:', error); throw error; } } /** * Get messages with cache busting */ async getMessagesWithCacheBust(chatId, timestamp) { try { console.log(`📥 Fetching messages for chat ${chatId} (cache bust: ${timestamp})...`); const url = `${CONFIG.ENDPOINTS.CHAT_MESSAGES(chatId)}?t=${timestamp}`; const response = await this.fetch(url, { headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' } }); console.log('✅ Messages fetched with cache bust:', response); return response; } catch (error) { console.error('❌ Failed to fetch messages with cache bust:', error); throw error; } } /** * Send message */ async sendMessage(chatId, messageText) { try { console.log(`📤 Sending message to chat ${chatId}...`); const response = await this.fetch(CONFIG.ENDPOINTS.SEND_MESSAGE, { method: 'POST', body: JSON.stringify({ chatId, message: messageText, userId: stateService.getState('userId'), }), }); console.log('✅ Message sent:', response); return response; } catch (error) { console.error('❌ Failed to send message:', error); throw error; } } /** * Create new chat */ async createChat(title = '') { try { console.log('📝 Creating new chat...'); const response = await this.fetch(CONFIG.ENDPOINTS.CREATE_CHAT, { method: 'POST', body: JSON.stringify({ title: title || `Chat ${new Date().toLocaleString()}`, userId: stateService.getState('userId'), }), }); console.log('✅ Chat created:', response); return response; } catch (error) { console.error('❌ Failed to create chat:', error); throw error; } } /** * Rename chat */ async renameChat(chatId, newTitle) { try { console.log(`✏️ Renaming chat ${chatId} to "${newTitle}"...`); const response = await this.fetch(CONFIG.ENDPOINTS.RENAME_CHAT(chatId), { method: 'PATCH', body: JSON.stringify({ newTitle }), }); console.log('✅ Chat renamed:', response); return response; } catch (error) { console.error('❌ Failed to rename chat:', error); throw error; } } /** * Get message status */ async getMessageStatus(messageId) { try { console.log(`📥 Fetching message status for ${messageId}...`); const response = await this.fetch( CONFIG.ENDPOINTS.MESSAGE_STATUS(messageId) ); console.log('✅ Message status fetched:', response); return response; } catch (error) { console.error('❌ Failed to get message status:', error); throw error; } } /** * Soft delete chat */ async deleteChat(chatId) { try { console.log(`🗑️ Soft deleting chat ${chatId}...`); const response = await this.fetch( CONFIG.ENDPOINTS.DELETE_CHAT(chatId), { method: 'DELETE', } ); console.log('✅ Chat soft deleted:', response); return response; } catch (error) { console.error('❌ Failed to delete chat:', error); throw error; } } /** * Restore deleted chat */ async restoreChat(chatId) { try { console.log(`♻️ Restoring chat ${chatId}...`); const response = await this.fetch( CONFIG.ENDPOINTS.RESTORE_CHAT(chatId), { method: 'POST', } ); console.log('✅ Chat restored:', response); return response; } catch (error) { console.error('❌ Failed to restore chat:', error); throw error; } } /** * Permanently delete chat */ async permanentDeleteChat(chatId) { try { console.log(`🔥 Permanently deleting chat ${chatId}...`); const response = await this.fetch( CONFIG.ENDPOINTS.PERMANENT_DELETE_CHAT(chatId), { method: 'DELETE', } ); console.log('✅ Chat permanently deleted:', response); return response; } catch (error) { console.error('❌ Failed to permanently delete chat:', error); throw error; } } /** * Invalidate cache for specific chat */ invalidateChatCache(chatId) { console.log(`🗑️ Invalidating cache for chat ${chatId}`); // Удаляем кэш для этого чата const cacheKey = `messages_${chatId}`; this.cache.delete(cacheKey); this.cacheTimestamps.delete(cacheKey); // Удаляем сообщения из состояния (если они есть) if (stateService.getState(`messages.${chatId}`)) { stateService.setState(`messages.${chatId}`, null); } // Публикуем событие для UI eventBus.publish('cache:invalidated', { chatId }); } /** * Delay helper */ delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } /** * Handle error */ handleError(error) { const message = error.name === 'AbortError' ? CONFIG.ERRORS.TIMEOUT : error.message.includes('Failed to fetch') ? CONFIG.ERRORS.NETWORK : error.message || CONFIG.ERRORS.SERVER; return new Error(message); } } const apiService = new ApiService(); console.log('🌐 API service ready');