12 Commits

Author SHA1 Message Date
123e8ff763 Moved the standards package out of internal/ so it can be imported by downstream consumers.
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful
2026-02-08 09:15:07 -06:00
00e811f8f7 normalizers/nws: add NWS alerts normalizer and canonical alert mapping
- Introduce AlertsNormalizer to convert Raw NWS Alerts (SchemaRawNWSAlertsV1)
  into canonical WeatherAlert runs (SchemaWeatherAlertV1)
- Add minimal NWS alerts response/types to support GeoJSON FeatureCollection parsing
- Map NWS alert properties (event, headline, severity, timing, area, references)
  into model.WeatherAlert with best-effort timestamp handling
- Establish clear AsOf / EffectiveAt policy for alert runs to support stable
  deduplication and snapshot semantics
- Register the new alerts normalizer alongside existing NWS observation and
  forecast normalizers
2026-01-16 21:40:20 -06:00
2eb2d4b90f feat(nws, normalizers): add NWS hourly forecast normalization and enforce canonical float rounding
- Implement full NWS hourly forecast normalizer (raw.nws.hourly.forecast.v1 → weather.forecast.v1)
- Add GeoJSON forecast types and helpers for NWS gridpoint hourly payloads
- Normalize temperatures, winds, humidity, PoP, and infer WMO condition codes from forecast text/icons
- Treat forecast IssuedAt as EffectiveAt for stable, dedupe-friendly event IDs

- Introduce project-wide float rounding at normalization finalization
  - Round all float values in canonical payloads to 2 decimal places
  - Apply consistently across pointers, slices, maps, and nested structs
  - Preserve opaque structs (e.g., time.Time) unchanged

- Add SchemaRawNWSHourlyForecastV1 and align schema matching/comments
- Clean up NWS helper organization and comments
- Update documentation to reflect numeric wire-format and normalization policies

This establishes a complete, deterministic hourly forecast pipeline for NWS
and improves JSON output stability across all canonical weather schemas.
2026-01-16 10:28:32 -06:00
0fcc536885 Updates in preparation for adding forecast sources. 2026-01-16 00:04:37 -06:00
f13f43cf56 refactor(providers): centralize provider-specific parsing and invariants
- Introduce internal/providers/nws with shared timestamp parsing used by both
  NWS sources and normalizers
- Migrate NWS observation source + normalizer to use the shared provider helper
  for consistent RFC3339/RFC3339Nano handling
- Introduce internal/providers/openweather with a shared URL invariant helper
  enforcing units=metric
- Remove duplicated OpenWeather URL validation logic from the observation source
- Align provider layering: move provider “contract/quirk” logic out of
  normalizers and into internal/providers
- Update normalizer and standards documentation to clearly distinguish:
  provider helpers (internal/providers) vs canonical mapping logic
  (internal/normalizers)

This refactor reduces duplication between sources and normalizers, clarifies
layering boundaries, and establishes a scalable pattern for future forecast
and alert implementations.
2026-01-15 20:40:53 -06:00
d8db58c004 sources: standardize Event.ID on Source:EffectiveAt; simplify raw event helper
- Adopt an opinionated Event.ID policy across sources:
  - use upstream-provided ID when available
  - otherwise derive a stable ID from Source:EffectiveAt (RFC3339Nano, UTC)
  - fall back to Source:EmittedAt when EffectiveAt is unavailable
- Add common/id helper to centralize ID selection logic and keep sources consistent
- Simplify common event construction by collapsing SingleRawEventAt/SingleRawEvent
  into a single explicit SingleRawEvent helper (emittedAt passed in)
- Update NWS/Open-Meteo/OpenWeather observation sources to:
  - compute EffectiveAt first
  - generate IDs via the shared helper
  - build envelopes via the unified SingleRawEvent helper
- Improve determinism and dedupe-friendliness without changing schemas or payloads
2026-01-15 19:38:15 -06:00
d9474b5a5b v0.x: add reusable HTTP source spine; fix routing; upstream HTTP transport helper
- fix dispatch route compilation so empty Kinds matches all (nil), not none
- introduce internal/sources/common/HTTPSource to centralize HTTP polling boilerplate:
  - standard cfg parsing (url + user_agent)
  - default HTTP client + Accept/User-Agent headers
  - consistent error wrapping
- refactor observation sources (nws/openmeteo/openweather) to use HTTPSource
- upstream generic HTTP fetch/limits/timeout helper from weatherfeeder to feedkit:
  - move internal/sources/common/http.go -> feedkit/transport/http.go
  - keep behavior: status checks, max-body limit, default timeout
2026-01-15 19:11:58 -06:00
e92577c30e Moved shared OpenMeteo time parsing code into a shared internal/providers/openmeteo library. 2026-01-15 10:17:56 -06:00
59111a1c82 sources: standardize HTTP source config + factor raw-event boilerplate
- Require params.user_agent for all HTTP sources (uniform config across providers)
- Add common.RequireHTTPSourceConfig() to validate name/url/user_agent in one call
- Add common.NewHTTPClient() with DefaultHTTPTimeout for consistent client setup
- Add common.SingleRawEvent() to centralize event envelope construction + validation
- Refactor NWS/Open-Meteo/OpenWeather observation sources to use new helpers
2026-01-15 09:43:22 -06:00
e28ff49201 Moved common HTTP body fetch code into a shared helper function. 2026-01-15 08:58:56 -06:00
0ba2602bcc nws: refactored the NWS source files to relocate normalization logic to internal/normalizers. 2026-01-14 11:18:21 -06:00
aa4774e0dd weatherfeeder: split the former maximumdirect.net/weatherd project in two.
feedkit now contains a reusable core, while weatherfeeder is a concrete implementation that includes weather-specific functions.
2026-01-13 18:14:21 -06:00