# @reng/air-quality ## Imports ```ts import { getSnapshot, getAirQuality, getPollen, searchPlaces } from 'kody:@reng/air-quality' import { getSnapshot as snap } from 'kody:@reng/air-quality/getSnapshot' ``` ## Smoke tests ```ts import { getSnapshot, getAirQuality } from 'kody:@reng/air-quality' const bj = await getSnapshot({ location: '北京', standard: 'aqi_cn' }) // expect source === 'air-quality.com' (or fallback), aqi number, pollutants.pm25 != null const sh = await getAirQuality({ location: '上海' }) // expect aqi / pm25 present ``` App: ```ts import { kody } from 'kody:runtime' await kody.packageAppFetch({ kody_id: 'air-quality', path: '/' }) await kody.packageAppFetch({ kody_id: 'air-quality', path: '/api/getSnapshot', method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ location: '北京', standard: 'aqi_cn' }), }) ``` ## Edge cases - Missing `location` and `place` throws. - Skeleton place pages (`1970-01-01` + short HTML) throw / fallback. - Pollen often null off-season. - Hosted app links use `packageContext.hostedUrl` + `appBasePath`. - Scraping is brittle; prefer reading `warnings` and `source`. ## Related - Slimmer Europe-CAMS pollen-only sibling: `@reng/pollen` (Open-Meteo).