@maptiler/client
Version: 
Javascript & Typescript wrapper to MapTiler Cloud API
1 lines • 204 kB
Source Map (JSON)
{"version":3,"file":"maptiler-client.cjs","sources":["../src/config.ts","../src/language.ts","../src/callFetch.ts","../src/defaults.ts","../src/services/ServiceError.ts","../src/services/geocoding.ts","../src/services/geolocation.ts","../src/services/coordinates.ts","../src/services/data.ts","../src/mapstyle.ts","../src/misc.ts","../src/services/staticMaps.ts","../src/services/math.ts","../node_modules/quick-lru/index.js","../src/tiledecoding.ts","../src/services/elevation.ts"],"sourcesContent":["import { BufferToPixelDataFunction } from \"./tiledecoding\";\n\nexport type FetchFunction = (\n  input: RequestInfo | URL,\n  init?: RequestInit,\n) => Promise<Response>;\n\nfunction tryGettingFetch() {\n  // this is browser, fetch exists\n  if (typeof self !== \"undefined\") {\n    return fetch.bind(self);\n  }\n\n  if (typeof global !== \"undefined\" && global.fetch) {\n    return global.fetch;\n  }\n\n  return null;\n}\n\n/**\n * The configuration object definition\n */\nclass ClientConfig {\n  /**\n   * MapTiler Cloud API key\n   */\n  private _apiKey = \"\";\n\n  /**\n   * The fetch function. To be set if in Node < 18, otherwise\n   * will be automatically resolved.\n   */\n  private _fetch: FetchFunction | null = tryGettingFetch();\n\n  /**\n   * Number of tiles to keep in cache\n   */\n  public tileCacheSize: number = 200;\n\n  public bufferToPixelData?: BufferToPixelDataFunction | null;\n\n  /**\n   * Set the MapTiler Cloud API key\n   */\n  set apiKey(k: string) {\n    this._apiKey = k;\n  }\n\n  /**\n   * Get the MapTiler Cloud API key\n   */\n  get apiKey(): string {\n    return this._apiKey;\n  }\n\n  /**\n   * Set a the custom fetch function to replace the default one\n   */\n  set fetch(f: FetchFunction) {\n    this._fetch = f;\n  }\n\n  /**\n   * Get the fetch fucntion\n   */\n  get fetch(): FetchFunction | null {\n    return this._fetch;\n  }\n}\n\n/**\n * Configuration object\n */\nconst config = new ClientConfig();\n\nexport { ClientConfig, config };\n","export type LanguageInfo = {\n  /**\n   * Two-letter ISO code, such as `\"en\"` for English language.\n   * Can be `null` if the language is a flag to be evaluated at runtime,\n   * as it is the case for some \"modes\".\n   */\n  code: string | null;\n\n  /**\n   * The full OSM language flag, such as `\"name:en\"` for the English language.\n   * Can also be a non-OSM flag if the language needs to be evaluated at runtime, such as `\"auto\"`,\n   * as it is the case for some \"modes\".\n   */\n  flag: string;\n\n  /**\n   * English name of the language.\n   */\n  name: string;\n\n  /**\n   * Whether the language leverages only the latin charsets.\n   */\n  latin: boolean;\n\n  /**\n   * Some language descriptions corresponds to \"modes\" rather than to actual languages.\n   * For instance the \"visitor\" mode consists in displaying bilingual labels.\n   */\n  isMode: boolean;\n\n  /**\n   * Whether the language is compatible with the geocoding API\n   */\n  geocoding: boolean;\n};\n\n/**\n * List of \"non-ISO specific\" languages.\n */\nexport const NonISOLanguage = {\n  /**\n   * Language mode to display the labels in the end user's device language.\n   */\n  AUTO: {\n    code: null,\n    flag: \"auto\",\n    name: \"Auto\",\n    latin: false,\n    isMode: true,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * The OSM language using latin script. MapTiler discourages its use as a primary language setting due to the lack of actual linguistic specificity,\n   * though it can be an handy fallback. This is not to be confused with the \"Classical Latin\" language, which is available under the tag `.CLASSICAL_LATIN`.\n   */\n  LATIN: {\n    code: \"latin\",\n    flag: \"name:latin\",\n    name: \"Latin\",\n    latin: true,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * The OSM language using non-latin script. MapTiler discourages its use as a primary language setting due to the lack of actual linguistic specificity,\n   * though it can be an handy fallback.\n   */\n  NON_LATIN: {\n    code: \"nonlatin\",\n    flag: \"name:nonlatin\",\n    name: \"Non Latin\",\n    latin: false,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Using the local language generaly (but not always) means that every labels of a given region will use the dominant local language.\n   */\n  LOCAL: {\n    code: null,\n    flag: \"name\",\n    name: \"Local\",\n    latin: true,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n} as const;\n\n/**\n * List of \"country specific\" languages.\n */\nexport const ISOLanguage = {\n  /**\n   * Albanian language\n   */\n  ALBANIAN: {\n    code: \"sq\",\n    flag: \"name:sq\",\n    name: \"Albanian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Amharic language\n   */\n  AMHARIC: {\n    code: \"am\",\n    flag: \"name:am\",\n    name: \"Amharic\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Arabic language (right-to-left script)\n   */\n  ARABIC: {\n    code: \"ar\",\n    flag: \"name:ar\",\n    name: \"Arabic\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Armenian language\n   */\n  ARMENIAN: {\n    code: \"hy\",\n    flag: \"name:hy\",\n    name: \"Armenian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Azerbaijani language\n   */\n  AZERBAIJANI: {\n    code: \"az\",\n    flag: \"name:az\",\n    name: \"Azerbaijani\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Basque language\n   */\n  BASQUE: {\n    code: \"eu\",\n    flag: \"name:eu\",\n    name: \"Basque\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Belarusian langauge\n   */\n  BELARUSIAN: {\n    code: \"be\",\n    flag: \"name:be\",\n    name: \"Belarusian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Bengali language\n   */\n  BENGALI: {\n    code: \"bn\",\n    flag: \"name:bn\",\n    name: \"Bengali\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Bosnian language\n   */\n  BOSNIAN: {\n    code: \"bs\",\n    flag: \"name:bs\",\n    name: \"Bosnian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Breton language\n   */\n  BRETON: {\n    code: \"br\",\n    flag: \"name:br\",\n    name: \"Breton\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Bulgarian language\n   */\n  BULGARIAN: {\n    code: \"bg\",\n    flag: \"bg\",\n    name: \"Bulgarian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Catalan language\n   */\n  CATALAN: {\n    code: \"ca\",\n    flag: \"name:ca\",\n    name: \"Catalan\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Chinese language\n   */\n  CHINESE: {\n    code: \"zh\",\n    flag: \"name:zh\",\n    name: \"Chinese\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Traditional Chinese language\n   */\n  TRADITIONAL_CHINESE: {\n    code: \"zh-Hant\",\n    flag: \"name:zh-Hant\",\n    name: \"Chinese (traditional)\",\n    latin: false,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Simplified Chinese language\n   */\n  SIMPLIFIED_CHINESE: {\n    code: \"zh-Hans\",\n    flag: \"name:zh-Hans\",\n    name: \"Chinese (simplified)\",\n    latin: false,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Corsican language\n   */\n  CORSICAN: {\n    code: \"co\",\n    flag: \"name:co\",\n    name: \"Corsican\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Croatian language\n   */\n  CROATIAN: {\n    code: \"hr\",\n    flag: \"name:hr\",\n    name: \"Croatian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Czech language\n   */\n  CZECH: {\n    code: \"cs\",\n    flag: \"name:cs\",\n    name: \"Czech\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Danish language\n   */\n  DANISH: {\n    code: \"da\",\n    flag: \"name:da\",\n    name: \"Danish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Dutch language\n   */\n  DUTCH: {\n    code: \"nl\",\n    flag: \"name:nl\",\n    name: \"Dutch\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * German language\n   */\n  GERMAN: {\n    code: \"de\",\n    flag: \"name:de\",\n    name: \"German\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Greek language\n   */\n  GREEK: {\n    code: \"el\",\n    flag: \"name:el\",\n    name: \"Greek\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * English language\n   */\n  ENGLISH: {\n    code: \"en\",\n    flag: \"name:en\",\n    name: \"English\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Esperanto language\n   */\n  ESPERANTO: {\n    code: \"eo\",\n    flag: \"name:eo\",\n    name: \"Esperanto\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Estonian language\n   */\n  ESTONIAN: {\n    code: \"et\",\n    flag: \"name:et\",\n    name: \"Estonian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Finnish language\n   */\n  FINNISH: {\n    code: \"fi\",\n    flag: \"name:fi\",\n    name: \"Finnish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * French language\n   */\n  FRENCH: {\n    code: \"fr\",\n    flag: \"name:fr\",\n    name: \"French\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Frisian language\n   */\n  FRISIAN: {\n    code: \"fy\",\n    flag: \"name:fy\",\n    name: \"Frisian (West)\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Georgian language\n   */\n  GEORGIAN: {\n    code: \"ka\",\n    flag: \"name:ka\",\n    name: \"Georgian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Hebrew language (right-to-left non-latin script)\n   */\n  HEBREW: {\n    code: \"he\",\n    flag: \"name:he\",\n    name: \"Hebrew\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Hindi language\n   */\n  HINDI: {\n    code: \"hi\",\n    flag: \"name:hi\",\n    name: \"Hindi\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Hungarian language\n   */\n  HUNGARIAN: {\n    code: \"hu\",\n    flag: \"name:hu\",\n    name: \"Hungarian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Icelandic language\n   */\n  ICELANDIC: {\n    code: \"is\",\n    flag: \"name:is\",\n    name: \"Icelandic\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Indonesian language\n   */\n  INDONESIAN: {\n    code: \"id\",\n    flag: \"name:id\",\n    name: \"Indonesian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Irish language\n   */\n  IRISH: {\n    code: \"ga\",\n    flag: \"name:ga\",\n    name: \"Irish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Italian language\n   */\n  ITALIAN: {\n    code: \"it\",\n    flag: \"name:it\",\n    name: \"Italian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Japanese language\n   */\n  JAPANESE: {\n    code: \"ja\",\n    flag: \"name:ja\",\n    name: \"Japanese\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Japanese language in Hiragana form\n   */\n  JAPANESE_HIRAGANA: {\n    code: \"ja-Hira\",\n    flag: \"name:ja-Hira\",\n    name: \"Japanese Hiragana form\",\n    latin: false,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Japanese language (latin script)\n   */\n  JAPANESE_2018: {\n    code: \"ja-Latn\",\n    flag: \"name:ja-Latn\",\n    name: \"Japanese (Latin 2018)\",\n    latin: true,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Japanese language in Kana form (non-latin script)\n   */\n  JAPANESE_KANA: {\n    code: \"ja_kana\",\n    flag: \"name:ja_kana\",\n    name: \"Japanese (Kana)\",\n    latin: false,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Japanse language, romanized (latin script)\n   */\n  JAPANESE_LATIN: {\n    code: \"ja_rm\",\n    flag: \"name:ja_rm\",\n    name: \"Japanese (Latin script)\",\n    latin: true,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Kannada language\n   */\n  KANNADA: {\n    code: \"kn\",\n    flag: \"name:kn\",\n    name: \"Kannada\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Kazakh language\n   */\n  KAZAKH: {\n    code: \"kk\",\n    flag: \"name:kk\",\n    name: \"Kazakh\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Korean language\n   */\n  KOREAN: {\n    code: \"ko\",\n    flag: \"name:ko\",\n    name: \"Korean\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Korean language (latin script)\n   */\n  KOREAN_LATIN: {\n    code: \"ko-Latn\",\n    flag: \"name:ko-Latn\",\n    name: \"Korean (Latin script)\",\n    latin: true,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Kurdish language\n   */\n  KURDISH: {\n    code: \"ku\",\n    flag: \"name:ku\",\n    name: \"Kurdish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Classical Latin language\n   */\n  CLASSICAL_LATIN: {\n    code: \"la\",\n    flag: \"name:la\",\n    name: \"Latin\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Latvian language\n   */\n  LATVIAN: {\n    code: \"lv\",\n    flag: \"name:lv\",\n    name: \"Latvian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Lithuanian language\n   */\n  LITHUANIAN: {\n    code: \"lt\",\n    flag: \"name:lt\",\n    name: \"Lithuanian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Luxembourgish language\n   */\n  LUXEMBOURGISH: {\n    code: \"lb\",\n    flag: \"name:lb\",\n    name: \"Luxembourgish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Macedonian language\n   */\n  MACEDONIAN: {\n    code: \"mk\",\n    flag: \"name:mk\",\n    name: \"Macedonian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Malayalm language\n   */\n  MALAYALAM: {\n    code: \"ml\",\n    flag: \"name:ml\",\n    name: \"Malayalam\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Maltese language\n   */\n  MALTESE: {\n    code: \"mt\",\n    flag: \"name:mt\",\n    name: \"Maltese\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Norwegian language\n   */\n  NORWEGIAN: {\n    code: \"no\",\n    flag: \"name:no\",\n    name: \"Norwegian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Occitan language\n   */\n  OCCITAN: {\n    code: \"oc\",\n    flag: \"name:oc\",\n    name: \"Occitan\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Persian language\n   */\n  PERSIAN: {\n    code: \"fa\",\n    flag: \"name:fa\",\n    name: \"Persian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Polish language\n   */\n  POLISH: {\n    code: \"pl\",\n    flag: \"name:pl\",\n    name: \"Polish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Portuguese language\n   */\n  PORTUGUESE: {\n    code: \"pt\",\n    flag: \"name:pt\",\n    name: \"Portuguese\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Punjabi language\n   */\n  PUNJABI: {\n    code: \"pa\",\n    flag: \"name:pa\",\n    name: \"Punjabi\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Western Punjabi language\n   */\n  WESTERN_PUNJABI: {\n    code: \"pnb\",\n    flag: \"name:pnb\",\n    name: \"Western Punjabi\",\n    latin: false,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Romanian language\n   */\n  ROMANIAN: {\n    code: \"ro\",\n    flag: \"name:ro\",\n    name: \"Romanian\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Romansh language\n   */\n  ROMANSH: {\n    code: \"rm\",\n    flag: \"name:rm\",\n    name: \"Romansh\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Russian language\n   */\n  RUSSIAN: {\n    code: \"ru\",\n    flag: \"name:ru\",\n    name: \"Russian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Serbian language (cyrillic script)\n   */\n  SERBIAN_CYRILLIC: {\n    code: \"sr\",\n    flag: \"name:sr\",\n    name: \"Serbian (Cyrillic script)\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Serbian language (latin script)\n   */\n  SERBIAN_LATIN: {\n    code: \"sr-Latn\",\n    flag: \"name:sr-Latn\",\n    name: \"Serbian (Latin script)\",\n    latin: true,\n    isMode: false,\n    geocoding: false,\n  } as LanguageInfo,\n\n  /**\n   * Scottish Gaelic language\n   */\n  SCOTTISH_GAELIC: {\n    code: \"gd\",\n    flag: \"name:gd\",\n    name: \"Scottish Gaelic\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Slovak language\n   */\n  SLOVAK: {\n    code: \"sk\",\n    flag: \"name:sk\",\n    name: \"Slovak\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Slovene language\n   */\n  SLOVENE: {\n    code: \"sl\",\n    flag: \"name:sl\",\n    name: \"Slovene\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Spanish language\n   */\n  SPANISH: {\n    code: \"es\",\n    flag: \"name:es\",\n    name: \"Spanish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Swedish language\n   */\n  SWEDISH: {\n    code: \"sv\",\n    flag: \"name:sv\",\n    name: \"Swedish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Tamil language\n   */\n  TAMIL: {\n    code: \"ta\",\n    flag: \"name:ta\",\n    name: \"Tamil\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Telugu language\n   */\n  TELUGU: {\n    code: \"te\",\n    flag: \"name:te\",\n    name: \"Telugu\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Thai language\n   */\n  THAI: {\n    code: \"th\",\n    flag: \"name:th\",\n    name: \"Thai\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Turkish language\n   */\n  TURKISH: {\n    code: \"tr\",\n    flag: \"name:tr\",\n    name: \"Turkish\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Ukrainian language\n   */\n  UKRAINIAN: {\n    code: \"uk\",\n    flag: \"name:uk\",\n    name: \"Ukrainian\",\n    latin: false,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Vietnamese language (latin script)\n   */\n  VIETNAMESE: {\n    code: \"vi\",\n    flag: \"name:vi\",\n    name: \"Vietnamese (Latin script)\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n\n  /**\n   * Welsh language\n   */\n  WELSH: {\n    code: \"cy\",\n    flag: \"name:cy\",\n    name: \"Welsh\",\n    latin: true,\n    isMode: false,\n    geocoding: true,\n  } as LanguageInfo,\n} as const;\n\n/**\n * The complete list of languages\n */\nexport const Language = {\n  ...NonISOLanguage,\n  ...ISOLanguage,\n} as const;\n\n/**\n * Get language infos from a provided language key, the key being the no-whitespace capital name.\n * By default, the language dictionary to look into is the one defined in this library, but another one could be provided\n * Returns `null` if not found.\n */\nexport function getLanguageInfoFromKey(\n  languageKey: string,\n  languageDictionary: { [k: string]: LanguageInfo } = Language,\n): LanguageInfo | null {\n  if (languageKey in languageDictionary) {\n    return languageKey[languageKey];\n  }\n  return null;\n}\n\n/**\n * Get the language info from a provided 2-character iso code.\n * By default, the language dictionary to look into is the one defined in this library, but another one could be provided\n * Returns `null` if not found.\n */\nexport function getLanguageInfoFromCode(\n  languageCode: string,\n  languageDictionary: { [k: string]: LanguageInfo } = Language,\n): LanguageInfo | null {\n  for (const lang of Object.values(languageDictionary)) {\n    if (lang.code === languageCode) {\n      return lang;\n    }\n  }\n  return null;\n}\n\n/**\n * Get the language info from a language flag (e.g. `\"name:en\"`).\n * This is also handy to check is a given language flag is a supported language.\n * By default, the language dictionary to look into is the one defined in this library, but another one could be provided\n * Returns `null` if not found.\n */\nexport function getLanguageInfoFromFlag(\n  languageFlag: string,\n  languageDictionary: { [k: string]: LanguageInfo } = Language,\n): LanguageInfo | null {\n  for (const lang of Object.values(languageDictionary)) {\n    if (lang.flag === languageFlag) {\n      return lang;\n    }\n  }\n  return null;\n}\n\n/**\n * Get the default language of the device, as a LanguageInfo object.\n */\nexport function getAutoLanguage(): LanguageInfo {\n  if (typeof navigator === \"undefined\") {\n    const code = Intl.DateTimeFormat().resolvedOptions().locale.split(\"-\")[0];\n    const langInfo = getLanguageInfoFromCode(code);\n    return langInfo ?? Language.ENGLISH;\n  }\n\n  const canditatelangs = Array.from(\n    new Set(navigator.languages.map((l) => l.split(\"-\")[0])),\n  )\n    .map((code) => getLanguageInfoFromCode(code))\n    .filter((li) => li);\n\n  return canditatelangs[0] ?? Language.ENGLISH;\n}\n\nexport function isLanguageInfo(obj: unknown): obj is LanguageInfo {\n  return (\n    obj !== null &&\n    typeof obj === \"object\" &&\n    \"code\" in obj &&\n    \"flag\" in obj &&\n    \"name\" in obj &&\n    \"latin\" in obj &&\n    \"isMode\" in obj &&\n    \"geocoding\" in obj &&\n    (typeof obj.code === \"string\" || obj.code === null) &&\n    typeof obj.flag === \"string\" &&\n    typeof obj.name === \"string\" &&\n    typeof obj.latin === \"boolean\" &&\n    typeof obj.isMode === \"boolean\" &&\n    typeof obj.geocoding === \"boolean\"\n  );\n}\n\n/**\n * By default, the language dictionary to look into is the one defined in this library, but another one could be provided\n */\nexport function toLanguageInfo(\n  lang: LanguageInfo | string,\n  languageDictionary: { [k: string]: LanguageInfo } = Language,\n): LanguageInfo | null {\n  // Could be directly an object of type LanguageInfo\n  if (isLanguageInfo(lang)) {\n    // Yet we want to make sure the provided languageInfo obj is not corrupted or incomplete,\n    // so we ask for the equivalent original:\n    return getLanguageInfoFromFlag(lang.flag, languageDictionary); // possibly returns null, which is fine.\n  }\n\n  // If it's not even a string, then it does not represent a language\n  if (typeof lang !== \"string\") {\n    return null;\n  }\n\n  return (\n    getLanguageInfoFromKey(lang, languageDictionary) ||\n    getLanguageInfoFromCode(lang, languageDictionary) ||\n    getLanguageInfoFromFlag(lang, languageDictionary) ||\n    null\n  );\n}\n\n/**\n * Tells if two languages are the same, even though possibly provided under different forms.\n * Note: this is not comparing object references, but values.\n */\nexport function areSameLanguages(\n  langA: string | LanguageInfo,\n  langB: string | LanguageInfo,\n  languageDictionary: { [k: string]: LanguageInfo } = Language,\n): boolean {\n  const langAObj = toLanguageInfo(langA, languageDictionary);\n  const langBObj = toLanguageInfo(langB, languageDictionary);\n\n  return langAObj && langBObj && langAObj.flag === langBObj.flag;\n}\n","import { config } from \"./config\";\n\nexport async function callFetch(resource, options = {}) {\n  if (config.fetch === null) {\n    throw new Error(\n      \"The fetch function was not found. If on NodeJS < 18 please specify the fetch function with config.fetch\",\n    );\n  }\n\n  //  Control if URL contains the api key\n  if (new URL(resource).searchParams.get(\"key\").trim() === \"\") {\n    throw new Error(\n      \"The MapTiler Cloud API key is missing. Set it in `config.apiKey` or get one for free at https://maptiler.com\",\n    );\n  }\n\n  return config.fetch(resource, options);\n}\n","/**\n * Some default settings for the SDK\n */\nconst defaults = {\n  maptilerApiURL: \"https://api.maptiler.com/\",\n  mapStyle: \"streets-v2\",\n};\n\nObject.freeze(defaults);\n\nexport { defaults };\n","/**\n * A ServiceError is an Error that includes the HTTP response details\n */\nexport class ServiceError extends Error {\n  constructor(\n    public res: Response,\n    customMessage = \"\",\n  ) {\n    super(\n      `Call to enpoint ${res.url} failed with the status code ${res.status}. ${customMessage}`,\n    );\n  }\n}\n","import type { BBox, Feature, Geometry, Position } from \"geojson\";\nimport { callFetch } from \"../callFetch\";\nimport { config } from \"../config\";\nimport { defaults } from \"../defaults\";\n\nimport {\n  type LanguageInfo,\n  getAutoLanguage,\n  getLanguageInfoFromCode,\n  isLanguageInfo,\n  Language,\n  getLanguageInfoFromFlag,\n} from \"../language\";\n\nimport { ServiceError } from \"./ServiceError\";\n\nconst customMessages = {\n  400: \"Query too long / Invalid parameters\",\n  403: \"Key is missing, invalid or restricted\",\n};\n\nexport type LanguageGeocodingOptions = {\n  /**\n   * Prefer results in specific language. It’s possible to specify multiple values.\n   */\n  language?: string | Array<string> | LanguageInfo | Array<LanguageInfo>;\n};\n\nexport type GeocodingPlaceType =\n  | \"continental_marine\"\n  | \"country\"\n  | \"major_landform\"\n  | \"region\"\n  | \"subregion\"\n  | \"county\"\n  | \"joint_municipality\"\n  | \"joint_submunicipality\"\n  | \"municipality\"\n  | \"municipal_district\"\n  | \"locality\"\n  | \"neighbourhood\"\n  | \"place\"\n  | \"postal_code\"\n  | \"address\"\n  | \"road\"\n  | \"poi\";\n\nexport type CommonForwardAndReverseGeocodingOptions =\n  LanguageGeocodingOptions & {\n    /**\n     * Custom MapTiler Cloud API key to use instead of the one in global `config`.\n     */\n    apiKey?: string;\n\n    /**\n     * Maximum number of results to show. Must be between 1 and 10.\n     * For reverse geocoding with multiple `types` this must not be set or must be set to 1.\n     * Default is 5 for forward and 1 for reverse geocoding.\n     */\n    limit?: number;\n\n    /**\n     * Features of specified types to query.\n     * If not specified, feature of all available types except `poi` and `major_landform` will be queried (`types = [\"poi\", \"major_landform\"]`, `excludeTypes = true`).\n     * In case of reverse geocoding if just a single type is specified, then multiple nearby features of the single type can be returned,\n     * otherwise single feature for every specified type (or default types) can be returned.\n     */\n    types?: GeocodingPlaceType[];\n\n    /**\n     * Set to `true` to use all available feature types except those mentioned in `types`. Default value is `false` if `types` is specified.\n     */\n    excludeTypes?: boolean;\n  };\n\nexport type GeocodingOptions = CommonForwardAndReverseGeocodingOptions & {\n  /**\n   * Only search for results in the specified area.\n   */\n  bbox?: BBox;\n\n  /**\n   * Prefer results close to a specific location.\n   */\n  proximity?: Position | \"ip\";\n\n  /**\n   * Limit search to specific country/countries specified as list of Alpha-2 ISO 3166-1 codes.\n   */\n  country?: string[];\n\n  /**\n   * Set to `false` to disable fuzzy (typo-tolerant) search. Default is `true`.\n   */\n  fuzzyMatch?: boolean;\n\n  /**\n   * Set to `true` to use autocomplete, `false` to disable it. Default is `true`.\n   */\n  autocomplete?: boolean;\n};\n\nexport type ReverseGeocodingOptions = CommonForwardAndReverseGeocodingOptions;\n\nexport type ByIdGeocodingOptions = LanguageGeocodingOptions & {\n  apiKey?: string;\n};\n\nexport type Coordinates = Position;\n\ntype FeatureProperties = {\n  /**\n   * External reference of the feature used for debugging purposes\n   */\n  ref: string;\n\n  /**\n   * ISO 3166-1 alpha-2 country code of the feature\n   */\n  country_code: string;\n\n  /**\n   * (experimental) Kind of the feature\n   */\n  kind?:\n    | \"road\"\n    | \"road_relation\"\n    | \"admin_area\"\n    | \"place\"\n    | \"street\"\n    | \"virtual_street\";\n\n  /**\n   * (experimental) Value of place=* tag from OpenStreetMap feature if kind=place\n   */\n  \"osm:place_type\"?: string;\n\n  /**\n   * (experimental) Feature tags from OpenStreetMap. Only available for `poi` type.\n   */\n  \"osm:tags\"?: Record<string, string>;\n\n  /**\n   * Array of POI categories. Only available for `poi` type.\n   */\n  categories?: string[];\n\n  /**\n   * Wikidata identifier.\n   */\n  wikidata?: string;\n};\n\ntype FeatureBase = {\n  /**\n   * Unique feature ID\n   */\n  id: string;\n\n  /**\n   * Localized feature name\n   */\n  text: string;\n\n  /**\n   * Query's primary ISO 639-1 language code\n   */\n  language?: string;\n\n  /**\n   * A string analogous to the `text` field that matches the query in the requested language.\n   * This field is only returned when multiple languages are requested using the `language` parameter, and will be present for each requested language.\n   */\n  [text: `text_${string}`]: string;\n\n  /**\n   * A ISO 639-1 query's fallback language code.\n   * This field is only returned when multiple languages are requested using the `language` parameter, and will be present for each requested language.\n   */\n  [language: `language_${string}`]: string;\n};\n\nexport type FeatureHierarchy = FeatureProperties & FeatureBase;\n\nexport type GeocodingFeature = Feature<Geometry, FeatureProperties> &\n  FeatureBase & {\n    /**\n     * Bounding box of the original feature as [w, s, e, n] array\n     */\n    bbox: BBox;\n\n    /**\n     * A [lon, lat] array of the original feature centeroid\n     */\n    center: Coordinates;\n\n    /**\n     * Formatted (including the hierarchy) and localized feature full name\n     */\n    place_name: string;\n\n    /**\n     * A string analogous to the `place_name` field that matches the query in the requested language.\n     * This field is only returned when multiple languages are requested using the `language` parameter, and will be present for each requested language.\n     */\n    [key: `place_name_${string}`]: string;\n\n    /**\n     * An array of feature types describing the feature.\n     * Currently each feature has only single type but this may change in the future.\n     */\n    place_type: GeocodingPlaceType[];\n\n    /**\n     * Localized type of the place name, matches `place_type` property\n     */\n    place_type_name: string[];\n\n    /**\n     * Feature hierarchy\n     */\n    context?: Array<FeatureHierarchy>;\n\n    /**\n     * Address number, if applicable\n     */\n    address?: string;\n\n    /**\n     * Indicates how well the returned feature matches the user's query on a scale from 0 to 1.\n     * 0 means the result does not match the query text at all, while 1 means the result fully matches the query text.\n     * You can use the relevance property to remove results that don't fully match the query.\n     */\n    relevance: number;\n\n    /**\n     * A string analogous to the `text` field that more closely matches the query than results in the specified language.\n     * For example, querying _Praha, Czechia_ with language set to English (`en`) might return a feature with the `text` _Prague_ and the `matching_text` _Praha_.\n     */\n    matching_text?: string;\n\n    /**\n     * A string analogous to the `place_name` field that more closely matches the query than results in the specified language.\n     * For example, querying _Praha, Czechia_ with language set to English (`en`) might return a feature with the `place_name` _Prague, Czechia_ and a `matching_place_name` of _Praha, Czechia_.\n     */\n    matching_place_name?: string;\n  };\n\nexport type GeocodingSearchResult = {\n  type: \"FeatureCollection\";\n\n  /**\n   * Array of features found\n   */\n  features: Array<GeocodingFeature>;\n\n  /**\n   * Tokenized search query\n   */\n  query: Array<string>;\n\n  /**\n   * Attribution of the result\n   */\n  attribution: string;\n};\n\nfunction addLanguageGeocodingOptions(\n  searchParams: URLSearchParams,\n  options: LanguageGeocodingOptions,\n) {\n  const { language } = options;\n\n  if (language === undefined) {\n    return;\n  }\n\n  // Making it an array of language codes\n  const languageCodes = (Array.isArray(language) ? language : [language])\n    .map((elem) => toValidGeocodingLanguageCode(elem))\n    .filter((elem) => elem); // removing the nulls\n\n  const languages = Array.from(new Set(languageCodes)).join(\",\");\n\n  searchParams.set(\"language\", languages);\n}\n\nfunction toValidGeocodingLanguageCode(\n  lang: string | LanguageInfo,\n): string | null {\n  const langInfo =\n    lang === Language.AUTO.flag\n      ? getAutoLanguage()\n      : typeof lang === \"string\"\n      ? getLanguageInfoFromCode(lang)\n      : isLanguageInfo(lang)\n      ? lang.flag === Language.AUTO.flag\n        ? getAutoLanguage()\n        : getLanguageInfoFromFlag(lang.flag)\n      : null;\n\n  return langInfo?.geocoding ? langInfo.code : null;\n}\n\nfunction addCommonForwardAndReverseGeocodingOptions(\n  searchParams: URLSearchParams,\n  options: CommonForwardAndReverseGeocodingOptions,\n) {\n  const { apiKey, limit, types, excludeTypes } = options;\n\n  searchParams.set(\"key\", apiKey ?? config.apiKey);\n\n  if (limit !== undefined) {\n    searchParams.set(\"limit\", String(limit));\n  }\n\n  if (types !== undefined) {\n    searchParams.set(\"types\", types.join(\",\"));\n  }\n\n  if (excludeTypes !== undefined) {\n    searchParams.set(\"excludeTypes\", String(excludeTypes));\n  }\n\n  addLanguageGeocodingOptions(searchParams, options);\n}\n\nfunction addForwardGeocodingOptions(\n  searchParams: URLSearchParams,\n  options: GeocodingOptions,\n) {\n  addCommonForwardAndReverseGeocodingOptions(searchParams, options);\n\n  const { bbox, proximity, country, fuzzyMatch, autocomplete } = options;\n\n  if (bbox !== undefined) {\n    searchParams.set(\"bbox\", bbox.join(\",\"));\n  }\n\n  if (proximity !== undefined) {\n    searchParams.set(\n      \"proximity\",\n      proximity === \"ip\" ? proximity : proximity.join(\",\"),\n    );\n  }\n\n  if (country !== undefined) {\n    searchParams.set(\"country\", country.join(\",\"));\n  }\n\n  if (fuzzyMatch !== undefined) {\n    searchParams.set(\"fuzzyMatch\", fuzzyMatch ? \"true\" : \"false\");\n  }\n\n  if (autocomplete !== undefined) {\n    searchParams.set(\"autocomplete\", autocomplete ? \"true\" : \"false\");\n  }\n}\n\n/**\n * Performs a forward geocoding query to MapTiler API.\n * Providing a human readable place name (of a city, country, street, etc.), the function returns\n * a list of candidate locations including longitude and latitude.\n *\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/geocoding/#search-by-name-forward\n *\n * @param query\n * @param options\n * @returns\n */\nasync function forward(\n  query: string,\n  options: GeocodingOptions = {},\n): Promise<GeocodingSearchResult> {\n  if (typeof query !== \"string\" || query.trim().length === 0) {\n    throw new Error(\"The query must be a non-empty string\");\n  }\n\n  const endpoint = new URL(\n    `geocoding/${encodeURIComponent(query)}.json`,\n    defaults.maptilerApiURL,\n  );\n\n  addForwardGeocodingOptions(endpoint.searchParams, options);\n\n  const res = await callFetch(endpoint.toString());\n\n  if (!res.ok) {\n    throw new ServiceError(res, customMessages[res.status] ?? \"\");\n  }\n\n  return await res.json();\n}\n\n/**\n * Perform a reverse geocoding query to MapTiler API.\n * Providing a longitude and latitude, this function returns a set of human readable information about this place (country, city, street, etc.)\n *\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/geocoding/#search-by-coordinates-reverse\n *\n * @param position\n * @param options\n * @returns\n */\nasync function reverse(\n  position: Position,\n  options: ReverseGeocodingOptions = {},\n): Promise<GeocodingSearchResult> {\n  if (!Array.isArray(position) || position.length < 2) {\n    throw new Error(\"The position must be an array of form [lng, lat].\");\n  }\n\n  const endpoint = new URL(\n    `geocoding/${position[0]},${position[1]}.json`,\n    defaults.maptilerApiURL,\n  );\n\n  addCommonForwardAndReverseGeocodingOptions(endpoint.searchParams, options);\n\n  const res = await callFetch(endpoint.toString());\n\n  if (!res.ok) {\n    throw new ServiceError(res, customMessages[res.status] ?? \"\");\n  }\n\n  return await res.json();\n}\n\n/**\n * Perform a geocoding query to MapTiler API to obtain fature by its ID.\n * Providing a feature ID, this function returns a feature which includes its full geometry.\n * Note that the feature ID is not stable and it changes when the database is re-indexed.\n *\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/geocoding/#search-by-feature-id\n *\n * @param id\n * @param options\n * @returns\n */\nasync function byId(\n  id: string,\n  options: ByIdGeocodingOptions = {},\n): Promise<GeocodingSearchResult> {\n  const endpoint = new URL(`geocoding/${id}.json`, defaults.maptilerApiURL);\n\n  endpoint.searchParams.set(\"key\", options.apiKey ?? config.apiKey);\n\n  addLanguageGeocodingOptions(endpoint.searchParams, options);\n\n  const res = await callFetch(endpoint.toString());\n\n  if (!res.ok) {\n    throw new ServiceError(res, customMessages[res.status] ?? \"\");\n  }\n\n  return await res.json();\n}\n\n/**\n * Perform a batch geocoding query to MapTiler API.\n * Provide multiple queries in the array. Each query can be forward, reverse or by feature ID.\n *\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/geocoding/#batch-geocoding\n *\n * @param queries\n * @param options\n * @returns\n */\nasync function batch(\n  queries: string[],\n  options: GeocodingOptions = {},\n): Promise<GeocodingSearchResult[]> {\n  if (!queries.length) {\n    return [];\n  }\n\n  const joinedQuery = queries\n    .map((query) => encodeURIComponent(query))\n    .join(\";\");\n\n  const endpoint = new URL(\n    `geocoding/${joinedQuery}.json`,\n    defaults.maptilerApiURL,\n  );\n\n  addForwardGeocodingOptions(endpoint.searchParams, options);\n\n  const res = await callFetch(endpoint.toString());\n\n  if (!res.ok) {\n    throw new ServiceError(res, customMessages[res.status] ?? \"\");\n  }\n\n  const obj = await res.json();\n\n  return queries.length === 1 ? [obj] : obj;\n}\n\n/**\n * The **geocoding** namespace contains asynchronous functions to call the [MapTiler Geocoding API](https://docs.maptiler.com/cloud/api/geocoding/).\n * The **Geocoding API** provides ways to get geographic coordinates from a human-readable search query of a place (forward geocoding)\n * and to get the location details (country, city, street, etc.) from a geographic coordinate (reverse geocoding);\n */\nconst geocoding = {\n  forward,\n  reverse,\n  byId,\n  batch,\n};\n\nexport { geocoding };\n","import { BBox } from \"geojson\";\nimport { callFetch } from \"../callFetch\";\nimport { config } from \"../config\";\nimport { defaults } from \"../defaults\";\nimport { ServiceError } from \"./ServiceError\";\n\nconst customMessages = {\n  403: \"Key is missing, invalid or restricted\",\n};\n\n/**\n * Options that can be provided to get user data.\n */\nexport type GeolocationInfoOptions = {\n  /**\n   * Custom MapTiler Cloud API key to use instead of the one in global `config`\n   */\n  apiKey?: string;\n\n  /**\n   * Include elevation (in meters) in the results.\n   * Default: `false`\n   */\n  elevation?: boolean;\n};\n\nexport type GeolocationResult = {\n  /**\n   * Name of the country\n   * Example: Switzerland\n   */\n  country?: string;\n\n  /**\n   * Two-letter code of the country ISO 3166-1 alpha-2 codes\n   * Example: CH\n   */\n  country_code?: string;\n\n  /**\n   * Bounds of the country in WGS84 degrees [west, south, east, north].\n   * Example: [5.95538,45.818852,10.490936,47.809357]\n   */\n  country_bounds?: BBox;\n\n  /**\n   * Official country languages in ISO 639-1 format. ISO 639-1 codes\n   * Example: [\"de\",\"fr\",\"it\"]\n   */\n  country_languages?: Array<string>;\n\n  /**\n   * Name of the continent\n   * Example: Europe\n   */\n  continent?: string;\n\n  /**\n   * Two-letter code of the continent\n   * Example: EU\n   */\n  continent_code?: string;\n\n  /**\n   * Indicated whether the country is part of the European Union.\n   */\n  eu?: boolean;\n\n  /**\n   * Name of the city\n   * Example: Zurich\n   */\n  city?: string;\n\n  /**\n   * Latitude of the location\n   * Example: 47.36667\n   */\n  latitude?: number;\n\n  /**\n   * Longitude of the location\n   * Example: 8.55\n   */\n  longitude?: number;\n\n  /**\n   * Postal code\n   * Example: 8000\n   */\n  postal?: string;\n\n  /**\n   * If known, the ISO 3166-2 name for the first level region. ISO 3166-2 codes\n   * Example: Zurich\n   */\n  region?: string;\n\n  /**\n   * If known, the ISO 3166-2 code for the first level region. ISO 3166-2 codes\n   * Example: ZH\n   */\n  region_code?: string;\n\n  /**\n   * Name of the timezone\n   * Example: Europe/Zurich\n   */\n  timezone?: string;\n\n  /**\n   * Elevation of the location in meters\n   * Example: 433\n   */\n  elevation?: number;\n};\n\n/**\n * Looks up geolocation details from IP address using MapTiler API.\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/geolocation/#ip-geolocation\n * @returns\n */\nasync function info(\n  options: GeolocationInfoOptions = {},\n): Promise<GeolocationResult> {\n  const endpoint = new URL(`geolocation/ip.json`, defaults.maptilerApiURL);\n  endpoint.searchParams.set(\"key\", options.apiKey ?? config.apiKey);\n\n  if (\"elevation\" in options) {\n    endpoint.searchParams.set(\n      \"elevation\",\n      options.elevation ? \"true\" : \"false\",\n    );\n  }\n\n  const urlWithParams = endpoint.toString();\n\n  const res = await callFetch(urlWithParams);\n\n  if (!res.ok) {\n    throw new ServiceError(\n      res,\n      res.status in customMessages ? customMessages[res.status] : \"\",\n    );\n  }\n\n  const obj = await res.json();\n  return obj as GeolocationResult;\n}\n\n/**\n * The **geolocation** namespace contains an asynchronous function to call the [MapTiler Geolocation API](https://docs.maptiler.com/cloud/api/geolocation/).\n * The **Geolocation API** provides a way to retrieve the IP address as well as geographic informations of a machine performing the query (most likely: a user)\n */\nconst geolocation = {\n  info,\n};\n\nexport { geolocation };\n","import { BBox, Position } from \"geojson\";\nimport { callFetch } from \"../callFetch\";\nimport { config } from \"../config\";\nimport { defaults } from \"../defaults\";\nimport { ServiceError } from \"./ServiceError\";\n\nconst customMessages = {\n  403: \"Key is missing, invalid or restricted\",\n};\n\nexport type CoordinatesSearchOptions = {\n  /**\n   * Custom MapTiler Cloud API key to use instead of the one in global `config`\n   */\n  apiKey?: string;\n\n  /**\n   * Maximum number of results returned (default: 10)\n   */\n  limit?: number;\n\n  /**\n   *  Show detailed transformations for each CRS (default: false)\n   */\n  transformations?: boolean;\n\n  /**\n   * Show exports in WKT and Proj4 notations (default: false)\n   */\n  exports?: boolean;\n};\n\nexport type CoordinateId = {\n  authority: string;\n  code: BigInteger;\n};\n\nexport type CoordinateExport = {\n  proj4: string;\n  wkt: string;\n};\n\nexport type CoordinateGrid = {\n  path: string;\n};\n\nexport type CoordinateTransformation = {\n  id: CoordinateId;\n  name: string;\n  reversible: boolean;\n  usable: boolean;\n  deprecated: boolean;\n  grids: Array<CoordinateGrid>;\n  accuracy?: number;\n  area?: string;\n  bbox?: BBox;\n  target_crs?: CoordinateId;\n  unit?: string;\n};\n\nexport type CoordinateSearch = {\n  id: CoordinateId;\n\n  name: string;\n\n  kind: string;\n\n  deprecated: boolean;\n\n  transformations?: Array<CoordinateTransformation | number>;\n\n  accuracy?: number;\n\n  unit?: string;\n\n  area?: string;\n\n  /**\n   * Bounding box of the resource in [min_lon, min_lat, max_lon, max_lat] order.\n   */\n  bbox?: BBox;\n\n  /**\n   * Most suitable transformation for this CRS.\n   */\n  default_transformation?: DefaultTransformation;\n\n  exports: CoordinateExport;\n};\n\nexport type DefaultTransformation = {\n  authority: string;\n  code: number;\n};\n\nexport type CoordinateSearchResult = {\n  /**\n   * The coordinate search results\n   */\n  results: Array<CoordinateSearch>;\n\n  /**\n   * The number of results\n   */\n  total: number;\n};\n\n/**\n * Search information about coordinate systems using MapTiler API.\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/coordinates/#search-coordinate-systems\n * @param query Can be any kind of CRS by name or code\n * @param options\n * @returns\n */\nasync function search(\n  query: string,\n  options: CoordinatesSearchOptions = {},\n): Promise<CoordinateSearchResult> {\n  if (typeof query !== \"string\" || query.trim().length === 0) {\n    throw new Error(\"The query must be a non-empty string\");\n  }\n\n  const endpoint = new URL(\n    `coordinates/search/${query}.json`,\n    defaults.maptilerApiURL,\n  );\n  endpoint.searchParams.set(\"key\", options.apiKey ?? config.apiKey);\n\n  if (\"limit\" in options) {\n    endpoint.searchParams.set(\"limit\", options.limit.toString());\n  }\n\n  if (\"transformations\" in options) {\n    endpoint.searchParams.set(\n      \"transformations\",\n      options.transformations.toString(),\n    );\n  }\n\n  if (\"exports\" in options) {\n    endpoint.searchParams.set(\"exports\", options.exports.toString());\n  }\n\n  const urlWithParams = endpoint.toString();\n  const res = await callFetch(urlWithParams);\n\n  if (!res.ok) {\n    throw new ServiceError(\n      res,\n      res.status in customMessages ? customMessages[res.status] : \"\",\n    );\n  }\n\n  const obj = await res.json();\n  return obj as CoordinateSearchResult;\n}\n\nexport type XYZ = {\n  x?: number;\n  y?: number;\n  z?: number;\n};\n\nexport type CoordinateTransformResult = {\n  results: Array<XYZ>;\n\n  /**\n   * Transformations are selected using given ops parameter.\n   * If no parameter is given, auto strategy is used.\n   * If given, it may try to use a listed transformation,\n   * then fallback to towgs84 patching, and finally boundcrs.\n   */\n  transformer_selection_strategy: string;\n};\n\n/**\n * Options that can be provided when transforming a coordinate from one CRS to another.\n */\nexport type CoordinatesTransformOptions = {\n  /**\n   * Custom MapTiler Cloud API key to use instead of the one in global `config`\n   */\n  apiKey?: string;\n\n  /**\n   * Source coordinate reference system (default: 4326)\n   */\n  sourceCrs?: number;\n\n  /**\n   * Target coordinate reference system (default: 4326)\n   */\n  targetCrs?: number;\n\n  /**\n   * List of codes of operations\n   */\n  operations?: number | Array<number>;\n};\n\n/**\n * Transforms coordinates from a source reference system to a target reference system using MapTiler API.\n * Learn more on the MapTiler API reference page: https://docs.maptiler.com/cloud/api/coordinates/#transform-coordinates\n * @param positions\n * @param options\n * @returns\n */\nasync function transform(\n  positions: Position | Array<Position>,\n  options: CoordinatesTransformOptions = {},\n): Promise<CoordinateTransformResult> {\n  const coordinatesStr = (Array.isArray(positions[0]) ? positions : [positions])\n    .map((coord) => `${coord[0]},${coord[1]}`)\n    .join(\";\");\n\n  const endpoint = new URL(\n    `coordinates/transform/${coordinatesStr}.json`,\n    defaults.maptilerApiURL,\n  );\n  endpoint.searchParams.set(\"key\", options.apiKey ?? config.ap