first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
# provider
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Adapts the three tide-prediction backends — TICON-style harmonic constituents, the ADMIRALTY HTTP API, and the equilibrium-tide physics model — to the universal `TidalProvider` shape from `@suaveplan/types`. Every factory returns a pair of methods (`predictHeight`, `getExtremes`) that accept a `PlanetConfig`, a `SphericalCoord`, and a `Date`, so callers can swap backends without changing call sites or domain logic. This is the recommended entry point for any consumer that doesn't need the lower-level station-rooted `AdmiraltyProvider` API.
## Features
- `createTiconProvider(constituents, meanSeaLevel?)` — pure, offline, deterministic. Wraps `predictHeight`/`findExtremes` from `@suaveplan/tides/harmonic`.
- `createAdmiraltyProvider(options)` — async, network-bound. Routes via `getNearestStation` so callers can pass any UK coordinate.
- `createPhysicsBasedProvider()` — zero-config, no network, no constituents. Equilibrium-tide model from `@suaveplan/tides` `physics`.
- All three return objects matching `TidalProvider` from `@suaveplan/types`, so they compose with anything in the universe stack expecting that contract.
- AbortSignal is forwarded for the ADMIRALTY adapter; ignored for the deterministic backends.
## Usage: Basic Example
```ts
import { createTiconProvider } from "@suaveplan/tides";
const provider = createTiconProvider([
{ name: "M2", amplitude: 1.0, phase: 0, speed: 28.984104 },
]);
const earth = { name: "Earth", radius: 6_371_000, rotationPeriod: 86_164 };
const height = await provider.predictHeight(
earth,
{ latitude: 51.5074, longitude: -0.1278 },
new Date("2024-06-15T12:00:00Z")
);
```
## Usage: Advanced Example
```ts
import {
createAdmiraltyProvider,
createPhysicsBasedProvider,
createTiconProvider,
} from "@suaveplan/tides";
import type { TidalProvider } from "@suaveplan/types";
function pickProvider(input: {
apiKey?: string;
constituents?: Parameters<typeof createTiconProvider>[0];
}): TidalProvider {
if (input.constituents?.length)
return createTiconProvider(input.constituents);
if (input.apiKey) return createAdmiraltyProvider({ apiKey: input.apiKey });
return createPhysicsBasedProvider();
}
```
## API Reference
- `createTiconProvider(constituents: readonly HarmonicConstituent[], meanSeaLevel?: number): TidalProvider`.
- `createAdmiraltyProvider(options: AdmiraltyProviderOptions): TidalProvider` — internally wraps a station-rooted `AdmiraltyProvider`.
- `createPhysicsBasedProvider(): TidalProvider`.
- Each `TidalProvider` exposes:
- `predictHeight(planet, coord, time, signal?): Promise<number>`.
- `getExtremes(planet, coord, date, signal?): Promise<TideExtreme[]>`.
## Implementation Notes
The `_planet` parameter is currently unused by every backend — it is preserved on the contract so future backends (e.g. Mars or exoplanet equilibrium tide models) can vary behaviour without breaking call sites. The ADMIRALTY adapter performs an extra `getNearestStation` round-trip per call; for batch workloads, consider hoisting that to once-per-coord and operating on the station-rooted `AdmiraltyProvider` API directly to amortise it. The TICON and physics adapters are synchronous internally but return Promises to satisfy the universal contract — they never reject and never await, so `await` is essentially zero-cost. `getExtremes` for the TICON adapter scans the full UTC day containing `date` (`startOfDay → +24h`) regardless of the time-of-day component on the input.