Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@goparrot/geocoder

goparrot336MIT4.5.0TypeScript support: included

TypeScript GeoCoder, node geocoding library, supports google maps, mapquest, here, open street map, tom tom

node, typescript, geo, geocode, geocoder, geocoding, geolocation, reverse, suggest, autocomplete, places, google-maps, arcgis, here, mapquest

readme

Build Status Coverage Status NPM version Greenkeeper badge Commitizen friendly Conventional Commits

Geocoder

Geocoder Logo

Description

Geocoder is a Typescript library which helps you build geo-aware applications by providing a powerful abstraction layer for geocoding manipulations.

Installation

$ npm i @goparrot/geocoder reflect-metadata axios

⚠️️ Each reflect-metadata installation has its own metadata storage, from which it reads and writes from. So if you had a project with multiple reflect-metadata packages, it could happen that in one file you write metadata in one reflect-metadata package and in another file you’re trying to retrieve this metadata accidently from the other reflect-metadata package, which of course doesn’t exist there.

Usage

Minimal

In the code snippet below we use Google provider.

import 'reflect-metadata';
import { Distance, Location, Geocoder, GoogleMapsProvider, Suggestion } from '@goparrot/geocoder';
import axios, { AxiosInstance } from 'axios';

const axios: AxiosInstance = axios.create();

const provider: GoogleMapsProvider = new GoogleMapsProvider(axios, 'YOUR_API_KEY');

const geocoder: Geocoder = new Geocoder(provider);

(async () => {
    try {
        const locations: Location[] = await geocoder.geocode({
            address: '1158 E 89th St, Chicago, IL 60619, USA',
        });

        console.info({ locations });
    } catch (err) {
        console.error(err);
    }

    try {
        const locations: Location[] = await geocoder.reverse({
            lat: 41.7340186,
            lon: -87.5960762,
        });

        console.info({ locations });
    } catch (err) {
        console.error(err);
    }

    try {
        const suggestions: Suggestion[] = await geocoder.suggest({
            address: '1158 E 89th St',
        });

        console.info({ suggestions });
    } catch (err) {
        console.error(err);
    }

    try {
        const location: Location = await geocoder.placeDetails({
            placeId: 'SOME_GOOGLE_PLACE_ID',
        });

        console.info({ location });
    } catch (err) {
        console.error(err);
    }

    try {
        const distance: Distance = await geocoder.distance({
            from: {
                lat: 40.871994,
                lon: -74.425937,
            },
            to: {
                lat: 40.863008,
                lon: -74.385286,
            },
            mode: TravelModeEnum.DRIVING,
        });

        console.info({ distance });
    } catch (err) {
        console.error(err);
    }
})();

Advanced

In the code snippet below we use Here provider.

import 'reflect-metadata';
import { Location, Geocoder, HereProvider, LoggerInterface } from '@goparrot/geocoder';
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';

// You can use any logger that fits the LoggerInterface
const logger: LoggerInterface = console;

// Set timeout for all requests
const axios: AxiosInstance = axios.create({
    timeout: 5000,
});

// You can log all requests
axios.interceptors.request.use((request: AxiosRequestConfig) => {
    logger.debug('api request', request);

    return request;
});

// You can log all responses
axios.interceptors.response.use((response: AxiosResponse): AxiosResponse => {
    logger.debug(`api response ${response.status}`, response.data);

    return response;
});

/**
 * Caching adapter for axios. Store request results in a configurable store to prevent unneeded network requests.
 * @link {https://github.com/RasCarlito/axios-cache-adapter}
 */

const provider: HereProvider = new HereProvider(axios, 'YOUR_APP_ID', 'YOUR_APP_CODE');

const geocoder: Geocoder = new Geocoder(provider);
geocoder.setLogger(logger);

(async () => {
    try {
        const locations: Location[] = await geocoder.geocode({
            // accuracy: AccuracyEnum.HOUSE_NUMBER,
            address: '1158 E 89th St, Chicago, IL 60619, USA',
            countryCode: 'US',
            // postalCode: '60619',
            // state: 'Illinois',
            // stateCode: 'IL',
            // city: 'Chicago',
            // language: 'en', // default
            // limit: 5, // default
            // fillMissingQueryProperties: true, // default
            withRaw: true, // default false
        });

        logger.info('locations', { locations });
    } catch (err) {
        logger.error(err);
    }

    try {
        const locations: Location[] = await geocoder.reverse({
            // accuracy: AccuracyEnum.HOUSE_NUMBER,
            lat: 41.7340186,
            lon: -87.5960762,
            countryCode: 'US',
            // language: 'en', // default
            // limit: 5, // default
            // withRaw: false, // default
        });

        console.info('locations', { locations });
    } catch (err) {
        console.error(err);
    }
})();

Providers

Legend:

  • ✅ - Implemented / ready to use
  • 🚫 - Provider doesn't support it
  • ⌛ - In progress
  • 🆘 - Need help with implementation
  • 🔍️ - Need to investigate if supported by provider

Location

World

Provider Geocode Reverse Suggest Place Details Distance
Algolia Places 🆘 🆘️ 🆘 🆘 🔍
ArcGIS Online ✅️ 🔍
Bing Maps 🆘 🆘️ 🔍️ 🆘 🔍
Geonames 🆘 🆘️ 🔍️ 🆘 🔍
Google Maps
Here 🔍
LocationIQ 🆘 🆘️ 🔍️ 🔍 🔍
Mapbox 🆘 🆘️ 🔍️ 🔍 🔍
MapQuest 🚫️ 🚫 🔍
Mapzen 🆘 🆘️ 🔍️ 🔍 🔍
Nominatim 🆘 🆘️ 🔍️ 🔍 🔍
OpenCage 🆘 🆘️ 🔍️ 🔍 🔍
Photon 🆘 🆘️ 🔍️ 🔍 🔍
PickPoint 🆘 🆘️ 🔍️ 🔍 🔍
TomTom 🆘 🆘️ 🔍️ 🔍 🔍
Yandex 🆘 🆘️ 🔍️ 🔍 🆘️

Special Geocoders and Providers

The ChainProvider

The ChainProvider is a special provider that takes a list of providers and iterates over this list to get information. Note that it stops its iteration when a provider returns a result.

import 'reflect-metadata';
import axios, { AxiosInstance } from 'axios';
import { Location, ChainProvider, HereProvider, MapQuestProvider, ProviderAggregator } from '@goparrot/geocoder';

const axios: AxiosInstance = axios.create({
    timeout: 5000,
});

const chainProvider: ChainProvider = new ChainProvider([new MapQuestProvider(axios, 'YOUR_API_KEY'), new HereProvider(axios, 'YOUR_APP_ID', 'YOUR_APP_CODE')]);

const geocoder: ProviderAggregator = new ProviderAggregator([chainProvider]);

(async () => {
    try {
        const locations: Location[] = await geocoder.geocode({
            address: '1158 E 89th St, Chicago, IL 60619, USA',
        });

        console.info({ locations });
    } catch (err) {
        console.error(err);
    }
})();

The ProviderAggregator

The ProviderAggregator is used to register several providers so that you can manualy decide which provider to use later on.

import 'reflect-metadata';
import axios, { AxiosInstance } from 'axios';
import { Location, GoogleMapsProvider, HereProvider, ProviderAggregator, MapQuestProvider } from '@goparrot/geocoder';

const axios: AxiosInstance = axios.create({
    timeout: 5000,
});

const geocoder: ProviderAggregator = new ProviderAggregator([
    new MapQuestProvider(axios, 'YOUR_API_KEY'),
    new HereProvider(axios, 'YOUR_APP_ID', 'YOUR_APP_CODE'),
]);

geocoder.registerProvider(new GoogleMapsProvider(axios, 'YOUR_API_KEY'));

(async () => {
    try {
        const locations: Location[] = await geocoder.using(GoogleMapsProvider).geocode({
            address: '1158 E 89th St, Chicago, IL 60619, USA',
        });

        console.info({ locations });
    } catch (err) {
        console.error(err);
    }
})();

The ProviderAggregator's API is fluent, meaning you can write:

const locations: Location[] = geocoder.registerProvider(new MyCustomProvider(axios)).using(MyCustomProvider).geocode({
    // ...
});

The using() method allows you to choose the provider to use by its class name. When you deal with multiple providers, you may want to choose one of them. The default behavior is to use the first one, but it can be annoying.

Versioning

Geocoder follows Semantic Versioning.

Contributing

See CONTRIBUTING file.

Unit Tests

In order to run the test suite, install the development dependencies:

$ npm i

Then, run the following command:

$ npm run coverage

Background

Inspired by geocoder-php/geocoder

License

Geocoder is MIT licensed.

changelog

Changelog

All notable changes to this project will be documented in this file. See standard-version for commit guidelines.

4.4.0 (2021-11-29)

Features

  • update npm dependencies (a22b9ef)

4.3.0 (2021-11-15)

Features

  • update npm dependencies (ae82fb7)

4.2.1 (2021-10-15)

Bug Fixes

  • provider: cannot find type definition file for heremaps (eeacc3a), closes #109

4.2.0 (2021-05-12)

Features

  • update npm dependencies (fce4674)

4.1.0 (2021-04-11)

Features

  • provider distance: add google distance api (7be4463)

Bug Fixes

  • command: an empty response should throw an InvalidServerResponseException (48fb804)
  • provider: google transformer cannot read property 'long_name' of undefined (ae5f8d5)

4.0.1 (2021-03-12)

Bug Fixes

  • geocode query stateCode can be more than 2 characters long (550c338)

4.0.0 (2020-03-23)

⚠ BREAKING CHANGES

  • lint: Drop support for Node.js 8. Require 10.18.0 instead which is the oldest supported version.

Bug Fixes

  • package: update world-countries to version 3.0.0 (ba12af3)

Chore

  • lint: move from tslint to eslint (a827fc1)

3.0.4 (2019-11-22)

Bug Fixes

  • provider place-details: restrict google place details query fields (be5dde9)

3.0.3 (2019-11-14)

3.0.1 (2019-11-13)

Bug Fixes

  • world-country-state-util: fix match method (a0df1fa)

3.0.0 (2019-11-04)

Bug Fixes

  • google location-bilder: fix raw data transformer (adc07bd)

Features

  • transformer: add a separate provider data transformation layer (f72dd77)

BREAKING CHANGES

  • transformer: - LocationInterface.country and LocationInterface.countryCode may be undefined.

  • remove LocationBuilder and SuggestionBuilder. Use AbstractLocationTransformer and AbstractSuggestionTransformer instead.

2.2.4 (2019-11-02)

Bug Fixes

  • google location: fix getting a city name (10b9c22)

2.2.3 (2019-10-22)

Bug Fixes

  • place-details: return NotFoundException if more then one result (53dd4f4)

2.2.2 (2019-10-18)

2.2.1 (2019-10-16)

Bug Fixes

  • geocode: query address max length from 100 to 150 (d08076d)

2.2.0 (2019-09-05)

Bug Fixes

  • google suggest: allow premise type as HOUSE_NUMBER accuracy (9eaab20)

Features

  • suggest: add suggestion accuracy for arcgis and here providers (6e898e3)

2.1.0 (2019-09-02)

Features

  • google suggest: add suggest accuracy (027691e)

2.0.0 (2019-08-27)

Bug Fixes

  • dependencies: fix dependencies (600e2b7)

BREAKING CHANGES

  • dependencies: axios, class-transformer and class-validator removed from dependencies and moved to peerDependencies

1.0.6 (2019-07-22)

1.0.5 (2019-07-20)

1.0.4 (2019-07-15)

1.0.3 (2019-06-21)

1.0.2 (2019-06-10)

1.0.1 (2019-05-08)

Bug Fixes

  • placeDetails: fix PlaceDetailsQuery interface (9ad6ec7)

1.0.0 (2019-05-03)

Bug Fixes

  • test: fix google integration test (21aa9b3)

0.10.0 (2019-04-12)

Features

  • geocoder: add placeDetails method (10ef077)
  • provider here: add suggest method (1c05fe9)
  • provider map-quest: add suggest method (cff7600)

0.9.1 (2019-03-25)

Bug Fixes

  • command geocode: cannot read property 'countryCode' of undefined (ecd79f4)

0.9.0 (2019-03-25)

Features

  • geocode query: add exactMatch option (9480892)
  • geocoder suggest: add suggest method (d4cb26c)

0.8.1 (2019-03-25)

Bug Fixes

  • provider arcgis: wrong reverse url (e0e3a6d)

0.8.0 (2019-03-20)

Features

  • query: no raw data is returned by default (6f708cd)

BREAKING CHANGES

  • query: in the previous version, the raw data was returned by default

0.7.1 (2019-03-19)

Bug Fixes

  • location-builder: fix types (bc4cb43)

0.7.0 (2019-03-19)

Features

  • provider: abstract logic for provider's actions (d705119)
  • provider: add raw data to the Location object (e65e652)

0.6.0 (2019-03-13)

Features

  • provider: add ArcgisProvider (4d7cbba)

0.5.0 (2019-03-06)

Bug Fixes

  • changelog: fix changelog for v0.3.0 and v0.4.0 (ab1b826)

Code Refactoring

  • chagne class name from Adress to Location (7225728)

BREAKING CHANGES

  • chagne class name from Adress to Location and AddressBuilder to LocationBuilder

0.4.0 (2019-03-05)

Features

  • decider: rm CircularDecider, add StatefulDecider, StatelessDecider (46c8455)

BREAKING CHANGES

  • decider: ProviderAggregator by default works with StatefulDecider (before was CircularDecider)

0.3.0 (2019-03-05)

Features

  • provider: add StatefulChainProvider (d038545)

0.2.0 (2019-03-04)

Features

  • provider: add provider.maxAccuracy (2516ab4), closes #3

BREAKING CHANGES

  • provider: contains a breaking change for MapQuestProvider and for general business logic

0.1.1 (2019-03-02)

Bug Fixes

Features