Complete rewrite of the package from plain JavaScript to TypeScript, compiled to dual CJS/ESM via tsup. The NREL SPA C source is recompiled to WASM with Emscripten using SINGLE_FILE base64 inlining, eliminating bundler path-resolution issues. Changes: - Rewrite JS wrapper in TypeScript with full type definitions - Recompile WASM with -O3 -flto, 1MB fixed memory, no filesystem - Add input validation with descriptive error messages - Add spaFormatted() for HH:MM:SS time strings - Add formatTime() utility and init() for eager WASM loading - Add SPA_ZA, SPA_ZA_INC, SPA_ZA_RTS, SPA_ALL function code exports - Dual CJS/ESM output via tsup with proper exports map - Test suite: 68 ESM + 13 CJS assertions - 100-scenario validation suite across 7 categories - GitHub Wiki with 8 documentation pages - CI workflow: Node 20/22/24 matrix, typecheck, pack-check - NREL attribution in LICENSE and README per their license terms - Minimum Node.js 20
2.7 KiB
solar-spa
NREL Solar Position Algorithm compiled to WebAssembly. Calculates solar zenith, azimuth, incidence angle, sunrise, sunset, solar noon, and equation of time for any location and date.
The algorithm is the NREL SPA by Ibrahim Reda and Afshin Andreas, originally written in C. This package compiles the original C source to WASM via Emscripten and provides a TypeScript/JavaScript interface on top.
Why WASM?
The SPA involves thousands of floating-point operations per call: trigonometric series, Julian date conversions, nutation corrections, and iterative sunrise/sunset bracketing. WASM executes these at near-native speed, which matters when computing positions for thousands of locations or running tight animation loops.
For single calls, the difference is negligible. See Performance for benchmarks.
Pages
- API Reference: Full function signatures, option fields, and return types.
- Architecture: How the three layers (C, WASM, JS) fit together and why each design choice was made.
- Performance: Benchmarks, memory footprint, and optimization notes.
- NREL SPA Algorithm: Background on the algorithm itself, its accuracy, and valid date range.
- WebAssembly in npm Packages: Practical notes on shipping WASM in npm packages, common pitfalls, and how this package avoids them.
- Bundler Compatibility: Tested environments and configuration notes for Webpack, Vite, Next.js, and web workers.
- Validation and Benchmarks: Accuracy validation against NREL reference values and performance benchmarks.
- Contributing: How to build from source, run tests, and submit changes.
- Changelog: Version history and breaking changes.
Quick Start
import { spa } from 'solar-spa';
const result = await spa(
new Date(2025, 5, 21, 12, 0, 0), // June 21, 2025 at noon
40.7128, // latitude (NYC)
-74.0060, // longitude
{ timezone: -4, elevation: 10 } // EDT (UTC-4), 10m elevation
);
console.log(result.zenith); // ~27 (degrees from vertical)
console.log(result.azimuth); // ~179 (degrees from north)
console.log(result.sunrise); // ~5.4 (fractional hours)
console.log(result.sunset); // ~20.5 (fractional hours)
CommonJS works too:
const { spa } = require('solar-spa');
License
MIT