Node Express Typescript 2024

From Logic Wiki
Revision as of 10:44, 17 March 2024 by AliIybar (Talk | contribs) (Created page with "Category:Node.js Category:Typescript Category:Express == Setup. == terminal : <pre> npm init -y npm i --save express dotenv npm i -D typescript @types/node @type...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Setup.

terminal :

npm init -y
npm i --save express dotenv
npm i -D typescript @types/node  @types/express nodemon ts-node
npx tsc --init


tsconfig.json

"rootDir": "./src", 
"outDir": "./dist",

package.json ->

{
  "name": "logicmade_api",
  "version": "1.0.0",
  "description": "API for many things needed",
  "main": "index.js",
  "scripts": {
    "build": "npx tsc",
    "start": "node dist/index.js",
    "dev": "nodemon src/index.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/express": "^4.17.21",
    "@types/node": "^20.11.28",
    "nodemon": "^3.1.0",
    "ts-node": "^10.9.2",
    "typescript": "^5.4.2"
  },
  "dependencies": {
    "dotenv": "^16.4.5",
    "express": "^4.18.3"
  }
}

.env file

PORT=3000

./src/index.ts ->

import express, {Express, Request, Response } from "express"
import dotenv from "dotenv"

dotenv.config()

const app: Express  = express()
const port = 3000

console.log("env : ", process.env.PORT )
app.get("/", (req:Request, res:Response) => {
    res.send("OK")
})

app.listen(port, ()=> {
    console.log(`[server]: Server is running at http://localhost:${port}`)
})

Vitest

npm i -D vitest 
npm i -D @vitest/ui

package.json ->

"scripts": {
...
    "test": "vitest",
    "test:ui": "vitest --ui",
    "coverage": "vitest run --coverage"
  },

Morgan (Logging the requests)

npm i -S morgan
npm i -D @types/morgan
npm i rotating-file-stream

/src/index.ts

import morgan from "morgan"
import  { createStream } from "rotating-file-stream"
...
import Router from "./routes"
...
var accessLogStream = createStream('access.log', {
    interval: '1d', // rotate daily
    path: path.join(__dirname, '../log')
})
...
app.use(express.json());
app.use(morgan('combined', { stream: accessLogStream }));
app.use(express.static("public"));

app.use(Router);

/src/routes/index.ts

import express from "express";
import PingController from "../controllers/ping";

const router = express.Router();

router.get("/ping", async (_req, res) => {
  const controller = new PingController();
  const response = await controller.getMessage();
  return res.send(response);
});

export default router;

/src/controller/ping.ts

interface PingResponse {
    message: string;
  }
  
  export default class PingController {
    public async getMessage(): Promise<PingResponse> {
      return {
        message: "hello",
      };
    }
  }

Swagger

npm i -S tsoa swagger-ui-express
npm i -D @types/swagger-ui-express concurrently

tsconfig.json

{
  "compilerOptions": {
    ...
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

tsoa.json (create)

{
  "entryFile": "src/index.ts",
  "noImplicitAdditionalProperties": "throw-on-extras",
  "spec": {
    "outputDirectory": "public",
    "specVersion": 3
  }
}

package.json

  "nodemonConfig": {
    "watch": [
      "src"
    ],
    "ext": "ts",
    "exec": "ts-node src/index.ts"
  },
"scripts": {
    "predev": "npm run swagger",
    "prebuild": "npm run swagger",
    "build": "npx tsc",
    "start": "node dist/index.js",
    "dev": "concurrently \"nodemon\" \"nodemon -x tsoa spec\"",
    "swagger": "tsoa spec",
    ...
  },

src/index.ts

import express, { Application, Request, Response } from "express";
import morgan from "morgan";
import swaggerUi from "swagger-ui-express";

import Router from "./routes";

const PORT = process.env.PORT || 8000;

const app: Application = express();

app.use(express.json());
app.use(morgan("tiny"));
app.use(express.static("public"));

app.use(
  "/docs",
  swaggerUi.serve,
  swaggerUi.setup(undefined, {
    swaggerOptions: {
      url: "/swagger.json",
    },
  })
);

app.use(Router);

src/controllers/ping.ts

import { Get, Route } from "tsoa";

interface PingResponse {
  message: string;
}

@Route("ping")
export default class PingController {
  @Get("/")
  public async getMessage(): Promise<PingResponse> {
    return {
      message: "hello",
    };
  }
}
<pre>
After making all the changes and running the server, visit http://localhost:3000/docs/ to access the APIs documentation.