Project Files
dist / weather.js
"use strict";
/**
* Tiny wttr.in client. No API key, no deps, no JS rendering needed.
*
* wttr.in returns plain text when called with `?format=…` or `?T` (terminal).
* We use the "j1" JSON endpoint for structure, then format a compact text
* summary so the model gets clean, low-token output.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWeather = getWeather;
function abortableFetch(url, opts) {
const ctl = new AbortController();
const timer = setTimeout(() => ctl.abort(), opts.timeoutMs);
return fetch(url, {
signal: ctl.signal,
headers: {
"User-Agent": opts.userAgent,
Accept: "application/json",
},
}).finally(() => clearTimeout(timer));
}
async function getWeather(location, opts) {
const loc = location.trim();
const units = opts.units ?? "metric";
const lang = opts.lang ?? "en";
const url = `https://wttr.in/${encodeURIComponent(loc)}?format=j1&lang=${encodeURIComponent(lang)}`;
let res;
try {
res = await abortableFetch(url, opts);
}
catch (e) {
return {
error: `wttr.in request failed: ${e?.message ?? String(e)}`,
source: "wttr.in",
source_url: url,
};
}
if (!res.ok) {
return {
error: `wttr.in returned HTTP ${res.status}`,
source: "wttr.in",
source_url: url,
};
}
let data;
try {
data = await res.json();
}
catch (e) {
return {
error: `wttr.in returned non-JSON (location may be unknown): ${e?.message ?? String(e)}`,
source: "wttr.in",
source_url: url,
};
}
const c = data?.current_condition?.[0];
const area = data?.nearest_area?.[0];
if (!c) {
return {
error: "wttr.in returned no current_condition (unknown location?)",
source: "wttr.in",
source_url: url,
};
}
const tempC = c.temp_C;
const tempF = c.temp_F;
const feelsC = c.FeelsLikeC;
const feelsF = c.FeelsLikeF;
const windKph = c.windspeedKmph;
const windMph = c.windspeedMiles;
const windDir = c.winddir16Point;
const description = c.weatherDesc?.[0]?.value ?? "Unknown";
const humidity = `${c.humidity}%`;
const localObs = c.localObsDateTime;
const resolved = area &&
[area.areaName?.[0]?.value, area.region?.[0]?.value, area.country?.[0]?.value]
.filter(Boolean)
.join(", ");
const fmtTemp = (cVal, fVal) => units === "imperial" ? `${fVal}°F` : `${cVal}°C`;
const fmtWind = (k, m, dir) => units === "imperial" ? `${m} mph ${dir}` : `${k} km/h ${dir}`;
const forecast = (data.weather ?? []).slice(0, 3).map((d) => {
const hourly = d.hourly ?? [];
const middayChunk = hourly[Math.min(4, hourly.length - 1)] ?? hourly[0];
const summary = middayChunk?.weatherDesc?.[0]?.value ?? "Unknown";
return {
date: d.date,
summary,
min: fmtTemp(d.mintempC, d.mintempF),
max: fmtTemp(d.maxtempC, d.maxtempF),
sunrise: d.astronomy?.[0]?.sunrise,
sunset: d.astronomy?.[0]?.sunset,
};
});
return {
location: loc,
resolved_location: resolved || undefined,
current: {
description,
temperature: fmtTemp(tempC, tempF),
feels_like: fmtTemp(feelsC, feelsF),
humidity,
wind: fmtWind(windKph, windMph, windDir),
observed_local_time: localObs,
},
forecast,
source: "wttr.in",
source_url: `https://wttr.in/${encodeURIComponent(loc)}`,
};
}
//# sourceMappingURL=weather.js.map