A high-precision JavaScript wrapper for the Swiss Ephemeris WebAssembly module, providing professional-grade astronomical calculations for astrology, astronomy, and related applications.
β Enjoying this project? Support development on Ko-fi to help keep it free and actively maintained!
Try it now: Interactive SwissEph Demo
Experience all features including:
npm install swisseph-wasm
yarn add swisseph-wasm
pnpm add swisseph-wasm
<script type="module">
import SwissEph from 'https://cdn.jsdelivr.net/gh/prolaxu/swisseph-wasm@main/src/swisseph.js';
// Your code here
</script>
src/swisseph.js) - Main JavaScript wrapperwasm/) - Compiled Swiss Ephemeristests/) - 106 tests covering all functionalityπ Want to see it in action first? Try the Interactive Demo
import SwissEph from 'swisseph-wasm';
// Create and initialize
const swe = new SwissEph();
await swe.initSwissEph();
// Calculate planetary position
const jd = swe.julday(2023, 6, 15, 12.0); // June 15, 2023, 12:00 UTC
const sunPos = swe.calc_ut(jd, swe.SE_SUN, swe.SEFLG_SWIEPH);
console.log(`Sun longitude: ${sunPos[0]}Β°`);
// Clean up
swe.close();
import SwissEph from 'swisseph-wasm';
// You can also import the example calculator
// import { BirthChartCalculator } from 'swisseph-wasm/examples/birth-chart.js';
const calculator = new BirthChartCalculator();
const chart = await calculator.calculateBirthChart({
year: 1990, month: 5, day: 15,
hour: 14, minute: 30, timezone: -5,
latitude: 40.7128, longitude: -74.0060
});
console.log('Planetary Positions:');
Object.entries(chart.planets).forEach(([name, planet]) => {
console.log(`${planet.symbol} ${name}: ${planet.zodiacSign.formatted}`);
});
calculator.destroy();
SwissEph WebAssembly works seamlessly across different environments. Here are platform-specific setup instructions:
import SwissEph from 'swisseph-wasm';
async function nodeExample() {
const swe = new SwissEph();
await swe.initSwissEph();
const jd = swe.julday(2023, 6, 15, 12.0);
const sunPos = swe.calc_ut(jd, swe.SE_SUN, swe.SEFLG_SWIEPH);
console.log(`Sun longitude: ${sunPos[0].toFixed(2)}Β°`);
swe.close();
}
nodeExample().catch(console.error);
Add this configuration to your vite.config.js:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' // or react, etc.
export default defineConfig({
plugins: [vue()],
server: {
fs: {
allow: ['..']
}
},
assetsInclude: ['**/*.wasm'],
optimizeDeps: {
exclude: ['swisseph-wasm']
}
})
<script setup>
import SwissEph from 'swisseph-wasm';
import { onMounted, onUnmounted, ref } from 'vue';
const swe = ref(null);
const isInitialized = ref(false);
const result = ref('');
onMounted(async () => {
try {
swe.value = new SwissEph();
await swe.value.initSwissEph();
isInitialized.value = true;
} catch (error) {
console.error('Failed to initialize SwissEph:', error);
}
});
onUnmounted(() => {
if (swe.value) {
swe.value.close();
}
});
const calculate = () => {
if (!isInitialized.value) return;
const jd = swe.value.julday(2023, 6, 15, 12.0);
const sunPos = swe.value.calc_ut(jd, swe.value.SE_SUN, swe.value.SEFLG_SWIEPH);
result.value = `Sun: ${sunPos[0].toFixed(2)}Β°`;
};
</script>
<template>
<div>
<button @click="calculate" :disabled="!isInitialized">
Calculate Sun Position
</button>
<p></p>
</div>
</template>
import React, { useState, useEffect } from 'react';
import SwissEph from 'swisseph-wasm';
function AstrologyCalculator() {
const [swe, setSwe] = useState(null);
const [isInitialized, setIsInitialized] = useState(false);
const [result, setResult] = useState('');
useEffect(() => {
const initSwissEph = async () => {
try {
const swissEph = new SwissEph();
await swissEph.initSwissEph();
setSwe(swissEph);
setIsInitialized(true);
} catch (error) {
console.error('Failed to initialize SwissEph:', error);
}
};
initSwissEph();
return () => {
if (swe) {
swe.close();
}
};
}, []);
const calculate = () => {
if (!isInitialized || !swe) return;
const jd = swe.julday(2023, 6, 15, 12.0);
const sunPos = swe.calc_ut(jd, swe.SE_SUN, swe.SEFLG_SWIEPH);
setResult(`Sun: ${sunPos[0].toFixed(2)}Β°`);
};
return (
<div>
<button onClick={calculate} disabled={!isInitialized}>
Calculate Sun Position
</button>
<p>{result}</p>
</div>
);
}
export default AstrologyCalculator;
<!DOCTYPE html>
<html>
<head>
<title>SwissEph Example</title>
</head>
<body>
<button id="calculate">Calculate Sun Position</button>
<div id="result"></div>
<script type="module">
import SwissEph from 'https://cdn.jsdelivr.net/gh/prolaxu/swisseph-wasm@main/src/swisseph.js';
let swe = null;
let isInitialized = false;
// Initialize SwissEph
(async () => {
try {
swe = new SwissEph();
await swe.initSwissEph();
isInitialized = true;
console.log('SwissEph initialized successfully');
} catch (error) {
console.error('Failed to initialize SwissEph:', error);
}
})();
// Calculate button handler
document.getElementById('calculate').addEventListener('click', () => {
if (!isInitialized || !swe) {
document.getElementById('result').textContent = 'SwissEph not initialized';
return;
}
const jd = swe.julday(2023, 6, 15, 12.0);
const sunPos = swe.calc_ut(jd, swe.SE_SUN, swe.SEFLG_SWIEPH);
document.getElementById('result').textContent = `Sun: ${sunPos[0].toFixed(2)}Β°`;
});
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
if (swe) {
swe.close();
}
});
</script>
</body>
</html>
If using Webpack, add this to your webpack.config.js:
module.exports = {
// ... other config
experiments: {
asyncWebAssembly: true,
},
module: {
rules: [
{
test: /\.wasm$/,
type: 'webassembly/async',
},
],
},
};
| Document | Description |
|---|---|
| DOCUMENTATION.md | Complete API reference and usage guide |
| QUICK_REFERENCE.md | Quick developer reference |
| examples/README.md | Example usage patterns |
| tests/README.md | Test suite documentation |
The library includes a comprehensive test suite with 106 tests:
npm install
npm test # Run all tests
npm run test:coverage # Run with coverage report
npm run test:watch # Watch mode
Test Coverage:
swiss-wasm/
βββ src/
β βββ swisseph.js # Main library file
βββ wasm/
β βββ swisseph.js # WebAssembly module
β βββ swisseph.wasm # WebAssembly binary
βββ tests/
β βββ swisseph.test.js # Core functionality tests
β βββ swisseph-advanced.test.js # Advanced features tests
β βββ swisseph-integration.test.js # Integration tests
β βββ swisseph-constants.test.js # Constants validation
β βββ __mocks__/ # Mock implementations
β βββ README.md # Test documentation
βββ examples/
β βββ basic-usage.js # Basic usage examples
β βββ birth-chart.js # Birth chart calculator
β βββ README.md # Examples documentation
βββ DOCUMENTATION.md # Complete API reference
βββ QUICK_REFERENCE.md # Quick developer guide
βββ README.md # This file
Modern Browsers:
Requirements:
Error: WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 64 6f
Solution: Add Vite configuration to your vite.config.js:
export default defineConfig({
plugins: [vue()],
server: {
fs: { allow: ['..'] }
},
assetsInclude: ['**/*.wasm'],
optimizeDeps: {
exclude: ['swisseph-wasm']
}
})
Error: Cannot read properties of undefined (reading 'ccall')
Solution: Always call await swe.initSwissEph() before using any methods:
const swe = new SwissEph();
await swe.initSwissEph(); // Required!
const jd = swe.julday(2023, 6, 15, 12.0);
Error: process is not defined in browser
Solution: This is fixed in the latest version. Update to the latest version:
npm update swisseph-wasm
Error: Out of memory or performance issues
Solution: Always call swe.close() when done:
try {
const swe = new SwissEph();
await swe.initSwissEph();
// ... your calculations
} finally {
swe.close(); // Always clean up!
}
Error: Module not found when using CDN
Solution: Use the correct CDN URL:
// β
Correct
import SwissEph from 'https://cdn.jsdelivr.net/gh/prolaxu/swisseph-wasm@main/src/swisseph.js';
// β Incorrect
import SwissEph from 'https://cdn.jsdelivr.net/npm/swisseph-wasm';
Error: Type definitions not found
Solution: Types are included in the package:
import SwissEph from 'swisseph-wasm';
// Types are automatically available
close() when doneawait swe.initSwissEph() only once per instanceπ Interactive Examples: Try all these examples and more in the Live Demo
async function getCurrentPositions() {
const swe = new SwissEph();
await swe.initSwissEph();
const now = new Date();
const jd = swe.julday(
now.getUTCFullYear(),
now.getUTCMonth() + 1,
now.getUTCDate(),
now.getUTCHours() + now.getUTCMinutes() / 60
);
const planets = [swe.SE_SUN, swe.SE_MOON, swe.SE_MERCURY];
const positions = {};
for (const planet of planets) {
const pos = swe.calc_ut(jd, planet, swe.SEFLG_SWIEPH);
positions[swe.get_planet_name(planet)] = pos[0];
}
swe.close();
return positions;
}
async function compareSystems(year, month, day) {
const swe = new SwissEph();
await swe.initSwissEph();
const jd = swe.julday(year, month, day, 12);
// Tropical
const tropical = swe.calc_ut(jd, swe.SE_SUN, swe.SEFLG_SWIEPH);
// Sidereal (Lahiri)
swe.set_sid_mode(swe.SE_SIDM_LAHIRI, 0, 0);
const sidereal = swe.calc_ut(jd, swe.SE_SUN, swe.SEFLG_SWIEPH | swe.SEFLG_SIDEREAL);
swe.close();
return {
tropical: tropical[0],
sidereal: sidereal[0],
difference: tropical[0] - sidereal[0]
};
}
# Basic usage examples
node examples/basic-usage.js
# Birth chart calculation
node examples/birth-chart.js
swe.close()async function safeCalculation() {
let swe = null;
try {
swe = new SwissEph();
await swe.initSwissEph();
// calculations here
return result;
} catch (error) {
console.error('Calculation failed:', error);
return null;
} finally {
if (swe) swe.close();
}
}
This library is a wrapper around the Swiss Ephemeris, which is licensed under the GNU General Public License (GPL) for non-commercial use. For commercial use, a license from Astrodienst is required.
Swiss Ephemeris License:
This project is licensed under GPL-3.0-or-later - see the LICENSE file for details.
IMPORTANT: This library incorporates the Swiss Ephemeris, which uses a dual licensing model:
For commercial use of Swiss Ephemeris:
Astrodienst AG π§ Email: swisseph@astro.ch π Website: https://www.astro.com/swisseph/ π Address: Dammstrasse 23, CH-8702 Zollikon, Switzerland
| Use Case | License Required | Action Needed |
|---|---|---|
| π Open Source Project | GPL v3 | β Use freely, keep project open source |
| πΌ Commercial Product | Commercial License | β οΈ Contact Astrodienst AG |
| π Educational/Research | GPL v3 | β Use freely for non-commercial purposes |
| π’ Internal Business Tools | Commercial License | β οΈ Contact Astrodienst AG |
The author of swisseph-wasm is not affiliated with Astrodienst AG and cannot provide commercial licenses for Swiss Ephemeris. This WebAssembly wrapper is provided βas isβ under GPL v3. Users are responsible for ensuring compliance with Swiss Ephemeris licensing terms for their specific use case.
We welcome contributions! Please feel free to submit a Pull Request.
Ready to calculate the cosmos? Start with the Quick Reference or dive into the Complete Documentation! π