Skip to content

πŸ§ͺ Proof of Concept for a RESTful API built with Node.js (TypeScript) and Express.js

License

Notifications You must be signed in to change notification settings

nanotaboada/ts-node-samples-express-restful

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

919 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

πŸ§ͺ RESTful API with Node.js and Express.js in TypeScript

Node.js CI Node.js CD CodeQL Quality Gate Status codecov CodeFactor License: MIT

Proof of Concept for a RESTful API made with Node.js LTS/Krypton (v24) and Express.js 5 in TypeScript. Manage football player data with SQLite, Sequelize ORM, Swagger documentation, and in-memory caching.

Table of Contents

Features

  • πŸ—οΈ Modern TypeScript architecture - Native ESM, strict mode, layered architecture with interface-based contracts
  • πŸ“š Interactive API exploration - Auto-generated OpenAPI docs with Swagger UI and Postman collection
  • ⚑ Performance optimizations - In-memory caching with node-cache, Sequelize ORM, and efficient SQLite operations
  • πŸ§ͺ Comprehensive integration tests - Full endpoint coverage with Jest/Supertest and automated reporting to Codecov
  • πŸ“– Token-efficient documentation - AGENTS.md + auto-loaded Copilot instructions for AI-assisted development
  • 🐳 Full containerization - Multi-stage Docker builds with Docker Compose orchestration
  • πŸ”„ Complete CI/CD pipeline - Automated linting (ESLint/Prettier), testing, Docker publishing, and GitHub releases
  • ⚽ Football-themed semantic versioning - Memorable, alphabetical release names using football terminology

Tech Stack

Category Technology
Runtime Node.js 24 (LTS/Krypton)
Language TypeScript 5.9
Module System Native ECMAScript Modules (ESM) - uses tsx for execution
Framework Express.js 5
Database SQLite3 with Sequelize ORM
Caching node-cache
Documentation Swagger (OpenAPI 3.0)
Security Helmet, CORS
Testing Jest 30 with Supertest
Containerization Docker with multi-stage builds
Code Quality ESLint, Prettier, Commitlint
Dev Tools tsx (TypeScript executor), nodemon

πŸ’‘ Note: While the repository name references ts-node (the original implementation), the project now uses tsx for faster, cleaner TypeScript execution without experimental flags.

Project Structure

src/
β”œβ”€β”€ app.ts              # Express app setup & middleware configuration
β”œβ”€β”€ server.ts           # HTTP server initialization & lifecycle
β”œβ”€β”€ controllers/        # Request handlers with Swagger annotations
β”œβ”€β”€ services/           # Business logic + caching layer
β”œβ”€β”€ database/           # Sequelize DB access (interfaces + implementations)
β”œβ”€β”€ models/             # Sequelize models (Player)
β”œβ”€β”€ routes/             # Express Router definitions
β”œβ”€β”€ docs/               # Swagger configuration & doc generation
└── middlewares/        # Custom middleware (swagger CSP)

tests/                  # Integration tests with supertest
scripts/                # Docker entrypoint & healthcheck scripts
storage/                # Pre-seeded SQLite database

Architecture

Layered architecture with dependency injection via constructors and interface-based contracts.

%%{init: {
  "theme": "default",
  "themeVariables": {
    "fontFamily": "Fira Code, Consolas, monospace",
    "textColor": "#555",
    "lineColor": "#555",
    "lineWidth": 2,
    "clusterBkg": "#f5f5f5",
    "clusterBorder": "#999"
  }
}}%%
graph BT
    subgraph API[" "]
        server[server]
        app[app]
        routes[routes]
        controllers[controllers]
        Express[Express]
    end

    subgraph Business[" "]
        services[services]
        nodeCache[node-cache]
    end

    subgraph Data[" "]
        database[database]
        models[models]
        Sequelize[Sequelize]
    end

    %% Tests (outside layers)
    tests[tests]

    %% Detailed connections within layers
    database --> services
    models --> database
    models --> services
    models --> controllers

    services --> controllers
    controllers --> routes
    routes --> app
    app --> server

    %% External Dependencies
    Sequelize --> database
    Sequelize --> models
    nodeCache --> services
    Express --> controllers
    Express --> routes
    Express --> app

    %% Tests connection
    app -.-> tests

    %% Styling
    classDef core fill:#b3d9ff,stroke:#6db1ff,stroke-width:2px,color:#555,font-family:monospace;
    classDef deps fill:#ffcccc,stroke:#ff8f8f,stroke-width:2px,color:#555,font-family:monospace;
    classDef test fill:#ccffcc,stroke:#53c45e,stroke-width:2px,color:#555,font-family:monospace;

    class server,app,routes,controllers,services,database,models core
    class Express,Sequelize,nodeCache deps
    class tests test
Loading

Simplified, conceptual project structure and main application flow. Not all dependencies are shown.

API Endpoints

Interactive API documentation is available via Swagger UI at http://localhost:9000/swagger/ when the server is running.

Quick Reference:

  • GET /players - List all players
  • GET /players/:id - Get player by ID
  • GET /players/squadNumber/:squadNumber - Get player by squad number
  • POST /players - Create new player
  • PUT /players/:id - Update player
  • DELETE /players/:id - Remove player
  • GET /health - Health check

For complete endpoint documentation with request/response schemas, explore the interactive Swagger UI. You can also access the OpenAPI JSON specification at http://localhost:9000/swagger.json.

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js (see .nvmrc for required version)
  • npm (comes with Node.js)
  • Docker and Docker Compose (optional, for containerized setup)

Quick Start

Clone the repository

git clone https://github.com/nanotaboada/ts-node-samples-express-restful.git
cd ts-node-samples-express-restful

Install dependencies

npm install

Start the development server

npm run dev

The server will start on http://localhost:9000 with the following output:

> ts-node-samples-express-restful@1.0.0 dev
> nodemon

[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts
[nodemon] starting `tsx ./src/server.ts`
πŸš€ Running at http://localhost:9000

Access the application

  • API: http://localhost:9000
  • Swagger Documentation: http://localhost:9000/swagger/
  • Health Check: http://localhost:9000/health

Testing

Run the test suite with Jest:

# Run all tests
npm test

# Run tests with coverage report
npm run coverage

# Run linter
npm run lint

# Validate commit message format
npm run lint:commit

Tests are located in the tests/ directory and use Supertest for integration testing. Coverage reports are generated for controllers, services, and routes only.

Docker

This project includes full Docker support with multi-stage builds and Docker Compose for easy deployment.

Build the Docker image

npm run docker:build
# or
docker compose build

Start the application

npm run docker:up
# or
docker compose up

πŸ’‘ Note: On first run, the container copies a pre-seeded SQLite database into a persistent volume. On subsequent runs, that volume is reused and the data is preserved.

Stop the application

npm run docker:down
# or
docker compose down

Reset the database

To remove the volume and reinitialize the database from the built-in seed file:

docker compose down -v

The containerized application runs on port 9000 and includes health checks that monitor the /health endpoint every 30 seconds.

Releases

This project uses football terminology as release names ⚽

Release Naming Convention

Releases follow the pattern: v{SEMVER}-{TERM} (e.g., v1.0.0-assist)

  • Semantic Version: Standard versioning (MAJOR.MINOR.PATCH)
  • Term Name: Alphabetically ordered codename from the football terminology list

Creating a Release

πŸ’‘ Important: Update CHANGELOG.md continuously as you work, not just before releases!

  1. Update CHANGELOG.md: Move items from [Unreleased] to new version section

  2. Create and push tag:

    git tag -a v1.1.0-bicyclekick -m "Release 1.1.0 - Bicycle-kick"
    git push origin v1.1.0-bicyclekick
  3. CD pipeline runs automatically to build and publish

See CHANGELOG.md for complete release workflow.

Pull Docker Images

Each release publishes three Docker tags:

# By semantic version (recommended for production)
docker pull ghcr.io/nanotaboada/ts-node-samples-express-restful:1.0.0

# By term name (memorable, useful for staging)
docker pull ghcr.io/nanotaboada/ts-node-samples-express-restful:assist

# Latest (development/testing only)
docker pull ghcr.io/nanotaboada/ts-node-samples-express-restful:latest

Environment Variables

Create a .env file in the root directory to customize configuration:

# Server port (default: 9000)
PORT=9000

# Database storage path (default: storage/players-sqlite3.db)
# In Docker: /storage/players-sqlite3.db
STORAGE_PATH=storage/players-sqlite3.db

Available Scripts

Script Description
npm run dev Start development server with hot reload
npm start Run compiled application from dist/
npm run build Compile TypeScript to JavaScript
npm test Run Jest tests with --detectOpenHandles flag
npm run coverage Generate test coverage report
npm run lint Run ESLint on all files
npm run lint:commit Validate last commit message format
npm run swagger:docs Generate swagger.json from JSDoc annotations
npm run docker:build Build Docker image
npm run docker:up Start Docker container
npm run docker:down Stop and remove Docker volume

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details on the code of conduct and the process for submitting pull requests.

Key guidelines:

  • Follow Conventional Commits for commit messages
  • Ensure all tests pass (npm test)
  • Run linter before committing (npm run lint)
  • Keep changes small and focused

Legal

This project is provided for educational and demonstration purposes and may be used in production environments at your discretion. All referenced trademarks, service marks, product names, company names, and logos are the property of their respective owners and are used solely for identification or illustrative purposes.