Skip to content

Commit

Permalink
Merge pull request #31 from conveyal/autocomplete
Browse files Browse the repository at this point in the history
Autocomplete
  • Loading branch information
evansiroky authored Feb 28, 2017
2 parents 3d36aa4 + 47070ae commit 4646c13
Show file tree
Hide file tree
Showing 7 changed files with 1,970 additions and 494 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ before_install:
- npm i -g codecov
script:
- yarn run lint
- yarn run lint-docs
- yarn run test-node
- yarn run cover
- codecov
Expand Down
92 changes: 91 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,43 @@
# isomorphic-mapzen-search

Isomorphic Mapzen search for reuse across our JavaScript libraries. Get an API key [here](https://mapzen.com/developers). Coordinates must be anything that can be parsed by [lonlng](https://github.com/conveyal/lonlng).

## API
- [Examples](#examples)
- [API Documentation](#api)

## Examples

### `Autocomplete`

```js
import {autocomplete} from 'isomorphic-mapzen-search'

autocomplete({
apiKey: MAPZEN_API_KEY,
boundary: {
country: 'US',
rect: {
minLon: minLon,
minLat: minLat,
maxLon: maxLon,
maxLat: maxLat
}
},
focusPoint: {lat: 39.7691, lon: -86.1570},
layers: 'venue,coarse',
text: '1301 U Str'
}).then((result) => {
console.log(result)
}).catch((err) => {
console.error(err)
})
```

### `search({apiKey, text, ...options})`

```js
import {search} from 'isomorphic-mapzen-search'

search({
apiKey: MAPZEN_API_KEY,
text: '1301 U Street NW, Washington, DC',
Expand Down Expand Up @@ -36,6 +67,7 @@ search({

```js
import {reverse} from 'isomorphic-mapzen-search'

reverse({
apiKey: MAPZEN_API_KEY,
point: {
Expand All @@ -49,3 +81,61 @@ reverse({
console.error(err)
})
```

## API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

### autocomplete

Search for and address using
Mapzen's [Autocomplete](https://mapzen.com/documentation/search/autocomplete/)
service.

**Parameters**

- `$0` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.apiKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The Mapzen API key
- `$0.boundary` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.focusPoint` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.format` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
- `$0.layers` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** a comma-separated list of
[layer types](https://mapzen.com/documentation/search/autocomplete/#layers)
- `$0.sources` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** (optional, default `'gn,oa,osm,wof'`)
- `$0.text` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** query text

Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** A Promise that'll get resolved with the autocomplete result

### search

Search for an address using
Mapzen's [Search](https://mapzen.com/documentation/search/search/)
service.

**Parameters**

- `$0` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.apiKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The Mapzen API key
- `$0.boundary` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.focusPoint` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.format` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
- `$0.size` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** (optional, default `10`)
- `$0.sources` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** (optional, default `'gn,oa,osm,wof'`)
- `$0.text` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The address text to query for

Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** A Promise that'll get resolved with search result

### reverse

Reverse geocode using
Mapzen's [Reverse geocoding](https://mapzen.com/documentation/search/reverse/)
service.

**Parameters**

- `$0` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `$0.apiKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The Mapzen API key
- `$0.format` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
- `$0.point` **{lat: [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), lon: [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)}** Point to reverse geocode

Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** A Promise that'll get resolved with reverse geocode result
85 changes: 85 additions & 0 deletions __tests__/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,88 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`autocomplete should successfully autocomplete and include query in response 1`] = `
Object {
"bbox": Array [
-77.017897,
38.904,
-76.978642,
39.001084,
],
"features": Array [
Object {
"bbox": Array [
-77.017242,
38.973896,
-77.012062,
38.980594,
],
"geometry": Object {
"coordinates": Array [
-77.023104,
38.976745,
],
"type": "Point",
},
"properties": Object {
"accuracy": "centroid",
"confidence": 0.965,
"country": "United States",
"country_a": "USA",
"country_gid": "whosonfirst:country:85633793",
"county": "Montgomery County",
"county_gid": "whosonfirst:county:102082719",
"gid": "whosonfirst:neighbourhood:85851759",
"id": "85851759",
"label": "Takoma, Takoma Park, MD, USA",
"layer": "neighbourhood",
"locality": "Takoma Park",
"locality_gid": "whosonfirst:locality:85949501",
"name": "Takoma",
"neighbourhood": "Takoma",
"neighbourhood_gid": "whosonfirst:neighbourhood:85851759",
"region": "Maryland",
"region_a": "MD",
"region_gid": "whosonfirst:region:85688501",
"source": "whosonfirst",
"source_id": "85851759",
},
"type": "Feature",
},
],
"geocoding": Object {
"attribution": "https://search.mapzen.com/v1/attribution",
"engine": Object {
"author": "Mapzen",
"name": "Pelias",
"version": "1.0",
},
"query": Object {
"boundary.circle.lat": 38.8886,
"boundary.circle.lon": -77.043,
"boundary.circle.radius": 25,
"private": false,
"querySize": 20,
"size": 10,
"sources": Array [
"geonames",
"openaddresses",
"openstreetmap",
"whosonfirst",
],
"text": "takoma",
},
"timestamp": 1479272483487,
"version": "0.2",
},
"isomorphicMapzenSearchQuery": Object {
"api_key": "test-key",
"sources": "gn,oa,osm,wof",
"text": "123 a",
},
"type": "FeatureCollection",
}
`;

exports[`reverse should successfully reverse geocode and format 1`] = `
Array [
Object {
Expand Down
20 changes: 20 additions & 0 deletions __tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ const mockReverseResult = require('./mock-reverse-result.json')
const mockSearchResult = require('./mock-search-result.json')
const mockKey = 'test-key'

describe('autocomplete', () => {
it('should successfully autocomplete', async () => {
nock('https://search.mapzen.com/')
.get(/v1\/autocomplete/)
.reply(200, mockSearchResult)

const result = await geocoder.autocomplete({apiKey: mockKey, text: '123 a'})
expect(result.features[0].geometry.coordinates[0]).toEqual(-77.023104)
})

it('should successfully autocomplete and include query in response', async () => {
nock('https://search.mapzen.com/')
.get(/v1\/autocomplete/)
.reply(200, mockSearchResult)

const result = await geocoder.autocomplete({apiKey: mockKey, includeQueryInResponse: true, text: '123 a'})
expect(result).toMatchSnapshot()
})
})

describe('search', () => {
const searchQuery = '123 abc st'

Expand Down
120 changes: 109 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,99 @@
/* globals fetch */

import lonlat from '@conveyal/lonlat'
import qs from 'qs'

let fetch = (
typeof window === 'object'
? window.fetch
: (
typeof global === 'object'
? global.fetch
: undefined))
if (!fetch) {
fetch = require('isomorphic-fetch')
if (typeof (fetch) === 'undefined') {
require('isomorphic-fetch')
}

const mapzenUrl = 'https://search.mapzen.com/v1'
const searchUrl = `${mapzenUrl}/search`
const autocompleteUrl = `${mapzenUrl}/autocomplete`
const reverseUrl = `${mapzenUrl}/reverse`
const searchUrl = `${mapzenUrl}/search`

/**
* Search for and address using
* Mapzen's {@link https://mapzen.com/documentation/search/autocomplete/|Autocomplete}
* service.
*
* @param {Object} $0
* @param {string} $0.apiKey The Mapzen API key
* @param {Object} $0.boundary
* @param {Object} $0.focusPoint
* @param {boolean} $0.format
* @param {string} $0.layers a comma-separated list of
* {@link https://mapzen.com/documentation/search/autocomplete/#layers|layer types}
* @param {string} [$0.sources='gn,oa,osm,wof']
* @param {string} $0.text query text
* @return {Promise} A Promise that'll get resolved with the autocomplete result
*/
export function autocomplete ({
apiKey,
boundary,
focusPoint,
format,
layers,
sources = 'gn,oa,osm,wof',
text
}) {
// build query
const query = {
api_key: apiKey,
sources,
text
}

if (layers) {
query.layers = layers
}

if (focusPoint) {
const {lat, lon} = lonlat(focusPoint)
query['focus.point.lat'] = lat
query['focus.point.lon'] = lon
}

if (boundary) {
if (boundary.country) query['boundary.country'] = boundary.country
if (boundary.rect) {
query['boundary.rect.min_lat'] = boundary.rect.minLat
query['boundary.rect.min_lon'] = boundary.rect.minLon
query['boundary.rect.max_lat'] = boundary.rect.maxLat
query['boundary.rect.max_lon'] = boundary.rect.maxLon
}
/* Circle currently not supported in autocomplete
if (boundary.circle) {
const {lat, lon} = lonlat(boundary.circle.centerPoint)
query['boundary.circle.lat'] = lat
query['boundary.circle.lon'] = lon
query['boundary.circle.radius'] = boundary.circle.radius
}
*/
}

return run({
format,
query,
url: autocompleteUrl
})
}

/**
* Search for an address using
* Mapzen's {@link https://mapzen.com/documentation/search/search/|Search}
* service.
*
* @param {Object} $0
* @param {string} $0.apiKey The Mapzen API key
* @param {Object} $0.boundary
* @param {Object} $0.focusPoint
* @param {boolean} $0.format
* @param {number} [$0.size=10]
* @param {string} [$0.sources='gn,oa,osm,wof']
* @param {string} $0.text The address text to query for
* @return {Promise} A Promise that'll get resolved with search result
*/
export function search ({
apiKey,
boundary,
Expand Down Expand Up @@ -59,6 +137,17 @@ export function search ({
return run({format, query})
}

/**
* Reverse geocode using
* Mapzen's {@link https://mapzen.com/documentation/search/reverse/|Reverse geocoding}
* service.
*
* @param {Object} $0
* @param {string} $0.apiKey The Mapzen API key
* @param {boolean} $0.format
* @param {{lat: number, lon: number}} $0.point Point to reverse geocode
* @return {Promise} A Promise that'll get resolved with reverse geocode result
*/
export function reverse ({
apiKey,
format,
Expand All @@ -83,7 +172,16 @@ function run ({
}) {
return fetch(`${url}?${qs.stringify(query)}`)
.then((res) => res.json())
.then((json) => { return json && json.features && format ? json.features.map(split) : json })
.then((json) => {
let jsonResponse = json
if (json && json.features && format) {
jsonResponse = json.features.map(split)
}

jsonResponse.isomorphicMapzenSearchQuery = query

return jsonResponse
})
}

function split ({
Expand Down
Loading

0 comments on commit 4646c13

Please sign in to comment.