-
Notifications
You must be signed in to change notification settings - Fork 365
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add geolocation data to Netlify Dev (#4566)
* feat: add support for geolocation * chore: add tests * chore: update contributors field * chore: update docs * chore: fix tests * chore: update tests * chore: skip test * chore: add type annotations Co-authored-by: eduardoboucas <eduardoboucas@users.noreply.github.com>
- Loading branch information
1 parent
2c58896
commit f35b14c
Showing
14 changed files
with
411 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// @ts-check | ||
const fetch = require('node-fetch') | ||
|
||
const API_URL = 'https://netlifind.netlify.app' | ||
const STATE_GEO_PROPERTY = 'geolocation' | ||
|
||
// 24 hours | ||
const CACHE_TTL = 8.64e7 | ||
|
||
// 10 seconds | ||
const REQUEST_TIMEOUT = 1e4 | ||
|
||
/** | ||
* @typedef GeoLocation | ||
* @type {object} | ||
* @property {string} city | ||
* @property {object} country | ||
* @property {string} country.code | ||
* @property {string} country.name | ||
* @property {object} country | ||
* @property {string} country.code | ||
* @property {string} country.name | ||
*/ | ||
|
||
// The default location to be used if we're unable to talk to the API. | ||
const mockLocation = { | ||
city: 'San Francisco', | ||
country: { code: 'US', name: 'United States' }, | ||
subdivision: { code: 'CA', name: 'California' }, | ||
} | ||
|
||
/** | ||
* Returns geolocation data from a remote API, the local cache, or a mock | ||
* location, depending on the mode selected. | ||
* | ||
* @param {object} params | ||
* @param {string} params.geolocationMode | ||
* @param {"cache"|"update"|"mock"} params.mode | ||
* @param {boolean} params.offline | ||
* @param {import('../utils/state-config').StateConfig} params.state | ||
* @returns {Promise<GeoLocation>} | ||
*/ | ||
const getGeoLocation = async ({ mode, offline, state }) => { | ||
const cacheObject = state.get(STATE_GEO_PROPERTY) | ||
|
||
// If we have cached geolocation data and the `--geo` option is set to | ||
// `cache`, let's try to use it. | ||
if (cacheObject !== undefined && mode === 'cache') { | ||
const age = Date.now() - cacheObject.timestamp | ||
|
||
// Let's use the cached data if it's not older than the TTL. Also, if the | ||
// `--offline` option was used, it's best to use the cached location than | ||
// the mock one. | ||
if (age < CACHE_TTL || offline) { | ||
return cacheObject.data | ||
} | ||
} | ||
|
||
// If the `--geo` option is set to `mock`, we use the mock location. Also, | ||
// if the `--offline` option was used, we can't talk to the API, so let's | ||
// also use the mock location. | ||
if (mode === 'mock' || offline) { | ||
return mockLocation | ||
} | ||
|
||
// Trying to retrieve geolocation data from the API and caching it locally. | ||
try { | ||
const data = await getGeoLocationFromAPI() | ||
const newCacheObject = { | ||
data, | ||
timestamp: Date.now(), | ||
} | ||
|
||
state.set(STATE_GEO_PROPERTY, newCacheObject) | ||
|
||
return data | ||
} catch { | ||
// We couldn't get geolocation data from the API, so let's return the | ||
// mock location. | ||
return mockLocation | ||
} | ||
} | ||
|
||
/** | ||
* Returns geolocation data from a remote API | ||
* | ||
* @returns {Promise<GeoLocation>} | ||
*/ | ||
const getGeoLocationFromAPI = async () => { | ||
const res = await fetch(API_URL, { | ||
method: 'GET', | ||
timeout: REQUEST_TIMEOUT, | ||
}) | ||
const { geo } = await res.json() | ||
|
||
return geo | ||
} | ||
|
||
module.exports = { getGeoLocation, mockLocation } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
f35b14c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📊 Benchmark results
Package size: 273 MB