openweather-api-node
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -6,3 +6,5 @@ export declare const SUP_LANGS: readonly ["af", "al", "ar", "az", "bg", "ca", "cz", "da", "de", "el", "en", "eu", "fa", "fi", "fr", "gl", "he", "hi", "hr", "hu", "id", "it", "ja", "kr", "la", "lt", "mk", "no", "nl", "pl", "pt", "pt_br", "ro", "ru", "sv", "se", "sk", "sl", "sp", "es", "sr", "th", "tr", "ua", "uk", "vi", "zh_cn", "zh_tw", "zu"]; | ||
export declare const DATA_PATH = "data/2.5"; | ||
export declare const WEATHER_PATH: string; | ||
export declare const FORECAST_PATH: string; | ||
export declare const ONECALL_PATH: string; | ||
export declare const AIR_POLLUTION_PATH: string; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AIR_POLLUTION_PATH = exports.ONECALL_PATH = exports.DATA_PATH = exports.GEO_PATH = exports.API_ENDPOINT = exports.SUP_UNITS = exports.SUP_LANGS = void 0; | ||
exports.AIR_POLLUTION_PATH = exports.ONECALL_PATH = exports.FORECAST_PATH = exports.WEATHER_PATH = exports.DATA_PATH = exports.GEO_PATH = exports.API_ENDPOINT = exports.SUP_UNITS = exports.SUP_LANGS = void 0; | ||
exports.SUP_LANGS = [ | ||
@@ -59,3 +59,5 @@ "af", | ||
exports.DATA_PATH = "data/2.5"; | ||
exports.WEATHER_PATH = exports.DATA_PATH + "/weather"; | ||
exports.FORECAST_PATH = exports.DATA_PATH + "/forecast"; | ||
exports.ONECALL_PATH = exports.DATA_PATH + "/onecall"; | ||
exports.AIR_POLLUTION_PATH = exports.DATA_PATH + "/air_pollution"; |
@@ -1,2 +0,2 @@ | ||
import { Alert, Language, Location, Options, Unit, CurrentWeather, MinutelyWeather, HourlyWeather, DailyWeather, Everything, AirPollution, WeatherHistory } from "./types"; | ||
import { Alert, Language, Location, Options, Unit, CurrentWeather, MinutelyWeather, HourlyWeather, DailyWeather, Everything, AirPollution, WeatherHistory, ForecastWeather } from "./types"; | ||
export declare class OpenWeatherAPI { | ||
@@ -95,2 +95,10 @@ private globalOptions; | ||
/** | ||
* Getter for forecasted weather | ||
* | ||
* @param limit - maximum length of returned array | ||
* @param options - options used only for this call | ||
* @returns array of Weather objects, one for every 3 hours, up to 5 days | ||
*/ | ||
getForecast(limit?: number, options?: Options): Promise<ForecastWeather[]>; | ||
/** | ||
* Getter for minutely weather | ||
@@ -97,0 +105,0 @@ * |
@@ -23,5 +23,7 @@ "use strict"; | ||
const current_parser_1 = __importDefault(require("./parsers/weather/current-parser")); | ||
const minutely_parser_1 = __importDefault(require("./parsers/weather/minutely-parser")); | ||
const hourly_parser_1 = __importDefault(require("./parsers/weather/hourly-parser")); | ||
const daily_parser_1 = __importDefault(require("./parsers/weather/daily-parser")); | ||
const forecast_parser_1 = __importDefault(require("./parsers/weather/forecast-parser")); | ||
const current_parser_2 = __importDefault(require("./parsers/onecall/current-parser")); | ||
const minutely_parser_1 = __importDefault(require("./parsers/onecall/minutely-parser")); | ||
const hourly_parser_1 = __importDefault(require("./parsers/onecall/hourly-parser")); | ||
const daily_parser_1 = __importDefault(require("./parsers/onecall/daily-parser")); | ||
const single_parser_1 = __importDefault(require("./parsers/air-pollution/single-parser")); | ||
@@ -270,5 +272,3 @@ const list_parser_1 = __importDefault(require("./parsers/air-pollution/list-parser")); | ||
const parsedOptions = await this.parseOptions(options); | ||
let response = await this.fetch(this.createURL(parsedOptions, constants_1.ONECALL_PATH, { | ||
exclude: "alerts,minutely,hourly,daily", | ||
})); | ||
let response = await this.fetch(this.createURL(parsedOptions, constants_1.WEATHER_PATH)); | ||
let data = response.data; | ||
@@ -278,2 +278,16 @@ return (0, current_parser_1.default)(data); | ||
/** | ||
* Getter for forecasted weather | ||
* | ||
* @param limit - maximum length of returned array | ||
* @param options - options used only for this call | ||
* @returns array of Weather objects, one for every 3 hours, up to 5 days | ||
*/ | ||
async getForecast(limit = Number.POSITIVE_INFINITY, options = {}) { | ||
await this.uncacheLocation(); | ||
const parsedOptions = await this.parseOptions(options); | ||
let response = await this.fetch(this.createURL(parsedOptions, constants_1.FORECAST_PATH)); | ||
let data = response.data; | ||
return (0, forecast_parser_1.default)(data, limit); | ||
} | ||
/** | ||
* Getter for minutely weather | ||
@@ -369,3 +383,3 @@ * | ||
timezoneOffset: data.timezone_offset, | ||
current: (0, current_parser_1.default)(data), | ||
current: (0, current_parser_2.default)(data), | ||
minutely: (0, minutely_parser_1.default)(data, Number.POSITIVE_INFINITY), | ||
@@ -398,3 +412,3 @@ hourly: (0, hourly_parser_1.default)(data, Number.POSITIVE_INFINITY), | ||
timezoneOffset: data.timezone_offset, | ||
current: (0, current_parser_1.default)(data), | ||
current: (0, current_parser_2.default)(data), | ||
hourly: (0, hourly_parser_1.default)(data, Number.POSITIVE_INFINITY), | ||
@@ -495,3 +509,3 @@ }; | ||
const data = res.data; | ||
if (data.cod) { | ||
if (data.cod && parseInt(data.cod) !== 200) { | ||
throw new Error(JSON.stringify(data)); | ||
@@ -498,0 +512,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function currentParser(data) { | ||
const w = data.current.weather[0]; | ||
const w = data.weather[0]; | ||
return { | ||
lat: data.lat, | ||
lon: data.lon, | ||
dt: new Date(data.current.dt * 1000), | ||
dtRaw: data.current.dt, | ||
lat: data.coord.lat, | ||
lon: data.coord.lon, | ||
dt: new Date(data.dt * 1000), | ||
dtRaw: data.dt, | ||
timezone: data.timezone, | ||
timezoneOffset: data.timezone_offset, | ||
astronomical: { | ||
sunrise: new Date(data.current.sunrise * 1000), | ||
sunriseRaw: data.current.sunrise, | ||
sunset: new Date(data.current.sunset * 1000), | ||
sunsetRaw: data.current.sunset, | ||
sunrise: new Date(data.sys.sunrise * 1000), | ||
sunriseRaw: data.sys.sunrise, | ||
sunset: new Date(data.sys.sunset * 1000), | ||
sunsetRaw: data.sys.sunset, | ||
}, | ||
weather: { | ||
temp: { cur: data.current.temp }, | ||
feelsLike: { cur: data.current.feels_like }, | ||
pressure: data.current.pressure, | ||
humidity: data.current.humidity, | ||
dewPoint: data.current.dew_point, | ||
clouds: data.current.clouds, | ||
uvi: data.current.uvi, | ||
visibility: data.current.visibility, | ||
temp: { cur: data.main.temp }, | ||
feelsLike: { cur: data.main.feels_like }, | ||
pressure: data.main.pressure, | ||
humidity: data.main.humidity, | ||
dewPoint: data.dew_point, | ||
clouds: data.clouds.all, | ||
uvi: data.uvi, | ||
visibility: data.visibility, | ||
wind: { | ||
deg: data.current.wind_deg, | ||
gust: data.current.wind_gust, | ||
speed: data.current.wind_speed, | ||
deg: data.wind.deg, | ||
gust: data.wind.gust, | ||
speed: data.wind.speed, | ||
}, | ||
rain: data.current.rain ? data.current.rain["1h"] : 0, | ||
snow: data.current.snow ? data.current.snow["1h"] : 0, | ||
rain: data.rain ? data.rain["1h"] : 0, | ||
snow: data.snow ? data.snow["1h"] : 0, | ||
conditionId: w.id, | ||
@@ -35,0 +35,0 @@ main: w.main, |
@@ -28,3 +28,3 @@ import { Icon, WeatherBase, WindData } from "./index"; | ||
*/ | ||
dewPoint: number; | ||
dewPoint: number | undefined; | ||
/** | ||
@@ -37,3 +37,3 @@ * Cloudiness, % | ||
*/ | ||
uvi: number; | ||
uvi: number | undefined; | ||
/** | ||
@@ -40,0 +40,0 @@ * Average visibility, metres |
import { CurrentWeather } from "./current"; | ||
import { ForecastWeather } from "./forecast"; | ||
import { MinutelyWeather } from "./minutely"; | ||
@@ -6,2 +7,3 @@ import { HourlyWeather } from "./hourly"; | ||
export * from "./current"; | ||
export * from "./forecast"; | ||
export * from "./minutely"; | ||
@@ -44,3 +46,3 @@ export * from "./hourly"; | ||
*/ | ||
gust: number; | ||
gust: number | undefined; | ||
/** | ||
@@ -75,3 +77,3 @@ * Wind direction, degrees (meteorological) | ||
*/ | ||
timezone: string; | ||
timezone: string | undefined; | ||
/** | ||
@@ -82,3 +84,3 @@ * Date and time, Unix, UTC | ||
} | ||
export type Weather = WeatherBase & CurrentWeather & MinutelyWeather & HourlyWeather & DailyWeather; | ||
export type Weather = WeatherBase & CurrentWeather & ForecastWeather & MinutelyWeather & HourlyWeather & DailyWeather; | ||
export interface Everything { | ||
@@ -85,0 +87,0 @@ lat: number; |
@@ -18,4 +18,5 @@ "use strict"; | ||
__exportStar(require("./current"), exports); | ||
__exportStar(require("./forecast"), exports); | ||
__exportStar(require("./minutely"), exports); | ||
__exportStar(require("./hourly"), exports); | ||
__exportStar(require("./daily"), exports); |
{ | ||
"name": "openweather-api-node", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Simple Node.js package that makes it easy to work with OpenWeather API", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -34,5 +34,7 @@ <br> | ||
Currently Supported APIs: | ||
* Weather (from OneCall) - get **current weather** and weather **forecast for up to 7 days** | ||
* Current Weather - get **current weather** | ||
* Forecast - get weather **forecast for up to 5 days** with 3-hour step | ||
* OneCall - get **current weather** and weather **forecast for up to 7 days** | ||
* Geocoding - get location **latitude and longitude from its name** and vice versa | ||
* Historical (from OneCall) - get weather from **previous 5 days** | ||
* Historical - get weather from **previous 5 days** | ||
* Air pollution - get **current, forecasted and historical data about air pollution** | ||
@@ -39,0 +41,0 @@ |
@@ -7,10 +7,9 @@ import fs from "fs"; | ||
const weather = new OpenWeatherAPI({ | ||
key: key, | ||
locationName: "Hong Kong", | ||
}); | ||
describe("Error tests:", function () { | ||
describe("Error tests:", () => { | ||
const emptyValues = ["", 0, null, undefined, false, NaN]; | ||
const weather = new OpenWeatherAPI({ | ||
key, locationName: "Hong Kong" | ||
}); | ||
it("handles invalid key", async () => { | ||
@@ -25,71 +24,51 @@ try { | ||
it("handles wrong coordinates", async () => { | ||
try { | ||
weather.setLocationByCoordinates("-200" as unknown as number, 78); | ||
} catch (err: any) { | ||
expect( | ||
err.message.toLowerCase().includes("invalid coordinates") | ||
).toBeTruthy(); | ||
} | ||
it("handles wrong coordinates", () => { | ||
expect( | ||
() => weather.setLocationByCoordinates("-200" as any, 78) | ||
).toThrow(/invalid coordinates/i); | ||
}); | ||
it("handles wrong location name", async () => { | ||
try { | ||
await weather.getCurrent({ locationName: "ptero" }); | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("ptero")).toBeTruthy(); | ||
} | ||
await expect( | ||
weather.getCurrent({ locationName: "ptero" }) | ||
).rejects.toThrow(/ptero/i); | ||
}); | ||
it("handles wrong language", async () => { | ||
try { | ||
weather.setLanguage("ptero" as Language); | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("ptero")).toBeTruthy(); | ||
} | ||
it("handles wrong language", () => { | ||
expect( | ||
() => weather.setLanguage("ptero" as Language) | ||
).toThrow(/ptero/i); | ||
}); | ||
it("handles wrong unit", async () => { | ||
try { | ||
weather.setUnits("ptero" as Unit); | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("ptero")).toBeTruthy(); | ||
} | ||
it("handles wrong unit", () => { | ||
expect( | ||
() => weather.setUnits("ptero" as Unit) | ||
).toThrow(/ptero/i); | ||
}); | ||
it("handles unknown parameter", async () => { | ||
try { | ||
await weather.getCurrent({ ptero: "" } as any); | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("ptero")).toBeTruthy(); | ||
} | ||
await expect( | ||
weather.getCurrent({ ptero: "" } as any) | ||
).rejects.toThrow(/ptero/i); | ||
}); | ||
it("handles wrong type of option argument", async () => { | ||
try { | ||
await weather.getCurrent("ptero" as {}); | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("provide {}")).toBeTruthy(); | ||
} | ||
await expect( | ||
weather.getCurrent("ptero" as {}) | ||
).rejects.toThrow(/provide {}/i); | ||
}); | ||
it("handles empty location name", async () => { | ||
it("handles empty location name", () => { | ||
emptyValues.forEach((element) => { | ||
try { | ||
weather.setLocationByName(element as string); | ||
expect(false).toBe(true); // TODO: fail test | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("empty")).toBeTruthy(); | ||
} | ||
expect( | ||
() => weather.setLocationByName(element as string) | ||
).toThrow(/empty/i); | ||
}); | ||
}); | ||
it("handles empty key", async () => { | ||
it("handles empty key", () => { | ||
emptyValues.forEach((element) => { | ||
try { | ||
weather.setKey(element as string); | ||
expect(false).toBe(true); // TODO: fail test | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("empty")).toBeTruthy(); | ||
} | ||
expect( | ||
() => weather.setKey(element as string) | ||
).toThrow(/empty/i); | ||
}); | ||
@@ -99,37 +78,19 @@ }); | ||
it("handles future in history", async () => { | ||
try { | ||
await weather.getHistory(new Date().getTime() + 900000); | ||
} catch (err: any) { | ||
expect( | ||
err.message.toLowerCase().includes("requested time is in the future") | ||
).toBeTruthy(); | ||
return; | ||
} | ||
expect(false).toBe(true); // TODO: fail test | ||
await expect( | ||
weather.getHistory(new Date().getTime() + 900000) | ||
).rejects.toThrow(/requested time is in the future/i); | ||
}); | ||
it("handles not within 5 days in history", async () => { | ||
try { | ||
await weather.getHistory(new Date().getTime() - 6 * 24 * 60 * 60 * 1000); | ||
} catch (err: any) { | ||
expect( | ||
err.message | ||
.toLowerCase() | ||
.includes("requested time is out of allowed range of 5 days back") | ||
).toBeTruthy(); | ||
return; | ||
} | ||
expect(false).toBe(true); // TODO: fail test | ||
await expect( | ||
weather.getHistory(new Date().getTime() - 6 * 24 * 60 * 60 * 1000) | ||
).rejects.toThrow(/requested time is out of allowed range of 5 days back/i); | ||
}); | ||
it("handles no time in history", async () => { | ||
try { | ||
await expect( | ||
// @ts-ignore | ||
await weather.getHistory(); | ||
} catch (err: any) { | ||
expect(err.message.toLowerCase().includes("provide time")).toBeTruthy(); | ||
return; | ||
} | ||
expect(false).toBe(true); // TODO: fail test | ||
weather.getHistory() | ||
).rejects.toThrow(/provide time/i); | ||
}); | ||
}); |
@@ -7,11 +7,9 @@ import fs from "fs"; | ||
const weather = new OpenWeatherAPI({ | ||
key: key, | ||
}); | ||
describe("Getting tests:", () => { | ||
const weather = new OpenWeatherAPI({ key }); | ||
describe("Getting tests:", function () { | ||
it("gets location", async () => { | ||
weather.setLocationByCoordinates(40.71, -74); | ||
let location = await weather.getLocation(); | ||
expect(location!.name.toLowerCase().includes("new york")).toBeTruthy(); | ||
expect(location!.name).toMatch(/new york/i); | ||
}); | ||
@@ -30,8 +28,25 @@ | ||
it("gets forecast", async () => { | ||
let forecast = await weather.getForecast(20); | ||
expect(forecast).toBeInstanceOf(Array); | ||
if (!forecast.length) { | ||
console.log("\t\x1b[31mEmpty forecast: ", forecast); | ||
} else { | ||
expect(forecast.length).toBe(20); | ||
expect(typeof forecast[Math.floor(Math.random() * 17)].weather.rain).toBe( | ||
"number" | ||
); | ||
} | ||
}); | ||
it("gets minutely", async () => { | ||
weather.setLocationByCoordinates(40.71, -74); | ||
let minutely = await weather.getMinutelyForecast(48); | ||
expect(minutely).toBeInstanceOf(Array); | ||
if (!minutely.length) { | ||
console.log("\t\x1b[31mEmpty minutely: ", minutely); | ||
expect(typeof minutely).toBe("object"); | ||
} else { | ||
@@ -48,5 +63,7 @@ expect(minutely.length).toBe(48); | ||
let hourly = await weather.getHourlyForecast(10); | ||
expect(hourly).toBeInstanceOf(Array); | ||
if (!hourly.length) { | ||
console.log("\t\x1b[31mEmpty hourly: ", hourly); | ||
expect(typeof hourly).toBe("object"); | ||
} else { | ||
@@ -63,5 +80,7 @@ expect(hourly.length).toBe(10); | ||
let daily = await weather.getDailyForecast(3); | ||
expect(daily).toBeInstanceOf(Array); | ||
if (!daily.length) { | ||
console.log("\t\x1b[31mEmpty daily: ", daily); | ||
expect(typeof daily).toBe("object"); | ||
} else { | ||
@@ -78,3 +97,3 @@ expect(daily.length).toBe(3); | ||
let alerts = await weather.getAlerts(); | ||
expect(typeof alerts).toBe("object"); | ||
expect(alerts).toBeInstanceOf(Array); | ||
}); | ||
@@ -85,7 +104,11 @@ | ||
let everything = await weather.getEverything(); | ||
expect(typeof everything.current.weather.temp.cur).toBe("number"); | ||
expect(typeof everything.minutely).toBe("object"); | ||
expect(everything.minutely).toBeInstanceOf(Array); | ||
expect( | ||
typeof everything.hourly[Math.floor(Math.random() * 20)].weather.rain | ||
).toBe("number"); | ||
expect( | ||
@@ -117,2 +140,3 @@ typeof everything.daily[Math.floor(Math.random() * 5)].weather.rain | ||
}); | ||
expect(pollution.length).toBe(10); | ||
@@ -129,2 +153,3 @@ expect( | ||
let dateFrom12HoursAgo = new Date().setHours(currentDate.getHours() - 12); | ||
let pollution = await weather.getHistoryAirPollution( | ||
@@ -135,2 +160,3 @@ dateFrom12HoursAgo, | ||
); | ||
expect(pollution.length).toBe(12); | ||
@@ -137,0 +163,0 @@ expect( |
@@ -7,9 +7,8 @@ import fs from "fs"; | ||
const weather = new OpenWeatherAPI(); | ||
describe("Options tests:", () => { | ||
const weather = new OpenWeatherAPI(); | ||
describe("Options tests:", function () { | ||
it("handles key in options", async () => { | ||
await weather.getCurrent({ | ||
locationName: "Ottawa", | ||
key: key, | ||
locationName: "Ottawa", key | ||
}); | ||
@@ -16,0 +15,0 @@ }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
80445
51
2155
94
0