@mharj/openweathermap 0.0.5 → 0.0.6

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.
@@ -45,6 +45,7 @@ export declare class OpenWeatherV2 {
45
45
  private cache;
46
46
  private loadableApiKey;
47
47
  private apiHandler;
48
+ private fetchPromiseMap;
48
49
  /**
49
50
  * OpenWeatherV2 constructor
50
51
  * @param {Loadable<string>} loadableApiKey - Loadable API key
@@ -77,6 +77,7 @@ class OpenWeatherV2 {
77
77
  cache;
78
78
  loadableApiKey;
79
79
  apiHandler;
80
+ fetchPromiseMap = new Map();
80
81
  /**
81
82
  * OpenWeatherV2 constructor
82
83
  * @param {Loadable<string>} loadableApiKey - Loadable API key
@@ -193,7 +194,15 @@ class OpenWeatherV2 {
193
194
  return `${main}:${lang}:${units}`;
194
195
  }
195
196
  async handleFetch(cacheKey, params, opts) {
196
- const dataApiResult = await this.apiHandler.dataWeatherApi(params);
197
+ // allow only one fetch per cacheKey until it is resolved
198
+ let promiseResult = this.fetchPromiseMap.get(cacheKey);
199
+ if (!promiseResult) {
200
+ promiseResult = this.apiHandler.dataWeatherApi(params);
201
+ this.fetchPromiseMap.set(cacheKey, promiseResult);
202
+ await promiseResult;
203
+ this.fetchPromiseMap.delete(cacheKey); // clear promise from map
204
+ }
205
+ const dataApiResult = await promiseResult;
197
206
  const data = dataApiResult.unwrap();
198
207
  (0, types_1.assertWeatherDataV2)(data);
199
208
  if (this.cache) {
@@ -1 +1 @@
1
- {"version":3,"file":"OpenWeatherV2.js","sourceRoot":"./src/","sources":["OpenWeatherV2.ts"],"names":[],"mappings":"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","sourcesContent":["import {assertWeatherDataV2, CountryCode, LangCode, Loadable, WeatherDataV2} from './types';\nimport {Err, Ok, Result, safeAsyncResult, safeAsyncResultBuilder} from 'mharj-result';\nimport {fetchErrorWrapper} from './lib/fetchUtils';\nimport type {ICacheOrAsync} from '@avanio/expire-cache';\nimport type {IOpenWeatherV2} from './interfaces/IOpenWeatherV2';\n\nconst fetchResult = safeAsyncResultBuilder<Parameters<typeof fetch>, Response, SyntaxError | TypeError>(fetch);\n\nfunction isJson(response: Response): boolean {\n\tconst contentType = response.headers.get('content-type');\n\treturn (contentType && contentType.startsWith('application/json')) || false;\n}\n\nfunction isOpenWeatherError(data: unknown): data is {cod: string; message: string} {\n\treturn typeof data === 'object' && data !== null && 'cod' in data && 'message' in data;\n}\n\n/**\n * Open Weather V2 API Common Options\n * @default {lang: 'en', units: 'standard'} in API\n * @example\n * {lang: 'fi', units: 'metric'}\n */\nexport type OpenWeatherV2CommonOptions = {\n\t/**\n\t * Language code\n\t */\n\tlang?: LangCode;\n\t/**\n\t * Weather units\n\t */\n\tunits?: 'standard' | 'metric' | 'imperial';\n};\n\nconst basePath = 'https://api.openweathermap.org/data/2.5/weather';\n\nfunction buildUrl(params: URLSearchParams): string {\n\treturn `${basePath}?${params.toString()}`;\n}\n\nfunction buildLogUrl(params: URLSearchParams): string {\n\tconst logParams = new URLSearchParams(params);\n\tlogParams.set('appid', '***');\n\treturn buildUrl(logParams);\n}\n\nconst defaultImplementation: IOpenWeatherV2 = {\n\tdataWeatherApi: async (params: URLSearchParams): Promise<Result<WeatherDataV2, SyntaxError | TypeError>> => {\n\t\tconst logUrl = buildLogUrl(params);\n\t\tconst result = await fetchResult(buildUrl(params));\n\t\tif (!result.isOk) {\n\t\t\treturn Err(result.err());\n\t\t}\n\t\tconst res = result.ok();\n\t\tif (!res.ok) {\n\t\t\tif (isJson(res)) {\n\t\t\t\tconst data: unknown = await res.json();\n\t\t\t\tif (isOpenWeatherError(data)) {\n\t\t\t\t\treturn Err(new TypeError(`OpenWeatherV2 error: ${data.message} from ${logUrl}`));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Err(new TypeError(`OpenWeatherV2 http error: ${res.status} ${res.statusText} from ${logUrl}`));\n\t\t}\n\t\tif (!isJson(res)) {\n\t\t\treturn Err(new TypeError(`OpenWeatherV2 response is not json payload from ${logUrl}`));\n\t\t}\n\t\tconst jsonResult = await safeAsyncResult<unknown, SyntaxError>(res.json());\n\t\tif (!jsonResult.isOk) {\n\t\t\treturn Err(jsonResult.err());\n\t\t}\n\t\tconst data = jsonResult.ok();\n\t\tassertWeatherDataV2(data);\n\t\treturn Ok<WeatherDataV2, SyntaxError | TypeError>(data);\n\t},\n};\n\n/**\n * Open Weather V2 API\n * @example\n * const weather = new OpenWeatherV2('your-api-key');\n *\n * const cache = new ExpireCache<WeatherDataV2>(undefined, undefined, 900000); // data 15 minutes in cache\n * const weather = new OpenWeatherV2(() => Promise.resolve('your-api-key'), cache);\n *\n * const data: WeatherDataV2 = (await weather.getWeatherById(2643743)).unwrap(); // throws if error\n * const data: WeatherDataV2 | undefined = (await weather.getWeatherByCity('Helsinki', 'fi')).ok();\n *\n * const result: Result<WeatherDataV2> = await weather.getWeatherByLatLon(60.1699, 24.9384);\n * result.match({\n * Ok: (data: WeatherDataV2) => console.log(data),\n * Err: (err: DOMException | TypeError) => console.error(err),\n * });\n *\n * if(result.isOk) {\n * const data: WeatherDataV2 = data.ok();\n * } else {\n * const err: DOMException | TypeError = data.err();\n * }\n */\nexport class OpenWeatherV2 {\n\tprivate cache: ICacheOrAsync<WeatherDataV2> | undefined;\n\tprivate loadableApiKey: Loadable<string>;\n\tprivate apiHandler: IOpenWeatherV2;\n\t/**\n\t * OpenWeatherV2 constructor\n\t * @param {Loadable<string>} loadableApiKey - Loadable API key\n\t * @param {ICacheOrAsync<WeatherDataV2>=} cache - optional async cache implementation\n\t * @param {IOpenWeatherV2=} apiHandler - optional API handler implementation for mocking\n\t */\n\tconstructor(loadableApiKey: Loadable<string>, cache?: ICacheOrAsync<WeatherDataV2>, apiHandler: IOpenWeatherV2 = defaultImplementation) {\n\t\tthis.loadableApiKey = loadableApiKey;\n\t\tthis.cache = cache;\n\t\tthis.apiHandler = apiHandler;\n\t}\n\n\t/**\n\t * get weather by Id\n\t * @param {number} id - Weather station ID\n\t * @param {OpenWeatherV2CommonOptions=} opts - Common options, example ```{lang: 'fi', units: 'metric'}```, defaults ```{lang: 'en', units: 'standard'}```\n\t * @return {Promise<Result<WeatherDataV2, DOMException | TypeError>>} Weather data Result Promise\n\t * @example\n\t * const result: Result<WeatherDataV2, DOMException | TypeError> = await weather.getWeatherResultById(id: 564, {lang: 'fi'});\n\t * if (result.isOk) {\n\t * const weatherData: WeatherDataV2 = result.ok();\n\t * } else {\n\t * const error: DOMException | TypeError = result.err();\n\t * }\n\t */\n\tpublic async getWeatherById(id: number, opts: OpenWeatherV2CommonOptions = {}): Promise<Result<WeatherDataV2, DOMException | TypeError>> {\n\t\ttry {\n\t\t\tconst cacheKey = this.buildBaseCacheKey(`id:${id}`, opts);\n\t\t\tlet cacheEntry = this.cache && (await this.cache.get(cacheKey));\n\t\t\tif (!cacheEntry) {\n\t\t\t\tconst params = await this.buildBaseParams(opts);\n\t\t\t\tparams.append('id', String(id));\n\t\t\t\tcacheEntry = await this.handleFetch(cacheKey, params, opts);\n\t\t\t}\n\t\t\treturn Ok(cacheEntry);\n\t\t} catch (err) {\n\t\t\treturn Err(fetchErrorWrapper(err));\n\t\t}\n\t}\n\n\t/**\n\t * get weather with city name and optional country code\n\t * @param {string} city - City name\n\t * @param {countryCode=} countryCode - Optional Country code\n\t * @param {OpenWeatherV2CommonOptions=} opts - Common options, example ```{lang: 'fi', units: 'metric'}```, defaults ```{lang: 'en', units: 'standard'}```\n\t * @return {Promise<Result<WeatherDataV2, DOMException | TypeError>>} Weather data Result Promise\n\t * @example\n\t * const result: Result<WeatherDataV2, DOMException | TypeError> = await weather.getWeatherByCity('Helsinki', 'fi', {lang: 'fi'});\n\t * if (result.isOk) {\n\t * const weatherData: WeatherDataV2 = result.ok();\n\t * } else {\n\t * const error: DOMException | TypeError = result.err();\n\t * }\n\t */\n\tpublic async getWeatherByCity(\n\t\tcity: string,\n\t\tcountryCode?: CountryCode,\n\t\topts: OpenWeatherV2CommonOptions = {},\n\t): Promise<Result<WeatherDataV2, DOMException | TypeError>> {\n\t\ttry {\n\t\t\tconst cacheKey = this.buildBaseCacheKey(`q:${city}:${countryCode}`, opts);\n\t\t\tlet cacheEntry = this.cache && (await this.cache.get(cacheKey));\n\t\t\tif (!cacheEntry) {\n\t\t\t\tconst params = await this.buildBaseParams(opts);\n\t\t\t\tparams.append('q', countryCode ? `${city},${countryCode}` : city);\n\t\t\t\tcacheEntry = await this.handleFetch(cacheKey, params, opts);\n\t\t\t}\n\t\t\treturn Ok(cacheEntry);\n\t\t} catch (err) {\n\t\t\treturn Err(fetchErrorWrapper(err));\n\t\t}\n\t}\n\n\t/**\n\t * get weather with latitude and longitude with Result\n\t * @param {number} lat - Latitude\n\t * @param {number} lon - Longitude\n\t * @param {OpenWeatherV2CommonOptions=} opts - Common options, example ```{lang: 'fi', units: 'metric'}```, defaults ```{lang: 'en', units: 'standard'}```\n\t * @return {Promise<Result<WeatherDataV2, DOMException | TypeError>>} Weather data Result Promise\n\t * @example\n\t * const result: Result<WeatherDataV2, DOMException | TypeError> = await weather.getWeatherByLatLon(60.1699, 24.9384, {lang: 'fi'});\n\t * if (result.isOk) {\n\t * const weatherData: WeatherDataV2 = result.ok();\n\t * } else {\n\t * const error: DOMException | TypeError = result.err();\n\t * }\n\t */\n\tpublic async getWeatherByLatLon(lat: number, lon: number, opts: OpenWeatherV2CommonOptions = {}): Promise<Result<WeatherDataV2, DOMException | TypeError>> {\n\t\ttry {\n\t\t\tconst cacheKey = this.buildBaseCacheKey(`latlon:${lat}:${lon}`, opts);\n\t\t\tlet cacheEntry = this.cache && (await this.cache.get(cacheKey));\n\t\t\tif (!cacheEntry) {\n\t\t\t\tconst params = await this.buildBaseParams(opts);\n\t\t\t\tparams.append('lat', String(lat));\n\t\t\t\tparams.append('lon', String(lon));\n\t\t\t\tcacheEntry = await this.handleFetch(cacheKey, params, opts);\n\t\t\t}\n\t\t\treturn Ok(cacheEntry);\n\t\t} catch (err) {\n\t\t\treturn Err(fetchErrorWrapper(err));\n\t\t}\n\t}\n\n\tprivate async buildBaseParams({lang, units}: OpenWeatherV2CommonOptions): Promise<URLSearchParams> {\n\t\tconst apiKey = await (typeof this.loadableApiKey === 'function' ? this.loadableApiKey() : this.loadableApiKey);\n\t\tconst params = new URLSearchParams();\n\t\tlang && params.append('lang', lang);\n\t\tunits && params.append('units', units);\n\t\tparams.append('appid', apiKey);\n\t\treturn params;\n\t}\n\n\t/**\n\t * build base cache key\n\t * @param main - main cache key prefix\n\t * @param opts - OpenWeatherV2CommonOptions\n\t * @returns {CacheKey}\n\t */\n\tprivate buildBaseCacheKey(main: string, {lang, units}: OpenWeatherV2CommonOptions): string {\n\t\treturn `${main}:${lang}:${units}`;\n\t}\n\n\tprivate async handleFetch(cacheKey: string, params: URLSearchParams, opts: OpenWeatherV2CommonOptions): Promise<WeatherDataV2> {\n\t\tconst dataApiResult = await this.apiHandler.dataWeatherApi(params);\n\t\tconst data: WeatherDataV2 = dataApiResult.unwrap();\n\t\tassertWeatherDataV2(data);\n\t\tif (this.cache) {\n\t\t\tawait this.cache.set(cacheKey, data);\n\t\t\tif (!cacheKey.startsWith('id:')) {\n\t\t\t\t// update id cache too\n\t\t\t\tawait this.cache.set(this.buildBaseCacheKey(`id:${data.id}`, opts), data);\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n}\n"]}
1
+ {"version":3,"file":"OpenWeatherV2.js","sourceRoot":"./src/","sources":["OpenWeatherV2.ts"],"names":[],"mappings":"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","sourcesContent":["import {assertWeatherDataV2, CountryCode, LangCode, Loadable, WeatherDataV2} from './types';\nimport {Err, Ok, Result, safeAsyncResult, safeAsyncResultBuilder} from 'mharj-result';\nimport {fetchErrorWrapper} from './lib/fetchUtils';\nimport type {ICacheOrAsync} from '@avanio/expire-cache';\nimport type {IOpenWeatherV2} from './interfaces/IOpenWeatherV2';\n\nconst fetchResult = safeAsyncResultBuilder<Parameters<typeof fetch>, Response, SyntaxError | TypeError>(fetch);\n\nfunction isJson(response: Response): boolean {\n\tconst contentType = response.headers.get('content-type');\n\treturn (contentType && contentType.startsWith('application/json')) || false;\n}\n\nfunction isOpenWeatherError(data: unknown): data is {cod: string; message: string} {\n\treturn typeof data === 'object' && data !== null && 'cod' in data && 'message' in data;\n}\n\n/**\n * Open Weather V2 API Common Options\n * @default {lang: 'en', units: 'standard'} in API\n * @example\n * {lang: 'fi', units: 'metric'}\n */\nexport type OpenWeatherV2CommonOptions = {\n\t/**\n\t * Language code\n\t */\n\tlang?: LangCode;\n\t/**\n\t * Weather units\n\t */\n\tunits?: 'standard' | 'metric' | 'imperial';\n};\n\nconst basePath = 'https://api.openweathermap.org/data/2.5/weather';\n\nfunction buildUrl(params: URLSearchParams): string {\n\treturn `${basePath}?${params.toString()}`;\n}\n\nfunction buildLogUrl(params: URLSearchParams): string {\n\tconst logParams = new URLSearchParams(params);\n\tlogParams.set('appid', '***');\n\treturn buildUrl(logParams);\n}\n\nconst defaultImplementation: IOpenWeatherV2 = {\n\tdataWeatherApi: async (params: URLSearchParams): Promise<Result<WeatherDataV2, SyntaxError | TypeError>> => {\n\t\tconst logUrl = buildLogUrl(params);\n\t\tconst result = await fetchResult(buildUrl(params));\n\t\tif (!result.isOk) {\n\t\t\treturn Err(result.err());\n\t\t}\n\t\tconst res = result.ok();\n\t\tif (!res.ok) {\n\t\t\tif (isJson(res)) {\n\t\t\t\tconst data: unknown = await res.json();\n\t\t\t\tif (isOpenWeatherError(data)) {\n\t\t\t\t\treturn Err(new TypeError(`OpenWeatherV2 error: ${data.message} from ${logUrl}`));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Err(new TypeError(`OpenWeatherV2 http error: ${res.status} ${res.statusText} from ${logUrl}`));\n\t\t}\n\t\tif (!isJson(res)) {\n\t\t\treturn Err(new TypeError(`OpenWeatherV2 response is not json payload from ${logUrl}`));\n\t\t}\n\t\tconst jsonResult = await safeAsyncResult<unknown, SyntaxError>(res.json());\n\t\tif (!jsonResult.isOk) {\n\t\t\treturn Err(jsonResult.err());\n\t\t}\n\t\tconst data = jsonResult.ok();\n\t\tassertWeatherDataV2(data);\n\t\treturn Ok<WeatherDataV2, SyntaxError | TypeError>(data);\n\t},\n};\n\n/**\n * Open Weather V2 API\n * @example\n * const weather = new OpenWeatherV2('your-api-key');\n *\n * const cache = new ExpireCache<WeatherDataV2>(undefined, undefined, 900000); // data 15 minutes in cache\n * const weather = new OpenWeatherV2(() => Promise.resolve('your-api-key'), cache);\n *\n * const data: WeatherDataV2 = (await weather.getWeatherById(2643743)).unwrap(); // throws if error\n * const data: WeatherDataV2 | undefined = (await weather.getWeatherByCity('Helsinki', 'fi')).ok();\n *\n * const result: Result<WeatherDataV2> = await weather.getWeatherByLatLon(60.1699, 24.9384);\n * result.match({\n * Ok: (data: WeatherDataV2) => console.log(data),\n * Err: (err: DOMException | TypeError) => console.error(err),\n * });\n *\n * if(result.isOk) {\n * const data: WeatherDataV2 = data.ok();\n * } else {\n * const err: DOMException | TypeError = data.err();\n * }\n */\nexport class OpenWeatherV2 {\n\tprivate cache: ICacheOrAsync<WeatherDataV2> | undefined;\n\tprivate loadableApiKey: Loadable<string>;\n\tprivate apiHandler: IOpenWeatherV2;\n\tprivate fetchPromiseMap = new Map<string, Promise<Result<WeatherDataV2, DOMException | TypeError>>>();\n\t/**\n\t * OpenWeatherV2 constructor\n\t * @param {Loadable<string>} loadableApiKey - Loadable API key\n\t * @param {ICacheOrAsync<WeatherDataV2>=} cache - optional async cache implementation\n\t * @param {IOpenWeatherV2=} apiHandler - optional API handler implementation for mocking\n\t */\n\tconstructor(loadableApiKey: Loadable<string>, cache?: ICacheOrAsync<WeatherDataV2>, apiHandler: IOpenWeatherV2 = defaultImplementation) {\n\t\tthis.loadableApiKey = loadableApiKey;\n\t\tthis.cache = cache;\n\t\tthis.apiHandler = apiHandler;\n\t}\n\n\t/**\n\t * get weather by Id\n\t * @param {number} id - Weather station ID\n\t * @param {OpenWeatherV2CommonOptions=} opts - Common options, example ```{lang: 'fi', units: 'metric'}```, defaults ```{lang: 'en', units: 'standard'}```\n\t * @return {Promise<Result<WeatherDataV2, DOMException | TypeError>>} Weather data Result Promise\n\t * @example\n\t * const result: Result<WeatherDataV2, DOMException | TypeError> = await weather.getWeatherResultById(id: 564, {lang: 'fi'});\n\t * if (result.isOk) {\n\t * const weatherData: WeatherDataV2 = result.ok();\n\t * } else {\n\t * const error: DOMException | TypeError = result.err();\n\t * }\n\t */\n\tpublic async getWeatherById(id: number, opts: OpenWeatherV2CommonOptions = {}): Promise<Result<WeatherDataV2, DOMException | TypeError>> {\n\t\ttry {\n\t\t\tconst cacheKey = this.buildBaseCacheKey(`id:${id}`, opts);\n\t\t\tlet cacheEntry = this.cache && (await this.cache.get(cacheKey));\n\t\t\tif (!cacheEntry) {\n\t\t\t\tconst params = await this.buildBaseParams(opts);\n\t\t\t\tparams.append('id', String(id));\n\t\t\t\tcacheEntry = await this.handleFetch(cacheKey, params, opts);\n\t\t\t}\n\t\t\treturn Ok(cacheEntry);\n\t\t} catch (err) {\n\t\t\treturn Err(fetchErrorWrapper(err));\n\t\t}\n\t}\n\n\t/**\n\t * get weather with city name and optional country code\n\t * @param {string} city - City name\n\t * @param {countryCode=} countryCode - Optional Country code\n\t * @param {OpenWeatherV2CommonOptions=} opts - Common options, example ```{lang: 'fi', units: 'metric'}```, defaults ```{lang: 'en', units: 'standard'}```\n\t * @return {Promise<Result<WeatherDataV2, DOMException | TypeError>>} Weather data Result Promise\n\t * @example\n\t * const result: Result<WeatherDataV2, DOMException | TypeError> = await weather.getWeatherByCity('Helsinki', 'fi', {lang: 'fi'});\n\t * if (result.isOk) {\n\t * const weatherData: WeatherDataV2 = result.ok();\n\t * } else {\n\t * const error: DOMException | TypeError = result.err();\n\t * }\n\t */\n\tpublic async getWeatherByCity(\n\t\tcity: string,\n\t\tcountryCode?: CountryCode,\n\t\topts: OpenWeatherV2CommonOptions = {},\n\t): Promise<Result<WeatherDataV2, DOMException | TypeError>> {\n\t\ttry {\n\t\t\tconst cacheKey = this.buildBaseCacheKey(`q:${city}:${countryCode}`, opts);\n\t\t\tlet cacheEntry = this.cache && (await this.cache.get(cacheKey));\n\t\t\tif (!cacheEntry) {\n\t\t\t\tconst params = await this.buildBaseParams(opts);\n\t\t\t\tparams.append('q', countryCode ? `${city},${countryCode}` : city);\n\t\t\t\tcacheEntry = await this.handleFetch(cacheKey, params, opts);\n\t\t\t}\n\t\t\treturn Ok(cacheEntry);\n\t\t} catch (err) {\n\t\t\treturn Err(fetchErrorWrapper(err));\n\t\t}\n\t}\n\n\t/**\n\t * get weather with latitude and longitude with Result\n\t * @param {number} lat - Latitude\n\t * @param {number} lon - Longitude\n\t * @param {OpenWeatherV2CommonOptions=} opts - Common options, example ```{lang: 'fi', units: 'metric'}```, defaults ```{lang: 'en', units: 'standard'}```\n\t * @return {Promise<Result<WeatherDataV2, DOMException | TypeError>>} Weather data Result Promise\n\t * @example\n\t * const result: Result<WeatherDataV2, DOMException | TypeError> = await weather.getWeatherByLatLon(60.1699, 24.9384, {lang: 'fi'});\n\t * if (result.isOk) {\n\t * const weatherData: WeatherDataV2 = result.ok();\n\t * } else {\n\t * const error: DOMException | TypeError = result.err();\n\t * }\n\t */\n\tpublic async getWeatherByLatLon(lat: number, lon: number, opts: OpenWeatherV2CommonOptions = {}): Promise<Result<WeatherDataV2, DOMException | TypeError>> {\n\t\ttry {\n\t\t\tconst cacheKey = this.buildBaseCacheKey(`latlon:${lat}:${lon}`, opts);\n\t\t\tlet cacheEntry = this.cache && (await this.cache.get(cacheKey));\n\t\t\tif (!cacheEntry) {\n\t\t\t\tconst params = await this.buildBaseParams(opts);\n\t\t\t\tparams.append('lat', String(lat));\n\t\t\t\tparams.append('lon', String(lon));\n\t\t\t\tcacheEntry = await this.handleFetch(cacheKey, params, opts);\n\t\t\t}\n\t\t\treturn Ok(cacheEntry);\n\t\t} catch (err) {\n\t\t\treturn Err(fetchErrorWrapper(err));\n\t\t}\n\t}\n\n\tprivate async buildBaseParams({lang, units}: OpenWeatherV2CommonOptions): Promise<URLSearchParams> {\n\t\tconst apiKey = await (typeof this.loadableApiKey === 'function' ? this.loadableApiKey() : this.loadableApiKey);\n\t\tconst params = new URLSearchParams();\n\t\tlang && params.append('lang', lang);\n\t\tunits && params.append('units', units);\n\t\tparams.append('appid', apiKey);\n\t\treturn params;\n\t}\n\n\t/**\n\t * build base cache key\n\t * @param main - main cache key prefix\n\t * @param opts - OpenWeatherV2CommonOptions\n\t * @returns {CacheKey}\n\t */\n\tprivate buildBaseCacheKey(main: string, {lang, units}: OpenWeatherV2CommonOptions): string {\n\t\treturn `${main}:${lang}:${units}`;\n\t}\n\n\tprivate async handleFetch(cacheKey: string, params: URLSearchParams, opts: OpenWeatherV2CommonOptions): Promise<WeatherDataV2> {\n\t\t// allow only one fetch per cacheKey until it is resolved\n\t\tlet promiseResult = this.fetchPromiseMap.get(cacheKey);\n\t\tif (!promiseResult) {\n\t\t\tpromiseResult = this.apiHandler.dataWeatherApi(params);\n\t\t\tthis.fetchPromiseMap.set(cacheKey, promiseResult);\n\t\t\tawait promiseResult;\n\t\t\tthis.fetchPromiseMap.delete(cacheKey); // clear promise from map\n\t\t}\n\t\tconst dataApiResult = await promiseResult;\n\t\tconst data: WeatherDataV2 = dataApiResult.unwrap();\n\t\tassertWeatherDataV2(data);\n\t\tif (this.cache) {\n\t\t\tawait this.cache.set(cacheKey, data);\n\t\t\tif (!cacheKey.startsWith('id:')) {\n\t\t\t\t// update id cache too\n\t\t\t\tawait this.cache.set(this.buildBaseCacheKey(`id:${data.id}`, opts), data);\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n}\n"]}
@@ -75,25 +75,25 @@ export declare const weatherDataV2Schema: z.ZodObject<{
75
75
  }>>;
76
76
  sys: z.ZodObject<{
77
77
  country: z.ZodString;
78
- id: z.ZodNumber;
78
+ id: z.ZodOptional<z.ZodNumber>;
79
79
  message: z.ZodOptional<z.ZodNumber>;
80
80
  sunrise: z.ZodNumber;
81
81
  sunset: z.ZodNumber;
82
- type: z.ZodNumber;
82
+ type: z.ZodOptional<z.ZodNumber>;
83
83
  }, "strip", z.ZodTypeAny, {
84
- type: number;
85
- id: number;
86
84
  country: string;
87
85
  sunrise: number;
88
86
  sunset: number;
87
+ id?: number | undefined;
89
88
  message?: number | undefined;
89
+ type?: number | undefined;
90
90
  }, {
91
- type: number;
92
- id: number;
93
91
  country: string;
94
92
  sunrise: number;
95
93
  sunset: number;
94
+ id?: number | undefined;
96
95
  message?: number | undefined;
96
+ type?: number | undefined;
97
97
  }>;
98
98
  timezone: z.ZodNumber;
99
99
  visibility: z.ZodNumber;
@@ -147,12 +147,12 @@ export declare const weatherDataV2Schema: z.ZodObject<{
147
147
  lat: number;
148
148
  };
149
149
  sys: {
150
- type: number;
151
- id: number;
152
150
  country: string;
153
151
  sunrise: number;
154
152
  sunset: number;
153
+ id?: number | undefined;
155
154
  message?: number | undefined;
155
+ type?: number | undefined;
156
156
  };
157
157
  timezone: number;
158
158
  weather: {
@@ -197,12 +197,12 @@ export declare const weatherDataV2Schema: z.ZodObject<{
197
197
  lat: number;
198
198
  };
199
199
  sys: {
200
- type: number;
201
- id: number;
202
200
  country: string;
203
201
  sunrise: number;
204
202
  sunset: number;
203
+ id?: number | undefined;
205
204
  message?: number | undefined;
205
+ type?: number | undefined;
206
206
  };
207
207
  timezone: number;
208
208
  weather: {
@@ -41,11 +41,11 @@ const snowSchema = zod_1.z.object({
41
41
  });
42
42
  const sysSchema = zod_1.z.object({
43
43
  country: zod_1.z.string(),
44
- id: zod_1.z.number(),
44
+ id: zod_1.z.number().optional(),
45
45
  message: zod_1.z.number().optional(),
46
46
  sunrise: zod_1.z.number(),
47
47
  sunset: zod_1.z.number(),
48
- type: zod_1.z.number(),
48
+ type: zod_1.z.number().optional(),
49
49
  });
50
50
  /**
51
51
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"./src/","sources":["types/v2/index.ts"],"names":[],"mappings":";;;;AAAA,iCAAkC;AAClC,qDAAiD;AACjD,6BAAsB;AACtB,iDAAuB;AACvB,qDAA2B;AAC3B,2DAAiC;AAEjC,MAAM,WAAW,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5B,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;IACf,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IAC9B,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE;IACvB,IAAI,EAAE,iBAAU;IAChB,EAAE,EAAE,gCAAe;IACnB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;CAChB,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;CAChB,CAAC,CAAC;AAEH;;GAEG;AACU,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;QAChB,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;KACf,CAAC;IACF,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,WAAW;IAClB,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE;IACtB,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,aAAa,CAAC;IAC/B,IAAI,EAAE,UAAU;CAChB,CAAC,CAAC;AAIH,SAAgB,eAAe,CAAC,IAAa;IAC5C,OAAO,2BAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AACpD,CAAC;AAFD,0CAEC;AAED,SAAgB,mBAAmB,CAAC,IAAa;IAChD,2BAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAFD,kDAEC","sourcesContent":["import {iconSchema} from './Icon';\nimport {weatherIdSchema} from './weatherIdGroup';\nimport {z} from 'zod';\nexport * from './Icon';\nexport * from './Language';\nexport * from './weatherIdGroup';\n\nconst coordSchema = z.object({\n\tlon: z.number(),\n\tlat: z.number(),\n});\n\nconst weatherSchema = z.object({\n\tdescription: z.string(),\n\ticon: iconSchema,\n\tid: weatherIdSchema,\n\tmain: z.string(),\n});\n\nconst mainSchema = z.object({\n\tgrnd_level: z.number().optional(),\n\thumidity: z.number(),\n\tpressure: z.number(),\n\tsea_level: z.number().optional(),\n\ttemp: z.number(),\n\ttemp_max: z.number(),\n\ttemp_min: z.number(),\n});\n\nconst windSchema = z.object({\n\tspeed: z.number(),\n\tdeg: z.number(),\n});\n\nconst rainSchema = z.object({\n\t'1h': z.number().optional(),\n\t'3h': z.number().optional(),\n});\n\nconst snowSchema = z.object({\n\t'1h': z.number().optional(),\n\t'3h': z.number().optional(),\n});\n\nconst sysSchema = z.object({\n\tcountry: z.string(),\n\tid: z.number(),\n\tmessage: z.number().optional(),\n\tsunrise: z.number(),\n\tsunset: z.number(),\n\ttype: z.number(),\n});\n\n/**\n * @internal\n */\nexport const weatherDataV2Schema = z.object({\n\tbase: z.string(),\n\tclouds: z.object({\n\t\tall: z.number(),\n\t}),\n\tcod: z.number(),\n\tcoord: coordSchema,\n\tdt: z.number(),\n\tid: z.number(),\n\tmain: mainSchema,\n\tname: z.string(),\n\train: rainSchema.optional(),\n\tsnow: snowSchema.optional(),\n\tsys: sysSchema,\n\ttimezone: z.number(),\n\tvisibility: z.number(),\n\tweather: z.array(weatherSchema),\n\twind: windSchema,\n});\n\nexport type WeatherDataV2 = z.infer<typeof weatherDataV2Schema>;\n\nexport function isWeatherDataV2(data: unknown): data is WeatherDataV2 {\n\treturn weatherDataV2Schema.safeParse(data).success;\n}\n\nexport function assertWeatherDataV2(data: unknown): asserts data is WeatherDataV2 {\n\tweatherDataV2Schema.parse(data);\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"./src/","sources":["types/v2/index.ts"],"names":[],"mappings":";;;;AAAA,iCAAkC;AAClC,qDAAiD;AACjD,6BAAsB;AACtB,iDAAuB;AACvB,qDAA2B;AAC3B,2DAAiC;AAEjC,MAAM,WAAW,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5B,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;IACf,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IAC9B,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE;IACvB,IAAI,EAAE,iBAAU;IAChB,EAAE,EAAE,gCAAe;IACnB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;CAChB,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC;AAEH;;GAEG;AACU,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;QAChB,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;KACf,CAAC;IACF,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,WAAW;IAClB,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE;IACtB,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,aAAa,CAAC;IAC/B,IAAI,EAAE,UAAU;CAChB,CAAC,CAAC;AAIH,SAAgB,eAAe,CAAC,IAAa;IAC5C,OAAO,2BAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AACpD,CAAC;AAFD,0CAEC;AAED,SAAgB,mBAAmB,CAAC,IAAa;IAChD,2BAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAFD,kDAEC","sourcesContent":["import {iconSchema} from './Icon';\nimport {weatherIdSchema} from './weatherIdGroup';\nimport {z} from 'zod';\nexport * from './Icon';\nexport * from './Language';\nexport * from './weatherIdGroup';\n\nconst coordSchema = z.object({\n\tlon: z.number(),\n\tlat: z.number(),\n});\n\nconst weatherSchema = z.object({\n\tdescription: z.string(),\n\ticon: iconSchema,\n\tid: weatherIdSchema,\n\tmain: z.string(),\n});\n\nconst mainSchema = z.object({\n\tgrnd_level: z.number().optional(),\n\thumidity: z.number(),\n\tpressure: z.number(),\n\tsea_level: z.number().optional(),\n\ttemp: z.number(),\n\ttemp_max: z.number(),\n\ttemp_min: z.number(),\n});\n\nconst windSchema = z.object({\n\tspeed: z.number(),\n\tdeg: z.number(),\n});\n\nconst rainSchema = z.object({\n\t'1h': z.number().optional(),\n\t'3h': z.number().optional(),\n});\n\nconst snowSchema = z.object({\n\t'1h': z.number().optional(),\n\t'3h': z.number().optional(),\n});\n\nconst sysSchema = z.object({\n\tcountry: z.string(),\n\tid: z.number().optional(),\n\tmessage: z.number().optional(),\n\tsunrise: z.number(),\n\tsunset: z.number(),\n\ttype: z.number().optional(),\n});\n\n/**\n * @internal\n */\nexport const weatherDataV2Schema = z.object({\n\tbase: z.string(),\n\tclouds: z.object({\n\t\tall: z.number(),\n\t}),\n\tcod: z.number(),\n\tcoord: coordSchema,\n\tdt: z.number(),\n\tid: z.number(),\n\tmain: mainSchema,\n\tname: z.string(),\n\train: rainSchema.optional(),\n\tsnow: snowSchema.optional(),\n\tsys: sysSchema,\n\ttimezone: z.number(),\n\tvisibility: z.number(),\n\tweather: z.array(weatherSchema),\n\twind: windSchema,\n});\n\nexport type WeatherDataV2 = z.infer<typeof weatherDataV2Schema>;\n\nexport function isWeatherDataV2(data: unknown): data is WeatherDataV2 {\n\treturn weatherDataV2Schema.safeParse(data).success;\n}\n\nexport function assertWeatherDataV2(data: unknown): asserts data is WeatherDataV2 {\n\tweatherDataV2Schema.parse(data);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mharj/openweathermap",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Open Weather API Client",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {