photon.js (3103B)
1 import L from 'leaflet'; 2 3 import * as logging from '~/lib/logging'; 4 import {fetch} from '~/lib/xhr-promise'; 5 6 import {BaseProvider} from './remoteBase'; 7 8 const PhotonProvider = BaseProvider.extend({ 9 name: 'Photon', 10 11 options: { 12 apiUrl: 'https://photon.komoot.io/api/', 13 attribution: { 14 text: 'Photon by Komoot', 15 url: 'https://photon.komoot.io/', 16 }, 17 delay: 700, 18 languages: ['en', 'de', 'fr', 'it'], 19 defaultLanguage: 'en', 20 }, 21 22 initialize: function (options) { 23 BaseProvider.prototype.initialize.call(this, options); 24 this.lang = this.getRequestLanguages(this.options.languages, this.options.defaultLanguage)[0]; 25 }, 26 27 search: async function (query, {latlng}) { 28 if (!(await this.waitNoNewRequestsSent())) { 29 return {error: 'Request cancelled'}; 30 } 31 const url = new URL(this.options.apiUrl); 32 if (this.options.maxResponses) { 33 url.searchParams.append('limit', this.options.maxResponses); 34 } 35 url.searchParams.append('q', query); 36 url.searchParams.append('lang', 'en'); 37 url.searchParams.append('lat', latlng.lat); 38 url.searchParams.append('lon', latlng.lng); 39 let xhr; 40 try { 41 xhr = await fetch(url.href, {responseType: 'json', timeout: 5000}); 42 } catch (e) { 43 if (e.name === 'XMLHttpRequestPromiseError') { 44 logging.captureException(e, 'Error response from photon search api'); 45 return {error: `Search failed: ${e.message}`}; 46 } 47 throw e; 48 } 49 const places = xhr.responseJSON.features.map((feature) => { 50 const properties = feature.properties; 51 let address = [ 52 properties.street, 53 properties.housenumber, 54 properties.city, 55 properties.state, 56 properties.country, 57 ] 58 .filter((it) => it) 59 .join(', '); 60 let bbox = null; 61 let zoom = null; 62 if (properties.extent) { 63 bbox = L.latLngBounds([ 64 [properties.extent[1], properties.extent[0]], 65 [properties.extent[3], properties.extent[2]], 66 ]); 67 } else { 68 zoom = 17; 69 } 70 let title = properties.name; 71 if (!title) { 72 title = address; 73 address = null; 74 } 75 let category = properties.osm_value; 76 if (['yes'].includes(category)) { 77 category = properties.osm_key; 78 } 79 category = category.replace('_', ' '); 80 return { 81 title, 82 latlng: L.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]), 83 bbox, 84 category, 85 address, 86 zoom, 87 icon: null, 88 }; 89 }); 90 return {results: places}; 91 }, 92 }); 93 94 export {PhotonProvider};