Spaces:
Running
Running
| /** | |
| * BIST Predictor β API Δ°letiΕim ModΓΌlΓΌ | |
| * Backend REST API ve SSE stream yΓΆnetimi. | |
| */ | |
| const API = { | |
| BASE_URL: window.location.origin, | |
| /** SSE event source instance */ | |
| _eventSource: null, | |
| _sseListeners: [], | |
| // βββ HTTP Δ°stekleri βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async _fetch(endpoint, options = {}) { | |
| try { | |
| const url = `${this.BASE_URL}/api${endpoint}`; | |
| const response = await fetch(url, { | |
| headers: { 'Content-Type': 'application/json' }, | |
| ...options, | |
| }); | |
| if (!response.ok) { | |
| const error = await response.json().catch(() => ({ detail: response.statusText })); | |
| throw new Error(error.detail || `HTTP ${response.status}`); | |
| } | |
| return await response.json(); | |
| } catch (error) { | |
| console.error(`API Error [${endpoint}]:`, error); | |
| throw error; | |
| } | |
| }, | |
| async get(endpoint) { | |
| return this._fetch(endpoint); | |
| }, | |
| async post(endpoint, data = null) { | |
| const options = { method: 'POST' }; | |
| if (data) options.body = JSON.stringify(data); | |
| return this._fetch(endpoint, options); | |
| }, | |
| // βββ Dashboard ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async getDashboard(horizon = 10) { | |
| return this.get(`/dashboard?horizon=${horizon}`); | |
| }, | |
| async getStocks() { | |
| return this.get('/stocks'); | |
| }, | |
| async getStockDetail(symbol, horizon = 10) { | |
| return this.get(`/stock/${symbol}?horizon=${horizon}`); | |
| }, | |
| // βββ Tahminler ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async getPredictions(symbol, horizon = 10) { | |
| return this.get(`/predictions/${symbol}?horizon=${horizon}`); | |
| }, | |
| async triggerPrediction(symbol, horizons = '10') { | |
| return this.post(`/predict/${symbol}?horizons=${horizons}`); | |
| }, | |
| async triggerAllPredictions() { | |
| return this.post('/predict-all'); | |
| }, | |
| // βββ GΓΌven PuanΔ± ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async getConfidence(symbol, horizon = 10) { | |
| return this.get(`/confidence/${symbol}?horizon=${horizon}`); | |
| }, | |
| async getConfidenceRanking(horizon = 10) { | |
| return this.get(`/confidence-ranking?horizon=${horizon}`); | |
| }, | |
| // βββ KarΕΔ±laΕtΔ±rma ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async getComparison(symbol, horizon = 10) { | |
| return this.get(`/comparison/${symbol}?horizon=${horizon}`); | |
| }, | |
| // βββ Veri YΓΆnetimi ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async loadInitialData() { | |
| return this.post('/data/load'); | |
| }, | |
| async updateStockData(symbol) { | |
| return this.post(`/data/update/${symbol}`); | |
| }, | |
| async triggerComparison() { | |
| return this.post('/data/compare'); | |
| }, | |
| // βββ Sistem βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async getSystemStatus() { | |
| return this.get('/system/status'); | |
| }, | |
| async getSystemLogs(limit = 50) { | |
| return this.get(`/system/logs?limit=${limit}`); | |
| }, | |
| // βββ SSE (Server-Sent Events) ββββββββββββββββββββββββββββββββββββββββββββ | |
| connectSSE() { | |
| if (this._eventSource) { | |
| this._eventSource.close(); | |
| } | |
| this._eventSource = new EventSource(`${this.BASE_URL}/api/stream`); | |
| this._eventSource.onopen = () => { | |
| console.log('SSE baΔlantΔ±sΔ± kuruldu'); | |
| this._notifyListeners('connected', {}); | |
| }; | |
| this._eventSource.onmessage = (event) => { | |
| try { | |
| const parsed = JSON.parse(event.data); | |
| const { type, data, timestamp } = parsed; | |
| this._notifyListeners(type, data, timestamp); | |
| } catch (e) { | |
| console.warn('SSE parse hatasΔ±:', e); | |
| } | |
| }; | |
| this._eventSource.onerror = (error) => { | |
| console.warn('SSE baΔlantΔ± hatasΔ±, yeniden baΔlanΔ±lΔ±yor...'); | |
| this._notifyListeners('disconnected', {}); | |
| // Otomatik yeniden baΔlanma (EventSource bunu otomatik yapar) | |
| }; | |
| }, | |
| disconnectSSE() { | |
| if (this._eventSource) { | |
| this._eventSource.close(); | |
| this._eventSource = null; | |
| } | |
| }, | |
| onSSE(callback) { | |
| this._sseListeners.push(callback); | |
| }, | |
| offSSE(callback) { | |
| this._sseListeners = this._sseListeners.filter(cb => cb !== callback); | |
| }, | |
| _notifyListeners(type, data, timestamp) { | |
| for (const listener of this._sseListeners) { | |
| try { | |
| listener(type, data, timestamp); | |
| } catch (e) { | |
| console.error('SSE listener hatasΔ±:', e); | |
| } | |
| } | |
| }, | |
| }; | |