coders gyan(rest api) ---> book library(1.1)

project setup

code

mkdir elib
cd elib
code .
# initialize a node project
npm init ---> manually answer all question asked during setup
or 
npm init -y
# install typescript as Dependency(for development) --> not necessary for production
# node_module folder is created
npm i -D typescript ts-node nodemon @types/node
# initialize tsconfig file --> create tsconfig.json file
npx tsc --init
# git setup to push code
git init
#install gitignore extension
# create git ignore file (node_module) --> using extension gitignore
ctrl+shift+p --->(search .git) add gitignore --> node


git add .
git commit -m "setup typescript"
# add dev script in package.json --> to run server.ts file
"dev": "nodemon server.ts"

npm run dev
# setup eslint --> to avoid bad code practice -->create .eslintrc.json
npm i @eslint/config

how would you like to use eslint?
-> to check code syntax and find problems

what type of module your project use?
-> javascript (import/export) --> not require

which framework are you using? 
-> none

does yyour project use typescript?
-> yes

what does your code run in ?
-> node

format of config file?
-> json

requre extra pacakge for tyoescript, install them now?
-> yes

which package manager do you want to use?
-> npm

git add .
git commit -m "add eslint"

#install eslint extension --> help you to give error while coding(follow best practise)
# setup prettier for text formatting
# install prettier extension
# create .pretter.json file in root directory

{
  "tabWidth" : 2
}

crtl + , --> format on save --> checked

git add .
git commit -m "add prettier"
# setup express server
npm i express
npm i -D @types/express
// src/app.ts
import express from "express";

const app = express();

export default app;
// server.ts
import app from "./src/app";
import { config } from "./src/config/config";

const startServer = async () => {
  const port = config.port || 3000;

  app.listen(port, () => {
    console.log(`Listening on port: ${port}`);
  });
};

startServer();
git add .
git commit -m "add express"
# setup dotenv --> project config
npm i dotenv
npm i -D @types/dotenv

# create .env file on root 
PORT=5513
//  src/config/config.ts
import { config as conf } from "dotenv";
conf();

const _config = {
  port: process.env.PORT,
};

# to make it read only
export const config = Object.freeze(_config);
git add .
git commit -m "add config"
# setup mongo db
npm i mongoose
npm i -D @types/mongoose # dont req to install types seperately(inbuilt)
// src/config/db.ts
import mongoose from "mongoose";
import { config } from "./config";

const connectDB = async () => {
  try {
    // listeners to be registered 1st (1)
    mongoose.connection.on("connected", () => {
      console.log("Connected to database successfully");
    });
    // listeners to be registered 1st (2)
    // throws error on connection fail
    mongoose.connection.on("error", (err) => {
      console.log("Error in connecting to database.", err);
    });

    await mongoose.connect(config.databaseUrl as string);
  } catch (err) {
    // throws error on 1st connection fail
    console.error("Failed to connect to database.", err);
    process.exit(1);
  }
};

export default connectDB;
// server.ts
import app from "./src/app";
import { config } from "./src/config/config";
import connectDB from "./src/config/db";

const startServer = async () => {
  // Connect database
  await connectDB();

  const port = config.port || 3000;

  app.listen(port, () => {
    console.log(`Listening on port: ${port}`);
  });
};

startServer();
git add .
git commit -m "add database setup"
# setup error handling --> 
npm i http-errors
npm i -D @types/http-errors

Middleware

Request Handler
2 types: async and sync

Req : Client —> Router —> Middleware 1 (next()) —> Middleware2 (next())—> …. —> Request Handler

Res : Request Handler —> Client

if there is error in Request Handler Sync

Req : Client —> Router —> Middleware 1 (next()) —> Middleware2 (next())—> …. —> Request Handler —> Global Error Handler

Res : Global Error Handler —> Client

if there is error in Request Handler Async

Req : Client —> Router —> Middleware 1 (next()) —> Middleware2 (next())—> …. —> Request Handler (next(error)) —> Global Error Handler

Res : Global Error Handler —> Client

// src/midlewares/globalErrorHandler.ts
import { Request, Response, NextFunction } from "express";
import { HttpError } from "http-errors";
import { config } from "../config/config";

const globalErrorHandler = (
  err: HttpError, // installed package
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const statusCode = err.statusCode || 500;

  return res.status(statusCode).json({
    message: err.message,
    errorStack: config.env === "development" ? err.stack : "",//we dont want to expose errorStack on production
  });
};

export default globalErrorHandler;
// app.ts
import express, { NextFunction, Request, Response } from "express";
import globalErrorHandler from "./middlewares/globalErrorHandler";
import { config } from "./config/config";

const app = express();

// Routes
// Http methods: GET, POST, PUT, PATCH, DELETE
app.get("/", (req, res, next) => {
    res.json({ message: "Welcome to elib apis" });
});

// Global error handler
app.use(globalErrorHandler);

export default app;