This document providing exhaustive coverage for the 72 distinct ways to integrate SwissEph across platforms, build types, entrypoint styles, and ephemeris modes.
We support 72 distinct integration paths based on:
- 3 Entrypoint Styles
- 2 Build Types
- 4 Platforms
- 3 Ephemeris Modes
- JS Entry point: Using the high-level
SwissEphclass (Recommended). - Direct WebAssembly: Manual instantiation using the
WebAssemblyAPI. - Inline integration: Using pre-bundled JS with embedded WASM (Fast-start).
- wasmbuild: Rust-powered build with high-level bindings
(
lib/wasm-inline). - wasi: Direct C-compiled build with a virtual POSIX environment
(
lib/wasi).
- Deno, Node.js, Browser, and Cloudflare Workers.
| Dimension | Options |
|---|---|
| 1. Entrypoint Style | JS API, Direct WASM, Inline |
| 2. Build Type | wasmbuild, wasi |
| 3. Platform | Deno, Node.js, Browser, Worker |
| 4. Ephemeris Mode | Moshier, Swiss Ephemeris, JPL |
Total: 3 × 2 × 4 × 3 = 72 paths verified for parity.
All 72 example files are located in examples/:
| # | Platform | Build | Style | Mode | Benchmark | File |
|---|---|---|---|---|---|---|
| 1 | deno | wasmbuild | js_api | moshier | 417k | deno/wasmbuild_js_api_moshier.ts |
| 2 | deno | wasmbuild | js_api | swiss | 417k | deno/wasmbuild_js_api_swiss.ts |
| 3 | deno | wasmbuild | js_api | jpl | 417k | deno/wasmbuild_js_api_jpl.ts |
| 4 | deno | wasmbuild | direct_wasm | moshier | 878k | deno/wasmbuild_direct_wasm_moshier.ts |
| 5 | deno | wasmbuild | direct_wasm | swiss | 878k | deno/wasmbuild_direct_wasm_swiss.ts |
| 6 | deno | wasmbuild | direct_wasm | jpl | 878k | deno/wasmbuild_direct_wasm_jpl.ts |
| 7 | deno | wasmbuild | inline | moshier | 371k | deno/wasmbuild_inline_moshier.ts |
| 8 | deno | wasmbuild | inline | swiss | 371k | deno/wasmbuild_inline_swiss.ts |
| 9 | deno | wasmbuild | inline | jpl | 371k | deno/wasmbuild_inline_jpl.ts |
| 10 | deno | wasi | js_api | moshier | 81k | deno/wasi_js_api_moshier.ts |
| 11 | deno | wasi | js_api | swiss | 81k | deno/wasi_js_api_swiss.ts |
| 12 | deno | wasi | js_api | jpl | 81k | deno/wasi_js_api_jpl.ts |
| 13 | deno | wasi | direct_wasm | moshier | N/A | deno/wasi_direct_wasm_moshier.ts |
| 14 | deno | wasi | direct_wasm | swiss | N/A | deno/wasi_direct_wasm_swiss.ts |
| 15 | deno | wasi | direct_wasm | jpl | N/A | deno/wasi_direct_wasm_jpl.ts |
| 16 | deno | wasi | inline | moshier | 85k | deno/wasi_inline_moshier.ts |
| 17 | deno | wasi | inline | swiss | 85k | deno/wasi_inline_swiss.ts |
| 18 | deno | wasi | inline | jpl | 85k | deno/wasi_inline_jpl.ts |
| 19 | node | wasmbuild | js_api | moshier | 627k | node/wasmbuild_js_api_moshier.mjs |
| 20 | node | wasmbuild | js_api | swiss | 627k | node/wasmbuild_js_api_swiss.mjs |
| 21 | node | wasmbuild | js_api | jpl | 627k | node/wasmbuild_js_api_jpl.mjs |
| 22 | node | wasmbuild | direct_wasm | moshier | 1,006k | node/wasmbuild_direct_wasm_moshier.mjs |
| 23 | node | wasmbuild | direct_wasm | swiss | 1,006k | node/wasmbuild_direct_wasm_swiss.mjs |
| 24 | node | wasmbuild | direct_wasm | jpl | 1,006k | node/wasmbuild_direct_wasm_jpl.mjs |
| 25 | node | wasmbuild | inline | moshier | 606k | node/wasmbuild_inline_moshier.mjs |
| 26 | node | wasmbuild | inline | swiss | 606k | node/wasmbuild_inline_swiss.mjs |
| 27 | node | wasmbuild | inline | jpl | 606k | node/wasmbuild_inline_jpl.mjs |
| 28 | node | wasi | js_api | moshier | 174k | node/wasi_js_api_moshier.mjs |
| 29 | node | wasi | js_api | swiss | 174k | node/wasi_js_api_swiss.mjs |
| 30 | node | wasi | js_api | jpl | 174k | node/wasi_js_api_jpl.mjs |
| 31 | node | wasi | direct_wasm | moshier | N/A | node/wasi_direct_wasm_moshier.mjs |
| 32 | node | wasi | direct_wasm | swiss | N/A | node/wasi_direct_wasm_swiss.mjs |
| 33 | node | wasi | direct_wasm | jpl | N/A | node/wasi_direct_wasm_jpl.mjs |
| 34 | node | wasi | inline | moshier | 173k | node/wasi_inline_moshier.mjs |
| 35 | node | wasi | inline | swiss | 173k | node/wasi_inline_swiss.mjs |
| 36 | node | wasi | inline | jpl | 173k | node/wasi_inline_jpl.mjs |
| 37 | browser | wasmbuild | js_api | moshier | ~400k | browser/wasmbuild_js_api_moshier.html |
| 38 | browser | wasmbuild | js_api | swiss | ~400k | browser/wasmbuild_js_api_swiss.html |
| 39 | browser | wasmbuild | js_api | jpl | ~400k | browser/wasmbuild_js_api_jpl.html |
| 40 | browser | wasmbuild | direct_wasm | moshier | ~800k | browser/wasmbuild_direct_wasm_moshier.html |
| 41 | browser | wasmbuild | direct_wasm | swiss | ~800k | browser/wasmbuild_direct_wasm_swiss.html |
| 42 | browser | wasmbuild | direct_wasm | jpl | ~800k | browser/wasmbuild_direct_wasm_jpl.html |
| 43 | browser | wasmbuild | inline | moshier | ~350k | browser/wasmbuild_inline_moshier.html |
| 44 | browser | wasmbuild | inline | swiss | ~350k | browser/wasmbuild_inline_swiss.html |
| 45 | browser | wasmbuild | inline | jpl | ~350k | browser/wasmbuild_inline_jpl.html |
| 46 | browser | wasi | js_api | moshier | ~80k | browser/wasi_js_api_moshier.html |
| 47 | browser | wasi | js_api | swiss | ~80k | browser/wasi_js_api_swiss.html |
| 48 | browser | wasi | js_api | jpl | ~80k | browser/wasi_js_api_jpl.html |
| 49 | browser | wasi | direct_wasm | moshier | N/A | browser/wasi_direct_wasm_moshier.html |
| 50 | browser | wasi | direct_wasm | swiss | N/A | browser/wasi_direct_wasm_swiss.html |
| 51 | browser | wasi | direct_wasm | jpl | N/A | browser/wasi_direct_wasm_jpl.html |
| 52 | browser | wasi | inline | moshier | ~80k | browser/wasi_inline_moshier.html |
| 53 | browser | wasi | inline | swiss | ~80k | browser/wasi_inline_swiss.html |
| 54 | browser | wasi | inline | jpl | ~80k | browser/wasi_inline_jpl.html |
| 55 | worker | wasmbuild | js_api | moshier | ~400k | worker/wasmbuild_js_api_moshier.ts |
| 56 | worker | wasmbuild | js_api | swiss | ~400k | worker/wasmbuild_js_api_swiss.ts |
| 57 | worker | wasmbuild | js_api | jpl | ~400k | worker/wasmbuild_js_api_jpl.ts |
| 58 | worker | wasmbuild | direct_wasm | moshier | ~800k | worker/wasmbuild_direct_wasm_moshier.ts |
| 59 | worker | wasmbuild | direct_wasm | swiss | ~800k | worker/wasmbuild_direct_wasm_swiss.ts |
| 60 | worker | wasmbuild | direct_wasm | jpl | ~800k | worker/wasmbuild_direct_wasm_jpl.ts |
| 61 | worker | wasmbuild | inline | moshier | ~350k | worker/wasmbuild_inline_moshier.ts |
| 62 | worker | wasmbuild | inline | swiss | ~350k | worker/wasmbuild_inline_swiss.ts |
| 63 | worker | wasmbuild | inline | jpl | ~350k | worker/wasmbuild_inline_jpl.ts |
| 64 | worker | wasi | js_api | moshier | ~80k | worker/wasi_js_api_moshier.ts |
| 65 | worker | wasi | js_api | swiss | ~80k | worker/wasi_js_api_swiss.ts |
| 66 | worker | wasi | js_api | jpl | ~80k | worker/wasi_js_api_jpl.ts |
| 67 | worker | wasi | direct_wasm | moshier | N/A | worker/wasi_direct_wasm_moshier.ts |
| 68 | worker | wasi | direct_wasm | swiss | N/A | worker/wasi_direct_wasm_swiss.ts |
| 69 | worker | wasi | direct_wasm | jpl | N/A | worker/wasi_direct_wasm_jpl.ts |
| 70 | worker | wasi | inline | moshier | ~80k | worker/wasi_inline_moshier.ts |
| 71 | worker | wasi | inline | swiss | ~80k | worker/wasi_inline_swiss.ts |
| 72 | worker | wasi | inline | jpl | ~80k | worker/wasi_inline_jpl.ts |
Tip
Deno/Node benchmarks are measured. Browser/Worker are estimated (~) based on similar runtime characteristics.
Benchmarks measured on Apple M1/M2 (ops/sec):
| Platform | Build | Style | Moshier | Swiss | JPL |
|---|---|---|---|---|---|
| Deno | wasmbuild | js_api | 417k | 417k | 417k |
| Deno | wasmbuild | direct_wasm | 878k | 878k | 878k |
| Deno | wasmbuild | inline | 371k | 371k | 371k |
| Deno | wasi | js_api | 81k | 81k | 81k |
| Node | wasmbuild | js_api | 627k | 627k | 627k |
| Node | wasmbuild | direct_wasm | 1,006k | 1,006k | 1,006k |
| Node | wasmbuild | inline | 606k | 606k | 606k |
| Node | wasi | js_api | 174k | 174k | 174k |
Tip
Peak performance: 1,006,000 ops/sec (Node.js + wasmbuild + direct_wasm)
Note
Warning (WebAssembly.instantiate on the wasi build in
Browser/Worker requires manual polyfilling of the wasi_snapshot_preview1
import. Use the JS Entry point (SwissEph class) to handle this
automatically. |
import { SwissEph } from "@fusionstrings/swiss-eph";
const wasmUrl = new URL("./swiss_eph.wasm", import.meta.url);
const eph = new SwissEph(await WebAssembly.compileStreaming(fetch(wasmUrl)));import Context from "@std/wasi"; // or native Deno.WASI
const wasi = new Context({ args: [], env: {}, preopens: { ".": "." } });
const instance = await WebAssembly.instantiate(module, {
wasi_snapshot_preview1: wasi.exports,
});import { readFile } from "node:fs/promises";
import { SwissEph } from "@fusionstrings/swiss-eph/wasi";
const eph = new SwissEph(
await WebAssembly.compile(await readFile("./swiss_eph.wasm")),
);import { WASI } from "node:wasi";
const wasi = new WASI({ version: "preview1" });
const { instance } = await WebAssembly.instantiate(buffer, {
wasi_snapshot_preview1: wasi.wasiImport,
});
wasi.initialize(instance);<script type="module">
import { SwissEph } from "./swiss_eph.js";
const eph = new SwissEph(
await WebAssembly.compile(
await fetch("./swiss_eph.wasm").then((r) => r.arrayBuffer()),
),
);
</script>import { instantiate } from "./loader.js";
const eph = await instantiate(); // WASM is inlined as Base64import wasmModule from "./swiss_eph.wasm";
const eph = new SwissEph(wasmModule);import { instantiate } from "@fusionstrings/swiss-eph";
const eph = await instantiate(); // No external fetch, fits 1MB limit.Warning
Direct WebAssembly.instantiate of the WASI binary in a browser will fail
unless you provide a full wasi_snapshot_preview1 polyfill. We recommend
using our SwissEph class which handles these mocks automatically.
When using the Standard API, memory is automatically managed through our
WasmHeap. In Raw and Native styles, you must manually handle
malloc/free if passing strings or arrays to the Swiss Ephemeris.
SwissEph supports three internal models for astronomical calculations. You can
specify these using the iflag parameter in swe_calc_ut.
| Mode | Constant | Dependency | Performance | precision |
|---|---|---|---|---|
| Moshier | SEFLG_MOSEPH |
None | ~700k ops/s | High |
| Swiss Ephemeris | SEFLG_SWIEPH |
.se1 files |
~500k ops/s | Ultra |
| JPL Ephemeris | SEFLG_JPLEPH |
JPL files | ~600k ops/s | Industry |
The fastest and most portable mode. It uses a semi-analytical model that is built-in to the WASM binary. No external files are required.
const result = eph.swe_calc_ut(jd, Constants.SE_SUN, Constants.SEFLG_MOSEPH);The primary mode of this library. It provides maximum precision but requires
ephemeris data files (.se1) typically stored in an /ephe directory. If files
are missing, it silently falls back to Moshier mode.
eph.swe_set_ephe_path("/path/to/ephe");
const result = eph.swe_calc_ut(jd, Constants.SE_SUN, Constants.SEFLG_SWIEPH);Uses industry-standard JPL ephemeris files (DE431, DE405, etc.). Requires explicit file loading and does not fallback to Moshier if files are missing.