// Accordance API Integration Module // This module provides functions to query Accordance Bible Software via OSC // for enhanced word information to display in popup cards /** * Query Accordance for word information * @param {string} word - The word to look up * @param {string} reference - Optional Bible reference (e.g., "John 3:16") * @returns {Promise} Enhanced word information from Accordance */ export async function queryAccordanceWord(word, reference = null) { try { // Build request payload const payload = { word: word, reference: reference || getCurrentReference() }; console.log('[Accordance API] Querying word:', payload); // Send request to server endpoint which proxies to Accordance via OSC const response = await fetch('/api/accordance/word', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); console.log('[Accordance API] Response status:', response.status); if (!response.ok) { const errorData = { success: false, error: `HTTP ${response.status}`, word: word, reference: reference }; console.warn('[Accordance API] Response not OK:', errorData); return errorData; } const data = await response.json(); console.log('[Accordance API] Response data:', data); return data; } catch (error) { console.warn('[Accordance API] Failed to query word:', word, error); // Return error object instead of null so enhancement function can process it return { success: false, error: error.message || 'Network error', word: word, reference: reference }; } } /** * Get current Bible reference from active tab * @returns {string|null} Current reference or null */ function getCurrentReference() { try { const activeTab = window.bibleApp?.tabs?.find(t => t.id === window.bibleApp?.activeTabId); if (!activeTab) return null; const book = activeTab.book || ''; const chapter = activeTab.chapter || ''; const verse = activeTab.verse || ''; if (book && chapter) { return verse ? `${book} ${chapter}:${verse}` : `${book} ${chapter}`; } return null; } catch (_) { return null; } } /** * Enhance word info object with Accordance data * @param {Object} wordInfo - Base word info object * @param {string} word - The word being looked up * @param {string} reference - Optional Bible reference * @returns {Promise} Enhanced word info with Accordance data */ export async function enhanceWordInfoWithAccordance(wordInfo, word, reference = null) { try { console.log('[Accordance API] Enhancing word info for:', word, 'reference:', reference); const accordanceData = await queryAccordanceWord(word, reference); console.log('[Accordance API] Received data:', accordanceData); // Merge Accordance data into word info const enhanced = { ...wordInfo }; // Always add Accordance section - this ensures it shows up in the popup if (!accordanceData) { // No response at all enhanced.accordance = { available: true, attempted: true, error: 'No response from Accordance API', note: 'Accordance integration attempted but no response received' }; console.log('[Accordance API] No response data, adding error info'); } else if (accordanceData.success) { // Success - add all the data enhanced.accordance = { available: true, strongs: accordanceData.strongs || null, lexicalForm: accordanceData.lexicalForm || null, morphology: accordanceData.morphology || null, definition: accordanceData.definition || null, usage: accordanceData.usage || null, crossReferences: accordanceData.crossReferences || [], commentaries: accordanceData.commentaries || [], originalLanguage: accordanceData.originalLanguage || null, note: accordanceData.note || null }; console.log('[Accordance API] Enhanced wordInfo with Accordance data:', enhanced.accordance); } else { // Failed - still show section with error enhanced.accordance = { available: true, attempted: true, error: accordanceData.error || 'Accordance query failed', note: accordanceData.note || 'Accordance integration attempted but no data received' }; console.log('[Accordance API] Accordance query failed, adding error info:', enhanced.accordance); } console.log('[Accordance API] Final enhanced wordInfo:', enhanced); // Enhance Greek data if available (guard derefs: enhanced.greek may be undefined) if (accordanceData.greek && !(enhanced.greek && enhanced.greek.text)) { enhanced.greek = { text: accordanceData.greek.text || (enhanced.greek && enhanced.greek.text), transliteration: accordanceData.greek.transliteration || (enhanced.greek && enhanced.greek.transliteration), meaning: accordanceData.greek.meaning || (enhanced.greek && enhanced.greek.meaning) }; } // Enhance Hebrew data if available (guard derefs: enhanced.hebrew may be undefined) if (accordanceData.hebrew && !(enhanced.hebrew && enhanced.hebrew.text)) { enhanced.hebrew = { text: accordanceData.hebrew.text || (enhanced.hebrew && enhanced.hebrew.text), transliteration: accordanceData.hebrew.transliteration || (enhanced.hebrew && enhanced.hebrew.transliteration), meaning: accordanceData.hebrew.meaning || (enhanced.hebrew && enhanced.hebrew.meaning) }; } return enhanced; } catch (error) { console.warn('[Accordance API] Failed to enhance word info:', error); return wordInfo; } } /** * Check if Accordance integration is available * @returns {Promise} True if Accordance is available */ export async function checkAccordanceAvailability() { try { const response = await fetch('/api/accordance/status'); if (!response.ok) { console.log('[Accordance API] Status check failed:', response.status); // Still return true to attempt integration (graceful fallback) return true; } const data = await response.json(); const available = data.available === true || data.configured === true || data.oscModuleInstalled === true; console.log('[Accordance API] Availability check:', available, data); return available; } catch (error) { console.warn('[Accordance API] Status check error:', error); // Return true to attempt integration anyway (will gracefully handle errors) return true; } } // Make functions available globally for backward compatibility if (typeof window !== 'undefined') { window.queryAccordanceWord = queryAccordanceWord; window.enhanceWordInfoWithAccordance = enhanceWordInfoWithAccordance; window.checkAccordanceAvailability = checkAccordanceAvailability; // Also expose via window.accordance for namespacing window.accordance = { queryWord: queryAccordanceWord, enhanceWordInfo: enhanceWordInfoWithAccordance, checkAvailability: checkAccordanceAvailability }; }