Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global Paths #22

Merged
merged 161 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
161 commits
Select commit Hold shift + click to select a range
7a9fcc8
Have started to move the major pieces into place, but huge huge issue…
sdl60660 Sep 17, 2021
c7d63c8
Updated prompt
sdl60660 Sep 17, 2021
9cc840e
Removed bounds on geocoder
sdl60660 Sep 17, 2021
16adf3f
small tweaks
sdl60660 Sep 21, 2021
187fe6a
Fixed 'x' button on navigation box during overview mode so that autop…
sdl60660 Sep 21, 2021
7decb11
Inset map now technically dynamic (though this is highlighting some o…
sdl60660 Sep 21, 2021
218fe18
Bumped padding and set max zoom level on inset map
sdl60660 Sep 22, 2021
82c9525
Adding ocean boundary data from here: https://github.com/nvkelso/natu…
sdl60660 Sep 22, 2021
b3deebf
Added global lakes files from here: https://github.com/nvkelso/natura…
sdl60660 Sep 22, 2021
ab2a5a0
Added global stopping features, fixed map bounds, fixed unknown river…
sdl60660 Oct 17, 2021
850f292
Added global stopping features, fixed map bounds, fixed unknown river…
sdl60660 Oct 17, 2021
88d4298
Pre-center map on origin for shared link
sdl60660 Oct 17, 2021
8eafd3f
Adjusting default multiplier on desktop
sdl60660 Oct 17, 2021
d5a5432
Resetting river highlight at start of run
sdl60660 Oct 17, 2021
f1aad5c
Changing default zoom on desktop back
sdl60660 Oct 17, 2021
e8d1044
Fixed feature group indexing and jumps, fixed an issue with final fea…
sdl60660 Oct 18, 2021
0f07569
Made some adjustments to elevation querrying that seems to help some …
sdl60660 Oct 18, 2021
5d606d2
Adjusted smoothing and error handling
sdl60660 Oct 18, 2021
43a583c
Fixed error handling for locations without hits
sdl60660 Oct 18, 2021
feb7331
Added latitude bounds to exclude Antarctica from the map, while still…
sdl60660 Oct 18, 2021
4be6a40
Disabled user pitch and rotate
sdl60660 Oct 19, 2021
d0d32df
Disabled user pitch and rotate
sdl60660 Oct 19, 2021
db36548
Removed some unnecessary lines
sdl60660 Oct 19, 2021
4d21520
Fixed starting position
sdl60660 Oct 19, 2021
83be652
Fixed click disable
sdl60660 Oct 19, 2021
4d9496f
Still some issues with speed variation at higher altitudes, but mostl…
sdl60660 Nov 5, 2021
92ee576
Updated terrain exagerration to get high elevation points more in lin…
sdl60660 Nov 7, 2021
edc0a5c
Removed a console log
sdl60660 Nov 8, 2021
a720762
Added ability for locator map to resize (and eventually serve as moda…
sdl60660 Nov 8, 2021
58ca448
Created feature name suggestion modal (though the design/content is n…
sdl60660 Nov 9, 2021
7023182
Fixed inset map size on mobile
sdl60660 Nov 9, 2021
ab90e1c
Fixed minor error-triggering bug on locator map
sdl60660 Nov 9, 2021
1ae49ca
Fixed one more locator map sizing issue introduced on the last commit
sdl60660 Nov 9, 2021
2481a6c
Fixed some conditional display issues on the navigation box
sdl60660 Nov 9, 2021
04280f3
Setting up name server
sdl60660 Dec 21, 2021
34c9db0
Merge branch 'global' of https://github.com/sdl60660/river-runner int…
sdl60660 Dec 21, 2021
0643aa3
Small name server fix and prepping for heroku
sdl60660 Dec 21, 2021
2daa978
Small name server tweak
sdl60660 Dec 21, 2021
05eb81f
node version specified'
sdl60660 Dec 21, 2021
4e06845
node version update
sdl60660 Dec 21, 2021
897af70
fixed package-locks
sdl60660 Dec 21, 2021
ce5b682
updated lockfile
sdl60660 Dec 21, 2021
9ce7ede
Removing package locks
sdl60660 Dec 21, 2021
1d00e8e
fixed procfile
sdl60660 Dec 21, 2021
2f49fe2
Text change on locator map modal
sdl60660 Dec 21, 2021
4d38f10
locator map styling
sdl60660 Dec 21, 2021
9dce5af
parsing request body
sdl60660 Dec 21, 2021
92f4954
Resolved merge issues, fixed some modal styling and added dummy (for …
sdl60660 Dec 21, 2021
3960d9b
Merge branch 'global' of https://github.com/sdl60660/river-runner int…
sdl60660 Dec 21, 2021
467fff1
Added another console log
sdl60660 Dec 21, 2021
3588c36
Merge branch 'global' of https://github.com/sdl60660/river-runner int…
sdl60660 Dec 21, 2021
ce8a509
Changing parsing on JSON
sdl60660 Dec 21, 2021
7fd1bef
Small update to models/logging
sdl60660 Dec 21, 2021
7126652
Removing debugging loggint
sdl60660 Dec 21, 2021
db0e657
Name suggestions are all wired up
sdl60660 Dec 21, 2021
2ac07f8
Merge branch 'global' of https://github.com/sdl60660/river-runner int…
sdl60660 Dec 21, 2021
45b9dcb
Bringing mapbox version back to 2.3 to reduce elevation responsivness…
sdl60660 Dec 21, 2021
0f5bd20
Removing duplicate attribution on locator/inset map
sdl60660 Dec 21, 2021
55d4c6c
Update README.md
sdl60660 Dec 22, 2021
3b5464c
Updated attribution
sdl60660 Dec 22, 2021
4cd39fc
Updating node versionn
sdl60660 Dec 22, 2021
3cd84d5
Fixed some of the issues with the intial terrain elevation query
sdl60660 Dec 22, 2021
fb62658
Set up name overrides for future if we hit critical mass of suggestio…
sdl60660 Dec 22, 2021
7d4e096
Added check on flowlines against inland features to properly label th…
sdl60660 Dec 22, 2021
6307463
Updated inset refresh rate and added manual override for gulf of st l…
sdl60660 Dec 23, 2021
dde50e1
Added some name overrides
sdl60660 Dec 23, 2021
0dbaf90
Updated data URL to trim number of returned properties and data size
sdl60660 Dec 27, 2021
3c3a416
Fixed issue with terminal stubs of stopping features (e.g. Gulf of Me…
sdl60660 Dec 27, 2021
a7e5b00
Fixed auto-play disrupt bug
sdl60660 Dec 27, 2021
fc3844a
Added an override
sdl60660 Dec 27, 2021
556a70f
Correcting an issue with river feature names when there are interrupt…
sdl60660 Dec 28, 2021
3dc4291
Added another couple of overrides
sdl60660 Dec 28, 2021
b2e0ae8
Added another override
sdl60660 Dec 28, 2021
2cfe037
Adding another name override
sdl60660 Dec 28, 2021
09cc2f9
Added another name override and prepped assignParentFeatureNames to a…
sdl60660 Dec 28, 2021
1595586
Cleaned up a little conditional logic
sdl60660 Dec 28, 2021
a7606a6
Added an extra clear on max bounds for inset map, as a fallback, and …
sdl60660 Dec 28, 2021
d67ef50
Commenting out some unused selectors
sdl60660 Dec 28, 2021
637821d
Adding a name override
sdl60660 Dec 28, 2021
592cb60
Added name override
sdl60660 Dec 28, 2021
4e45306
Added a couple more Australian overrides
sdl60660 Dec 28, 2021
82254a0
Trying something with overrides
sdl60660 Dec 28, 2021
e149337
reverting .toString() method, since it's unnecessary
sdl60660 Dec 28, 2021
dde6622
Name override
sdl60660 Dec 28, 2021
877d756
Updated Columbia River stopping feature name
sdl60660 Dec 28, 2021
ba427cc
Fixed cases where river features are staggered with several lakes in-…
sdl60660 Dec 28, 2021
8472500
Name override
sdl60660 Dec 28, 2021
2e22d48
Had to bump active path removal array length because some paths are l…
sdl60660 Dec 28, 2021
625723a
A few more name overrides
sdl60660 Dec 28, 2021
0ca37f4
Adding some name overrides, updating method on terminal stopping feat…
sdl60660 Dec 28, 2021
2643c41
Adjusted default mobile zoom level
sdl60660 Dec 28, 2021
c8fe5ef
Name override
sdl60660 Dec 29, 2021
b8f4132
Adding name overrides in Madagascar
sdl60660 Dec 29, 2021
be5abc0
Updated attribution box
sdl60660 Dec 30, 2021
71cd548
name overrides
sdl60660 Dec 30, 2021
7e2814b
Updated mobile breakpoint to 700px and added a new breakpoint for con…
sdl60660 Dec 30, 2021
f020d6c
Fixed navigation grouping issue when identified inland features don't…
sdl60660 Dec 31, 2021
2aa28af
Updated global stopping features to attach IDs
sdl60660 Dec 31, 2021
496b0d9
Fixed positioning on inset map's dot to true path instead of smoothed…
sdl60660 Dec 31, 2021
8cde3d7
Removing an unused variable from ticks
sdl60660 Dec 31, 2021
3664287
Removing some console logs
sdl60660 Dec 31, 2021
8cd6e93
Overrides
sdl60660 Dec 31, 2021
cd16a94
Override/stopping feature name update
sdl60660 Dec 31, 2021
e480450
Small name override/stopping feature name fix
sdl60660 Dec 31, 2021
6108788
Overrides
sdl60660 Dec 31, 2021
0628630
Switched format of override file to CSV, adjusted resize anomation on…
sdl60660 Jan 1, 2022
5305169
Renamed a component and added new overrides
sdl60660 Jan 1, 2022
afb8ec8
Renamed a component and added new overrides
sdl60660 Jan 1, 2022
67b5a94
Adding capacity to track queries (completely anonymously)
sdl60660 Jan 1, 2022
25f4a0c
Fixed a name server import issue
sdl60660 Jan 1, 2022
5291214
Re-factored/moved a lot of the old NLDI or advanced feature methods i…
sdl60660 Jan 1, 2022
909cdac
Removing some old data files and adding some overrides in Vietnam
sdl60660 Jan 1, 2022
ac6bc92
Some norweigen overrides
sdl60660 Jan 1, 2022
a3a9563
Name overrides
sdl60660 Jan 1, 2022
6843010
A little re-factoring
sdl60660 Jan 1, 2022
c9b2f16
A little refactoring and clean up
sdl60660 Jan 1, 2022
45d66df
Name override
sdl60660 Jan 1, 2022
68498d3
Fixed the camera start issue by unsmoothing the first couple of coord…
sdl60660 Jan 1, 2022
4364a99
Fixed some syntax in a util
sdl60660 Jan 1, 2022
18fc05e
Name overrides
sdl60660 Jan 1, 2022
a952931
Fixed a stopping feature and unsmoothed the last coordinate in a path…
sdl60660 Jan 1, 2022
3238bd7
Writing in an exception to the smoother in case of very short paths
sdl60660 Jan 1, 2022
ceb1581
Name overrides
sdl60660 Jan 1, 2022
8dac88f
Updated site meta tags (some will need to revert after merging back i…
sdl60660 Jan 1, 2022
f28dc49
package.json changes
sdl60660 Jan 2, 2022
bc38dba
Re-disabled touchZoomRotate on mobile
sdl60660 Jan 2, 2022
42cb24f
Correctly disabled zoom rotate without disabling zoom
sdl60660 Jan 2, 2022
9f5d0a7
Name overrides
sdl60660 Jan 2, 2022
85831cf
Name overrides
sdl60660 Jan 2, 2022
f5c7588
Adjusted default zoom levels and added override
sdl60660 Jan 2, 2022
35dd227
Added manifest.json and robots.txt to public
sdl60660 Jan 2, 2022
d10ef56
Updated robots.txt
sdl60660 Jan 2, 2022
6744538
Fixed some edge case issues with elevation queries and path smoothing…
sdl60660 Jan 2, 2022
160fa95
PR name overrides
sdl60660 Jan 2, 2022
f0b9eda
Name override
sdl60660 Jan 2, 2022
83eccea
Fixed geolocator issues for points out of bounds on map wrap
sdl60660 Jan 2, 2022
35b52b3
Sending search errors to queries collection now too to track most fre…
sdl60660 Jan 2, 2022
1ea58b8
Updated mongo schema for queries to include error flag
sdl60660 Jan 2, 2022
0e38e7d
Added a ridiculous, manual adjustment for the great lakes path, which…
sdl60660 Jan 2, 2022
70ccbd7
Adjusted default zoom level on desktop
sdl60660 Jan 2, 2022
ea22715
Added ko-fi link and tab-enabled some components with some new aria l…
sdl60660 Jan 2, 2022
f635881
Updated inset map aria label to be more dynamic
sdl60660 Jan 2, 2022
2479aab
Fixed Amazon feature naming/stop feature name
sdl60660 Jan 3, 2022
d86c118
Added some credits on usused components and capacity for adding a bui…
sdl60660 Jan 3, 2022
78940de
Made some adjustments to inland features
sdl60660 Jan 3, 2022
8a09cd3
Updated meta tags in site header
sdl60660 Jan 3, 2022
b11b793
Updated project github link to point to global branch (for now)
sdl60660 Jan 4, 2022
57b963d
Added different preview image for global
sdl60660 Jan 4, 2022
c293537
Adding version to preview image to fix cache
sdl60660 Jan 4, 2022
fd65724
Update README.md
sdl60660 Jan 4, 2022
920ece9
Update README.md
sdl60660 Jan 4, 2022
00dcebf
Added funding link
sdl60660 Jan 4, 2022
37c289a
Fixed funding links directory
sdl60660 Jan 4, 2022
381e188
More dynamic error handling to handle server down cases differently t…
sdl60660 Jan 4, 2022
fd5f7e9
Fixed typo in prompt box
sdl60660 Jan 4, 2022
33e9b8c
Overriding Amazon stopping feature name
sdl60660 Jan 5, 2022
b27b3f5
Tacking a tag onto email link
sdl60660 Jan 5, 2022
0e41695
Added name override
sdl60660 Jan 5, 2022
e2ac908
Directly attaching route URL to suggestions to make it faster to vet
sdl60660 Jan 5, 2022
e59f147
Updated column name on name override csv
sdl60660 Jan 5, 2022
76695bc
Merge branch 'main' into global
sdl60660 Jan 5, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/node_modules/
/name_server/node_modules
/name_server/.env
/public/build/

.DS_Store
Expand All @@ -20,4 +22,5 @@
# Original shapefile can be found here: https://hub.arcgis.com/datasets/esri::usa-detailed-water-bodies?geometry=167.943%2C22.299%2C-35.172%2C47.182
# /data_processing/data/water_bodies.geojson

name_server
package-lock.json
*/package-lock.json
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: npm start --prefix name_server
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# River Runner

This uses USGS [NHDPlus data](https://www.usgs.gov/core-science-systems/ngp/national-hydrography/nhdplus-high-resolution) and their [NLDI API](https://waterdata.usgs.gov/blog/nldi-intro/) to visualize the path of a rain droplet from any point in the contiguous United States to its end point (usually the ocean, sometimes the Great Lakes, Canada/Mexico, or another inland water feature). It'll find the closest river/stream flowline coordinate to a click/search and then animate along that flowline's downstream path.
This project visualizes the path of a rain droplet from any point in the world to its end point (usually an ocean or an inland water features). It will find the closest river/stream flowline coordinate to a click/search and then animate along that flowline's downstream path. The data used in this project comes from the [River Runner API](https://ksonda.github.io/global-river-runner/), which is based on several open source projects and datasets. Similar data, initially used for the project, came from the USGS's [NHDPlus data](https://www.usgs.gov/core-science-systems/ngp/national-hydrography/nhdplus-high-resolution) and their [NLDI API](https://waterdata.usgs.gov/blog/nldi-intro/)

I've used mapbox to animate the downstream path, but needed to make all sorts of adjustments for elevation and bearing changes to prevent jerkiness/nausea (just moving from point to point feels a little like flying through turbulence while shaking your head side-to-side).

I've hosted a dataset with NHDPlus [Value Added Attributes](https://www.usgs.gov/core-science-systems/ngp/national-hydrography/value-added-attributes-vaas) on Firebase, which allows me to group flowlines into their parent features and determine distances quickly.

**Note**: The newly-released, global version of this project is in beta. We currently have relatively poor coverage of river names outside of the United States, which we are hoping to fill out, as well as some UX edge-cases and bugs that we hope to resolve.

## Examples

Here are a couple of examples of what it looks like in action.
Expand Down Expand Up @@ -35,7 +37,7 @@ Thank you to [Mapbox](https://www.mapbox.com/) for sponsoring this project!
<img src="https://user-images.githubusercontent.com/12772904/129089126-5c528d47-961f-427f-820f-df58974d15c3.png" alt="mapbox-logo-black" width="300"/>

## Updates
* **January 2021**: The [global version](https://river-runner-global.samlearner.com/) of this tool is now released and in beta! While some lingering issues are resolved and it remains in beta, it can be found on this branch, while the original, US-only version is preserved [here](https://github.com/sdl60660/river-runner/tree/us-only) in Github, and at its original URL: https://river-runner.samlearner.com/. This is to avoid any breaking changes to existing share links/paths due to any discrepancies and because minor US issues persist on the global version, mainly when paths involve dams, canals, or conduits.

* **January 2021**: The [global version](https://river-runner-global.samlearner.com/) of this tool is now released and in beta! While some lingering issues are resolved and it remains in beta, it can be found on [this branch](https://github.com/sdl60660/river-runner/tree/global). The original, US-only version is preserved on [this branch](https://github.com/sdl60660/river-runner/tree/us-only) in Github and at its original URL: https://river-runner.samlearner.com/. This is to avoid any breaking changes to existing share links/paths due to any discrepancies and because minor US issues persist on the global version, mainly when paths involve dams, canals, or conduits.

If you'd like to be notified about major updates to the tool, you can sign up for an email list [here](https://tinyletter.com/samlearner)
42 changes: 42 additions & 0 deletions data_processing/create_global_stop_feature_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import json

with open('data/ne_10m_geography_marine_polys.geojson', 'r') as f:
seas = json.load(f)['features']

with open('data/ne_10m_lakes.geojson', 'r') as f:
lakes = json.load(f)['features']


output_cols = ['name','featurecla']
ocean_feature_types = ['strait', 'gulf', 'river', 'inlet', 'sound', 'lagoon', 'ocean', 'sea', 'bay', 'fjord', 'generic', 'channel', 'reef']
lake_feature_types = ['alkaline lake', 'lake', 'reservoir']

all_output_features = []

for feature in (seas + lakes):
if feature['properties']['featurecla'].lower() in ocean_feature_types:
stop_feature_type = 'ocean'
else:
stop_feature_type = 'inland lake'

slimmed_feature_properties = {
'stop_feature_type': stop_feature_type,
'stop_feature_type_specific': feature['properties']['featurecla'].lower(),
'stop_feature_name': feature['properties']['name'],
}

geometry = feature['geometry']
if type(geometry['coordinates'][0][0][0]) == list:
geometry['type'] = "MultiPolygon"

output_feature = {
"type": "Feature",
"geometry": geometry,
"properties": slimmed_feature_properties
}
all_output_features.append(output_feature)

# Output as a GeoJSON file for now, but then use mapshaper.org to compress to a TopoJSON
output_data = {"type": "FeatureCollection", "features": all_output_features}
with open('data/global_stopping_features.geojson', 'w') as f:
json.dump(output_data, f)
1 change: 1 addition & 0 deletions data_processing/data/global_stopping_features.geojson

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions data_processing/data/global_stopping_features.json

Large diffs are not rendered by default.

307 changes: 307 additions & 0 deletions data_processing/data/ne_10m_geography_marine_polys.geojson

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions data_processing/data/ne_10m_geography_marine_polys.json

Large diffs are not rendered by default.

1,357 changes: 1,357 additions & 0 deletions data_processing/data/ne_10m_lakes.geojson

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions data_processing/data/ne_10m_lakes.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions name_server/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Port number
PORT=3000

# URL of the Mongo DB
MONGODB_URL=mongodb://127.0.0.1:27017/node-boilerplate
15 changes: 15 additions & 0 deletions name_server/ecosystem.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"apps": [
{
"name": "app",
"script": "src/index.js",
"instances": 1,
"autorestart": true,
"watch": false,
"time": true,
"env": {
"NODE_ENV": "production"
}
}
]
}
43 changes: 43 additions & 0 deletions name_server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "name_server",
"version": "1.0.0",
"private": true,
"description": "node/express name server for processing name suggestions from river runner app",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "pm2 start ecosystem.config.json --no-daemon",
"dev": "cross-env NODE_ENV=development nodemon src/index.js"
},
"author": "Sam Learner",
"repository": {
"type": "git",
"url": "https://github.com/sdl60660/river-runner"
},
"license": "ISC",
"dependencies": {
"compression": "^1.7.4",
"cors": "^2.8.5",
"cross-env": "^7.0.0",
"dotenv": "^10.0.0",
"express": "^4.17.2",
"express-mongo-sanitize": "^2.1.0",
"express-rate-limit": "^5.5.1",
"helmet": "^4.1.0",
"http-status": "^1.5.0",
"joi": "^17.5.0",
"mongoose": "^5.13.13",
"nodemailer": "^6.3.1",
"passport": "^0.5.2",
"pm2": "^5.1.2",
"validator": "^13.0.0",
"winston": "^3.3.3",
"xss-clean": "^0.1.1"
},
"devDependencies": {
"nodemon": "^2.0.15"
},
"engines": {
"node": "14.x"
}
}
49 changes: 49 additions & 0 deletions name_server/src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const express = require('express');
const helmet = require('helmet');
const xss = require('xss-clean');
const mongoSanitize = require('express-mongo-sanitize');
const compression = require('compression');
const cors = require('cors');
const httpStatus = require('http-status');
const { errorConverter, errorHandler } = require('./middlewares/error');
const ApiError = require('./utils/ApiError');

const { router } = require('./routes');

const app = express();

// set security HTTP headers
app.use(helmet());

// parse json request body
app.use(express.json());

// parse urlencoded request body
app.use(express.urlencoded({ extended: true }));

// sanitize request data
app.use(xss());
app.use(mongoSanitize());

// gzip compression
app.use(compression());

// enable cors
app.use(cors());
app.options('*', cors());

// API Routes
app.use('/api', router);

// send back a 404 error for any unknown api request
app.use((req, res, next) => {
next(new ApiError(httpStatus.NOT_FOUND, 'Not Found'));
});

// convert error to ApiError, if needed
app.use(errorConverter);

// handle error
app.use(errorHandler);

module.exports = app;
34 changes: 34 additions & 0 deletions name_server/src/config/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const dotenv = require('dotenv');
const path = require('path');
const Joi = require('joi');

if (process.env.NODE_ENV !== "production") {
dotenv.config({ path: path.join(__dirname, '../../.env') });
}

const envVarsSchema = Joi.object()
.keys({
NODE_ENV: Joi.string().valid('production', 'development', 'test').required(),
PORT: Joi.number().default(3000),
MONGODB_URL: Joi.string().required().description('Mongo DB url')
})
.unknown();

const { value: envVars, error } = envVarsSchema.prefs({ errors: { label: 'key' } }).validate(process.env);

if (error) {
throw new Error(`Config validation error: ${error.message}`);
}

module.exports = {
env: envVars.NODE_ENV,
port: envVars.PORT,
mongoose: {
url: envVars.MONGODB_URL,
options: {
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
},
}
};
26 changes: 26 additions & 0 deletions name_server/src/config/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const winston = require('winston');
const config = require('./config');

const enumerateErrorFormat = winston.format((info) => {
if (info instanceof Error) {
Object.assign(info, { message: info.stack });
}
return info;
});

const logger = winston.createLogger({
level: config.env === 'development' ? 'debug' : 'info',
format: winston.format.combine(
enumerateErrorFormat(),
config.env === 'development' ? winston.format.colorize() : winston.format.uncolorize(),
winston.format.splat(),
winston.format.printf(({ level, message }) => `${level}: ${message}`)
),
transports: [
new winston.transports.Console({
stderrLevels: ['error'],
}),
],
});

module.exports = logger;
38 changes: 38 additions & 0 deletions name_server/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const mongoose = require('mongoose');
const app = require('./app');
const config = require('./config/config');
const logger = require('./config/logger');

let server;
mongoose.connect(config.mongoose.url, config.mongoose.options).then(() => {
logger.info('Connected to MongoDB');
server = app.listen(config.port, () => {
logger.info(`Listening to port ${config.port}`);
});
});

const exitHandler = () => {
if (server) {
server.close(() => {
logger.info('Server closed');
process.exit(1);
});
} else {
process.exit(1);
}
};

const unexpectedErrorHandler = (error) => {
logger.error(error);
exitHandler();
};

process.on('uncaughtException', unexpectedErrorHandler);
process.on('unhandledRejection', unexpectedErrorHandler);

process.on('SIGTERM', () => {
logger.info('SIGTERM received');
if (server) {
server.close();
}
});
39 changes: 39 additions & 0 deletions name_server/src/middlewares/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const mongoose = require('mongoose');
const httpStatus = require('http-status');
const config = require('../config/config');
const ApiError = require('../utils/ApiError');

const errorConverter = (err, req, res, next) => {
let error = err;
if (!(error instanceof ApiError)) {
const statusCode =
error.statusCode || error instanceof mongoose.Error ? httpStatus.BAD_REQUEST : httpStatus.INTERNAL_SERVER_ERROR;
const message = error.message || httpStatus[statusCode];
error = new ApiError(statusCode, message, false, err.stack);
}
next(error);
};

// eslint-disable-next-line no-unused-vars
const errorHandler = (err, req, res, next) => {
let { statusCode, message } = err;
if (config.env === 'production' && !err.isOperational) {
statusCode = httpStatus.INTERNAL_SERVER_ERROR;
message = httpStatus[httpStatus.INTERNAL_SERVER_ERROR];
}

res.locals.errorMessage = err.message;

const response = {
code: statusCode,
message,
...(config.env === 'development' && { stack: err.stack }),
};

res.status(statusCode).send(response);
};

module.exports = {
errorConverter,
errorHandler,
};
11 changes: 11 additions & 0 deletions name_server/src/middlewares/rateLimiter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const rateLimit = require('express-rate-limit');

const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 20,
skipSuccessfulRequests: true,
});

module.exports = {
authLimiter,
};
24 changes: 24 additions & 0 deletions name_server/src/models/query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const mongoose = require("mongoose");

const querySchema = new mongoose.Schema({
lat: {
type: String,
required: true,
},
lng: {
type: String,
required: true,
},
from_share_link: {
type: Boolean,
required: true,
},
query_error: {
type: Boolean,
required: false
},
timestamp: Number,
});

const Query = mongoose.model("Query", querySchema);
module.exports = Query;
Loading