144 lines
4.9 KiB
Markdown
144 lines
4.9 KiB
Markdown
# Presenters and Templates
|
|
|
|
This document describes payload shaping in
|
|
`internal/adapters/inbound/httpapi/presenter` and its relationship to text
|
|
templates. Public response fields are documented in [`docs/api.md`](../api.md).
|
|
|
|
## Purpose
|
|
|
|
Presenters translate repository/application read models into response-ready
|
|
payloads. They own unit conversion, numeric rounding, timezone conversion,
|
|
optional field preservation, and copy semantics.
|
|
|
|
## Inputs and Outputs
|
|
|
|
Inputs:
|
|
|
|
- weatherfeeder model values returned by the repository;
|
|
- `app.CurrentConditions` values returned by the application service;
|
|
- requested unit mode;
|
|
- requested precision;
|
|
- optional timezone location.
|
|
|
|
Outputs:
|
|
|
|
- JSON/XML/text-ready payload structs or canonical model copies;
|
|
- nil payloads for nil inputs.
|
|
|
|
## Boundaries
|
|
|
|
Presenters may:
|
|
|
|
- convert metric values to US-customary response fields;
|
|
- round numeric values that are presentation values;
|
|
- convert timestamps to a requested timezone;
|
|
- copy slices and pointers before changing presentation values;
|
|
- add template-only helper fields when they are not serialized.
|
|
|
|
Presenters must not:
|
|
|
|
- execute SQL;
|
|
- call services or repositories;
|
|
- parse HTTP query parameters;
|
|
- load templates;
|
|
- change canonical repository models in place.
|
|
|
|
## Config Fields Used
|
|
|
|
Presenters do not read config directly. They receive unit, precision, and
|
|
timezone selections from HTTP binders. Text output depends indirectly on
|
|
`templates.base_dir` because feedapi loads templates from that configured
|
|
directory.
|
|
|
|
## External Adapters Used
|
|
|
|
- `weatherfeeder/model` for canonical weather payloads.
|
|
- `weatherfeeder/standards` for current-condition text from WMO codes.
|
|
- `internal/app` for the current-conditions read model.
|
|
- Feedapi templates indirectly consume presenter output during text rendering.
|
|
|
|
## State
|
|
|
|
Presenters are stateless. Helper functions allocate copied values and return
|
|
new payloads for each request.
|
|
|
|
## Unit Conversion
|
|
|
|
Metric mode generally returns weatherfeeder canonical model shapes or
|
|
metric-named fields. US mode uses explicit US response structs for observations
|
|
and forecasts and US-specific fields in current conditions.
|
|
|
|
Conversion constants live in `constants.go`:
|
|
|
|
- Celsius to Fahrenheit;
|
|
- kilometers per hour to miles per hour;
|
|
- meters to miles or feet;
|
|
- pascals to inches of mercury;
|
|
- millimeters to inches.
|
|
|
|
Non-unit fields such as percentages, directions, text, IDs, and ordering values
|
|
keep their existing values.
|
|
|
|
## Precision
|
|
|
|
`roundedPtr` and `roundFloat` round numeric presentation values. Precision `0`
|
|
rounds to whole numbers. Positive precision uses powers of ten. Nil numeric
|
|
pointers remain nil.
|
|
|
|
Latitude and longitude are copied but not rounded by forecast presenters.
|
|
|
|
## Timezone Conversion
|
|
|
|
`inLocationTime` and `inLocationTimePtr` convert timestamps only when a
|
|
timezone is supplied. Without a timezone, timestamps are preserved as returned
|
|
by the repository.
|
|
|
|
Timezone conversion is applied by forecast, discussion, and weather story
|
|
presenters. Observations and current conditions do not currently receive
|
|
timezone input from their routes.
|
|
|
|
## Optional Fields and Copy Semantics
|
|
|
|
Presenter helpers copy pointer values before changing them. Slices are copied
|
|
before inclusion where needed. This preserves nil/omitempty behavior and avoids
|
|
mutating repository-returned values.
|
|
|
|
Nil input payloads return nil. Endpoint handlers wrap those nil payloads in a
|
|
response envelope so renderers can produce `data: null`.
|
|
|
|
## Endpoint Families
|
|
|
|
- Observations: metric copy or US response shape, including present-weather
|
|
slice copy.
|
|
- Current conditions: single response shape with either metric or US unit
|
|
fields populated, plus a template-only day/night text helper.
|
|
- Alerts: pass-through of canonical alert runs, with nil preserved.
|
|
- Forecasts: metric copy or US response shape, period copy, unit conversion,
|
|
precision, and timezone conversion.
|
|
- Discussions: full or focused payload shapes, section copy, key-message copy,
|
|
timezone conversion.
|
|
- Weather stories: run/story copy and timezone conversion.
|
|
|
|
## Templates
|
|
|
|
Text templates consume the same envelope data produced by presenters. Template
|
|
files live under `templates/` and are loaded by feedapi from `templates.base_dir`.
|
|
|
|
Presenter changes can break text output even when JSON and XML still compile.
|
|
Check template field references before renaming or removing presenter fields.
|
|
|
|
## Tests to Inspect Before Changing
|
|
|
|
- `internal/adapters/inbound/httpapi/presenter/payload_test.go`
|
|
- `internal/adapters/inbound/httpapi/endpoints_test.go` for rendered text and
|
|
envelope behavior
|
|
- affected template files under `templates/`
|
|
|
|
## Invariants
|
|
|
|
- Keep unit conversion and rounding out of handlers and repositories.
|
|
- Preserve nil pointer and optional field behavior.
|
|
- Copy before converting, rounding, or timezone-shifting values.
|
|
- Keep text-template helper fields out of JSON/XML when they are not API fields.
|
|
- Update `docs/api.md` and templates when payload shape changes.
|