import Geodecoder from "react-native-geocoder" ; type GeocodingProvider = "Google" | "Geocodio" | "LocationIQ" | "MapQuest" ; param { string } address param { "NanoflowCommons.GeocodingProvider.Google" | "NanoflowCommons.GeocodingProvider.Geocodio" | "NanoflowCommons.GeocodingProvider.LocationIQ" | "NanoflowCommons.GeocodingProvider.MapQuest" } geocodingProvider param { string } providerApiKey returns { Promise . < MxObject > } export async function Geocode ( address ? , geocodingProvider ? , providerApiKey ? ) { /**
     * Documentation:
     *  - Native: https://github.com/devfd/react-native-geocoder
     *  - Google: https://developers.google.com/maps/documentation/geocoding/intro#GeocodingRequests
     *  - Geocodio: https://www.geocod.io/docs/#geocoding
     *  - LocationIQ: https://locationiq.com/docs-html/index.html#search-forward-geocoding
     *  - MapQuest: https://developer.mapquest.com/documentation/open/geocoding-api/address/get/
     */ if ( ! address ) { return Promise . reject ( new Error ( "Input parameter 'Address' is required" ) ) ; } if ( navigator && navigator . product === "ReactNative" ) { return Geodecoder . geocodeAddress ( address ) . then ( results => { if ( results . length === 0 ) { return Promise . reject ( new Error ( "No results found" ) ) ; } return createMxObject ( String ( results [ 0 ] . position . lat ) , String ( results [ 0 ] . position . lng ) ) ; } ) ; } if ( ! geocodingProvider ) { return Promise . reject ( new Error ( "Input parameter 'Geocoding provider' is required for use on web" ) ) ; } if ( ! providerApiKey ) { return Promise . reject ( new Error ( "Input parameter 'Provider api key' is required for use on web" ) ) ; } const url = getApiUrl ( geocodingProvider , address , providerApiKey ) ; return fetch ( url ) . then ( response => response . json ( ) . catch ( ( ) => response . text ( ) . then ( text => { return Promise . reject ( new Error ( text ) ) ; } ) ) ) . then ( response => getLatLong ( geocodingProvider , response ) ) . then ( latLong => createMxObject ( latLong [ 0 ] , latLong [ 1 ] ) ) . catch ( error => Promise . reject ( error ) ) ; function getApiUrl ( provider , query , key ) { query = encodeURIComponent ( query ) ; key = encodeURIComponent ( key ) ; switch ( provider ) { case "Google" : return `https://maps.googleapis.com/maps/api/geocode/json?address=${ query }&key=${ key }` ; case "Geocodio" : return `https://api.geocod.io/v1.3/geocode?q=${ query }&api_key=${ key }` ; case "LocationIQ" : return `https://eu1.locationiq.com/v1/search.php?format=json&q=${ query }&key=${ key }` ; case "MapQuest" : return `https://open.mapquestapi.com/geocoding/v1/address?location=${ query }&key=${ key }` ; } } function getLatLong ( provider , response ) { switch ( provider ) { case "Google" : if ( response . status !== "OK" ) { throw new Error ( response . error_message ) ; } return [ response . results [ 0 ] . geometry . location . lat , response . results [ 0 ] . geometry . location . lng ] ; case "Geocodio" : if ( response . error ) { throw new Error ( response . error ) ; } if ( response . results . length === 0 ) { throw new Error ( "No results found" ) ; } return [ response . results [ 0 ] . location . lat , response . results [ 0 ] . location . lng ] ; case "LocationIQ" : if ( response . error ) { throw new Error ( response . error ) ; } if ( response . length === 0 ) { throw new Error ( "No results found" ) ; } return [ response [ 0 ] . lat , response [ 0 ] . lon ] ; case "MapQuest" : if ( response . info . statuscode !== 0 ) { throw new Error ( response . info . messages . join ( ", " ) ) ; } if ( response . results . length === 0 ) { throw new Error ( "No results found" ) ; } return [ response . results [ 0 ] . locations [ 0 ] . latLng . lat , response . results [ 0 ] . locations [ 0 ] . latLng . lng ] ; } } function createMxObject ( lat , long ) { return new Promise ( ( resolve , reject ) => { mx . data . create ( { entity : "NanoflowCommons.Position" , callback : mxObject => { mxObject . set ( "Latitude" , lat ) ; mxObject . set ( "Longitude" , long ) ; resolve ( mxObject ) ; } , error : ( ) => { reject ( new Error ( "Could not create 'NanoflowCommons.Position' object to store coordinates" ) ) ; } } ) ; } ) ; } }