{"name":"backend","version":"1.0.0","description":"","main":"index.js","type":"module",// allows use to import statements from es6"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":[],"author":"","license":"ISC","dependencies":{"body-parser":"^1.19.0","bson":"^4.2.2","cors":"^2.8.5","dotenv":"^8.2.0","express":"^4.17.1","mongodb":"^3.6.4"}}
importexpressfrom"express"importcorsfrom"cors"importrestaurantsfrom"./api/restaurants.route.js"constapp=express()app.use(cors())app.use(express.json())// allow server to accept & read json in requests// default routeapp.use("/api/v1/restaurants",restaurants)// fallback routeapp.use("*",(req,res)=>res.status(404).json({error:"not found"}))// export the app as a module,// so that it can be imported in another file that accesses the databaseexportdefaultapp
dotenv.config()constMongoClient=mongodb.MongoClientconstport=process.env.PORT||8000MongoClient.connect(process.env.RESTREVIEWS_DB_URI,// connect to database{poolSize:50,wtimeout:2500,useNewUrlParse:true}).catch(err=>{// check for errorconsole.error(err.stack)process.exit(1)}).then(asyncclient=>{// start webserverawaitRestaurantsDAO.injectDB(client)awaitReviewsDAO.injectDB(client)app.listen(port,()=>{console.log(`listening on port ${port}`)})}))
importReviewsDAOfrom"../dao/reviewsDAO.js"exportdefaultclassReviewsController{staticasyncapiPostReview(req,res,next){try{constrestaurantId=req.body.restaurant_idconstreview=req.body.textconstuserInfo={name:req.body.name,_id:req.body.user_id}constdate=newDate()constReviewResponse=awaitReviewsDAO.addReview(restaurantId,userInfo,review,date,)res.json({status:"success"})}catch(e){res.status(500).json({error:e.message})}}staticasyncapiUpdateReview(req,res,next){try{constreviewId=req.body.review_idconsttext=req.body.textconstdate=newDate()constreviewResponse=awaitReviewsDAO.updateReview(reviewId,req.body.user_id,text,date,)var{error}=reviewResponseif(error){res.status(400).json({error})}if(reviewResponse.modifiedCount===0){thrownewError("unable to update review - user may not be original poster",)}res.json({status:"success"})}catch(e){res.status(500).json({error:e.message})}}staticasyncapiDeleteReview(req,res,next){try{constreviewId=req.query.idconstuserId=req.body.user_idconsole.log(reviewId)constreviewResponse=awaitReviewsDAO.deleteReview(reviewId,userId,)res.json({status:"success"})}catch(e){res.status(500).json({error:e.message})}}}
importmongodbfrom"mongodb"constObjectId=mongodb.ObjectIDletrestaurantsexportdefaultclassRestaurantsDAO{staticasyncinjectDB(conn){if(restaurants){return}try{restaurants=awaitconn.db(process.env.RESTREVIEWS_NS).collection("restaurants")}catch(e){console.error(`Unable to establish a collection handle in restaurantsDAO: ${e}`,)}}staticasyncgetRestaurants({filters=null,page=0,restaurantsPerPage=20,}={}){letqueryif(filters){if("name"infilters){query={$text:{$search:filters["name"]}}// $text needs to be configured in mongodb}elseif("cuisine"infilters){query={"cuisine":{$eq:filters["cuisine"]}}}elseif("zipcode"infilters){query={"address.zipcode":{$eq:filters["zipcode"]}}}}letcursortry{cursor=awaitrestaurants.find(query)}catch(e){console.error(`Unable to issue find command, ${e}`)return{restaurantsList:[],totalNumRestaurants:0}}constdisplayCursor=cursor.limit(restaurantsPerPage).skip(restaurantsPerPage*page)try{constrestaurantsList=awaitdisplayCursor.toArray()consttotalNumRestaurants=awaitrestaurants.countDocuments(query)return{restaurantsList,totalNumRestaurants}}catch(e){console.error(`Unable to convert cursor to array or problem counting documents, ${e}`,)return{restaurantsList:[],totalNumRestaurants:0}}}staticasyncgetRestaurantByID(id){try{constpipeline=[{$match:{_id:newObjectId(id),},},{$lookup:{from:"reviews",let:{id:"$_id",},pipeline:[{$match:{$expr:{$eq:["$restaurant_id","$$id"],},},},{$sort:{date:-1,},},],as:"reviews",},},{$addFields:{reviews:"$reviews",},},]returnawaitrestaurants.aggregate(pipeline).next()}catch(e){console.error(`Something went wrong in getRestaurantByID: ${e}`)throwe}}staticasyncgetCuisines(){letcuisines=[]try{cuisines=awaitrestaurants.distinct("cuisine")returncuisines}catch(e){console.error(`Unable to get cuisines, ${e}`)returncuisines}}}
importmongodbfrom"mongodb"constObjectId=mongodb.ObjectIDletreviewsexportdefaultclassReviewsDAO{staticasyncinjectDB(conn){if(reviews){return}try{reviews=awaitconn.db(process.env.RESTREVIEWS_NS).collection("reviews")}catch(e){console.error(`Unable to establish collection handles in userDAO: ${e}`)}}staticasyncaddReview(restaurantId,user,review,date){try{constreviewDoc={name:user.name,user_id:user._id,date:date,text:review,restaurant_id:ObjectId(restaurantId),}returnawaitreviews.insertOne(reviewDoc)}catch(e){console.error(`Unable to post review: ${e}`)return{error:e}}}staticasyncupdateReview(reviewId,userId,text,date){try{constupdateResponse=awaitreviews.updateOne({user_id:userId,_id:ObjectId(reviewId)},{$set:{text:text,date:date}},)returnupdateResponse}catch(e){console.error(`Unable to update review: ${e}`)return{error:e}}}staticasyncdeleteReview(reviewId,userId){try{constdeleteResponse=awaitreviews.deleteOne({_id:ObjectId(reviewId),user_id:userId,})returndeleteResponse}catch(e){console.error(`Unable to delete review: ${e}`)return{error:e}}}}