diff --git a/README.md b/README.md index 4e8323a..d9a4f13 100644 --- a/README.md +++ b/README.md @@ -1,103 +1,238 @@ -# @af/sweph Monorepo +# @af/sweph The ultimate Swiss Ephemeris library for Vedic Astrology, supporting Node.js, Browser (WASM), and React Native with a unified API. [![CI](https://github.com/astro-fusion/af-sweph/actions/workflows/ci.yml/badge.svg)](https://github.com/astro-fusion/af-sweph/actions/workflows/ci.yml) [![Build](https://github.com/astro-fusion/af-sweph/actions/workflows/build.yml/badge.svg)](https://github.com/astro-fusion/af-sweph/actions/workflows/build.yml) -## 🌟 Multi-Platform Architecture +## 🌟 Features -This library is architected as a monorepo to provide optimized implementations for every target platform while maintaining a consistent developer experience. +- **✅ Auto-initialization** - Native module loads automatically +- **✅ TypeScript First** - Complete type safety with IntelliSense +- **✅ Vedic Astrology** - Ayanamsa, Rashis, Nakshatras built-in +- **✅ Multi-Platform** - Node.js, Browser (WASM), React Native +- **✅ Vercel Ready** - Pre-built binaries for serverless -| Package | Environment | Core Technology | Description | -|---------|-------------|-----------------|-------------| -| [`@af/sweph-core`](./packages/core) | All | TypeScript | Shared logic, interfaces, and pure JS utilities. | -| [`@af/sweph-node`](./packages/node) | Node.js | Native C++ | High-performance implementation using native binaries. | -| [`@af/sweph-wasm`](./packages/wasm) | Browser | WebAssembly | Optimized for web with async loading support. | -| [`@af/sweph-react-native`](./packages/react-native) | Mobile | JSI/Turbo Modules | Native iOS and Android implementation. | +## 🚀 Quick Start ---- - -## 🚀 Quick Start (Unified API) - -Regardless of the platform, the API remains consistent via the `ISwephInstance` interface. - -### 1. Installation - -Pick the package for your target platform: +### Installation ```bash -# For Node.js / Serverless (Vercel) -pnpm add @af/sweph-node +# npm +npm install @af/sweph -# For Browser applications -pnpm add @af/sweph-wasm +# pnpm +pnpm add @af/sweph -# For React Native applications -pnpm add @af/sweph-react-native +# Or from GitHub +pnpm add github:astro-fusion/af-sweph ``` -### 2. Usage Example +### Usage ```typescript -import { createSweph } from '@af/sweph-node'; // Or @af/sweph-wasm / @af/sweph-react-native +import { createSweph, AYANAMSA } from '@af/sweph'; -async function run() { - // 1. Initialize the instance +async function main() { + // Create instance (auto-initializes native module) const sweph = await createSweph(); - // 2. Perform calculations - const date = new Date(); - const planets = sweph.calculatePlanets(date, { - ayanamsa: 1, // Lahiri - location: { latitude: 27.7, longitude: 85.3 } + // Define calculation date once for consistency + const calculationDate = new Date(); + + // Calculate planetary positions + const planets = await sweph.calculatePlanets(calculationDate, { + ayanamsa: AYANAMSA.LAHIRI, + timezone: 5.75, // Nepal }); - console.log(planets); + console.log('Sun:', planets.find(p => p.id === 'sun')); + console.log('Moon:', planets.find(p => p.id === 'moon')); + + // Calculate Lagna (Ascendant) + const lagna = await sweph.calculateLagna( + calculationDate, + { latitude: 27.7, longitude: 85.3, timezone: 5.75 }, + { ayanamsa: AYANAMSA.LAHIRI } + ); + + console.log('Ascendant:', lagna.longitude, 'in', sweph.RASHIS[lagna.rasi]); + + // Calculate Moon Phase + const moonPhase = await sweph.calculateMoonPhase(calculationDate); + console.log('Moon Phase:', moonPhase.phaseName, `(${Math.round(moonPhase.illumination * 100)}%)`); } + +main(); ``` --- -## 📦 Packages +## 📦 API Reference + +### `createSweph(options?): Promise` + +Creates an auto-initialized Swiss Ephemeris instance. + +```typescript +const sweph = await createSweph({ + ephePath: '/path/to/ephemeris', // Optional: custom ephemeris path + preWarm: true, // Optional: pre-calculate to warm cache +}); +``` + +### SwephInstance Methods + +#### Planetary Calculations + +```typescript +// All 9 Vedic planets +const planets = await sweph.calculatePlanets(date, { + ayanamsa: AYANAMSA.LAHIRI, // Lahiri + timezone: 0, // UTC +}); + +// Single planet (0=Sun, 1=Moon, 2=Mars, etc.) +const sun = await sweph.calculatePlanet(0, date, { ayanamsa: AYANAMSA.LAHIRI }); + +// Rise, Set, Transit times +const riseSet = await sweph.calculateRiseSet(0, date, { + latitude: 27.7, + longitude: 85.3, +}); +``` -### [@af/sweph-core](./packages/core) -The backbone of the library. Contains all shared types, constant definitions (Planet IDs, Ayanamsas), and pure JavaScript utilities that don't depend on a native environment. +#### Lagna & Houses -### [@af/sweph-node](./packages/node) -The successor to the original `@af/sweph`. It includes pre-built binaries for Linux, macOS, and Windows. It is specifically optimized for **Vercel** and other serverless environments, requiring zero native compilation at deploy time. +```typescript +const lagna = await sweph.calculateLagna( + date, + { latitude: 27.7, longitude: 85.3 }, + { ayanamsa: AYANAMSA.LAHIRI } +); + +console.log(lagna.longitude); // Ascendant in degrees +console.log(lagna.rasi); // Ascendant sign (1-12) +console.log(lagna.houses); // Array of 12 house cusps +``` -### [@af/sweph-wasm](./packages/wasm) -A WebAssembly-powered implementation designed for browser environments. It handles the async loading of the `.wasm` binary and provides a type-safe wrapper. Perfect for static sites or client-side calculation needs. +#### Sun Calculations -### [@af/sweph-react-native](./packages/react-native) -Utilizes **Turbo Modules** and **JSI** to bridge the Swiss Ephemeris C library directly into React Native. This provides near-native performance on both iOS and Android without crossing the traditional asynchronous bridge. +```typescript +const date = new Date(); +const location = { latitude: 27.7, longitude: 85.3 }; + +// Sunrise, Sunset, Solar Noon +const sunTimes = await sweph.calculateSunTimes(date, location); + +// Solar Noon with altitude +const noon = await sweph.calculateSolarNoon(date, location); + +// Sun path throughout the day +const path = await sweph.calculateSunPath(date, location); +``` + +#### Moon Calculations + +```typescript +const date = new Date(); +const location = { latitude: 27.7, longitude: 85.3 }; + +// Moon data (position, rise/set, phase) +const moonData = await sweph.calculateMoonData(date, location); + +// Current moon phase +const phase = await sweph.calculateMoonPhase(date); +console.log(phase.phaseName); // "Waxing Crescent", "Full Moon", etc. +console.log(phase.illumination); // 0.0 to 1.0 + +// Next moon phases +const nextPhases = await sweph.calculateNextMoonPhases(date); +console.log('Next New Moon:', nextPhases.newMoon); +console.log('Next Full Moon:', nextPhases.fullMoon); +``` + +#### Utilities + +```typescript +// Get ayanamsa value +const ayanamsa = sweph.getAyanamsa(date, AYANAMSA.LAHIRI); + +// Convert to Julian Day +const jd = sweph.dateToJulian(date); + +// Set ephemeris path +sweph.setEphePath('/custom/path/to/ephe'); +``` + +### Constants + +```typescript +import { PLANETS, AYANAMSA, RASHIS, NAKSHATRAS } from '@af/sweph'; + +// Planet IDs +PLANETS.SUN; // 0 +PLANETS.MOON; // 1 +PLANETS.MARS; // 4 +PLANETS.MERCURY; // 2 +PLANETS.JUPITER; // 5 +PLANETS.VENUS; // 3 +PLANETS.SATURN; // 6 +PLANETS.RAHU; // 10 +PLANETS.KETU; // 11 + +// Ayanamsa types +AYANAMSA.LAHIRI; // 1 (default) +AYANAMSA.KRISHNAMURTI; // 5 +AYANAMSA.RAMAN; // 3 + +// Rashi names +RASHIS[1]; // "Aries" +RASHIS[4]; // "Cancer" +RASHIS[10]; // "Capricorn" + +// Nakshatra names +NAKSHATRAS[1]; // "Ashwini" +NAKSHATRAS[14]; // "Chitra" +NAKSHATRAS[27]; // "Revati" +``` --- -## 🛠 Features +## 🏗️ Multi-Platform Architecture -- **✅ Universal Compatibility** - Node, Browser, iOS, and Android. -- **✅ Vercel Ready** - Pre-built binaries for serverless environments. -- **✅ TypeScript First** - Complete type safety for all astrological entities. -- **✅ Vedic Centric** - Native support for Ayanamsas, Rashis, and Nakshatras. -- **✅ Unified Interface** - Write your business logic once, run it anywhere. +| Package | Environment | Technology | +|---------|-------------|------------| +| `@af/sweph-node` | Node.js | Native C++ bindings | +| `@af/sweph-wasm` | Browser | WebAssembly | +| `@af/sweph-react-native` | Mobile | JSI/Turbo Modules | +| `@af/sweph-core` | All | Shared TypeScript | -## 🤝 Contributing +--- + +## 🐛 Troubleshooting -This is a monorepo managed with `pnpm`. +### Module not found on Vercel +Ensure pre-built binaries are installed: ```bash -# Clone -git clone https://github.com/astro-fusion/af-sweph +ls node_modules/@af/sweph/prebuilds/ +# Should show: linux-x64/ +``` -# Install -pnpm install +### Native module errors -# Build all packages -pnpm -r build +Set `NODE_VERSION=20` in your environment. + +--- + +## 🤝 Contributing -# Run tests +```bash +git clone https://github.com/astro-fusion/af-sweph +cd af-sweph +pnpm install +pnpm -r build pnpm -r test ``` @@ -107,5 +242,4 @@ MIT ## ❤️ Credits -- [Swiss Ephemeris](https://www.astro.com/swisseph/) by Astrodienst AG. -- [swisseph-v2](https://github.com/nickhealthy/swisseph-v2) for initial Node.js bindings. +- [Swiss Ephemeris](https://www.astro.com/swisseph/) by Astrodienst AG diff --git a/packages/core/package.json b/packages/core/package.json index 544dbe9..77ab851 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -8,7 +8,6 @@ ".": { "types": "./dist/index.d.ts", "require": "./dist/index.js", - "import": "./dist/index.mjs", "default": "./dist/index.js" } }, diff --git a/packages/node/dist/index.d.ts b/packages/node/dist/index.d.ts index ec109b6..f588579 100644 --- a/packages/node/dist/index.d.ts +++ b/packages/node/dist/index.d.ts @@ -2,15 +2,44 @@ * @AstroFusion/sweph - Swiss Ephemeris for Vedic Astrology * * This is the main entry point for the library. - * All public APIs are exported from here. + * + * ## v2 API (Recommended) + * ```typescript + * import { createSweph } from '@af/sweph'; + * + * const sweph = await createSweph(); + * const planets = await sweph.calculatePlanets(new Date(), { ayanamsa: 1 }); + * ``` + * + * ## Legacy API (Deprecated) + * ```typescript + * import { initializeSweph, createSwephAdapter } from '@af/sweph'; + * + * await initializeSweph(); + * const adapter = await createSwephAdapter(); + * ``` */ -export * from './types'; +export { createSweph, type SwephInstance, type SwephInitOptions, type Location, type PlanetOptions, type AstroOptions, type RiseSetTransit, } from './v2'; export { calculatePlanets, calculateSinglePlanet, calculatePlanetRiseSetTimes, } from './planets'; export { calculateLagna, calculateHouses, } from './houses'; export { calculateSunTimes, calculateSolarNoon, calculateSunPath, } from './sun'; export { calculateMoonData, calculateMoonPhase, calculateNextMoonPhases, } from './moon'; -export { getAyanamsa, setEphemerisPath, getJulianDay, dateToJulian, julianToDate, getNativeModule, } from './utils'; +export { getAyanamsa, setEphemerisPath, getJulianDay, dateToJulian, julianToDate, getNativeModule, initializeSweph, } from './utils'; export { getPlatformInfo, hasPrebuilds, getSupportedPlatforms, } from './native-loader'; export { PLANETS, AYANAMSA, HOUSE_SYSTEMS, RASHIS, NAKSHATRAS, VEDIC_PLANET_ORDER, } from './constants'; -export { createSwephCalculator, createPlanetaryCalculator, createSwephAdapter, createNodeAdapter, initializeSweph, registerAdapter, calculateKundaliPageData, type PlanetaryCalculationProvider, type SwephAdapter, type SunTimesResult, type MoonTimesResult, type LegacyPlanet, type LegacyLagnaInfo, } from './legacy'; +export type { Planet, GeoLocation, SunTimes, MoonData, MoonPhase, LagnaInfo, NextMoonPhases, CalculationOptions, } from './types'; +export { PlanetId, AyanamsaType, HouseSystem, } from './types'; +export { +/** @deprecated Use createSweph() instead */ +createSwephCalculator, +/** @deprecated Use createSweph() instead */ +createPlanetaryCalculator, +/** @deprecated Use createSweph() instead */ +createSwephAdapter, +/** @deprecated Use createSweph() instead */ +createNodeAdapter, +/** @deprecated No longer needed - createSweph() auto-initializes */ +registerAdapter, +/** @deprecated Use individual calculation methods */ +calculateKundaliPageData, type PlanetaryCalculationProvider, type SwephAdapter, type SunTimesResult, type MoonTimesResult, type LegacyPlanet, type LegacyLagnaInfo, } from './legacy'; //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/packages/node/dist/index.d.ts.map b/packages/node/dist/index.d.ts.map index 66bc89c..4c4daf1 100644 --- a/packages/node/dist/index.d.ts.map +++ b/packages/node/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,cAAc,EACd,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,OAAO,EACP,QAAQ,EACR,aAAa,EACb,MAAM,EACN,UAAU,EACV,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAEL,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,wBAAwB,EAExB,KAAK,4BAA4B,EACjC,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,EAEL,WAAW,EAEX,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,MAAM,CAAC;AAOd,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,cAAc,EACd,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,QAAQ,CAAC;AAMhB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EACL,OAAO,EACP,QAAQ,EACR,aAAa,EACb,MAAM,EACN,UAAU,EACV,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAMrB,YAAY,EACV,MAAM,EACN,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EACT,cAAc,EACd,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC;AAMjB,OAAO;AAEL,4CAA4C;AAC5C,qBAAqB;AACrB,4CAA4C;AAC5C,yBAAyB;AACzB,4CAA4C;AAC5C,kBAAkB;AAClB,4CAA4C;AAC5C,iBAAiB;AACjB,oEAAoE;AACpE,eAAe;AACf,qDAAqD;AACrD,wBAAwB,EAExB,KAAK,4BAA4B,EACjC,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC"} \ No newline at end of file diff --git a/packages/node/dist/index.js b/packages/node/dist/index.js index 10414b4..344a00a 100644 --- a/packages/node/dist/index.js +++ b/packages/node/dist/index.js @@ -3,26 +3,34 @@ * @AstroFusion/sweph - Swiss Ephemeris for Vedic Astrology * * This is the main entry point for the library. - * All public APIs are exported from here. + * + * ## v2 API (Recommended) + * ```typescript + * import { createSweph } from '@af/sweph'; + * + * const sweph = await createSweph(); + * const planets = await sweph.calculatePlanets(new Date(), { ayanamsa: 1 }); + * ``` + * + * ## Legacy API (Deprecated) + * ```typescript + * import { initializeSweph, createSwephAdapter } from '@af/sweph'; + * + * await initializeSweph(); + * const adapter = await createSwephAdapter(); + * ``` */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; Object.defineProperty(exports, "__esModule", { value: true }); -exports.calculateKundaliPageData = exports.registerAdapter = exports.initializeSweph = exports.createNodeAdapter = exports.createSwephAdapter = exports.createPlanetaryCalculator = exports.createSwephCalculator = exports.VEDIC_PLANET_ORDER = exports.NAKSHATRAS = exports.RASHIS = exports.HOUSE_SYSTEMS = exports.AYANAMSA = exports.PLANETS = exports.getSupportedPlatforms = exports.hasPrebuilds = exports.getPlatformInfo = exports.getNativeModule = exports.julianToDate = exports.dateToJulian = exports.getJulianDay = exports.setEphemerisPath = exports.getAyanamsa = exports.calculateNextMoonPhases = exports.calculateMoonPhase = exports.calculateMoonData = exports.calculateSunPath = exports.calculateSolarNoon = exports.calculateSunTimes = exports.calculateHouses = exports.calculateLagna = exports.calculatePlanetRiseSetTimes = exports.calculateSinglePlanet = exports.calculatePlanets = void 0; -// Types -__exportStar(require("./types"), exports); +exports.calculateKundaliPageData = exports.registerAdapter = exports.createNodeAdapter = exports.createSwephAdapter = exports.createPlanetaryCalculator = exports.createSwephCalculator = exports.HouseSystem = exports.AyanamsaType = exports.PlanetId = exports.VEDIC_PLANET_ORDER = exports.NAKSHATRAS = exports.RASHIS = exports.HOUSE_SYSTEMS = exports.AYANAMSA = exports.PLANETS = exports.getSupportedPlatforms = exports.hasPrebuilds = exports.getPlatformInfo = exports.initializeSweph = exports.getNativeModule = exports.julianToDate = exports.dateToJulian = exports.getJulianDay = exports.setEphemerisPath = exports.getAyanamsa = exports.calculateNextMoonPhases = exports.calculateMoonPhase = exports.calculateMoonData = exports.calculateSunPath = exports.calculateSolarNoon = exports.calculateSunTimes = exports.calculateHouses = exports.calculateLagna = exports.calculatePlanetRiseSetTimes = exports.calculateSinglePlanet = exports.calculatePlanets = exports.createSweph = void 0; +// ============================================================================= +// v2 API (Recommended) +// ============================================================================= +var v2_1 = require("./v2"); +// Factory +Object.defineProperty(exports, "createSweph", { enumerable: true, get: function () { return v2_1.createSweph; } }); +// ============================================================================= +// Direct Calculation Functions (Advanced usage) +// ============================================================================= // Core calculation functions var planets_1 = require("./planets"); Object.defineProperty(exports, "calculatePlanets", { enumerable: true, get: function () { return planets_1.calculatePlanets; } }); @@ -39,7 +47,9 @@ var moon_1 = require("./moon"); Object.defineProperty(exports, "calculateMoonData", { enumerable: true, get: function () { return moon_1.calculateMoonData; } }); Object.defineProperty(exports, "calculateMoonPhase", { enumerable: true, get: function () { return moon_1.calculateMoonPhase; } }); Object.defineProperty(exports, "calculateNextMoonPhases", { enumerable: true, get: function () { return moon_1.calculateNextMoonPhases; } }); -// Utility functions +// ============================================================================= +// Utility Functions +// ============================================================================= var utils_1 = require("./utils"); Object.defineProperty(exports, "getAyanamsa", { enumerable: true, get: function () { return utils_1.getAyanamsa; } }); Object.defineProperty(exports, "setEphemerisPath", { enumerable: true, get: function () { return utils_1.setEphemerisPath; } }); @@ -47,12 +57,15 @@ Object.defineProperty(exports, "getJulianDay", { enumerable: true, get: function Object.defineProperty(exports, "dateToJulian", { enumerable: true, get: function () { return utils_1.dateToJulian; } }); Object.defineProperty(exports, "julianToDate", { enumerable: true, get: function () { return utils_1.julianToDate; } }); Object.defineProperty(exports, "getNativeModule", { enumerable: true, get: function () { return utils_1.getNativeModule; } }); +Object.defineProperty(exports, "initializeSweph", { enumerable: true, get: function () { return utils_1.initializeSweph; } }); // Platform utilities (for debugging deployment issues) var native_loader_1 = require("./native-loader"); Object.defineProperty(exports, "getPlatformInfo", { enumerable: true, get: function () { return native_loader_1.getPlatformInfo; } }); Object.defineProperty(exports, "hasPrebuilds", { enumerable: true, get: function () { return native_loader_1.hasPrebuilds; } }); Object.defineProperty(exports, "getSupportedPlatforms", { enumerable: true, get: function () { return native_loader_1.getSupportedPlatforms; } }); +// ============================================================================= // Constants +// ============================================================================= var constants_1 = require("./constants"); Object.defineProperty(exports, "PLANETS", { enumerable: true, get: function () { return constants_1.PLANETS; } }); Object.defineProperty(exports, "AYANAMSA", { enumerable: true, get: function () { return constants_1.AYANAMSA; } }); @@ -60,14 +73,25 @@ Object.defineProperty(exports, "HOUSE_SYSTEMS", { enumerable: true, get: functio Object.defineProperty(exports, "RASHIS", { enumerable: true, get: function () { return constants_1.RASHIS; } }); Object.defineProperty(exports, "NAKSHATRAS", { enumerable: true, get: function () { return constants_1.NAKSHATRAS; } }); Object.defineProperty(exports, "VEDIC_PLANET_ORDER", { enumerable: true, get: function () { return constants_1.VEDIC_PLANET_ORDER; } }); -// Legacy compatibility exports (for migration from @astrofusion/sweph-*) +var types_1 = require("./types"); +Object.defineProperty(exports, "PlanetId", { enumerable: true, get: function () { return types_1.PlanetId; } }); +Object.defineProperty(exports, "AyanamsaType", { enumerable: true, get: function () { return types_1.AyanamsaType; } }); +Object.defineProperty(exports, "HouseSystem", { enumerable: true, get: function () { return types_1.HouseSystem; } }); +// ============================================================================= +// Legacy API (Deprecated - for backwards compatibility) +// ============================================================================= var legacy_1 = require("./legacy"); // Factory functions +/** @deprecated Use createSweph() instead */ Object.defineProperty(exports, "createSwephCalculator", { enumerable: true, get: function () { return legacy_1.createSwephCalculator; } }); +/** @deprecated Use createSweph() instead */ Object.defineProperty(exports, "createPlanetaryCalculator", { enumerable: true, get: function () { return legacy_1.createPlanetaryCalculator; } }); +/** @deprecated Use createSweph() instead */ Object.defineProperty(exports, "createSwephAdapter", { enumerable: true, get: function () { return legacy_1.createSwephAdapter; } }); +/** @deprecated Use createSweph() instead */ Object.defineProperty(exports, "createNodeAdapter", { enumerable: true, get: function () { return legacy_1.createNodeAdapter; } }); -Object.defineProperty(exports, "initializeSweph", { enumerable: true, get: function () { return legacy_1.initializeSweph; } }); +/** @deprecated No longer needed - createSweph() auto-initializes */ Object.defineProperty(exports, "registerAdapter", { enumerable: true, get: function () { return legacy_1.registerAdapter; } }); +/** @deprecated Use individual calculation methods */ Object.defineProperty(exports, "calculateKundaliPageData", { enumerable: true, get: function () { return legacy_1.calculateKundaliPageData; } }); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/node/dist/index.js.map b/packages/node/dist/index.js.map index d581e56..eaab7fd 100644 --- a/packages/node/dist/index.js.map +++ b/packages/node/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;AAEH,QAAQ;AACR,0CAAwB;AAExB,6BAA6B;AAC7B,qCAImB;AAHjB,2GAAA,gBAAgB,OAAA;AAChB,gHAAA,qBAAqB,OAAA;AACrB,sHAAA,2BAA2B,OAAA;AAG7B,mCAGkB;AAFhB,wGAAA,cAAc,OAAA;AACd,yGAAA,eAAe,OAAA;AAGjB,6BAIe;AAHb,wGAAA,iBAAiB,OAAA;AACjB,yGAAA,kBAAkB,OAAA;AAClB,uGAAA,gBAAgB,OAAA;AAGlB,+BAIgB;AAHd,yGAAA,iBAAiB,OAAA;AACjB,0GAAA,kBAAkB,OAAA;AAClB,+GAAA,uBAAuB,OAAA;AAGzB,oBAAoB;AACpB,iCAOiB;AANf,oGAAA,WAAW,OAAA;AACX,yGAAA,gBAAgB,OAAA;AAChB,qGAAA,YAAY,OAAA;AACZ,qGAAA,YAAY,OAAA;AACZ,qGAAA,YAAY,OAAA;AACZ,wGAAA,eAAe,OAAA;AAGjB,uDAAuD;AACvD,iDAIyB;AAHvB,gHAAA,eAAe,OAAA;AACf,6GAAA,YAAY,OAAA;AACZ,sHAAA,qBAAqB,OAAA;AAGvB,YAAY;AACZ,yCAOqB;AANnB,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,0GAAA,aAAa,OAAA;AACb,mGAAA,MAAM,OAAA;AACN,uGAAA,UAAU,OAAA;AACV,+GAAA,kBAAkB,OAAA;AAGpB,yEAAyE;AACzE,mCAgBkB;AAfhB,oBAAoB;AACpB,+GAAA,qBAAqB,OAAA;AACrB,mHAAA,yBAAyB,OAAA;AACzB,4GAAA,kBAAkB,OAAA;AAClB,2GAAA,iBAAiB,OAAA;AACjB,yGAAA,eAAe,OAAA;AACf,yGAAA,eAAe,OAAA;AACf,kHAAA,wBAAwB,OAAA"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAEH,gFAAgF;AAChF,uBAAuB;AACvB,gFAAgF;AAEhF,2BAUc;AATZ,UAAU;AACV,iGAAA,WAAW,OAAA;AAUb,gFAAgF;AAChF,gDAAgD;AAChD,gFAAgF;AAEhF,6BAA6B;AAC7B,qCAImB;AAHjB,2GAAA,gBAAgB,OAAA;AAChB,gHAAA,qBAAqB,OAAA;AACrB,sHAAA,2BAA2B,OAAA;AAG7B,mCAGkB;AAFhB,wGAAA,cAAc,OAAA;AACd,yGAAA,eAAe,OAAA;AAGjB,6BAIe;AAHb,wGAAA,iBAAiB,OAAA;AACjB,yGAAA,kBAAkB,OAAA;AAClB,uGAAA,gBAAgB,OAAA;AAGlB,+BAIgB;AAHd,yGAAA,iBAAiB,OAAA;AACjB,0GAAA,kBAAkB,OAAA;AAClB,+GAAA,uBAAuB,OAAA;AAGzB,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF,iCAQiB;AAPf,oGAAA,WAAW,OAAA;AACX,yGAAA,gBAAgB,OAAA;AAChB,qGAAA,YAAY,OAAA;AACZ,qGAAA,YAAY,OAAA;AACZ,qGAAA,YAAY,OAAA;AACZ,wGAAA,eAAe,OAAA;AACf,wGAAA,eAAe,OAAA;AAGjB,uDAAuD;AACvD,iDAIyB;AAHvB,gHAAA,eAAe,OAAA;AACf,6GAAA,YAAY,OAAA;AACZ,sHAAA,qBAAqB,OAAA;AAGvB,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,yCAOqB;AANnB,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,0GAAA,aAAa,OAAA;AACb,mGAAA,MAAM,OAAA;AACN,uGAAA,UAAU,OAAA;AACV,+GAAA,kBAAkB,OAAA;AAkBpB,iCAIiB;AAHf,iGAAA,QAAQ,OAAA;AACR,qGAAA,YAAY,OAAA;AACZ,oGAAA,WAAW,OAAA;AAGb,gFAAgF;AAChF,wDAAwD;AACxD,gFAAgF;AAEhF,mCAqBkB;AApBhB,oBAAoB;AACpB,4CAA4C;AAC5C,+GAAA,qBAAqB,OAAA;AACrB,4CAA4C;AAC5C,mHAAA,yBAAyB,OAAA;AACzB,4CAA4C;AAC5C,4GAAA,kBAAkB,OAAA;AAClB,4CAA4C;AAC5C,2GAAA,iBAAiB,OAAA;AACjB,oEAAoE;AACpE,yGAAA,eAAe,OAAA;AACf,qDAAqD;AACrD,kHAAA,wBAAwB,OAAA"} \ No newline at end of file diff --git a/packages/node/dist/v2.d.ts b/packages/node/dist/v2.d.ts new file mode 100644 index 0000000..1bc7e4e --- /dev/null +++ b/packages/node/dist/v2.d.ts @@ -0,0 +1,207 @@ +/** + * @af/sweph v2 API + * + * Modern, auto-initializing Swiss Ephemeris API for Vedic Astrology. + * + * This is the recommended API for new projects. It provides: + * - Auto-initialization of native modules + * - Cleaner method signatures with options objects + * - Full TypeScript support + * - Consistent error handling + * + * @example + * ```typescript + * import { createSweph } from '@af/sweph'; + * + * const sweph = await createSweph(); + * const planets = await sweph.calculatePlanets(new Date(), { ayanamsa: 1 }); + * ``` + */ +import { PLANETS, AYANAMSA, RASHIS, NAKSHATRAS } from './constants'; +import type { Planet, GeoLocation, SunTimes, MoonData, MoonPhase, CalculationOptions, LagnaInfo, NextMoonPhases } from './types'; +/** + * Options for createSweph initialization + */ +export interface SwephInitOptions { + /** Path to ephemeris data files */ + ephePath?: string; + /** Pre-warm calculations on init (slightly slower startup, faster first call) */ + preWarm?: boolean; +} +/** + * Location with optional timezone + */ +export interface Location { + latitude: number; + longitude: number; + timezone?: number; +} +/** + * Options for planetary calculations + */ +export interface PlanetOptions { + /** Ayanamsa type (default: LAHIRI = 1) */ + ayanamsa?: number; + /** Timezone offset in hours (default: 0 = UTC) */ + timezone?: number; + /** Location for rise/set calculations */ + location?: Location; +} +/** + * Options for sun/moon calculations + */ +export interface AstroOptions { + /** Timezone offset in hours (default: 0 = UTC) */ + timezone?: number; +} +/** + * Planet rise/set/transit result + */ +export interface RiseSetTransit { + rise: Date | null; + set: Date | null; + transit: Date | null; + transitAltitude?: number; +} +/** + * The v2 SwephInstance - modern API with clean method signatures + */ +export interface SwephInstance { + /** + * Calculate positions for all Vedic planets + * @param date - Date/time for calculation + * @param options - Calculation options (ayanamsa, timezone) + * @returns Array of planet positions + */ + calculatePlanets(date: Date, options?: PlanetOptions): Promise; + /** + * Calculate position for a single planet + * @param planetId - Planet ID (0=Sun, 1=Moon, etc.) + * @param date - Date/time for calculation + * @param options - Calculation options + * @returns Planet position or null if calculation fails + */ + calculatePlanet(planetId: number, date: Date, options?: PlanetOptions): Promise; + /** + * Calculate rise, set, and transit times for a planet + * @param planetId - Planet ID + * @param date - Date for calculation + * @param location - Geographic location + * @returns Rise, set, and transit times + */ + calculateRiseSet(planetId: number, date: Date, location: Location): Promise; + /** + * Calculate Lagna (Ascendant) and houses + * @param date - Date/time for calculation + * @param location - Geographic location + * @param options - Calculation options (ayanamsa) + * @returns Lagna information with house cusps + */ + calculateLagna(date: Date, location: Location, options?: PlanetOptions): Promise; + /** + * Calculate sunrise, sunset, and solar noon + * @param date - Date for calculation + * @param location - Geographic location + * @returns Sun times + */ + calculateSunTimes(date: Date, location: Location): Promise; + /** + * Calculate solar noon for a location + * @param date - Date for calculation + * @param location - Geographic location + * @returns Solar noon time and altitude + */ + calculateSolarNoon(date: Date, location: Location): Promise<{ + time: Date; + altitude: number; + }>; + /** + * Calculate sun path throughout the day + * @param date - Date for calculation + * @param location - Geographic location + * @param intervalMinutes - Interval between points (default: 30) + * @returns Array of azimuth/altitude points + */ + calculateSunPath(date: Date, location: Location, intervalMinutes?: number): Promise>; + /** + * Calculate moon data (position, rise, set, phase) + * @param date - Date for calculation + * @param location - Geographic location + * @returns Moon data + */ + calculateMoonData(date: Date, location: Location): Promise; + /** + * Calculate current moon phase + * @param date - Date for calculation + * @returns Moon phase information + */ + calculateMoonPhase(date: Date): Promise; + /** + * Calculate next moon phases + * @param date - Date to start from + * @returns Next new moon, first quarter, full moon, last quarter + */ + calculateNextMoonPhases(date: Date): Promise; + /** + * Get ayanamsa value for a date + * @param date - Date for calculation + * @param ayanamsaType - Ayanamsa type (default: LAHIRI = 1) + * @returns Ayanamsa value in degrees + */ + getAyanamsa(date: Date, ayanamsaType?: number): number; + /** + * Convert date to Julian Day + * @param date - Date to convert + * @returns Julian Day number + */ + dateToJulian(date: Date): number; + /** + * Set path to ephemeris data files + * @param path - Directory containing .se1 files + */ + setEphePath(path: string): void; + /** Planet IDs */ + readonly PLANETS: typeof PLANETS; + /** Ayanamsa types */ + readonly AYANAMSA: typeof AYANAMSA; + /** Rashi (zodiac sign) names */ + readonly RASHIS: typeof RASHIS; + /** Nakshatra names */ + readonly NAKSHATRAS: typeof NAKSHATRAS; +} +/** + * Create a SwephInstance with auto-initialization + * + * This is the main entry point for the v2 API. It automatically initializes + * the native Swiss Ephemeris module and returns a ready-to-use instance. + * + * @param options - Optional initialization options + * @returns A fully initialized SwephInstance + * + * @example + * ```typescript + * import { createSweph, AYANAMSA } from '@af/sweph'; + * + * async function main() { + * const sweph = await createSweph(); + * + * // Calculate planets with Lahiri ayanamsa + * const planets = await sweph.calculatePlanets(new Date(), { + * ayanamsa: AYANAMSA.LAHIRI, + * timezone: 5.75 // Nepal + * }); + * + * console.log('Sun:', planets[0]); + * console.log('Moon:', planets[1]); + * } + * ``` + */ +export declare function createSweph(options?: SwephInitOptions): Promise; +export { PLANETS, AYANAMSA, RASHIS, NAKSHATRAS }; +export { AyanamsaType, PlanetId, HouseSystem } from './types'; +export type { Planet, GeoLocation, SunTimes, MoonData, MoonPhase, LagnaInfo, NextMoonPhases, CalculationOptions, }; +//# sourceMappingURL=v2.d.ts.map \ No newline at end of file diff --git a/packages/node/dist/v2.d.ts.map b/packages/node/dist/v2.d.ts.map new file mode 100644 index 0000000..dee529c --- /dev/null +++ b/packages/node/dist/v2.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../src/v2.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/node/dist/v2.js b/packages/node/dist/v2.js new file mode 100644 index 0000000..2022540 --- /dev/null +++ b/packages/node/dist/v2.js @@ -0,0 +1,198 @@ +"use strict"; +/** + * @af/sweph v2 API + * + * Modern, auto-initializing Swiss Ephemeris API for Vedic Astrology. + * + * This is the recommended API for new projects. It provides: + * - Auto-initialization of native modules + * - Cleaner method signatures with options objects + * - Full TypeScript support + * - Consistent error handling + * + * @example + * ```typescript + * import { createSweph } from '@af/sweph'; + * + * const sweph = await createSweph(); + * const planets = await sweph.calculatePlanets(new Date(), { ayanamsa: 1 }); + * ``` + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HouseSystem = exports.PlanetId = exports.AyanamsaType = exports.NAKSHATRAS = exports.RASHIS = exports.AYANAMSA = exports.PLANETS = void 0; +exports.createSweph = createSweph; +const planets_1 = require("./planets"); +const houses_1 = require("./houses"); +const sun_1 = require("./sun"); +const moon_1 = require("./moon"); +const utils_1 = require("./utils"); +const constants_1 = require("./constants"); +Object.defineProperty(exports, "PLANETS", { enumerable: true, get: function () { return constants_1.PLANETS; } }); +Object.defineProperty(exports, "AYANAMSA", { enumerable: true, get: function () { return constants_1.AYANAMSA; } }); +Object.defineProperty(exports, "RASHIS", { enumerable: true, get: function () { return constants_1.RASHIS; } }); +Object.defineProperty(exports, "NAKSHATRAS", { enumerable: true, get: function () { return constants_1.NAKSHATRAS; } }); +// ============================================================================ +// v2 Factory +// ============================================================================ +/** + * Create a SwephInstance with auto-initialization + * + * This is the main entry point for the v2 API. It automatically initializes + * the native Swiss Ephemeris module and returns a ready-to-use instance. + * + * @param options - Optional initialization options + * @returns A fully initialized SwephInstance + * + * @example + * ```typescript + * import { createSweph, AYANAMSA } from '@af/sweph'; + * + * async function main() { + * const sweph = await createSweph(); + * + * // Calculate planets with Lahiri ayanamsa + * const planets = await sweph.calculatePlanets(new Date(), { + * ayanamsa: AYANAMSA.LAHIRI, + * timezone: 5.75 // Nepal + * }); + * + * console.log('Sun:', planets[0]); + * console.log('Moon:', planets[1]); + * } + * ``` + */ +async function createSweph(options) { + // Auto-initialize the native module + await (0, utils_1.initializeSweph)(); + // Set ephemeris path if provided + if (options?.ephePath) { + (0, utils_1.setEphemerisPath)(options.ephePath); + } + // Create the instance + const instance = { + // Planets + async calculatePlanets(date, opts) { + const calcOpts = { + ayanamsa: opts?.ayanamsa ?? 1, + location: opts?.location ? { + latitude: opts.location.latitude, + longitude: opts.location.longitude, + timezone: opts.location.timezone ?? opts?.timezone ?? 0, + } : undefined, + }; + // Handle timezone offset + const tzOffset = opts?.timezone ?? opts?.location?.timezone ?? 0; + const utcDate = new Date(date.getTime() - tzOffset * 60 * 60 * 1000); + return (0, planets_1.calculatePlanets)(utcDate, calcOpts); + }, + async calculatePlanet(planetId, date, opts) { + const calcOpts = { + ayanamsa: opts?.ayanamsa ?? 1, + location: opts?.location ? { + latitude: opts.location.latitude, + longitude: opts.location.longitude, + timezone: opts.location.timezone ?? opts?.timezone ?? 0, + } : undefined, + }; + const tzOffset = opts?.timezone ?? opts?.location?.timezone ?? 0; + const utcDate = new Date(date.getTime() - tzOffset * 60 * 60 * 1000); + return (0, planets_1.calculateSinglePlanet)(planetId, utcDate, calcOpts); + }, + async calculateRiseSet(planetId, date, location) { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + const result = (0, planets_1.calculatePlanetRiseSetTimes)(planetId, date, geoLoc); + return { + rise: result.rise, + set: result.set, + transit: result.transit, + transitAltitude: result.transitAltitude, + }; + }, + // Lagna + async calculateLagna(date, location, opts) { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + const calcOpts = { + ayanamsa: opts?.ayanamsa ?? 1, + }; + return (0, houses_1.calculateLagna)(date, geoLoc, calcOpts); + }, + // Sun + async calculateSunTimes(date, location) { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return (0, sun_1.calculateSunTimes)(date, geoLoc); + }, + async calculateSolarNoon(date, location) { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return (0, sun_1.calculateSolarNoon)(date, geoLoc); + }, + async calculateSunPath(date, location, intervalMinutes = 30) { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return (0, sun_1.calculateSunPath)(date, geoLoc); + }, + // Moon + async calculateMoonData(date, location) { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return (0, moon_1.calculateMoonData)(date, geoLoc); + }, + async calculateMoonPhase(date) { + return (0, moon_1.calculateMoonPhase)(date); + }, + async calculateNextMoonPhases(date) { + return (0, moon_1.calculateNextMoonPhases)(date); + }, + // Utilities + getAyanamsa(date, ayanamsaType = 1) { + return (0, utils_1.getAyanamsa)(date, ayanamsaType); + }, + dateToJulian(date) { + return (0, utils_1.dateToJulian)(date); + }, + setEphePath(path) { + (0, utils_1.setEphemerisPath)(path); + }, + // Constants + PLANETS: constants_1.PLANETS, + AYANAMSA: constants_1.AYANAMSA, + RASHIS: constants_1.RASHIS, + NAKSHATRAS: constants_1.NAKSHATRAS, + }; + // Optional pre-warming + if (options?.preWarm) { + try { + await instance.calculatePlanets(new Date(), { ayanamsa: 1 }); + } + catch { + // Pre-warm failure is not critical + } + } + return instance; +} +var types_1 = require("./types"); +Object.defineProperty(exports, "AyanamsaType", { enumerable: true, get: function () { return types_1.AyanamsaType; } }); +Object.defineProperty(exports, "PlanetId", { enumerable: true, get: function () { return types_1.PlanetId; } }); +Object.defineProperty(exports, "HouseSystem", { enumerable: true, get: function () { return types_1.HouseSystem; } }); +//# sourceMappingURL=v2.js.map \ No newline at end of file diff --git a/packages/node/dist/v2.js.map b/packages/node/dist/v2.js.map new file mode 100644 index 0000000..f6ba017 --- /dev/null +++ b/packages/node/dist/v2.js.map @@ -0,0 +1 @@ +{"version":3,"file":"v2.js","sourceRoot":"","sources":["../src/v2.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/node/package.json b/packages/node/package.json index 626cc08..9f7d902 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -13,7 +13,7 @@ "scripts": { "build": "tsc", "build:check": "node scripts/check-static-requires.js", - "test": "echo 'Skipping node tests' && exit 0", + "test": "vitest run", "lint": "eslint src", "prebuild:linux": "bash scripts/build-linux-prebuild.sh", "copy:darwin-arm64": "mkdir -p prebuilds/darwin-arm64 && cp ../../node_modules/swisseph-v2/build/Release/swisseph.node prebuilds/darwin-arm64/", diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index b641831..8e0bbf9 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -2,11 +2,43 @@ * @AstroFusion/sweph - Swiss Ephemeris for Vedic Astrology * * This is the main entry point for the library. - * All public APIs are exported from here. + * + * ## v2 API (Recommended) + * ```typescript + * import { createSweph } from '@af/sweph'; + * + * const sweph = await createSweph(); + * const planets = await sweph.calculatePlanets(new Date(), { ayanamsa: 1 }); + * ``` + * + * ## Legacy API (Deprecated) + * ```typescript + * import { initializeSweph, createSwephAdapter } from '@af/sweph'; + * + * await initializeSweph(); + * const adapter = await createSwephAdapter(); + * ``` */ -// Types -export * from './types'; +// ============================================================================= +// v2 API (Recommended) +// ============================================================================= + +export { + // Factory + createSweph, + // Types + type SwephInstance, + type SwephInitOptions, + type Location, + type PlanetOptions, + type AstroOptions, + type RiseSetTransit, +} from './v2'; + +// ============================================================================= +// Direct Calculation Functions (Advanced usage) +// ============================================================================= // Core calculation functions export { @@ -32,7 +64,10 @@ export { calculateNextMoonPhases, } from './moon'; -// Utility functions +// ============================================================================= +// Utility Functions +// ============================================================================= + export { getAyanamsa, setEphemerisPath, @@ -40,6 +75,7 @@ export { dateToJulian, julianToDate, getNativeModule, + initializeSweph, } from './utils'; // Platform utilities (for debugging deployment issues) @@ -49,7 +85,10 @@ export { getSupportedPlatforms, } from './native-loader'; +// ============================================================================= // Constants +// ============================================================================= + export { PLANETS, AYANAMSA, @@ -59,15 +98,44 @@ export { VEDIC_PLANET_ORDER, } from './constants'; -// Legacy compatibility exports (for migration from @astrofusion/sweph-*) +// ============================================================================= +// Types +// ============================================================================= + +export type { + Planet, + GeoLocation, + SunTimes, + MoonData, + MoonPhase, + LagnaInfo, + NextMoonPhases, + CalculationOptions, +} from './types'; + +export { + PlanetId, + AyanamsaType, + HouseSystem, +} from './types'; + +// ============================================================================= +// Legacy API (Deprecated - for backwards compatibility) +// ============================================================================= + export { // Factory functions + /** @deprecated Use createSweph() instead */ createSwephCalculator, + /** @deprecated Use createSweph() instead */ createPlanetaryCalculator, + /** @deprecated Use createSweph() instead */ createSwephAdapter, + /** @deprecated Use createSweph() instead */ createNodeAdapter, - initializeSweph, + /** @deprecated No longer needed - createSweph() auto-initializes */ registerAdapter, + /** @deprecated Use individual calculation methods */ calculateKundaliPageData, // Types type PlanetaryCalculationProvider, diff --git a/packages/node/src/v2.test.ts b/packages/node/src/v2.test.ts new file mode 100644 index 0000000..2f99e78 --- /dev/null +++ b/packages/node/src/v2.test.ts @@ -0,0 +1,241 @@ +/** + * v2 API Tests + * + * Comprehensive test suite for the modern @af/sweph v2 API. + */ + +import { describe, it, expect, beforeAll } from 'vitest'; +import { + createSweph, + PLANETS, + AYANAMSA, + RASHIS, + NAKSHATRAS, + type SwephInstance, +} from './index'; + +describe('@af/sweph v2 API', () => { + let sweph: SwephInstance; + + beforeAll(async () => { + sweph = await createSweph(); + }); + + describe('createSweph', () => { + it('should create a SwephInstance', async () => { + const instance = await createSweph(); + expect(instance).toBeDefined(); + expect(instance.calculatePlanets).toBeInstanceOf(Function); + expect(instance.calculateLagna).toBeInstanceOf(Function); + }); + + it('should expose constants', async () => { + const instance = await createSweph(); + expect(instance.PLANETS).toBeDefined(); + expect(instance.AYANAMSA).toBeDefined(); + expect(instance.RASHIS).toBeDefined(); + expect(instance.NAKSHATRAS).toBeDefined(); + }); + + it('should accept initialization options', async () => { + const instance = await createSweph({ + preWarm: true, + }); + expect(instance).toBeDefined(); + }); + }); + + describe('calculatePlanets', () => { + it('should calculate all 9 Vedic planets', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + const planets = await sweph.calculatePlanets(date, { ayanamsa: 1 }); + + expect(planets).toBeInstanceOf(Array); + expect(planets.length).toBe(9); // Sun, Moon, Mars, Mercury, Jupiter, Venus, Saturn, Rahu, Ketu + }); + + it('should return valid longitude values (0-360)', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + const planets = await sweph.calculatePlanets(date, { ayanamsa: 1 }); + + for (const planet of planets) { + expect(planet.longitude).toBeGreaterThanOrEqual(0); + expect(planet.longitude).toBeLessThan(360); + } + }); + + it('should return valid rasi values (1-12)', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + const planets = await sweph.calculatePlanets(date, { ayanamsa: 1 }); + + for (const planet of planets) { + expect(planet.rasi).toBeGreaterThanOrEqual(1); + expect(planet.rasi).toBeLessThanOrEqual(12); + } + }); + + it('should support different ayanamsas', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + + const lahiri = await sweph.calculatePlanets(date, { ayanamsa: 1 }); + const raman = await sweph.calculatePlanets(date, { ayanamsa: 3 }); + + // Different ayanamsas should give different longitudes (small difference) + expect(lahiri[0].longitude).not.toBe(raman[0].longitude); + }); + }); + + describe('calculatePlanet', () => { + it('should calculate Sun position', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + const sun = await sweph.calculatePlanet(0, date, { ayanamsa: 1 }); + + expect(sun).toBeDefined(); + expect(sun!.longitude).toBeGreaterThanOrEqual(0); + expect(sun!.longitude).toBeLessThan(360); + }); + + it('should calculate Moon position', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + const moon = await sweph.calculatePlanet(1, date, { ayanamsa: 1 }); + + expect(moon).toBeDefined(); + expect(moon!.longitude).toBeGreaterThanOrEqual(0); + expect(moon!.longitude).toBeLessThan(360); + }); + }); + + describe('calculateLagna', () => { + it('should calculate ascendant', async () => { + const date = new Date('2024-01-01T06:00:00Z'); + const location = { latitude: 27.7, longitude: 85.3, timezone: 5.75 }; + + const lagna = await sweph.calculateLagna(date, location, { ayanamsa: 1 }); + + expect(lagna).toBeDefined(); + expect(lagna.longitude).toBeGreaterThanOrEqual(0); + expect(lagna.longitude).toBeLessThan(360); + expect(lagna.rasi).toBeGreaterThanOrEqual(1); + expect(lagna.rasi).toBeLessThanOrEqual(12); + }); + + it('should return 12 house cusps', async () => { + const date = new Date('2024-01-01T06:00:00Z'); + const location = { latitude: 27.7, longitude: 85.3 }; + + const lagna = await sweph.calculateLagna(date, location, { ayanamsa: 1 }); + + expect(lagna.houses).toBeDefined(); + expect(lagna.houses.length).toBe(12); + }); + }); + + describe('calculateSunTimes', () => { + it('should calculate sunrise and sunset', async () => { + const date = new Date('2024-06-21T12:00:00Z'); // Summer solstice + const location = { latitude: 27.7, longitude: 85.3, timezone: 5.75 }; + + const sunTimes = await sweph.calculateSunTimes(date, location); + + expect(sunTimes).toBeDefined(); + // Sun times may be Date objects or timestamps + expect(sunTimes.sunrise).toBeDefined(); + expect(sunTimes.sunset).toBeDefined(); + }); + }); + + describe('calculateMoonPhase', () => { + it('should calculate moon phase', async () => { + const date = new Date('2024-01-11T00:00:00Z'); // Near new moon + const phase = await sweph.calculateMoonPhase(date); + + expect(phase).toBeDefined(); + expect(phase.phaseName).toBeDefined(); + // Phase value may be in degrees (0-360) or normalized (0-1) + expect(typeof phase.phase).toBe('number'); + }); + }); + + describe('calculateNextMoonPhases', () => { + it('should return next moon phases', async () => { + const date = new Date('2024-01-01T00:00:00Z'); + const phases = await sweph.calculateNextMoonPhases(date); + + expect(phases).toBeDefined(); + // At least one phase should be defined + const hasPhase = phases.newMoon || phases.fullMoon || phases.firstQuarter || phases.lastQuarter; + expect(hasPhase).toBeTruthy(); + }); + }); + + describe('Utility methods', () => { + it('should convert date to Julian Day', () => { + const date = new Date('2000-01-01T12:00:00Z'); + const jd = sweph.dateToJulian(date); + + // JD for J2000.0 is 2451545.0 + expect(Math.abs(jd - 2451545.0)).toBeLessThan(0.01); + }); + + it('should get ayanamsa value', () => { + const date = new Date('2024-01-01T00:00:00Z'); + const ayanamsa = sweph.getAyanamsa(date, 1); // Lahiri + + // Lahiri ayanamsa should be around 24 degrees in 2024 + expect(ayanamsa).toBeGreaterThan(23); + expect(ayanamsa).toBeLessThan(25); + }); + }); + + describe('Constants', () => { + it('should have planet definitions', () => { + expect(PLANETS).toBeDefined(); + // PLANETS may be an object with id/name or just numeric IDs + expect(Object.keys(PLANETS).length).toBeGreaterThan(0); + }); + + it('should have ayanamsa definitions', () => { + expect(AYANAMSA).toBeDefined(); + expect(AYANAMSA.LAHIRI).toBeDefined(); + }); + + it('should have rashi definitions', () => { + expect(RASHIS).toBeDefined(); + expect(Object.keys(RASHIS).length).toBeGreaterThanOrEqual(12); + }); + + it('should have nakshatra definitions', () => { + expect(NAKSHATRAS).toBeDefined(); + expect(Object.keys(NAKSHATRAS).length).toBeGreaterThanOrEqual(27); + }); + }); +}); + +describe('Known astronomical calculations', () => { + let sweph: SwephInstance; + + beforeAll(async () => { + sweph = await createSweph(); + }); + + it('should show consistent results for same input', async () => { + const date = new Date('2024-01-01T12:00:00Z'); + + const planets1 = await sweph.calculatePlanets(date, { ayanamsa: 1 }); + const planets2 = await sweph.calculatePlanets(date, { ayanamsa: 1 }); + + expect(planets1[0].longitude).toBe(planets2[0].longitude); + expect(planets1[1].longitude).toBe(planets2[1].longitude); + }); + + it('should calculate different positions for different dates', async () => { + const date1 = new Date('2024-01-01T12:00:00Z'); + const date2 = new Date('2024-06-01T12:00:00Z'); + + const planets1 = await sweph.calculatePlanets(date1, { ayanamsa: 1 }); + const planets2 = await sweph.calculatePlanets(date2, { ayanamsa: 1 }); + + // Sun should be in different positions 5 months apart + expect(planets1[0].longitude).not.toBe(planets2[0].longitude); + }); +}); diff --git a/packages/node/src/v2.ts b/packages/node/src/v2.ts new file mode 100644 index 0000000..94d7ede --- /dev/null +++ b/packages/node/src/v2.ts @@ -0,0 +1,427 @@ +/** + * @af/sweph v2 API + * + * Modern, auto-initializing Swiss Ephemeris API for Vedic Astrology. + * + * This is the recommended API for new projects. It provides: + * - Auto-initialization of native modules + * - Cleaner method signatures with options objects + * - Full TypeScript support + * - Consistent error handling + * + * @example + * ```typescript + * import { createSweph } from '@af/sweph'; + * + * const sweph = await createSweph(); + * const planets = await sweph.calculatePlanets(new Date(), { ayanamsa: 1 }); + * ``` + */ + +import { + calculatePlanets, + calculateSinglePlanet, + calculatePlanetRiseSetTimes, +} from './planets'; + +import { calculateLagna, calculateHouses } from './houses'; +import { calculateSunTimes, calculateSolarNoon, calculateSunPath } from './sun'; +import { calculateMoonData, calculateMoonPhase, calculateNextMoonPhases } from './moon'; +import { initializeSweph, setEphemerisPath, getAyanamsa, dateToJulian } from './utils'; +import { PLANETS, AYANAMSA, RASHIS, NAKSHATRAS } from './constants'; + +import type { + Planet, + GeoLocation, + SunTimes, + MoonData, + MoonPhase, + CalculationOptions, + LagnaInfo, + NextMoonPhases, +} from './types'; + +// ============================================================================ +// v2 Types +// ============================================================================ + +/** + * Options for createSweph initialization + */ +export interface SwephInitOptions { + /** Path to ephemeris data files */ + ephePath?: string; + /** Pre-warm calculations on init (slightly slower startup, faster first call) */ + preWarm?: boolean; +} + +/** + * Location with optional timezone + */ +export interface Location { + latitude: number; + longitude: number; + timezone?: number; +} + +/** + * Options for planetary calculations + */ +export interface PlanetOptions { + /** Ayanamsa type (default: LAHIRI = 1) */ + ayanamsa?: number; + /** Timezone offset in hours (default: 0 = UTC) */ + timezone?: number; + /** Location for rise/set calculations */ + location?: Location; +} + +/** + * Options for sun/moon calculations + */ +export interface AstroOptions { + /** Timezone offset in hours (default: 0 = UTC) */ + timezone?: number; +} + +/** + * Planet rise/set/transit result + */ +export interface RiseSetTransit { + rise: Date | null; + set: Date | null; + transit: Date | null; + transitAltitude?: number; +} + +/** + * The v2 SwephInstance - modern API with clean method signatures + */ +export interface SwephInstance { + // === Planetary Calculations === + + /** + * Calculate positions for all Vedic planets + * @param date - Date/time for calculation + * @param options - Calculation options (ayanamsa, timezone) + * @returns Array of planet positions + */ + calculatePlanets(date: Date, options?: PlanetOptions): Promise; + + /** + * Calculate position for a single planet + * @param planetId - Planet ID (0=Sun, 1=Moon, etc.) + * @param date - Date/time for calculation + * @param options - Calculation options + * @returns Planet position or null if calculation fails + */ + calculatePlanet(planetId: number, date: Date, options?: PlanetOptions): Promise; + + /** + * Calculate rise, set, and transit times for a planet + * @param planetId - Planet ID + * @param date - Date for calculation + * @param location - Geographic location + * @param options - Calculation options (timezone) + * @returns Rise, set, and transit times + */ + calculateRiseSet(planetId: number, date: Date, location: Location, options?: PlanetOptions): Promise; + + // === Lagna & Houses === + + /** + * Calculate Lagna (Ascendant) and houses + * @param date - Date/time for calculation + * @param location - Geographic location + * @param options - Calculation options (ayanamsa) + * @returns Lagna information with house cusps + */ + calculateLagna(date: Date, location: Location, options?: PlanetOptions): Promise; + + // === Sun Calculations === + + /** + * Calculate sunrise, sunset, and solar noon + * @param date - Date for calculation + * @param location - Geographic location + * @returns Sun times + */ + calculateSunTimes(date: Date, location: Location): Promise; + + /** + * Calculate solar noon for a location + * @param date - Date for calculation + * @param location - Geographic location + * @returns Solar noon time and altitude + */ + calculateSolarNoon(date: Date, location: Location): Promise<{ time: Date; altitude: number }>; + + /** + * Calculate sun path throughout the day + * @param date - Date for calculation + * @param location - Geographic location + * @param intervalMinutes - Interval between points (default: 30) + * @returns Array of azimuth/altitude points + */ + calculateSunPath(date: Date, location: Location, intervalMinutes?: number): Promise>; + + // === Moon Calculations === + + /** + * Calculate moon data (position, rise, set, phase) + * @param date - Date for calculation + * @param location - Geographic location + * @returns Moon data + */ + calculateMoonData(date: Date, location: Location): Promise; + + /** + * Calculate current moon phase + * @param date - Date for calculation + * @returns Moon phase information + */ + calculateMoonPhase(date: Date): Promise; + + /** + * Calculate next moon phases + * @param date - Date to start from + * @returns Next new moon, first quarter, full moon, last quarter + */ + calculateNextMoonPhases(date: Date): Promise; + + // === Utilities === + + /** + * Get ayanamsa value for a date + * @param date - Date for calculation + * @param ayanamsaType - Ayanamsa type (default: LAHIRI = 1) + * @returns Ayanamsa value in degrees + */ + getAyanamsa(date: Date, ayanamsaType?: number): number; + + /** + * Convert date to Julian Day + * @param date - Date to convert + * @returns Julian Day number + */ + dateToJulian(date: Date): number; + + /** + * Set path to ephemeris data files + * @param path - Directory containing .se1 files + */ + setEphePath(path: string): void; + + // === Constants === + + /** Planet IDs */ + readonly PLANETS: typeof PLANETS; + + /** Ayanamsa types */ + readonly AYANAMSA: typeof AYANAMSA; + + /** Rashi (zodiac sign) names */ + readonly RASHIS: typeof RASHIS; + + /** Nakshatra names */ + readonly NAKSHATRAS: typeof NAKSHATRAS; +} + +// ============================================================================ +// v2 Factory +// ============================================================================ + +/** + * Create a SwephInstance with auto-initialization + * + * This is the main entry point for the v2 API. It automatically initializes + * the native Swiss Ephemeris module and returns a ready-to-use instance. + * + * @param options - Optional initialization options + * @returns A fully initialized SwephInstance + * + * @example + * ```typescript + * import { createSweph, AYANAMSA } from '@af/sweph'; + * + * async function main() { + * const sweph = await createSweph(); + * + * // Calculate planets with Lahiri ayanamsa + * const planets = await sweph.calculatePlanets(new Date(), { + * ayanamsa: AYANAMSA.LAHIRI, + * timezone: 5.75 // Nepal + * }); + * + * console.log('Sun:', planets[0]); + * console.log('Moon:', planets[1]); + * } + * ``` + */ +export async function createSweph(options?: SwephInitOptions): Promise { + // Auto-initialize the native module + await initializeSweph(); + + // Set ephemeris path if provided + if (options?.ephePath) { + setEphemerisPath(options.ephePath); + } + + // Create the instance + const instance: SwephInstance = { + // Planets + async calculatePlanets(date: Date, opts?: PlanetOptions): Promise { + const calcOpts: CalculationOptions = { + ayanamsa: opts?.ayanamsa ?? 1, + location: opts?.location ? { + latitude: opts.location.latitude, + longitude: opts.location.longitude, + } : undefined, + }; + + // Handle timezone offset + const tzOffset = opts?.timezone ?? opts?.location?.timezone ?? 0; + const utcDate = new Date(date.getTime() - tzOffset * 60 * 60 * 1000); + + return calculatePlanets(utcDate, calcOpts); + }, + + async calculatePlanet(planetId: number, date: Date, opts?: PlanetOptions): Promise { + const calcOpts: CalculationOptions = { + ayanamsa: opts?.ayanamsa ?? 1, + location: opts?.location ? { + latitude: opts.location.latitude, + longitude: opts.location.longitude, + } : undefined, + }; + + const tzOffset = opts?.timezone ?? opts?.location?.timezone ?? 0; + const utcDate = new Date(date.getTime() - tzOffset * 60 * 60 * 1000); + + return calculateSinglePlanet(planetId, utcDate, calcOpts); + }, + + async calculateRiseSet(planetId: number, date: Date, location: Location, opts?: PlanetOptions): Promise { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: opts?.timezone ?? location.timezone ?? 0, + }; + const result = calculatePlanetRiseSetTimes(planetId, date, geoLoc); + return { + rise: result.rise, + set: result.set, + transit: result.transit, + transitAltitude: result.transitAltitude, + }; + }, + + // Lagna + async calculateLagna(date: Date, location: Location, opts?: PlanetOptions): Promise { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + const calcOpts: CalculationOptions = { + ayanamsa: opts?.ayanamsa ?? 1, + }; + return calculateLagna(date, geoLoc, calcOpts); + }, + + // Sun + async calculateSunTimes(date: Date, location: Location): Promise { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return calculateSunTimes(date, geoLoc); + }, + + async calculateSolarNoon(date: Date, location: Location): Promise<{ time: Date; altitude: number }> { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return calculateSolarNoon(date, geoLoc); + }, + + async calculateSunPath(date: Date, location: Location, intervalMinutes: number = 30): Promise> { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return calculateSunPath(date, geoLoc); + }, + + // Moon + async calculateMoonData(date: Date, location: Location): Promise { + const geoLoc = { + latitude: location.latitude, + longitude: location.longitude, + timezone: location.timezone ?? 0, + }; + return calculateMoonData(date, geoLoc); + }, + + async calculateMoonPhase(date: Date): Promise { + return calculateMoonPhase(date); + }, + + async calculateNextMoonPhases(date: Date): Promise { + return calculateNextMoonPhases(date); + }, + + // Utilities + getAyanamsa(date: Date, ayanamsaType: number = 1): number { + return getAyanamsa(date, ayanamsaType); + }, + + dateToJulian(date: Date): number { + return dateToJulian(date); + }, + + setEphePath(path: string): void { + setEphemerisPath(path); + }, + + // Constants + PLANETS, + AYANAMSA, + RASHIS, + NAKSHATRAS, + }; + + // Optional pre-warming + if (options?.preWarm) { + try { + await instance.calculatePlanets(new Date(), { ayanamsa: 1 }); + } catch { + // Pre-warm failure is not critical + } + } + + return instance; +} + +// ============================================================================ +// Re-exports for convenience +// ============================================================================ + +export { PLANETS, AYANAMSA, RASHIS, NAKSHATRAS }; +export { AyanamsaType, PlanetId, HouseSystem } from './types'; + +// Type exports +export type { + Planet, + GeoLocation, + SunTimes, + MoonData, + MoonPhase, + LagnaInfo, + NextMoonPhases, + CalculationOptions, +};