New project structure

New folder structure
Changed to type:module
Moved routes to separate files
This commit is contained in:
2020-07-17 22:07:55 +02:00
parent ad8ed283d2
commit 2abec5017f
28 changed files with 1252 additions and 305 deletions

1
.env
View File

@@ -1 +1,2 @@
DB_PASS=joncio1 DB_PASS=joncio1
PORT=3000

302
app.js
View File

@@ -1,292 +1,20 @@
/* import * as config from "./config/index.js";
const { port, dbPass } = config;
import express from "express";
CONFIGS
*/
require("dotenv").config(); //require environment variables
const mongoose = require("mongoose");
const express = require("express");
const helmet = require("helmet");
const multer = require("multer");
const bcrypt = require("bcrypt");
const validators = require("./validation");
var sanitizer = require("string-sanitizer");
const app = express(); const app = express();
app.use(helmet()); import loaders from "./loaders/index.js";
const port = 3000; //
const rateLimit = require("express-rate-limit"); // Server init function
const limiter = rateLimit({ //
windowMs: 15 * 60 * 1000, //time window async function startServer() {
max: 100, //requests from a single IP for a time window await loaders({ expressApp: app, dbPass: dbPass });
}); app.listen(port, (err) => {
app.use(limiter);
const bodyParser = require("body-parser");
app.use(bodyParser.json({ limit: "100kb" })); // limit body payload size
app.use(bodyParser.urlencoded({ extended: true }));
/*
Mongoose schemas
*/
const Restaurant = require("./models/restaurant");
const Dish = require("./models/dish");
const User = require("./models/users");
/*
Image upload config (multer)
*/
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./images");
},
filename: function (req, file, cb) {
cb(
null,
new Date()
.toISOString()
.trim()
.replace(/[:_ -.]/g, "") +
Math.floor(Math.random() * 5000 + 1) +
file.mimetype.replace("/", ".")
);
},
});
const upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
if (file.mimetype !== "image/jpg") {
return cb(null, false);
}
cb(null, true);
},
limits: { fileSize: 4000000 },
}); //max file size = 4Mb
/*
Code
*/
// Connect to DB
mongoose.connect(
"mongodb+srv://menui_db_user:" +
process.env.DB_PASS +
"@menui-database.9quwf.mongodb.net/<dbname>?retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true },
(err) => {
if (err) console.log("Unable to connect :(");
else console.log("Connected To Database");
}
);
// GET RESTAURANT BY ID
app.get("/restaurant", function (req, res) {
//validate restaurant
validators.validateRestaurant(req.body.restaurantId, (result) => {
if (!result) {
res.sendStatus(400);
} else {
Restaurant.findById(req.body.restaurantId, (err, data) => {
if (err) {
res.sendStatus(404);
} else res.send(data);
});
}
});
});
// GET RESTAURANTS IN A SPECIFIED CITY
app.get("/city", function (req, res) {
Restaurant.find({ city: req.body.city }, (err, data) => {
if (err) { if (err) {
res.sendStatus(404); console.log("Server Startup Failed");
} else res.send(data); return;
});
});
// GET DISH BY ID
app.get("/dish", (req, res) => {
Dish.findById(req.body.dishId, (err, data) => {
if (err) {
res.sendStatus(404);
} else res.send(data);
});
});
// ADD NEW RESTAURANT
app.post("/restaurant", (req, res) => {
//validate user
validators.validateUser(req.body.userId, (result) => {
if (!result) res.sendStatus(401);
//create restaurant
const restaurant = new Restaurant({
_id: new mongoose.Types.ObjectId(),
name: sanitizer.sanitize.keepUnicode(req.body.name),
city: sanitizer.sanitize.keepUnicode(req.body.city),
imgUrl: req.body.imgUrl,
workingHours: req.body.workingHours,
hidden: req.body.hidden,
});
//add restaurant to DB
restaurant.save((err) => {
if (err) {
res.sendStatus(400);
} else {
res.status(201);
}
});
});
});
// ADD NEW DISH
app.post("/dish", (req, res) => {
//validate restaurant
validators.validateRestaurant(req.body.restaurantId, (result) => {
if (!result) res.sendStatus(400);
else {
//validate user
validators.validateUser(req.body.userId, (result) => {
if (!result) {
res.sendStatus(401);
} else {
//construct dish
const dish = new Dish({
_id: new mongoose.Types.ObjectId(),
name: sanitizer.sanitize.keepUnicode(req.body.dish.name),
category: req.body.dish.category,
price: req.body.dish.price,
notes: sanitizer.sanitize.keepUnicode(req.body.dish.notes),
imgUrl: req.body.dish.imgUrl,
weight: req.body.dish.weight,
allergens: {
gluten: req.body.dish.allergens.gluten,
lactose: req.body.dish.allergens.lactose,
soy: req.body.dish.allergens.soy,
eggs: req.body.dish.allergens.eggs,
seaFood: req.body.dish.allergens.seaFood,
peanuts: req.body.dish.allergens.peanuts,
sesame: req.body.dish.allergens.sesame,
},
vegan: req.body.dish.vegan,
vegetarian: req.body.dish.vegetarian,
});
//add dish to DB
dish.save((err) => {
if (err) {
res.sendStatus(400);
} else {
//add dish ID to restaurant
Restaurant.updateOne(
{ _id: req.body.restaurantId },
{ $push: { dishes: dish._id } },
(err) => {
if (err) {
res.sendStatus(400);
} else {
res.sendStatus(201);
}
}
);
}
});
}
});
} }
console.log("Server is running");
}); });
}); }
// GET ALL DISHES FROM A RESTAURANT ID (All at once) startServer();
app.get("/dishes", (req, res) => {
//validate restaurant
validators.validateRestaurant(req.body.restaurantId, (result) => {
if (!result) {
res.sendStatus(400);
} else {
//get restaurant
Restaurant.findById(req.body.restaurantId, (err, result) => {
if (err) {
res.sendStatus(404);
} else {
//prepare variables
const dishesCount = result.dishes.length;
let dishes = [];
//fetch all dishes
result.dishes.forEach((element) => {
Dish.findById(element, (err, result) => {
if (err) console.log("ERROR fetching dish");
dishes.push(result);
if (dishes.length == dishesCount) res.send(dishes);
});
});
}
});
}
});
});
// UPDATE DISH
app.put("/dish", (req, res) => {
//validate dish ID
validators.validateDishId(req.body.dishId, (result) => {
if (!result) {
res.sendStatus(204);
} else {
//validate user
validators.validateUser(req.body.userId, (result) => {
if (!result) {
res.sendStatus(401);
} else {
//replace dish in DB
Dish.replaceOne(
{ _id: req.body.dishId },
{
name: sanitizer.sanitize.keepUnicode(req.body.dish.name),
category: req.body.dish.category,
price: req.body.dish.price,
notes: sanitizer.sanitize.keepUnicode(req.body.dish.notes),
imgUrl: req.body.dish.imgUrl,
weight: req.body.dish.weight,
allergens: {
gluten: req.body.dish.allergens.gluten,
lactose: req.body.dish.allergens.lactose,
soy: req.body.dish.allergens.soy,
eggs: req.body.dish.allergens.eggs,
seaFood: req.body.dish.allergens.seaFood,
peanuts: req.body.dish.allergens.peanuts,
sesame: req.body.dish.allergens.sesame,
},
vegan: req.body.dish.vegan,
vegetarian: req.body.dish.vegetarian,
},
(err) => {
if (err) {
res.sendStatus(304);
} else {
res.sendStatus(200);
}
}
);
}
});
}
});
});
app.post("/img", upload.single("menuiImage"), (req, res) => {
res.sendStatus(201);
});
app.listen(port, () => console.log("Menui listening at: " + port));

5
config/index.js Normal file
View File

@@ -0,0 +1,5 @@
import dotenv from "dotenv";
dotenv.config();
export const port = process.env.PORT;
export const dbPass = process.env.DB_PASS;

27
loaders/express.js Normal file
View File

@@ -0,0 +1,27 @@
import bodyParser from "body-parser";
import cors from "cors";
import rateLimiter from "express-rate-limit";
import helmet from "helmet";
import routeDish from "../routes/routeDish.js";
import routeCity from "../routes/routeCity.js";
import routeRestaurant from "../routes/routeRestaurant.js";
import routeImg from "../routes/routeImg.js";
export default ({ app }) => {
const limiter = rateLimiter({
windowMs: 15 * 60 * 1000, //time window
max: 100, //requests from a single IP for a time window
});
app.use(bodyParser.json({ limit: "100kb" })); // limit JSON body payload size
app.use(bodyParser.urlencoded({ extended: true }));
app.use(helmet());
app.use(limiter);
app.use(cors());
app.use("/dish", routeDish);
app.use("/city", routeCity);
app.use("/restaurant", routeRestaurant);
app.use("/img", routeImg);
return app;
};

9
loaders/index.js Normal file
View File

@@ -0,0 +1,9 @@
import expressLoader from "./express.js";
import mongooseLoader from "./mongoose.js";
export default async ({ expressApp, dbPass }) => {
const mongoConnection = await mongooseLoader({ pass: dbPass });
console.log("Mongoose Loaded");
await expressLoader({ app: expressApp });
console.log("Express Initialized");
};

14
loaders/mongoose.js Normal file
View File

@@ -0,0 +1,14 @@
import mongoose from "mongoose";
export default async ({ pass }) => {
const connection = await mongoose.connect(
"mongodb+srv://menui_db_user:" +
pass +
"@menui-database.9quwf.mongodb.net/<dbname>?retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true },
(err) => {
if (err) console.log("Unable to connect :(");
else console.log("Connected To Database");
}
);
};

View File

@@ -1,4 +1,4 @@
const mongoose = require("mongoose"); import mongoose from "mongoose";
const dishSchema = mongoose.Schema({ const dishSchema = mongoose.Schema({
_id: mongoose.Types.ObjectId, _id: mongoose.Types.ObjectId,
@@ -39,4 +39,4 @@ const dishSchema = mongoose.Schema({
vegetarian: Boolean, vegetarian: Boolean,
}); });
module.exports = mongoose.model("Dish", dishSchema); export default mongoose.model("Dish", dishSchema);

View File

@@ -1,4 +1,4 @@
const mongoose = require("mongoose"); import mongoose from "mongoose";
const restaurantSchema = mongoose.Schema({ const restaurantSchema = mongoose.Schema({
_id: mongoose.Types.ObjectId, _id: mongoose.Types.ObjectId,
@@ -24,4 +24,4 @@ const restaurantSchema = mongoose.Schema({
dishes: [mongoose.Types.ObjectId], dishes: [mongoose.Types.ObjectId],
}); });
module.exports = mongoose.model("Restaurant", restaurantSchema); export default mongoose.model("Restaurant", restaurantSchema);

View File

@@ -1,4 +1,4 @@
const mongoose = require("mongoose"); import mongoose from "mongoose";
const userSchema = mongoose.Schema({ const userSchema = mongoose.Schema({
_id: mongoose.Types.ObjectId, _id: mongoose.Types.ObjectId,
@@ -18,4 +18,4 @@ const userSchema = mongoose.Schema({
subscriptionDue: Date, subscriptionDue: Date,
}); });
module.exports = mongoose.model("User", userSchema); export default mongoose.model("User", userSchema);

33
node_modules/cors/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,33 @@
# contributing to `cors`
CORS is a node.js package for providing a [connect](http://www.senchalabs.org/connect/)/[express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. Learn more about the project in [the README](README.md).
## The CORS Spec
[http://www.w3.org/TR/cors/](http://www.w3.org/TR/cors/)
## Pull Requests Welcome
* Include `'use strict';` in every javascript file.
* 2 space indentation.
* Please run the testing steps below before submitting.
## Testing
```bash
$ npm install
$ npm test
```
## Interactive Testing Harness
[http://node-cors-client.herokuapp.com](http://node-cors-client.herokuapp.com)
Related git repositories:
* [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
* [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
## License
[MIT License](http://www.opensource.org/licenses/mit-license.php)

58
node_modules/cors/HISTORY.md generated vendored Normal file
View File

@@ -0,0 +1,58 @@
2.8.5 / 2018-11-04
==================
* Fix setting `maxAge` option to `0`
2.8.4 / 2017-07-12
==================
* Work-around Safari bug in default pre-flight response
2.8.3 / 2017-03-29
==================
* Fix error when options delegate missing `methods` option
2.8.2 / 2017-03-28
==================
* Fix error when frozen options are passed
* Send "Vary: Origin" when using regular expressions
* Send "Vary: Access-Control-Request-Headers" when dynamic `allowedHeaders`
2.8.1 / 2016-09-08
==================
This release only changed documentation.
2.8.0 / 2016-08-23
==================
* Add `optionsSuccessStatus` option
2.7.2 / 2016-08-23
==================
* Fix error when Node.js running in strict mode
2.7.1 / 2015-05-28
==================
* Move module into expressjs organization
2.7.0 / 2015-05-28
==================
* Allow array of matching condition as `origin` option
* Allow regular expression as `origin` option
2.6.1 / 2015-05-28
==================
* Update `license` in package.json
2.6.0 / 2015-04-27
==================
* Add `preflightContinue` option
* Fix "Vary: Origin" header added for "*"

22
node_modules/cors/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Troy Goode <troygoode@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

243
node_modules/cors/README.md generated vendored Normal file
View File

@@ -0,0 +1,243 @@
# cors
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
CORS is a node.js package for providing a [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options.
**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)**
* [Installation](#installation)
* [Usage](#usage)
* [Simple Usage](#simple-usage-enable-all-cors-requests)
* [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
* [Configuring CORS](#configuring-cors)
* [Configuring CORS Asynchronously](#configuring-cors-asynchronously)
* [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
* [Configuration Options](#configuration-options)
* [Demo](#demo)
* [License](#license)
* [Author](#author)
## Installation
This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/). Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
```sh
$ npm install cors
```
## Usage
### Simple Usage (Enable *All* CORS Requests)
```javascript
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
```
### Enable CORS for a Single Route
```javascript
var express = require('express')
var cors = require('cors')
var app = express()
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
```
### Configuring CORS
```javascript
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
```
### Configuring CORS w/ Dynamic Origin
```javascript
var express = require('express')
var cors = require('cors')
var app = express()
var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
```
If you do not want to block REST tools or server-to-server requests,
add a `!origin` check in the origin function like so:
```javascript
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
```
### Enabling CORS Pre-Flight
Certain CORS requests are considered 'complex' and require an initial
`OPTIONS` request (called the "pre-flight request"). An example of a
'complex' CORS request is one that uses an HTTP verb other than
GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
pre-flighting, you must add a new OPTIONS handler for the route you want
to support:
```javascript
var express = require('express')
var cors = require('cors')
var app = express()
app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
app.del('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
```
You can also enable pre-flight across-the-board like so:
```javascript
app.options('*', cors()) // include before other routes
```
### Configuring CORS Asynchronously
```javascript
var express = require('express')
var cors = require('cors')
var app = express()
var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
} else {
corsOptions = { origin: false } // disable CORS for this request
}
callback(null, corsOptions) // callback expects two parameters: error and options
}
app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
```
## Configuration Options
* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:
- `Boolean` - set `origin` to `true` to reflect the [request origin](http://tools.ietf.org/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.
- `String` - set `origin` to a specific origin. For example if you set it to `"http://example.com"` only requests from "http://example.com" will be allowed.
- `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com".
- `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com".
- `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature `err [object], allow [bool]`) as the second.
* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`).
* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.
* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.
* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.
* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.
* `preflightContinue`: Pass the CORS preflight response to the next handler.
* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.
The default configuration is the equivalent of:
```json
{
"origin": "*",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 204
}
```
For details on the effect of each CORS header, read [this](http://www.html5rocks.com/en/tutorials/cors/) article on HTML5 Rocks.
## Demo
A demo that illustrates CORS working (and not working) using jQuery is available here: [http://node-cors-client.herokuapp.com/](http://node-cors-client.herokuapp.com/)
Code for that demo can be found here:
* Client: [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
* Server: [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
## License
[MIT License](http://www.opensource.org/licenses/mit-license.php)
## Author
[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
[downloads-image]: https://img.shields.io/npm/dm/cors.svg
[downloads-url]: https://npmjs.org/package/cors
[npm-image]: https://img.shields.io/npm/v/cors.svg
[npm-url]: https://npmjs.org/package/cors
[travis-image]: https://img.shields.io/travis/expressjs/cors/master.svg
[travis-url]: https://travis-ci.org/expressjs/cors

238
node_modules/cors/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,238 @@
(function () {
'use strict';
var assign = require('object-assign');
var vary = require('vary');
var defaults = {
origin: '*',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
preflightContinue: false,
optionsSuccessStatus: 204
};
function isString(s) {
return typeof s === 'string' || s instanceof String;
}
function isOriginAllowed(origin, allowedOrigin) {
if (Array.isArray(allowedOrigin)) {
for (var i = 0; i < allowedOrigin.length; ++i) {
if (isOriginAllowed(origin, allowedOrigin[i])) {
return true;
}
}
return false;
} else if (isString(allowedOrigin)) {
return origin === allowedOrigin;
} else if (allowedOrigin instanceof RegExp) {
return allowedOrigin.test(origin);
} else {
return !!allowedOrigin;
}
}
function configureOrigin(options, req) {
var requestOrigin = req.headers.origin,
headers = [],
isAllowed;
if (!options.origin || options.origin === '*') {
// allow any origin
headers.push([{
key: 'Access-Control-Allow-Origin',
value: '*'
}]);
} else if (isString(options.origin)) {
// fixed origin
headers.push([{
key: 'Access-Control-Allow-Origin',
value: options.origin
}]);
headers.push([{
key: 'Vary',
value: 'Origin'
}]);
} else {
isAllowed = isOriginAllowed(requestOrigin, options.origin);
// reflect origin
headers.push([{
key: 'Access-Control-Allow-Origin',
value: isAllowed ? requestOrigin : false
}]);
headers.push([{
key: 'Vary',
value: 'Origin'
}]);
}
return headers;
}
function configureMethods(options) {
var methods = options.methods;
if (methods.join) {
methods = options.methods.join(','); // .methods is an array, so turn it into a string
}
return {
key: 'Access-Control-Allow-Methods',
value: methods
};
}
function configureCredentials(options) {
if (options.credentials === true) {
return {
key: 'Access-Control-Allow-Credentials',
value: 'true'
};
}
return null;
}
function configureAllowedHeaders(options, req) {
var allowedHeaders = options.allowedHeaders || options.headers;
var headers = [];
if (!allowedHeaders) {
allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
headers.push([{
key: 'Vary',
value: 'Access-Control-Request-Headers'
}]);
} else if (allowedHeaders.join) {
allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
}
if (allowedHeaders && allowedHeaders.length) {
headers.push([{
key: 'Access-Control-Allow-Headers',
value: allowedHeaders
}]);
}
return headers;
}
function configureExposedHeaders(options) {
var headers = options.exposedHeaders;
if (!headers) {
return null;
} else if (headers.join) {
headers = headers.join(','); // .headers is an array, so turn it into a string
}
if (headers && headers.length) {
return {
key: 'Access-Control-Expose-Headers',
value: headers
};
}
return null;
}
function configureMaxAge(options) {
var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
if (maxAge && maxAge.length) {
return {
key: 'Access-Control-Max-Age',
value: maxAge
};
}
return null;
}
function applyHeaders(headers, res) {
for (var i = 0, n = headers.length; i < n; i++) {
var header = headers[i];
if (header) {
if (Array.isArray(header)) {
applyHeaders(header, res);
} else if (header.key === 'Vary' && header.value) {
vary(res, header.value);
} else if (header.value) {
res.setHeader(header.key, header.value);
}
}
}
}
function cors(options, req, res, next) {
var headers = [],
method = req.method && req.method.toUpperCase && req.method.toUpperCase();
if (method === 'OPTIONS') {
// preflight
headers.push(configureOrigin(options, req));
headers.push(configureCredentials(options, req));
headers.push(configureMethods(options, req));
headers.push(configureAllowedHeaders(options, req));
headers.push(configureMaxAge(options, req));
headers.push(configureExposedHeaders(options, req));
applyHeaders(headers, res);
if (options.preflightContinue) {
next();
} else {
// Safari (and potentially other browsers) need content-length 0,
// for 204 or they just hang waiting for a body
res.statusCode = options.optionsSuccessStatus;
res.setHeader('Content-Length', '0');
res.end();
}
} else {
// actual response
headers.push(configureOrigin(options, req));
headers.push(configureCredentials(options, req));
headers.push(configureExposedHeaders(options, req));
applyHeaders(headers, res);
next();
}
}
function middlewareWrapper(o) {
// if options are static (either via defaults or custom options passed in), wrap in a function
var optionsCallback = null;
if (typeof o === 'function') {
optionsCallback = o;
} else {
optionsCallback = function (req, cb) {
cb(null, o);
};
}
return function corsMiddleware(req, res, next) {
optionsCallback(req, function (err, options) {
if (err) {
next(err);
} else {
var corsOptions = assign({}, defaults, options);
var originCallback = null;
if (corsOptions.origin && typeof corsOptions.origin === 'function') {
originCallback = corsOptions.origin;
} else if (corsOptions.origin) {
originCallback = function (origin, cb) {
cb(null, corsOptions.origin);
};
}
if (originCallback) {
originCallback(req.headers.origin, function (err2, origin) {
if (err2 || !origin) {
next(err2);
} else {
corsOptions.origin = origin;
cors(corsOptions, req, res, next);
}
});
} else {
next();
}
}
});
};
}
// can pass either an options hash, an options delegate, or nothing
module.exports = middlewareWrapper;
}());

78
node_modules/cors/package.json generated vendored Normal file
View File

@@ -0,0 +1,78 @@
{
"_from": "cors",
"_id": "cors@2.8.5",
"_inBundle": false,
"_integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"_location": "/cors",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "cors",
"name": "cors",
"escapedName": "cors",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"_shasum": "eac11da51592dd86b9f06f6e7ac293b3df875d29",
"_spec": "cors",
"_where": "D:\\WORK\\Menui\\menui_backend",
"author": {
"name": "Troy Goode",
"email": "troygoode@gmail.com",
"url": "https://github.com/troygoode/"
},
"bugs": {
"url": "https://github.com/expressjs/cors/issues"
},
"bundleDependencies": false,
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"deprecated": false,
"description": "Node.js CORS middleware",
"devDependencies": {
"after": "0.8.2",
"eslint": "2.13.1",
"express": "4.16.3",
"mocha": "5.2.0",
"nyc": "13.1.0",
"supertest": "3.3.0"
},
"engines": {
"node": ">= 0.10"
},
"files": [
"lib/index.js",
"CONTRIBUTING.md",
"HISTORY.md",
"LICENSE",
"README.md"
],
"homepage": "https://github.com/expressjs/cors#readme",
"keywords": [
"cors",
"express",
"connect",
"middleware"
],
"license": "MIT",
"main": "./lib/index.js",
"name": "cors",
"repository": {
"type": "git",
"url": "git+https://github.com/expressjs/cors.git"
},
"scripts": {
"lint": "eslint lib test",
"test": "npm run lint && nyc --reporter=html --reporter=text mocha --require test/support/env"
},
"version": "2.8.5"
}

23
node_modules/esm/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright esm contributors
Based on reify, copyright Ben Newman <https://github.com/benjamn/reify>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

137
node_modules/esm/README.md generated vendored Normal file
View File

@@ -0,0 +1,137 @@
# esm
The brilliantly simple, babel-less, bundle-less ECMAScript module loader.
> `esm` is the worlds most advanced ECMAScript module loader.
This fast, production ready, zero dependency loader is all you need to support
ECMAScript modules in Node 6+. See the release [post](https://medium.com/web-on-the-edge/tomorrows-es-modules-today-c53d29ac448c)
and [video](https://www.youtube.com/watch?v=JcZ-FzfDq8A#t=5) for details!
Install
---
* __New projects__
Run `npm init esm` or `yarn create esm`.
:bulb: Use the `-y` flag to answer “yes” to all prompts.
* __Existing projects__
Run `npm i esm` or `yarn add esm`.
Getting started
---
There are two ways to enable `esm`.
1. Enable `esm` for packages:
Use `esm` to load the main ES module and export it as CommonJS.
__index.js__
```js
// Set options as a parameter, environment variable, or rc file.
require = require("esm")(module/*, options*/)
module.exports = require("./main.js")
```
__main.js__
```js
// ESM syntax is supported.
export {}
```
:bulb: These files are automagically created with `npm init esm` or `yarn create esm`.
2. Enable `esm` for local runs:
```shell
node -r esm main.js
```
:bulb: Omit the filename to enable `esm` in the REPL.
Features
---
:clap: By default, :100: percent CJS interoperability is enabled so you can get stuff done.<br>
:lock: `.mjs` files are limited to basic functionality without support for `esm` options.
Out of the box `esm` just works, no configuration necessary, and supports:
* Passing all applicable [test262](https://github.com/tc39/test262) compliance tests
* [`import`](https://ponyfoo.com/articles/es6-modules-in-depth#import)/[`export`](https://ponyfoo.com/articles/es6-modules-in-depth#export)
* [`import.meta`](https://github.com/tc39/proposal-import-meta)
* [Dynamic `import`](https://github.com/tc39/proposal-dynamic-import)
* [Live bindings](https://ponyfoo.com/articles/es6-modules-in-depth#bindings-not-values)
* [File URI scheme](https://en.wikipedia.org/wiki/File_URI_scheme)
* Node `stdin`, [`--eval`](https://nodejs.org/api/cli.html#cli_e_eval_script), [`--print`](https://nodejs.org/api/cli.html#cli_p_print_script) flags
* Node [`--check`](https://nodejs.org/api/cli.html#cli_c_check) flag _(Node 10+)_
Options
---
Specify options with one of the following:
* `"esm"` field in `package.json`
* CJS/ESM in an `.esmrc.js`, `.esmrc.cjs`, or `.esmrc.mjs` file
* [JSON6](https://github.com/d3x0r/json6) in an `.esmrc` or `.esmrc.json` file
* JSON6 or file path in the `ESM_OPTIONS` environment variable
* `ESM_DISABLE_CACHE` environment variable
<table><tr><td colspan=2><code>{</code><tr><td valign=top><code>"cjs":true</code><td><p>A boolean or object for toggling CJS features in ESM.<details><summary>Features</summary><table><tr><td colspan=2><code>{</code><tr><td valign=top><code>"cache":true</code><td><p>A boolean for storing ES modules in <code>require.cache</code>.<tr><td valign=top><code>"esModule":true</code><td><p>A boolean for <code>__esModule</code> interoperability.<tr><td valign=top><code>"extensions":true</code><td><p>A boolean for respecting <code>require.extensions</code> in ESM.<tr><td valign=top><code>"mutableNamespace":true</code><td><p>A boolean for mutable <a href=https://ponyfoo.com/articles/es6-modules-in-depth#import-all-the-things>namespace objects</a>.<tr><td valign=top><code>"namedExports":true</code><td><p>A boolean for <a href=https://ponyfoo.com/articles/es6-modules-in-depth#importing-named-exports>importing named exports</a> of CJS modules.<tr><td valign=top><code>"paths":true</code><td><p>A boolean for following CJS <a href=https://github.com/nodejs/node-eps/blob/master/002-es-modules.md#432-removal-of-non-local-dependencies>path rules</a> in ESM.<tr><td valign=top><code>"vars":true</code><td><p>A boolean for <code>__dirname</code>, <code>__filename</code>, and <code>require</code> in ESM.<tr><td valign=top><code>"dedefault":false</code><td><p>A boolean for requiring ES modules without the dangling <code>require().default</code>.<tr><td valign=top><code>"topLevelReturn":false</code><td><p>A boolean for top-level <code>return</code> support.<tr><td colspan=2><code>}</code></table></details><tr><td valign=top><code>"mainFields":["main"]</code><td><p>An array of fields checked when importing a package.<tr><td valign=top><code>"mode":"auto"</code><td><p>A string mode:<ul><li><code>"auto"</code> detect files with <code>import</code>, <code>import.meta</code>, <code>export</code>,<br><a href=https://github.com/tc39/proposal-modules-pragma><code>"use module"</code></a>, or <code>.mjs</code> as ESM.<li><code>"all"</code> files besides those with <code>"use script"</code> or <code>.cjs</code> are treated as ESM.<li><code>"strict"</code> to treat <strong>only</strong> <code>.mjs</code> files as ESM.</ul><tr><td valign=top><code>"await":false</code><td><p>A boolean for <a href=https://github.com/tc39/proposal-top-level-await>top-level <code>await</code></a> in modules without ESM exports. <em>(Node 10+)</em><tr><td valign=top><code>"force":false</code><td><p>A boolean to apply these options to all module loads.<tr><td valign=top><code>"wasm":false</code><td><p>A boolean for <a href=https://nodejs.org/api/globals.html#globals_webassembly>WebAssembly</a> module support. <em>(Node 8+)</em><tr><td colspan=2><code>}</code></table>
DevOpts
---
<table><tr><td colspan=2><code>{</code><tr><td valign=top><code>"cache":true</code><td><p>A boolean for toggling cache creation or a cache directory path.<tr><td valign=top><code>"sourceMap":false</code><td><p>A boolean for including inline source maps.<tr><td colspan=2><code>}</code></table>
Tips
---
### Bundling
* For bundlers like [`browserify`](http://browserify.org/)+[`esmify`](https://github.com/mattdesl/esmify),
[`parcel-bundler`](https://parceljs.org/), and [`webpack`](https://webpack.js.org/)
add a `"module"` field to `package.json` pointing to the main ES module.
```json
"main": "index.js",
"module": "main.js"
```
:bulb: This is automagically done with `npm init esm` or `yarn create esm`.
### Extensions
* Enable `esm` for [`wallaby.js`](https://wallabyjs.com/) following their
[integration example](https://wallabyjs.com/docs/integration/node.html#es-modules).
### Loading
* Load `esm` before loaders/monitors like
[`@babel/register`](https://babeljs.io/docs/en/next/babel-register.html),
[`newrelic`](https://github.com/newrelic/node-newrelic),
[`sqreen`](https://docs.sqreen.io/sqreen-for-nodejs/getting-started-2/), and
[`ts-node`](https://github.com/TypeStrong/ts-node#programmatic).
* Load `esm` for [`jasmine`](https://jasmine.github.io/) using the
[`"helpers"`](https://jasmine.github.io/setup/nodejs.html#configuration)
field in `jasmine.json`:
```json
"helpers": [
"node_modules/esm"
]
```
* Load `esm` with “node-args" options of:<br>
- [`pm2`](https://pm2.io/doc/en/runtime/reference/pm2-cli/#pm2-flags): `--node-args="-r esm"`
* Load `esm` with “require” options of
[`ava`](https://github.com/avajs/ava/blob/master/docs/recipes/es-modules.md),
[`mocha`](https://mochajs.org/#-require-module-r-module),
[`nodemon`](https://nodemon.io/),
[`nyc`](https://github.com/istanbuljs/nyc#require-additional-modules),
[`qunit`](https://github.com/qunitjs/qunit/releases/tag/2.6.0),
[`tape`](https://github.com/substack/tape#preloading-modules), and
[`webpack`](https://webpack.js.org/api/cli/#config-options).
:bulb: Builtin `require` cannot sideload `.mjs` files. However, `.js` files
can be sideloaded or `.mjs` files may be loaded with dynamic `import`.

1
node_modules/esm/esm.js generated vendored Normal file
View File

@@ -0,0 +1 @@
const e=(function(){return this||Function("return this")()})(),{apply:t,defineProperty:n}=Reflect,{freeze:r}=Object,{hasOwnProperty:l}=Object.prototype,o=Symbol.for,{type:i,versions:u}=process,{filename:a,id:s,parent:c}=module,_=x(u,"electron"),p=_&&"renderer"===i;let d="";"string"==typeof s&&s.startsWith("internal/")&&(d=q("internal/esm/loader"));const f=require("module"),{Script:m}=require("vm"),{createCachedData:y,runInNewContext:h,runInThisContext:b}=m.prototype,{sep:g}=require("path"),{readFileSync:v}=require("fs"),w=new f(s);function q(e){let t;try{const{internalBinding:n}=require("internal/bootstrap/loaders"),r=n("natives");x(r,e)&&(t=r[e])}catch(e){}return"string"==typeof t?t:""}function x(e,n){return null!=e&&t(l,e,[n])}function D(){return M(require,w,T),w.exports}function O(e,t){return D()(e,t)}function j(e,t){try{return v(e,t)}catch(e){}return null}let C,F;w.filename=a,w.parent=c;let I="",S="";""!==d?(S=d,F={__proto__:null,filename:"esm.js"}):(I=__dirname+g+"node_modules"+g+".cache"+g+"esm",C=j(I+g+".data.blob"),S=j(__dirname+g+"esm"+g+"loader.js","utf8"),null===C&&(C=void 0),null===S&&(S=""),F={__proto__:null,cachedData:C,filename:a,produceCachedData:"function"!=typeof y});const k=new m("const __global__ = this;(function (require, module, __shared__) { "+S+"\n});",F);let M,T;if(M=p?t(b,k,[{__proto__:null,filename:a}]):t(h,k,[{__proto__:null,global:e},{__proto__:null,filename:a}]),T=D(),""!==I){const{dir:e}=T.package;let t=e.get(I);if(void 0===t){let n=C;void 0===n&&(n=null),t={buffer:C,compile:new Map([["esm",{circular:0,code:null,codeWithTDZ:null,filename:null,firstAwaitOutsideFunction:null,firstReturnOutsideFunction:null,mtime:-1,scriptData:n,sourceType:1,transforms:0,yieldIndex:-1}]]),meta:new Map},e.set(I,t)}const{pendingScripts:n}=T;let r=n.get(I);void 0===r&&(r=new Map,n.set(I,r)),r.set("esm",k)}n(O,T.symbol.package,{__proto__:null,value:!0}),n(O,T.customInspectKey,{__proto__:null,value:()=>"esm enabled"}),n(O,o("esm:package"),{__proto__:null,value:!0}),r(O),module.exports=O;

1
node_modules/esm/esm/loader.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
node_modules/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
"use strict";module.exports=require("./esm.js");

71
node_modules/esm/package.json generated vendored Normal file
View File

@@ -0,0 +1,71 @@
{
"_from": "esm",
"_id": "esm@3.2.25",
"_inBundle": false,
"_integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
"_location": "/esm",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "esm",
"name": "esm",
"escapedName": "esm",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
"_shasum": "342c18c29d56157688ba5ce31f8431fbb795cc10",
"_spec": "esm",
"_where": "D:\\WORK\\Menui\\menui_backend",
"author": {
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com"
},
"bugs": {
"url": "https://github.com/standard-things/esm/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Tomorrow's ECMAScript modules today!",
"engines": {
"node": ">=6"
},
"files": [
"index.js",
"esm.js",
"esm/loader.js"
],
"homepage": "https://github.com/standard-things/esm#readme",
"husky": {
"hooks": {
"precommit": "npm run lint"
}
},
"keywords": [
"commonjs",
"ecmascript",
"export",
"import",
"modules",
"node",
"require"
],
"license": "MIT",
"main": "esm.js",
"name": "esm",
"repository": {
"type": "git",
"url": "git+https://github.com/standard-things/esm.git"
},
"runkitExample": "require = require(\"esm\")(module)\nrequire(\"lodash-es\")",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "3.2.25"
}

14
package-lock.json generated
View File

@@ -531,6 +531,15 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
}, },
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"crypto-random-string": { "crypto-random-string": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
@@ -703,6 +712,11 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
}, },
"esm": {
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
},
"etag": { "etag": {
"version": "1.8.1", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",

View File

@@ -7,13 +7,16 @@
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"keywords": [], "keywords": [],
"type": "module",
"author": "Jonasz Bigda", "author": "Jonasz Bigda",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"bcrypt": "^5.0.0", "bcrypt": "^5.0.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"esm": "^3.2.25",
"express": "^4.17.1", "express": "^4.17.1",
"express-rate-limit": "^5.1.3", "express-rate-limit": "^5.1.3",
"gitignore": "^0.6.0", "gitignore": "^0.6.0",

14
routes/routeCity.js Normal file
View File

@@ -0,0 +1,14 @@
import express from "express";
import Restaurant from "../models/restaurant.js";
var router = express.Router();
router.get("/", (req, res) => {
Restaurant.find({ city: req.body.city }, (err, data) => {
if (err) {
res.sendStatus(404);
} else res.send(data);
});
});
export default router;

119
routes/routeDish.js Normal file
View File

@@ -0,0 +1,119 @@
import express from "express";
import Restaurant from "../models/restaurant.js";
import Dish from "../models/dish.js";
import sanitizer from "string-sanitizer";
var router = express.Router();
router.get("/", (req, res) => {
Dish.findById(req.body.dishId, (err, data) => {
if (err) {
res.sendStatus(404);
} else res.send(data);
});
});
router.post("/", (req, res) => {
//validate restaurant
validators.validateRestaurant(req.body.restaurantId, (result) => {
if (!result) res.sendStatus(400);
else {
//validate user
validators.validateUser(req.body.userId, (result) => {
if (!result) {
res.sendStatus(401);
} else {
//construct dish
const dish = new Dish({
_id: new mongoose.Types.ObjectId(),
name: sanitizer.sanitize.keepUnicode(req.body.dish.name),
category: req.body.dish.category,
price: req.body.dish.price,
notes: sanitizer.sanitize.keepUnicode(req.body.dish.notes),
imgUrl: req.body.dish.imgUrl,
weight: req.body.dish.weight,
allergens: {
gluten: req.body.dish.allergens.gluten,
lactose: req.body.dish.allergens.lactose,
soy: req.body.dish.allergens.soy,
eggs: req.body.dish.allergens.eggs,
seaFood: req.body.dish.allergens.seaFood,
peanuts: req.body.dish.allergens.peanuts,
sesame: req.body.dish.allergens.sesame,
},
vegan: req.body.dish.vegan,
vegetarian: req.body.dish.vegetarian,
});
//add dish to DB
dish.save((err) => {
if (err) {
res.sendStatus(400);
} else {
//add dish ID to restaurant
Restaurant.updateOne(
{ _id: req.body.restaurantId },
{ $push: { dishes: dish._id } },
(err) => {
if (err) {
res.sendStatus(400);
} else {
res.sendStatus(201);
}
}
);
}
});
}
});
}
});
});
router.put("/", (req, res) => {
//validate dish ID
validators.validateDishId(req.body.dishId, (result) => {
if (!result) {
res.sendStatus(204);
} else {
//validate user
validators.validateUser(req.body.userId, (result) => {
if (!result) {
res.sendStatus(401);
} else {
//replace dish in DB
Dish.replaceOne(
{ _id: req.body.dishId },
{
name: sanitizer.sanitize.keepUnicode(req.body.dish.name),
category: req.body.dish.category,
price: req.body.dish.price,
notes: sanitizer.sanitize.keepUnicode(req.body.dish.notes),
imgUrl: req.body.dish.imgUrl,
weight: req.body.dish.weight,
allergens: {
gluten: req.body.dish.allergens.gluten,
lactose: req.body.dish.allergens.lactose,
soy: req.body.dish.allergens.soy,
eggs: req.body.dish.allergens.eggs,
seaFood: req.body.dish.allergens.seaFood,
peanuts: req.body.dish.allergens.peanuts,
sesame: req.body.dish.allergens.sesame,
},
vegan: req.body.dish.vegan,
vegetarian: req.body.dish.vegetarian,
},
(err) => {
if (err) {
res.sendStatus(304);
} else {
res.sendStatus(200);
}
}
);
}
});
}
});
});
export default router;

35
routes/routeImg.js Normal file
View File

@@ -0,0 +1,35 @@
import express from "express";
import multer from "multer";
var router = express.Router();
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./images");
},
filename: function (req, file, cb) {
cb(
null,
new Date() //Date.now().toString
.toISOString()
.trim()
.replace(/[:_ -.]/g, "") +
Math.floor(Math.random() * 5000 + 1) +
file.mimetype.replace("/", ".")
);
},
});
const upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
if (file.mimetype !== "image/jpg") {
return cb(null, false);
}
cb(null, true);
},
limits: { fileSize: 4000000 },
}); //max file size = 4Mb
router.post("/", upload.single("menuiImage"), (req, res) => {
res.sendStatus(201);
});
export default router;

76
routes/routeRestaurant.js Normal file
View File

@@ -0,0 +1,76 @@
import express from "express";
import * as validators from "../services/validation.js";
import Restaurant from "../models/restaurant.js";
import Dish from "../models/dish.js";
import User from "../models/users.js";
import sanitizer from "string-sanitizer";
var router = express.Router();
router.get("/", (req, res) => {
validators.validateRestaurant(req.body.restaurantId, (result) => {
if (!result) {
res.sendStatus(400);
} else {
Restaurant.findById(req.body.restaurantId, (err, data) => {
if (err) {
res.sendStatus(404);
} else res.send(data);
});
}
});
});
router.post("/", (req, res) => {
//validate user
validators.validateUser(req.body.userId, (result) => {
if (!result) res.sendStatus(401);
//create restaurant
const restaurant = new Restaurant({
_id: new mongoose.Types.ObjectId(),
name: sanitizer.sanitize.keepUnicode(req.body.name),
city: sanitizer.sanitize.keepUnicode(req.body.city),
imgUrl: req.body.imgUrl,
workingHours: req.body.workingHours,
hidden: req.body.hidden,
});
//add restaurant to DB
restaurant.save((err) => {
if (err) {
res.sendStatus(400);
} else {
res.status(201);
}
});
});
});
router.get("/dishes", (req, res) => {
//validate restaurant
validators.validateRestaurant(req.body.restaurantId, (result) => {
if (!result) {
res.sendStatus(400);
} else {
//get restaurant
Restaurant.findById(req.body.restaurantId, (err, result) => {
if (err) {
res.sendStatus(404);
} else {
//prepare variables
const dishesCount = result.dishes.length;
let dishes = [];
//fetch all dishes
result.dishes.forEach((element) => {
Dish.findById(element, (err, result) => {
if (err) console.log("ERROR fetching dish");
dishes.push(result);
if (dishes.length == dishesCount) res.send(dishes);
});
});
}
});
}
});
});
export default router;

View File

@@ -1,9 +1,9 @@
const Restaurant = require("./models/restaurant"); import Restaurant from "../models/restaurant.js";
const Dish = require("./models/dish"); import Dish from "../models/dish.js";
const User = require("./models/users"); import User from "../models/users.js";
const mongoose = require("mongoose"); import mongoose from "mongoose";
function validateRestaurant(id, callback) { export function validateRestaurant(id, callback) {
if (mongoose.Types.ObjectId.isValid(id)) { if (mongoose.Types.ObjectId.isValid(id)) {
Restaurant.exists({ _id: id }, (err, res) => { Restaurant.exists({ _id: id }, (err, res) => {
if (err) { if (err) {
@@ -15,11 +15,11 @@ function validateRestaurant(id, callback) {
} else callback(false); } else callback(false);
} }
function validateUser(id, callback) { export function validateUser(id, callback) {
callback(true); callback(true);
} }
function validateDishId(id, callback) { export function validateDishId(id, callback) {
if (mongoose.Types.ObjectId.isValid(id)) { if (mongoose.Types.ObjectId.isValid(id)) {
Dish.exists({ _id: id }, (err, res) => { Dish.exists({ _id: id }, (err, res) => {
if (err) { if (err) {
@@ -30,7 +30,3 @@ function validateDishId(id, callback) {
}); });
} else callback(false); } else callback(false);
} }
exports.validateRestaurant = validateRestaurant;
exports.validateUser = validateUser;
exports.validateDishId = validateDishId;