From 8b122c43ff7c264ccefb13113a4a4a607a408a2c Mon Sep 17 00:00:00 2001 From: Stephan Meijer Date: Mon, 27 Apr 2020 17:38:18 +0200 Subject: [PATCH] add Here provider --- .env.sample | 1 + docs/lib/providers.ts | 5 ++ docs/providers/here.mdx | 38 +++++++++++ doczrc.js | 1 + src/index.ts | 2 +- src/providers/__tests__/hereProvider.spec.js | 25 +++++++ src/providers/__tests__/hereResponse.json | 70 ++++++++++++++++++++ src/providers/hereProvider.ts | 60 +++++++++++++++++ 8 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 docs/providers/here.mdx create mode 100644 src/providers/__tests__/hereProvider.spec.js create mode 100644 src/providers/__tests__/hereResponse.json create mode 100644 src/providers/hereProvider.ts diff --git a/.env.sample b/.env.sample index 3b6c0957..16059460 100644 --- a/.env.sample +++ b/.env.sample @@ -2,3 +2,4 @@ BING_API_KEY=___YOUR_KEY___ GOOGLE_API_KEY=___YOUR_KEY___ LOCATIONIQ_API_KEY=___YOUR_KEY___ OPENCAGE_API_KEY=___YOUR_KEY___ +HERE_API_KEY=___YOUR_KEY___ diff --git a/docs/lib/providers.ts b/docs/lib/providers.ts index 20e9eef2..2ce22f49 100644 --- a/docs/lib/providers.ts +++ b/docs/lib/providers.ts @@ -2,6 +2,7 @@ import { BingProvider, EsriProvider, GoogleProvider, + HereProvider, LocationIQProvider, OpenCageProvider, OpenStreetMapProvider, @@ -18,6 +19,10 @@ export default { params: { key: process.env.GATSBY_GOOGLE_API_KEY }, }), + Here: new HereProvider({ + params: { apiKey: process.env.GATSBY_HERE_API_KEY }, + }), + LocationIQ: new LocationIQProvider({ params: { key: process.env.GATSBY_LOCATIONIQ_API_KEY }, }), diff --git a/docs/providers/here.mdx b/docs/providers/here.mdx new file mode 100644 index 00000000..60406c84 --- /dev/null +++ b/docs/providers/here.mdx @@ -0,0 +1,38 @@ +--- +name: Here +menu: Providers +route: /providers/here +--- + +import Playground from '../components/Playground'; +import Map from '../components/Map'; + +# Here Provider + +**note**: Here services require an API key. [Obtain here][1]. +For more options and configurations, see the [Here developer docs][2]. + + + + + + +```js +import { HereProvider } from 'leaflet-geosearch'; + +const provider = new HereProvider({ + params: { + apiKey: '__YOUR_HERE_KEY__' + }, +}); + +// add to leaflet +import { GeoSearchControl } from 'leaflet-geosearch'; + +map.addControl(new GeoSearchControl({ + provider, +})); +``` + +[1]: https://developer.here.com +[2]: https://developer.here.com/documentation/geocoding-search-api diff --git a/doczrc.js b/doczrc.js index 860f075d..b6efbb9b 100644 --- a/doczrc.js +++ b/doczrc.js @@ -20,6 +20,7 @@ export default { 'Bing', 'Esri', 'Google', + 'Here', 'LocationIQ', 'OpenCage', 'OpenStreetMap', diff --git a/src/index.ts b/src/index.ts index 07e1ae19..04506c04 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,8 +5,8 @@ export { default as SearchElement } from './SearchElement'; export { default as BingProvider } from './providers/bingProvider'; export { default as EsriProvider } from './providers/esriProvider'; export { default as GoogleProvider } from './providers/googleProvider'; +export { default as HereProvider } from './providers/hereProvider'; export { default as LocationIQProvider } from './providers/locationIQProvider'; export { default as OpenCageProvider } from './providers/openCageProvider'; export { default as OpenStreetMapProvider } from './providers/openStreetMapProvider'; - export { default as JsonProvider } from './providers/provider'; diff --git a/src/providers/__tests__/hereProvider.spec.js b/src/providers/__tests__/hereProvider.spec.js new file mode 100644 index 00000000..a1d5c614 --- /dev/null +++ b/src/providers/__tests__/hereProvider.spec.js @@ -0,0 +1,25 @@ +import Provider from '../hereProvider'; +import fixtures from './hereResponse.json'; + +describe('HereProvider', () => { + beforeAll(() => { + fetch.mockResponse(async () => ({ body: JSON.stringify(fixtures) })); + }); + + test('Can fetch results', async () => { + const provider = new Provider({ + params: { + apiKey: process.env.HERE_API_KEY, + }, + }); + + const results = await provider.search({ query: 'Madurodam' }); + const result = results[0]; + + expect(result.label).toBeTruthy(); + expect(result.x).toEqual(+fixtures.items[0].position.lng); + expect(result.y).toEqual(+fixtures.items[0].position.lat); + // here provider doesn't return bounds :( + expect(result.bounds).toBeFalsy(); + }); +}); diff --git a/src/providers/__tests__/hereResponse.json b/src/providers/__tests__/hereResponse.json new file mode 100644 index 00000000..67bfb403 --- /dev/null +++ b/src/providers/__tests__/hereResponse.json @@ -0,0 +1,70 @@ +{ + "items": [ + { + "title": "Madurodam", + "id": "here:pds:place:528u1703-2f80762a07494e6b9d5442d7ca773402", + "resultType": "place", + "address": { + "label": "Madurodam, George Maduroplein 1, 2584 RZ Den Haag, Nederland", + "countryCode": "NLD", + "countryName": "Nederland", + "state": "Zuid-Holland", + "county": "Den Haag", + "city": "Den Haag", + "district": "Van Stolkpark/Scheveningse Bosjes", + "street": "George Maduroplein", + "postalCode": "2584 RZ", + "houseNumber": "1" + }, + "position": { + "lat": 52.0991, + "lng": 4.29904 + }, + "access": [ + { + "lat": 52.09909, + "lng": 4.2995 + } + ], + "categories": [ + { + "id": "300-3000-0000" + }, + { + "id": "300-3000-0025" + }, + { + "id": "300-3100-0000" + }, + { + "id": "550-5520-0207" + } + ], + "contacts": [ + { + "phone": [ + { + "value": "+31704162400" + } + ], + "www": [ + { + "value": "http://www.madurodam.nl" + } + ], + "email": [ + { + "value": "info@madurodam.nl" + } + ] + } + ], + "scoring": { + "queryScore": 1.0, + "fieldScore": { + "placeName": 1.0 + } + } + } + ] +} diff --git a/src/providers/hereProvider.ts b/src/providers/hereProvider.ts new file mode 100644 index 00000000..768761e4 --- /dev/null +++ b/src/providers/hereProvider.ts @@ -0,0 +1,60 @@ +import AbstractProvider, { + EndpointArgument, + LatLng, + ParseArgument, + SearchResult, +} from './provider'; + +export interface RequestResult { + items: RawResult[]; +} + +export interface RawResult { + title: string; + id: string; + resultType: string; + address: { + label: string; + countryCode: string; + countryName: string; + state: string; + county: string; + city: string; + district: string; + street: string; + postalCode: string; + houseNumber: string; + }; + position: LatLng; + access: LatLng[]; + categories: { id: string }[]; + contacts: { [key: string]: { value: string }[] }[]; + scoring: { + queryScore: number; + fieldScore: { + placeName: number; + }; + }; +} + +export default class HereProvider extends AbstractProvider< + RequestResult, + RawResult +> { + searchUrl = 'https://geocode.search.hereapi.com/v1/geocode'; + + endpoint({ query }: EndpointArgument): string { + const params = typeof query === 'string' ? { q: query } : query; + return this.getUrl(this.searchUrl, params); + } + + parse(response: ParseArgument): SearchResult[] { + return response.data.items.map((r) => ({ + x: r.position.lng, + y: r.position.lat, + label: r.address.label, + bounds: null, + raw: r, + })); + } +}