A secure and scalable Node.js REST API with authentication, built with Express.js, Drizzle ORM, and Neon Database. Features comprehensive security middleware, JWT authentication, and Docker-based development workflow.
- Features
- Tech Stack
- Project Structure
- Getting Started
- API Documentation
- Database Management
- Development
- Scripts
- Docker
- Security
- Troubleshooting
- License
- π JWT Authentication - Secure user authentication with bcrypt password hashing
- π‘οΈ Security First - Helmet, CORS, Arcjet security middleware
- π Neon Database - Serverless PostgreSQL with Neon Local for development
- π Hot Reload - Auto-restart on file changes in development
- π Structured Logging - Winston logger with Morgan HTTP logging
- π³ Docker Ready - Separate dev/prod Docker configurations
- π― Modern ES Modules - Full ESM support with import path aliases
- β Input Validation - Zod schema validation for requests
- π§© Modular Architecture - Clean separation of concerns (MVC pattern)
- Runtime: Node.js 22
- Framework: Express.js 5
- Database: Neon PostgreSQL
- ORM: Drizzle ORM
- Authentication: JWT + bcrypt
- Security: Helmet, CORS, Arcjet
- Logging: Winston + Morgan
- Validation: Zod
- Dev Tools: ESLint, Prettier, Docker
acquisitions/
βββ src/
β βββ config/ # Configuration files
β β βββ arject.js # Arcjet security config
β β βββ database.js # Database connection
β β βββ logger.js # Winston logger setup
β βββ controllers/ # Request handlers
β β βββ auth.controller.js
β β βββ user.controller.js
β βββ middleware/ # Custom middleware
β β βββ security.middleware.js
β βββ models/ # Database schemas
β β βββ user.model.js
β βββ routes/ # API routes
β β βββ auth.routes.js
β β βββ user.route.js
β βββ services/ # Business logic
β β βββ auth.service.js
β β βββ user.service.js
β βββ utils/ # Utility functions
β β βββ cookies.js
β β βββ format.js
β β βββ jwt.js
β βββ validations/ # Zod schemas
β β βββ auth.validation.js
β β βββ user.validation.js
β βββ app.js # Express app setup
β βββ index.js # Entry point
β βββ server.js # Server configuration
βββ drizzle/ # Database migrations
βββ scripts/ # Helper scripts
β βββ dev.sh # Development startup
β βββ prod.sh # Production startup
βββ logs/ # Application logs
βββ Dockerfile # Production container
βββ docker-compose.dev.yml # Development setup
βββ docker-compose.prod.yml # Production setup
βββ drizzle.config.js # Drizzle ORM config
βββ package.json
- Node.js 22 or higher
- Docker and Docker Compose (for containerized setup)
- Neon Account (sign up at neon.tech)
- Git
-
Clone the repository
git clone https://github.com/n-ithesh/acquisitions.git cd acquisitions -
Install dependencies
npm install
-
Set up Neon Database
- Go to console.neon.tech
- Create a new project
- Get your API Key from Settings β API Keys
- Copy your Project ID from Project Settings
- Copy your Branch ID from Branches tab
-
Configure environment files
Development (
.env.development):# Neon Configuration NEON_API_KEY=your_api_key_here NEON_PROJECT_ID=your_project_id_here PARENT_BRANCH_ID=your_main_branch_id_here # Database URL (for Neon Local) DB_URL=postgres://neon:npg@neon-local:5432/neondb # Application NODE_ENV=development PORT=3000 # JWT JWT_SECRET=your_jwt_secret_here JWT_EXPIRES_IN=7d # Arcjet (optional) ARCJET_KEY=your_arcjet_key_here
Production (
.env.production):# Database URL (from Neon Console) DB_URL=postgres://user:pass@ep-xxx.aws.neon.tech/neondb?sslmode=require # Application NODE_ENV=production PORT=3000 # JWT JWT_SECRET=your_secure_jwt_secret_here JWT_EXPIRES_IN=7d # Arcjet ARCJET_KEY=your_arcjet_key_here
Using Docker (Recommended):
# Start with Neon Local proxy
docker compose -f docker-compose.dev.yml up --build
# Or use the helper script
npm run dev:dockerLocal Development (without Docker):
# Ensure DB_URL points to a valid database
npm run devYour API will be available at http://localhost:3000
Using Docker:
docker compose -f docker-compose.prod.yml up --build
# Or use the helper script
npm run prod:dockerDirect deployment:
npm starthttp://localhost:3000/api
GET /healthReturns server health status
Sign Up
POST /api/auth/sign-up
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"password": "securePassword123"
}Sign In
POST /api/auth/sign-in
Content-Type: application/json
{
"email": "john@example.com",
"password": "securePassword123"
}Sign Out
POST /api/auth/sign-outGet Users (Protected)
GET /api/users
Authorization: Bearer <token>Generate migrations (after schema changes):
npm run db:generateApply migrations:
Development:
docker compose -f docker-compose.dev.yml exec app npm run db:migrateProduction:
DB_URL="your_prod_connection_string" npm run db:migrateAccess Drizzle Studio to manage your database:
npm run db:studioOpens at https://local.drizzle.studio
Current schema includes:
- users table with authentication fields
id(serial, primary key)name(varchar)email(varchar, unique)password(varchar, hashed)role(varchar, default: 'user')created_at(timestamp)updated_at(timestamp)
Linting:
npm run lint # Check for issues
npm run lint:fix # Auto-fix issuesFormatting:
npm run format:check # Check formatting
npm run format # Auto-format codeThe project uses import aliases for cleaner imports:
import User from '#models/user.model.js';
import { db } from '#config/database.js';
import { validateAuth } from '#validations/auth.validation.js';Available aliases:
#models/β./src/models/#config/β./src/config/#controllers/β./src/controllers/#routes/β./src/routes/#utils/β./src/utils/#middlewares/β./src/middlewares/#services/β./src/services/#validations/β./src/validations/
| Script | Description |
|---|---|
npm run dev |
Start development server with watch mode |
npm start |
Start production server |
npm run lint |
Run ESLint |
npm run lint:fix |
Fix ESLint issues |
npm run format |
Format code with Prettier |
npm run format:check |
Check code formatting |
npm run db:generate |
Generate Drizzle migrations |
npm run db:migrate |
Apply Drizzle migrations |
npm run db:studio |
Open Drizzle Studio |
npm run dev:docker |
Start development with Docker |
npm run prod:docker |
Start production with Docker |
Uses Neon Local proxy for ephemeral database branches:
- Fresh database branch per container start
- Hot-reload enabled
- Database accessible at
localhost:5432 - Auto-cleanup on container stop
docker compose -f docker-compose.dev.yml up --buildConnects directly to Neon Cloud Database:
- No local proxy
- Optimized Node.js image
- Non-root user execution
- Health checks included
docker compose -f docker-compose.prod.yml up --build# View logs
docker compose -f docker-compose.dev.yml logs -f app
# Shell into container
docker compose -f docker-compose.dev.yml exec app sh
# Stop and remove volumes
docker compose -f docker-compose.dev.yml down -v
# Rebuild from scratch
docker compose -f docker-compose.dev.yml up --build --force-recreateFor detailed Docker documentation, see DOCKER.md and QUICKSTART.md
- Helmet.js - Sets secure HTTP headers
- CORS - Cross-origin resource sharing
- Arcjet - Advanced security middleware
- bcrypt - Password hashing (salt rounds: 10)
- JWT - Token-based authentication
- Cookie Security - HttpOnly, Secure, SameSite cookies
- Input Validation - Zod schema validation
- Rate Limiting - Via Arcjet
- SQL Injection Protection - Via Drizzle ORM parameterized queries
- Never commit
.env*files (except.env.example) - Use strong JWT secrets in production
- Enable SSL/TLS for production database connections
- Rotate API keys regularly
- Use environment variables for all secrets
- Keep dependencies updated
- Enable 2FA on Neon account
Stop local PostgreSQL or change the port:
# Windows
net stop postgresql-x64-14
# Or change port in docker-compose.dev.yml
ports:
- "54320:5432"-
Check if containers are running:
docker compose -f docker-compose.dev.yml ps
-
View container logs:
docker compose -f docker-compose.dev.yml logs -f
-
Verify environment variables:
docker compose -f docker-compose.dev.yml config
- Verify Neon credentials in
.env.development - Check API key hasn't expired
- Ensure Project ID and Branch ID are correct
# Reset local database
docker compose -f docker-compose.dev.yml down -v
docker compose -f docker-compose.dev.yml up --build
# Regenerate migrations
npm run db:generate
npm run db:migrate# Clean rebuild
docker compose down -v
docker system prune -a
npm run dev:docker- Quick Start Guide - Get up and running in 5 minutes
- Docker Documentation - Comprehensive Docker setup guide
- Neon Documentation
- Drizzle ORM Docs
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
ISC
n-ithesh
- GitHub: @n-ithesh
- Repository: acquisitions
- Neon Database - Serverless PostgreSQL
- Drizzle ORM - TypeScript ORM
- Express.js - Web framework
- Arcjet - Security platform
Happy coding! π
For quick setup instructions, see QUICKSTART.md