Skip to content

What it decodes

Coverage is driven by the feeds the forecast engine actually reads, not by the GRIB2 specification’s full surface. The package parses sections over raw GRIB2 bytes, including repeated sections 2–7 (multi-field messages) and section 6 bitmaps, and decodes the grid and packing templates below. Anything else is rejected with a named error, not approximated — for example, an unsupported packing template fails with the exact template number and the supported list.

Each grid carries an analytic inverse mapping, so nearest-gridpoint lookup is O(1) per point.

TemplateGridWhere it appears in the feeds
3.0Regular latitude-longitudeGFS 0.25°, GDPS 0.15°, GEPS 0.5°
3.1Rotated latitude-longitudeEvery ECCC HRDPS, RDPS, REPS, and RAQDPS field
3.30Lambert conformalHRRR CONUS 3 km, NAM 12 km and CONUS nest

nearestGridpoint reports the great-circle distance alongside the index, because callers use distance as the out-of-domain guard — it deliberately clamps and reports rather than throwing. src/grid.ts holds the inverses; src/nearest.ts the lookup.

TemplatePackingImplementation
5.0Simple packingPure TypeScript
5.2Complex packingPure TypeScript
5.3Complex packing with spatial differencingPure TypeScript
5.40JPEG 2000Through an injected decoder interface, so the codec dependency never enters this package’s core

The measured shape of the feeds (fixture findings): every harvested NOAA record (GFS, HRRR, NAM) uses DRT 5.3, and every ECCC Datamart product uses DRT 5.40. The JPEG 2000 seam and its Node wiring have their own page.

Rotated and Lambert grids store wind grid-relative (uvRelativeToGrid=1 on every ECCC rotated grid). src/wind.ts rotates grid-relative components to earth-relative, including the Lambert cone constant.

NOMADS publishes an .idx sidecar per GRIB file: one line per record, with byte offsets. src/idx.ts parses the sidecar and fetches single records by HTTP Range request, with fetch injected rather than ambient:

  • parseIdx / findRecord — parse the sidecar text and locate a record by its fields.
  • byteRange — the inclusive HTTP Range header value for a record, open-ended for the last record.
  • pairSpan — the combined span of a paired U/V record set.
  • fetchIndex — fetch and parse a sidecar (a plain, unranged GET).
  • fetchRecord — fetch one record’s bytes with a Range request.

One rule is load-bearing: a 200 response to a Range request is a failure, never a body to use. A 200 means the server ignored Range and sent the whole multi-hundred-megabyte file; only 206 Partial Content is success. fetchRecord enforces this and throws with the offending status.

The browser-safe barrel (@azohra/meteo.grib) contains no node: imports, no ambient I/O, and no WASM. Everything that needs a runtime — the JPEG 2000 codecs, the worker pool — lives behind the Node-only @azohra/meteo.grib/j2k-node subpath.