Clean and update documentation
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful
This commit is contained in:
92
docs/consumers/api.md
Normal file
92
docs/consumers/api.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Consumer API Guide
|
||||
|
||||
## Purpose
|
||||
|
||||
This guide is for developers and LLM coding agents integrating `weatherfeeder`
|
||||
from another Go codebase.
|
||||
|
||||
`weatherfeeder` is primarily a daemon, not an SDK. Its public integration
|
||||
surface is intentionally narrow:
|
||||
|
||||
- `model`: canonical weather payload structs.
|
||||
- `standards`: schema strings, event kind strings, and shared WMO constants.
|
||||
- JSON event output from stdout and NATS sinks.
|
||||
- Postgres tables written by the optional Postgres sink.
|
||||
|
||||
Packages under `internal/` are implementation details and are not public
|
||||
integration surfaces.
|
||||
|
||||
## Recommended Workflow
|
||||
|
||||
Consumers should switch on the event `schema` value and decode `payload` into
|
||||
the matching `model` type.
|
||||
|
||||
Minimal example:
|
||||
|
||||
```go
|
||||
package consumer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"gitea.maximumdirect.net/ejr/weatherfeeder/model"
|
||||
"gitea.maximumdirect.net/ejr/weatherfeeder/standards"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
ID string `json:"id"`
|
||||
Kind string `json:"kind"`
|
||||
Schema string `json:"schema"`
|
||||
Payload json.RawMessage `json:"payload"`
|
||||
}
|
||||
|
||||
func Decode(payload []byte) (any, error) {
|
||||
var evt Event
|
||||
if err := json.Unmarshal(payload, &evt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch evt.Schema {
|
||||
case standards.SchemaWeatherObservationV1:
|
||||
var out model.WeatherObservation
|
||||
return &out, json.Unmarshal(evt.Payload, &out)
|
||||
case standards.SchemaWeatherForecastV1:
|
||||
var out model.WeatherForecastRun
|
||||
return &out, json.Unmarshal(evt.Payload, &out)
|
||||
case standards.SchemaWeatherForecastDiscussionV1:
|
||||
var out model.WeatherForecastDiscussion
|
||||
return &out, json.Unmarshal(evt.Payload, &out)
|
||||
case standards.SchemaWeatherStoryV1:
|
||||
var out model.WeatherStoryRun
|
||||
return &out, json.Unmarshal(evt.Payload, &out)
|
||||
case standards.SchemaWeatherAlertV1:
|
||||
var out model.WeatherAlertRun
|
||||
return &out, json.Unmarshal(evt.Payload, &out)
|
||||
case standards.SchemaWeatherOutlookV1:
|
||||
var out model.WeatherOutlookRun
|
||||
return &out, json.Unmarshal(evt.Payload, &out)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported weatherfeeder schema %q", evt.Schema)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Consumer Responsibilities
|
||||
|
||||
- Treat event IDs as opaque.
|
||||
- Treat absent `omitempty` fields as unknown, not zero.
|
||||
- Prefer schema constants from `standards` over string literals in Go code.
|
||||
- Expect canonical numeric measurements to use metric units.
|
||||
- Expect canonical timestamps from normalizers to be UTC unless a field-specific
|
||||
contract says otherwise.
|
||||
- Handle additive fields within the same schema version.
|
||||
- Do not import `internal/...` packages.
|
||||
|
||||
## Canonical References
|
||||
|
||||
- Public payload package: [`pkg-model.md`](pkg-model.md).
|
||||
- Public constants package: [`pkg-standards.md`](pkg-standards.md).
|
||||
- JSON event wire contract: [`../integrations/events.md`](../integrations/events.md).
|
||||
- Postgres table contract: [`../integrations/postgres.md`](../integrations/postgres.md).
|
||||
- Runtime and adapter architecture: [`../policy/architecture.md`](../policy/architecture.md).
|
||||
63
docs/consumers/pkg-model.md
Normal file
63
docs/consumers/pkg-model.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Package `model`
|
||||
|
||||
## Import Path
|
||||
|
||||
```go
|
||||
import "gitea.maximumdirect.net/ejr/weatherfeeder/model"
|
||||
```
|
||||
|
||||
## Purpose
|
||||
|
||||
Package `model` defines `weatherfeeder`'s canonical weather payload structs.
|
||||
These structs are emitted as the `payload` of canonical `weather.*.v1` events
|
||||
and are also the domain types consumed by downstream applications such as
|
||||
`weatherapi`.
|
||||
|
||||
The JSON field tags on these structs are part of the wire contract. For the full
|
||||
field-by-field JSON contract, use the [event wire contract](../integrations/events.md).
|
||||
|
||||
## Payload Types
|
||||
|
||||
Current canonical schema families map to these public types:
|
||||
|
||||
| Schema | Primary type |
|
||||
|---|---|
|
||||
| `weather.observation.v1` | `WeatherObservation` |
|
||||
| `weather.forecast.v1` | `WeatherForecastRun` |
|
||||
| `weather.forecast_discussion.v1` | `WeatherForecastDiscussion` |
|
||||
| `weather.weather_story.v1` | `WeatherStoryRun` |
|
||||
| `weather.alert.v1` | `WeatherAlertRun` |
|
||||
| `weather.outlook.v1` | `WeatherOutlookRun` |
|
||||
|
||||
Related child types include:
|
||||
|
||||
- `WeatherObservationPresentWeather`
|
||||
- `WeatherForecastPeriod`
|
||||
- `WeatherForecastDiscussionSection`
|
||||
- `WeatherStory`
|
||||
- `WeatherAlert`
|
||||
- `WeatherAlertReference`
|
||||
- `WeatherOutlook`
|
||||
- `WMOCode`
|
||||
|
||||
## Wire And Compatibility Rules
|
||||
|
||||
- JSON tags define canonical payload field names.
|
||||
- Pointer fields and fields tagged `omitempty` are optional on the wire.
|
||||
- Missing optional fields mean unknown or not applicable.
|
||||
- Canonical measurements use metric units.
|
||||
- Canonical timestamps are `time.Time` values encoded by Go's JSON encoder.
|
||||
- Normalized canonical timestamps are UTC unless a field-specific contract says
|
||||
otherwise.
|
||||
- Additive fields are compatible within a schema version.
|
||||
- Removing, renaming, or changing the meaning of a field requires a new schema
|
||||
identifier.
|
||||
|
||||
## Boundaries
|
||||
|
||||
`model` should not depend on source adapters, sinks, SQL column names, provider
|
||||
HTTP shapes, or runtime configuration.
|
||||
|
||||
Consumers should not rely on packages under `internal/...`. Use `model` with
|
||||
schema constants from [`standards`](pkg-standards.md) and the JSON contract in
|
||||
[`docs/integrations/events.md`](../integrations/events.md).
|
||||
90
docs/consumers/pkg-standards.md
Normal file
90
docs/consumers/pkg-standards.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Package `standards`
|
||||
|
||||
## Import Path
|
||||
|
||||
```go
|
||||
import "gitea.maximumdirect.net/ejr/weatherfeeder/standards"
|
||||
```
|
||||
|
||||
## Purpose
|
||||
|
||||
Package `standards` defines stable identifiers and shared weather constants used
|
||||
by `weatherfeeder` producers and Go consumers.
|
||||
|
||||
Use this package when switching on event schemas, comparing event kinds, or
|
||||
working with canonical WMO condition codes.
|
||||
|
||||
## Event Kind Constants
|
||||
|
||||
Current event kind constants are:
|
||||
|
||||
| Constant | Value |
|
||||
|---|---|
|
||||
| `KindObservation` | `observation` |
|
||||
| `KindForecast` | `forecast` |
|
||||
| `KindForecastDiscussion` | `forecast_discussion` |
|
||||
| `KindWeatherStory` | `weather_story` |
|
||||
| `KindAlert` | `alert` |
|
||||
| `KindOutlook` | `outlook` |
|
||||
|
||||
These are plain string constants. Convert them at adapter boundaries when using
|
||||
feedkit's `event.Kind` type.
|
||||
|
||||
## Canonical Schema Constants
|
||||
|
||||
Canonical schemas emitted after normalization:
|
||||
|
||||
| Constant | Value |
|
||||
|---|---|
|
||||
| `SchemaWeatherObservationV1` | `weather.observation.v1` |
|
||||
| `SchemaWeatherForecastV1` | `weather.forecast.v1` |
|
||||
| `SchemaWeatherForecastDiscussionV1` | `weather.forecast_discussion.v1` |
|
||||
| `SchemaWeatherStoryV1` | `weather.weather_story.v1` |
|
||||
| `SchemaWeatherAlertV1` | `weather.alert.v1` |
|
||||
| `SchemaWeatherOutlookV1` | `weather.outlook.v1` |
|
||||
|
||||
## Raw Schema Constants
|
||||
|
||||
Raw source schemas emitted by current registered sources:
|
||||
|
||||
| Constant | Value |
|
||||
|---|---|
|
||||
| `SchemaRawNWSObservationV1` | `raw.nws.observation.v1` |
|
||||
| `SchemaRawOpenMeteoCurrentV1` | `raw.openmeteo.current.v1` |
|
||||
| `SchemaRawOpenWeatherCurrentV1` | `raw.openweather.current.v1` |
|
||||
| `SchemaRawNWSHourlyForecastV1` | `raw.nws.hourly.forecast.v1` |
|
||||
| `SchemaRawNWSNarrativeForecastV1` | `raw.nws.narrative.forecast.v1` |
|
||||
| `SchemaRawNWSForecastDiscussionV1` | `raw.nws.forecast_discussion.v1` |
|
||||
| `SchemaRawNWSWeatherStoriesV1` | `raw.nws.weatherstories.v1` |
|
||||
| `SchemaRawOpenMeteoHourlyForecastV1` | `raw.openmeteo.hourly.forecast.v1` |
|
||||
| `SchemaRawNWSAlertsV1` | `raw.nws.alerts.v1` |
|
||||
| `SchemaRawSPCConvectiveOutlookV1` | `raw.spc.convective_outlook.v1` |
|
||||
|
||||
Additional raw schema constant:
|
||||
|
||||
| Constant | Value |
|
||||
|---|---|
|
||||
| `SchemaRawOpenWeatherHourlyForecastV1` | `raw.openweather.hourly.forecast.v1` |
|
||||
|
||||
`SchemaRawOpenWeatherHourlyForecastV1` exists in code, but no current registered
|
||||
source emits it. Consumers should not expect that raw schema unless a later
|
||||
registered source documents it as part of the current event contract.
|
||||
|
||||
## WMO Constants And Text
|
||||
|
||||
`standards` also defines the canonical `WMOCode` vocabulary and text helpers
|
||||
used by normalized observations and forecasts.
|
||||
|
||||
Consumer guidance:
|
||||
|
||||
- Treat `WMOUnknown` as unknown condition data.
|
||||
- Observation `conditionCode` is required in the current event contract.
|
||||
- Forecast period `conditionCode` is optional because some forecast products do
|
||||
not provide a meaningful WMO condition.
|
||||
- Prefer WMO constants and helper functions from this package instead of
|
||||
duplicating code tables in consumers.
|
||||
|
||||
## Boundaries
|
||||
|
||||
`standards` is provider-agnostic. Provider-specific parsing belongs in
|
||||
`weatherfeeder` internals, not in this package and not in consumers.
|
||||
Reference in New Issue
Block a user