iqair-api 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/client/iqair-client.config.ts","../src/types/station/station.interface.ts","../src/types/station/station-with-distance.interface.ts","../src/types/station/station-item.interface.ts","../src/types/aqi/pollutant.interface.ts","../src/types/aqi/current-conditions.interface.ts","../src/types/forecast/forecast-item.interface.ts","../src/types/station/station-details.interface.ts","../src/types/history/historical-data-point.interface.ts","../src/types/aqi/aqi-response.interface.ts","../src/types/params/get-stations.params.ts","../src/types/params/get-station-aqi.params.ts","../src/types/params/get-nearest-station.params.ts","../src/types/params/get-nearest-stations.params.ts","../src/types/params/get-aqi-for-location.params.ts","../src/types/internal/station-list-response.interface.ts","../src/types/internal/individual-station-response.interface.ts","../src/client/iqair-client.ts","../src/client/create-iqair-client.ts","../src/exceptions/iqair.exception.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,OAAA,CAAA,EAAA,MAAA;;;;;;UCAA,OAAA;EDAA,EAAA,EAAA,MAAA;;;;ECAA,SAAA,EAAO,MAAA;;;;;;ADAP,UEEA,mBAAA,SAA4B,OFFX,CAAA;;;;;UGAjB,WAAA;EHAA,EAAA,EAAA,MAAA;;;;ICAA,QAAO,EAAA,MAAA;;;;ICEP,GAAA,EAAA;;;;ICFA,CAAA;;;;;;UCAA,SAAA;EJAA,IAAA,EAAA,MAAA;;;;ECAA,aAAO,EAAA,MAAA;;;;ADAP,UKEA,iBAAA,CLFiB;;;;ECAjB,aAAO,EAAA,MAAA;;;;ECEP,QAAA,CAAA,EAAA,MAAA;;;;ICFA,KAAA,EAAA,MAAW;;;eEiBb;EDjBE,cAAS,CAAA,EAAA,MAAA;;;;UEAT,YAAA;ENAA,EAAA,EAAA,MAAA;;;;ECAA,IAAA,CAAA,EAAA;;;;ECEA,IAAA,CAAA,EAAA,MAAA;;;;ICFA,GAAA,EAAA,MAAW;;;;;UIGX,cAAA;;;ENHA,OAAA,EAAA,MAAO;;;;ECEP,WAAA,EAAA;;;;ECFA,OAAA,EIcN,iBJdiB;;YIgBhB;WACD;EHjBM,CAAA;;;;UIAA,mBAAA;ERAA,EAAA,EAAA,MAAA;;;;ICAA,aAAO,EAAA,MAAA;;;;ICEP,aAAA,EAAA,MAAoB;;;;ICFpB,aAAW,EAAA,MAAA;;;;ICAX,aAAS,EAAA,MAAA;;;;ICET,aAAA,EAAA,MAAiB;;;;ICFjB,aAAY,EAAA,MAAA;;;;ECGZ,WAAA,CAAA,EAAA,MAAc,GAAA;IAWpB,GAAA,EAAA,MAAA;IAEC,GAAA,EAAA,MAAA;EACD,CAAA;EAAY,IAAA,CAAA,EAAA;;;;ECjBN,SAAA,CAAA,EAAA,MAAA;;;;;ARAA,USEA,WAAA,CTFiB;;;;ICAjB,GAAA,EAAA,MAAO;;;;ICEP,EAAA,EAAA,MAAA;;;;ICFA,SAAA,CAAW,EAAA,MAAA;;;;ICAX,IAAA,CAAA,EAAA;;;;ECEA,CAAA;eIqBF;;;IHvBE,aAAY,EAAA,MAAA;;;;ICGZ,MAAA,EE2BL,mBF3BmB,EAAA;IAWpB,KAAA,EEiBA,mBFjBA,EAAA;EAEC,CAAA;;;;UGhBK,iBAAA;EVAA,UAAA,EAAA,MAAA;;;;;UWAA,mBAAA;EXAA,UAAA,EAAA,MAAA;;;;UYAA,uBAAA;EZAA,GAAA,EAAA,MAAA;;;;;;UaAA,wBAAA;EbAA,GAAA,EAAA,MAAA;;;;ACAjB;;;UaAiB,uBAAA;EdAA,GAAA,EAAA,MAAA;;;;;;AAAA,UeEA,eAAA,CfFiB;;UeIxB;cACI;EdLG,CAAA;;UcQP;cACI;EbPG,CAAA;;UaWA,mBAAA;;IZbA,IAAA,EYeP,eZfkB;;;UYkBlB;EXlBO,CAAA;;;;UYGA,qBAAA;YACL;;IfJK,IAAA,CAAA,EAAO;;iBeQP;gBACD;MdPC,CAAA;;;;ACFA,UaeA,yBAAA,CbfW;;UaiBlB;;EZjBO,UAAA,EAAS;UYoBhB;;;;;cCKG,WAAA;;;EhBzBI,iBAAO,SAAA;uBgB8BF;;sBAUM,oBAAoB,QAAQ;EftCvC,aAAA,CAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/client/iqair-client.config.ts","../src/types/station/station.interface.ts","../src/types/station/station-with-distance.interface.ts","../src/types/station/station-item.interface.ts","../src/types/aqi/pollutant.interface.ts","../src/types/aqi/current-conditions.interface.ts","../src/types/forecast/forecast-item.interface.ts","../src/types/station/station-details.interface.ts","../src/types/history/historical-data-point.interface.ts","../src/types/aqi/aqi-response.interface.ts","../src/types/params/get-stations.params.ts","../src/types/params/get-station-aqi.params.ts","../src/types/params/get-nearest-station.params.ts","../src/types/params/get-nearest-stations.params.ts","../src/types/params/get-aqi-for-location.params.ts","../src/types/internal/station-list-response.interface.ts","../src/types/internal/individual-station-response.interface.ts","../src/client/iqair-client.ts","../src/client/create-iqair-client.ts","../src/exceptions/iqair.exception.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,OAAA,CAAA,EAAA,MAAA;;;;;;UCAA,OAAA;EDAA,EAAA,EAAA,MAAA;;;;ECAA,SAAA,EAAO,MAAA;;;;;;ADAP,UEEA,mBAAA,SAA4B,OFFX,CAAA;;;;;UGAjB,WAAA;EHAA,EAAA,EAAA,MAAA;;;;ICAA,QAAO,EAAA,MAAA;;;;ICEP,GAAA,EAAA;;;;ICFA,CAAA;;;;;;UCAA,SAAA;EJAA,IAAA,EAAA,MAAA;;;;ECAA,aAAO,EAAA,MAAA;;;;ADAP,UKEA,iBAAA,CLFiB;;;;ECAjB,aAAO,EAAA,MAAA;;;;ECEP,QAAA,CAAA,EAAA,MAAA;;;;ICFA,KAAA,EAAA,MAAW;;;eEiBb;EDjBE,cAAS,CAAA,EAAA,MAAA;;;;UEAT,YAAA;ENAA,EAAA,EAAA,MAAA;;;;ECAA,IAAA,CAAA,EAAA;;;;ECEA,IAAA,CAAA,EAAA,MAAA;;;;ICFA,GAAA,EAAA,MAAW;;;;;UIGX,cAAA;;;ENHA,OAAA,EAAA,MAAO;;;;ECEP,WAAA,EAAA;;;;ECFA,OAAA,EIcN,iBJdiB;;YIgBhB;WACD;EHjBM,CAAA;;;;UIAA,mBAAA;ERAA,EAAA,EAAA,MAAA;;;;ICAA,aAAO,EAAA,MAAA;;;;ICEP,aAAA,EAAA,MAAoB;;;;ICFpB,aAAW,EAAA,MAAA;;;;ICAX,aAAS,EAAA,MAAA;;;;ICET,aAAA,EAAA,MAAiB;;;;ICFjB,aAAY,EAAA,MAAA;;;;ECGZ,WAAA,CAAA,EAAA,MAAc,GAAA;IAWpB,GAAA,EAAA,MAAA;IAEC,GAAA,EAAA,MAAA;EACD,CAAA;EAAY,IAAA,CAAA,EAAA;;;;ECjBN,SAAA,CAAA,EAAA,MAAA;;;;;ARAA,USEA,WAAA,CTFiB;;;;ICAjB,GAAA,EAAA,MAAO;;;;ICEP,EAAA,EAAA,MAAA;;;;ICFA,SAAA,CAAW,EAAA,MAAA;;;;ICAX,IAAA,CAAA,EAAA;;;;ECEA,CAAA;eIqBF;;;IHvBE,aAAY,EAAA,MAAA;;;;ICGZ,MAAA,EE2BL,mBF3BmB,EAAA;IAWpB,KAAA,EEiBA,mBFjBA,EAAA;EAEC,CAAA;;;;UGhBK,iBAAA;EVAA,UAAA,EAAA,MAAA;;;;;UWAA,mBAAA;EXAA,UAAA,EAAA,MAAA;;;;UYAA,uBAAA;EZAA,GAAA,EAAA,MAAA;;;;;;UaAA,wBAAA;EbAA,GAAA,EAAA,MAAA;;;;ACAjB;;;UaAiB,uBAAA;EdAA,GAAA,EAAA,MAAA;;;;;;AAAA,UeEA,eAAA,CfFiB;;UeIxB;cACI;EdLG,CAAA;;UcQP;cACI;EbPG,CAAA;;UaWA,mBAAA;;IZbA,IAAA,EYeP,eZfkB;;;UYkBlB;EXlBO,CAAA;;;;UYGA,qBAAA;YACL;;IfJK,IAAA,CAAA,EAAO;;iBeQP;gBACD;MdPC,CAAA;;;;ACFA,UaeA,yBAAA,CbfW;;UaiBlB;;EZjBO,UAAA,EAAS;UYoBhB;;;;;cCKG,WAAA;;;EhBzBI,iBAAO,SAAA;uBgB8BF;;sBAUM,oBAAoB,QAAQ;EftCvC,aAAA,CAAA,MAAA,EemEa,mBfnEsB,CAAA,EemEA,OfnEA,CemEQ,WfnER,CAAA;4BeyHxC,0BACP,QAAQ;6BAMD,2BACP,QAAQ;4BAMD,0BACP,QAAQ;Ad1Ib;;;iBeGgB,iBAAA,UAA2B,oBAAoB;;;cCHlD,cAAA,SAAuB,KAAA;EnBAnB,SAAA,UAAA,EAAiB,MAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -9,8 +9,8 @@ const DEFAULT_LOCALE = "in-en";
|
|
|
9
9
|
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/constants/routes.constant.ts
|
|
12
|
-
const STATION_LIST_ROUTES =
|
|
13
|
-
const INDIVIDUAL_STATION_ROUTES =
|
|
12
|
+
const STATION_LIST_ROUTES = "routes/$(locale),routes/$(locale).profile.$slug";
|
|
13
|
+
const INDIVIDUAL_STATION_ROUTES = "routes/$";
|
|
14
14
|
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/constants/user-agent.constant.ts
|
|
@@ -126,6 +126,7 @@ var IQAirClient = class {
|
|
|
126
126
|
limit: params.limit ?? 500,
|
|
127
127
|
_routes: STATION_LIST_ROUTES
|
|
128
128
|
});
|
|
129
|
+
console.log(url.toString());
|
|
129
130
|
const stationsData = ((await this.request(url.toString()))["routes/$(locale).profile.$slug"]?.data)?.stationsMapData?.data;
|
|
130
131
|
if (!stationsData || stationsData.length === 0) return [];
|
|
131
132
|
return stationsData.map((station) => ({
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["nearest: StationWithDistance | null","withDistances: StationWithDistance[]"],"sources":["../src/constants/base-url.constant.ts","../src/constants/locale.constant.ts","../src/constants/routes.constant.ts","../src/constants/user-agent.constant.ts","../src/exceptions/iqair.exception.ts","../src/utils/decoder.util.ts","../src/utils/geo.util.ts","../src/utils/build-url.util.ts","../src/client/iqair-client.ts","../src/client/create-iqair-client.ts"],"sourcesContent":["export const DEFAULT_BASE_URL = \"https://www.iqair.com\";\n","export const DEFAULT_LOCALE = \"in-en\";\n","export const STATION_LIST_ROUTES = encodeURIComponent(\n \"routes/$(locale),routes/$(locale).profile.$slug\"\n);\n\nexport const INDIVIDUAL_STATION_ROUTES = encodeURIComponent(\"routes/$\");\n","export const DEFAULT_USER_AGENT =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36\";\n","export class IQAirException extends Error {\n readonly statusCode: number;\n readonly body?: string;\n\n constructor(message: string, statusCode: number, body?: string) {\n super(message);\n this.name = \"IQAirException\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n","import { UNSAFE_decodeViaTurboStream } from \"react-router\";\nimport { IQAirException } from \"../exceptions\";\n\nasync function resolveAllPromises<T>(obj: T): Promise<T> {\n if (obj instanceof Promise) {\n const resolved = await obj;\n return resolveAllPromises(resolved);\n }\n\n if (Array.isArray(obj)) {\n const resolved = await Promise.all(obj.map(resolveAllPromises));\n return resolved as T;\n }\n\n if (obj !== null && typeof obj === \"object\") {\n const entries = Object.entries(obj);\n const resolvedEntries = await Promise.all(\n entries.map(async ([key, value]) => [key, await resolveAllPromises(value)])\n );\n return Object.fromEntries(resolvedEntries) as T;\n }\n\n return obj;\n}\n\nexport async function decodeTurboStream<T>(\n stream: ReadableStream<Uint8Array>\n): Promise<T> {\n const decoded = await UNSAFE_decodeViaTurboStream(stream, globalThis);\n await decoded.done;\n const resolved = await resolveAllPromises(decoded.value);\n return resolved as T;\n}\n\nexport async function fetchAndDecode<T>(url: string, userAgent: string): Promise<T> {\n const response = await fetch(url, {\n headers: {\n \"User-Agent\": userAgent,\n Accept: \"*/*\",\n \"Accept-Language\": \"en-US,en;q=0.9\",\n },\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new IQAirException(\n `Request failed: ${response.status} ${response.statusText}`,\n response.status,\n text\n );\n }\n\n if (!response.body) {\n throw new IQAirException(\"Response body is null\", 500);\n }\n\n return decodeTurboStream<T>(response.body);\n}\n","import type { Station, StationWithDistance } from \"../types\";\n\nconst EARTH_RADIUS_KM = 6371;\n\nfunction toRadians(degrees: number): number {\n return degrees * (Math.PI / 180);\n}\n\nexport function haversineDistance(\n lat1: number,\n lon1: number,\n lat2: number,\n lon2: number\n): number {\n const dLat = toRadians(lat2 - lat1);\n const dLon = toRadians(lon2 - lon1);\n\n const a =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(toRadians(lat1)) *\n Math.cos(toRadians(lat2)) *\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2);\n\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n return EARTH_RADIUS_KM * c;\n}\n\nexport function findNearestStation(\n latitude: number,\n longitude: number,\n stations: Station[]\n): StationWithDistance | null {\n if (stations.length === 0) {\n return null;\n }\n\n let nearest: StationWithDistance | null = null;\n let minDistance = Infinity;\n\n for (const station of stations) {\n const distance = haversineDistance(\n latitude,\n longitude,\n station.latitude,\n station.longitude\n );\n\n if (distance < minDistance) {\n minDistance = distance;\n nearest = { ...station, distance };\n }\n }\n\n return nearest;\n}\n\nexport function findNearestStations(\n latitude: number,\n longitude: number,\n stations: Station[],\n limit: number = 5\n): StationWithDistance[] {\n const withDistances: StationWithDistance[] = stations.map((station) => ({\n ...station,\n distance: haversineDistance(\n latitude,\n longitude,\n station.latitude,\n station.longitude\n ),\n }));\n\n withDistances.sort((a, b) => a.distance - b.distance);\n\n return withDistances.slice(0, limit);\n}\n","export function buildUrl(\n baseUrl: string,\n path: string,\n params?: Record<string, string | number | undefined>\n): URL {\n const url = new URL(baseUrl + path);\n\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n\n return url;\n}\n","import { IQAirClientConfig } from \"./iqair-client.config\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_LOCALE,\n DEFAULT_USER_AGENT,\n STATION_LIST_ROUTES,\n INDIVIDUAL_STATION_ROUTES,\n} from \"../constants\";\nimport { IQAirException } from \"../exceptions\";\nimport { fetchAndDecode } from \"../utils/decoder.util\";\nimport { findNearestStation, findNearestStations } from \"../utils/geo.util\";\nimport { buildUrl } from \"../utils/build-url.util\";\nimport type {\n Station,\n StationWithDistance,\n AQIResponse,\n StationListResponse,\n IndividualStationResponse,\n GetStationsParams,\n GetStationAQIParams,\n GetNearestStationParams,\n GetNearestStationsParams,\n GetAQIForLocationParams,\n} from \"../types\";\n\nexport class IQAirClient {\n private readonly baseUrl: string;\n private readonly locale: string;\n private readonly userAgent: string;\n\n constructor(config: IQAirClientConfig = {}) {\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.locale = config.locale ?? DEFAULT_LOCALE;\n this.userAgent = config.userAgent ?? DEFAULT_USER_AGENT;\n }\n\n private async request<T>(url: string): Promise<T> {\n return fetchAndDecode<T>(url, this.userAgent);\n }\n\n async getStations(params: GetStationsParams): Promise<Station[]> {\n const url = buildUrl(\n this.baseUrl,\n `/${this.locale}/profile/${params.dataSource}.data`,\n {\n limit: params.limit ?? 500,\n _routes: STATION_LIST_ROUTES,\n }\n );\n\n const data = await this.request<StationListResponse>(url.toString());\n const routeData = data[\"routes/$(locale).profile.$slug\"]?.data;\n const stationsData = routeData?.stationsMapData?.data;\n\n if (!stationsData || stationsData.length === 0) {\n return [];\n }\n\n return stationsData.map((station) => ({\n id: station.id,\n name: station.name,\n url: station.url,\n latitude: station.coordinates.latitude,\n longitude: station.coordinates.longitude,\n }));\n }\n\n async getStationAQI(params: GetStationAQIParams): Promise<AQIResponse> {\n const url = buildUrl(\n this.baseUrl,\n `/${this.locale}${params.stationUrl}.data`,\n {\n _routes: INDIVIDUAL_STATION_ROUTES,\n }\n );\n\n const data = await this.request<IndividualStationResponse>(url.toString());\n const routeData = data.root?.data || data[\"routes/$\"]?.data;\n const details = routeData?.details;\n\n if (!details || !details.current) {\n throw new IQAirException(\"No station details found in response\", 404);\n }\n\n const measurements = routeData?.measurements?.data?.measurements;\n const historical = measurements\n ? {\n hourly: measurements.hourly || [],\n daily: measurements.daily || [],\n }\n : undefined;\n\n return {\n station: {\n id: details.id,\n name: details.name,\n url: params.stationUrl,\n distance: 0,\n },\n current: {\n ts: details.current.ts,\n aqi: details.current.aqi,\n mainPollutant: details.current.mainPollutant,\n concentration: details.current.concentration,\n condition: details.current.condition,\n temperature: details.current.temperature,\n humidity: details.current.humidity,\n pressure: details.current.pressure,\n wind: details.current.wind,\n },\n pollutants: details.current.pollutants?.map((p) => ({\n name: p.pollutantName,\n aqi: p.aqi,\n concentration: p.concentration,\n unit: p.unit,\n })),\n historical,\n };\n }\n\n async getNearestStation(\n params: GetNearestStationParams\n ): Promise<StationWithDistance | null> {\n const stations = await this.getStations({ dataSource: params.dataSource });\n return findNearestStation(params.lat, params.lng, stations);\n }\n\n async getNearestStations(\n params: GetNearestStationsParams\n ): Promise<StationWithDistance[]> {\n const stations = await this.getStations({ dataSource: params.dataSource });\n return findNearestStations(params.lat, params.lng, stations, params.limit);\n }\n\n async getAQIForLocation(\n params: GetAQIForLocationParams\n ): Promise<AQIResponse | null> {\n const nearestStation = await this.getNearestStation({\n lat: params.lat,\n lng: params.lng,\n dataSource: params.dataSource,\n });\n\n if (!nearestStation) {\n return null;\n }\n\n const aqi = await this.getStationAQI({ stationUrl: nearestStation.url });\n aqi.station.distance = nearestStation.distance;\n return aqi;\n }\n}\n","import { IQAirClient } from \"./iqair-client\";\nimport { IQAirClientConfig } from \"./iqair-client.config\";\n\nexport function createIQAirClient(config?: IQAirClientConfig): IQAirClient {\n return new IQAirClient(config);\n}\n"],"mappings":";;;AAAA,MAAa,mBAAmB;;;;ACAhC,MAAa,iBAAiB;;;;ACA9B,MAAa,sBAAsB,mBACjC,kDACD;AAED,MAAa,4BAA4B,mBAAmB,WAAW;;;;ACJvE,MAAa,qBACX;;;;ACDF,IAAa,iBAAb,cAAoC,MAAM;CACxC,AAAS;CACT,AAAS;CAET,YAAY,SAAiB,YAAoB,MAAe;AAC9D,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,aAAa;AAClB,OAAK,OAAO;;;;;;ACLhB,eAAe,mBAAsB,KAAoB;AACvD,KAAI,eAAe,QAEjB,QAAO,mBADU,MAAM,IACY;AAGrC,KAAI,MAAM,QAAQ,IAAI,CAEpB,QADiB,MAAM,QAAQ,IAAI,IAAI,IAAI,mBAAmB,CAAC;AAIjE,KAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;EAC3C,MAAM,UAAU,OAAO,QAAQ,IAAI;EACnC,MAAM,kBAAkB,MAAM,QAAQ,IACpC,QAAQ,IAAI,OAAO,CAAC,KAAK,WAAW,CAAC,KAAK,MAAM,mBAAmB,MAAM,CAAC,CAAC,CAC5E;AACD,SAAO,OAAO,YAAY,gBAAgB;;AAG5C,QAAO;;AAGT,eAAsB,kBACpB,QACY;CACZ,MAAM,UAAU,MAAM,4BAA4B,QAAQ,WAAW;AACrE,OAAM,QAAQ;AAEd,QADiB,MAAM,mBAAmB,QAAQ,MAAM;;AAI1D,eAAsB,eAAkB,KAAa,WAA+B;CAClF,MAAM,WAAW,MAAM,MAAM,KAAK,EAChC,SAAS;EACP,cAAc;EACd,QAAQ;EACR,mBAAmB;EACpB,EACF,CAAC;AAEF,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,QAAM,IAAI,eACR,mBAAmB,SAAS,OAAO,GAAG,SAAS,cAC/C,SAAS,QACT,KACD;;AAGH,KAAI,CAAC,SAAS,KACZ,OAAM,IAAI,eAAe,yBAAyB,IAAI;AAGxD,QAAO,kBAAqB,SAAS,KAAK;;;;;ACtD5C,MAAM,kBAAkB;AAExB,SAAS,UAAU,SAAyB;AAC1C,QAAO,WAAW,KAAK,KAAK;;AAG9B,SAAgB,kBACd,MACA,MACA,MACA,MACQ;CACR,MAAM,OAAO,UAAU,OAAO,KAAK;CACnC,MAAM,OAAO,UAAU,OAAO,KAAK;CAEnC,MAAM,IACJ,KAAK,IAAI,OAAO,EAAE,GAAG,KAAK,IAAI,OAAO,EAAE,GACvC,KAAK,IAAI,UAAU,KAAK,CAAC,GACvB,KAAK,IAAI,UAAU,KAAK,CAAC,GACzB,KAAK,IAAI,OAAO,EAAE,GAClB,KAAK,IAAI,OAAO,EAAE;AAItB,QAAO,mBAFG,IAAI,KAAK,MAAM,KAAK,KAAK,EAAE,EAAE,KAAK,KAAK,IAAI,EAAE,CAAC;;AAK1D,SAAgB,mBACd,UACA,WACA,UAC4B;AAC5B,KAAI,SAAS,WAAW,EACtB,QAAO;CAGT,IAAIA,UAAsC;CAC1C,IAAI,cAAc;AAElB,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,WAAW,kBACf,UACA,WACA,QAAQ,UACR,QAAQ,UACT;AAED,MAAI,WAAW,aAAa;AAC1B,iBAAc;AACd,aAAU;IAAE,GAAG;IAAS;IAAU;;;AAItC,QAAO;;AAGT,SAAgB,oBACd,UACA,WACA,UACA,QAAgB,GACO;CACvB,MAAMC,gBAAuC,SAAS,KAAK,aAAa;EACtE,GAAG;EACH,UAAU,kBACR,UACA,WACA,QAAQ,UACR,QAAQ,UACT;EACF,EAAE;AAEH,eAAc,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,SAAS;AAErD,QAAO,cAAc,MAAM,GAAG,MAAM;;;;;AC5EtC,SAAgB,SACd,SACA,MACA,QACK;CACL,MAAM,MAAM,IAAI,IAAI,UAAU,KAAK;AAEnC,KAAI,OACF,QAAO,QAAQ,OAAO,CAAC,SAAS,CAAC,KAAK,WAAW;AAC/C,MAAI,UAAU,OACZ,KAAI,aAAa,IAAI,KAAK,OAAO,MAAM,CAAC;GAE1C;AAGJ,QAAO;;;;;ACUT,IAAa,cAAb,MAAyB;CACvB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAEjB,YAAY,SAA4B,EAAE,EAAE;AAC1C,OAAK,UAAU,OAAO,WAAW;AACjC,OAAK,SAAS,OAAO,UAAU;AAC/B,OAAK,YAAY,OAAO,aAAa;;CAGvC,MAAc,QAAW,KAAyB;AAChD,SAAO,eAAkB,KAAK,KAAK,UAAU;;CAG/C,MAAM,YAAY,QAA+C;EAC/D,MAAM,MAAM,SACV,KAAK,SACL,IAAI,KAAK,OAAO,WAAW,OAAO,WAAW,QAC7C;GACE,OAAO,OAAO,SAAS;GACvB,SAAS;GACV,CACF;EAID,MAAM,iBAFO,MAAM,KAAK,QAA6B,IAAI,UAAU,CAAC,EAC7C,mCAAmC,OAC1B,iBAAiB;AAEjD,MAAI,CAAC,gBAAgB,aAAa,WAAW,EAC3C,QAAO,EAAE;AAGX,SAAO,aAAa,KAAK,aAAa;GACpC,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd,KAAK,QAAQ;GACb,UAAU,QAAQ,YAAY;GAC9B,WAAW,QAAQ,YAAY;GAChC,EAAE;;CAGL,MAAM,cAAc,QAAmD;EACrE,MAAM,MAAM,SACV,KAAK,SACL,IAAI,KAAK,SAAS,OAAO,WAAW,QACpC,EACE,SAAS,2BACV,CACF;EAED,MAAM,OAAO,MAAM,KAAK,QAAmC,IAAI,UAAU,CAAC;EAC1E,MAAM,YAAY,KAAK,MAAM,QAAQ,KAAK,aAAa;EACvD,MAAM,UAAU,WAAW;AAE3B,MAAI,CAAC,WAAW,CAAC,QAAQ,QACvB,OAAM,IAAI,eAAe,wCAAwC,IAAI;EAGvE,MAAM,eAAe,WAAW,cAAc,MAAM;EACpD,MAAM,aAAa,eACf;GACE,QAAQ,aAAa,UAAU,EAAE;GACjC,OAAO,aAAa,SAAS,EAAE;GAChC,GACD;AAEJ,SAAO;GACL,SAAS;IACP,IAAI,QAAQ;IACZ,MAAM,QAAQ;IACd,KAAK,OAAO;IACZ,UAAU;IACX;GACD,SAAS;IACP,IAAI,QAAQ,QAAQ;IACpB,KAAK,QAAQ,QAAQ;IACrB,eAAe,QAAQ,QAAQ;IAC/B,eAAe,QAAQ,QAAQ;IAC/B,WAAW,QAAQ,QAAQ;IAC3B,aAAa,QAAQ,QAAQ;IAC7B,UAAU,QAAQ,QAAQ;IAC1B,UAAU,QAAQ,QAAQ;IAC1B,MAAM,QAAQ,QAAQ;IACvB;GACD,YAAY,QAAQ,QAAQ,YAAY,KAAK,OAAO;IAClD,MAAM,EAAE;IACR,KAAK,EAAE;IACP,eAAe,EAAE;IACjB,MAAM,EAAE;IACT,EAAE;GACH;GACD;;CAGH,MAAM,kBACJ,QACqC;EACrC,MAAM,WAAW,MAAM,KAAK,YAAY,EAAE,YAAY,OAAO,YAAY,CAAC;AAC1E,SAAO,mBAAmB,OAAO,KAAK,OAAO,KAAK,SAAS;;CAG7D,MAAM,mBACJ,QACgC;EAChC,MAAM,WAAW,MAAM,KAAK,YAAY,EAAE,YAAY,OAAO,YAAY,CAAC;AAC1E,SAAO,oBAAoB,OAAO,KAAK,OAAO,KAAK,UAAU,OAAO,MAAM;;CAG5E,MAAM,kBACJ,QAC6B;EAC7B,MAAM,iBAAiB,MAAM,KAAK,kBAAkB;GAClD,KAAK,OAAO;GACZ,KAAK,OAAO;GACZ,YAAY,OAAO;GACpB,CAAC;AAEF,MAAI,CAAC,eACH,QAAO;EAGT,MAAM,MAAM,MAAM,KAAK,cAAc,EAAE,YAAY,eAAe,KAAK,CAAC;AACxE,MAAI,QAAQ,WAAW,eAAe;AACtC,SAAO;;;;;;AClJX,SAAgB,kBAAkB,QAAyC;AACzE,QAAO,IAAI,YAAY,OAAO"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["nearest: StationWithDistance | null","withDistances: StationWithDistance[]"],"sources":["../src/constants/base-url.constant.ts","../src/constants/locale.constant.ts","../src/constants/routes.constant.ts","../src/constants/user-agent.constant.ts","../src/exceptions/iqair.exception.ts","../src/utils/decoder.util.ts","../src/utils/geo.util.ts","../src/utils/build-url.util.ts","../src/client/iqair-client.ts","../src/client/create-iqair-client.ts"],"sourcesContent":["export const DEFAULT_BASE_URL = \"https://www.iqair.com\";\n","export const DEFAULT_LOCALE = \"in-en\";\n","export const STATION_LIST_ROUTES =\n \"routes/$(locale),routes/$(locale).profile.$slug\";\n\nexport const INDIVIDUAL_STATION_ROUTES = \"routes/$\";\n","export const DEFAULT_USER_AGENT =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36\";\n","export class IQAirException extends Error {\n readonly statusCode: number;\n readonly body?: string;\n\n constructor(message: string, statusCode: number, body?: string) {\n super(message);\n this.name = \"IQAirException\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n","import { UNSAFE_decodeViaTurboStream } from \"react-router\";\nimport { IQAirException } from \"../exceptions\";\n\nasync function resolveAllPromises<T>(obj: T): Promise<T> {\n if (obj instanceof Promise) {\n const resolved = await obj;\n return resolveAllPromises(resolved);\n }\n\n if (Array.isArray(obj)) {\n const resolved = await Promise.all(obj.map(resolveAllPromises));\n return resolved as T;\n }\n\n if (obj !== null && typeof obj === \"object\") {\n const entries = Object.entries(obj);\n const resolvedEntries = await Promise.all(\n entries.map(async ([key, value]) => [key, await resolveAllPromises(value)])\n );\n return Object.fromEntries(resolvedEntries) as T;\n }\n\n return obj;\n}\n\nexport async function decodeTurboStream<T>(\n stream: ReadableStream<Uint8Array>\n): Promise<T> {\n const decoded = await UNSAFE_decodeViaTurboStream(stream, globalThis);\n await decoded.done;\n const resolved = await resolveAllPromises(decoded.value);\n return resolved as T;\n}\n\nexport async function fetchAndDecode<T>(url: string, userAgent: string): Promise<T> {\n const response = await fetch(url, {\n headers: {\n \"User-Agent\": userAgent,\n Accept: \"*/*\",\n \"Accept-Language\": \"en-US,en;q=0.9\",\n },\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new IQAirException(\n `Request failed: ${response.status} ${response.statusText}`,\n response.status,\n text\n );\n }\n\n if (!response.body) {\n throw new IQAirException(\"Response body is null\", 500);\n }\n\n return decodeTurboStream<T>(response.body);\n}\n","import type { Station, StationWithDistance } from \"../types\";\n\nconst EARTH_RADIUS_KM = 6371;\n\nfunction toRadians(degrees: number): number {\n return degrees * (Math.PI / 180);\n}\n\nexport function haversineDistance(\n lat1: number,\n lon1: number,\n lat2: number,\n lon2: number\n): number {\n const dLat = toRadians(lat2 - lat1);\n const dLon = toRadians(lon2 - lon1);\n\n const a =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(toRadians(lat1)) *\n Math.cos(toRadians(lat2)) *\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2);\n\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n return EARTH_RADIUS_KM * c;\n}\n\nexport function findNearestStation(\n latitude: number,\n longitude: number,\n stations: Station[]\n): StationWithDistance | null {\n if (stations.length === 0) {\n return null;\n }\n\n let nearest: StationWithDistance | null = null;\n let minDistance = Infinity;\n\n for (const station of stations) {\n const distance = haversineDistance(\n latitude,\n longitude,\n station.latitude,\n station.longitude\n );\n\n if (distance < minDistance) {\n minDistance = distance;\n nearest = { ...station, distance };\n }\n }\n\n return nearest;\n}\n\nexport function findNearestStations(\n latitude: number,\n longitude: number,\n stations: Station[],\n limit: number = 5\n): StationWithDistance[] {\n const withDistances: StationWithDistance[] = stations.map((station) => ({\n ...station,\n distance: haversineDistance(\n latitude,\n longitude,\n station.latitude,\n station.longitude\n ),\n }));\n\n withDistances.sort((a, b) => a.distance - b.distance);\n\n return withDistances.slice(0, limit);\n}\n","export function buildUrl(\n baseUrl: string,\n path: string,\n params?: Record<string, string | number | undefined>\n): URL {\n const url = new URL(baseUrl + path);\n\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n\n return url;\n}\n","import { IQAirClientConfig } from \"./iqair-client.config\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_LOCALE,\n DEFAULT_USER_AGENT,\n STATION_LIST_ROUTES,\n INDIVIDUAL_STATION_ROUTES,\n} from \"../constants\";\nimport { IQAirException } from \"../exceptions\";\nimport { fetchAndDecode } from \"../utils/decoder.util\";\nimport { findNearestStation, findNearestStations } from \"../utils/geo.util\";\nimport { buildUrl } from \"../utils/build-url.util\";\nimport type {\n Station,\n StationWithDistance,\n AQIResponse,\n StationListResponse,\n IndividualStationResponse,\n GetStationsParams,\n GetStationAQIParams,\n GetNearestStationParams,\n GetNearestStationsParams,\n GetAQIForLocationParams,\n} from \"../types\";\n\nexport class IQAirClient {\n private readonly baseUrl: string;\n private readonly locale: string;\n private readonly userAgent: string;\n\n constructor(config: IQAirClientConfig = {}) {\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.locale = config.locale ?? DEFAULT_LOCALE;\n this.userAgent = config.userAgent ?? DEFAULT_USER_AGENT;\n }\n\n private async request<T>(url: string): Promise<T> {\n return fetchAndDecode<T>(url, this.userAgent);\n }\n\n async getStations(params: GetStationsParams): Promise<Station[]> {\n const url = buildUrl(\n this.baseUrl,\n `/${this.locale}/profile/${params.dataSource}.data`,\n {\n limit: params.limit ?? 500,\n _routes: STATION_LIST_ROUTES,\n }\n );\n\n console.log(url.toString());\n\n const data = await this.request<StationListResponse>(url.toString());\n const routeData = data[\"routes/$(locale).profile.$slug\"]?.data;\n const stationsData = routeData?.stationsMapData?.data;\n\n if (!stationsData || stationsData.length === 0) {\n return [];\n }\n\n return stationsData.map((station) => ({\n id: station.id,\n name: station.name,\n url: station.url,\n latitude: station.coordinates.latitude,\n longitude: station.coordinates.longitude,\n }));\n }\n\n async getStationAQI(params: GetStationAQIParams): Promise<AQIResponse> {\n const url = buildUrl(\n this.baseUrl,\n `/${this.locale}${params.stationUrl}.data`,\n {\n _routes: INDIVIDUAL_STATION_ROUTES,\n }\n );\n\n const data = await this.request<IndividualStationResponse>(url.toString());\n const routeData = data.root?.data || data[\"routes/$\"]?.data;\n const details = routeData?.details;\n\n if (!details || !details.current) {\n throw new IQAirException(\"No station details found in response\", 404);\n }\n\n const measurements = routeData?.measurements?.data?.measurements;\n const historical = measurements\n ? {\n hourly: measurements.hourly || [],\n daily: measurements.daily || [],\n }\n : undefined;\n\n return {\n station: {\n id: details.id,\n name: details.name,\n url: params.stationUrl,\n distance: 0,\n },\n current: {\n ts: details.current.ts,\n aqi: details.current.aqi,\n mainPollutant: details.current.mainPollutant,\n concentration: details.current.concentration,\n condition: details.current.condition,\n temperature: details.current.temperature,\n humidity: details.current.humidity,\n pressure: details.current.pressure,\n wind: details.current.wind,\n },\n pollutants: details.current.pollutants?.map((p) => ({\n name: p.pollutantName,\n aqi: p.aqi,\n concentration: p.concentration,\n unit: p.unit,\n })),\n historical,\n };\n }\n\n async getNearestStation(\n params: GetNearestStationParams\n ): Promise<StationWithDistance | null> {\n const stations = await this.getStations({ dataSource: params.dataSource });\n return findNearestStation(params.lat, params.lng, stations);\n }\n\n async getNearestStations(\n params: GetNearestStationsParams\n ): Promise<StationWithDistance[]> {\n const stations = await this.getStations({ dataSource: params.dataSource });\n return findNearestStations(params.lat, params.lng, stations, params.limit);\n }\n\n async getAQIForLocation(\n params: GetAQIForLocationParams\n ): Promise<AQIResponse | null> {\n const nearestStation = await this.getNearestStation({\n lat: params.lat,\n lng: params.lng,\n dataSource: params.dataSource,\n });\n\n if (!nearestStation) {\n return null;\n }\n\n const aqi = await this.getStationAQI({ stationUrl: nearestStation.url });\n aqi.station.distance = nearestStation.distance;\n return aqi;\n }\n}\n","import { IQAirClient } from \"./iqair-client\";\nimport { IQAirClientConfig } from \"./iqair-client.config\";\n\nexport function createIQAirClient(config?: IQAirClientConfig): IQAirClient {\n return new IQAirClient(config);\n}\n"],"mappings":"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"}
|