@neilberkman/sidereon 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Neil Berkman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # @neilberkman/sidereon
2
+
3
+ A WebAssembly / JavaScript interface over the [sidereon](https://github.com/neilberkman/sidereon)
4
+ GNSS + astrodynamics engine. It loads SP3 precise ephemerides, runs single-point
5
+ positioning (SPP), queries IONEX slant ionospheric delay, and propagates SGP4 /
6
+ TLE orbits with ground-station look angles. The numbers come straight from
7
+ `sidereon-core`; this package only marshals across the wasm boundary.
8
+
9
+ The binding calls the engine's serial paths only, so no thread pool is spawned
10
+ under wasm32.
11
+
12
+ ## Install / build
13
+
14
+ The published package ships the prebuilt wasm. To build from source:
15
+
16
+ ```sh
17
+ wasm-pack build --target web --out-dir pkg --out-name sidereon
18
+ wasm-pack build --target nodejs --out-dir pkg-node --out-name sidereon
19
+ ```
20
+
21
+ ## Usage (ESM, async init)
22
+
23
+ The `web` build follows the standard wasm-pack pattern: import the default
24
+ `init`, await it once, then call the API. In the browser `init()` fetches the
25
+ `.wasm` for you; in Node, hand it the bytes.
26
+
27
+ ```js
28
+ import init, { loadSp3, loadIonex, Tle, GroundStation } from "@neilberkman/sidereon";
29
+ import { readFile } from "node:fs/promises";
30
+
31
+ // Browser: await init(); Node: pass the wasm bytes.
32
+ await init({ module_or_path: await readFile(new URL("./pkg/sidereon_bg.wasm", import.meta.url)) });
33
+
34
+ const sp3 = loadSp3(new Uint8Array(await readFile("COD0MGXFIN.SP3")));
35
+ console.log(sp3.epochCount, sp3.satellites);
36
+
37
+ // Positions come back as Float64Array; epochs as plain numbers (seconds J2000).
38
+ const epochs = sp3.epochsJ2000Seconds();
39
+ const { positionM, clockS } = sp3.interpolate("G01", epochs.slice(0, 1));
40
+
41
+ // Single-point positioning. Pass one options object (see the SppRequest type).
42
+ const solution = sp3.solveSpp({
43
+ observations: [{ satelliteId: "G01", pseudorangeM: 22853110.4 }, /* ... */],
44
+ tRxJ2000S: 649728000,
45
+ tRxSecondOfDayS: 86400,
46
+ dayOfYear: 176,
47
+ corrections: { ionosphere: false, troposphere: false },
48
+ });
49
+ console.log(solution.positionM, solution.rxClockS, solution.usedSats);
50
+ ```
51
+
52
+ For CommonJS / synchronous Node, `require("@neilberkman/sidereon")` resolves to
53
+ the `nodejs` build, which loads the wasm at require time (no init step):
54
+
55
+ ```js
56
+ const { loadSp3 } = require("@neilberkman/sidereon");
57
+ const sp3 = loadSp3(require("fs").readFileSync("COD0MGXFIN.SP3"));
58
+ ```
59
+
60
+ ## IONEX slant delay
61
+
62
+ ```js
63
+ const ionex = loadIonex(new Uint8Array(await readFile("igsg.20i")));
64
+ const epochs = ionex.mapEpochsJ2000S; // Float64Array, seconds since J2000
65
+ // receiver lat/lon deg, satellite az/el deg, epoch, carrier Hz -> metres
66
+ const delayM = ionex.slantDelay(37.4, -122.1, 135, 30, epochs[0], 1575.42e6);
67
+ ```
68
+
69
+ ## SGP4 propagation and look angles
70
+
71
+ ```js
72
+ const tle = new Tle(line1, line2 /*, "improved" | "afspc" */);
73
+ const t0 = BigInt(Date.now()) * 1000n; // unix microseconds
74
+ const epochs = new BigInt64Array([t0, t0 + 600n * 1_000_000n]);
75
+
76
+ const { positionKm, velocityKmS } = tle.propagate(epochs); // TEME, flat [x,y,z,...]
77
+
78
+ const station = new GroundStation(37.7749, -122.4194 /*, altitudeM */);
79
+ const { azimuthDeg, elevationDeg, rangeKm } = tle.lookAngles(station, epochs);
80
+ ```
81
+
82
+ ## Errors
83
+
84
+ Engine failures (parse rejections, non-converging solves, SGP4 error codes)
85
+ throw a JS `Error` carrying the engine's own message. Bad input throws
86
+ `TypeError` (wrong shape or an unparseable satellite token) or `RangeError`
87
+ (non-finite or out-of-domain numbers). Nothing traps or panics across the
88
+ boundary.
89
+
90
+ ## Data conventions
91
+
92
+ - Positions and vectors cross as `Float64Array`. Multi-epoch arrays are flat,
93
+ row-major: `[x0, y0, z0, x1, y1, z1, ...]`, length `3 * epochCount`.
94
+ - Epochs are plain numbers (seconds since J2000) except SGP4 epoch grids, which
95
+ are `BigInt64Array` of unix microseconds.
96
+ - SPP positions are ECEF metres; geodetic output is `[latRad, lonRad, heightM]`.
97
+ - SGP4 states are TEME, kilometres and km/s.
98
+
99
+ ## Scope
100
+
101
+ Exposed: SP3 load/query, SPP solve, IONEX slant delay, SGP4 propagate /
102
+ look angles. Not yet exposed: RTK, PPP, RINEX OBS/NAV/clock, velocity, and the
103
+ broader astro event/conjunction surface. The rayon-parallel batch solves are
104
+ intentionally omitted (wasm32 is single-threaded; the serial paths produce the
105
+ same numbers).
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@neilberkman/sidereon",
3
+ "version": "0.8.0",
4
+ "description": "WebAssembly / JavaScript interface over the sidereon GNSS + astrodynamics engine: SP3 loading and multi-product merge, SPP / RTK (float + fixed) / PPP (float + fixed) positioning, IONEX slant delay, SGP4 and numerical orbit propagation, RINEX observation/navigation/clock parsing, CRINEX (Hatanaka) decoding, observable-domain math (carrier combinations, cycle slips, Hatch smoothing, weighting, velocity, GPS C/A signal), and the astro domain (scale-tagged time, frame transforms, Sun/Moon ephemerides, eclipse / body angles, DOP, passes / visibility, conjunction + collision probability, CDM / OMM / ANTEX parsing, RF link budget)",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./pkg/sidereon.d.ts",
10
+ "import": "./pkg/sidereon.js",
11
+ "require": "./pkg-node/sidereon.js"
12
+ },
13
+ "./types": "./types/sidereon-extra.d.ts"
14
+ },
15
+ "types": "./pkg/sidereon.d.ts",
16
+ "files": [
17
+ "pkg/sidereon.js",
18
+ "pkg/sidereon.d.ts",
19
+ "pkg/sidereon_bg.wasm",
20
+ "pkg/sidereon_bg.wasm.d.ts",
21
+ "pkg-node/sidereon.js",
22
+ "pkg-node/sidereon.d.ts",
23
+ "pkg-node/sidereon_bg.wasm",
24
+ "pkg-node/sidereon_bg.wasm.d.ts",
25
+ "types/sidereon-extra.d.ts",
26
+ "README.md"
27
+ ],
28
+ "scripts": {
29
+ "build": "wasm-pack build --target web --out-dir pkg --out-name sidereon && wasm-pack build --target nodejs --out-dir pkg-node --out-name sidereon",
30
+ "test": "node --test"
31
+ }
32
+ }