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
JavaScript
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;