// app/api/generate-kundali/route.ts
// Server-side API route for Kundali generation
import { NextRequest, NextResponse } from 'next/server';
// Import vedic-astrology-api only on server-side
// @ts-ignore
import { BirthChartGenerator } from 'vedic-astrology-api/lib/utils/birthchart.js';
// @ts-ignore
import {calculatePlanetaryPositions,calculateAscendant,createDate,getRashiFromLongitude,getNakshatraFromLongitude,} from 'vedic-astrology-api/lib/utils/common.js';
// Types
interface BirthDetails {
name: string;
dateOfBirth: string;
timeOfBirth: string;
placeOfBirth: string;
latitude: number;
longitude: number;
timezone?: number;
}
// Sign Lords mapping
const SIGN_LORDS: Record<string, string> = {
'Aries': 'Mars',
'Taurus': 'Venus',
'Gemini': 'Mercury',
'Cancer': 'Moon',
'Leo': 'Sun',
'Virgo': 'Mercury',
'Libra': 'Venus',
'Scorpio': 'Mars',
'Sagittarius': 'Jupiter',
'Capricorn': 'Saturn',
'Aquarius': 'Saturn',
'Pisces': 'Jupiter'
};
const ZODIAC_SIGNS = [
'Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo',
'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces'
];
function getRashiName(longitude: number): string {
const rashiResult = getRashiFromLongitude(longitude);
if (typeof rashiResult === 'object' && rashiResult !== null) {
return (rashiResult as any).name || (rashiResult as any).sign || String(rashiResult);
}
if (typeof rashiResult === 'string') {
return rashiResult;
}
const rashiIndex = Math.floor(longitude / 30);
return ZODIAC_SIGNS[rashiIndex] || 'Aries';
}
function getNakshatraInfo(longitude: number): { name: string; lord: string; pada: number } {
const nakshatraResult = getNakshatraFromLongitude(longitude);
if (typeof nakshatraResult === 'object' && nakshatraResult !== null) {
return {
name: (nakshatraResult as any).name || (nakshatraResult as any).nakshatra || 'Unknown',
lord: (nakshatraResult as any).lord || (nakshatraResult as any).ruler || 'Unknown',
pada: (nakshatraResult as any).pada || (nakshatraResult as any).quarter || 1
};
}
if (typeof nakshatraResult === 'string') {
return { name: nakshatraResult, lord: 'Unknown', pada: 1 };
}
return { name: 'Unknown', lord: 'Unknown', pada: 1 };
}
function getDegreeInSign(longitude: number): number {
const normalizedLon = ((longitude % 360) + 360) % 360;
return normalizedLon % 30;
}
function formatDegree(longitude: number): string {
const degInSign = getDegreeInSign(longitude);
const deg = Math.floor(degInSign);
const min = Math.floor((degInSign - deg) * 60);
return `${deg}° ${min}'`;
}
function parseDateTimeComponents(dateStr: string, timeStr: string) {
const [year, month, day] = dateStr.split('-').map(Number);
const [hour, minute] = timeStr.split(':').map(Number);
return { year, month, day, hour, minute };
}
export async function POST(request: NextRequest) {
try {
const birthDetails: BirthDetails = await request.json();
console.log('Received birth details:', birthDetails);
// Parse birth date and time
const { year, month, day, hour, minute } = parseDateTimeComponents(
birthDetails.dateOfBirth,
birthDetails.timeOfBirth
);
const timezone = birthDetails.timezone || 5.5;
console.log('Creating date with:', { year, month, day, hour, minute, timezone });
// Create date object
const date = createDate(year, month, day, hour, minute, timezone);
// Calculate planetary positions
const result = calculatePlanetaryPositions(
date,
birthDetails.latitude,
birthDetails.longitude
);
const positions = result.positions;
const ayanamsa = result.ayanamsa;
console.log('Positions calculated, ayanamsa:', ayanamsa);
// Calculate ascendant
const ascendantLon = calculateAscendant(
date,
birthDetails.latitude,
birthDetails.longitude
);
const ascendantSign = getRashiName(ascendantLon);
const ascendantSignIndex = Math.floor(((ascendantLon % 360) + 360) % 360 / 30);
// Generate birth chart
const birthChartGenerator = new BirthChartGenerator();
const birthChart = birthChartGenerator.generateBirthChart(positions, ascendantLon);
// Process planets
const planetsArray: any[] = [];
const planetOrder = ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn'];
for (const planetName of planetOrder) {
const planetData = positions[planetName];
if (!planetData) continue;
const longitude = planetData.longitude;
const sign = getRashiName(longitude);
const signLord = SIGN_LORDS[sign] || 'Unknown';
const nakshatraInfo = getNakshatraInfo(longitude);
const planetInChart = birthChart.planets[planetName];
const house = planetInChart?.house || 1;
const isRetrograde = planetData.speed ? planetData.speed < 0 : false;
planetsArray.push({
name: planetName,
longitude: longitude,
sign: sign,
signLord: signLord,
house: house,
degree: formatDegree(longitude),
nakshatra: nakshatraInfo.name,
nakshatraLord: nakshatraInfo.lord,
nakshatra_pada: nakshatraInfo.pada,
isRetrograde: isRetrograde
});
}
// Add Rahu and Ketu
if (birthChart.planets['Rahu']) {
const rahuData = birthChart.planets['Rahu'];
const rahuLon = rahuData.degree || 0;
const rahuSign = rahuData.sign || getRashiName(rahuLon);
const rahuNakshatraInfo = getNakshatraInfo(rahuLon);
planetsArray.push({
name: 'Rahu',
longitude: rahuLon,
sign: rahuSign,
signLord: SIGN_LORDS[rahuSign] || 'Unknown',
house: rahuData.house || 1,
degree: formatDegree(rahuLon),
nakshatra: rahuNakshatraInfo.name,
nakshatraLord: rahuNakshatraInfo.lord,
nakshatra_pada: rahuNakshatraInfo.pada,
isRetrograde: true
});
}
if (birthChart.planets['Ketu']) {
const ketuData = birthChart.planets['Ketu'];
const ketuLon = ketuData.degree || 0;
const ketuSign = ketuData.sign || getRashiName(ketuLon);
const ketuNakshatraInfo = getNakshatraInfo(ketuLon);
planetsArray.push({
name: 'Ketu',
longitude: ketuLon,
sign: ketuSign,
signLord: SIGN_LORDS[ketuSign] || 'Unknown',
house: ketuData.house || 1,
degree: formatDegree(ketuLon),
nakshatra: ketuNakshatraInfo.name,
nakshatraLord: ketuNakshatraInfo.lord,
nakshatra_pada: ketuNakshatraInfo.pada,
isRetrograde: true
});
}
// Process houses
const housesArray: any[] = [];
for (let i = 1; i <= 12; i++) {
const houseData = birthChart.houses[i];
if (!houseData) continue;
housesArray.push({
house: i,
sign: houseData.sign,
signLord: houseData.lord || SIGN_LORDS[houseData.sign] || 'Unknown',
degree: '',
planets: houseData.planets || []
});
}
// Get Moon and Sun signs
const moonPlanet = planetsArray.find(p => p.name === 'Moon');
const sunPlanet = planetsArray.find(p => p.name === 'Sun');
const kundaliData = {
birthDetails,
planets: planetsArray,
houses: housesArray,
ascendant: {
longitude: ascendantLon,
sign: ascendantSign,
signIndex: ascendantSignIndex,
degree: formatDegree(ascendantLon),
lord: SIGN_LORDS[ascendantSign] || 'Unknown'
},
moonSign: moonPlanet?.sign || 'Unknown',
sunSign: sunPlanet?.sign || 'Unknown',
nakshatraDetails: moonPlanet ? {
name: moonPlanet.nakshatra,
lord: moonPlanet.nakshatraLord,
pada: moonPlanet.nakshatra_pada
} : { name: 'Unknown', lord: 'Unknown', pada: 1 }
};
console.log('Kundali generated successfully');
return NextResponse.json(kundaliData);
} catch (error) {
console.error('Error generating Kundali:', error);
return NextResponse.json(
{ error: 'Failed to generate Kundali', details: (error as Error).message },
{ status: 500 }
);
}
}