import apiClient from './apiClient.js'; const ENDPOINTS = [ { label: 'Health', method: 'GET', path: '/api/health', description: 'Core service health check' }, { label: 'Market Stats', method: 'GET', path: '/api/market/stats', description: 'Global market metrics' }, { label: 'Top Coins', method: 'GET', path: '/api/coins/top', description: 'Top market cap coins', params: 'limit=10' }, { label: 'Latest News', method: 'GET', path: '/api/news/latest', description: 'Latest curated news', params: 'limit=20' }, { label: 'Chart History', method: 'GET', path: '/api/charts/price/BTC', description: 'Historical price data', params: 'timeframe=7d' }, { label: 'Chart AI Analysis', method: 'POST', path: '/api/charts/analyze', description: 'AI chart insights', body: '{"symbol":"BTC","timeframe":"7d"}' }, { label: 'Sentiment Analysis', method: 'POST', path: '/api/sentiment/analyze', description: 'Run sentiment models', body: '{"text":"Bitcoin rally","mode":"auto"}' }, { label: 'News Summarize', method: 'POST', path: '/api/news/summarize', description: 'Summarize a headline', body: '{"title":"Headline","body":"Full article"}' }, ]; class ApiExplorerView { constructor(section) { this.section = section; this.endpointSelect = section?.querySelector('[data-api-endpoint]'); this.methodSelect = section?.querySelector('[data-api-method]'); this.paramsInput = section?.querySelector('[data-api-params]'); this.bodyInput = section?.querySelector('[data-api-body]'); this.sendButton = section?.querySelector('[data-api-send]'); this.responseNode = section?.querySelector('[data-api-response]'); this.metaNode = section?.querySelector('[data-api-meta]'); } init() { if (!this.section) return; this.populateEndpoints(); this.bindEvents(); this.applyPreset(ENDPOINTS[0]); } populateEndpoints() { if (!this.endpointSelect) return; this.endpointSelect.innerHTML = ENDPOINTS.map((endpoint, index) => ``).join(''); } bindEvents() { this.endpointSelect?.addEventListener('change', () => { const index = Number(this.endpointSelect.value); this.applyPreset(ENDPOINTS[index]); }); this.sendButton?.addEventListener('click', () => this.sendRequest()); } applyPreset(preset) { if (!preset) return; if (this.methodSelect) { this.methodSelect.value = preset.method; } if (this.paramsInput) { this.paramsInput.value = preset.params || ''; } if (this.bodyInput) { this.bodyInput.value = preset.body || ''; } this.section.querySelector('[data-api-description]').textContent = preset.description; this.section.querySelector('[data-api-path]').textContent = preset.path; } async sendRequest() { const index = Number(this.endpointSelect?.value || 0); const preset = ENDPOINTS[index]; const method = this.methodSelect?.value || preset.method; let endpoint = preset.path; const params = (this.paramsInput?.value || '').trim(); if (params) { endpoint += endpoint.includes('?') ? `&${params}` : `?${params}`; } let body = this.bodyInput?.value.trim(); if (!body) body = undefined; let parsedBody; if (body && method !== 'GET') { try { parsedBody = JSON.parse(body); } catch (error) { this.renderError('Invalid JSON body'); return; } } this.renderMeta('pending'); this.renderResponse('Fetching...'); const started = performance.now(); const result = await apiClient.request(method, endpoint, { cache: false, body: parsedBody }); const duration = Math.round(performance.now() - started); if (!result.ok) { this.renderError(result.error || 'Request failed', duration); return; } this.renderMeta('ok', duration, method, endpoint); this.renderResponse(result.data); } renderResponse(data) { if (!this.responseNode) return; if (typeof data === 'string') { this.responseNode.textContent = data; return; } this.responseNode.textContent = JSON.stringify(data, null, 2); } renderMeta(status, duration = 0, method = '', path = '') { if (!this.metaNode) return; if (status === 'pending') { this.metaNode.textContent = 'Sending request...'; return; } this.metaNode.textContent = `${method} ${path} • ${duration}ms`; } renderError(message, duration = 0) { this.renderMeta('error', duration); this.renderResponse({ error: message }); } } export default ApiExplorerView;