4.0 KiB
@suaveplan/tides — Tidal Prediction Capability
Universal-tier tidal prediction surface exposing the unified TidalProvider
contract from @suaveplan/types, three concrete provider factories
(harmonic / equilibrium-physics / ADMIRALTY API), harmonic-constituent math
with nodal corrections, equilibrium-tide physics, and tide-station search.
Requirements
Requirement: Harmonic prediction engine
The package SHALL expose predictHeight(constituents, time, meanSeaLevel?)
and findExtremes(constituents, from, to, meanSeaLevel?) computing tide
height per the harmonic formula h(t) = H₀ + Σ f(t)·Hₙ·cos(ωₙ·t + V₀ₙ(t) − Gₙ)
using the J2000 epoch (2000-01-01T12:00:00Z) as the time base.
Scenario: Empty constituent list rejected
- WHEN
predictHeight([], time)is called with zero constituents - THEN it MUST throw
TideErrorwith codeNO_CONSTITUENTS.
Scenario: Nodal corrections applied
- WHEN
predictHeightruns over named constituents (M2, S2, K1, …) - THEN the per-constituent node factor
fand astronomical argumentV₀MUST be derived from the time argument vianodeFactor(name, time)/astronomicalArgument(name, time)rather than treated as static.
Requirement: Harmonic-constituent registry
The package SHALL ship CONSTITUENT_SPEEDS (degrees/hour angular speeds)
and DOODSON_NUMBERS tables for the canonical major constituents
(M2, S2, N2, K2, K1, O1, P1, Q1, M4, …) re-exported from
./harmonic/harmonic-constituents.
Requirement: Equilibrium-tide physics
The package SHALL expose equilibriumTideHeight(planet, coord, time) and
findEquilibriumExtremes(planet, coord, date, signal?) modelling the
solid-body equilibrium tide on a PlanetConfig ellipsoid (consumes
@suaveplan/geo-planet).
Requirement: ADMIRALTY UK Hydrographic Office client
The package SHALL expose AdmiraltyProvider and createAdmiraltyProvider
binding the ADMIRALTY UK Tidal API
(https://admiraltyapi.azure-api.net/uktidalapi/api/V1) with:
Ocp-Apim-Subscription-Keyheader taken from constructor optionapiKey.- Injectable
fetchFn(defaults toglobalThis.fetch). - Configurable
cacheTtlMs(default3_600_000).
Scenario: ADMIRALTY API key absent
- WHEN
createAdmiraltyProvider({ apiKey: "" })is called - THEN the resulting provider MUST throw
TideError(MISSING_API_KEY) on first network call.
Requirement: Provider factory surface
The package SHALL expose three factories returning the unified
TidalProvider shape from @suaveplan/types:
createTiconProvider(constituents, meanSeaLevel?)— offline harmonic.createPhysicsBasedProvider(planet)— equilibrium-tide approximation.createAdmiraltyProvider(options)— ADMIRALTY UK API.
All three MUST satisfy predictHeight(planet, coord, time) and
getExtremes(planet, coord, date, signal?).
Requirement: Tide-station search
The package SHALL expose findNearestStation(stations, latitude, longitude)
returning NearestStationResult with great-circle distanceKm computed
via @suaveplan/geo haversine math.
Requirement: Typed error surface
The package SHALL expose a frozen TideError class with stable codes
covering NO_CONSTITUENTS, MISSING_API_KEY, STATION_NOT_FOUND, and
network/parse failure paths surfaced by the ADMIRALTY provider.
Requirement: AbortSignal threading
Every async provider call (predictHeight, getExtremes,
getNearestStation, getStations) SHALL accept and honour an optional
AbortSignal, aborting in-flight ADMIRALTY HTTP requests via the underlying
fetchFn.
Requirement: Universal-tier purity
The package MUST NOT import browser-only or Node-only APIs at module top
level — fetch is consumed only through the injectable fetchFn so the
package runs unchanged in browser, Bun, and Node environments.
Requirement: Test + coverage gates
bunx turbo lint typecheck test --filter=@suaveplan/tides MUST be green
and bunx turbo test:coverage --filter=@suaveplan/tides MUST hit 100%
on touched modules before any release.