Node.js Backend Architecture TypeScript

repository·main·Indexed 25 days ago

https://github.com/afteracademy/nodejs-backend-architecture-typescript

A production-ready Node.js backend architecture built with TypeScript and Express.js, featuring a custom 3RE (Router, RouteHandler, ResponseHandler, ErrorHandler) architecture designed for high-scale platforms. The project includes integrated support for MongoDB and Redis, JWT-based authentication, and a modular directory structure for maintainability and testability.

Tokens
7.1K
Snippets
13
Records
47
Agent score
85%

What's inside nodejs-backend-architecture-typescript

  1. Overview of the 3RE Architecture

    main

    The project implements a custom architecture called 3RE, designed for maintainability and testability. The architecture consists of four primary layers for handling requests:

    1. Router: Handles incoming request routing.
    2. RouteHandler: Contains the logic for specific routes.
    3. ResponseHandler: Manages the standardized API response format.
    4. ErrorHandler: Provides centralized error handling across the application.
  2. Run the project on a local machine

    main

    To run the project without Docker, you must have Node.js and npm installed.

    1. Configure host settings in .env and .env.test:
      • DB_HOST=localhost
      • REDIS_HOST=localhost
    2. Install dependencies:
      npm install
    3. Run the application:
      • Production mode: npm start
      • Watch mode (for development): npm run watch
    4. Run tests:
      npm test

    To stop the application and tester containers if previously running via Docker:

    docker compose stop tester
    docker compose stop app
    # From the root of the project executes
    $ npm install
    
    # production mode
    $ npm start
    
    # watch mode
    $ npm run watch
    
    # unit and integration tests
    $ npm test
  3. Install and run the project using Docker Compose

    main

    The fastest way to get the project running is using Docker Compose, which sets up the application and its dependencies (MongoDB, Redis) automatically.

    1. Clone the repository:
      git clone https://github.com/afteracademy/nodejs-backend-architecture-typescript.git
    2. Start the containers:
      docker-compose up --build
    3. Access the API at http://localhost:3000.

    To run tests within the Docker environment:

    docker exec -t blogs-tester npm run test

    Troubleshooting Port Conflicts: If the application fails to start, ensure the following ports are not occupied. If they are, update the corresponding variables in the .env file:

    • PORT (default 3000)
    • DB_PORT (default 27017)
    • REDIS_PORT (default 6379)
    # clone repository recursively
    git clone https://github.com/afteracademy/nodejs-backend-architecture-typescript.git
    
    # install and start docker containers
    docker-compose up --build
    
    # Run Tests
    docker exec -t blogs-tester npm run test
  4. Get Private User Profile

    main

    Retrieve the authenticated user's profile information using the GET /profile/my endpoint. This request requires an x-api-key and a Bearer token in the Authorization header (obtained from a previous signup or login).

    GET /profile/my HTTP/1.1
    Host: localhost:3000
    x-api-key: GCMUDiuY5a7WvyUNt9n3QztToSHzK7Uj
    Content-Type: application/json
    Authorization: Bearer <your_token_received_from_signup_or_login>
  5. Perform Basic Signup

    main

    Register a new user using the POST /signup/basic endpoint. This requires an x-api-key in the headers and a JSON body containing user details. A successful signup returns a 200 status code with the user object and authentication tokens.

    POST /signup/basic HTTP/1.1
    Host: localhost:3000
    x-api-key: GCMUDiuY5a7WvyUNt9n3QztToSHzK7Uj
    Content-Type: application/json
    
    {
        "name" : "Janishar Ali",
        "email": "ali@github.com",
        "password": "changeit",
        "profilePicUrl": "https://avatars1.githubusercontent.com/u/11065002?s=460&u=1e8e42bda7e6f579a2b216767b2ed986619bbf78&v=4"
    }
  6. Configure the application services with Docker Compose

    main

    The project uses Docker Compose to orchestrate the blogging platform services. The primary services are app (the Node.js backend), tester (for running tests), mongo (database), and redis (cache).

    Key configuration details:

    • App Service: Built using Dockerfile. It maps the host port defined by ${PORT} to container port 3000. It depends on mongo and redis being healthy.
    • Tester Service: Built using Dockerfile.test. It uses .env.test for environment variables and depends on mongo and redis being healthy.
    • Mongo Service: Uses mongo:8.3.2. It maps ${DB_PORT} to 27017. It uses a volume dbdata for persistence and initializes using ./addons/init-mongo.js.
    • Redis Service: Uses redis:8.8.0. It maps ${REDIS_PORT} to 6379 and requires ${REDIS_PASSWORD} for authentication.
    services:
      app:
        build:
          context: .
          dockerfile: Dockerfile
        container_name: blogs-app
        restart: unless-stopped
        env_file: .env
        ports:
          - '${PORT}:3000'
        depends_on:
          mongo:
            condition: service_healthy
          redis:
            condition: service_healthy
    
      mongo:
        image: mongo:8.3.2
        ports:
          - '${DB_PORT}:27017'
        volumes:
          - ./addons/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
          - dbdata:/data/db
    
      redis:
        image: redis:8.8.0
        ports:
          - '${REDIS_PORT}:6379'
  7. Configure MongoDB persistence and initialization

    main

    To ensure data persistence and automatic database setup, the MongoDB service uses the following configurations:

    1. Initialization: The file ./addons/init-mongo.js is mounted to /docker-entrypoint-initdb.d/init-mongo.js inside the container. This script runs upon the first creation of the container.
    2. Persistence: A named volume dbdata is used to store data in /data/db, ensuring data survives container removal.
    mongo:
      image: mongo:8.3.2
      volumes:
        - ./addons/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
        - dbdata:/data/db
    
    volumes:
      dbdata:
  8. Reference: Signup API Request and Response Formats

    main

    Details for the POST /signup/basic endpoint.

    Request Body Schema:

    • name: string
    • email: string
    • password: string
    • profilePicUrl: string

    Success Response (200): Returns statusCode: "10000", a success message, and a data object containing the user (with _id, name, roles, and profilePicUrl) and tokens (accessToken and refreshToken).

    Error Response (400): Returns statusCode: "10001" and message "Bad Parameters".

    // Success Response (200)
    {
      "statusCode": "10000",
      "message": "Signup Successful",
      "data": {
        "user": {
          "_id": "63a19e5ba2730d1599d46c0b",
          "name": "Janishar Ali",
          "roles": [
             {
               "_id": "63a197b39e07f859826e6626",
               "code": "LEARNER",
               "status": true
             }
            ],
          "profilePicUrl": "https://avatars1.githubusercontent.com/u/11065002?s=460&u=1e8e42bda7e6f579a2b216767b2ed986619bbf78&v=4"
        },
        "tokens": {
          "accessToken": "some_token",
          "refreshToken": "some_token"
        }
      }
    }
    
    // Error Response (400)
    {
      "statusCode": "10001",
      "message": "Bad Parameters"
    }
  9. Project Directory Structure Reference

    main

    The project follows a modular structure organized by feature and layer:

    • src/auth: Authentication and authorization logic.
    • src/cache: Redis-based caching implementation.
    • src/core: Core utilities including ApiError, ApiResponse, JWT, and Logger.
    • src/database/model: Mongoose models (e.g., User, Blog, Role).
    • src/database/repository: Data access layer (Repositories) for interacting with models.
    • src/helpers: Shared utilities like asyncHandler, validator, and permission helpers.
    • src/routes: API route definitions grouped by feature (e.g., access, blog, blogs, profile).
    • tests: Comprehensive unit and integration tests mirroring the src structure.
    ├── src
    │   ├── auth
    │   ├── core
    │   ├── cache
    │   ├── database
    │   │   ├── model
    │   │   └── repository
    │   ├── helpers
    │   ├── routes
    │   └── types
    ├── tests
  10. Reference: Profile API Response Format

    main

    Details for the GET /profile/my endpoint.

    Success Response (200): Returns statusCode: "10000", a success message, and a data object containing the user's name, profilePicUrl, and an array of roles (each containing an _id and a code).

    {
      "statusCode": "10000",
      "message": "success",
      "data": {
        "name": "Janishar Ali Anwar",
        "profilePicUrl": "https://avatars1.githubusercontent.com/u/11065002?s=460&u=1e8e42bda7e6f579a2b216767b2ed986619bbf78&v=4",
        "roles": [
          {
            "_id": "5e7b8acad7aded2407e078d7",
            "code": "LEARNER"
          },
          {
            "_id": "5e7b8c22d347fc2407c564a6",
            "code": "WRITER"
          },
          {
            "_id": "5e7b8c2ad347fc2407c564a7",
            "code": "EDITOR"
          }
        ]
      }
    }