Skip to content

DVGY/tours

Repository files navigation

Table of contents

Demo

Flow of development

File setup, linting and configs

🚀 Run npx gitignore node. It creates a gitignore for node env

🚀 Install express, morgan, validator, jest and all other deps, with types

🚀 Install api extractor for auto docs

Seperate Client and Server

🚀 Make one folder for server and one for client

Implement Models, Controllers, Routes and Middlewares

🚀 Script to seed dev database

🚀 Implement Model, Routes and Controller for Users

🚀 Implement Model, Routes and Controller for Trips

🚀 Implement a class APIFeatures to filter by params Trips collections

🚀 Handle Operational Error and Programming Error centrally using AppError Class

🚀 Handle Unhandled rejections and Uncaught exceptions

🚀 Handle security using different npm packages

🚀 Implement Model, Routes and Controller for Reviews

Setup React boilerplate.

🚀 Set up login, signup for user

🚀 Show all the trips to user, filter trips, pagination (work in progess...)

🚀 User profile, change password, update password logout

🚀 Show each trip details, add maps images, reviews

DevOps

🐳 Dockerize development

🚀 Run baseline application

🚀 Dockerize tours server

🚀 Set up docker compose

🚀 Enable hot reloading by mounting in src

🐳 Dockerize production

🚀 Break out separate docker compose files

🚀 Move DB to Atlas

🚀 Update client Dockerfile to build production version

Nginx

Database Modelling

  1. https://sagarvasa.medium.com/5-ways-to-improve-mongodb-performance-130fb4734472

  2. Each Tour documents has a guide property, which stores the guides from the Users Collection (1:N).

    Embeddeing: Suppose we embedd users (who are tour guides) in the guide and If users (who are tour guides) update their data, then we need to update each Tour documents

    Child Referencing: Suppose we embedd any change in users (who are tour guides) need not to update for each tours

  3. A Tour can have many reviews (1:N)

    Embeddeing: Suppose we embedd reviews in Tour document it can grow infinitely. This might exhaust mongo bson limit

    Parent Referencing: Each review will store it tour id and user id. In this way we can save the infinite growth of review. Here Review is pointing to tours and users NOT vice versa

    How can we populate reviews in Tours collection query?:

    1. Query Review Collection each time we query Tours. Make two call on DB
    2. Virtual Populate: Stores all the reviews on Tours withour persisting on DB

Commands

https://simplernerd.com/docker-typescript-production/

docker-compose up -d build the image if does not exist ex: docker-compose -f docker-compose.server.prod.yml up -d

docker-compose down -v removing the container ex: docker-compose -f docker-compose.server.prod.yml down -v

docker-compose up -d --build rebuild the image bcz dockerfile changed

docker rm $(docker ps --filter status=exited -q) delete failed container

To run APP : docker-compose -f docker-compose.dev.yml up -d

Tours Server Docker Instruction

Learning

🔆 https://stackoverflow.com/questions/42938220/nodemon-not-restarting-after-typescript-change

🔆 CHOKIDAR_USEPOLLING=true worked for hot realoading react app

🔆 If we use mongo atlas cluster we do not need to make a seperate container for mongo. Since a container essentially stores the database locally

🔆 Class APIFeatures<T,U> tried to make it generic over Query<> and queryParams It did not work since it was failing to identify methods like find, findOne.

     const features = new APIFeatures<
       Query<ITrips[], ITrips, unknown>,
       tripsReqQuery
     >(Trips.find(), queryProps);

I changed my method and make is generic over Documents and queryParams so it is detecting methods like find,findOne.

    const features = new APIFeatures<ITrips, tripsReqQuery>(
      Trips.find(),
      queryProps
    );

🔆 Can declare extending types in @types

🔆 https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/nodemailer/nodemailer-tests.ts

🔆 Pass the DocType in mongoose.Schema<DocType> to access the schema.methods properly

🔆 Indexes can improve read performance by reducing the number of document it scans. Do not set index blindly, each index use resouces, each index is updated when collection updates, if a collection regularly updates then index would not be much beneficial. Choose to create index using access pattern of application

🔆 Nested routes: When two resources are related together like GET trip/tripid/review Then we use nested routes in express and merge params to get the id from params like app.use('/:tripId/review', reviewsRoutes) merge params will automatically make the tripId equals req.params.id. Other wise we will need a middleWare function mergeTripId app.use('/:tripId/review', mergeTripId, reviewsRoutes)

🔆 https://stackoverflow.com/questions/50369779/cookie-not-being-set-in-browser. Use proxy in react app to set the same origin or cors origin and credential policy

🔆 disptach(loginUser('email', 'password')); to dispatch an action/async action we always need to pass in dispatch. What id we can directly call our actions like loginUser('email','password'). bindActionCreator action wrapped in dispatch call

🔆 https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically

🔆 If suppose the user has ratings average 4.5, he agains slides the ratings to 3.5 and then back to 4.5. Make sure it does make any api call. If the ratingsStartValue is Equal to ratingsEndValue then only call below function

Solution 1: JSON.stringify(deps), it then uses compare by values instead of reference.

Solution 2: useRef, The problem was I was mutating the array, instead of returing new one. Discussed here forum question solution

Advice: useAPI should not care about checking previous props and next props. It should only care about calling api. So I moved all this logic to FilterTrips.tsx. Seperation of concern, so either use a different hook for this, or move logic to filter trips

Node JS Security Cheat sheet

https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html

Todo

  1. Remove password hash field from reponse
  2. Add to wishlist trip
  3. Make pagination handle N number of call
  4. Add transparent interactive icons for trip locations and calculate centroid and zoom on centroid
  5. If user send a role of admin send error back
  6. Send welcome email, password reset successful email
  7. Add trips types into sepefic and use utility func to derive types

Special Thanks

  1. Jonas Schemdattman
  2. Abhishek Panda
  3. u/Jerp
  4. Pooja Prasad

Releases

No releases published

Packages

No packages published

Languages