open-meteo-mcp-server
Version:
Model Context Protocol server for Open-Meteo weather APIs
1,477 lines • 47.5 kB
JavaScript
import { z } from 'zod';
// Base parameter schemas
export const CoordinateSchema = z
.object({
latitude: z.number().min(-90).max(90),
longitude: z.number().min(-180).max(180),
})
.strict();
export const TemperatureUnitSchema = z.enum(['celsius', 'fahrenheit']).default('celsius');
export const WindSpeedUnitSchema = z.enum(['kmh', 'ms', 'mph', 'kn']).default('kmh');
export const PrecipitationUnitSchema = z.enum(['mm', 'inch']).default('mm');
export const TimeFormatSchema = z.enum(['iso8601', 'unixtime']).default('iso8601');
// Shared field schemas for parameters whose meaning isn't obvious from the name
// alone — described once here and reused across the per-endpoint schemas below,
// so the published JSON schema explains them to callers instead of exposing bare
// type/enum/min/max constraints.
export const CellSelectionSchema = z
.enum(['land', 'sea', 'nearest'])
.describe('Grid-cell preference when the coordinate sits near a coastline: "land" prefers a land grid cell, "sea" prefers a sea grid cell, "nearest" picks whichever grid cell is closest regardless of land or sea.');
export const TiltSchema = z
.number()
.min(0)
.max(90)
.describe('Tilt angle of a solar panel in degrees from horizontal (0 = flat, 90 = vertical), used together with `azimuth` to compute panel-plane irradiance (global_tilted_irradiance).');
export const AzimuthSchema = z
.number()
.min(-180)
.max(180)
.describe('Solar panel orientation in degrees (0 = south, -90 = east, 90 = west, ±180 = north), used together with `tilt` to compute panel-plane irradiance (global_tilted_irradiance).');
const DATE_FORMAT_MESSAGE = 'Must be a date in YYYY-MM-DD format (e.g. "2024-03-15").';
export const DateStringSchema = z
.string()
.regex(/^\d{4}-\d{2}-\d{2}$/, DATE_FORMAT_MESSAGE)
.describe('Date in YYYY-MM-DD format.');
const HOURLY_TIMESTAMP_FORMAT_MESSAGE = 'Must be an hourly timestamp in YYYY-MM-DDTHH:MM format (e.g. "2024-03-15T14:00").';
export const HourlyTimestampSchema = z
.string()
.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/, HOURLY_TIMESTAMP_FORMAT_MESSAGE)
.describe('Hourly timestamp in YYYY-MM-DDTHH:MM format, for selecting a sub-day range at hourly granularity (alternative to start_date/end_date).');
const PAST_DAYS_DESCRIPTION = 'Number of days before today to include in the response, in addition to the forecast period.';
const PAST_HOURS_DESCRIPTION = 'Number of hours before the current hour to include; an hourly-resolution alternative to `past_days`.';
const FORECAST_DAYS_DESCRIPTION = 'Number of days ahead to forecast, starting from today.';
const FORECAST_HOURS_DESCRIPTION = 'Number of hours ahead to forecast; an hourly-resolution alternative to `forecast_days`.';
// Geocoding schemas
export const GeocodingParamsSchema = z
.object({
name: z.string().min(2, 'Le nom doit contenir au moins 2 caractères'),
count: z.number().min(1).max(100).default(10).optional(),
language: z.string().optional(),
countryCode: z
.string()
.regex(/^[A-Z]{2}$/, 'Le code pays doit être au format ISO-3166-1 alpha2 (ex: FR, DE, US)')
.optional(),
format: z.enum(['json', 'protobuf']).default('json').optional(),
})
.strict();
export const LocationSchema = z.object({
id: z.number(),
name: z.string(),
latitude: z.number().min(-90).max(90),
longitude: z.number().min(-180).max(180),
elevation: z.number().optional(),
feature_code: z.string().optional(),
country_code: z
.string()
.regex(/^[A-Z]{2}$/)
.optional(),
admin1_id: z.number().optional(),
admin2_id: z.number().optional(),
admin3_id: z.number().optional(),
admin4_id: z.number().optional(),
timezone: z.string().optional(),
population: z.number().min(0).optional(),
postcodes: z.array(z.string()).optional(),
country_id: z.number().optional(),
country: z.string().optional(),
admin1: z.string().optional(),
admin2: z.string().optional(),
admin3: z.string().optional(),
admin4: z.string().optional(),
});
export const GeocodingResponseSchema = z.object({
results: z.array(LocationSchema),
});
export const GeocodingErrorSchema = z.object({
error: z.boolean(),
reason: z.string(),
});
// Weather variables schemas
export const HourlyVariablesSchema = z
.array(z.enum([
'temperature_2m',
'relative_humidity_2m',
'dewpoint_2m',
'dew_point_2m',
'apparent_temperature',
'precipitation_probability',
'precipitation',
'rain',
'showers',
'snowfall',
'snow_depth',
'weather_code',
'pressure_msl',
'surface_pressure',
'cloud_cover',
'cloud_cover_low',
'cloud_cover_mid',
'cloud_cover_high',
'visibility',
'evapotranspiration',
'et0_fao_evapotranspiration',
'vapour_pressure_deficit',
'wind_speed_10m',
'wind_speed_80m',
'wind_speed_120m',
'wind_speed_180m',
'wind_direction_10m',
'wind_direction_80m',
'wind_direction_120m',
'wind_direction_180m',
'wind_gusts_10m',
'temperature_80m',
'temperature_120m',
'temperature_180m',
'soil_temperature_0cm',
'soil_temperature_6cm',
'soil_temperature_18cm',
'soil_temperature_54cm',
'soil_moisture_0_to_1cm',
'soil_moisture_1_to_3cm',
'soil_moisture_3_to_9cm',
'soil_moisture_9_to_27cm',
'soil_moisture_27_to_81cm',
'uv_index',
'uv_index_clear_sky',
'is_day',
'sunshine_duration',
'wet_bulb_temperature_2m',
'total_column_integrated_water_vapour',
'cape',
'lifted_index',
'convective_inhibition',
'freezing_level_height',
'boundary_layer_height_pbl',
'shortwave_radiation',
'direct_radiation',
'diffuse_radiation',
'direct_normal_irradiance',
'global_tilted_irradiance',
'terrestrial_radiation',
'shortwave_radiation_instant',
'direct_radiation_instant',
'diffuse_radiation_instant',
'direct_normal_irradiance_instant',
'global_tilted_irradiance_instant',
'terrestrial_radiation_instant',
'wind_speed_200m',
'wind_direction_200m',
'snow_height',
'updraft',
'lightning_potential',
'temperature_1000hPa',
'temperature_975hPa',
'temperature_950hPa',
'temperature_925hPa',
'temperature_900hPa',
'temperature_850hPa',
'temperature_800hPa',
'temperature_700hPa',
'temperature_600hPa',
'temperature_500hPa',
'temperature_400hPa',
'temperature_300hPa',
'temperature_250hPa',
'temperature_200hPa',
'temperature_150hPa',
'temperature_100hPa',
'temperature_70hPa',
'temperature_50hPa',
'temperature_30hPa',
'relative_humidity_1000hPa',
'relative_humidity_975hPa',
'relative_humidity_950hPa',
'relative_humidity_925hPa',
'relative_humidity_900hPa',
'relative_humidity_850hPa',
'relative_humidity_800hPa',
'relative_humidity_700hPa',
'relative_humidity_600hPa',
'relative_humidity_500hPa',
'relative_humidity_400hPa',
'relative_humidity_300hPa',
'relative_humidity_250hPa',
'relative_humidity_200hPa',
'relative_humidity_150hPa',
'relative_humidity_100hPa',
'relative_humidity_70hPa',
'relative_humidity_50hPa',
'relative_humidity_30hPa',
'cloud_cover_1000hPa',
'cloud_cover_975hPa',
'cloud_cover_950hPa',
'cloud_cover_925hPa',
'cloud_cover_900hPa',
'cloud_cover_850hPa',
'cloud_cover_800hPa',
'cloud_cover_700hPa',
'cloud_cover_600hPa',
'cloud_cover_500hPa',
'cloud_cover_400hPa',
'cloud_cover_300hPa',
'cloud_cover_250hPa',
'cloud_cover_200hPa',
'cloud_cover_150hPa',
'cloud_cover_100hPa',
'cloud_cover_70hPa',
'cloud_cover_50hPa',
'cloud_cover_30hPa',
'wind_speed_1000hPa',
'wind_speed_975hPa',
'wind_speed_950hPa',
'wind_speed_925hPa',
'wind_speed_900hPa',
'wind_speed_850hPa',
'wind_speed_800hPa',
'wind_speed_700hPa',
'wind_speed_600hPa',
'wind_speed_500hPa',
'wind_speed_400hPa',
'wind_speed_300hPa',
'wind_speed_250hPa',
'wind_speed_200hPa',
'wind_speed_150hPa',
'wind_speed_100hPa',
'wind_speed_70hPa',
'wind_speed_50hPa',
'wind_speed_30hPa',
'wind_direction_1000hPa',
'wind_direction_975hPa',
'wind_direction_950hPa',
'wind_direction_925hPa',
'wind_direction_900hPa',
'wind_direction_850hPa',
'wind_direction_800hPa',
'wind_direction_700hPa',
'wind_direction_600hPa',
'wind_direction_500hPa',
'wind_direction_400hPa',
'wind_direction_300hPa',
'wind_direction_250hPa',
'wind_direction_200hPa',
'wind_direction_150hPa',
'wind_direction_100hPa',
'wind_direction_70hPa',
'wind_direction_50hPa',
'wind_direction_30hPa',
'geopotential_height_1000hPa',
'geopotential_height_975hPa',
'geopotential_height_950hPa',
'geopotential_height_925hPa',
'geopotential_height_900hPa',
'geopotential_height_850hPa',
'geopotential_height_800hPa',
'geopotential_height_700hPa',
'geopotential_height_600hPa',
'geopotential_height_500hPa',
'geopotential_height_400hPa',
'geopotential_height_300hPa',
'geopotential_height_250hPa',
'geopotential_height_200hPa',
'geopotential_height_150hPa',
'geopotential_height_100hPa',
'geopotential_height_70hPa',
'geopotential_height_50hPa',
'geopotential_height_30hPa',
'vertical_velocity_1000hPa',
'vertical_velocity_975hPa',
'vertical_velocity_950hPa',
'vertical_velocity_925hPa',
'vertical_velocity_900hPa',
'vertical_velocity_850hPa',
'vertical_velocity_800hPa',
'vertical_velocity_700hPa',
'vertical_velocity_600hPa',
'vertical_velocity_500hPa',
'vertical_velocity_400hPa',
'vertical_velocity_300hPa',
'vertical_velocity_250hPa',
'vertical_velocity_200hPa',
'vertical_velocity_150hPa',
'vertical_velocity_100hPa',
'vertical_velocity_70hPa',
'vertical_velocity_50hPa',
'vertical_velocity_30hPa',
]))
.optional();
export const DailyVariablesSchema = z
.array(z.enum([
'weather_code',
'temperature_2m_max',
'temperature_2m_min',
'apparent_temperature_max',
'apparent_temperature_min',
'sunrise',
'sunset',
'daylight_duration',
'sunshine_duration',
'uv_index_max',
'uv_index_clear_sky_max',
'rain_sum',
'showers_sum',
'snowfall_sum',
'precipitation_sum',
'precipitation_hours',
'precipitation_probability_max',
'wind_speed_10m_max',
'wind_gusts_10m_max',
'wind_direction_10m_dominant',
'shortwave_radiation_sum',
'et0_fao_evapotranspiration',
'temperature_2m_mean',
'apparent_temperature_mean',
'cape_mean',
'cape_max',
'cape_min',
'cloud_cover_mean',
'cloud_cover_max',
'cloud_cover_min',
'dewpoint_2m_mean',
'dewpoint_2m_max',
'dewpoint_2m_min',
'dew_point_2m_mean',
'dew_point_2m_max',
'dew_point_2m_min',
'et0_fao_evapotranspiration_sum',
'growing_degree_days_base_0_limit_50',
'leaf_wetness_probability_mean',
'leaf_wetness_probability_max',
'leaf_wetness_probability_min',
'precipitation_probability_mean',
'precipitation_probability_min',
'relative_humidity_2m_mean',
'relative_humidity_2m_max',
'relative_humidity_2m_min',
'snowfall_water_equivalent_sum',
'pressure_msl_mean',
'pressure_msl_max',
'pressure_msl_min',
'surface_pressure_mean',
'surface_pressure_max',
'surface_pressure_min',
'updraft_max',
'visibility_mean',
'visibility_max',
'visibility_min',
'wind_gusts_10m_mean',
'wind_gusts_10m_min',
'wind_speed_10m_mean',
'wind_speed_10m_min',
'wet_bulb_temperature_2m_mean',
'wet_bulb_temperature_2m_max',
'wet_bulb_temperature_2m_min',
'vapour_pressure_deficit_max',
]))
.optional();
// Union of the model IDs accepted by the live /v1/forecast API: the historical names
// already in this schema, plus the canonical names from the OpenAPI spec (verified —
// both families resolve on the live API; Open-Meteo keeps them as aliases).
export const MinutelyVariablesSchema = z
.array(z.enum([
'temperature_2m',
'relative_humidity_2m',
'dew_point_2m',
'apparent_temperature',
'precipitation',
'rain',
'snowfall',
'snowfall_height',
'freezing_level_height',
'sunshine_duration',
'weather_code',
'wind_speed_10m',
'wind_speed_80m',
'wind_speed_100m',
'wind_direction_10m',
'wind_direction_80m',
'wind_direction_100m',
'wind_gusts_10m',
'visibility',
'cape',
'lightning_potential',
'is_day',
]))
.optional();
export const ForecastModelsSchema = z
.enum([
'best_match',
'ecmwf_ifs04',
'ecmwf_ifs',
'ecmwf_ifs025',
'ecmwf_aifs025_single',
'cma_grapes_global',
'bom_access_global',
'gfs_seamless',
'ncep_gfs_seamless',
'ncep_gfs_global',
'ncep_hrrr_conus',
'ncep_nbm_conus',
'ncep_nam_conus',
'ncep_gfs_graphcast025',
'ncep_aigfs025',
'ncep_hgefs025_ensemble_mean',
'jma_seamless',
'jma_msm',
'jma_gsm',
'kma_seamless',
'kma_ldps',
'kma_gdps',
'dwd_icon_seamless',
'dwd_icon_global',
'dwd_icon_eu',
'dwd_icon_d2',
'icon_seamless',
'icon_global',
'icon_eu',
'icon_d2',
'gem_seamless',
'gem_global',
'gem_regional',
'gem_hrdps_continental',
'gem_hrdps_west',
'cmc_gem_seamless',
'cmc_gem_gdps',
'cmc_gem_rdps',
'cmc_gem_hrdps',
'cmc_gem_hrdps_west',
'meteofrance_seamless',
'meteofrance_arpege_world',
'meteofrance_arpege_europe',
'meteofrance_arome_france',
'meteofrance_arome_france_hd',
'italia_meteo_arpae_icon_2i',
'metno_seamless',
'metno_nordic',
'knmi_seamless',
'knmi_harmonie_arome_europe',
'knmi_harmonie_arome_netherlands',
'dmi_seamless',
'dmi_harmonie_arome_europe',
'ukmo_seamless',
'ukmo_global_deterministic_10km',
'ukmo_uk_deterministic_2km',
'meteoswiss_icon_seamless',
'meteoswiss_icon_ch1',
'meteoswiss_icon_ch2',
'geosphere_seamless',
'geosphere_arome_austria',
])
.optional();
// Valid model IDs for the dedicated /v1/ecmwf endpoint (different from /v1/forecast)
export const EcmwfModelsSchema = z.enum(['ecmwf_ifs', 'ecmwf_ifs025', 'best_match']).optional();
// Note: the ensemble.yml OpenAPI spec documents dwd_*_eps / cmc_gem_geps names, but
// the live /v1/ensemble API rejects them (verified) and only accepts the names below.
const EnsembleModelEnum = z.enum([
'icon_seamless_eps',
'icon_global_eps',
'icon_eu_eps',
'icon_d2_eps',
'gfs_seamless',
'ncep_gefs025',
'ncep_gefs05',
'ncep_aigefs025',
'ecmwf_ifs025_ensemble',
'ecmwf_aifs025_ensemble',
'gem_global',
'bom_access_global',
'ukmo_global_ensemble_20km',
'ukmo_uk_ensemble_2km',
'meteoswiss_icon_ch1',
'meteoswiss_icon_ch2',
]);
// The live /v1/ensemble API accepts a comma-separated list of models (verified),
// so this accepts either a single model or an array of models.
export const EnsembleModelsSchema = z
.union([EnsembleModelEnum, z.array(EnsembleModelEnum)])
.optional();
// Forecast parameters schema
export const ForecastParamsSchema = CoordinateSchema.extend({
hourly: HourlyVariablesSchema,
daily: DailyVariablesSchema,
minutely_15: MinutelyVariablesSchema,
current_weather: z.boolean().optional(),
current: HourlyVariablesSchema,
temperature_unit: TemperatureUnitSchema,
wind_speed_unit: WindSpeedUnitSchema,
precipitation_unit: PrecipitationUnitSchema,
timeformat: TimeFormatSchema,
timezone: z.string().optional(),
past_days: z.number().int().min(1).max(92).describe(PAST_DAYS_DESCRIPTION).optional(),
past_hours: z.number().int().min(0).describe(PAST_HOURS_DESCRIPTION).optional(),
forecast_days: z.number().min(1).max(16).describe(FORECAST_DAYS_DESCRIPTION).optional(),
forecast_hours: z.number().int().min(0).describe(FORECAST_HOURS_DESCRIPTION).optional(),
start_date: DateStringSchema.optional(),
end_date: DateStringSchema.optional(),
start_hour: HourlyTimestampSchema.optional(),
end_hour: HourlyTimestampSchema.optional(),
cell_selection: CellSelectionSchema.optional(),
tilt: TiltSchema.optional(),
azimuth: AzimuthSchema.optional(),
models: ForecastModelsSchema,
});
// ECMWF-specific parameters schema (uses a different model ID namespace than /v1/forecast)
export const EcmwfParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: EcmwfModelsSchema,
});
// Per-provider model ID subsets, so each model-specific tool only accepts model IDs
// that are actually valid for its own dedicated endpoint.
export const DwdIconModelsSchema = z
.enum([
'dwd_icon_seamless',
'dwd_icon_global',
'dwd_icon_eu',
'dwd_icon_d2',
'icon_seamless',
'icon_global',
'icon_eu',
'icon_d2',
])
.optional();
export const GfsModelsSchema = z
.enum([
'gfs_seamless',
'ncep_gfs_seamless',
'ncep_gfs_global',
'ncep_hrrr_conus',
'ncep_nbm_conus',
'ncep_nam_conus',
'ncep_gfs_graphcast025',
'ncep_aigfs025',
'ncep_hgefs025_ensemble_mean',
])
.optional();
export const MeteoFranceModelsSchema = z
.enum([
'meteofrance_seamless',
'meteofrance_arpege_world',
'meteofrance_arpege_europe',
'meteofrance_arome_france',
'meteofrance_arome_france_hd',
])
.optional();
export const JmaModelsSchema = z.enum(['jma_seamless', 'jma_msm', 'jma_gsm']).optional();
export const MetnoModelsSchema = z.enum(['metno_seamless', 'metno_nordic']).optional();
export const GemModelsSchema = z
.enum([
'gem_seamless',
'gem_global',
'gem_regional',
'gem_hrdps_continental',
'gem_hrdps_west',
'cmc_gem_seamless',
'cmc_gem_gdps',
'cmc_gem_rdps',
'cmc_gem_hrdps',
'cmc_gem_hrdps_west',
])
.optional();
export const DwdIconParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: DwdIconModelsSchema,
});
export const GfsParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: GfsModelsSchema,
});
export const MeteoFranceParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: MeteoFranceModelsSchema,
});
export const JmaParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: JmaModelsSchema,
});
export const MetnoParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: MetnoModelsSchema,
});
export const GemParamsSchema = ForecastParamsSchema.omit({ models: true }).extend({
models: GemModelsSchema,
});
// ERA5 archive-specific variable schemas (different from forecast API)
export const ArchiveHourlyVariablesSchema = z
.array(z.enum([
'temperature_2m',
'relative_humidity_2m',
'dew_point_2m',
'apparent_temperature',
'precipitation',
'rain',
'snowfall',
'snow_depth',
'weather_code',
'pressure_msl',
'surface_pressure',
'cloud_cover',
'cloud_cover_low',
'cloud_cover_mid',
'cloud_cover_high',
'et0_fao_evapotranspiration',
'vapour_pressure_deficit',
'wind_speed_10m',
'wind_speed_100m',
'wind_direction_10m',
'wind_direction_100m',
'wind_gusts_10m',
'soil_temperature_0_to_7cm',
'soil_temperature_7_to_28cm',
'soil_temperature_28_to_100cm',
'soil_temperature_100_to_255cm',
'soil_moisture_0_to_7cm',
'soil_moisture_7_to_28cm',
'soil_moisture_28_to_100cm',
'soil_moisture_100_to_255cm',
'shortwave_radiation',
'direct_radiation',
'diffuse_radiation',
'direct_normal_irradiance',
'terrestrial_radiation',
'shortwave_radiation_instant',
'direct_radiation_instant',
'diffuse_radiation_instant',
'direct_normal_irradiance_instant',
'terrestrial_radiation_instant',
'sunshine_duration',
'is_day',
'boundary_layer_height',
'wet_bulb_temperature_2m',
'total_column_integrated_water_vapour',
'growing_degree_days_base_0_limit_50',
'leaf_wetness_probability',
'soil_moisture_0_to_100cm',
'soil_temperature_0_to_100cm',
'soil_moisture_index_0_to_7cm',
'soil_moisture_index_7_to_28cm',
'soil_moisture_index_28_to_100cm',
'soil_moisture_index_0_to_100cm',
'global_tilted_irradiance',
'global_tilted_irradiance_instant',
]))
.optional();
export const ArchiveDailyVariablesSchema = z
.array(z.enum([
'weather_code',
'temperature_2m_max',
'temperature_2m_min',
'temperature_2m_mean',
'apparent_temperature_max',
'apparent_temperature_min',
'apparent_temperature_mean',
'sunrise',
'sunset',
'daylight_duration',
'sunshine_duration',
'precipitation_sum',
'rain_sum',
'snowfall_sum',
'precipitation_hours',
'wind_speed_10m_max',
'wind_gusts_10m_max',
'wind_direction_10m_dominant',
'shortwave_radiation_sum',
'et0_fao_evapotranspiration',
'cloud_cover_mean',
'dew_point_2m_mean',
'dew_point_2m_max',
'dew_point_2m_min',
'relative_humidity_2m_mean',
'relative_humidity_2m_max',
'relative_humidity_2m_min',
'pressure_msl_mean',
'wind_speed_10m_mean',
'wet_bulb_temperature_2m_mean',
'vapour_pressure_deficit_max',
'soil_moisture_0_to_7cm_mean',
'soil_moisture_7_to_28cm_mean',
'soil_moisture_28_to_100cm_mean',
'soil_moisture_0_to_100cm_mean',
'soil_temperature_0_to_7cm_mean',
'soil_temperature_7_to_28cm_mean',
'soil_temperature_28_to_100cm_mean',
]))
.optional();
export const ArchiveModelsSchema = z
.enum([
'best_match',
'era5_seamless',
'era5',
'era5_land',
'ecmwf_ifs',
'cerra',
'era5_ensemble',
'ecmwf_ifs_analysis_long_window',
])
.optional();
// Archive parameters schema
export const ArchiveParamsSchema = CoordinateSchema.extend({
hourly: ArchiveHourlyVariablesSchema,
daily: ArchiveDailyVariablesSchema,
models: ArchiveModelsSchema,
start_date: DateStringSchema,
end_date: DateStringSchema,
temperature_unit: TemperatureUnitSchema,
wind_speed_unit: WindSpeedUnitSchema,
precipitation_unit: PrecipitationUnitSchema,
timeformat: TimeFormatSchema,
timezone: z.string().optional(),
elevation: z.number().optional(),
tilt: TiltSchema.optional(),
azimuth: AzimuthSchema.optional(),
cell_selection: CellSelectionSchema.optional(),
}).refine((data) => data.start_date <= data.end_date, {
message: 'start_date must be before or equal to end_date',
path: ['end_date'],
});
// Air quality variables
export const AirQualityVariablesSchema = z
.array(z.enum([
'pm10',
'pm2_5',
'carbon_monoxide',
'nitrogen_dioxide',
'ozone',
'sulphur_dioxide',
'ammonia',
'dust',
'aerosol_optical_depth',
'carbon_dioxide',
'methane',
'alder_pollen',
'birch_pollen',
'grass_pollen',
'mugwort_pollen',
'olive_pollen',
'ragweed_pollen',
'european_aqi',
'european_aqi_pm2_5',
'european_aqi_pm10',
'european_aqi_nitrogen_dioxide',
'european_aqi_ozone',
'european_aqi_sulphur_dioxide',
'us_aqi',
'us_aqi_pm2_5',
'us_aqi_pm10',
'us_aqi_nitrogen_dioxide',
'us_aqi_ozone',
'us_aqi_sulphur_dioxide',
'us_aqi_carbon_monoxide',
'uv_index',
'uv_index_clear_sky',
'formaldehyde',
'glyoxal',
'non_methane_volatile_organic_compounds',
'pm10_wildfires',
'peroxyacyl_nitrates',
'secondary_inorganic_aerosol',
'residential_elementary_carbon',
'total_elementary_carbon',
'pm2_5_total_organic_matter',
'sea_salt_aerosol',
'nitrogen_monoxide',
'is_day',
]))
.optional();
export const AirQualityCurrentVariablesSchema = z
.array(z.enum([
'european_aqi',
'us_aqi',
'pm10',
'pm2_5',
'carbon_monoxide',
'nitrogen_dioxide',
'sulphur_dioxide',
'ozone',
'aerosol_optical_depth',
'dust',
'uv_index',
'uv_index_clear_sky',
'ammonia',
'alder_pollen',
'birch_pollen',
'grass_pollen',
'mugwort_pollen',
'olive_pollen',
'ragweed_pollen',
]))
.optional();
export const AirQualityParamsSchema = CoordinateSchema.extend({
hourly: AirQualityVariablesSchema,
current: AirQualityCurrentVariablesSchema,
domains: z.enum(['auto', 'cams_europe', 'cams_global']).optional(),
timezone: z.string().optional(),
timeformat: TimeFormatSchema,
past_days: z.number().min(0).max(92).describe(PAST_DAYS_DESCRIPTION).optional(),
forecast_days: z.number().min(0).max(7).describe(FORECAST_DAYS_DESCRIPTION).optional(),
start_date: DateStringSchema.optional(),
end_date: DateStringSchema.optional(),
});
// Marine variables
export const MarineHourlyVariablesSchema = z
.array(z.enum([
'wave_height',
'wave_direction',
'wave_period',
'wave_peak_period',
'wind_wave_height',
'wind_wave_direction',
'wind_wave_period',
'wind_wave_peak_period',
'swell_wave_height',
'swell_wave_direction',
'swell_wave_period',
'swell_wave_peak_period',
'secondary_swell_wave_height',
'secondary_swell_wave_period',
'secondary_swell_wave_direction',
'tertiary_swell_wave_height',
'tertiary_swell_wave_period',
'tertiary_swell_wave_direction',
'sea_level_height_msl',
'sea_surface_temperature',
'ocean_current_velocity',
'ocean_current_direction',
'invert_barometer_height',
]))
.optional();
export const MarineDailyVariablesSchema = z
.array(z.enum([
'wave_height_max',
'wave_direction_dominant',
'wave_period_max',
'wind_wave_height_max',
'wind_wave_direction_dominant',
'wind_wave_period_max',
'wind_wave_peak_period_max',
'swell_wave_height_max',
'swell_wave_direction_dominant',
'swell_wave_period_max',
'swell_wave_peak_period_max',
]))
.optional();
export const MarineMinutelyVariablesSchema = z
.array(z.enum(['ocean_current_velocity', 'ocean_current_direction', 'sea_level_height_msl']))
.optional();
export const MarineModelsSchema = z
.enum([
'best_match',
'meteofrance_wave',
'dwd_ewam',
'ecmwf_wam',
'ncep_gfswave025',
'era5_ocean',
])
.optional();
export const MarineParamsSchema = CoordinateSchema.extend({
hourly: MarineHourlyVariablesSchema,
daily: MarineDailyVariablesSchema,
current: MarineHourlyVariablesSchema,
minutely_15: MarineMinutelyVariablesSchema,
models: MarineModelsSchema,
length_unit: z.enum(['metric', 'imperial']).optional(),
temperature_unit: TemperatureUnitSchema,
wind_speed_unit: WindSpeedUnitSchema,
timezone: z.string().optional(),
timeformat: TimeFormatSchema,
past_days: z.number().min(0).max(92).describe(PAST_DAYS_DESCRIPTION).optional(),
forecast_days: z.number().min(0).max(16).describe(FORECAST_DAYS_DESCRIPTION).optional(),
start_date: DateStringSchema.optional(),
end_date: DateStringSchema.optional(),
cell_selection: CellSelectionSchema.optional(),
});
// Flood variables
export const FloodDailyVariablesSchema = z
.array(z.enum([
'river_discharge',
'river_discharge_mean',
'river_discharge_median',
'river_discharge_max',
'river_discharge_min',
'river_discharge_p25',
'river_discharge_p75',
]))
.optional();
export const FloodModelsSchema = z
.enum([
'seamless_v4',
'forecast_v4',
'consolidated_v4',
'seamless_v3',
'forecast_v3',
'consolidated_v3',
])
.optional();
export const FloodParamsSchema = CoordinateSchema.extend({
daily: FloodDailyVariablesSchema,
models: FloodModelsSchema,
timezone: z.string().optional(),
timeformat: TimeFormatSchema,
past_days: z.number().min(0).max(92).describe(PAST_DAYS_DESCRIPTION).optional(),
forecast_days: z.number().min(0).max(366).describe(FORECAST_DAYS_DESCRIPTION).optional(),
start_date: DateStringSchema.optional(),
end_date: DateStringSchema.optional(),
ensemble: z.boolean().optional(),
cell_selection: CellSelectionSchema.default('nearest').optional(),
});
// Seasonal forecast parameters
export const SeasonalParamsSchema = CoordinateSchema.extend({
hourly: z
.array(z.enum([
'temperature_2m',
'temperature_2m_max',
'temperature_2m_min',
'dew_point_2m',
'pressure_msl',
'sea_surface_temperature',
'snowfall_water_equivalent',
'precipitation',
'rain',
'showers',
'snowfall',
'cloud_cover',
'wind_speed_10m',
'wind_direction_10m',
'wind_speed_100m',
'wind_direction_100m',
'wind_speed_200m',
'wind_direction_200m',
'relative_humidity_2m',
'apparent_temperature',
'et0_fao_evapotranspiration',
'vapour_pressure_deficit',
'weather_code',
'sunshine_duration',
'wave_height',
'wave_direction',
'wave_period',
'wave_peak_period',
'soil_temperature_0_to_7cm',
'soil_temperature_7_to_28cm',
'soil_temperature_28_to_100cm',
'soil_temperature_100_to_255cm',
'soil_moisture_0_to_7cm',
'soil_moisture_7_to_28cm',
'soil_moisture_28_to_100cm',
'soil_moisture_100_to_255cm',
'shortwave_radiation',
'direct_radiation',
'diffuse_radiation',
'direct_normal_irradiance',
'global_tilted_irradiance',
'terrestrial_radiation',
'shortwave_radiation_instant',
'direct_radiation_instant',
'diffuse_radiation_instant',
'direct_normal_irradiance_instant',
'global_tilted_irradiance_instant',
'terrestrial_radiation_instant',
]))
.optional(),
daily: z
.array(z.enum([
'sunrise',
'sunset',
'weather_code',
'et0_fao_evapotranspiration',
'vapour_pressure_deficit_max',
'temperature_2m_max',
'temperature_2m_min',
'temperature_2m_mean',
'sunshine_duration',
'dew_point_2m_mean',
'pressure_msl_mean',
'sea_surface_temperature_mean',
'cloud_cover_mean',
'wind_speed_10m_mean',
'wind_speed_100m_mean',
'snow_depth_mean',
'soil_temperature_0_to_7cm_mean',
'shortwave_radiation_sum',
'precipitation_sum',
'rain_sum',
'precipitation_hours',
'wind_speed_10m_max',
'wind_direction_10m_dominant',
]))
.optional(),
weekly: z
.array(z.enum([
'wind_speed_10m_mean',
'wind_speed_10m_anomaly',
'wind_speed_100m_mean',
'wind_speed_100m_anomaly',
'wind_direction_10m_mean',
'wind_direction_10m_anomaly',
'wind_direction_100m_mean',
'wind_direction_100m_anomaly',
'snow_depth_mean',
'snow_depth_anomaly',
'snowfall_mean',
'snowfall_anomaly',
'temperature_2m_anomaly_gt0',
'temperature_2m_anomaly_gt1',
'temperature_2m_anomaly_gt2',
'temperature_2m_anomaly_ltm1',
'temperature_2m_anomaly_ltm2',
'pressure_msl_anomaly_gt0',
'surface_temperature_anomaly_gt0',
'precipitation_anomaly_gt0',
'precipitation_anomaly_gt10',
'precipitation_anomaly_gt20',
'temperature_2m_sot10',
'temperature_2m_sot90',
'temperature_2m_efi',
'precipitation_efi',
'precipitation_sot90',
'showers_mean',
'snow_density_mean',
'snow_density_anomaly',
'snow_depth_water_equivalent_mean',
'snow_depth_water_equivalent_anomaly',
'total_column_integrated_water_vapour_mean',
'total_column_integrated_water_vapour_anomaly',
'temperature_2m_mean',
'temperature_2m_anomaly',
'dew_point_2m_mean',
'dew_point_2m_anomaly',
'pressure_msl_mean',
'pressure_msl_anomaly',
'sea_surface_temperature_mean',
'sea_surface_temperature_anomaly',
'wind_u_component_10m_mean',
'wind_u_component_10m_anomaly',
'wind_v_component_10m_mean',
'wind_v_component_10m_anomaly',
'wind_u_component_100m_mean',
'wind_u_component_100m_anomaly',
'wind_v_component_100m_mean',
'wind_v_component_100m_anomaly',
'snowfall_water_equivalent_mean',
'snowfall_water_equivalent_anomaly',
'precipitation_mean',
'precipitation_anomaly',
'cloud_cover_mean',
'cloud_cover_anomaly',
'sunshine_duration_mean',
'sunshine_duration_anomaly',
'soil_temperature_0_to_7cm_mean',
'soil_temperature_0_to_7cm_anomaly',
'temperature_max6h_2m_mean',
'temperature_max6h_2m_anomaly',
'temperature_min6h_2m_mean',
'temperature_min6h_2m_anomaly',
]))
.optional(),
monthly: z
.array(z.enum([
'wind_gusts_10m_anomaly',
'wind_speed_10m_mean',
'wind_speed_10m_anomaly',
'albedo_mean',
'albedo_anomaly',
'cloud_cover_low_mean',
'cloud_cover_low_anomaly',
'showers_mean',
'showers_anomaly',
'runoff_mean',
'runoff_anomaly',
'snow_density_mean',
'snow_density_anomaly',
'snow_depth_water_equivalent_mean',
'snow_depth_water_equivalent_anomaly',
'total_column_integrated_water_vapour_mean',
'total_column_integrated_water_vapour_anomaly',
'temperature_2m_mean',
'temperature_2m_anomaly',
'dew_point_2m_mean',
'dew_point_2m_anomaly',
'pressure_msl_mean',
'pressure_msl_anomaly',
'sea_surface_temperature_mean',
'sea_surface_temperature_anomaly',
'wind_u_component_10m_mean',
'wind_u_component_10m_anomaly',
'wind_v_component_10m_mean',
'wind_v_component_10m_anomaly',
'snowfall_water_equivalent_mean',
'snowfall_water_equivalent_anomaly',
'precipitation_mean',
'precipitation_anomaly',
'shortwave_radiation_mean',
'shortwave_radiation_anomaly',
'longwave_radiation_mean',
'longwave_radiation_anomaly',
'cloud_cover_mean',
'cloud_cover_anomaly',
'sunshine_duration_mean',
'sunshine_duration_anomaly',
'soil_temperature_0_to_7cm_mean',
'soil_temperature_0_to_7cm_anomaly',
'soil_temperature_7_to_28cm_mean',
'soil_temperature_7_to_28cm_anomaly',
'soil_temperature_28_to_100cm_mean',
'soil_temperature_28_to_100cm_anomaly',
'soil_temperature_100_to_255cm_mean',
'soil_temperature_100_to_255cm_anomaly',
'soil_moisture_0_to_7cm_mean',
'soil_moisture_0_to_7cm_anomaly',
'soil_moisture_7_to_28cm_mean',
'soil_moisture_7_to_28cm_anomaly',
'soil_moisture_28_to_100cm_mean',
'soil_moisture_28_to_100cm_anomaly',
'soil_moisture_100_to_255cm_mean',
'soil_moisture_100_to_255cm_anomaly',
'temperature_max24h_2m_mean',
'temperature_max24h_2m_anomaly',
'temperature_min24h_2m_mean',
'temperature_min24h_2m_anomaly',
'sea_ice_cover_mean',
'sea_ice_cover_anomaly',
'latent_heat_flux_mean',
'latent_heat_flux_anomaly',
'sensible_heat_flux_mean',
'sensible_heat_flux_anomaly',
'evapotranspiration_mean',
'evapotranspiration_anomaly',
'snowfall_mean',
'snowfall_anomaly',
'snow_depth_mean',
'snow_depth_anomaly',
]))
.optional(),
forecast_days: z.number().int().min(0).max(217).describe(FORECAST_DAYS_DESCRIPTION).optional(),
past_days: z.number().min(0).max(92).describe(PAST_DAYS_DESCRIPTION).optional(),
start_date: DateStringSchema.optional(),
end_date: DateStringSchema.optional(),
temperature_unit: TemperatureUnitSchema,
wind_speed_unit: WindSpeedUnitSchema,
precipitation_unit: PrecipitationUnitSchema,
timezone: z.string().optional(),
timeformat: TimeFormatSchema,
cell_selection: CellSelectionSchema.optional(),
models: z
.enum([
'best_match',
'ecmwf_seasonal_seamless',
'ecmwf_seas5',
'ecmwf_ec46',
'ecmwf_seasonal_ensemble_mean_seamless',
'ecmwf_seas5_ensemble_mean',
'ecmwf_ec46_ensemble_mean',
])
.optional(),
});
// Climate models
export const ClimateModelsSchema = z.array(z.enum([
'CMCC_CM2_VHR4',
'FGOALS_f3_H',
'HiRAM_SIT_HR',
'MRI_AGCM3_2_S',
'EC_Earth3P_HR',
'MPI_ESM1_2_XR',
'NICAM16_8S',
]));
// Climate projection parameters
export const ClimateParamsSchema = CoordinateSchema.extend({
daily: z
.array(z.enum([
'temperature_2m_max',
'temperature_2m_min',
'temperature_2m_mean',
'cloud_cover_mean',
'relative_humidity_2m_max',
'relative_humidity_2m_min',
'relative_humidity_2m_mean',
'precipitation_sum',
'rain_sum',
'snowfall_sum',
'snowfall_water_equivalent_sum',
'wind_speed_10m_mean',
'wind_speed_10m_max',
'wind_gusts_10m_mean',
'wind_gusts_10m_max',
'pressure_msl_mean',
'shortwave_radiation_sum',
'et0_fao_evapotranspiration_sum',
'vapour_pressure_deficit_max',
'dew_point_2m_mean',
'dew_point_2m_max',
'dew_point_2m_min',
'growing_degree_days_base_0_limit_50',
'leaf_wetness_probability_mean',
'daylight_duration',
'soil_moisture_0_to_7cm_mean',
'soil_moisture_7_to_28cm_mean',
'soil_moisture_28_to_100cm_mean',
'soil_moisture_0_to_100cm_mean',
'soil_moisture_index_0_to_7cm_mean',
'soil_moisture_index_7_to_28cm_mean',
'soil_moisture_index_28_to_100cm_mean',
'soil_temperature_0_to_7cm_mean',
'soil_temperature_7_to_28cm_mean',
'soil_temperature_28_to_100cm_mean',
'soil_temperature_0_to_100cm_mean',
]))
.optional(),
start_date: DateStringSchema,
end_date: DateStringSchema,
models: ClimateModelsSchema.optional(),
temperature_unit: TemperatureUnitSchema,
wind_speed_unit: WindSpeedUnitSchema,
precipitation_unit: PrecipitationUnitSchema,
disable_bias_correction: z.boolean().optional(),
timezone: z.string().optional(),
timeformat: TimeFormatSchema,
cell_selection: CellSelectionSchema.optional(),
}).refine((data) => data.start_date <= data.end_date, {
message: 'start_date must be before or equal to end_date',
path: ['end_date'],
});
// Ensemble forecast parameters
export const EnsembleParamsSchema = CoordinateSchema.extend({
models: EnsembleModelsSchema,
hourly: z
.array(z.enum([
'temperature_2m',
'relative_humidity_2m',
'dew_point_2m',
'apparent_temperature',
'precipitation',
'rain',
'snowfall',
'snow_depth',
'weather_code',
'pressure_msl',
'surface_pressure',
'cloud_cover',
'visibility',
'wind_speed_10m',
'wind_direction_10m',
'wind_gusts_10m',
'wind_speed_80m',
'wind_direction_80m',
'wind_speed_100m',
'wind_direction_100m',
'surface_temperature',
'soil_temperature_0_to_10cm',
'cape',
'et0_fao_evapotranspiration',
'vapour_pressure_deficit',
'shortwave_radiation',
'uv_index',
'uv_index_clear_sky',
'temperature_2m_min',
'temperature_2m_max',
'wet_bulb_temperature_2m',
'convective_inhibition',
'freezing_level_height',
'snowfall_height',
'sunshine_duration',
'snowfall_water_equivalent',
'snow_depth_water_equivalent',
'temperature_1000hPa',
'temperature_975hPa',
'temperature_950hPa',
'temperature_925hPa',
'temperature_900hPa',
'temperature_850hPa',
'temperature_800hPa',
'temperature_700hPa',
'temperature_600hPa',
'temperature_500hPa',
'temperature_400hPa',
'temperature_300hPa',
'temperature_250hPa',
'temperature_200hPa',
'temperature_150hPa',
'temperature_100hPa',
'temperature_70hPa',
'temperature_50hPa',
'temperature_30hPa',
'relative_humidity_1000hPa',
'relative_humidity_975hPa',
'relative_humidity_950hPa',
'relative_humidity_925hPa',
'relative_humidity_900hPa',
'relative_humidity_850hPa',
'relative_humidity_800hPa',
'relative_humidity_700hPa',
'relative_humidity_600hPa',
'relative_humidity_500hPa',
'relative_humidity_400hPa',
'relative_humidity_300hPa',
'relative_humidity_250hPa',
'relative_humidity_200hPa',
'relative_humidity_150hPa',
'relative_humidity_100hPa',
'relative_humidity_70hPa',
'relative_humidity_50hPa',
'relative_humidity_30hPa',
'wind_speed_1000hPa',
'wind_speed_975hPa',
'wind_speed_950hPa',
'wind_speed_925hPa',
'wind_speed_900hPa',
'wind_speed_850hPa',
'wind_speed_800hPa',
'wind_speed_700hPa',
'wind_speed_600hPa',
'wind_speed_500hPa',
'wind_speed_400hPa',
'wind_speed_300hPa',
'wind_speed_250hPa',
'wind_speed_200hPa',
'wind_speed_150hPa',
'wind_speed_100hPa',
'wind_speed_70hPa',
'wind_speed_50hPa',
'wind_speed_30hPa',
'wind_direction_1000hPa',
'wind_direction_975hPa',
'wind_direction_950hPa',
'wind_direction_925hPa',
'wind_direction_900hPa',
'wind_direction_850hPa',
'wind_direction_800hPa',
'wind_direction_700hPa',
'wind_direction_600hPa',
'wind_direction_500hPa',
'wind_direction_400hPa',
'wind_direction_300hPa',
'wind_direction_250hPa',
'wind_direction_200hPa',
'wind_direction_150hPa',
'wind_direction_100hPa',
'wind_direction_70hPa',
'wind_direction_50hPa',
'wind_direction_30hPa',
'geopotential_height_1000hPa',
'geopotential_height_975hPa',
'geopotential_height_950hPa',
'geopotential_height_925hPa',
'geopotential_height_900hPa',
'geopotential_height_850hPa',
'geopotential_height_800hPa',
'geopotential_height_700hPa',
'geopotential_height_600hPa',
'geopotential_height_500hPa',
'geopotential_height_400hPa',
'geopotential_height_300hPa',
'geopotential_height_250hPa',
'geopotential_height_200hPa',
'geopotential_height_150hPa',
'geopotential_height_100hPa',
'geopotential_height_70hPa',
'geopotential_height_50hPa',
'geopotential_height_30hPa',
'vertical_velocity_1000hPa',
'vertical_velocity_975hPa',
'vertical_velocity_950hPa',
'vertical_velocity_925hPa',
'vertical_velocity_900hPa',
'vertical_velocity_850hPa',
'vertical_velocity_800hPa',
'vertical_velocity_700hPa',
'vertical_velocity_600hPa',
'vertical_velocity_500hPa',
'vertical_velocity_400hPa',
'vertical_velocity_300hPa',
'vertical_velocity_250hPa',
'vertical_velocity_200hPa',
'vertical_velocity_150hPa',
'vertical_velocity_100hPa',
'vertical_velocity_70hPa',
'vertical_velocity_50hPa',
'vertical_velocity_30hPa',
]))
.optional(),
daily: z
.array(z.enum([
'temperature_2m_mean',
'temperature_2m_min',
'temperature_2m_max',
'apparent_temperature_mean',
'apparent_temperature_min',
'apparent_temperature_max',
'wind_speed_10m_mean',
'wind_speed_10m_min',
'wind_speed_10m_max',
'wind_direction_10m_dominant',
'wind_gusts_10m_mean',
'wind_gusts_10m_min',
'wind_gusts_10m_max',
'wind_speed_100m_mean',
'wind_speed_100m_min',
'wind_speed_100m_max',
'wind_direction_100m_dominant',
'precipitation_sum',
'precipitation_hours',
'rain_sum',
'snowfall_sum',
'pressure_msl_mean',
'pressure_msl_min',
'pressure_msl_max',
'surface_pressure_mean',
'surface_pressure_min',
'surface_pressure_max',
'cloud_cover_mean',
'cloud_cover_min',
'cloud_cover_max',
'relative_humidity_2m_mean',
'relative_humidity_2m_min',
'relative_humidity_2m_max',
'dew_point_2m_mean',
'dew_point_2m_min',
'dew_point_2m_max',
'cape_mean',
'cape_min',
'cape_max',
'shortwave_radiation_sum',
'et0_fao_evapotranspiration',
]))
.optional(),
forecast_days: z.number().min(0).max(36).describe(FORECAST_DAYS_DESCRIPTION).optional(),
temperature_unit: TemperatureUnitSchema,
wind_speed_unit: WindSpeedUnitSchema,
precipitation_unit: PrecipitationUnitSchema,
timezone: z.string().optional(),
elevation: z.number().optional(),
timeformat: TimeFormatSchema,
past_days: z.number().int().min(0).max(92).describe(PAST_DAYS_DESCRIPTION).optional(),
past_hours: z.number().int().min(0).describe(PAST_HOURS_DESCRIPTION).optional(),
forecast_hours: z.number().int().min(0).describe(FORECAST_HOURS_DESCRIPTION).optional(),
start_date: DateStringSchema.optional(),
end_date: DateStringSchema.optional(),
tilt: TiltSchema.optional(),
azimuth: AzimuthSchema.optional(),
cell_selection: CellSelectionSchema.optional(),
temporal_resolution: z.enum(['native', 'hourly', 'hourly_3', 'hourly_6']).optional(),
});
// Elevation parameters — the API supports batch lookups via comma-separated
// lat/lon lists, so each coordinate accepts either a single value or an array.
export const ElevationParamsSchema = z
.object({
latitude: z.union([z.number().min(-90).max(90), z.array(z.number().min(-90).max(90))]),
longitude: z.union([z.number().min(-180).max(180), z.array(z.number().min(-180).max(180))]),
})
.strict();
// Response types
export const WeatherResponseSchema = z.object({
latitude: z.number(),
longitude: z.number(),
elevation: z.number(),
generationtime_ms: z.number(),
utc_offset_seconds: z.number(),
hourly: z.record(z.array(z.union([z.number(), z.string()]))).optional(),
hourly_units: z.record(z.string()).optional(),
daily: z.record(z.array(z.union([z.number(), z.string()]))).optional(),
daily_units: z.record(z.string()).optional(),
current_weather: z
.object({
time: z.string(),
temperature: z.number(),
wind_speed: z.number(),
wind_direction: z.number(),
weather_code: z.number(),
})
.optional(),
});
export const ElevationResponseSchema = z.object({
elevation: z.array(z.number()),
});
//# sourceMappingURL=types.js.map