Nucleus Powered Mitochondria

    @goparrot/geocoder
    TypeScript icon, indicating that this package has built-in type declarations

    4.4.0 • Public • Published

    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.

    Install

    npm i @goparrot/geocoder

    DownloadsWeekly Downloads

    94

    Version

    4.4.0

    License

    MIT

    Unpacked Size

    1.74 MB

    Total Files

    894

    Last publish

    Collaborators

    • dev.goparrot.ai