https://github.com/luizcurti/redis_postgres_node
This project demonstrates a simple integration between Node.js, Redis, and PostgreSQL to perform basic operations such as user creation, login authentication, and storing user data in Redis for fast access.
https://github.com/luizcurti/redis_postgres_node
jwt nodejs postgresql redis typescript
Last synced: 3 months ago
JSON representation
This project demonstrates a simple integration between Node.js, Redis, and PostgreSQL to perform basic operations such as user creation, login authentication, and storing user data in Redis for fast access.
- Host: GitHub
- URL: https://github.com/luizcurti/redis_postgres_node
- Owner: luizcurti
- Created: 2025-04-30T14:30:09.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-10-05T20:06:58.000Z (9 months ago)
- Last Synced: 2025-10-05T21:26:29.132Z (9 months ago)
- Topics: jwt, nodejs, postgresql, redis, typescript
- Language: TypeScript
- Homepage:
- Size: 97.7 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Node.js + Redis + PostgreSQL REST API
A REST API built with Node.js, Express, PostgreSQL, and Redis that handles user registration, authentication with JWT, and Redis-based profile caching.
---
## Tech Stack
| Layer | Technology |
|---|---|
| Runtime | Node.js 20 + TypeScript |
| Framework | Express 4 |
| Database | PostgreSQL 15 (persistent storage) |
| Cache | Redis 7 (session cache via ioredis) |
| Auth | JWT (jsonwebtoken) |
| Passwords | bcryptjs |
| Testing | Jest + ts-jest + Supertest |
| Containers | Docker + Docker Compose |
---
## Architecture Overview
```
Client
│
▼
Express Router
│
├── POST /users → CreateUserController → PostgreSQL (INSERT)
├── POST /login → LoginUserController → PostgreSQL (SELECT) + Redis (SET)
└── GET /users/profile/:id → auth middleware → GetUserInfoController → Redis (GET)
```
After a successful login, the user's data is stored in Redis with a 1-hour TTL (`user-{id}`).
`GET /users/profile/:id` reads exclusively from the Redis cache — no database round-trip.
---
## API Endpoints
### `POST /users` — Create a new user
**Request body:**
```json
{
"name": "newname",
"username": "newuser",
"email": "newuser@example.com",
"password": "newpassword"
}
```
**Responses:**
| Status | Body |
|---|---|
| `201 Created` | `{ "message": "User created successfully", "userId": "" }` |
| `400 Bad Request` | `{ "error": "Missing required fields." }` |
| `409 Conflict` | `{ "error": "Username already taken." }` |
| `500 Internal Server Error` | `{ "error": "Internal server error" }` |
---
### `POST /login` — Authenticate a user
**Request body:**
```json
{
"username": "newuser",
"password": "newpassword"
}
```
**Responses:**
| Status | Body |
|---|---|
| `200 OK` | `{ "message": "Login successful", "token": "", "user": { "id", "name", "username", "email" } }` |
| `400 Bad Request` | `{ "error": "Username and password are required." }` |
| `401 Unauthorized` | `{ "error": "Invalid credentials." }` |
| `500 Internal Server Error` | `{ "error": "Internal server error." }` |
---
### `GET /users/profile/:id` — Get user profile (requires JWT)
**Header:**
```
Authorization: Bearer
```
**Responses:**
| Status | Body |
|---|---|
| `200 OK` | `{ "id", "name", "username", "email" }` |
| `401 Unauthorized` | `{ "error": "Token missing" }` or `{ "error": "Invalid token" }` |
| `404 Not Found` | `{ "error": "User not found in cache." }` *(session expired or user never logged in)* |
| `500 Internal Server Error` | `{ "error": "Internal server error." }` |
> **Note:** This endpoint reads from Redis only. The cache is populated on login and expires after 1 hour. A 404 means the user needs to log in again.
---
## Getting Started
### Prerequisites
- [Docker](https://www.docker.com/) and Docker Compose
- Node.js 20+ (for local development without Docker)
### 1. Clone the repository
```bash
git clone https://github.com/luizcurti/redis-nodis-pg.git
cd redis-nodis-pg
```
### 2. Configure environment variables
Create a `.env` file in the project root:
```env
# Application
PORT=3000
JWT_SECRET=your_jwt_secret_key
# PostgreSQL
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_DB=mydb
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
```
> When running via Docker Compose, `POSTGRES_HOST` should be `postgres` and `REDIS_HOST` should be `redis` (the service names defined in `docker-compose.yml`).
### 3. Start with Docker Compose
```bash
docker-compose up
```
This starts:
- **PostgreSQL** on port `5432` (creates the `users` table automatically via `database.sql`)
- **Redis** on port `6379`
- **Node.js app** on port `3000`
### 4. Start locally (without Docker)
Make sure PostgreSQL and Redis are running, then:
```bash
npm install
npm run dev
```
---
## Database Schema
```sql
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY,
name TEXT NOT NULL,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
```
---
## Available Scripts
| Script | Description |
|---|---|
| `npm run dev` | Start development server with hot reload (tsx watch) |
| `npm start` | Start production server (tsx) |
| `npm run build` | Compile TypeScript to JavaScript |
| `npm test` | Run all tests |
| `npm run coverage` | Run tests with coverage report |
| `npm run lint` | Run ESLint |
| `npm run lint:fix` | Run ESLint with automatic fixes |
| `npm run format` | Format code with Prettier |
| `npm run format:check` | Check if code is properly formatted |
---
## Running Tests
```bash
npm test
```
The test suite uses Jest with mocked PostgreSQL, Redis, bcrypt, and JWT dependencies — no live services are required to run the tests.
```
Test Suites: 7 passed
Tests: 30 passed
```
---
## CI/CD Pipeline
This project uses GitHub Actions for continuous integration. The pipeline runs on every push and pull request to `main` and includes:
- ESLint code quality check
- Prettier format validation
- TypeScript type checking
- Full test suite with coverage
- Build verification
**Services provisioned in CI:**
- PostgreSQL 13
- Redis Alpine
---
## Project Structure
```
.
├── src/
│ ├── server.ts # Express app entry point
│ ├── routes.ts # Route definitions
│ ├── postgres.ts # PostgreSQL pool (pg)
│ ├── redisConfig.ts # Redis client (ioredis)
│ ├── controllers/
│ │ ├── CreateUserController.ts
│ │ ├── LoginUserController.ts
│ │ └── GetUserInfoController.ts
│ ├── middleware/
│ │ └── auth.ts # JWT authentication middleware
│ └── @types/
│ └── express/index.d.ts # Express Request type extension
├── __tests__/ # Jest test suites
├── database.sql # PostgreSQL schema (auto-run by Docker)
├── docker-compose.yml
├── Dockerfile
├── jest.config.js
├── tsconfig.json
└── eslint.config.js
```