Visit Root Page: Messages-CRUD-RESTAPI Root page
Visit Swagger API Docs: Messages-CRUD-RESTAPI Swagger API docs
This project is a simple Node.js REST API that allows users to manage messages.
Each message is analyzed to check if it's a palindrome.
The service includes full CRUD operations:
- Create a message
- Retrieve a message
- Update a message
- Delete a message
- List all messages
Everything is built using a modular architecture. This means that the code is organized into separate modules, each responsible for a specific part of the application.
Every layer has its job - routes, controllers, services, repositories, and models.
This makes it easier to maintain and extend the codebase in the future.
- Introduction
- Features
- Architecture
- Design Patterns
- Tech Stack
- How to Run
- API Endpoints
- Testing
- CLI Tool
- CI/CD
- Deployment
- Project Structure
- Environment Variables
- Contact
- Simple REST API with full CRUD operations support
- Checks if a message is a palindrome
- MongoDB or In-memory storage (configurable)
- Uses Dependency Injection for better testability and modularity
- Full test coverage with Mocha, Chai, Sinon and Supertest
- Docker support for easy deployment and local running
- GitHub Actions for CI/CD
- Swagger documentation for API endpoints
- Deployed to Railway Cloud Provider
As mentioned earlier, the project is built using a modular architecture.
In the picture below you can see the different layers of the application and how they interact with each other.

In this section, I will explain the design patterns used:
- Dependency Injection Pattern
Instead of manually creating dependencies everywhere, the app uses thekontainer-dilibrary(see src/container.js)to manage all dependencies in one place. This makes the code easier to test and keeps everything loosely coupled. - Controller-Service-Repository Pattern
Repository's layer is a (DAL - Data Access Layer), provides an additional layer to classic Controller-Service model as following:- Controller - Handles incoming HTTP requests (e.g., from the client), and calls the relevant service.
- Service - Contains the actual business logic (like creating a message or checking if it’s a palindrome), and creates the
Messageentity. - Repository - Talks to the database. It abstracts how data is stored or retrieved, so the service doesn’t need to know which database is in use.
- Factory Pattern (via Container)
Using the container, we can easily "swap" or create different object instances depending on the environment – for example, switching between a MongoDB connection or an In-Memory database. This gives flexibility without changing core logic. - Base Class Pattern (Generic,Template methods)
The project uses base classes to promote code reuse and enforce a consistent structure across layers.
These are similar to the Template Method Pattern in design:BaseRepository: Provides shared CRUD operations (create,findAll,findById,update,delete). TheMessageRepositorysimply extends it and passes in the correctdatabaseandschema.BaseCrudService: Encapsulates common service-level logic.MessageServiceinherits it and overrides only what’s necessary (like thecreateandupdatemethods to handle Message entity logic).BaseSchema: A key abstraction for different data storage schemas.BaseControllerandBaseDatabasealso serve as a foundational layers for extension.
- Node.js
- Express.js
- MongoDB + Mongoose + In-memory storage
- Joi for validation
- Docker
- Mocha, Chai, Sinon, Supertest for testing
- Swagger for API documentation
- Dependency Injection with kontainer-di
- GitHub Actions for CI/CD
- Railway for deployment
- Node.js (v18 or higher)
- MongoDB (if using MongoDB storage)
- Docker (if using Docker)
- Git
- npm or yarn
- Postman or any other API testing tool
npm install
npm startdocker build -t <your-image-name> .
docker run -d -p <port>:<port> --env-file .env <your-image-name>for example:
docker build -t messages-api .
docker run -d -p 8080:8080 --env-file .env messages-apiOpen your browser and go to http://localhost:8080 to see the API in action.
You can also use Postman or any other API testing tool to test the endpoints.
for example:
# If you want to create a new message, use the following command:
curl -X POST http://localhost:8080/api/v1/messages -H "Content-Type: application/json" -d '{"content": "your message"}'
# To list all messages, use the following command:
curl -X GET http://localhost:8080/api/v1/messages
# To get a message by ID, use the following command:
curl -X GET http://localhost:8080/api/v1/messages/<message-id>
# To update a message, use the following command:
curl -X PUT http://localhost:8080/api/v1/messages/<message-id> -H "Content-Type: application/json" -d '{"content": "your message"}'
# To delete a message, use the following command:
curl -X DELETE http://localhost:8080/api/v1/messages/<message-id>To generate the documentation, run the following command:
npm run docs
# You can find the generated documentation in the src/docs folder.
# Open the index.html file in your browser to view the documentation for better readability and understanding.All the endpoints are documented using Swagger. You can access the documentation at http://localhost:8080/api-docs after running the server.
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
List all messages |
| GET | /:id |
Retrieve a message by ID |
| POST | / |
Create a new message |
| PUT | /:id |
Update a message |
| DELETE | /:id |
Delete a message |
Each message is an object with the following structure:
{
"id": "uuid",
"content": "string",
"isPalindrome": "boolean",
"creationTime": "date.toISOString()",
"lastUpdateTime": "date.toISOString()"
}The project includes both unit and integration tests, covering:
- Integration Tests:
- Full CRUD flow on message routes (
POST,GET,PUT,DELETE)
- Full CRUD flow on message routes (
- Unit Tests:
InMemoryDatabase: create, read, update, delete, edge casesMessage Entity: validation, update logic, palindrome detectionMessageRepository: correct interactions with the databaseMessageService: business logic and error handlingPalindrome Checker: case sensitivity, numbers, edge cases
✔ All tests are written using Mocha, Chai, Sinon, and Supertest
✔ Test runner outputs:
> npm test
41 passing ✔You can interact with the API using a CLI tool.
You can find the CLI tool in the following repository: Messages-CRUD-RestAPI CLI
There you can find the instructions on how to use it.
In short, Clone the repository:
>git clone https://github.com/GalBitton/Messages-CRUD-CLI.git
cd message-cli
npm install
# Start using the CLI tool (read the README file inside the CLI repository for more details):The project uses GitHub Actions for CI/CD. The workflow is defined in .github/workflows/ci.yml.
It runs on every push to the main branch and on every pull request.
The project is deployed on Railway Cloud Provider.
You can access the live API at Messages-CRUD-RESTAPI.
In order to deploy your own version:
- Create a new Railway project
- Connect your GitHub repository
- Set up the environment variables in Railway
- Deploy the project
Messages-CRUD-RestAPI/
├── src/
│ ├── api/
│ │ └── swagger.js # Swagger configuration (YAML loader)
│ ├── config/
│ │ └── config.js # Environment-based app configuration
│ ├── controllers/
│ │ ├── baseController.js # Base controller with shared logic
│ │ └── messageController.js # Handles message-specific requests
│ ├── docs/
│ │ ├── architecture.jpg # System architecture diagram
│ │ └── swagger.yaml # Swagger OpenAPI definition
│ ├── interfaces/
│ │ ├── baseDatabase.js # Abstract DB interface
│ │ └── baseSchema.js # Abstract schema interface
│ ├── middlewares/
│ │ └── validateMessage.js # Joi-based input validation middleware
│ ├── models/
│ │ ├── inMemoryDatabase.js # In-memory DB implementation
│ │ ├── messageEntity.js # Message domain model
│ │ ├── messageInMemorySchema.js # In-memory schema logic
│ │ ├── messageMongoSchema.js # MongoDB schema definition and logic
│ │ └── mongoDatabase.js # MongoDB connection and operations
│ ├── repositories/
│ │ ├── baseRepository.js # Generic repository operations
│ │ └── messageRepository.js # Message-specific repository logic
│ ├── routes/
│ │ └── messageRoutes.js # Message API route definitions
│ ├── services/
│ │ ├── baseCrudService.js # Base service layer
│ │ └── messageService.js # Message service logic
│ ├── utils/
│ │ ├── logger.js # Winston logger with file support
│ │ └── palindromeChecker.js # Utility to check if message is palindrome
│ ├── app.js # Express app setup
│ ├── container.js # Dependency Injection setup (kontainer-di)
│ ├── root.html # Basic root page served at '/'
│ └── server.js # App and DB bootstrapping
├── tests/
│ ├── integration/
│ │ └── messageRoutes.test.js # Integration tests for REST endpoints
│ └── unit/
│ ├── inMemoryDatabase.test.js # Unit test for in-memory DB
│ ├── messageEntity.test.js # Unit test for message entity logic
│ ├── messageRepository.test.js # Repository logic tests
│ ├── messageService.test.js # Service layer tests
│ └── palindromeChecker.test.js # Palindrome checker logic
├── .github/
│ └── workflows/
│ └── ci.yaml # GitHub Actions workflow for CI
├── Dockerfile # Docker image configuration
├── .env (ignored) # Environment variables (not committed)
├── .gitignore # Git ignored files
├── .prettierrc.json # Prettier configuration
├── LICENSE # Project license (MIT)
├── package.json # NPM dependencies and metadata
├── package-lock.json # Exact dependency versions
└── README.md # You're reading it
These variables are used to configure the application
Note: The .env file is ignored by git, so you need to create it manually. make sure you don't commit it.
Please create a .env file in the root directory with the following variables:
NODE_ENV=production
PORT=8080
ROUTE_URL=https://messages-crud.up.railway.app/
MONGODB_URI=<your-mongodb-uri>
MONGODB_COLLECTION=<your-collection-name>
LOG_LEVEL=info
LOG_CONSOLE=true
LOG_FILE=true
LOG_FILE_PATH=../../logs/
DB_SETUP=mongoDBNote: The MONGODB_URI and MONGODB_COLLECTION variables are only needed if you are using MongoDB as your database. If you are using the in-memory database, you can just configure the DB_SETUP variable to inMemoryDB.
If you have any questions or suggestions, feel free to contact me at:
Gal Bitton
Email: galbitton22@gmail.com
LinkedIn: Gal Bitton