├── CHANGELOG.md ├── Geocoder.js ├── LICENSE ├── README.md ├── index.d.ts └── package.json /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Release Notes 2 | 3 | ### 0.4.0 4 | 5 | - Fixed fetching options 6 | - Removed deprecated code 7 | 8 | ### 0.3.0 9 | 10 | - Documented functions and errors 11 | - Only one function to use now 12 | 13 | ### 0.2.0 14 | 15 | - Reverse geocoding 16 | 17 | ### 0.1.0 18 | 19 | - Initial release -------------------------------------------------------------------------------- /Geocoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module to use google's geocoding & reverse geocoding. 3 | */ 4 | let Geocoder; 5 | export default Geocoder = { 6 | apiKey : null, 7 | options : {}, 8 | 9 | /** 10 | * Initialize the module. 11 | * @param {String} apiKey The api key of your application in google. 12 | * @param {Object} [options] extra options for your geocoding request. 13 | * @see https://developers.google.com/maps/documentation/geocoding/intro#geocoding 14 | */ 15 | init(apiKey, options = {}) { 16 | this.apiKey = apiKey; 17 | this.options = options; 18 | }, 19 | 20 | /** 21 | * @returns {boolean} True if the module has been initiated. False otherwise. 22 | */ 23 | get isInit() { 24 | return !!this.apiKey; 25 | }, 26 | 27 | /** 28 | * Do (reverse) geocoding, converting geographic coordinates into a human-readable address & vice-versa. 29 | * Accepted parameters: 30 | * 37 | * @returns {Promise.} Object containing informations about the place at the coordinates. 38 | * @see https://developers.google.com/maps/documentation/geocoding/intro#GeocodingResponses 39 | */ 40 | async from(...params) { 41 | // check api key 42 | if (!Geocoder.isInit) 43 | throw { 44 | code : Geocoder.Errors.NOT_INITIATED, 45 | message : "Geocoder isn't initialized. Call Geocoder.init function (only once), passing it your app's api key as parameter.", 46 | }; 47 | 48 | // --- convert parameters --- 49 | let queryParams; 50 | 51 | // (latitude, longitude) 52 | if (!isNaN(params[0]) && !isNaN(params[1])) 53 | queryParams = {latlng : `${params[0]},${params[1]}`}; 54 | 55 | // [latitude, longitude] 56 | else if (params[0] instanceof Array) 57 | queryParams = {latlng : `${params[0][0]},${params[0][1]}`}; 58 | 59 | // {latitude, longitude} or {lat, lng} 60 | else if (params[0] instanceof Object) 61 | queryParams = {latlng : `${params[0].lat || params[0].latitude},${params[0].lng || params[0].longitude}`}; 62 | 63 | // address, {bounds: {northeast: {lat, lng}, southwest: {lan, lng}}} 64 | else if (typeof params[0] === 'string' && params[1] instanceof Object) 65 | queryParams = {address : params[0], bounds : params[1]}; 66 | 67 | // address 68 | else if (typeof params[0] === 'string') 69 | queryParams = {address : params[0]}; 70 | 71 | // --- start geocoding --- 72 | 73 | // check query params 74 | if (!queryParams) 75 | // no query params, means parameters where invalid 76 | throw { 77 | code : Geocoder.Errors.INVALID_PARAMETERS, 78 | message : "Invalid parameters : \n" + JSON.stringify(params, null, 2), 79 | }; 80 | 81 | queryParams = { key: this.apiKey, ...this.options, ...queryParams } 82 | // build url 83 | const url = `https://maps.google.com/maps/api/geocode/json?${toQueryParams(queryParams)}`; 84 | 85 | let response, data; 86 | 87 | // fetch 88 | try { 89 | response = await fetch(url); 90 | } catch(error) { 91 | throw { 92 | code : Geocoder.Errors.FETCHING, 93 | message : "Error while fetching. Check your network.", 94 | origin : error, 95 | }; 96 | } 97 | 98 | // parse 99 | try { 100 | data = await response.json(); 101 | } catch(error) { 102 | throw { 103 | code : Geocoder.Errors.PARSING, 104 | message : "Error while parsing response's body into JSON. The response is in the error's 'origin' field. Try to parse it yourself.", 105 | origin : response, 106 | }; 107 | } 108 | 109 | // check response's data 110 | if (data.status !== 'OK') 111 | throw { 112 | code : Geocoder.Errors.SERVER, 113 | message : "Error from the server while geocoding. The received datas are in the error's 'origin' field. Check it for more informations.", 114 | origin : data, 115 | }; 116 | 117 | return data; 118 | }, 119 | 120 | /** 121 | * All possible errors. 122 | */ 123 | Errors : { 124 | /** 125 | * Module hasn't been initiated. Call {@link Geocoder.init}. 126 | */ 127 | NOT_INITIATED : 0, 128 | 129 | /** 130 | * Parameters are invalid. 131 | */ 132 | INVALID_PARAMETERS : 1, 133 | 134 | /** 135 | * Error wile fetching to server. 136 | * The error.origin property contains the original fetch error. 137 | */ 138 | FETCHING : 2, 139 | 140 | /** 141 | * Error while parsing server response. 142 | * The error.origin property contains the response. 143 | */ 144 | PARSING : 3, 145 | 146 | /** 147 | * Error from the server. 148 | * The error.origin property contains the response's body. 149 | */ 150 | SERVER : 4, 151 | }, 152 | } 153 | 154 | /** 155 | * Encodes a bounds object into a URL encoded-string. 156 | */ 157 | function encodeBounds(bounds) { 158 | const southwest = bounds.southwest; 159 | const northeast = bounds.northeast; 160 | return `${encodeURIComponent(southwest.lat)},${encodeURIComponent(southwest.lng)}|${encodeURIComponent(northeast.lat)},${encodeURIComponent(northeast.lng)}`; 161 | } 162 | 163 | /** 164 | * Encodes a component so it can be used safely inside a URL. 165 | */ 166 | function encodeComponent(key, value) { 167 | if (key === 'bounds') { 168 | return encodeBounds(value); 169 | } 170 | return encodeURIComponent(value); 171 | } 172 | 173 | /** 174 | * Convert an object into query parameters. 175 | * @param {Object} object Object to convert. 176 | * @returns {string} Encoded query parameters. 177 | */ 178 | function toQueryParams(object) { 179 | return Object.keys(object) 180 | .filter(key => !!object[key]) 181 | .map(key => key + "=" + encodeComponent(key, object[key])) 182 | .join("&") 183 | } 184 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Marco Lovetere 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-geocoding 2 | 3 | A geocoding module for [React Native](https://github.com/facebook/react-native) to transform a description of a location (i.e. street address, town name, etc.) into geographic coordinates (i.e. latitude and longitude) and vice versa. 4 | 5 | This module uses [Google Maps Geocoding API](https://developers.google.com/maps/documentation/geocoding/intro) and requires an API key for purposes of quota management. Please check [this link](https://developers.google.com/maps/documentation/geocoding/get-api-key) out to obtain your API key. 6 | 7 | ## Install 8 | 9 | ```shell 10 | npm install --save react-native-geocoding 11 | ``` 12 | 13 | ## Example 14 | 15 | ```js 16 | import Geocoder from 'react-native-geocoding'; 17 | 18 | // Initialize the module (needs to be done only once) 19 | Geocoder.init("xxxxxxxxxxxxxxxxxxxxxxxxx"); // use a valid API key 20 | // With more options 21 | // Geocoder.init("xxxxxxxxxxxxxxxxxxxxxxxxx", {language : "en"}); // set the language 22 | 23 | // Search by address 24 | Geocoder.from("Colosseum") 25 | .then(json => { 26 | var location = json.results[0].geometry.location; 27 | console.log(location); 28 | }) 29 | .catch(error => console.warn(error)); 30 | 31 | // Search by address, with a biased geo-bounds 32 | Geocoder.from("Pyramid", { 33 | southwest: {lat: 36.05, lng: -115.25}, 34 | northeast: {lat: 36.16, lng: -115.10}}) 35 | .then(json => { 36 | var location = json.results[0].geometry.location; 37 | console.log(location); 38 | }) 39 | .catch(error => console.warn(error)); 40 | 41 | // Search by geo-location (reverse geo-code) 42 | Geocoder.from(41.89, 12.49) 43 | .then(json => { 44 | var addressComponent = json.results[0].address_components[0]; 45 | console.log(addressComponent); 46 | }) 47 | .catch(error => console.warn(error)); 48 | 49 | // Works as well : 50 | // ------------ 51 | 52 | // location object 53 | Geocoder.from({ 54 | latitude : 41.89, 55 | longitude : 12.49 56 | }); 57 | 58 | // latlng object 59 | Geocoder.from({ 60 | lat : 41.89, 61 | lng : 12.49 62 | }); 63 | 64 | // array 65 | Geocoder.from([41.89, 12.49]); 66 | ``` 67 | 68 | # Error Codes 69 | | Name | Code | Description | 70 | | --- | --- | --- | 71 | | NOT_INITIATED | 0 | Module hasn't been initiated. Call init function, and pass it your app's api key as parameter. | 72 | | INVALID_PARAMETERS | 1 | Parameters are invalid. | 73 | | FETCHING | 2 | Error wile fetching to server. The error's 'origin' property contains the fetch error. | 74 | | PARSING | 3 | Error while parsing server response. The error's 'origin' property contains the response. | 75 | | SERVER | 4 | Error from the server. The error's 'origin' property contains the response's body. | 76 | 77 | 78 | ## Release Notes 79 | 80 | See [CHANGELOG.md](https://github.com/marlove/react-native-geocoding/blob/master/CHANGELOG.md) 81 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Geocoder { 2 | interface LatLng { 3 | lat: number; 4 | lng: number; 5 | } 6 | interface PlusCode { 7 | compound_code: string; 8 | global_code: string; 9 | } 10 | interface GeocoderResponse { 11 | plus_code: PlusCode; 12 | results: { 13 | address_components: { 14 | long_name: string; 15 | short_name: string; 16 | types: string[]; 17 | }[]; 18 | formatted_address: string; 19 | geometry: { 20 | bounds: { 21 | northeast: LatLng; 22 | southwest: LatLng; 23 | }; 24 | location: LatLng; 25 | location_type: 'APPROXIMATE' | 'ROOFTOP' | string; 26 | viewport: { 27 | northeast: LatLng; 28 | southwest: LatLng; 29 | }; 30 | }; 31 | place_id: string; 32 | types: string[]; 33 | plus_code: PlusCode; 34 | }[]; 35 | status: 'OK' | string; 36 | } 37 | 38 | type fromParams = 39 | | number 40 | | number[] 41 | | LatLng 42 | | { latitude: number; longitude: number } 43 | | string; 44 | 45 | function init(apiKey: string, options?: Object): void; 46 | function isInit(): boolean; 47 | function from(...params: fromParams[]): Promise; 48 | } 49 | 50 | declare module 'react-native-geocoding' { 51 | export default Geocoder; 52 | } 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-geocoding", 3 | "version": "0.5.0", 4 | "description": "A React Native module to transform a description of a location (i.e. street address, town name, etc.) into geographic coordinates (i.e. latitude and longitude) and vice versa.", 5 | "main": "Geocoder.js", 6 | "typings": "./index.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/marlove/react-native-geocoding" 10 | }, 11 | "keywords": [ 12 | "react-native", 13 | "ios", 14 | "android", 15 | "geocoder", 16 | "geocoding" 17 | ], 18 | "authors": [ 19 | "Marco Lovetere (https://marlove.net)", 20 | "Yairopro " 21 | ], 22 | "license": "MIT" 23 | } 24 | --------------------------------------------------------------------------------