UNPKG

besper-frontend-site-dev-main

Version:

Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment

258 lines (226 loc) 7.54 kB
/** * Centralized API Service for B-esper Frontend Toolkit * Consolidates all API endpoint definitions and provides consistent API calling interface * Uses dynamic endpoints from build-time environment variables for APIM deployment flexibility */ // Dynamic base URL from build-time environment (NO FALLBACKS ALLOWED) const APIM_BASE_ENDPOINT = process.env.API_ENDPOINT; // Validate API_ENDPOINT is set during build - fail fast if not configured if (!APIM_BASE_ENDPOINT) { console.error( '[ERROR] CRITICAL: API_ENDPOINT environment variable is required but not set!' ); console.error('[ERROR] This indicates a build configuration error.'); console.error( '[ERROR] Production deployments must set API_ENDPOINT to match infrastructure: {env}0926apim_internal.azure-api.net' ); console.error( '[ERROR] Build will fail - no hardcoded fallback endpoints allowed' ); throw new Error( 'API_ENDPOINT environment variable is required for deployment - no fallbacks allowed' ); } /** * Get the base APIM endpoint (dynamic only, no fallbacks) */ function getBaseAPIEndpoint() { // Return only the dynamic endpoint - no fallback logic allowed return APIM_BASE_ENDPOINT; } // API service paths const API_PATHS = { // Bot operations (chat, messaging) botOperations: '/api/bot-operations', // Bot management (configuration, settings) botManagement: '/api/bot-management', // Root API for general operations root: '/api', // Management operations (legacy mgmt path if needed) management: '/mgmt', }; /** * Get the complete API endpoint URL for a specific service * Uses ONLY the dynamic base endpoint from build-time environment variables * NO FALLBACKS ALLOWED - ensures consistent infrastructure naming * @param {string} service - Service name from API_PATHS * @returns {string} Complete API endpoint URL */ export function getServiceEndpoint(service = 'botOperations') { // Use ONLY the dynamic base endpoint - no fallbacks allowed const baseUrl = getBaseAPIEndpoint(); const path = API_PATHS[service] || API_PATHS.botOperations; // Ensure no double slashes const endpoint = `${baseUrl}${path}` .replace(/\/+/g, '/') .replace('http:/', 'http://') .replace('https:/', 'https://'); // Only log in development/debug mode to reduce console noise if ( typeof window !== 'undefined' && window.location?.hostname?.includes('localhost') ) { console.log(`[API] API Endpoint for ${service}:`, endpoint); } return endpoint; } /** * Get bot operations endpoint (for chat functionality) * Uses dynamic endpoint from build-time configuration * @returns {string} Bot operations API endpoint */ export function getBotOperationsEndpoint() { return getServiceEndpoint('botOperations'); } /** * Get bot management endpoint (for configuration management) * Uses dynamic endpoint from build-time configuration * @returns {string} Bot management API endpoint */ export function getBotManagementEndpoint() { return getServiceEndpoint('botManagement'); } /** * Get root API endpoint (for general operations) * Uses dynamic endpoint from build-time configuration * @returns {string} Root API endpoint */ export function getRootApiEndpoint() { return getServiceEndpoint('root'); } /** * Generic API call helper with enhanced error handling and logging * @param {string} endpoint - Full API endpoint URL * @param {string} method - HTTP method (GET, POST, PUT, DELETE) * @param {Object} body - Request body for POST/PUT requests * @param {Object} headers - Additional headers * @returns {Promise<Object>} API response data */ export async function apiCall( endpoint, method = 'GET', body = null, headers = {} ) { const config = { method, headers: { 'Content-Type': 'application/json', Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'Cache-Control': 'no-cache', Pragma: 'no-cache', ...headers, }, }; if (body && method !== 'GET') { config.body = JSON.stringify(body); } // Debug logging (reduced in production) const isDebugMode = typeof window !== 'undefined' && (window.location?.hostname?.includes('localhost') || window.location?.search?.includes('debug=true')); if (isDebugMode) { console.log(`[API] Making ${method} request to:`, endpoint); if (body) { console.log(`📦 Request payload:`, body); } } try { const response = await fetch(endpoint, config); if (isDebugMode) { console.log( `📡 Response status: ${response.status} ${response.statusText}` ); } if (!response.ok) { let errorMessage = `HTTP ${response.status}: ${response.statusText}`; // Try to get error details from response body try { const errorData = await response.text(); if (errorData) { if (isDebugMode) { console.log(`[ERROR] Error response body:`, errorData); } errorMessage += ` - ${errorData}`; } } catch (parseError) { if (isDebugMode) { console.log(`[ERROR] Could not parse error response:`, parseError); } } throw new Error(errorMessage); } const data = await response.json(); if (isDebugMode) { console.log(`[SUCCESS] Response data:`, data); } return data; } catch (error) { // Always log errors for debugging, but make them less verbose in production if (isDebugMode) { console.error(`[ERROR] API call failed:`, error); } else { console.error(`[ERROR] API call failed: ${error.message}`); } throw error; } } /** * Make a bot management API call * @param {string} path - API path (e.g., 'get_config_json', 'config') * @param {string} method - HTTP method * @param {Object} body - Request body * @param {Object} headers - Additional headers * @returns {Promise<Object>} API response */ export async function managementApiCall( path, method = 'GET', body = null, headers = {} ) { const baseEndpoint = getBotManagementEndpoint(); const fullEndpoint = `${baseEndpoint}/${path}` .replace(/\/+/g, '/') .replace('http:/', 'http://') .replace('https:/', 'https://'); return apiCall(fullEndpoint, method, body, headers); } /** * Make a bot operations API call * @param {string} path - API path (e.g., 'create_session', 'generate_response') * @param {string} method - HTTP method * @param {Object} body - Request body * @param {Object} headers - Additional headers * @returns {Promise<Object>} API response */ export async function operationsApiCall( path, method = 'GET', body = null, headers = {} ) { const baseEndpoint = getBotOperationsEndpoint(); const fullEndpoint = `${baseEndpoint}/${path}` .replace(/\/+/g, '/') .replace('http:/', 'http://') .replace('https:/', 'https://'); return apiCall(fullEndpoint, method, body, headers); } /** * Export legacy function names for backward compatibility * These will be deprecated in favor of the more specific functions above */ // Legacy compatibility exports export { getBotOperationsEndpoint as getApiEndpoint }; export { getBotManagementEndpoint as getManagementEndpoint }; // Export all endpoints for direct access if needed export const API_ENDPOINTS = { getBotOperations: getBotOperationsEndpoint, getBotManagement: getBotManagementEndpoint, getRoot: getRootApiEndpoint, }; // Export constants for external use export { API_PATHS, getBaseAPIEndpoint };