import type { WithAbortSignal } from "#Source/abort/index.ts" import { generalFetch } from "#Source/request/index.ts" import type { Lang, Unit } from "../base.ts" export type GridWeatherHourlyForecastHours = "24h" | "72h" const internalGridWeatherHourlyForecastUnitSet = new Set(["m", "i"]) const internalGridWeatherHourlyForecastHoursSet = new Set([ "24h", "72h", ]) /** * @description 调用和风天气格点逐小时天气预报接口时使用的参数。 * * @example * ;``` * const options: GridWeatherHourlyForecastOptions = { * baseUrl: "https://abcxyz.qweatherapi.com", * jwt: "eyJhbGciOiJFZERTQSJ9.payload.signature", * hours: "24h", * location: "116.41,39.92", * unit: "m", * } * ``` */ export interface GridWeatherHourlyForecastOptions extends WithAbortSignal { /** * @description 和风天气 API Base URL,例如 `https://abcxyz.qweatherapi.com`。 */ baseUrl: string /** * @description 用于 `Authorization: Bearer` 请求头的 JWT。 */ jwt: string hours: GridWeatherHourlyForecastHours /** * @description 需要查询地区的经度、纬度坐标,例如 `116.41,39.92`。 */ location: string /** * @description 返回结果的多语言代码。 */ lang?: Lang | undefined /** * @description 数据单位设置,`m` 为公制,`i` 为英制。 */ unit?: Unit | undefined /** * @description 请求超时时间,单位为毫秒。 */ timeout?: number | undefined } /** * @description 格点逐小时天气预报响应中的单小时数据。 */ export interface GridWeatherHourlyForecastResultHourly { /** * @description 预报时间。 */ fxTime: string /** * @description 温度。 */ temp: string /** * @description 天气状况图标代码。 */ icon: string /** * @description 天气状况文字描述。 */ text: string /** * @description 风向 360 角度。 */ wind360: string /** * @description 风向。 */ windDir: string /** * @description 风力等级。 */ windScale: string /** * @description 风速,单位为公里/小时。 */ windSpeed: string /** * @description 相对湿度,百分比数值。 */ humidity: string /** * @description 当前小时累计降水量。 */ precip: string /** * @description 大气压强。 */ pressure: string /** * @description 云量,可能为空。 */ cloud: string /** * @description 露点温度,可能为空。 */ dew: string } /** * @description 和风天气格点逐小时天气预报接口的响应结果。 */ export interface GridWeatherHourlyForecastResultRefer { /** * @description 原始数据来源或数据源说明。 */ sources?: string[] | undefined /** * @description 数据许可或版权声明。 */ license?: string[] | undefined } export interface GridWeatherHourlyForecastResult { /** * @description 接口状态码。 */ code: string /** * @description 当前 API 的最近更新时间。 */ updateTime: string /** * @description 当前数据对应的响应式天气页面链接。 */ fxLink: string hourly: GridWeatherHourlyForecastResultHourly[] /** * @description 响应中的来源与许可信息。 */ refer?: GridWeatherHourlyForecastResultRefer | undefined } const internalValidateGridWeatherHourlyForecastOptions = ( options: GridWeatherHourlyForecastOptions, ): { baseUrl: string jwt: string location: string hours: GridWeatherHourlyForecastHours } => { const baseUrl = options.baseUrl.trim() const jwt = options.jwt.trim() const location = options.location.trim() if (baseUrl === "") { throw new TypeError("GridWeatherHourlyForecast baseUrl must not be empty.") } if (jwt === "") { throw new TypeError("GridWeatherHourlyForecast jwt must not be empty.") } if (location === "") { throw new TypeError("GridWeatherHourlyForecast location must not be empty.") } if (internalGridWeatherHourlyForecastHoursSet.has(options.hours) === false) { throw new RangeError("GridWeatherHourlyForecast hours must be one of: 24h, 72h.") } if ( options.unit !== undefined && internalGridWeatherHourlyForecastUnitSet.has(options.unit) === false ) { throw new RangeError("GridWeatherHourlyForecast unit must be one of: m, i.") } return { baseUrl, jwt, location, hours: options.hours, } } /** * @description 获取指定坐标的格点逐小时天气预报。 * * @see {@link https://dev.qweather.com/docs/api/weather/grid-weather-hourly-forecast/} */ export const gridWeatherHourlyForecast = async ( options: GridWeatherHourlyForecastOptions, ): Promise => { const { baseUrl, jwt, location, hours } = internalValidateGridWeatherHourlyForecastOptions(options) const { lang, unit, timeout, abortSignal } = options return await generalFetch< { query: { location: string lang?: Lang | undefined unit?: Unit | undefined } }, { type: "json" data: GridWeatherHourlyForecastResult } >({ baseUrl, path: `/v7/grid-weather/${hours}`, method: "get", headers: { Authorization: `Bearer ${jwt}`, }, query: { location, lang, unit, }, responseType: "json", timeout, abortSignal, }).getJson() }