mirror of
https://github.com/acamarata/solar-spa.git
synced 2026-07-01 03:14:31 +00:00
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
58 lines
1.6 KiB
JavaScript
58 lines
1.6 KiB
JavaScript
'use strict';
|
|
|
|
const { spa, spaFormatted, formatTime, init, SPA_ZA, SPA_ALL } = require('./dist/index.cjs');
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
function assert(condition, message) {
|
|
if (condition) {
|
|
passed++;
|
|
} else {
|
|
failed++;
|
|
console.error(' FAIL: ' + message);
|
|
}
|
|
}
|
|
|
|
async function run() {
|
|
console.log('CJS smoke test\n');
|
|
|
|
// Verify all exports are available
|
|
assert(typeof spa === 'function', 'spa is a function');
|
|
assert(typeof spaFormatted === 'function', 'spaFormatted is a function');
|
|
assert(typeof formatTime === 'function', 'formatTime is a function');
|
|
assert(typeof init === 'function', 'init is a function');
|
|
assert(SPA_ZA === 0, 'SPA_ZA constant is 0');
|
|
assert(SPA_ALL === 3, 'SPA_ALL constant is 3');
|
|
|
|
// Core calculation
|
|
const result = await spa(
|
|
new Date(2023, 3, 1, 0, 0, 0),
|
|
40.7128, -74.006,
|
|
{ timezone: -4, elevation: 10 },
|
|
);
|
|
assert(result.error_code === 0, 'calculation succeeds');
|
|
assert(result.zenith > 0, 'zenith is positive');
|
|
assert(result.azimuth > 0, 'azimuth is positive');
|
|
assert(result.sunrise > 0, 'sunrise is positive');
|
|
|
|
// Formatted output
|
|
const fmt = await spaFormatted(
|
|
new Date(2023, 3, 1, 12, 0, 0),
|
|
40.7128, -74.006,
|
|
{ timezone: -4 },
|
|
);
|
|
assert(typeof fmt.sunrise === 'string', 'formatted sunrise is a string');
|
|
assert(/^\d{2}:\d{2}:\d{2}$/.test(fmt.sunrise), 'sunrise matches HH:MM:SS');
|
|
|
|
// formatTime
|
|
assert(formatTime(6.5) === '06:30:00', 'formatTime works');
|
|
|
|
console.log('\n' + passed + ' passed, ' + failed + ' failed');
|
|
if (failed > 0) process.exit(1);
|
|
}
|
|
|
|
run().catch((err) => {
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|