34 lines
1.4 KiB
JavaScript
34 lines
1.4 KiB
JavaScript
// lib/weather.js — Melbourne, Open-Meteo, no API key, 15-min cache.
|
|
const LAT = -37.81, LON = 144.96, TTL_MS = 15 * 60 * 1000;
|
|
const CODES = { 0:'Clear',1:'Mainly clear',2:'Partly cloudy',3:'Overcast',45:'Fog',48:'Rime fog',
|
|
51:'Light drizzle',53:'Drizzle',55:'Heavy drizzle',61:'Light rain',63:'Rain',65:'Heavy rain',
|
|
71:'Light snow',73:'Snow',75:'Heavy snow',80:'Showers',81:'Showers',82:'Violent showers',
|
|
95:'Thunderstorm',96:'Thunderstorm',99:'Thunderstorm' };
|
|
|
|
let cache = null; // { at, data }
|
|
let fetcher = defaultFetcher;
|
|
|
|
async function defaultFetcher() {
|
|
const url = `https://api.open-meteo.com/v1/forecast?latitude=${LAT}&longitude=${LON}` +
|
|
`¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m`;
|
|
const res = await fetch(url, { signal: AbortSignal.timeout(6000) });
|
|
if (!res.ok) throw new Error(`open-meteo ${res.status}`);
|
|
return res.json();
|
|
}
|
|
|
|
export function _setFetcher(fn) { fetcher = fn; }
|
|
export function _resetCache() { cache = null; fetcher = defaultFetcher; }
|
|
|
|
export async function current() {
|
|
if (cache && Date.now() - cache.at < TTL_MS) return cache.data;
|
|
const raw = await fetcher();
|
|
const c = raw.current || {};
|
|
const data = {
|
|
temp: c.temperature_2m, feels_like: c.apparent_temperature,
|
|
humidity: c.relative_humidity_2m, wind: c.wind_speed_10m,
|
|
code: c.weather_code, label: CODES[c.weather_code] || 'Unknown'
|
|
};
|
|
cache = { at: Date.now(), data };
|
|
return data;
|
|
}
|