UNPKG

astrobaba-astro-engine-sdk

Version:

Official Node.js SDK for AstroBaba Astro Engine - Professional Vedic Astrology API with automatic retry logic and comprehensive error handling

545 lines (482 loc) 16.6 kB
const axios = require('axios'); /** * AstroBaba Astro Engine SDK Client * Professional Vedic Astrology API Client with automatic retry logic */ class AstroEngineClient { /** * Initialize the Astro Engine SDK * @param {Object} config - Configuration options * @param {string} [config.baseUrl='http://localhost:8000/api/v1'] - Base URL for the API * @param {number} [config.timeout=10000] - Request timeout in milliseconds * @param {number} [config.maxRetries=3] - Maximum number of retry attempts * @param {number} [config.retryDelay=1000] - Initial delay between retries in milliseconds * @param {number} [config.backoffFactor=2] - Exponential backoff multiplier */ constructor(config = {}) { this.config = { baseUrl: config.baseUrl || 'http://localhost:8000/api/v1', timeout: config.timeout || 10000, maxRetries: config.maxRetries !== undefined ? config.maxRetries : 3, retryDelay: config.retryDelay || 1000, backoffFactor: config.backoffFactor || 2, }; // Create axios instance with base configuration this.client = axios.create({ baseURL: this.config.baseUrl, timeout: this.config.timeout, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, }); // Setup interceptors for retry logic this._setupInterceptors(); } /** * Setup axios interceptors for automatic retry with exponential backoff * @private */ _setupInterceptors() { // Response interceptor for retry logic this.client.interceptors.response.use( (response) => response, async (error) => { const config = error.config; // Initialize retry count if (!config.__retryCount) { config.__retryCount = 0; } // Check if we should retry const shouldRetry = config.__retryCount < this.config.maxRetries && this._isRetryableError(error); if (!shouldRetry) { return Promise.reject(this._formatError(error)); } // Increment retry count config.__retryCount += 1; // Calculate delay with exponential backoff const delay = this.config.retryDelay * Math.pow(this.config.backoffFactor, config.__retryCount - 1); // Wait before retrying await this._sleep(delay); // Retry the request return this.client(config); } ); } /** * Check if error is retryable * @private * @param {Error} error - The error object * @returns {boolean} - Whether the error is retryable */ _isRetryableError(error) { // Network errors if (!error.response) { return true; } // Server errors (5xx) const status = error.response.status; if (status >= 500 && status < 600) { return true; } // Too many requests if (status === 429) { return true; } return false; } /** * Sleep utility for retry delays * @private * @param {number} ms - Milliseconds to sleep * @returns {Promise} - Promise that resolves after delay */ _sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } /** * Format error response * @private * @param {Error} error - The error object * @returns {Error} - Formatted error */ _formatError(error) { const formattedError = new Error(); if (error.response) { // Server responded with error formattedError.message = error.response.data?.detail || error.response.data?.message || error.message || 'Request failed'; formattedError.status = error.response.status; formattedError.code = error.code || 'API_ERROR'; formattedError.data = error.response.data; } else if (error.request) { // Request made but no response formattedError.message = 'No response from server'; formattedError.status = null; formattedError.code = 'NETWORK_ERROR'; } else { // Request setup error formattedError.message = error.message || 'Request failed'; formattedError.status = null; formattedError.code = 'REQUEST_ERROR'; } formattedError.originalError = error; return formattedError; } /** * Make POST request * @private * @param {string} endpoint - API endpoint * @param {Object} data - Request data * @returns {Promise<Object>} - Response data */ async _post(endpoint, data) { try { const response = await this.client.post(endpoint, data); return response.data; } catch (error) { throw error; } } /** * Make GET request * @private * @param {string} endpoint - API endpoint * @param {Object} params - Query parameters * @returns {Promise<Object>} - Response data */ async _get(endpoint, params = {}) { try { const response = await this.client.get(endpoint, { params }); return response.data; } catch (error) { throw error; } } // ==================== CHART ENDPOINTS ==================== /** * Calculate birth chart with planetary positions and houses * @param {Object} birthData - Birth data * @param {string} birthData.name - Person's name * @param {string} birthData.date - Birth date (YYYY-MM-DD) * @param {string} birthData.time - Birth time (HH:MM:SS) * @param {number} birthData.latitude - Birth place latitude * @param {number} birthData.longitude - Birth place longitude * @param {string} [birthData.timezone='Asia/Kolkata'] - Timezone * @param {string} [houseSystem='PLACIDUS'] - House system * @returns {Promise<Object>} - Birth chart data */ async birthChart(birthData, houseSystem = 'PLACIDUS') { return this._post('/chart/birth', { birth_data: birthData, house_system: houseSystem, }); } // ==================== DASHA ENDPOINTS ==================== /** * Calculate Vimshottari Dasha periods * @param {Object} birthData - Birth data * @param {number} [years=120] - Years to calculate * @returns {Promise<Object>} - Dasha periods */ async vimshottariDasha(birthData, years = 120) { return this._post('/dasha/vimshottari', { birth_data: birthData, years, }); } /** * Calculate Antardasha (sub-periods) within a Mahadasha * @param {string} mahaDashaLord - Maha dasha lord planet * @param {string} mahaDashaStart - Start date (YYYY-MM-DD) * @param {number} mahaDashaYears - Duration in years * @returns {Promise<Object>} - Antardasha periods */ async antardasha(mahaDashaLord, mahaDashaStart, mahaDashaYears) { return this._post('/dasha/antardasha', { maha_dasha_lord: mahaDashaLord, maha_dasha_start: mahaDashaStart, maha_dasha_years: mahaDashaYears, }); } // ==================== PANCHANG ENDPOINTS ==================== /** * Calculate Panchang (Vedic calendar) * @param {string} date - Date (YYYY-MM-DD) * @param {number} latitude - Location latitude * @param {number} longitude - Location longitude * @param {string} [timezone='Asia/Kolkata'] - Timezone * @returns {Promise<Object>} - Panchang data */ async panchang(date, latitude, longitude, timezone = 'Asia/Kolkata') { return this._post('/panchang', { date, latitude, longitude, timezone, }); } // ==================== DIVISIONAL CHART ENDPOINTS ==================== /** * Calculate specific divisional chart * @param {Object} birthData - Birth data * @param {string} division - Division (D1, D9, D10, etc.) * @returns {Promise<Object>} - Divisional chart data */ async divisionalChart(birthData, division) { return this._post('/divisional', { birth_data: birthData, division, }); } /** * Calculate all major divisional charts * @param {Object} birthData - Birth data * @returns {Promise<Object>} - All divisional charts */ async allDivisionalCharts(birthData) { return this._post('/divisional/all', { birth_data: birthData, }); } // ==================== KP SYSTEM ENDPOINTS ==================== /** * Calculate KP (Krishnamurti Paddhati) cuspal chart * @param {Object} birthData - Birth data * @returns {Promise<Object>} - KP chart with cusps and sub-lords */ async kpChart(birthData) { return this._post('/kp/cuspal', { birth_data: birthData, }); } // ==================== MATCHING ENDPOINTS ==================== /** * Calculate Ashtakoot (8-Kuta) compatibility matching * @param {Object} maleData - Male birth data * @param {Object} femaleData - Female birth data * @returns {Promise<Object>} - Matching analysis with 8 Kutas */ async ashtakootMatching(maleData, femaleData) { return this._post('/matching/ashtakoot', { male_data: maleData, female_data: femaleData, }); } // ==================== YOGAS & DOSHAS ENDPOINTS ==================== /** * Analyze all yogas and doshas in birth chart * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Yogas and doshas analysis */ async yogasAndDoshas(birthData) { return this._post('/yogas', { birth_data: birthData, }); } // ==================== HOROSCOPE ENDPOINTS ==================== /** * Calculate Ashtakavarga (8-point benefic system) * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Ashtakavarga analysis */ async ashtakavarga(birthData) { return this._post('/horoscope/ashtakavarga', { birth_data: birthData, }); } /** * Generate comprehensive horoscope report * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Complete horoscope */ async completeHoroscope(birthData) { return this._post('/horoscope/complete', { birth_data: birthData, }); } // ==================== DAILY HOROSCOPE ENDPOINTS ==================== /** * Get daily horoscope for zodiac sign * @param {string} zodiacSign - Zodiac sign (Aries, Taurus, etc.) * @param {string} [date] - Date (YYYY-MM-DD), default: today * @returns {Promise<Object>} - Daily horoscope */ async dailyHoroscope(zodiacSign, date = null) { const params = date ? { date } : {}; return this._get(`/horoscope/daily/${zodiacSign}`, params); } /** * Get weekly horoscope for zodiac sign * @param {string} zodiacSign - Zodiac sign * @param {string} [startDate] - Week start date (YYYY-MM-DD) * @returns {Promise<Object>} - Weekly horoscope */ async weeklyHoroscope(zodiacSign, startDate = null) { const params = startDate ? { start_date: startDate } : {}; return this._get(`/horoscope/weekly/${zodiacSign}`, params); } /** * Get monthly horoscope for zodiac sign * @param {string} zodiacSign - Zodiac sign * @param {number} [year] - Year * @param {number} [month] - Month (1-12) * @returns {Promise<Object>} - Monthly horoscope */ async monthlyHoroscope(zodiacSign, year = null, month = null) { const params = {}; if (year) params.year = year; if (month) params.month = month; return this._get(`/horoscope/monthly/${zodiacSign}`, params); } /** * Get yearly horoscope for zodiac sign * @param {string} zodiacSign - Zodiac sign * @param {number} [year] - Year * @returns {Promise<Object>} - Yearly horoscope */ async yearlyHoroscope(zodiacSign, year = null) { const params = year ? { year } : {}; return this._get(`/horoscope/yearly/${zodiacSign}`, params); } /** * Get daily horoscope for all zodiac signs * @param {string} [date] - Date (YYYY-MM-DD) * @returns {Promise<Object>} - All signs daily horoscope */ async allSignsDailyHoroscope(date = null) { const params = date ? { date } : {}; return this._get('/horoscope/all-signs/daily', params); } // ==================== KUNDLI ENDPOINTS ==================== /** * Generate complete Kundli with all details * @param {Object} birthData - Birth data * @param {boolean} [includePredictions=true] - Include life predictions * @param {boolean} [includeRemedies=true] - Include remedies * @returns {Promise<Object>} - Complete Kundli analysis */ async kundli(birthData, includePredictions = true, includeRemedies = true) { return this._post('/kundli/complete', { birth_data: birthData, include_predictions: includePredictions, include_remedies: includeRemedies, }); } /** * Get basic Kundli information * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Basic Kundli details */ async basicKundli(birthData) { return this._post('/kundli/basic', { birth_data: birthData, }); } /** * Get all divisional charts (D1-D60) formatted for display * @param {Object} birthData - Birth data * @returns {Promise<Object>} - All formatted charts */ async allCharts(birthData) { return this._post('/kundli/charts', { birth_data: birthData, }); } /** * Get detailed planetary analysis * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Planetary analysis with strengths, friendships, aspects */ async planetaryAnalysis(birthData) { return this._post('/kundli/planetary-analysis', { birth_data: birthData, }); } /** * Get current and upcoming Dasha predictions * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Dasha predictions */ async dashaPredictions(birthData) { return this._post('/kundli/dasha-predictions', { birth_data: birthData, }); } /** * Get planetary positions (legacy method - use planetaryAnalysis for detailed info) * @param {Object} birthData - Birth data * @returns {Promise<Object>} - Planetary positions * @deprecated Use planetaryAnalysis() instead */ async planetaryPositions(birthData) { return this._post('/kundli/planets', { birth_data: birthData, }); } /** * Get house positions and cusps (legacy method) * @param {Object} birthData - Birth data * @returns {Promise<Object>} - House details * @deprecated Use basicKundli() instead */ async housePositions(birthData) { return this._post('/kundli/houses', { birth_data: birthData, }); } // ==================== KUNDLI MATCHING ENDPOINTS ==================== /** * Comprehensive Kundli matching analysis * @param {Object} maleData - Male birth data * @param {Object} femaleData - Female birth data * @param {boolean} [includeDetailedAnalysis=true] - Include detailed analysis * @returns {Promise<Object>} - Detailed matching report */ async kundliMatching(maleData, femaleData, includeDetailedAnalysis = true) { return this._post('/kundli-matching/comprehensive', { male_data: maleData, female_data: femaleData, include_detailed_analysis: includeDetailedAnalysis, }); } /** * Quick compatibility check * @param {Object} maleData - Male birth data * @param {Object} femaleData - Female birth data * @returns {Promise<Object>} - Quick compatibility score */ async quickCompatibility(maleData, femaleData) { return this._post('/kundli-matching/quick', { male_data: maleData, female_data: femaleData, }); } // ==================== UTILITY METHODS ==================== /** * Update configuration * @param {Object} newConfig - New configuration options */ updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; // Recreate axios instance with new config this.client = axios.create({ baseURL: this.config.baseUrl, timeout: this.config.timeout, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, }); // Reapply interceptors this._setupInterceptors(); } } module.exports = AstroEngineClient;