Node JS
  • SetUp Node&NVM
  • Folder Structure
  • Setup NodeJS Project
  • Library
    • Awilix
    • Swagger
    • Express
    • Jest
      • Supertest
    • Prettier
    • Eslint & Tslint
      • Tslint & Prettier
      • Tslint Plugin Prettier
      • Config With Airbnb
    • Husky And Friends
    • Sentry
  • INFRASTRUCTURE
    • Docker
      • Docker image
      • Docker container
      • Docker Volume
      • Docker command
      • Docker Compose
      • Problem & Solution
    • SonarQube
      • How to use in Nodejs
    • NGinX
    • ดูเพิ่มเติม
  • Note
    • .env declare type
    • Learn Link
Powered by GitBook
On this page
  • repository
  • services
  • controller
  • middleware
  • routes
  • utils
  • __tests__

Folder Structure

PreviousSetUp Node&NVMNextSetup NodeJS Project

Last updated 3 years ago

Flow

|user Request==> API Gateway ==> API Service| ==> Route Folder ==> Controller Folder ==> Service Folder ==> Repository Folder ==> dcConenct | Database |

repository

ประกอบไปด้วยฟังก์ชั่นสำหรับเชื่อมต่อ database เพื่อ ดึงข้อมูล เพิ่มข้อมูล แก้ไขข้อมูล

โดยจะแยกตามประเภทของข้อมูลและ ประเภทของการดึงข้อมูล

จากรูปจะแบ่งการจัดการข้อมูลเป็น 2 ส่วน คือ jwt และ userและ แบ่งเป็น 2 ไฟล์คือ

  1. commands.ts จะมีฟังก์ชั่น เพิ่ม แก้ไข หรือลบข้อมูล เช่น เพิ่มพนักงาน, ลบพนักงาน

  2. queries.ts จะมีฟังก์ชั่น เพื่อดึงข้อมูล เช่น ดึงข้อมูลพนักงานทั้งหมด, ดึงข้อมูลพนักงานตามรหัสพนักงาน

services

เป็นส่วนของ business model จะเป็นตัวกลางระหว่าง repository กับ controller ทำหน้าที่ประมวลผลหรือ คิดคำนวณข้อมูลต่างๆตามที่ controller ร้องขอ

โดยจะแยกตามประเภทของ service เช่น - jwt ซึ่งใช้ในการจัดการเกี่ยวกับระบบ jwt - user ซึ่งใช้ในการจัดการเกี่ยวกับระบบ user

เช่น การสร้าง jwt token 1. controller จะร้องขอ jwt token ใหม่ 2. service สร้าง token ขั้นมา 3. service ส่งไป insert ผ่าน repository 4. service ส่งค่า jwt token ที่สร้างมาใหม่คืนให้ controller

controller

ไฟล์ Controller จะรับ Request จาก Routes และนำ Requrest ไปหาผลลัพธ์เพื่อส่งกลับไปเป็น HTTP Response

static Login = async (
    req: Request<any, any, LoginBodyType, IpQueryRequestType>,
    res: Response,
    next: NextFunction
  ): promiseResponseDTO<string | UserDTO> => {
    try {
      const { userId, password, org, trackingstatus } = req.body;
      if (!isLoginBodyType(req.body)) return BadRequest(res, 'bad param');
      const userData = await this.userManager.Login(org, userId, password);
      const jwtToken = await this.jwtGenerator.CreateToken(
        userData,
        req.query.ipAddress,
        trackingstatus || 'F'
      );
      this.setToken(res, jwtToken.token, jwtToken.refreshToken);
      return res.send({ ...userData, token: jwtToken.token });
    } catch (err: any) {
      return BadRequest(res, err.message);
    }
  };

middleware

ฟังก์ชั่นที่สามารถเข้าไปจัดการกับ request object (req) , response object (res) และ ฟังก์ชั่น next() ที่อยู่กระบวนการเกิดของ request-response cycle next() คือฟังก์ชั่นที่อยู่ใน express router ซึ่งเมื่อมีการเรียกใช้งาน จะเป็นการไปทำงานใน middleware ฟังก์ชั่นในลำดับถัดไป จากฟังก์ชั่นปัจจุบัน

เช่น - เรา controller ต้องการรู้ IP ที่ส่งเข้ามาแต่จะให้ตัว controller มี code ที่ดึงค่า IP จาก header มาทุกครั้งก็ ดูจะเป็นการเขียน code ที่ซ้ำกันเยอะเกิน เราลยทำ middleware เพื่อที่จะ set ip address ใส่ไว้ใน request เพื่อให้ตัว controller สามารถดึงมาใช้ได้เลย - ต้องการเช็ค ตัว request body ว่าข้อมูลที่ส่งมามีครบตามที่ต้องการหรือไม่

export const setIPAddress = (req: Request, res: Response, next: NextFunction) => {
  const ip = requestIp.getClientIp(req);
  req.query.ipAddress = ip == null ? 'Unknown' : ip;
  next();
};

export const RequireJWTtoken = (req: Request, res: Response, next: NextFunction) => {
  const token = getToken(req);
  if (!token) {
    return BadRequest(res, 'A token is required for authentication');
  }
  next();
};

routes

เก็บ router path ของ api ควรจะเป็นไฟล์ไฟล์เดียว แต่อาจจะเก็บแยกเป็น V1, V2 ของแต่ละ version ของ api ก็ได้

เป็นส่วนใช้ middleware ในการจัดการข้อมูลก่อนที่จะถึง controller ที่เราต้องการให้ทำงานเป็นตัวหลักโดยที่ถ้า middleware ตัวไหนไม่ผ่านก็จะไม่ทำ middleware ตัวต่อไป

เช่น /api/user/logout RequireJWTtoken : มี jwttoken ส่งมารึป่าว VerifyToken : token ที่ส่งมาถูกต้องมั้ย LoginController.Logout : เมื่อผ่าน middleware ข้างต้นแล้วถึงจะมา จัดการ logout

#src/index.ts
const app = express();
app.use(setIPAddress);
app.use('/', routes);

#src/routes/index.ts
const router = express.Router();
router.post('/api/user/login', LoginController.Login);
router.post('/api/user/logout', RequireJWTtoken, VerifyToken, LoginController.Logout);
router.post('/api/user/changepassword', RequireJWTtoken, VerifyToken, LoginController.Logout);
router.post('/api/user/forcepassword', RequireJWTtoken, VerifyToken, LoginController.ForcePassword);
router.post('/api/user/refresh-token', LoginController.RefreshToken);

utils

Utilities and Helpers ที่ต้องเอาไว้แชร์ Application เช่น function ที่เอาไว้ใช้คำนวณ offset ของ query ที่ใช้สำกรับการแบ่งหน้า, function ที่เอาไว้จัดการกับ response ว่า error handle มาเป็นแบบนี้ต้องส่ง status code เป็นอะไร

__tests__

จะมีโครงสร้างเหมือน src สำหรับเอาไว้ทำ unit test โดนเรื่อง unit test จะพูดถึงในหัวข้อเรื่อง jest

รูปแบบการจัดโฟลเดอร์