Skip to content

Commit

Permalink
feat: add Geoapify Provider (#361)
Browse files Browse the repository at this point in the history
Added provider for communication with the Geoapify API.

---------

Co-authored-by: Stephan Meijer <stephan.meijer@gmail.com>
  • Loading branch information
CarolineVantim and smeijer committed Apr 18, 2023
1 parent d18b72f commit 8a7b7f4
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 1 deletion.
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ GOOGLE_API_KEY=___YOUR_KEY___
LOCATIONIQ_API_KEY=___YOUR_KEY___
OPENCAGE_API_KEY=___YOUR_KEY___
HERE_API_KEY=___YOUR_KEY___
GEOAPIFY_API_KEY=___YOUR_KEY___
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Leaflet.GeoSearch

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

[![All Contributors](https://img.shields.io/badge/all_contributors-53-orange.svg?style=flat-square)](#contributors-)

<!-- ALL-CONTRIBUTORS-BADGE:END -->

**Demo and Docs: [smeijer.github.io/leaflet-geosearch](https://smeijer.github.io/leaflet-geosearch)**
Expand Down Expand Up @@ -58,6 +60,7 @@ The control comes with a number of default providers:
- [Pelias]
- [Mapbox](https://docs.mapbox.com/help/tutorials/local-search-geocoding-api/)
- [GeoApiFR](https://geo.api.gouv.fr/adresse)
- [Geoapify](https://apidocs.geoapify.com/docs/geocoding/forward-geocoding/#about)

Although this project is still named `leaflet-geosearch`, this library is also
usable without LeafletJS, and does not have any dependencies whatsoever.
Expand Down Expand Up @@ -424,10 +427,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://paulschreiber.com/"><img src="https://avatars.githubusercontent.com/u/86784?v=4?s=100" width="100px;" alt="Paul Schreiber"/><br /><sub><b>Paul Schreiber</b></sub></a><br /><a href="https://github.com/smeijer/leaflet-geosearch/commits?author=paulschreiber" title="Code">💻</a></td>
<td align="center"><a href="https://nsilvestri.me/"><img src="https://avatars.githubusercontent.com/u/33607815?v=4?s=100" width="100px;" alt="Nick Silvestri"/><br /><sub><b>Nick Silvestri</b></sub></a><br /><a href="#ideas-nsilvestri" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/smeijer/leaflet-geosearch/commits?author=nsilvestri" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/teriblus"><img src="https://avatars.githubusercontent.com/u/17048774?v=4?s=100" width="100px;" alt="teriblus"/><br /><sub><b>teriblus</b></sub></a><br /><a href="https://github.com/smeijer/leaflet-geosearch/commits?author=teriblus" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/CarolineVantim"><img src="https://avatars.githubusercontent.com/u/82098788?s=400&u=b20b0acc98f9bdb694e20c56d6c157b3198b7c62&v=4" width="100px;" alt="Caroline Vantim"/><br /><sub><b>Caroline Vantim</b></sub></a><br /><a href="https://github.com/smeijer/leaflet-geosearch/commits?author=CarolineVantim" title="Code">💻</a></td>
</tr>
</tbody>
<tfoot>

</tfoot>
</table>

Expand Down
5 changes: 5 additions & 0 deletions docs/lib/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
OpenStreetMapProvider,
PeliasProvider,
GeoApiFrProvider,
GeoapifyProvider,
} from 'leaflet-geosearch';

export default {
Expand Down Expand Up @@ -44,6 +45,10 @@ export default {
params: { key: process.env.GATSBY_OPENCAGE_API_KEY },
}),

Geoapify: new GeoapifyProvider({
params: { apiKey: process.env.GATSBY_GEOAPIFY_API_KEY },
}),

OpenStreetMap: new OpenStreetMapProvider(),

Pelias: new PeliasProvider(),
Expand Down
40 changes: 40 additions & 0 deletions docs/providers/geoapify.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: Geoapify
menu: Providers
route: /providers/geoapify
---

import Playground from '../components/Playground';
import Map from '../components/Map';

# Geoapify Provider

**note**: Geoapify services require an API key. [Obtain geoapify][1].
For more options and configurations, see the [Geoapify developer docs][2].

<Playground>
<Map provider="Geoapify" />
</Playground>

```js
import { GeoapifyProvider } from 'leaflet-geosearch';

const provider = new GeoapifyProvider({
params: {
apiKey: '__YOUR_HERE_KEY__',
},
});

// add to leaflet
import { GeoSearchControl } from 'leaflet-geosearch';

map.addControl(
new GeoSearchControl({
provider,
style: 'bar',
}),
);
```

[1]: https://apidocs.geoapify.com/
[2]: https://apidocs.geoapify.com/docs/geocoding/forward-geocoding/#geocode-addresses
1 change: 1 addition & 0 deletions doczrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
'OpenStreetMap',
'Pelias',
'Custom Providers',
'Geoapify',
],
},
],
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export { default as OpenStreetMapProvider } from './providers/openStreetMapProvi
export { default as PeliasProvider } from './providers/peliasProvider';
export { default as MapBoxProvider } from './providers/mapBoxProvider';
export { default as GeoApiFrProvider } from './providers/geoApiFrProvider';
export { default as GeoapifyProvider } from './providers/geoapifyProvider';

export { default as JsonProvider } from './providers/provider';
39 changes: 39 additions & 0 deletions src/providers/__tests__/geoapifyProvider.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Provider from '../geoapifyProvider';
import fixtures from './geoapifyResponse.json';

describe('Geoapify', () => {
beforeAll(() => {
fetch.mockResponse(async () => ({ body: JSON.stringify(fixtures) }));
});

test('Can fetch results', async () => {
const provider = new Provider({
params: {
apiKey: process.env.GEOAPIFY_API_KEY,
},
});

const results = await provider.search({ query: 'Chicago' });
const result = results[0];

expect(result.label).toBeTruthy();
expect(result.x).toEqual(+fixtures.results[0].lon);
expect(result.y).toEqual(+fixtures.results[0].lat);
expect(result.bounds).toBeValidBounds();
});

test.skip('Can get localized results', async () => {
const provider = new Provider({
params: {
apiKey: process.env.GEOAPIFY_API_KEY,
'accept-language': 'nl',
},
});

const results = await provider.search({ query: 'Chicago' });
t.is(
results[0].label,
'1214-1224 West Van Buren Street, Chicago, IL 60607, United States of America',
);
});
});
65 changes: 65 additions & 0 deletions src/providers/__tests__/geoapifyResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"results": [
{
"datasource": {
"sourcename": "openstreetmap",
"attribution": "© OpenStreetMap contributors",
"license": "Open Database License",
"url": "https://www.openstreetmap.org/copyright"
},
"country": "United States",
"country_code": "us",
"state": "Illinois",
"county": "Cook County",
"city": "Chicago",
"postcode": "60607",
"suburb": "Near West Side",
"street": "West Van Buren Street",
"housenumber": "1214-1224",
"lon": -87.65816734222005,
"lat": 41.87695205,
"state_code": "IL",
"formatted": "1214-1224 West Van Buren Street, Chicago, IL 60607, United States of America",
"address_line1": "1214-1224 West Van Buren Street",
"address_line2": "Chicago, IL 60607, United States of America",
"category": "building",
"timezone": {
"name": "America/Chicago",
"offset_STD": "-06:00",
"offset_STD_seconds": -21600,
"offset_DST": "-05:00",
"offset_DST_seconds": -18000,
"abbreviation_STD": "CST",
"abbreviation_DST": "CDT"
},
"result_type": "building",
"rank": {
"importance": 0.60001,
"popularity": 6.686411370288237,
"confidence": 1,
"confidence_city_level": 1,
"confidence_street_level": 1,
"match_type": "full_match"
},
"place_id": "515888ea691fea55c0598074fbf63ff04440f00102f9013076880c00000000c00203",
"bbox": {
"lon1": -87.658723,
"lat1": 41.8765924,
"lon2": -87.6576007,
"lat2": 41.8770888
}
}
],
"query": {
"text": "1214-1224 West Van Buren Street, Chicago, IL 60607, United States of America",
"parsed": {
"housenumber": "1214-1224",
"street": "west van buren street",
"postcode": "60607",
"city": "chicago",
"state": "il",
"country": "united states of america",
"expected_type": "building"
}
}
}
95 changes: 95 additions & 0 deletions src/providers/geoapifyProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import AbstractProvider, {
EndpointArgument,
ParseArgument,
ProviderOptions,
RequestType,
SearchResult,
} from './provider';

export type RequestResult = {
results: RawResult[];
query: RawQuery[];
};

export interface RawResult {
country: string;
country_code: string;
state: string;
county: string;
city: string;
postcode: number;
suburb: string;
street: string;
lon: string;
lat: string;
state_code: string;
formatted: string;
bbox: BBox;
}

export interface RawQuery {
text: string;
parsed: RawQueryParsed;
}

export type RawQueryParsed = {
city: string;
expected_type: string;
};

export type BBox = {
lon1: string;
lat1: string;
lon2: string;
lat2: string;
};

export type GeoapifyProviderOptions = {
searchUrl?: string;
reverseUrl?: string;
} & ProviderOptions;

export default class GeoapifyProvider extends AbstractProvider<
RequestResult,
RawResult
> {
searchUrl: string;
reverseUrl: string;

constructor(options: GeoapifyProviderOptions = {}) {
super(options);

const host = 'https://api.geoapify.com/v1/geocode';
this.searchUrl = options.searchUrl || `${host}/search`;
this.reverseUrl = options.reverseUrl || `${host}/reverse`;
}

endpoint({ query, type }: EndpointArgument): string {
const params = typeof query === 'string' ? { text: query } : query;
params.format = 'json';

switch (type) {
case RequestType.REVERSE:
return this.getUrl(this.reverseUrl, params);

default:
return this.getUrl(this.searchUrl, params);
}
}

parse(response: ParseArgument<RequestResult>): SearchResult<RawResult>[] {
const records = Array.isArray(response.data.results)
? response.data.results
: [response.data.results];
return records.map((r) => ({
x: Number(r.lon),
y: Number(r.lat),
label: r.formatted,
bounds: [
[parseFloat(r.bbox.lat1), parseFloat(r.bbox.lon1)], // s, w
[parseFloat(r.bbox.lat2), parseFloat(r.bbox.lon2)], // n, e
],
raw: r,
}));
}
}
1 change: 1 addition & 0 deletions src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export { default as OpenStreetMapProvider } from './openStreetMapProvider';
export { default as PeliasProvider } from './peliasProvider';
export { default as MapBoxProvider } from './mapBoxProvider';
export { default as GeoApiFrProvider } from './geoApiFrProvider';
export { default as GeoapifyProvider } from './geoapifyProvider';

export { default as Provider } from './provider';

0 comments on commit 8a7b7f4

Please sign in to comment.