mostlyright 1.2.0 → 1.4.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../core/src/index.ts","../../core/src/data/generated/stations.ts","../../core/src/data/generated/source-priority.ts","../../core/src/data/generated/qc-alpha-rules.ts","../../core/src/exceptions/index.ts","../../core/src/snapshot.ts","../../core/src/stations/index.ts","../../core/src/internal/http.ts"],"sourcesContent":["// @mostlyrightmd/core — placeholder scaffold for TS-W0 Wave 1.\n// Real implementation (research, snapshot, mode2, transforms, qc, ...) lands in TS-W1+.\n\n/**\n * Placeholder version string from the TS-W0 Wave 1 scaffold. The\n * authoritative package version lives in `package.json#version`\n * (currently `0.1.0-rc.7`); this constant has not been bumped.\n */\nexport const version = \"0.0.0\";\n\n/**\n * Smoke-test export from the TS-W0 Wave 1 scaffold. Returns the literal\n * string `\"hello @mostlyrightmd/core\"`. Retained so the published package\n * has at least one importable runtime export until the scaffold is\n * removed in a later phase.\n */\nexport function helloCore(): string {\n return \"hello @mostlyrightmd/core\";\n}\n\n// Re-export generated types + data (NOT auto-generated; hand-maintained barrel).\n// The targets ARE auto-generated by @mostlyrightmd/codegen — see packages-ts/codegen.\nexport * from \"./schemas/generated/index.js\";\nexport * from \"./data/generated/index.js\";\n\n// TS-W1 Wave 1+5: structured exceptions + snapshot math.\nexport * from \"./exceptions/index.js\";\nexport * from \"./snapshot.js\";\n\n// Phase 22: venue-agnostic station catalog (mirrors Python `mostlyright.stations`).\nexport * from \"./stations/index.js\";\n\n// TS-W3 Plan 04 / 05 / 07: temporal primitives, formats, and validator.\n//\n// These surfaces are intentionally NOT re-exported from the main barrel —\n// they ship via dedicated subpath exports to keep `@mostlyrightmd/core`'s\n// main bundle under its 25 KB size-limit gate (TS-BUNDLE-01). Iter-4 H8\n// dropped the root re-exports after Codex caught the bundle at 25,725 B\n// (≈125 B over the gate) because TS-W3 piled temporal + formats + cache +\n// validator + new error classes onto the main entry.\n//\n// Use the subpath imports instead:\n// import { TimePoint, KnowledgeView, assertNoLeakage } from \"@mostlyrightmd/core/temporal\";\n// import { jsonDumps, csvDumps, toonDumps } from \"@mostlyrightmd/core/formats\";\n// import { validateRows } from \"@mostlyrightmd/core/validator\";\n// import type { ValidateOptions, ValidateResult } from \"@mostlyrightmd/core/validator\";\n\n// Internal modules — re-export selected helpers only. `internal/convert` and\n// `internal/bounds` stay deep imports for fetchers + parsers in later waves.\nexport { fetchWithRetry } from \"./internal/http.js\";\nexport type { FetchWithRetryOptions } from \"./internal/http.js\";\n","// AUTO-GENERATED by @mostlyrightmd/codegen from schemas/stations.json.\n// DO NOT EDIT — regenerate with: pnpm codegen\n// Last manifest SHA recorded in schemas/EXPORT_MANIFEST.json\n\nexport interface StationInfo {\n code: string | null;\n ghcnh_id: string | null;\n icao: string;\n name: string | null;\n tz: string;\n latitude: number | null;\n longitude: number | null;\n country: string | null;\n venues: ReadonlyArray<string>;\n}\n\nexport const STATIONS: ReadonlyArray<StationInfo> = [\n {\n code: \"EDDB\",\n country: \"DE\",\n ghcnh_id: null,\n icao: \"EDDB\",\n latitude: 52.3667,\n longitude: 13.5033,\n name: \"Berlin Brandenburg\",\n tz: \"Europe/Berlin\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EDDF\",\n country: \"DE\",\n ghcnh_id: null,\n icao: \"EDDF\",\n latitude: 50.0379,\n longitude: 8.5622,\n name: \"Frankfurt am Main\",\n tz: \"Europe/Berlin\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EDDM\",\n country: \"DE\",\n ghcnh_id: null,\n icao: \"EDDM\",\n latitude: 48.3538,\n longitude: 11.7861,\n name: \"Munich Franz Josef Strauss\",\n tz: \"Europe/Berlin\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EFHK\",\n country: \"FI\",\n ghcnh_id: null,\n icao: \"EFHK\",\n latitude: 60.3172,\n longitude: 24.9633,\n name: \"Helsinki-Vantaa\",\n tz: \"Europe/Helsinki\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EGKK\",\n country: \"GB\",\n ghcnh_id: null,\n icao: \"EGKK\",\n latitude: 51.1481,\n longitude: -0.1903,\n name: \"London Gatwick\",\n tz: \"Europe/London\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EGLL\",\n country: \"GB\",\n ghcnh_id: null,\n icao: \"EGLL\",\n latitude: 51.4706,\n longitude: -0.4619,\n name: \"London Heathrow\",\n tz: \"Europe/London\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EHAM\",\n country: \"NL\",\n ghcnh_id: null,\n icao: \"EHAM\",\n latitude: 52.3086,\n longitude: 4.7639,\n name: \"Amsterdam Schiphol\",\n tz: \"Europe/Amsterdam\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EKCH\",\n country: \"DK\",\n ghcnh_id: null,\n icao: \"EKCH\",\n latitude: 55.6181,\n longitude: 12.6561,\n name: \"Copenhagen Kastrup\",\n tz: \"Europe/Copenhagen\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"EPWA\",\n country: \"PL\",\n ghcnh_id: null,\n icao: \"EPWA\",\n latitude: 52.1657,\n longitude: 20.9671,\n name: \"Warsaw Chopin\",\n tz: \"Europe/Warsaw\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"ESSA\",\n country: \"SE\",\n ghcnh_id: null,\n icao: \"ESSA\",\n latitude: 59.6519,\n longitude: 17.9186,\n name: \"Stockholm Arlanda\",\n tz: \"Europe/Stockholm\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"ATL\",\n country: \"US\",\n ghcnh_id: \"USW00013874\",\n icao: \"KATL\",\n latitude: 33.6407,\n longitude: -84.4277,\n name: \"Hartsfield-Jackson Atlanta International\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"AUS\",\n country: \"US\",\n ghcnh_id: \"USW00013904\",\n icao: \"KAUS\",\n latitude: 30.1975,\n longitude: -97.6664,\n name: \"Austin-Bergstrom International\",\n tz: \"America/Chicago\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"BNA\",\n country: \"US\",\n ghcnh_id: \"USW00013897\",\n icao: \"KBNA\",\n latitude: 36.1245,\n longitude: -86.6782,\n name: \"Nashville International\",\n tz: \"America/Chicago\",\n venues: [\n \"kalshi\",\n ],\n },\n {\n code: \"BOS\",\n country: \"US\",\n ghcnh_id: \"USW00014739\",\n icao: \"KBOS\",\n latitude: 42.3656,\n longitude: -71.0096,\n name: \"Boston Logan International\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"CVG\",\n country: \"US\",\n ghcnh_id: \"USW00093814\",\n icao: \"KCVG\",\n latitude: 39.0488,\n longitude: -84.6678,\n name: \"Cincinnati/Northern Kentucky International\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n ],\n },\n {\n code: \"DCA\",\n country: \"US\",\n ghcnh_id: \"USW00013743\",\n icao: \"KDCA\",\n latitude: 38.8512,\n longitude: -77.0402,\n name: \"Washington Reagan National\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"DEN\",\n country: \"US\",\n ghcnh_id: \"USW00003017\",\n icao: \"KDEN\",\n latitude: 39.8561,\n longitude: -104.6737,\n name: \"Denver International\",\n tz: \"America/Denver\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"DFW\",\n country: \"US\",\n ghcnh_id: \"USW00003927\",\n icao: \"KDFW\",\n latitude: 32.8998,\n longitude: -97.0403,\n name: \"Dallas-Fort Worth International\",\n tz: \"America/Chicago\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"DTW\",\n country: \"US\",\n ghcnh_id: \"USW00094847\",\n icao: \"KDTW\",\n latitude: 42.2124,\n longitude: -83.3534,\n name: \"Detroit Metropolitan Wayne County\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"HOU\",\n country: \"US\",\n ghcnh_id: \"USW00012918\",\n icao: \"KHOU\",\n latitude: 29.6454,\n longitude: -95.2789,\n name: \"Houston Hobby\",\n tz: \"America/Chicago\",\n venues: [],\n },\n {\n code: \"IAH\",\n country: \"US\",\n ghcnh_id: \"USW00012960\",\n icao: \"KIAH\",\n latitude: 29.9844,\n longitude: -95.3414,\n name: \"Houston George Bush Intercontinental\",\n tz: \"America/Chicago\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"LAS\",\n country: \"US\",\n ghcnh_id: \"USW00023169\",\n icao: \"KLAS\",\n latitude: 36.084,\n longitude: -115.1537,\n name: \"Harry Reid (McCarran) International\",\n tz: \"America/Los_Angeles\",\n venues: [\n \"kalshi\",\n ],\n },\n {\n code: \"LAX\",\n country: \"US\",\n ghcnh_id: \"USW00023174\",\n icao: \"KLAX\",\n latitude: 33.9425,\n longitude: -118.4081,\n name: \"Los Angeles International\",\n tz: \"America/Los_Angeles\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"MDW\",\n country: \"US\",\n ghcnh_id: \"USW00014819\",\n icao: \"KMDW\",\n latitude: 41.7868,\n longitude: -87.7522,\n name: \"Chicago Midway International\",\n tz: \"America/Chicago\",\n venues: [\n \"kalshi\",\n ],\n },\n {\n code: \"MIA\",\n country: \"US\",\n ghcnh_id: \"USW00012839\",\n icao: \"KMIA\",\n latitude: 25.7959,\n longitude: -80.287,\n name: \"Miami International\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"MSP\",\n country: \"US\",\n ghcnh_id: \"USW00014922\",\n icao: \"KMSP\",\n latitude: 44.8848,\n longitude: -93.2223,\n name: \"Minneapolis-St Paul International\",\n tz: \"America/Chicago\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"MSY\",\n country: \"US\",\n ghcnh_id: \"USW00012916\",\n icao: \"KMSY\",\n latitude: 29.9934,\n longitude: -90.258,\n name: \"New Orleans Louis Armstrong International\",\n tz: \"America/Chicago\",\n venues: [],\n },\n {\n code: \"NYC\",\n country: \"US\",\n ghcnh_id: \"USW00094728\",\n icao: \"KNYC\",\n latitude: 40.7789,\n longitude: -73.9692,\n name: \"Central Park, New York\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n ],\n },\n {\n code: \"OKC\",\n country: \"US\",\n ghcnh_id: \"USW00013967\",\n icao: \"KOKC\",\n latitude: 35.3931,\n longitude: -97.6007,\n name: \"Oklahoma City Will Rogers World\",\n tz: \"America/Chicago\",\n venues: [],\n },\n {\n code: \"PHL\",\n country: \"US\",\n ghcnh_id: \"USW00013739\",\n icao: \"KPHL\",\n latitude: 39.8721,\n longitude: -75.2411,\n name: \"Philadelphia International\",\n tz: \"America/New_York\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"PHX\",\n country: \"US\",\n ghcnh_id: \"USW00023183\",\n icao: \"KPHX\",\n latitude: 33.4373,\n longitude: -112.0078,\n name: \"Phoenix Sky Harbor International\",\n tz: \"America/Phoenix\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"SAT\",\n country: \"US\",\n ghcnh_id: \"USW00012921\",\n icao: \"KSAT\",\n latitude: 29.5337,\n longitude: -98.4698,\n name: \"San Antonio International\",\n tz: \"America/Chicago\",\n venues: [],\n },\n {\n code: \"SEA\",\n country: \"US\",\n ghcnh_id: \"USW00024233\",\n icao: \"KSEA\",\n latitude: 47.4502,\n longitude: -122.3088,\n name: \"Seattle-Tacoma International\",\n tz: \"America/Los_Angeles\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"SFO\",\n country: \"US\",\n ghcnh_id: \"USW00023234\",\n icao: \"KSFO\",\n latitude: 37.6213,\n longitude: -122.379,\n name: \"San Francisco International\",\n tz: \"America/Los_Angeles\",\n venues: [\n \"kalshi\",\n \"polymarket\",\n ],\n },\n {\n code: \"SLC\",\n country: \"US\",\n ghcnh_id: \"USW00024127\",\n icao: \"KSLC\",\n latitude: 40.7884,\n longitude: -111.9778,\n name: \"Salt Lake City International\",\n tz: \"America/Denver\",\n venues: [\n \"kalshi\",\n ],\n },\n {\n code: \"LEBL\",\n country: \"ES\",\n ghcnh_id: null,\n icao: \"LEBL\",\n latitude: 41.2974,\n longitude: 2.0833,\n name: \"Barcelona El Prat\",\n tz: \"Europe/Madrid\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LEMD\",\n country: \"ES\",\n ghcnh_id: null,\n icao: \"LEMD\",\n latitude: 40.4719,\n longitude: -3.5626,\n name: \"Madrid Barajas\",\n tz: \"Europe/Madrid\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LFPB\",\n country: \"FR\",\n ghcnh_id: null,\n icao: \"LFPB\",\n latitude: 48.9694,\n longitude: 2.4414,\n name: \"Paris Le Bourget\",\n tz: \"Europe/Paris\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LFPG\",\n country: \"FR\",\n ghcnh_id: null,\n icao: \"LFPG\",\n latitude: 49.0097,\n longitude: 2.5479,\n name: \"Paris Charles de Gaulle\",\n tz: \"Europe/Paris\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LFPO\",\n country: \"FR\",\n ghcnh_id: null,\n icao: \"LFPO\",\n latitude: 48.7233,\n longitude: 2.3794,\n name: \"Paris Orly\",\n tz: \"Europe/Paris\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LIMC\",\n country: \"IT\",\n ghcnh_id: null,\n icao: \"LIMC\",\n latitude: 45.6306,\n longitude: 8.7281,\n name: \"Milan Malpensa\",\n tz: \"Europe/Rome\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LIRF\",\n country: \"IT\",\n ghcnh_id: null,\n icao: \"LIRF\",\n latitude: 41.8003,\n longitude: 12.2389,\n name: \"Rome Fiumicino\",\n tz: \"Europe/Rome\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LOWW\",\n country: \"AT\",\n ghcnh_id: null,\n icao: \"LOWW\",\n latitude: 48.1103,\n longitude: 16.5697,\n name: \"Vienna International\",\n tz: \"Europe/Vienna\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"LSZH\",\n country: \"CH\",\n ghcnh_id: null,\n icao: \"LSZH\",\n latitude: 47.4647,\n longitude: 8.5492,\n name: \"Zurich\",\n tz: \"Europe/Zurich\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"NZAA\",\n country: \"NZ\",\n ghcnh_id: null,\n icao: \"NZAA\",\n latitude: -37.0081,\n longitude: 174.7917,\n name: \"Auckland\",\n tz: \"Pacific/Auckland\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"NZWN\",\n country: \"NZ\",\n ghcnh_id: null,\n icao: \"NZWN\",\n latitude: -41.3272,\n longitude: 174.8053,\n name: \"Wellington\",\n tz: \"Pacific/Auckland\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"OERK\",\n country: \"SA\",\n ghcnh_id: null,\n icao: \"OERK\",\n latitude: 24.9576,\n longitude: 46.6988,\n name: \"Riyadh King Khalid International\",\n tz: \"Asia/Riyadh\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"OMDB\",\n country: \"AE\",\n ghcnh_id: null,\n icao: \"OMDB\",\n latitude: 25.2532,\n longitude: 55.3657,\n name: \"Dubai International\",\n tz: \"Asia/Dubai\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"OTHH\",\n country: \"QA\",\n ghcnh_id: null,\n icao: \"OTHH\",\n latitude: 25.2731,\n longitude: 51.608,\n name: \"Doha Hamad International\",\n tz: \"Asia/Qatar\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"RCTP\",\n country: \"TW\",\n ghcnh_id: null,\n icao: \"RCTP\",\n latitude: 25.0777,\n longitude: 121.2328,\n name: \"Taipei Taoyuan\",\n tz: \"Asia/Taipei\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"RJAA\",\n country: \"JP\",\n ghcnh_id: null,\n icao: \"RJAA\",\n latitude: 35.7647,\n longitude: 140.3864,\n name: \"Tokyo Narita\",\n tz: \"Asia/Tokyo\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"RJTT\",\n country: \"JP\",\n ghcnh_id: null,\n icao: \"RJTT\",\n latitude: 35.5522,\n longitude: 139.78,\n name: \"Tokyo Haneda\",\n tz: \"Asia/Tokyo\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"RKSI\",\n country: \"KR\",\n ghcnh_id: null,\n icao: \"RKSI\",\n latitude: 37.4691,\n longitude: 126.4505,\n name: \"Seoul Incheon\",\n tz: \"Asia/Seoul\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"SAEZ\",\n country: \"AR\",\n ghcnh_id: null,\n icao: \"SAEZ\",\n latitude: -34.8222,\n longitude: -58.5358,\n name: \"Buenos Aires Ezeiza\",\n tz: \"America/Argentina/Buenos_Aires\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"SBGR\",\n country: \"BR\",\n ghcnh_id: null,\n icao: \"SBGR\",\n latitude: -23.4356,\n longitude: -46.4731,\n name: \"São Paulo Guarulhos\",\n tz: \"America/Sao_Paulo\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"UUEE\",\n country: \"RU\",\n ghcnh_id: null,\n icao: \"UUEE\",\n latitude: 55.9728,\n longitude: 37.4147,\n name: \"Moscow Sheremetyevo\",\n tz: \"Europe/Moscow\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"VABB\",\n country: \"IN\",\n ghcnh_id: null,\n icao: \"VABB\",\n latitude: 19.0887,\n longitude: 72.8679,\n name: \"Mumbai Chhatrapati Shivaji\",\n tz: \"Asia/Kolkata\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"VHHH\",\n country: \"HK\",\n ghcnh_id: null,\n icao: \"VHHH\",\n latitude: 22.308,\n longitude: 113.9185,\n name: \"Hong Kong International\",\n tz: \"Asia/Hong_Kong\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"VIDP\",\n country: \"IN\",\n ghcnh_id: null,\n icao: \"VIDP\",\n latitude: 28.5562,\n longitude: 77.1,\n name: \"Delhi Indira Gandhi\",\n tz: \"Asia/Kolkata\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"VTBS\",\n country: \"TH\",\n ghcnh_id: null,\n icao: \"VTBS\",\n latitude: 13.69,\n longitude: 100.7501,\n name: \"Bangkok Suvarnabhumi\",\n tz: \"Asia/Bangkok\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"WSSS\",\n country: \"SG\",\n ghcnh_id: null,\n icao: \"WSSS\",\n latitude: 1.3644,\n longitude: 103.9915,\n name: \"Singapore Changi\",\n tz: \"Asia/Singapore\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"YBBN\",\n country: \"AU\",\n ghcnh_id: null,\n icao: \"YBBN\",\n latitude: -27.3842,\n longitude: 153.1175,\n name: \"Brisbane\",\n tz: \"Australia/Brisbane\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"YMML\",\n country: \"AU\",\n ghcnh_id: null,\n icao: \"YMML\",\n latitude: -37.6733,\n longitude: 144.8433,\n name: \"Melbourne Tullamarine\",\n tz: \"Australia/Melbourne\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"YSSY\",\n country: \"AU\",\n ghcnh_id: null,\n icao: \"YSSY\",\n latitude: -33.9461,\n longitude: 151.1772,\n name: \"Sydney Kingsford Smith\",\n tz: \"Australia/Sydney\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"ZBAA\",\n country: \"CN\",\n ghcnh_id: null,\n icao: \"ZBAA\",\n latitude: 40.0801,\n longitude: 116.5846,\n name: \"Beijing Capital\",\n tz: \"Asia/Shanghai\",\n venues: [\n \"polymarket\",\n ],\n },\n {\n code: \"ZSPD\",\n country: \"CN\",\n ghcnh_id: null,\n icao: \"ZSPD\",\n latitude: 31.1443,\n longitude: 121.8083,\n name: \"Shanghai Pudong\",\n tz: \"Asia/Shanghai\",\n venues: [\n \"polymarket\",\n ],\n },\n] as const;\n\nexport const STATION_BY_CODE: ReadonlyMap<string, StationInfo> = new Map<string, StationInfo>([\n [\"ATL\", STATIONS[10]!],\n [\"AUS\", STATIONS[11]!],\n [\"BNA\", STATIONS[12]!],\n [\"BOS\", STATIONS[13]!],\n [\"CVG\", STATIONS[14]!],\n [\"DCA\", STATIONS[15]!],\n [\"DEN\", STATIONS[16]!],\n [\"DFW\", STATIONS[17]!],\n [\"DTW\", STATIONS[18]!],\n [\"EDDB\", STATIONS[0]!],\n [\"EDDF\", STATIONS[1]!],\n [\"EDDM\", STATIONS[2]!],\n [\"EFHK\", STATIONS[3]!],\n [\"EGKK\", STATIONS[4]!],\n [\"EGLL\", STATIONS[5]!],\n [\"EHAM\", STATIONS[6]!],\n [\"EKCH\", STATIONS[7]!],\n [\"EPWA\", STATIONS[8]!],\n [\"ESSA\", STATIONS[9]!],\n [\"HOU\", STATIONS[19]!],\n [\"IAH\", STATIONS[20]!],\n [\"LAS\", STATIONS[21]!],\n [\"LAX\", STATIONS[22]!],\n [\"LEBL\", STATIONS[35]!],\n [\"LEMD\", STATIONS[36]!],\n [\"LFPB\", STATIONS[37]!],\n [\"LFPG\", STATIONS[38]!],\n [\"LFPO\", STATIONS[39]!],\n [\"LIMC\", STATIONS[40]!],\n [\"LIRF\", STATIONS[41]!],\n [\"LOWW\", STATIONS[42]!],\n [\"LSZH\", STATIONS[43]!],\n [\"MDW\", STATIONS[23]!],\n [\"MIA\", STATIONS[24]!],\n [\"MSP\", STATIONS[25]!],\n [\"MSY\", STATIONS[26]!],\n [\"NYC\", STATIONS[27]!],\n [\"NZAA\", STATIONS[44]!],\n [\"NZWN\", STATIONS[45]!],\n [\"OERK\", STATIONS[46]!],\n [\"OKC\", STATIONS[28]!],\n [\"OMDB\", STATIONS[47]!],\n [\"OTHH\", STATIONS[48]!],\n [\"PHL\", STATIONS[29]!],\n [\"PHX\", STATIONS[30]!],\n [\"RCTP\", STATIONS[49]!],\n [\"RJAA\", STATIONS[50]!],\n [\"RJTT\", STATIONS[51]!],\n [\"RKSI\", STATIONS[52]!],\n [\"SAEZ\", STATIONS[53]!],\n [\"SAT\", STATIONS[31]!],\n [\"SBGR\", STATIONS[54]!],\n [\"SEA\", STATIONS[32]!],\n [\"SFO\", STATIONS[33]!],\n [\"SLC\", STATIONS[34]!],\n [\"UUEE\", STATIONS[55]!],\n [\"VABB\", STATIONS[56]!],\n [\"VHHH\", STATIONS[57]!],\n [\"VIDP\", STATIONS[58]!],\n [\"VTBS\", STATIONS[59]!],\n [\"WSSS\", STATIONS[60]!],\n [\"YBBN\", STATIONS[61]!],\n [\"YMML\", STATIONS[62]!],\n [\"YSSY\", STATIONS[63]!],\n [\"ZBAA\", STATIONS[64]!],\n [\"ZSPD\", STATIONS[65]!],\n]);\n\nexport const STATION_BY_ICAO: ReadonlyMap<string, StationInfo> = new Map<string, StationInfo>([\n [\"EDDB\", STATIONS[0]!],\n [\"EDDF\", STATIONS[1]!],\n [\"EDDM\", STATIONS[2]!],\n [\"EFHK\", STATIONS[3]!],\n [\"EGKK\", STATIONS[4]!],\n [\"EGLL\", STATIONS[5]!],\n [\"EHAM\", STATIONS[6]!],\n [\"EKCH\", STATIONS[7]!],\n [\"EPWA\", STATIONS[8]!],\n [\"ESSA\", STATIONS[9]!],\n [\"KATL\", STATIONS[10]!],\n [\"KAUS\", STATIONS[11]!],\n [\"KBNA\", STATIONS[12]!],\n [\"KBOS\", STATIONS[13]!],\n [\"KCVG\", STATIONS[14]!],\n [\"KDCA\", STATIONS[15]!],\n [\"KDEN\", STATIONS[16]!],\n [\"KDFW\", STATIONS[17]!],\n [\"KDTW\", STATIONS[18]!],\n [\"KHOU\", STATIONS[19]!],\n [\"KIAH\", STATIONS[20]!],\n [\"KLAS\", STATIONS[21]!],\n [\"KLAX\", STATIONS[22]!],\n [\"KMDW\", STATIONS[23]!],\n [\"KMIA\", STATIONS[24]!],\n [\"KMSP\", STATIONS[25]!],\n [\"KMSY\", STATIONS[26]!],\n [\"KNYC\", STATIONS[27]!],\n [\"KOKC\", STATIONS[28]!],\n [\"KPHL\", STATIONS[29]!],\n [\"KPHX\", STATIONS[30]!],\n [\"KSAT\", STATIONS[31]!],\n [\"KSEA\", STATIONS[32]!],\n [\"KSFO\", STATIONS[33]!],\n [\"KSLC\", STATIONS[34]!],\n [\"LEBL\", STATIONS[35]!],\n [\"LEMD\", STATIONS[36]!],\n [\"LFPB\", STATIONS[37]!],\n [\"LFPG\", STATIONS[38]!],\n [\"LFPO\", STATIONS[39]!],\n [\"LIMC\", STATIONS[40]!],\n [\"LIRF\", STATIONS[41]!],\n [\"LOWW\", STATIONS[42]!],\n [\"LSZH\", STATIONS[43]!],\n [\"NZAA\", STATIONS[44]!],\n [\"NZWN\", STATIONS[45]!],\n [\"OERK\", STATIONS[46]!],\n [\"OMDB\", STATIONS[47]!],\n [\"OTHH\", STATIONS[48]!],\n [\"RCTP\", STATIONS[49]!],\n [\"RJAA\", STATIONS[50]!],\n [\"RJTT\", STATIONS[51]!],\n [\"RKSI\", STATIONS[52]!],\n [\"SAEZ\", STATIONS[53]!],\n [\"SBGR\", STATIONS[54]!],\n [\"UUEE\", STATIONS[55]!],\n [\"VABB\", STATIONS[56]!],\n [\"VHHH\", STATIONS[57]!],\n [\"VIDP\", STATIONS[58]!],\n [\"VTBS\", STATIONS[59]!],\n [\"WSSS\", STATIONS[60]!],\n [\"YBBN\", STATIONS[61]!],\n [\"YMML\", STATIONS[62]!],\n [\"YSSY\", STATIONS[63]!],\n [\"ZBAA\", STATIONS[64]!],\n [\"ZSPD\", STATIONS[65]!],\n]);\n","// AUTO-GENERATED by @mostlyrightmd/codegen from schemas/source-priority.json.\n// DO NOT EDIT — regenerate with: pnpm codegen\n// Last manifest SHA recorded in schemas/EXPORT_MANIFEST.json\n\nexport const OBSERVATION_SOURCE_PRIORITY: Readonly<Record<string, number>> = {\n awc: 3,\n ghcnh: 1,\n iem: 2,\n} as const;\n\nexport const CLIMATE_REPORT_TYPE_PRIORITY: Readonly<Record<string, number>> = {\n correction: 2,\n estimated: 0,\n final: 3,\n ncei_final: 2.5,\n preliminary: 1,\n} as const;\n\nexport const LIVE_V1_POLICY: {\n name: string;\n sourcePriority: Readonly<Record<string, number>>;\n secondaryKey: ReadonlyArray<string>;\n} = {\n name: \"LIVE_V1\",\n secondaryKey: [\n \"source_received_at\",\n \"ingestion_id\",\n ],\n sourcePriority: {\n awc: 3,\n ghcnh: 1,\n iem: 2,\n ncei: 0,\n },\n} as const;\n","// AUTO-GENERATED by @mostlyrightmd/codegen from schemas/qc-alpha-rules.json.\n// DO NOT EDIT — regenerate with: pnpm codegen\n// Last manifest SHA recorded in schemas/EXPORT_MANIFEST.json\n\nexport interface QcAlphaRule {\n rule_id: string;\n bit_position: number;\n description: string;\n field: string;\n}\n\nexport const QC_ALPHA_RULES: ReadonlyArray<QcAlphaRule> = [\n {\n bit_position: 0,\n description: \"Temperature outside [-89C, 57C] (world-record bounds).\",\n field: \"temp_c\",\n rule_id: \"temp_c.out_of_range\",\n },\n {\n bit_position: 1,\n description: \"Dewpoint greater than temperature (physically impossible).\",\n field: \"dew_point_c\",\n rule_id: \"dew_point_c.exceeds_temp\",\n },\n {\n bit_position: 2,\n description: \"Wind speed negative.\",\n field: \"wind_speed_ms\",\n rule_id: \"wind_speed_ms.negative\",\n },\n {\n bit_position: 3,\n description: \"Wind direction outside [0, 360].\",\n field: \"wind_dir_deg\",\n rule_id: \"wind_dir_deg.out_of_range\",\n },\n {\n bit_position: 4,\n description: \"Sea-level pressure outside [870, 1085] mb.\",\n field: \"slp_hpa\",\n rule_id: \"slp_hpa.out_of_range\",\n },\n] as const;\n\nexport const QC_ALPHA_RULES_BY_ID: ReadonlyMap<string, QcAlphaRule> = new Map<string, QcAlphaRule>([\n [\"temp_c.out_of_range\", QC_ALPHA_RULES[0]!],\n [\"dew_point_c.exceeds_temp\", QC_ALPHA_RULES[1]!],\n [\"wind_speed_ms.negative\", QC_ALPHA_RULES[2]!],\n [\"wind_dir_deg.out_of_range\", QC_ALPHA_RULES[3]!],\n [\"slp_hpa.out_of_range\", QC_ALPHA_RULES[4]!],\n]);\n","// Structured exception hierarchy for the mostlyright TS SDK.\n//\n// Mirrors the Python design in `packages/core/src/mostlyright/core/exceptions.py`\n// and `packages/core/src/mostlyright/_internal/exceptions.py`. Every error\n// subclasses `MostlyRightError` and exposes a `toDict()` method that returns a\n// JSON-safe payload suitable for MCP `error.data` / extension messaging.\n//\n// Role-name vocabulary for SourceMismatchError matches Python:\n// \"observations\" / \"forecasts\" / \"settlement\" (long form, NOT the col prefixes)\n\n// ---------------------------------------------------------------------------\n// JSON-safe coercion (mirrors `mostlyright.core._json_safe.to_json_safe`)\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively coerce `value` into a JSON-serializable structure.\n *\n * Coercion rules (mirrors Python's `to_json_safe`):\n * - `null` / `undefined` / `NaN` / `Infinity` / `-Infinity` → `null`\n * - `Date` → ISO 8601 UTC string ending in `Z`\n * - Numeric / boolean / string scalars pass through (non-finite numbers → null)\n * - Arrays + plain objects → recursive (cycles → `{ _cycle: true, value: String(obj) }`)\n * - Dict keys MUST be strings; non-string keys throw `TypeError`.\n * - Anything else (Symbol, function, class instance without `toJSON`) →\n * `{ _repr_only: true, value: String(value) }`.\n */\nexport function toJsonSafe(value: unknown, seen?: WeakSet<object>): unknown {\n const visited = seen ?? new WeakSet<object>();\n\n // null / undefined → null\n if (value === null || value === undefined) {\n return null;\n }\n\n // Booleans pass through.\n if (typeof value === \"boolean\") {\n return value;\n }\n\n // Strings pass through.\n if (typeof value === \"string\") {\n return value;\n }\n\n // Numbers — non-finite (NaN, +/-Infinity) coerce to null.\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? value : null;\n }\n\n // bigint → number when safe, else stringify (JSON can't natively encode bigint).\n if (typeof value === \"bigint\") {\n // Match Python: integers pass through as native numeric. Safe-range only.\n if (value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER)) {\n return Number(value);\n }\n return { _repr_only: true, value: value.toString() };\n }\n\n // Date → ISO 8601 UTC string (always ending in \"Z\").\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) {\n return null;\n }\n return value.toISOString();\n }\n\n // Arrays — recurse, track cycles.\n if (Array.isArray(value)) {\n if (visited.has(value)) {\n return { _cycle: true, value: String(value) };\n }\n visited.add(value);\n try {\n return value.map((item) => toJsonSafe(item, visited));\n } finally {\n visited.delete(value);\n }\n }\n\n // Plain objects — recurse, track cycles, enforce string keys.\n if (typeof value === \"object\") {\n if (visited.has(value as object)) {\n return { _cycle: true, value: String(value) };\n }\n visited.add(value as object);\n try {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n if (typeof key !== \"string\") {\n throw new TypeError(`toJsonSafe dict keys must be string; got ${typeof key}`);\n }\n out[key] = toJsonSafe((value as Record<string, unknown>)[key], visited);\n }\n return out;\n } finally {\n visited.delete(value as object);\n }\n }\n\n // Symbols, functions, etc. — repr-only marker.\n return { _repr_only: true, value: String(value) };\n}\n\n// ---------------------------------------------------------------------------\n// Base class\n// ---------------------------------------------------------------------------\n\nexport interface MostlyRightErrorOptions {\n errorCode?: string;\n source?: string | null;\n requestId?: string | null;\n}\n\n/**\n * Base class for all mostlyright structured errors.\n *\n * `errorCode` is a stable enum (e.g. \"SOURCE_UNAVAILABLE\") used by callers /\n * agents to branch on without parsing message text. `source` is the source id\n * involved (e.g. \"iem.archive\") when applicable, and `requestId` correlates a\n * JSON-RPC / MCP request id when applicable.\n */\nexport class MostlyRightError extends Error {\n /** Subclass override — the stable string enum surfaced via `errorCode`. */\n static defaultErrorCode = \"MOSTLYRIGHT_ERROR\";\n\n readonly errorCode: string;\n readonly source: string | null;\n readonly requestId: string | null;\n\n constructor(message = \"\", options: MostlyRightErrorOptions = {}) {\n super(message);\n this.name = new.target.name;\n const ctor = this.constructor as typeof MostlyRightError;\n this.errorCode = options.errorCode ?? ctor.defaultErrorCode;\n this.source = options.source ?? null;\n this.requestId = options.requestId ?? null;\n // Restore prototype chain after `Error` (needed for `instanceof` across\n // transpilation / ES5 targets).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * Subclass hook returning the structured attributes for `toDict`.\n * Values are passed through `toJsonSafe` by `toDict()`, so subclasses\n * don't need to coerce values themselves.\n */\n protected payload(): Record<string, unknown> {\n return {\n error_code: this.errorCode,\n message: this.message,\n source: this.source,\n request_id: this.requestId,\n };\n }\n\n /** Return a JSON-safe dict suitable for MCP `error.data`. */\n toDict(): Record<string, unknown> {\n const safe = toJsonSafe(this.payload());\n return safe as Record<string, unknown>;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SourceUnavailableError\n// ---------------------------------------------------------------------------\n\nexport interface SourceUnavailableErrorOptions extends MostlyRightErrorOptions {\n httpStatus?: number | null;\n retryable?: boolean;\n retryAfterS?: number | null;\n underlying?: string;\n url?: string | null;\n}\n\nexport class SourceUnavailableError extends MostlyRightError {\n static override defaultErrorCode = \"SOURCE_UNAVAILABLE\";\n\n readonly httpStatus: number | null;\n readonly retryable: boolean;\n readonly retryAfterS: number | null;\n readonly underlying: string;\n readonly url: string | null;\n\n constructor(message = \"\", options: SourceUnavailableErrorOptions = {}) {\n super(message, options);\n this.httpStatus = options.httpStatus ?? null;\n this.retryable = options.retryable ?? false;\n this.retryAfterS = options.retryAfterS ?? null;\n this.underlying = options.underlying ?? \"\";\n this.url = options.url ?? null;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n http_status: this.httpStatus,\n retryable: this.retryable,\n retry_after_s: this.retryAfterS,\n underlying: this.underlying,\n url: this.url,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// DataAvailabilityError (Phase 21 21-09)\n// ---------------------------------------------------------------------------\n//\n// Typed exception for \"I tried to fetch and got nothing usable\" — replaces\n// 3+ overloaded SourceUnavailableError sites where consumers had to parse\n// message strings to differentiate (rate-limit retry vs model-unavailable\n// hard-fail vs cache-miss re-fetch). The reason enum is shared lockstep\n// with Python (`mostlyright.core.exceptions.DataAvailabilityError`); drift\n// is the load-bearing risk.\n\n/** Shared reason enum — MUST match Python EXACTLY (Phase 21 D-04). */\nexport const DATA_AVAILABILITY_REASONS = [\n \"model_unavailable\",\n \"out_of_window\",\n \"cache_miss\",\n \"source_404\",\n \"source_5xx\",\n \"rate_limited\",\n] as const;\n\nexport type DataAvailabilityReason = (typeof DATA_AVAILABILITY_REASONS)[number];\n\nexport interface DataAvailabilityErrorOptions extends MostlyRightErrorOptions {\n reason: DataAvailabilityReason;\n hint: string;\n}\n\nexport class DataAvailabilityError extends MostlyRightError {\n static override defaultErrorCode = \"DATA_AVAILABILITY\";\n\n readonly reason: DataAvailabilityReason;\n readonly hint: string;\n\n constructor(options: DataAvailabilityErrorOptions) {\n if (!DATA_AVAILABILITY_REASONS.includes(options.reason)) {\n throw new RangeError(\n `DataAvailabilityError: unknown reason \"${String(options.reason)}\". ` +\n `Valid reasons: ${DATA_AVAILABILITY_REASONS.join(\", \")}`,\n );\n }\n if (typeof options.hint !== \"string\" || options.hint.length === 0) {\n throw new TypeError(\"DataAvailabilityError: hint is required and must be a non-empty string\");\n }\n const message = `[${options.reason}] ${options.hint}`;\n super(message, options);\n this.reason = options.reason;\n this.hint = options.hint;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n reason: this.reason,\n hint: this.hint,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// NwpNotAvailableError (Post-21-07 follow-up)\n// ---------------------------------------------------------------------------\n//\n// Subclass of DataAvailabilityError raised when the TS `forecastNwp()` stub\n// is called. Phase 21 21-07 routes the generic stub error through\n// DataAvailabilityError; this dedicated subclass adds:\n//\n// 1. instanceof-based dispatch — `catch (e) { if (e instanceof\n// NwpNotAvailableError) ... }` is cleaner than `e.reason ===\n// \"model_unavailable\" && e.source === \"nwp-stub\"`.\n// 2. IDE autocomplete on `.model` + `.station` — narrows the payload so\n// consumers don't have to parse `e.hint` to retrieve them.\n// 3. A typed compile-time signal: `forecastNwp()` returns\n// `Promise<never>`, but the throw site declares `@throws\n// NwpNotAvailableError` so JSDoc tooling surfaces the deferral up-front.\n//\n// Back-compat: NwpNotAvailableError IS-A DataAvailabilityError with\n// reason=\"model_unavailable\", so existing `catch (e) { if (e instanceof\n// DataAvailabilityError && e.reason === \"model_unavailable\") ... }` paths\n// continue to work unchanged.\n\nexport interface NwpNotAvailableErrorOptions extends MostlyRightErrorOptions {\n /** Station the caller asked for (echoed back for log/error attribution). */\n station: string;\n /** NWP model the caller asked for (e.g. `\"gfs\"`, `\"hrrr\"`). */\n model: string;\n /** Operator-actionable hint. Required (matches DataAvailabilityError contract). */\n hint: string;\n}\n\n/**\n * Raised when the TS `forecastNwp()` stub is called.\n *\n * **Why this exists:** no production-ready browser GRIB2 decoder ships in\n * v1.x (eccodes / cfgrib are C/Python only; WASM compile-time + bundle\n * size make a browser port impractical today). The function signature is\n * stable so callers can write code today; v2.0+ lands the execution body.\n *\n * **Recommended catch pattern:**\n *\n * ```ts\n * import { forecastNwp } from '@mostlyrightmd/weather';\n * import { NwpNotAvailableError } from '@mostlyrightmd/core';\n *\n * try {\n * const grid = await forecastNwp('KNYC', 'gfs');\n * } catch (e) {\n * if (e instanceof NwpNotAvailableError) {\n * console.warn(`NWP deferred to v2.0+; ${e.hint}`);\n * // Fall back to iemMosForecasts() when available, else Python SDK.\n * } else {\n * throw e;\n * }\n * }\n * ```\n *\n * See [docs/nwp-forecasts.md](https://mostlyright.md/docs/sdk/typescript/nwp-forecasts/)\n * for the full architectural rationale and the v2.0+ roadmap.\n */\nexport class NwpNotAvailableError extends DataAvailabilityError {\n static override defaultErrorCode = \"NWP_NOT_AVAILABLE\";\n\n readonly station: string;\n readonly model: string;\n\n constructor(options: NwpNotAvailableErrorOptions) {\n // exactOptionalPropertyTypes: true — only include requestId when the\n // caller passed a non-undefined value. Passing `requestId: undefined`\n // explicitly would type-error against the parent's narrower contract.\n const parentOpts: DataAvailabilityErrorOptions = {\n reason: \"model_unavailable\",\n hint: options.hint,\n source: options.source ?? `nwp.${options.model}`,\n };\n if (options.requestId !== undefined && options.requestId !== null) {\n parentOpts.requestId = options.requestId;\n }\n super(parentOpts);\n this.station = options.station;\n this.model = options.model;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n station: this.station,\n model: this.model,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// SchemaValidationError\n// ---------------------------------------------------------------------------\n\nexport interface SchemaValidationErrorOptions extends MostlyRightErrorOptions {\n schemaId: string;\n violations?: Array<Record<string, unknown>>;\n quarantineCount?: number;\n sampleViolations?: Array<Record<string, unknown>>;\n}\n\nexport class SchemaValidationError extends MostlyRightError {\n static override defaultErrorCode = \"SCHEMA_VALIDATION_FAILED\";\n\n readonly schemaId: string;\n readonly violations: Array<Record<string, unknown>>;\n readonly quarantineCount: number;\n readonly sampleViolations: Array<Record<string, unknown>>;\n\n constructor(message: string, options: SchemaValidationErrorOptions) {\n super(message, options);\n this.schemaId = options.schemaId;\n this.violations = [...(options.violations ?? [])];\n this.quarantineCount = options.quarantineCount ?? 0;\n this.sampleViolations = [...(options.sampleViolations ?? [])];\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n schema_id: this.schemaId,\n violations: this.violations,\n quarantine_count: this.quarantineCount,\n sample_violations: this.sampleViolations,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// SourceMismatchError\n// ---------------------------------------------------------------------------\n\nexport type SourceMismatchRole = \"observations\" | \"forecasts\" | \"settlement\";\n\nexport interface SourceMismatchErrorOptions extends MostlyRightErrorOptions {\n schemaSource: string;\n dataSource: string;\n role?: SourceMismatchRole | null;\n catalogWarning?: string | null;\n}\n\nexport class SourceMismatchError extends MostlyRightError {\n static override defaultErrorCode = \"SOURCE_MISMATCH\";\n\n /** Canonical role-name vocabulary (design.md §R). */\n static readonly VALID_ROLES: ReadonlySet<SourceMismatchRole> = new Set([\n \"observations\",\n \"forecasts\",\n \"settlement\",\n ]);\n\n readonly schemaSource: string;\n readonly dataSource: string;\n readonly role: SourceMismatchRole | null;\n readonly catalogWarning: string | null;\n\n constructor(message: string, options: SourceMismatchErrorOptions) {\n super(message, options);\n this.schemaSource = options.schemaSource;\n this.dataSource = options.dataSource;\n this.role = options.role ?? null;\n this.catalogWarning = options.catalogWarning ?? null;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n schema_source: this.schemaSource,\n data_source: this.dataSource,\n role: this.role,\n catalog_warning: this.catalogWarning,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// LeakageError\n// ---------------------------------------------------------------------------\n\nexport interface LeakageErrorOptions extends MostlyRightErrorOptions {\n asOf: string;\n violatingCount: number;\n sampleViolations?: Array<Record<string, unknown>>;\n}\n\nexport class LeakageError extends MostlyRightError {\n static override defaultErrorCode = \"LEAKAGE_DETECTED\";\n\n readonly asOf: string;\n readonly violatingCount: number;\n readonly sampleViolations: Array<Record<string, unknown>>;\n\n constructor(message: string, options: LeakageErrorOptions) {\n super(message, options);\n this.asOf = options.asOf;\n this.violatingCount = options.violatingCount;\n this.sampleViolations = [...(options.sampleViolations ?? [])];\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n as_of: this.asOf,\n violating_count: this.violatingCount,\n sample_violations: this.sampleViolations,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// IssuedAtMissingError (Phase 20 OM-04)\n// ---------------------------------------------------------------------------\n\nexport interface IssuedAtMissingErrorOptions extends MostlyRightErrorOptions {\n violatingCount?: number;\n sampleViolations?: Array<Record<string, unknown>>;\n}\n\n/**\n * A forecast row would land with `issuedAt = null`.\n *\n * Phase 20 OM-04. Origin: Tarabcak/mostlyright#70 — the legacy\n * seamless-feed bug where `/forecast_series` proxied Open-Meteo's\n * seamless endpoint without preserving `issued_at`, silently using\n * post-snapshot model runs in training data.\n */\nexport class IssuedAtMissingError extends SchemaValidationError {\n static override defaultErrorCode = \"ISSUED_AT_MISSING\";\n\n readonly violatingCountRows: number;\n\n constructor(message: string, options: IssuedAtMissingErrorOptions = {}) {\n super(message, {\n ...options,\n schemaId: \"schema.forecast.station.v1\",\n violations: [{ column: \"issued_at\", rule: \"non_null\" }],\n });\n this.violatingCountRows = options.violatingCount ?? 0;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n name: \"IssuedAtMissingError\",\n violating_count: this.violatingCountRows,\n origin_issue: \"Tarabcak/mostlyright#70\",\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// OpenMeteoSeamlessLeakageError (Phase 20 OM-04)\n// ---------------------------------------------------------------------------\n\nexport interface OpenMeteoSeamlessLeakageErrorOptions extends MostlyRightErrorOptions {\n model: string;\n endpointUrl: string;\n asOf?: string | null;\n}\n\n/**\n * The Open-Meteo Historical Forecast (seamless) endpoint was used\n * without `allowLeakage: true`.\n *\n * Phase 20 D-01 (locked decision): the seamless endpoint silently\n * stitches forecasts from multiple model cycles into a continuous\n * timeseries; the cycle that produced each value is unrecoverable from\n * the response. `LeakageDetector` rejects rows tagged\n * `source=\"open_meteo.seamless\"` whenever `as_of` is asserted.\n *\n * Origin: Tarabcak/mostlyright#70.\n */\nexport class OpenMeteoSeamlessLeakageError extends LeakageError {\n static override defaultErrorCode = \"OPEN_METEO_SEAMLESS_LEAKAGE\";\n\n readonly model: string;\n readonly endpointUrl: string;\n\n constructor(message: string, options: OpenMeteoSeamlessLeakageErrorOptions) {\n super(message, {\n ...options,\n asOf: options.asOf ?? \"(seamless-endpoint-refused-before-fetch)\",\n violatingCount: 0,\n });\n this.model = options.model;\n this.endpointUrl = options.endpointUrl;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n name: \"OpenMeteoSeamlessLeakageError\",\n model: this.model,\n endpoint_url: this.endpointUrl,\n origin_issue: \"Tarabcak/mostlyright#70\",\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// TemporalDriftError\n// ---------------------------------------------------------------------------\n\nexport interface TemporalDriftErrorOptions extends MostlyRightErrorOptions {\n schemaId: string;\n assertedRange: [string, string];\n violatingRows: number;\n sampleViolations?: Array<Record<string, unknown>>;\n}\n\nexport class TemporalDriftError extends MostlyRightError {\n static override defaultErrorCode = \"TEMPORAL_DRIFT\";\n\n readonly schemaId: string;\n readonly assertedRange: [string, string];\n readonly violatingRows: number;\n readonly sampleViolations: Array<Record<string, unknown>>;\n\n constructor(message: string, options: TemporalDriftErrorOptions) {\n super(message, options);\n this.schemaId = options.schemaId;\n this.assertedRange = [options.assertedRange[0], options.assertedRange[1]];\n this.violatingRows = options.violatingRows;\n this.sampleViolations = [...(options.sampleViolations ?? [])];\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n schema_id: this.schemaId,\n asserted_range: [this.assertedRange[0], this.assertedRange[1]],\n violating_rows: this.violatingRows,\n sample_violations: this.sampleViolations,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// PayloadTooLargeError\n// ---------------------------------------------------------------------------\n\nexport interface PayloadTooLargeErrorOptions extends MostlyRightErrorOptions {\n declaredSize: number;\n limit: number;\n acceptedModes?: string[];\n}\n\nexport class PayloadTooLargeError extends MostlyRightError {\n static override defaultErrorCode = \"PAYLOAD_TOO_LARGE\";\n\n readonly declaredSize: number;\n readonly limit: number;\n readonly acceptedModes: string[];\n\n constructor(message: string, options: PayloadTooLargeErrorOptions) {\n super(message, options);\n this.declaredSize = options.declaredSize;\n this.limit = options.limit;\n this.acceptedModes = [...(options.acceptedModes ?? [])];\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n declared_size: this.declaredSize,\n limit: this.limit,\n accepted_modes: this.acceptedModes,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// DeferredMarketError (TS-W6 placeholder; mirrors mostlyright.international)\n// ---------------------------------------------------------------------------\n\nexport class DeferredMarketError extends MostlyRightError {\n static override defaultErrorCode = \"DEFERRED_MARKET\";\n}\n\n// ---------------------------------------------------------------------------\n// PolymarketEventError (TS-W5 placeholder; mirrors mostlyright.markets.polymarket)\n// ---------------------------------------------------------------------------\n\nexport class PolymarketEventError extends MostlyRightError {\n static override defaultErrorCode = \"POLYMARKET_EVENT_INVALID\";\n}\n\n// ---------------------------------------------------------------------------\n// HTTP-layer hierarchy (mirrors mostlyright._internal.exceptions)\n// ---------------------------------------------------------------------------\n\nexport interface TherminalErrorOptions extends MostlyRightErrorOptions {\n statusCode?: number | null;\n retryAfter?: number | null;\n}\n\n/**\n * Base HTTP-layer marker. Subclass of `MostlyRightError` so callers that\n * catch `MostlyRightError` also catch transport errors.\n */\nexport class TherminalError extends MostlyRightError {\n static override defaultErrorCode = \"HTTP_ERROR\";\n\n readonly statusCode: number | null;\n\n constructor(message: string, options: TherminalErrorOptions = {}) {\n super(message, options);\n this.statusCode = options.statusCode ?? null;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n status_code: this.statusCode,\n };\n }\n}\n\nexport class NotFoundError extends TherminalError {\n static override defaultErrorCode = \"HTTP_NOT_FOUND\";\n\n constructor(message = \"Resource not found\", options: TherminalErrorOptions = {}) {\n super(message, { ...options, statusCode: options.statusCode ?? 404 });\n }\n}\n\nexport interface RateLimitErrorOptions extends TherminalErrorOptions {\n retryAfter?: number | null;\n}\n\nexport class RateLimitError extends TherminalError {\n static override defaultErrorCode = \"HTTP_RATE_LIMITED\";\n\n readonly retryAfter: number | null;\n\n constructor(retryAfter: number | null = 1, options: RateLimitErrorOptions = {}) {\n const msg = `Rate limit exceeded. Retry after ${retryAfter ?? \"?\"}s`;\n super(msg, { ...options, statusCode: options.statusCode ?? 429 });\n this.retryAfter = retryAfter;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n retry_after: this.retryAfter,\n };\n }\n}\n\nexport class ValidationError extends TherminalError {\n static override defaultErrorCode = \"HTTP_BAD_REQUEST\";\n\n constructor(message = \"Invalid request\", options: TherminalErrorOptions = {}) {\n super(message, { ...options, statusCode: options.statusCode ?? 400 });\n }\n}\n\nexport class AuthenticationError extends TherminalError {\n static override defaultErrorCode = \"HTTP_UNAUTHORIZED\";\n\n constructor(message = \"Authentication required\", options: TherminalErrorOptions = {}) {\n super(message, { ...options, statusCode: options.statusCode ?? 401 });\n }\n}\n\nexport class ForbiddenError extends TherminalError {\n static override defaultErrorCode = \"HTTP_FORBIDDEN\";\n\n constructor(message = \"Access denied\", options: TherminalErrorOptions = {}) {\n super(message, { ...options, statusCode: options.statusCode ?? 403 });\n }\n}\n\nexport class ServerError extends TherminalError {\n static override defaultErrorCode = \"HTTP_SERVER_ERROR\";\n\n constructor(message = \"Server error\", options: TherminalErrorOptions = {}) {\n super(message, { ...options, statusCode: options.statusCode ?? 500 });\n }\n}\n\n// ---------------------------------------------------------------------------\n// LiveStreamError + NoLiveDataError (Phase 11)\n// ---------------------------------------------------------------------------\n\n/**\n * Base class for `mostlyright.live.stream` / `live.latest` failures.\n *\n * Mirrors Python `LiveStreamError`. Live-streaming errors are a separate\n * sub-tree from `SourceUnavailableError` because the recovery path differs —\n * `stream()` swallows empty-tick errors and waits for the next polite-floor\n * cycle. Only `latest()` raises `NoLiveDataError` on empty responses.\n */\nexport class LiveStreamError extends MostlyRightError {\n static override defaultErrorCode = \"LIVE_STREAM_ERROR\";\n}\n\nexport interface NoLiveDataErrorOptions extends MostlyRightErrorOptions {\n station: string;\n source: string;\n}\n\n/**\n * `mostlyright.live.latest` returned no observations for the station.\n *\n * Carries the resolved ICAO `station` and the canonical source identity\n * tag (`\"awc.live\"` / `\"iem.live\"`) so caller logs can branch by source\n * without re-parsing the message.\n */\nexport class NoLiveDataError extends LiveStreamError {\n static override defaultErrorCode = \"NO_LIVE_DATA\";\n\n readonly station: string;\n\n constructor(message: string, options: NoLiveDataErrorOptions) {\n super(message, { ...options, source: options.source });\n this.station = options.station;\n }\n\n protected override payload(): Record<string, unknown> {\n return {\n ...super.payload(),\n station: this.station,\n };\n }\n}\n","// Snapshot math — settlement-window and market-close arithmetic.\n//\n// Ported from `packages/core/src/mostlyright/snapshot.py` and\n// `packages/core/src/mostlyright/_internal/_pairs.py:market_close_utc`.\n//\n// Key concepts:\n// - LOCAL STANDARD TIME (LST): station's standard UTC offset, DST ignored.\n// Kalshi NHIGH/NLOW contracts define the settlement window in LST.\n// - Settlement window: midnight-midnight LST for a given date.\n// During US daylight saving the clock window is 1:00 AM–1:00 AM next day\n// (EDT), but the UTC bounds are the same year-round.\n// - CLI publication delay: NWS issues the overnight final CLI ~04:00–10:00\n// UTC the day after observation. Default: 10 h after midnight LST.\n\n// ---------------------------------------------------------------------------\n// Station → IANA timezone database\n// ---------------------------------------------------------------------------\n//\n// Used to extract the LOCAL STANDARD TIME UTC offset via a January reference\n// moment. Ported from `mostlyright.snapshot._STATION_TZ`.\n\nexport const _STATION_TZ: Readonly<Record<string, string>> = Object.freeze({\n // Eastern (UTC-5 standard / UTC-4 DST)\n NYC: \"America/New_York\",\n JFK: \"America/New_York\",\n LGA: \"America/New_York\",\n EWR: \"America/New_York\",\n ATL: \"America/New_York\",\n BOS: \"America/New_York\",\n PHL: \"America/New_York\",\n DCA: \"America/New_York\",\n IAD: \"America/New_York\",\n BWI: \"America/New_York\",\n MIA: \"America/New_York\",\n MCO: \"America/New_York\",\n TPA: \"America/New_York\",\n CLT: \"America/New_York\",\n RDU: \"America/New_York\",\n CLE: \"America/New_York\",\n PIT: \"America/New_York\",\n BUF: \"America/New_York\",\n DTW: \"America/Detroit\",\n IND: \"America/Indiana/Indianapolis\",\n CVG: \"America/New_York\",\n CMH: \"America/New_York\",\n SYR: \"America/New_York\",\n ALB: \"America/New_York\",\n BTV: \"America/New_York\",\n ORF: \"America/New_York\",\n RIC: \"America/New_York\",\n GSO: \"America/New_York\",\n CHS: \"America/New_York\",\n SAV: \"America/New_York\",\n JAX: \"America/New_York\",\n RSW: \"America/New_York\",\n PBI: \"America/New_York\",\n FLL: \"America/New_York\",\n // Central (UTC-6 standard / UTC-5 DST)\n ORD: \"America/Chicago\",\n MDW: \"America/Chicago\",\n DFW: \"America/Chicago\",\n DAL: \"America/Chicago\",\n IAH: \"America/Chicago\",\n HOU: \"America/Chicago\",\n MSP: \"America/Chicago\",\n STL: \"America/Chicago\",\n MCI: \"America/Chicago\",\n OMA: \"America/Chicago\",\n MKE: \"America/Chicago\",\n MSY: \"America/Chicago\",\n MEM: \"America/Chicago\",\n BNA: \"America/Chicago\",\n OKC: \"America/Chicago\",\n SAT: \"America/Chicago\",\n AUS: \"America/Chicago\",\n DSM: \"America/Chicago\",\n TUL: \"America/Chicago\",\n LIT: \"America/Chicago\",\n BIR: \"America/Chicago\",\n SDF: \"America/Chicago\",\n HSV: \"America/Chicago\",\n BHM: \"America/Chicago\",\n MOB: \"America/Chicago\",\n BTR: \"America/Chicago\",\n SHV: \"America/Chicago\",\n // Mountain (UTC-7 standard / UTC-6 DST)\n DEN: \"America/Denver\",\n SLC: \"America/Denver\",\n ABQ: \"America/Denver\",\n BOI: \"America/Boise\",\n BZN: \"America/Denver\",\n GJT: \"America/Denver\",\n // Arizona: no DST (UTC-7 always)\n PHX: \"America/Phoenix\",\n TUS: \"America/Phoenix\",\n // Pacific (UTC-8 standard / UTC-7 DST)\n LAX: \"America/Los_Angeles\",\n SFO: \"America/Los_Angeles\",\n SEA: \"America/Los_Angeles\",\n PDX: \"America/Los_Angeles\",\n LAS: \"America/Los_Angeles\",\n SAN: \"America/Los_Angeles\",\n OAK: \"America/Los_Angeles\",\n SJC: \"America/Los_Angeles\",\n SMF: \"America/Los_Angeles\",\n RNO: \"America/Los_Angeles\",\n FAT: \"America/Los_Angeles\",\n SNA: \"America/Los_Angeles\",\n ONT: \"America/Los_Angeles\",\n BUR: \"America/Los_Angeles\",\n // Alaska (UTC-9 standard / UTC-8 DST)\n ANC: \"America/Anchorage\",\n FAI: \"America/Anchorage\",\n JNU: \"America/Juneau\",\n // Hawaii (UTC-10, no DST)\n HNL: \"Pacific/Honolulu\",\n OGG: \"Pacific/Honolulu\",\n KOA: \"Pacific/Honolulu\",\n // International (iter-6 H12): minimal set required to un-skip the\n // case-5 RJTT year-wrap cache behavior test. Python's\n // `mostlyright.snapshot._resolve_tz` falls back to the broader STATIONS\n // registry for intl ICAOs; the TS port hasn't ported that fallback\n // yet (tracked as TS-W6 — exhaustive intl-station tz coverage). This\n // entry closes H12 cleanly without pulling the whole STATIONS map in.\n // ICAO key (RJTT) — international stations have no 3-letter NWS code.\n // Tokyo Haneda — UTC+9 LST, no DST.\n RJTT: \"Asia/Tokyo\",\n});\n\n/** Reference UTC moment in January (no DST in Northern Hemisphere US). */\nexport const _JAN_REF = new Date(Date.UTC(2024, 0, 15, 12, 0, 0));\n\n/** NWS CLI typical publication delay: 10 h after midnight LST. */\nexport const _CLI_PUBLICATION_DELAY_HOURS = 10.0;\n\n/** Kalshi market typical close time (LST). */\nexport const _MARKET_CLOSE_HOUR_LST = 16;\nexport const _MARKET_CLOSE_MINUTE_LST = 30;\n\n// ---------------------------------------------------------------------------\n// LST offset extraction\n// ---------------------------------------------------------------------------\n\nconst _OFFSET_CACHE = new Map<string, number>();\n\n/**\n * Return the LOCAL STANDARD TIME UTC offset (in hours) for an IANA tz,\n * sampled from January 15 2024 12:00 UTC so the result is never affected\n * by DST in the Northern Hemisphere.\n *\n * Implementation: format `_JAN_REF` in the target tz via Intl.DateTimeFormat\n * and diff against the UTC formatted view to recover the offset.\n */\nexport function _lstOffsetHours(stationTz: string): number {\n const cached = _OFFSET_CACHE.get(stationTz);\n if (cached !== undefined) return cached;\n\n // We compute: localComponents(stationTz, _JAN_REF) − utcComponents(_JAN_REF).\n // The difference gives the tz offset in (hours). Negative for west of UTC.\n const fmt = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: stationTz,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n const parts = fmt.formatToParts(_JAN_REF);\n const get = (type: string): number => {\n const part = parts.find((p) => p.type === type);\n if (!part) {\n throw new Error(`Intl.DateTimeFormat missing ${type} for tz=${stationTz}`);\n }\n return Number(part.value);\n };\n\n const year = get(\"year\");\n const month = get(\"month\");\n const day = get(\"day\");\n let hour = get(\"hour\");\n const minute = get(\"minute\");\n const second = get(\"second\");\n // Some locales return hour \"24\" instead of \"00\" for midnight; normalize.\n if (hour === 24) hour = 0;\n\n // Compute the timezone's wall-clock for _JAN_REF treated as UTC.\n const localAsUtc = Date.UTC(year, month - 1, day, hour, minute, second);\n const offsetMs = localAsUtc - _JAN_REF.getTime();\n const offsetHours = offsetMs / 3_600_000;\n _OFFSET_CACHE.set(stationTz, offsetHours);\n return offsetHours;\n}\n\n// ---------------------------------------------------------------------------\n// Station code normalization + tz lookup\n// ---------------------------------------------------------------------------\n\nfunction _stationCodeNormalized(station: string): string {\n const s = station.trim().toUpperCase();\n if (s.length === 4 && s.startsWith(\"K\")) {\n return s.substring(1);\n }\n return s;\n}\n\n/**\n * Resolve a station code (NWS 3-letter, ICAO 4-letter) to an IANA tz string.\n * Honors `tzOverride` first, then the built-in `_STATION_TZ` map.\n * Throws if no tz can be resolved.\n */\nexport function _resolveStationTz(station: string, tzOverride?: string): string {\n if (tzOverride) return tzOverride;\n const code = _stationCodeNormalized(station);\n const tz = _STATION_TZ[code];\n if (tz) return tz;\n throw new Error(\n `Unknown station timezone: ${JSON.stringify(code)}. Add it to _STATION_TZ or pass tzOverride=\"America/...\".`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// as_of parsing\n// ---------------------------------------------------------------------------\n\nfunction _parseAsOf(asOf: Date | string): Date {\n if (asOf instanceof Date) {\n if (Number.isNaN(asOf.getTime())) {\n throw new Error(\"Invalid Date passed as asOf\");\n }\n return asOf;\n }\n let s = asOf.trim();\n // Python: bare ISO without tz → assume UTC.\n if (s.endsWith(\"Z\")) {\n // Date.parse handles \"Z\" natively.\n } else if (!/[+-]\\d{2}:?\\d{2}$/.test(s)) {\n // No timezone suffix — treat as UTC.\n s = `${s}Z`;\n }\n const ms = Date.parse(s);\n if (!Number.isFinite(ms)) {\n throw new Error(`Invalid as_of string: ${JSON.stringify(asOf)}`);\n }\n return new Date(ms);\n}\n\n// ---------------------------------------------------------------------------\n// Public surface\n// ---------------------------------------------------------------------------\n\nfunction _pad2(n: number): string {\n return n < 10 ? `0${n}` : `${n}`;\n}\n\nfunction _isoDate(year: number, month: number, day: number): string {\n return `${year}-${_pad2(month)}-${_pad2(day)}`;\n}\n\n/**\n * Return the Kalshi settlement date (YYYY-MM-DD LST) for a UTC moment.\n *\n * Kalshi NHIGH/NLOW contracts cover midnight–midnight LOCAL STANDARD TIME.\n * DST is ignored: the window is always fixed to the standard UTC offset.\n */\nexport function settlementDateFor(\n asOf: Date | string,\n station: string,\n tzOverride?: string,\n): string {\n const utcDt = _parseAsOf(asOf);\n const tz = _resolveStationTz(station, tzOverride);\n const offsetHours = _lstOffsetHours(tz);\n // offsetHours is negative for US stations → lstMs < utcMs.\n const lstMs = utcDt.getTime() + offsetHours * 3_600_000;\n const lst = new Date(lstMs);\n // Use getUTC* because we already shifted the epoch by the LST offset.\n return _isoDate(lst.getUTCFullYear(), lst.getUTCMonth() + 1, lst.getUTCDate());\n}\n\n/**\n * Return UTC start/end of the Kalshi settlement window for a date.\n * The window is midnight-midnight LST, expressed in UTC.\n */\nexport function settlementWindowUtc(\n dateStr: string,\n station: string,\n tzOverride?: string,\n): [Date, Date] {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateStr);\n if (!match) {\n throw new Error(`Invalid ISO date for settlement window: ${JSON.stringify(dateStr)}`);\n }\n const [, yStr, mStr, dStr] = match;\n const year = Number(yStr);\n const month = Number(mStr);\n const day = Number(dStr);\n const tz = _resolveStationTz(station, tzOverride);\n const offsetHours = _lstOffsetHours(tz);\n\n // midnight LST = 00:00 LST = (00:00 UTC) − offset (offset is negative)\n // Example: UTC-5 → midnight LST = 05:00 UTC.\n const midnightLstAsUtcMs = Date.UTC(year, month - 1, day, 0, 0, 0);\n const startMs = midnightLstAsUtcMs - offsetHours * 3_600_000;\n const start = new Date(startMs);\n const end = new Date(startMs + 24 * 3_600_000);\n return [start, end];\n}\n\n/**\n * Return the UTC time at which the NWS CLI for a date is expected to be\n * available. Default delay is 10 h after midnight LST on the next day.\n */\nexport function cliAvailableAt(\n dateStr: string,\n station: string,\n delayHours: number = _CLI_PUBLICATION_DELAY_HOURS,\n tzOverride?: string,\n): Date {\n const [, windowEnd] = settlementWindowUtc(dateStr, station, tzOverride);\n return new Date(windowEnd.getTime() + delayHours * 3_600_000);\n}\n\n/**\n * Return the UTC time of the Kalshi market close for a settlement date.\n * Kalshi NHIGH/NLOW markets close at 4:30 PM LST on the day of settlement.\n */\nexport function marketCloseUtc(dateStr: string, station: string, tzOverride?: string): Date {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateStr);\n if (!match) {\n throw new Error(`Invalid ISO date for market close: ${JSON.stringify(dateStr)}`);\n }\n const [, yStr, mStr, dStr] = match;\n const year = Number(yStr);\n const month = Number(mStr);\n const day = Number(dStr);\n const tz = _resolveStationTz(station, tzOverride);\n const offsetHours = _lstOffsetHours(tz);\n\n const marketCloseAsUtcMs = Date.UTC(\n year,\n month - 1,\n day,\n _MARKET_CLOSE_HOUR_LST,\n _MARKET_CLOSE_MINUTE_LST,\n 0,\n );\n return new Date(marketCloseAsUtcMs - offsetHours * 3_600_000);\n}\n","// Venue-agnostic station catalog (Phase 22) — the TS mirror of Python's\n// `mostlyright.stations`.\n//\n// A station is a physical fact; the prediction-market venue that settles on it\n// is metadata. The `venues` tag follows each issuer's ACTUAL settlement map,\n// not country — Kalshi and Polymarket settle several shared cities against\n// different stations (NYC: KNYC vs KLGA; Chicago: KMDW vs KORD), so\n// `filterByVenue(\"kalshi\")` is the Kalshi settlement universe, NOT \"every US\n// station\". Markets derives its settlement universe by filtering here; bare-data\n// consumers ignore venues entirely.\n//\n// `venues` is `readonly string[]` (not a Set) on each record to keep the data\n// tree-shakeable and the gzipped bundle small.\n\nimport {\n STATIONS,\n STATION_BY_CODE,\n STATION_BY_ICAO,\n type StationInfo,\n} from \"../data/generated/stations.js\";\n\n// The codegen record IS the public station shape — one source of truth,\n// re-exported (not duplicated), mirroring Python's `Station = StationInfo`.\nexport type Station = StationInfo;\n\n/**\n * Read-only view over the station registry with venue/country filters.\n *\n * Lookups accept either the registry code (3-letter NWS code for US stations,\n * ICAO for international) or the 4-letter ICAO directly, so `get(\"NYC\")`,\n * `get(\"KNYC\")`, and `get(\"EGLL\")` all resolve.\n */\nexport class StationCatalog {\n private readonly stations: ReadonlyArray<Station>;\n private readonly byCode: ReadonlyMap<string, Station>;\n private readonly byIcao: ReadonlyMap<string, Station>;\n\n constructor(stations: ReadonlyArray<Station> = STATIONS) {\n this.stations = stations;\n if (stations === STATIONS) {\n // Reuse the codegen maps for the default catalog — no rebuild.\n this.byCode = STATION_BY_CODE;\n this.byIcao = STATION_BY_ICAO;\n } else {\n const byCode = new Map<string, Station>();\n const byIcao = new Map<string, Station>();\n for (const s of stations) {\n if (s.code !== null) byCode.set(s.code, s);\n byIcao.set(s.icao, s);\n }\n this.byCode = byCode;\n this.byIcao = byIcao;\n }\n }\n\n /**\n * Return the station for `code` (registry code or ICAO).\n * @throws if no station matches.\n */\n get(code: string): Station {\n const station = this.byCode.get(code) ?? this.byIcao.get(code);\n if (station === undefined) {\n throw new Error(\n `Unknown station ${JSON.stringify(code)}. Expected a registry code (e.g. \"NYC\", \"EGLL\") or a 4-letter ICAO (e.g. \"KNYC\").`,\n );\n }\n return station;\n }\n\n /** Stations tagged with `venue` (e.g. \"kalshi\"), sorted by ICAO. */\n filterByVenue(venue: string): Station[] {\n return this.stations\n .filter((s) => s.venues.includes(venue))\n .sort((a, b) => a.icao.localeCompare(b.icao));\n }\n\n /** Stations whose ISO 3166-1 alpha-2 `country` matches, sorted by ICAO. */\n filterByCountry(country: string): Station[] {\n return this.stations\n .filter((s) => s.country === country)\n .sort((a, b) => a.icao.localeCompare(b.icao));\n }\n\n /** Union of all venue tags present in the catalog. */\n venues(): ReadonlySet<string> {\n const out = new Set<string>();\n for (const s of this.stations) {\n for (const v of s.venues) out.add(v);\n }\n return out;\n }\n\n /** True iff `code` resolves to a station (by registry code or ICAO). */\n has(code: string): boolean {\n return this.byCode.has(code) || this.byIcao.has(code);\n }\n\n get size(): number {\n return this.stations.length;\n }\n\n [Symbol.iterator](): Iterator<Station> {\n return this.stations[Symbol.iterator]();\n }\n}\n\n/** Process-wide default catalog over the codegen station registry. */\nexport const CATALOG = new StationCatalog();\n","// Shared HTTP download helper with retry logic.\n//\n// Ported from `packages/core/src/mostlyright/_internal/_http.py`.\n// Uses the native `fetch` API so this module works in browsers, Node 20+,\n// Cloudflare Workers, and Deno. Returns the `Response` on success — callers\n// decide whether to consume JSON, text, or bytes.\n\nimport {\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n RateLimitError,\n ServerError,\n TherminalError,\n ValidationError,\n} from \"../exceptions/index.js\";\n\n/** Default base backoff delay (ms). Mirrors Python `BASE_DELAY = 1.0`. */\nconst DEFAULT_BASE_DELAY_MS = 1000;\n/** Default retry budget. Mirrors Python `MAX_RETRIES = 3` (total attempts). */\nconst DEFAULT_MAX_RETRIES = 3;\n/** Default per-attempt timeout. Mirrors Python `HTTP_TIMEOUT = 60.0`. */\nconst DEFAULT_TIMEOUT_MS = 60_000;\n/** Retryable statuses. Mirrors Python `TRANSIENT_CODES`. */\nconst DEFAULT_RETRY_STATUSES: ReadonlySet<number> = new Set([429, 500, 502, 503, 504]);\n\n/**\n * Upper cap on the per-attempt sleep induced by a server ``Retry-After``\n * header. Mirrors Python ``_MAX_RETRY_AFTER_S = 120.0`` in\n * `packages/markets/src/mostlyright/markets/_kalshi_client.py`. A hostile\n * or buggy upstream returning ``Retry-After: 999999`` would otherwise\n * hang the runtime for ~11 days per retry; a 2-minute cap matches the\n * AWS SDK default and is more than enough headroom for any legitimate\n * rate-limit backoff hint. Iter-3 codex + python-architect HIGH.\n */\nconst MAX_RETRY_AFTER_MS = 120_000;\n\nexport interface FetchWithRetryOptions {\n /** Base backoff delay in milliseconds (default 1000). */\n baseDelayMs?: number;\n /** Total attempts (default 3). */\n maxRetries?: number;\n /** Per-attempt timeout in milliseconds (default 60_000). */\n timeoutMs?: number;\n /** Statuses that trigger a retry. Default {429, 500, 502, 503, 504}. */\n retryStatuses?: ReadonlySet<number>;\n /** Caller-supplied abort signal (composed with per-attempt timeout). */\n signal?: AbortSignal;\n /** Request headers. */\n headers?: Record<string, string>;\n /** Convenience: set the User-Agent header. */\n userAgent?: string;\n /** HTTP method (default GET). */\n method?: string;\n /** Optional request body (forwarded to `fetch`). */\n body?: BodyInit | null;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n cleanup();\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n const cleanup = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction parseRetryAfter(header: string | null): number | null {\n if (!header) return null;\n const asInt = Number(header);\n if (Number.isFinite(asInt) && asInt >= 0) return asInt;\n // HTTP-date form — convert to seconds-from-now.\n const dateMs = Date.parse(header);\n if (Number.isFinite(dateMs)) {\n return Math.max(0, Math.round((dateMs - Date.now()) / 1000));\n }\n return null;\n}\n\nfunction throwForNonRetryableStatus(status: number, url: string, retryAfter: number | null): never {\n if (status === 404) {\n throw new NotFoundError(`HTTP 404 for ${url}`);\n }\n if (status === 400) {\n throw new ValidationError(`HTTP 400 for ${url}`);\n }\n if (status === 401) {\n throw new AuthenticationError(`HTTP 401 for ${url}`);\n }\n if (status === 403) {\n throw new ForbiddenError(`HTTP 403 for ${url}`);\n }\n if (status === 429) {\n throw new RateLimitError(retryAfter, { source: url });\n }\n if (status >= 500 && status < 600) {\n throw new ServerError(`HTTP ${status} for ${url}`, { statusCode: status });\n }\n throw new TherminalError(`HTTP ${status} for ${url}`, { statusCode: status });\n}\n\n/**\n * GET (or other) a URL with exponential-backoff retry semantics.\n *\n * Behaviour:\n * - `signal` is composed with a per-attempt timeout via `AbortController`.\n * - On retryable status (default: 429/500/502/503/504), wait\n * `baseDelayMs * 2^attempt` (with ≤25% jitter) and retry, up to\n * `maxRetries` total attempts.\n * - On 404 → `NotFoundError`. On 400/401/403 → `ValidationError` /\n * `AuthenticationError` / `ForbiddenError`. After retry exhaustion on\n * 429 → `RateLimitError` (with `retryAfter` honoured). After retry\n * exhaustion on 5xx → `ServerError`.\n * - On network/transport failure: retried under the same budget, last\n * error rethrown as a `TherminalError` if it isn't one already.\n */\nexport async function fetchWithRetry(\n url: string,\n opts: FetchWithRetryOptions = {},\n): Promise<Response> {\n const baseDelay = opts.baseDelayMs ?? DEFAULT_BASE_DELAY_MS;\n const maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const retryStatuses = opts.retryStatuses ?? DEFAULT_RETRY_STATUSES;\n\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.userAgent && !(\"user-agent\" in lowercaseKeys(headers))) {\n headers[\"User-Agent\"] = opts.userAgent;\n }\n\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n const attemptController = new AbortController();\n const timeoutHandle = setTimeout(() => attemptController.abort(), timeoutMs);\n const onParentAbort = () => attemptController.abort();\n if (opts.signal) {\n if (opts.signal.aborted) {\n clearTimeout(timeoutHandle);\n throw new DOMException(\"Aborted\", \"AbortError\");\n }\n opts.signal.addEventListener(\"abort\", onParentAbort, { once: true });\n }\n\n try {\n const init: RequestInit = {\n method: opts.method ?? \"GET\",\n headers,\n signal: attemptController.signal,\n };\n if (opts.body !== undefined && opts.body !== null) {\n init.body = opts.body;\n }\n const response = await fetch(url, init);\n\n if (response.status === 404) {\n throw new NotFoundError(`HTTP 404 for ${url}`);\n }\n\n if (retryStatuses.has(response.status)) {\n const retryAfterHeader = parseRetryAfter(response.headers.get(\"retry-after\"));\n if (attempt < maxRetries - 1) {\n const jitter = baseDelay * 2 ** attempt * Math.random() * 0.25;\n const delayMs = baseDelay * 2 ** attempt + jitter;\n // RFC 7231 §7.1.3: prefer caller's Retry-After when present.\n // Iter-3 codex + python-architect HIGH: cap the upstream hint at\n // MAX_RETRY_AFTER_MS so a hostile/buggy server cannot pin us in\n // `sleep()` for arbitrary durations (mirrors Python's\n // `_MAX_RETRY_AFTER_S = 120.0`).\n const sleepMs =\n retryAfterHeader !== null\n ? Math.min(retryAfterHeader * 1000, MAX_RETRY_AFTER_MS)\n : delayMs;\n await sleep(sleepMs, opts.signal);\n continue;\n }\n throwForNonRetryableStatus(response.status, url, retryAfterHeader);\n }\n\n if (response.status >= 400) {\n const retryAfterHeader = parseRetryAfter(response.headers.get(\"retry-after\"));\n throwForNonRetryableStatus(response.status, url, retryAfterHeader);\n }\n\n return response;\n } catch (err) {\n // Preserve TherminalError subclasses unchanged (don't retry permanent\n // 4xx errors). Retry network/transport errors and AbortError from the\n // per-attempt timeout only — caller-provided signal abort is fatal.\n if (\n err instanceof TherminalError &&\n !(err instanceof ServerError) &&\n !(err instanceof RateLimitError)\n ) {\n throw err;\n }\n if (opts.signal?.aborted) {\n throw err;\n }\n lastError = err;\n if (attempt < maxRetries - 1) {\n const jitter = baseDelay * 2 ** attempt * Math.random() * 0.25;\n const delayMs = baseDelay * 2 ** attempt + jitter;\n await sleep(delayMs, opts.signal);\n continue;\n }\n // Retry budget exhausted — propagate.\n if (err instanceof TherminalError) throw err;\n throw new TherminalError(`fetch failed after ${maxRetries} attempts: ${describeError(err)}`, {\n source: url,\n });\n } finally {\n clearTimeout(timeoutHandle);\n opts.signal?.removeEventListener(\"abort\", onParentAbort);\n }\n }\n\n // Unreachable in practice — the loop either returns or throws each\n // iteration, but TS can't prove it.\n /* istanbul ignore next */\n if (lastError instanceof Error) throw lastError;\n /* istanbul ignore next */\n throw new TherminalError(`fetch failed: ${describeError(lastError)}`, { source: url });\n}\n\nfunction describeError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction lowercaseKeys(obj: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const k of Object.keys(obj)) {\n out[k.toLowerCase()] = obj[k] as string;\n }\n return out;\n}\n"],"mappings":"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,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,OAAO,SAAS,EAAE,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AACxB,CAAC;AAEM,IAAM,kBAAoD,oBAAI,IAAyB;AAAA,EAC5F,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,CAAC,CAAE;AAAA,EACrB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,EACtB,CAAC,QAAQ,SAAS,EAAE,CAAE;AAAA,E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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fetchWithRetry
3
- } from "./chunk-WKPNA46C.mjs";
3
+ } from "./chunk-7XWX6QZG.mjs";
4
4
 
5
5
  // ../weather/src/_fetchers/_iem_chunks.ts
6
6
  var ISO_DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
@@ -105,4 +105,4 @@ export {
105
105
  buildIemUrl,
106
106
  downloadIemAsos
107
107
  };
108
- //# sourceMappingURL=chunk-64FNXDHG.mjs.map
108
+ //# sourceMappingURL=chunk-TT6J2BKH.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../weather/src/_fetchers/_iem_chunks.ts","../../weather/src/_fetchers/iem-asos.ts"],"sourcesContent":["// Shared calendar-year chunkers for IEM fetchers.\n//\n// Byte-faithful TS port of\n// `packages/weather/src/mostlyright/weather/_fetchers/_iem_chunks.py::yearly_chunks_exclusive_end`\n// (mostlyright PR #85 commit cf9eb85, 2026-05-12; Pattern 1).\n//\n// Only the EXCLUSIVE-end variant is ported here — the IEM ASOS download\n// loop (`iem-asos.ts`) is the sole TS-side consumer, and IEM's `day2`\n// query parameter is exclusive. `yearly_chunks_inclusive` (used by the\n// Python forecast / climate paths) is NOT ported in TS-W2.\n//\n// Leap-year safety: the advance step uses calendar arithmetic\n// (`date(year+1, 1, 1)`), NOT `+365 days`. The latter silently drops Feb 29\n// in leap years and walks the calendar boundary by one day every leap year\n// — PR #85's primary anti-pattern.\n//\n// Date representation: ISO 8601 date strings (\"YYYY-MM-DD\"). Strings sort\n// lexicographically equivalent to calendar order and round-trip cleanly;\n// the JS `Date` constructor is deliberately avoided because its arithmetic\n// silently shifts to local-time, which would poison cache keys at midnight\n// boundaries for non-UTC hosts (Python's `_iem_chunks.py` module docstring\n// references this class of bug).\n\n/**\n * ISO 8601 date string, no time component. Format: `YYYY-MM-DD`.\n *\n * Brand-style alias — at runtime this is a plain `string`. Use\n * {@link parseIsoDate} when you need the parsed year/month/day integers.\n */\nexport type IsoDate = string;\n\nconst ISO_DATE_RE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\ninterface YMD {\n readonly year: number;\n readonly month: number;\n readonly day: number;\n}\n\n/**\n * Parse an ISO date string into year/month/day integers. Throws on\n * malformed input. The validation is intentionally minimal — chunker\n * inputs come from the fetcher's normalization layer, which is the\n * defensive boundary. Calendar-validity (e.g. Feb 30) is NOT checked\n * here; the caller has already validated.\n */\nfunction parseIsoDate(value: IsoDate): YMD {\n const m = ISO_DATE_RE.exec(value);\n if (m === null) {\n throw new Error(`Invalid ISO date: ${JSON.stringify(value)}; expected \"YYYY-MM-DD\"`);\n }\n // Indices 1-3 always present when the regex matches.\n return {\n year: Number.parseInt(m[1] as string, 10),\n month: Number.parseInt(m[2] as string, 10),\n day: Number.parseInt(m[3] as string, 10),\n };\n}\n\n/**\n * Format integer year/month/day as an ISO date string. Month and day are\n * zero-padded to 2 digits to preserve lexicographic order.\n */\nfunction formatIsoDate(year: number, month: number, day: number): IsoDate {\n const mm = month < 10 ? `0${month}` : String(month);\n const dd = day < 10 ? `0${day}` : String(day);\n return `${year}-${mm}-${dd}`;\n}\n\n/**\n * Range split into per-calendar-year EXCLUSIVE-end chunks\n * (Jan 1 of next year).\n *\n * Properties:\n * - The first chunk's start is `max(date(start.year, 1, 1), start)` — i.e.\n * the caller's actual start for the first chunk, NOT Jan 1. The\n * `current = date(start.year, 1, 1)` initialization ensures the loop\n * visits every calendar-year boundary regardless of the caller's start.\n * - Every chunk's end is `date(year+1, 1, 1)` — the IEM `day2`-exclusive\n * convention for \"include all of `year`\".\n * - Leap-year safe: advance via `date(year+1, 1, 1)`, NOT `+365 days`.\n * - Reversed range (`start > end` by lexicographic compare) returns `[]`\n * without throwing — higher layers iterate the list directly.\n *\n * Byte-faithful with the Python helper used by `iem_asos.download_iem_asos`.\n */\nexport function yearlyChunksExclusiveEnd(\n start: IsoDate,\n end: IsoDate,\n): ReadonlyArray<readonly [IsoDate, IsoDate]> {\n // Reversed-range short-circuit (lexicographic compare is equivalent to\n // calendar compare for YYYY-MM-DD strings of identical shape). Mirrors\n // Python L66-67 (`if start > end: return []`).\n if (start > end) {\n return [];\n }\n\n const { year: startYear } = parseIsoDate(start);\n const { year: endYear } = parseIsoDate(end);\n\n const chunks: Array<readonly [IsoDate, IsoDate]> = [];\n // Match Python `current = date(start.year, 1, 1)` initialization.\n let currentYear = startYear;\n while (currentYear <= endYear) {\n const currentYearStart = formatIsoDate(currentYear, 1, 1);\n // Match Python `chunk_start = max(current, start)`. For the first\n // iteration this clamps to the caller's `start`; for subsequent\n // iterations `currentYearStart` is always greater.\n const chunkStart: IsoDate = currentYearStart > start ? currentYearStart : start;\n // CRITICAL: leap-year safe via calendar arithmetic, NOT `+365 days`.\n const nextYearFirst: IsoDate = formatIsoDate(currentYear + 1, 1, 1);\n chunks.push([chunkStart, nextYearFirst]);\n currentYear += 1;\n }\n return chunks;\n}\n","// IEM ASOS historical METAR fetcher — yearly-chunked CSV downloads.\n//\n// Byte-faithful TS port of Python\n// `packages/weather/src/mostlyright/weather/_fetchers/iem_asos.py::download_iem_asos`,\n// with the following deliberate adaptations:\n//\n// 1. No disk cache. Python writes per-station CSVs under\n// `dest_dir/{station}/iem_*.csv`; the TS port returns the CSV body\n// in-memory via `{ chunkStart, chunkEnd, csv }`. The disk-cache layer\n// (PERF-02 partial-namespace + cache-poisoning paths) lands in TS-W3 —\n// it's intentionally out of scope here. Drop ALL filename / `skip_cache`\n// / `today_utc` partial-namespace logic.\n// 2. Station validation at the URL boundary uses an inline regex\n// (`^[A-Z]{3,4}$`) matching `iem-cli.ts`'s `validateIcao` pattern. The\n// Python `validate_icao_for_path` from `_internal/_bounds.py` is a\n// path-traversal guard — there's no path here in TS-W2, so the regex\n// check is the equivalent defense-in-depth measure.\n//\n// URL shape, start-normalization (caller's `start` clamped to\n// `date(start.year, 1, 1)` for cache idempotence under per-month callers),\n// reversed-range short-circuit (`start > end → []`), report_type guard\n// ({3, 4}), and 1-sec polite delay are byte-faithful.\n//\n// CORS posture: OPEN — IEM emits `Access-Control-Allow-Origin: *` per\n// `.planning/research/TS-CORS-MATRIX.md` §IEM-ASOS. Works in browsers,\n// Node 20+, Cloudflare Workers, Deno.\n\nimport { fetchWithRetry } from \"@mostlyrightmd/core\";\nimport type { FetchWithRetryOptions } from \"@mostlyrightmd/core\";\n\nimport { type IsoDate, yearlyChunksExclusiveEnd } from \"./_iem_chunks.js\";\n\n/** IEM ASOS request endpoint. Mirrors Python `IEM_BASE_URL`. */\nexport const IEM_BASE_URL = \"https://mesonet.agron.iastate.edu/cgi-bin/request/asos.py\";\n\n/**\n * Polite delay (ms) between consecutive IEM HTTP requests. Mirrors Python\n * `IEM_POLITE_DELAY = 1.0` (s) — IEM runs on a university server and\n * documents a 1-sec/IP throttle (see .planning/research/SOURCE-LIMITS.md).\n */\nexport const IEM_POLITE_DELAY_MS = 1000;\n\n/**\n * Station code regex (3-4 uppercase letters). Mirrors the inline pattern\n * used by `iem-cli.ts::validateIcao` and the shared `STATION_CODE_RE` from\n * `@mostlyrightmd/core/internal/bounds`. Inlined here so the fetcher does not\n * transitively pull in the validators barrel — keeps the per-fetcher\n * dep graph narrow per the TS-W1 review pattern.\n */\nconst STATION_CODE_RE = /^[A-Z]{3,4}$/;\n\n/** Permitted IEM report_type values: 3 = METAR, 4 = SPECI. */\nconst VALID_REPORT_TYPES = new Set<number>([3, 4]);\n\n/**\n * One downloaded yearly chunk. The CSV body is forwarded verbatim from\n * the upstream response so the parser can run a downstream pass over it.\n */\nexport interface IemChunkResult {\n /** First day of this chunk's range (caller's start for chunk 0; Jan 1 for subsequent). */\n readonly chunkStart: IsoDate;\n /** EXCLUSIVE end of this chunk's range — Jan 1 of the following calendar year. */\n readonly chunkEnd: IsoDate;\n /** Raw CSV body returned by IEM (text/plain, comma-separated). */\n readonly csv: string;\n}\n\nexport interface DownloadIemAsosOptions extends FetchWithRetryOptions {\n /** `3` (METAR, default) or `4` (SPECI). */\n reportType?: 3 | 4;\n /**\n * Delay (ms) between successive chunk requests. Defaults to\n * {@link IEM_POLITE_DELAY_MS}. Set to `0` in unit tests.\n */\n politenessMs?: number;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction validateIcao(stationCode: string): void {\n if (typeof stationCode !== \"string\" || !STATION_CODE_RE.test(stationCode)) {\n throw new Error(\n `station_code=${JSON.stringify(\n stationCode,\n )} does not match STATION_CODE_RE (3-4 uppercase letters); refusing to use as URL component`,\n );\n }\n}\n\n/**\n * Build the IEM ASOS download URL for one (chunk, report_type) request.\n *\n * Param shape and ordering are byte-faithful to Python `_build_iem_url`:\n * station, data, tz, format, latlon, elev, missing, trace, direct,\n * report_type, year1, month1, day1, year2, month2, day2.\n *\n * Month/day are emitted WITHOUT zero-padding (Python uses bare `{start.month}`,\n * not `{start.month:02d}`) — preserve byte-equivalence on URL snapshots.\n *\n * `end` is the EXCLUSIVE end (already adjusted by the chunker to Jan 1 of\n * the following calendar year).\n */\nexport function buildIemUrl(\n stationCode: string,\n start: IsoDate,\n end: IsoDate,\n reportType: number,\n): string {\n // Parse ISO strings into ints (no Date — avoids local-TZ silent shifts).\n const [sy, sm, sd] = splitIso(start);\n const [ey, em, ed] = splitIso(end);\n const params = `station=${stationCode}&data=all&tz=Etc/UTC&format=comma&latlon=no&elev=no&missing=M&trace=T&direct=no&report_type=${reportType}&year1=${sy}&month1=${sm}&day1=${sd}&year2=${ey}&month2=${em}&day2=${ed}`;\n return `${IEM_BASE_URL}?${params}`;\n}\n\nfunction splitIso(iso: IsoDate): [number, number, number] {\n // The chunker has already validated; we just split.\n const parts = iso.split(\"-\");\n // Length-3 guaranteed if the chunker emitted this; defense in depth.\n if (parts.length !== 3) {\n throw new Error(`Invalid ISO date passed to buildIemUrl: ${JSON.stringify(iso)}`);\n }\n return [\n Number.parseInt(parts[0] as string, 10),\n Number.parseInt(parts[1] as string, 10),\n Number.parseInt(parts[2] as string, 10),\n ];\n}\n\n/**\n * Download yearly chunks of IEM ASOS data for one station, returning the\n * raw CSV bodies in chunker-natural order.\n *\n * The caller's inclusive `[start, end]` is normalized internally to\n * `[date(start.year, 1, 1), end]` and split into per-calendar-year\n * EXCLUSIVE-end chunks via {@link yearlyChunksExclusiveEnd}. Each chunk\n * fires one HTTP request to the IEM ASOS endpoint, with a polite delay\n * between successful responses (default {@link IEM_POLITE_DELAY_MS}).\n *\n * Errors propagate from `fetchWithRetry` — 4xx/5xx after retry exhaustion\n * are NOT swallowed (the IEM ASOS path is parity-critical; silent failure\n * would manifest as missing observation rows downstream).\n *\n * @throws If `reportType` is not `3` (METAR) or `4` (SPECI).\n * @throws If `stationCode` does not match `^[A-Z]{3,4}$` (path-traversal /\n * URL-injection defense).\n * @throws Whatever `fetchWithRetry` propagates on persistent network/HTTP\n * errors.\n */\nexport async function downloadIemAsos(\n stationCode: string,\n start: IsoDate,\n end: IsoDate,\n opts: DownloadIemAsosOptions = {},\n): Promise<ReadonlyArray<IemChunkResult>> {\n const reportType = opts.reportType ?? 3;\n if (!VALID_REPORT_TYPES.has(reportType)) {\n throw new Error(`report_type must be 3 (METAR) or 4 (SPECI), got ${reportType}`);\n }\n // Defense-in-depth: validate at the URL boundary BEFORE any HTTP.\n validateIcao(stationCode);\n\n // Reversed-range guard. Mirror Python L201-202: the chunker honors\n // `start > end → []`, but defensive short-circuit here avoids ever\n // computing the normalized year boundary for a malformed call.\n if (start > end) {\n return [];\n }\n\n // Tradewinds-specific normalization: clamp caller's `start` to Jan 1 of\n // its year so per-month callers share a yearly cache key (parity-faithful\n // with Python's `normalized_start = date(start.year, 1, 1)`). Mirrored in\n // TS so the URL shape (and the future TS-W3 cache key) stays byte-stable\n // with Python on the same range.\n const normalizedStart: IsoDate = `${start.slice(0, 4)}-01-01`;\n const chunks = yearlyChunksExclusiveEnd(normalizedStart, end);\n\n const politenessMs = opts.politenessMs ?? IEM_POLITE_DELAY_MS;\n // Strip fetcher-specific opts from the bag forwarded to fetchWithRetry.\n const { reportType: _rtDrop, politenessMs: _pmDrop, ...fetchOpts } = opts;\n void _rtDrop;\n void _pmDrop;\n\n const out: IemChunkResult[] = [];\n for (const [chunkStart, chunkEnd] of chunks) {\n const url = buildIemUrl(stationCode, chunkStart, chunkEnd, reportType);\n const response = await fetchWithRetry(url, fetchOpts);\n const csv = await response.text();\n out.push({ chunkStart, chunkEnd, csv });\n // Polite delay AFTER each successful round-trip (mirror Python L224\n // which sleeps unconditionally). Skipping the trailing sleep on the\n // last chunk would be a micro-optimization not present in Python.\n if (politenessMs > 0) {\n await sleep(politenessMs);\n }\n }\n return out;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../weather/src/_fetchers/_iem_chunks.ts","../../weather/src/_fetchers/iem-asos.ts"],"sourcesContent":["// Shared calendar-year chunkers for IEM fetchers.\n//\n// Byte-faithful TS port of\n// `packages/weather/src/mostlyright/weather/_fetchers/_iem_chunks.py::yearly_chunks_exclusive_end`\n// (mostlyright PR #85 commit cf9eb85, 2026-05-12; Pattern 1).\n//\n// Only the EXCLUSIVE-end variant is ported here — the IEM ASOS download\n// loop (`iem-asos.ts`) is the sole TS-side consumer, and IEM's `day2`\n// query parameter is exclusive. `yearly_chunks_inclusive` (used by the\n// Python forecast / climate paths) is NOT ported in TS-W2.\n//\n// Leap-year safety: the advance step uses calendar arithmetic\n// (`date(year+1, 1, 1)`), NOT `+365 days`. The latter silently drops Feb 29\n// in leap years and walks the calendar boundary by one day every leap year\n// — PR #85's primary anti-pattern.\n//\n// Date representation: ISO 8601 date strings (\"YYYY-MM-DD\"). Strings sort\n// lexicographically equivalent to calendar order and round-trip cleanly;\n// the JS `Date` constructor is deliberately avoided because its arithmetic\n// silently shifts to local-time, which would poison cache keys at midnight\n// boundaries for non-UTC hosts (Python's `_iem_chunks.py` module docstring\n// references this class of bug).\n\n/**\n * ISO 8601 date string, no time component. Format: `YYYY-MM-DD`.\n *\n * Brand-style alias — at runtime this is a plain `string`. Use\n * {@link parseIsoDate} when you need the parsed year/month/day integers.\n */\nexport type IsoDate = string;\n\nconst ISO_DATE_RE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\ninterface YMD {\n readonly year: number;\n readonly month: number;\n readonly day: number;\n}\n\n/**\n * Parse an ISO date string into year/month/day integers. Throws on\n * malformed input. The validation is intentionally minimal — chunker\n * inputs come from the fetcher's normalization layer, which is the\n * defensive boundary. Calendar-validity (e.g. Feb 30) is NOT checked\n * here; the caller has already validated.\n */\nfunction parseIsoDate(value: IsoDate): YMD {\n const m = ISO_DATE_RE.exec(value);\n if (m === null) {\n throw new Error(`Invalid ISO date: ${JSON.stringify(value)}; expected \"YYYY-MM-DD\"`);\n }\n // Indices 1-3 always present when the regex matches.\n return {\n year: Number.parseInt(m[1] as string, 10),\n month: Number.parseInt(m[2] as string, 10),\n day: Number.parseInt(m[3] as string, 10),\n };\n}\n\n/**\n * Format integer year/month/day as an ISO date string. Month and day are\n * zero-padded to 2 digits to preserve lexicographic order.\n */\nfunction formatIsoDate(year: number, month: number, day: number): IsoDate {\n const mm = month < 10 ? `0${month}` : String(month);\n const dd = day < 10 ? `0${day}` : String(day);\n return `${year}-${mm}-${dd}`;\n}\n\n/**\n * Range split into per-calendar-year EXCLUSIVE-end chunks\n * (Jan 1 of next year).\n *\n * Properties:\n * - The first chunk's start is `max(date(start.year, 1, 1), start)` — i.e.\n * the caller's actual start for the first chunk, NOT Jan 1. The\n * `current = date(start.year, 1, 1)` initialization ensures the loop\n * visits every calendar-year boundary regardless of the caller's start.\n * - Every chunk's end is `date(year+1, 1, 1)` — the IEM `day2`-exclusive\n * convention for \"include all of `year`\".\n * - Leap-year safe: advance via `date(year+1, 1, 1)`, NOT `+365 days`.\n * - Reversed range (`start > end` by lexicographic compare) returns `[]`\n * without throwing — higher layers iterate the list directly.\n *\n * Byte-faithful with the Python helper used by `iem_asos.download_iem_asos`.\n */\nexport function yearlyChunksExclusiveEnd(\n start: IsoDate,\n end: IsoDate,\n): ReadonlyArray<readonly [IsoDate, IsoDate]> {\n // Reversed-range short-circuit (lexicographic compare is equivalent to\n // calendar compare for YYYY-MM-DD strings of identical shape). Mirrors\n // Python L66-67 (`if start > end: return []`).\n if (start > end) {\n return [];\n }\n\n const { year: startYear } = parseIsoDate(start);\n const { year: endYear } = parseIsoDate(end);\n\n const chunks: Array<readonly [IsoDate, IsoDate]> = [];\n // Match Python `current = date(start.year, 1, 1)` initialization.\n let currentYear = startYear;\n while (currentYear <= endYear) {\n const currentYearStart = formatIsoDate(currentYear, 1, 1);\n // Match Python `chunk_start = max(current, start)`. For the first\n // iteration this clamps to the caller's `start`; for subsequent\n // iterations `currentYearStart` is always greater.\n const chunkStart: IsoDate = currentYearStart > start ? currentYearStart : start;\n // CRITICAL: leap-year safe via calendar arithmetic, NOT `+365 days`.\n const nextYearFirst: IsoDate = formatIsoDate(currentYear + 1, 1, 1);\n chunks.push([chunkStart, nextYearFirst]);\n currentYear += 1;\n }\n return chunks;\n}\n","// IEM ASOS historical METAR fetcher — yearly-chunked CSV downloads.\n//\n// Byte-faithful TS port of Python\n// `packages/weather/src/mostlyright/weather/_fetchers/iem_asos.py::download_iem_asos`,\n// with the following deliberate adaptations:\n//\n// 1. No disk cache. Python writes per-station CSVs under\n// `dest_dir/{station}/iem_*.csv`; the TS port returns the CSV body\n// in-memory via `{ chunkStart, chunkEnd, csv }`. The disk-cache layer\n// (PERF-02 partial-namespace + cache-poisoning paths) lands in TS-W3 —\n// it's intentionally out of scope here. Drop ALL filename / `skip_cache`\n// / `today_utc` partial-namespace logic.\n// 2. Station validation at the URL boundary uses an inline regex\n// (`^[A-Z]{3,4}$`) matching `iem-cli.ts`'s `validateIcao` pattern. The\n// Python `validate_icao_for_path` from `_internal/_bounds.py` is a\n// path-traversal guard — there's no path here in TS-W2, so the regex\n// check is the equivalent defense-in-depth measure.\n//\n// URL shape, start-normalization (caller's `start` clamped to\n// `date(start.year, 1, 1)` for cache idempotence under per-month callers),\n// reversed-range short-circuit (`start > end → []`), report_type guard\n// ({3, 4}), and 1-sec polite delay are byte-faithful.\n//\n// CORS posture: OPEN — IEM emits `Access-Control-Allow-Origin: *` per\n// `.planning/research/TS-CORS-MATRIX.md` §IEM-ASOS. Works in browsers,\n// Node 20+, Cloudflare Workers, Deno.\n\nimport { fetchWithRetry } from \"@mostlyrightmd/core\";\nimport type { FetchWithRetryOptions } from \"@mostlyrightmd/core\";\n\nimport { type IsoDate, yearlyChunksExclusiveEnd } from \"./_iem_chunks.js\";\n\n/** IEM ASOS request endpoint. Mirrors Python `IEM_BASE_URL`. */\nexport const IEM_BASE_URL = \"https://mesonet.agron.iastate.edu/cgi-bin/request/asos.py\";\n\n/**\n * Polite delay (ms) between consecutive IEM HTTP requests. Mirrors Python\n * `IEM_POLITE_DELAY = 1.0` (s) — IEM runs on a university server and\n * documents a 1-sec/IP throttle (see .planning/research/SOURCE-LIMITS.md).\n */\nexport const IEM_POLITE_DELAY_MS = 1000;\n\n/**\n * Station code regex (3-4 uppercase letters). Mirrors the inline pattern\n * used by `iem-cli.ts::validateIcao` and the shared `STATION_CODE_RE` from\n * `@mostlyrightmd/core/internal/bounds`. Inlined here so the fetcher does not\n * transitively pull in the validators barrel — keeps the per-fetcher\n * dep graph narrow per the TS-W1 review pattern.\n */\nconst STATION_CODE_RE = /^[A-Z]{3,4}$/;\n\n/** Permitted IEM report_type values: 3 = METAR, 4 = SPECI. */\nconst VALID_REPORT_TYPES = new Set<number>([3, 4]);\n\n/**\n * One downloaded yearly chunk. The CSV body is forwarded verbatim from\n * the upstream response so the parser can run a downstream pass over it.\n */\nexport interface IemChunkResult {\n /** First day of this chunk's range (caller's start for chunk 0; Jan 1 for subsequent). */\n readonly chunkStart: IsoDate;\n /** EXCLUSIVE end of this chunk's range — Jan 1 of the following calendar year. */\n readonly chunkEnd: IsoDate;\n /** Raw CSV body returned by IEM (text/plain, comma-separated). */\n readonly csv: string;\n}\n\nexport interface DownloadIemAsosOptions extends FetchWithRetryOptions {\n /** `3` (METAR, default) or `4` (SPECI). */\n reportType?: 3 | 4;\n /**\n * Delay (ms) between successive chunk requests. Defaults to\n * {@link IEM_POLITE_DELAY_MS}. Set to `0` in unit tests.\n */\n politenessMs?: number;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction validateIcao(stationCode: string): void {\n if (typeof stationCode !== \"string\" || !STATION_CODE_RE.test(stationCode)) {\n throw new Error(\n `station_code=${JSON.stringify(\n stationCode,\n )} does not match STATION_CODE_RE (3-4 uppercase letters); refusing to use as URL component`,\n );\n }\n}\n\n/**\n * Build the IEM ASOS download URL for one (chunk, report_type) request.\n *\n * Param shape and ordering are byte-faithful to Python `_build_iem_url`:\n * station, data, tz, format, latlon, elev, missing, trace, direct,\n * report_type, year1, month1, day1, year2, month2, day2.\n *\n * Month/day are emitted WITHOUT zero-padding (Python uses bare `{start.month}`,\n * not `{start.month:02d}`) — preserve byte-equivalence on URL snapshots.\n *\n * `end` is the EXCLUSIVE end (already adjusted by the chunker to Jan 1 of\n * the following calendar year).\n */\nexport function buildIemUrl(\n stationCode: string,\n start: IsoDate,\n end: IsoDate,\n reportType: number,\n): string {\n // Parse ISO strings into ints (no Date — avoids local-TZ silent shifts).\n const [sy, sm, sd] = splitIso(start);\n const [ey, em, ed] = splitIso(end);\n const params = `station=${stationCode}&data=all&tz=Etc/UTC&format=comma&latlon=no&elev=no&missing=M&trace=T&direct=no&report_type=${reportType}&year1=${sy}&month1=${sm}&day1=${sd}&year2=${ey}&month2=${em}&day2=${ed}`;\n return `${IEM_BASE_URL}?${params}`;\n}\n\nfunction splitIso(iso: IsoDate): [number, number, number] {\n // The chunker has already validated; we just split.\n const parts = iso.split(\"-\");\n // Length-3 guaranteed if the chunker emitted this; defense in depth.\n if (parts.length !== 3) {\n throw new Error(`Invalid ISO date passed to buildIemUrl: ${JSON.stringify(iso)}`);\n }\n return [\n Number.parseInt(parts[0] as string, 10),\n Number.parseInt(parts[1] as string, 10),\n Number.parseInt(parts[2] as string, 10),\n ];\n}\n\n/**\n * Download yearly chunks of IEM ASOS data for one station, returning the\n * raw CSV bodies in chunker-natural order.\n *\n * The caller's inclusive `[start, end]` is normalized internally to\n * `[date(start.year, 1, 1), end]` and split into per-calendar-year\n * EXCLUSIVE-end chunks via {@link yearlyChunksExclusiveEnd}. Each chunk\n * fires one HTTP request to the IEM ASOS endpoint, with a polite delay\n * between successful responses (default {@link IEM_POLITE_DELAY_MS}).\n *\n * Errors propagate from `fetchWithRetry` — 4xx/5xx after retry exhaustion\n * are NOT swallowed (the IEM ASOS path is parity-critical; silent failure\n * would manifest as missing observation rows downstream).\n *\n * @throws If `reportType` is not `3` (METAR) or `4` (SPECI).\n * @throws If `stationCode` does not match `^[A-Z]{3,4}$` (path-traversal /\n * URL-injection defense).\n * @throws Whatever `fetchWithRetry` propagates on persistent network/HTTP\n * errors.\n */\nexport async function downloadIemAsos(\n stationCode: string,\n start: IsoDate,\n end: IsoDate,\n opts: DownloadIemAsosOptions = {},\n): Promise<ReadonlyArray<IemChunkResult>> {\n const reportType = opts.reportType ?? 3;\n if (!VALID_REPORT_TYPES.has(reportType)) {\n throw new Error(`report_type must be 3 (METAR) or 4 (SPECI), got ${reportType}`);\n }\n // Defense-in-depth: validate at the URL boundary BEFORE any HTTP.\n validateIcao(stationCode);\n\n // Reversed-range guard. Mirror Python L201-202: the chunker honors\n // `start > end → []`, but defensive short-circuit here avoids ever\n // computing the normalized year boundary for a malformed call.\n if (start > end) {\n return [];\n }\n\n // mostlyright-specific normalization: clamp caller's `start` to Jan 1 of\n // its year so per-month callers share a yearly cache key (parity-faithful\n // with Python's `normalized_start = date(start.year, 1, 1)`). Mirrored in\n // TS so the URL shape (and the future TS-W3 cache key) stays byte-stable\n // with Python on the same range.\n const normalizedStart: IsoDate = `${start.slice(0, 4)}-01-01`;\n const chunks = yearlyChunksExclusiveEnd(normalizedStart, end);\n\n const politenessMs = opts.politenessMs ?? IEM_POLITE_DELAY_MS;\n // Strip fetcher-specific opts from the bag forwarded to fetchWithRetry.\n const { reportType: _rtDrop, politenessMs: _pmDrop, ...fetchOpts } = opts;\n void _rtDrop;\n void _pmDrop;\n\n const out: IemChunkResult[] = [];\n for (const [chunkStart, chunkEnd] of chunks) {\n const url = buildIemUrl(stationCode, chunkStart, chunkEnd, reportType);\n const response = await fetchWithRetry(url, fetchOpts);\n const csv = await response.text();\n out.push({ chunkStart, chunkEnd, csv });\n // Polite delay AFTER each successful round-trip (mirror Python L224\n // which sleeps unconditionally). Skipping the trailing sleep on the\n // last chunk would be a micro-optimization not present in Python.\n if (politenessMs > 0) {\n await sleep(politenessMs);\n }\n }\n return out;\n}\n"],"mappings":"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","names":[]}
@@ -3,8 +3,8 @@ import {
3
3
  IEM_POLITE_DELAY_MS,
4
4
  buildIemUrl,
5
5
  downloadIemAsos
6
- } from "./chunk-64FNXDHG.mjs";
7
- import "./chunk-WKPNA46C.mjs";
6
+ } from "./chunk-TT6J2BKH.mjs";
7
+ import "./chunk-7XWX6QZG.mjs";
8
8
  import "./chunk-J5LGTIGS.mjs";
9
9
  export {
10
10
  IEM_BASE_URL,
@@ -12,4 +12,4 @@ export {
12
12
  buildIemUrl,
13
13
  downloadIemAsos
14
14
  };
15
- //# sourceMappingURL=iem-asos-2D5EP2FT.mjs.map
15
+ //# sourceMappingURL=iem-asos-OLJNQPEM.mjs.map