implemented openmeteo client

main
Inga 🏳‍🌈 1 year ago
parent b8f9ee0e76
commit 5aba64eb5f
  1. 26
      src/clients/weather/openmeteo.spec.ts
  2. 68
      src/clients/weather/openmeteo.ts
  3. 10
      src/clients/weather/types.ts

@ -0,0 +1,26 @@
import { createOpenmeteoClient } from './openmeteo';
describe('createOpenmeteoClient', () => {
const client = createOpenmeteoClient();
it('returns some weather for the sample address', async () => {
const result = await client.getCurrentWeather({
latitude: 52.28,
longitude: 10.52,
});
expect(result.apparentTemperature).toMatch(/^\d+(\.?\d+)?°C$/);
expect(result.temperature).toMatch(/^\d+(\.?\d+)?°C$/);
expect(result.relativeHumidity).toMatch(/^\d+%$/);
// Just to make sure that the returned weather seems to be reasonable
expect(result).not.toEqual({
apparentTemperature: '0°C',
temperature: '0°C',
relativeHumidity: '0%',
});
expect(result).not.toEqual({
apparentTemperature: '0.0°C',
temperature: '0.0°C',
relativeHumidity: '0%',
});
});
});

@ -0,0 +1,68 @@
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}&current=${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'),
//...
};
}),
};
};

@ -0,0 +1,10 @@
export type WeatherProvider = {
getCurrentWeather(params: {
longitude: number;
latitude: number;
}): Promise<{
temperature: string;
apparentTemperature: string;
relativeHumidity: string;
}>;
};
Loading…
Cancel
Save