@chrtco/sdk 0.10.3 → 0.10.4

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/README.md CHANGED
@@ -366,6 +366,9 @@ call any language can make. Everything marked **JS-only** runs in-process and ha
366
366
  | `chrt.cells.get(id)` | `GET /v1/cells/{id}` | |
367
367
  | `chrt.coverage.list(opts?)` | `GET /v1/coverage` | |
368
368
  | `chrt.coverage.forRoute(opts)` | `GET /v1/coverage/route` | which cells a passage needs |
369
+ | `chrt.weather.conditions(opts)` | `GET /v1/weather/conditions` | observed at sea (NDBC); needs `weather:read` |
370
+ | `chrt.weather.alerts(opts)` | `GET /v1/weather/marine-alerts` | active NWS warnings; needs `weather:read` |
371
+ | `chrt.weather.forecast(opts)` | `GET /v1/weather/marine-forecast` | NWS zone forecast; needs `weather:read` |
369
372
  | `chrt.warmTiles(region?)` | `POST /v1/mint/tile-token` | |
370
373
  | `chrt.styleUrl(opts?)` | `GET {tileBaseUrl}/v1/styles/{region}/style.json` | mints first |
371
374
  | `chrt.fetchStyle(opts?)` | same, then fetches it | |
@@ -618,3 +621,55 @@ try {
618
621
  ## License
619
622
 
620
623
  MIT
624
+
625
+ ## CHRTweather (marine weather)
626
+
627
+ NOAA-backed marine weather on the same client and the same key. **U.S. waters only**, and every
628
+ call needs the **`weather:read` scope** — a chart key does not carry it implicitly, so ask CHRT to
629
+ enable it. Without it you get `403 weather_not_entitled`, which retrying will never fix.
630
+
631
+ ```ts
632
+ // Observed — a measurement from the nearest buoy, NOT live.
633
+ const now = await chrt.weather.conditions({ lat: 41.0, lon: -71.1 });
634
+ console.log(now.observed.ageMinutes); // display this: median ~40 min old
635
+ console.log(now.conditions.windSpeed); // undefined => NOT REPORTED, not calm
636
+ console.log(now.unavailable); // what this station did not report
637
+
638
+ // Warnings — poll these cheaply (~60 s) without pulling a forecast.
639
+ const { alerts } = await chrt.weather.alerts({ lat: 42.5, lon: -70.3 });
640
+
641
+ // Forecast — the NWS zone narrative.
642
+ const fc = await chrt.weather.forecast({ zone: "LEZ166" });
643
+ for (const p of fc.periods) console.log(p.label, p.text);
644
+ ```
645
+
646
+ Three rules govern reading any of it. They are the difference between a useful readout and a
647
+ dangerous one.
648
+
649
+ **An empty result never means calm water.** No alerts in force, no buoy in range, no marine zone at
650
+ this position — each means *we do not know* or *nothing is posted*, never *conditions are good*.
651
+ There is deliberately no `safe` or `status` field to bind a green tick to. Render "no warnings in
652
+ force", never "conditions are good".
653
+
654
+ **Absent is not zero.** A measurement a station did not report, or a phrase the forecast parser
655
+ could not read, is omitted rather than defaulted — `conditions.windSpeed === undefined` means the
656
+ buoy sent NDBC's `MM` missing-value sentinel, and rendering that as `0 kn` puts a false calm on a
657
+ sailing display. `"winds less than 10 knots"` gives you `maxKn` and no `minKn` for the same reason.
658
+
659
+ **On the forecast, `text` is authoritative.** The structured `wind` / `seas` / `swell` fields are
660
+ parsed from NWS's own sentence, and where they disagree the text wins — some content exists only
661
+ there. Periods are NWS's own and are neither hourly nor uniform (`OVERNIGHT`, `TUE NIGHT`,
662
+ `WED NIGHT THROUGH THU NIGHT`); a single period can span days, so do not flatten them into an
663
+ hourly series.
664
+
665
+ Two field-level traps worth naming:
666
+
667
+ - **`expires` vs `ends`** on an alert. `expires` is when the *bulletin* lapses; `ends` is when the
668
+ *hazard* passes. Routinely hours apart. Describe the hazard with `ends`.
669
+ - **`seas.minFt`/`maxFt` vs `seas.occasionalFt`.** The range is the mean of the highest **1/3**;
670
+ `occasionalFt` (Great Lakes only) is the mean of the highest **1/10**. In *"Waves 2 to 4 ft …
671
+ occasionally to 8 ft"* the 8 ft wave is the one that knocks a small boat down — never average it
672
+ into the range.
673
+
674
+ CHRT is **not** the issuing authority. Every response carries `attribution` and `disclaimer`;
675
+ display them, and always consult NWS and VHF broadcasts.
package/dist/index.cjs CHANGED
@@ -96,6 +96,7 @@ __export(index_exports, {
96
96
  TileAuth: () => TileAuth,
97
97
  TileTokenError: () => TileTokenError,
98
98
  WATER_BODY_LAYER_GROUPS: () => WATER_BODY_LAYER_GROUPS,
99
+ WeatherEndpoint: () => WeatherEndpoint,
99
100
  applyChrtSymbolSet: () => applyChrtSymbolSet,
100
101
  applyColorTheme: () => applyColorTheme,
101
102
  applyCustomStyleSettings: () => applyCustomStyleSettings,
@@ -647,6 +648,79 @@ var CellsEndpoint = class {
647
648
  }
648
649
  };
649
650
 
651
+ // src/endpoints/weather.ts
652
+ var WeatherEndpoint = class {
653
+ constructor(http) {
654
+ this.http = http;
655
+ }
656
+ /**
657
+ * Observed conditions from the nearest reporting NOAA NDBC station.
658
+ *
659
+ * A **measurement, not a forecast**, and not live — most buoys report hourly
660
+ * and the median observation is around 40 minutes old. `observed.ageMinutes`
661
+ * is on every response and should be displayed: a readout that looks current
662
+ * but is 90 minutes stale is worse than one that says so.
663
+ *
664
+ * `unavailable` names every field the station did not report, so absence is
665
+ * stated rather than inferred from a missing key.
666
+ */
667
+ async conditions(options) {
668
+ return this.http.request(
669
+ "/weather/conditions",
670
+ {
671
+ lat: options.lat,
672
+ lon: options.lon,
673
+ units: options.units,
674
+ station: options.station
675
+ },
676
+ options.signal
677
+ );
678
+ }
679
+ /**
680
+ * Active NWS marine warnings for the zone — Small Craft Advisory, Gale,
681
+ * Storm, Hurricane Force Wind, Special Marine Warning. Most severe first.
682
+ *
683
+ * Its own call, so warnings can be re-checked cheaply (~60 s) without pulling
684
+ * a forecast you already have.
685
+ *
686
+ * **`expires` and `ends` are different.** `expires` is when the *bulletin*
687
+ * lapses — alerts are usually re-issued before then. `ends` is when the
688
+ * *hazard* is expected to be over. They are routinely hours apart, so
689
+ * describe the hazard with `ends` and use `expires` only to decide when to
690
+ * re-fetch.
691
+ *
692
+ * Display `instruction` verbatim: it is NWS's own advice to mariners.
693
+ */
694
+ async alerts(options) {
695
+ return this.http.request(
696
+ "/weather/marine-alerts",
697
+ { lat: options.lat, lon: options.lon, zone: options.zone },
698
+ options.signal
699
+ );
700
+ }
701
+ /**
702
+ * The NWS marine zone forecast — U.S. coastal and Great Lakes waters.
703
+ *
704
+ * Periods are NWS's own and are **neither hourly nor uniform**: `OVERNIGHT`,
705
+ * `TUE NIGHT`, `WED NIGHT THROUGH THU NIGHT`. A single period can span days.
706
+ * Flattening them into an hourly series invents resolution the data does not
707
+ * have.
708
+ *
709
+ * `expires` is the forecast's **own** stated validity, taken from the
710
+ * bulletin, not a TTL CHRT invented. `source.productId` identifies the
711
+ * upstream NWS product, so you can verify CHRT against NOAA directly.
712
+ *
713
+ * Offshore zones are not yet supported and fail with `501`.
714
+ */
715
+ async forecast(options) {
716
+ return this.http.request(
717
+ "/weather/marine-forecast",
718
+ { lat: options.lat, lon: options.lon, zone: options.zone },
719
+ options.signal
720
+ );
721
+ }
722
+ };
723
+
650
724
  // src/endpoints/coverage.ts
651
725
  var METRES_PER_NAUTICAL_MILE = 1852;
652
726
  var CoverageEndpoint = class {
@@ -28582,6 +28656,14 @@ var Chrt = class {
28582
28656
  cells;
28583
28657
  /** Coverage data — list available chart sources */
28584
28658
  coverage;
28659
+ /**
28660
+ * CHRTweather — NOAA-backed marine weather: observed conditions, active
28661
+ * warnings, and the NWS zone forecast. U.S. waters only, and requires the
28662
+ * `weather:read` scope on your key — a chart key does not carry it.
28663
+ *
28664
+ * An empty result from any of these never means calm water.
28665
+ */
28666
+ weather;
28585
28667
  /**
28586
28668
  * CHRToffline — download MBTiles bundles for offline use.
28587
28669
  * Requires `deviceId` in config. Manifest-based budget enforcement
@@ -28613,6 +28695,7 @@ var Chrt = class {
28613
28695
  this.tiles = new TilesEndpoint(this.http, this.tileAuth, tileOpts);
28614
28696
  this.cells = new CellsEndpoint(this.http);
28615
28697
  this.coverage = new CoverageEndpoint(this.http);
28698
+ this.weather = new WeatherEndpoint(this.http);
28616
28699
  this.featuresEp = new FeaturesEndpoint(this.http);
28617
28700
  this.queryEp = new QueryEndpoint(this.http);
28618
28701
  this.offline = new OfflineEndpoint(this.http, config.deviceId, config.manifestPath);
@@ -28949,6 +29032,7 @@ var Chrt = class {
28949
29032
  TileAuth,
28950
29033
  TileTokenError,
28951
29034
  WATER_BODY_LAYER_GROUPS,
29035
+ WeatherEndpoint,
28952
29036
  applyChrtSymbolSet,
28953
29037
  applyColorTheme,
28954
29038
  applyCustomStyleSettings,