5.3 KiB
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.
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.CurrentConditionsvalues 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/modelfor canonical weather payloads.weatherfeeder/standardsfor current-condition text from WMO codes.internal/appfor 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, weather story, and outlook 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.
- Convective outlooks: canonical model copy, pointer and geometry copy,
run-level discussion copy, and timezone conversion for run, outlook, and
discussion timestamps. Outlook polygon prose is not handled by the presenter;
prose is carried by run-level discussions.
unitsis accepted by routes but ignored by the presenter because outlook fields are not unit-bearing.
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.gointernal/adapters/inbound/httpapi/endpoints_test.gofor 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.mdand templates when payload shape changes.