@chrtco/sdk 0.10.39 → 0.10.41

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/CHANGELOG.md CHANGED
@@ -4,6 +4,152 @@ All notable changes to `@chrtco/sdk` will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ### Added
8
+ - `MarineZoneRef.bbox` on `weather.marineForecast()` — `[west, south, east, north]` of the
9
+ forecast's zone, from the same build as the `NWS_MARINE_ZONES` tile source. A camera hint: fit
10
+ the map to it; draw the zone from the tiles, never the box. `west > east` crosses 180°.
11
+ - **`RELIEF_ENCODING` / `RELIEF_TILE_SIZE`** — `CHRT_RELIEF`'s raster-dem
12
+ `encoding` (`"terrarium"`) and tile size (512), the values `buildSources()`
13
+ emits for the relief source. Exported for consumers that describe that
14
+ source themselves, such as the tile-worker's TileJSON.
15
+
16
+ ### Fixed
17
+ - **The `CHRT_LAND` and `CHRT_RELIEF` sources carried no attribution.**
18
+ `generateStyle({ land: true })` emitted a `CHRT_LAND` source with no
19
+ `attribution`, so a map using MapLibre's attribution control showed no
20
+ credit for CHRTland — which is built from OpenStreetMap, whose ODbL requires
21
+ `© OpenStreetMap contributors` wherever the map is shown. The source now
22
+ carries `LAND_ATTRIBUTION`, and `CHRT_RELIEF` names its source, USGS 3DEP
23
+ (`RELIEF_ATTRIBUTION`; public domain, a courtesy). `CHRT_BASE` already
24
+ carried `BASE_ATTRIBUTION` and is unchanged; the chart source's credit is
25
+ still the tile-worker's to stamp. `RasterDemSource` gains the optional
26
+ `attribution` field `PmtilesVectorSource` already had.
27
+
28
+ ## [0.10.40]
29
+
30
+ The first publish since 0.10.39 (2026-09-11, from `ada7e73e`). The publish
31
+ workflow's typecheck failed on every merge to `main` from 2026-09-11 to
32
+ 2026-09-26 — the SDK's decode parity suite compiles the app's reference
33
+ decoder, which had begun importing `@chrtco/sdk` by name, and inside the
34
+ package that name resolved to a `dist/` not yet built — so everything below
35
+ reached `main` without reaching npm. No function signature is removed or
36
+ narrowed; the **Changed** entries are behaviour and type-shape changes to read
37
+ before upgrading.
38
+
39
+ ### Added
40
+ - **`weather.conditions({ hours })` — a station's recent history.** Adds
41
+ `series` to `MarineConditionsResponse`: the chosen station's readings over
42
+ the last `hours` hours (1–1080), oldest first, each in the top-level shape
43
+ (`MarineConditionsObservation`). Never interpolated or gap-filled;
44
+ `series.cadenceMinutes` gives the station's normal spacing. Without `hours`
45
+ the response is unchanged. New types: `MarineConditionsSeries`,
46
+ `MarineConditionsObservation`.
47
+ - **`StyleUrlOptions.units`** — `"metric"` (default) or `"imperial"`, sent by
48
+ `styleUrl()` / `fetchStyle()` as `?units=imperial` to
49
+ `GET /v1/styles/{region}/style.json`. The served style then prints
50
+ soundings, depth-contour labels, dredged-channel notes and bridge notes in
51
+ feet. Send the reader's setting here rather than converting soundings
52
+ client-side: a bridge note is composed text a client cannot rewrite, and
53
+ soundings in feet beside a clearance in metres is the disagreement this
54
+ prevents. Metric spells nothing, so existing style URLs and their cache
55
+ keys are unchanged; any other value is a typed 400 `invalid_units`.
56
+ - **`SIGSEQ` light rhythms.** `parseSigseqTerms(sigseq, sigper)` reads a
57
+ light's charted on/off sequence (`"00.4+(03.6)"` — 0.4 s lit, 3.6 s dark),
58
+ checked against `SIGPER`, and returns the phases or a typed refusal
59
+ (`SigseqRefusal`: `"malformed" | "nonPositiveDuration" | "sigperMismatch"`,
60
+ or `"absent"` when the light charts no sequence) — never an invented rhythm. `rhythmProperties()`, `lampRhythmOpacity()` and
61
+ `lampRhythmColour()` turn a parsed rhythm into feature properties and paint
62
+ expressions so a map can flash every light on the GPU from one paint update
63
+ per tick. Also `SIGSEQ_MAX_TERMS`, `SIGPER_TOLERANCE_SECONDS`,
64
+ `LAMP_TICK_MS`, `ParsedSigseqTerms`, `SigseqTerm`. The first-party app now
65
+ reads SIGSEQ through this parser: one grammar.
66
+ - **Night lamps.** `buildLampLayers(sourceId, ct)` returns two circle layers
67
+ on `LIGHTS` (`LAMP_GLOW_LAYER_ID` / `LAMP_CORE_LAYER_ID`, `LAMP_LAYER_IDS`)
68
+ that draw lighted aids as points of light: coloured by the same LIGHTS05
69
+ reading as the flare, sized by nominal range (`VALNMR`), viewport-aligned so
70
+ they neither grow nor lie flat under pitch. They carry only lights that are
71
+ steady from every bearing (no `SECTR1`, no `SIGSEQ`). Every generated style
72
+ now includes them **hidden** (`visibility: "none"`); show them with
73
+ `setLayoutProperty`.
74
+ - **The app-embeddable CHRT_BASE bundle.** `applyBaseBundle(style, { tiles })`
75
+ points a style's `CHRT_BASE` source at a local copy of the z0–6 world
76
+ basemap bundle and drops every base layer the bundle cannot feed. With
77
+ `BASE_BUNDLE_ID`, `BASE_BUNDLE_SCHEMA` (`chrt.basemap-bundle/1`),
78
+ `BASE_BUNDLE_MAXZOOM` (6), `BASE_BUNDLE_SOURCE_LAYERS`,
79
+ `BASE_BUNDLE_ATTRIBUTION` (`"© CHRT · Made with Natural Earth"`) and
80
+ `BASE_CLIENT_RASTER_BEFORE_ID`. The online `CHRT_BASE` source now declares
81
+ its credit (`BASE_ATTRIBUTION`, which also names OpenStreetMap for the
82
+ z9–11 inland-water tier) through the new optional
83
+ `PmtilesVectorSource.attribution`.
84
+ - **Terrain ordering helpers** — `drapedFirst()`, `drapeHalves()`,
85
+ `isDrapeable()`, `terrainStackCount()`, `DRAPEABLE_LAYER_TYPES`. See
86
+ *Generated styles are ordered draped-first* below.
87
+ - **Band aliases** — `BAND_CODE_ALIASES`, `cellBandCharacters()`,
88
+ `cellBandMatch()`. See the USACE fix below.
89
+
90
+ ### Changed
91
+ - **Generated styles are ordered draped-first.** The generator's last pass is
92
+ now a stable partition: every background, fill, line, raster and hillshade
93
+ layer in its existing order, then every symbol and circle layer in theirs.
94
+ With MapLibre terrain on, the interleaved order cut a z12+ chart into ~130
95
+ render stacks, each re-rendered every frame (24.6 fps → 52.6 fps measured at
96
+ pitch 45, MapLibre 5.24); draped-first is one stack. It applies to the flat
97
+ chart too — it is the S-52 display order (areas, lines, then point symbols
98
+ and text) — and the only pixels that move are where a symbol used to sit
99
+ under a later line or fill (0.1–2.8 % of pixels across six measured views).
100
+ If you insert your own layers into a generated style by `beforeId`, re-check
101
+ where they land.
102
+ - **Land mode: `LAKARE` relocates with the water family under CHRTland.**
103
+ Within a band the order is water → land → lake; across bands the finer
104
+ band's land paints after the coarser band's lake. A coarse band's
105
+ generalised lake no longer bleeds over CHRTland (Tisbury Great Pond at
106
+ z13.5).
107
+ - **The charted water/land repaint now sits beneath the CHRT_BASE
108
+ inland-water pair**, not above it. Its band-4/5/6 `LNDARE` clones have no
109
+ holes for ponds the chart does not chart, so above the pair they painted
110
+ every uncharted lake inside fine-band coverage as land.
111
+ - **`buildSectorArcsFC()` no longer draws the derived all-round arcs.**
112
+ `buildSectorsFromFeatures()` still emits them (`allRound: true`) — they are
113
+ what a reader in the uncovered arc sees, and a bearing lookup needs them —
114
+ but S-52 LIGHTS05 gives an all-round light its flare and no arc. This
115
+ reverses the drawing half of the 0.10.x entry *All-round lights co-located
116
+ with sector lights were not drawn*, below.
117
+ - **Sector arcs are coloured per S-52 LIGHTS05.** `SectorInfo` gains
118
+ `colourCodes` (every charted `COLOUR`, in order — an alternating sector has
119
+ two), `arcColourToken` / `arcColourHex` (`LITRD` / `LITGN` / `LITYW` — white,
120
+ yellow and orange all draw yellow — `CHMGD` where the colours do not
121
+ resolve, `CHBRN` when obscured), `obscured` (`LITVIS` 3, 7 or 8), and
122
+ `sigseq` / `sigper`. `buildSectorsFromFeatures(features, ct = "DAY")` takes
123
+ the palette `arcColourHex` is resolved in, and each arc feature from
124
+ `buildSectorArcsFC()` carries `arcColourHex`, `arcColourToken` and
125
+ `obscured`. **These fields are required**: code that builds `SectorInfo`
126
+ literals by hand must now supply them.
127
+ - **`buildFlashPattern()` uses the chart's own timing first.**
128
+ `DecodedNavAid` gains `sigseq`. When a light carries a valid `SIGSEQ` the
129
+ pattern is its charted phases and `FlashPattern.timing` is `"charted"`;
130
+ otherwise it is the previous animation of the character code, marked
131
+ `"invented"`. (Before, every pattern was invented — 400 ms flashes and
132
+ 300 ms gaps — though 74 % of charted lights carry their real sequence.)
133
+ `DecodedNavAid.sigseq` and `FlashPattern.timing` are required fields.
134
+
135
+ ### Fixed
136
+ - **USACE Inland ENC features were filtered out by every band-5 gate.** USACE
137
+ cell ids are `U37…`: the third character is `7` on every cell and means
138
+ nothing. The pipeline builds the product as band 5, but the style's band-5
139
+ gates read that character and never matched `7`, so the offline
140
+ `USACE_IENC` bundle rendered blank. `BAND_CODE_ALIASES = { "5": ["7"] }` is
141
+ folded into `bandFilterExpression()` and the orientation-label fan
142
+ (`cellBandMatch()`); a gate admits `7` exactly when it admits `5`. This is
143
+ not a seventh band — draw order and priorities are unchanged.
144
+
145
+ ## [0.10.0 – 0.10.39] — 2026-07-15 to 2026-09-11
146
+
147
+ Published by the publish workflow's auto-bump while `package.json` stayed at
148
+ 0.10.0, so no per-version sections were cut. The entries below are the
149
+ `[Unreleased]` section as it stood at `ada7e73e`, the commit 0.10.39 was
150
+ published from. For what a single version contains, run
151
+ `npm view @chrtco/sdk@<version> gitHead`.
152
+
7
153
  ### Fixed
8
154
  - **Sector-light arcs were drawn on the wrong side of the light.**
9
155
  `buildSectorArcGeoJSON()` / `buildSectorArcsFC()` painted each sector at the