You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
2.2 KiB
68 lines
2.2 KiB
import fetch from 'node-fetch';
|
|
import PQueue from 'p-queue';
|
|
import { WeatherProvider } from './types';
|
|
|
|
const requestedFields = [
|
|
'temperature_2m',
|
|
'relativehumidity_2m',
|
|
'apparent_temperature',
|
|
'is_day',
|
|
'precipitation',
|
|
'rain',
|
|
'showers',
|
|
'snowfall',
|
|
'weathercode',
|
|
'cloudcover',
|
|
'pressure_msl',
|
|
'surface_pressure',
|
|
'windspeed_10m',
|
|
'winddirection_10m',
|
|
'windgusts_10m',
|
|
] as const;
|
|
|
|
type OpenmeteoKey = (typeof requestedFields)[number];
|
|
type OpenmeteoResponse =
|
|
| {
|
|
current_units?: Record<OpenmeteoKey, string | undefined>;
|
|
current?: Record<OpenmeteoKey, string | number | undefined>;
|
|
}
|
|
| undefined;
|
|
|
|
export const createOpenmeteoClient = (): WeatherProvider => {
|
|
// Rate limit (according to https://open-meteo.com/en/terms it's 10k per day;
|
|
// here we set it 1 per second, should be enough for the demo app goal)
|
|
const queue = new PQueue({
|
|
interval: 1000,
|
|
intervalCap: 1,
|
|
timeout: 2000,
|
|
throwOnTimeout: true,
|
|
});
|
|
|
|
return {
|
|
getCurrentWeather: async ({ latitude, longitude }) =>
|
|
queue.add(async () => {
|
|
const response = await fetch(
|
|
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=${requestedFields.join(
|
|
',',
|
|
)}`,
|
|
);
|
|
const body = (await response.json()) as OpenmeteoResponse;
|
|
if (!body || !body.current || !body.current_units) {
|
|
throw new Error('cannot load weather');
|
|
}
|
|
|
|
const { current, current_units } = body;
|
|
const getReadableValue = (key: OpenmeteoKey) =>
|
|
`${current[key]}${current_units[key]}`;
|
|
|
|
return {
|
|
temperature: getReadableValue('temperature_2m'),
|
|
apparentTemperature: getReadableValue(
|
|
'apparent_temperature',
|
|
),
|
|
relativeHumidity: getReadableValue('relativehumidity_2m'),
|
|
//...
|
|
};
|
|
}),
|
|
};
|
|
};
|
|
|