Skip to content

@mostlyrightmd/core/discovery

Compatibility subclass of DataAvailabilityError raised by dailySummaryGaps. Existing catch (e instanceof DailySummaryGapsNotImplementedError) sites keep working; new code should catch the parent class DataAvailabilityError and dispatch on reason === "model_unavailable".

Prefer catching DataAvailabilityError directly.

new DailySummaryGapsNotImplementedError(): DailySummaryGapsNotImplementedError

DailySummaryGapsNotImplementedError

DataAvailabilityError.constructor

readonly static defaultErrorCode: "DATA_AVAILABILITY" = "DATA_AVAILABILITY"

Subclass override — the stable string enum surfaced via errorCode.

DataAvailabilityError.defaultErrorCode

readonly errorCode: string

DataAvailabilityError.errorCode

readonly hint: string

DataAvailabilityError.hint

readonly reason: "model_unavailable" | "out_of_window" | "cache_miss" | "source_404" | "source_5xx" | "rate_limited"

DataAvailabilityError.reason

readonly requestId: null | string

DataAvailabilityError.requestId

readonly source: null | string

DataAvailabilityError.source

toDict(): Record<string, unknown>

Return a JSON-safe dict suitable for MCP error.data.

Record<string, unknown>

DataAvailabilityError.toDict


Thrown by describe when schemaId is not registered.

new UnknownSchemaError(message): UnknownSchemaError

string

UnknownSchemaError

MostlyrightError.constructor

readonly static defaultErrorCode: "UNKNOWN_SCHEMA" = "UNKNOWN_SCHEMA"

Subclass override — the stable string enum surfaced via errorCode.

MostlyrightError.defaultErrorCode

readonly errorCode: string

MostlyrightError.errorCode

readonly requestId: null | string

MostlyrightError.requestId

readonly source: null | string

MostlyrightError.source

toDict(): Record<string, unknown>

Return a JSON-safe dict suitable for MCP error.data.

Record<string, unknown>

MostlyrightError.toDict

Options for availability().

readonly optional validate: boolean

If true, confirm each candidate key with cache.get() before counting. Eliminates the small overcount possible on stores whose listKeys() can return keys with already-expired TTL entries (FsStore and IndexedDBStore lazy-evict on get, not on listKeys). Off by default because the v0.1.0 research() flow never writes with ttlMs, so the overcount window is empty; turn on only if you populate the cache with explicit TTLs.

Cost: one get() per matching key. On warm caches this is cheap (MemoryStore + IndexedDBStore in-memory). On FsStore it reads each candidate’s file.


Cache-coverage summary for a station.

Mirrors Python availability() return shape.

dailySummaryYears: number

Count of cached daily-summary years.

firstDailySummaryYear: null | string

Earliest cached daily-summary year as "YYYY", or null if none.

firstMonth: null | string

Earliest cached month as "YYYY-MM", or null if none.

lastDailySummaryYear: null | string

Latest cached daily-summary year as "YYYY", or null if none.

lastMonth: null | string

Latest cached month as "YYYY-MM", or null if none.

monthsCached: number

Count of distinct (year, month) observation cache entries.

station: string


optional dataVersion: null | DataVersion

optional knowledgeTime: string | Date

optional metadata: Record<string, unknown>

rows: readonly Record<string, unknown>[]

schemaId: string

source: string


localDate: string

Station-local calendar date as YYYY-MM-DD.

nObs: number

Count of rows with a parseable temp_c.

precipMm: number

Total 1-hour precipitation across the local day, in mm.

sourceTmax: null | string

Source identifier of the row that produced tmax (or null on low coverage).

sourceTmin: null | string

Source identifier of the row that produced tmin (or null on low coverage).

tempMaxC: null | number

Max temperature in °C, or null on low coverage.

tempMaxF: null | number

Max temperature in °F, or null on low coverage.

tempMeanC: null | number

Mean temperature in °C, or null on low coverage.

tempMinC: null | number

Min temperature in °C, or null on low coverage.

tempMinF: null | number

Min temperature in °F, or null on low coverage.


Frozen snapshot wrapper around row data + provenance.

readonly dataVersion: null | DataVersion

Optional reproducibility token.

readonly knowledgeTime: string

ISO 8601 UTC instant when the snapshot was built (always ends with Z).

readonly metadata: Readonly<Record<string, unknown>>

Optional arbitrary metadata. JSON-safe-coerced on toDict.

readonly rows: readonly Readonly<Record<string, unknown>>[]

Row payload — opaque to this layer. Frozen.

readonly schemaId: string

Schema id the rows conform to.

readonly source: string

Source identifier (e.g. iem.archive, awc.live). Snapshot-scoped.

toDict(): Record<string, unknown>

JSON-safe dict form.

Record<string, unknown>

toToon(): string

TOON-v3 tabular form (rows only — provenance lives in the dict form).

string


Immutable reproducibility token stamping a single research() call.

readonly codeSha: string

readonly dataSha: string

readonly schemaIds: readonly string[]

readonly sdkVersion: string

readonly sources: readonly string[]

readonly token: string


codeSha: string

dataSha: string

schemaIds: readonly string[]

sdkVersion: string

sources: readonly string[]


optional minObs: number

Minimum number of observations required for tmin/tmax/tmean to be populated. Defaults to 12 (the Python threshold). Tests can override.

optional precision: number

Decimal places for HALF_UP rounding. Defaults to 0 (whole °C) — the international convention. Pass 1 for US-station tenths.

stationTz: string

IANA timezone identifier for the station, e.g. "Asia/Tokyo". Required.


Minimal row shape consumed by internationalDailyExtremes.

optional event_time_utc: null | string

ISO 8601 UTC instant. Must end with Z or include an offset.

optional precipitation_mm_1h: null | number

1-hour precipitation total in millimeters.

optional source: null | string

Source identifier (preserved on the tmin/tmax aggregate).

optional temp_c: null | number

Air temperature in degrees Celsius.


Optional adapter that lets availability() enumerate keys from a store.

CacheStore’s mandatory contract is opaque key-value: get/set/delete/withLock. Discovery needs to enumerate which keys exist for a station — this is implementation-specific (Memory iterates its Map, IndexedDB uses getAllKeys, Fs walks the directory tree). Stores that support enumeration implement the optional listKeys(prefix) method and availability() uses it; stores without it return zero-coverage but never throw.

Listed keys may exceed the requested prefix in the result (callers filter); listKeys is best-effort.

  • CacheStore

delete(key): Promise<void>

string

Promise<void>

CacheStore.delete

get<T>(key): Promise<null | T>

T = unknown

string

Promise<null | T>

CacheStore.get

listKeys(prefix): Promise<readonly string[]>

string

Promise<readonly string[]>

set<T>(key, value, opts?): Promise<void>

T = unknown

string

T

CacheSetOptions

Promise<void>

CacheStore.set

withLock<T>(key, fn): Promise<T>

T

string

() => Promise<T>

Promise<T>

CacheStore.withLock

availability(station, cache, opts): Promise<AvailabilityResult>

Return a summary of cached coverage for station.

Stores without enumeration support return a zero-coverage result with the station name populated (counts all zero, dates null).

Pass { validate: true } to confirm each candidate key via cache.get() — needed if your callers populate the cache with ttlMs and might query after expiry. The v0.1.0 research() flow does not use ttlMs, so the default (fast scan, no validation) is correct for the canonical path.

string

CacheStore

AvailabilityOptions = {}

Promise<AvailabilityResult>


buildSnapshot(opts): DataSnapshot

Build a frozen DataSnapshot.

Throws RangeError on invalid knowledgeTime. Row payloads are shallow- cloned and frozen so callers can’t mutate snapshot state post-build.

BuildSnapshotOptions

DataSnapshot


dailySummaryGaps(_station, _fromDate, _toDate): never

Climate-gap scanning is unavailable in TypeScript because GHCNh archives are too large for the browser cache.

string

string

string

never

DataAvailabilityError with reason=“model_unavailable” and a hint pointing at the Python SDK as the supported alternative.


dataVersionForResearch(args): Promise<DataVersion>

Build a DataVersion for a research() call. Mirrors Python DataVersion.for_research: the codeSha encodes the call signature (research:STATION:FROM:TO) and dataSha is supplied by the caller (typically a cache fingerprint).

The schema ids + source contract match the v0.1.0 Python SDK exactly so tokens computed in TS match tokens computed in Python for the same inputs.

string

string

string

string

string

Promise<DataVersion>


dataVersionFromComponents(components): Promise<DataVersion>

Build a frozen DataVersion from explicit components.

Mirrors Python DataVersion.from_components: sorts schemaIds + sources internally before the canonical hash so input order does not affect the token, while the returned object keeps the caller’s order on its schemaIds and sources arrays. Sorting the stored arrays too would hide source-priority order — iem.archive, iem.live, awc.live, ghcnh, nws.cli is the precedence Python preserves on the tuple, not alphabetical order.

DataVersionComponents

Promise<DataVersion>


describe(schemaId): string

Return a multi-line description of a registered schema.

string

string

MostlyrightError if schemaId is not registered. The error code is UNKNOWN_SCHEMA so callers can distinguish from validation/IO errors.


internationalDailyExtremes(rows, opts): DailyExtreme[]

Roll up observation rows to per-local-calendar-day temperature extremes.

readonly InternationalRow[]

raw observation rows (any source). Rows without a parseable event_time_utc are dropped.

InternationalDailyExtremesOptions

stationTz is required. Optional precision (default 0; pass 1 for US-station tenths) and minObs (default 12).

DailyExtreme[]

one entry per local calendar day with at least one row. Days with fewer than minObs rows have temps set to null.


registerSchema(info): void

Register or override a schema for describe(). Built-in v0.1.0 schemas are registered at module load (BUILT_IN_SCHEMAS); callers may add custom schemas or override built-ins (e.g. with richer descriptions).

SchemaInfo

void