A modern, scalable REST API built with Node.js, Express, and TypeScript for managing a virtual radio station with real-time chat, user management, and streaming capabilities.
- Overview
- Tech Stack
- Prerequisites
- Quick Start
- Detailed Setup
- Configuration
- Database
- Running the Application
- Project Structure
- API Documentation
- Contributing
- Support & Contact
Radio Enchufe Virtual is a full-featured API for managing a virtual radio station. It provides comprehensive functionality for:
- ποΈ Radio Management: Stream management and station control
- π₯ User Management: Authentication, authorization, and user profiles
- π¬ Real-time Chat: WebSocket-powered instant messaging
- π Posts: Content management system for radio updates
- π€ Social Features: User interactions and social networking
- π€ File Uploads: Efficient image and audio handling with Sharp optimization
- π Authentication: JWT-based secure authentication with bcrypt password hashing
- π CORS Support: Configurable cross-origin resource sharing
This project is built with TypeScript for type safety, Express.js for routing, Sequelize for ORM, and Socket.io for real-time communication.
| Layer | Technology |
|---|---|
| Runtime | Node.js v18.14.2 |
| Language | TypeScript 5.0+ |
| Framework | Express.js 4.18+ |
| Database | MariaDB 10.5+ |
| ORM | Sequelize 6.30+ |
| Real-time | Socket.io 4.6+ |
| Authentication | JWT + bcrypt |
| File Upload | Multer 1.4+ with Sharp optimization |
| Validation | Joi 17.9+ |
| Container | Docker + Docker Compose |
Before you begin, ensure you have the following installed on your system:
-
Node.js (v18.14.2 or higher)
- Download Node.js
- Verify:
node -v && npm -v
-
Git
- Download Git
- Verify:
git --version
-
Docker (Desktop or Server)
- Install Docker
- Verify:
docker --version
-
Docker Compose
- Usually included with Docker Desktop
- Verify:
docker-compose --version
Get the API running in less than 5 minutes:
# 1. Clone the repository
git clone [email protected]:enchufevirtual/radio-api.git
cd radio-api
# 2. Install dependencies
npm install
# 3. Set up environment variables (see Configuration section)
cp .env.example .env
# Edit .env with your configuration
# 4. Start database with Docker Compose
docker-compose up -d
# 5. Run database migrations
npm run migrations:run
# 6. Start development server
npm run devThe API will be available at http://localhost:4000
This is the recommended approach for consistent development and easier deployment.
git clone [email protected]:enchufevirtual/radio-api.git
cd radio-api
npm installCopy the example environment file and update the values:
cp .env.example .envEdit .env with your specific configuration:
# Node Environment
NODE_ENV=development
# Database Configuration
DB_HOST=mariadb # Service name in docker-compose.yml
DB_NAME=radio_db
DB_USER=radio_user
DB_PASSWORD=secure_password_here
DB_ROOT_PASSWORD=root_password_here
# JWT Secret (use a strong, random string)
JWT_SECRET=your_secure_jwt_secret_key_here
# URLs
FRONTEND_URL=http://localhost:3000
BACKEND_URL=http://localhost:4000
PORT=4000
# Zeno FM Configuration (for streaming)
ZENO_STATION_ID=your_station_id
ZENO_STREAM_ID=your_stream_id
# Email Configuration (NodeMailer)
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_USER=[email protected]
EMAIL_PASS=your_email_password# Start MariaDB and phpMyAdmin containers
docker-compose up -d
# Verify containers are running
docker-compose psYou should see:
- mariadb container running on port 3306
- phpmyadmin container running on port 8080
# Run all migrations to create database schema
npm run migrations:run
# Verify tables were created (optional)
# Access phpMyAdmin at http://localhost:8080
# User: your_db_user
# Password: your_db_password# Development mode with hot reload
npm run devSuccess! API is running at http://localhost:4000 β
For local database setup without Docker.
git clone [email protected]:enchufevirtual/radio-api.git
cd radio-api
npm installOn macOS (with Homebrew):
brew install mariadb
brew services start mariadb
mysql -u root -p # Access MariaDB console (no password by default)On Linux (Ubuntu/Debian):
sudo apt-get update
sudo apt-get install mariadb-server
sudo systemctl start mariadb
mysql -u root -pInside MariaDB console:
CREATE DATABASE radio_db;
CREATE USER 'radio_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON radio_db.* TO 'radio_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;cp .env.example .envUpdate .env with your local database credentials:
DB_HOST=localhost
DB_NAME=radio_db
DB_USER=radio_user
DB_PASSWORD=your_password
DB_ROOT_PASSWORD=your_root_password
DATABASE_URL=mariadb://radio_user:your_password@localhost:3306/radio_dbnpm run migrations:runnpm run devAll configuration is managed through the .env file. Here's what each variable does:
| Variable | Required | Description |
|---|---|---|
NODE_ENV |
Yes | development or production |
PORT |
No | API port (default: 4000) |
DB_HOST |
Yes | Database host/service name |
DB_NAME |
Yes | Database name |
DB_USER |
Yes | Database username |
DB_PASSWORD |
Yes | Database password |
DB_ROOT_PASSWORD |
Yes | Database root password |
JWT_SECRET |
Yes | Secret key for JWT signing (use strong random string) |
DATABASE_URL |
Yes | Full connection string |
FRONTEND_URL |
Yes | Frontend application URL (for CORS and links) |
BACKEND_URL |
Yes | Backend API URL (for email links, etc.) |
ZENO_STATION_ID |
No | Zeno.fm station ID for streaming |
ZENO_STREAM_ID |
No | Zeno.fm stream ID for streaming |
EMAIL_HOST |
No | SMTP server host |
EMAIL_PORT |
No | SMTP server port |
EMAIL_USER |
No | SMTP authentication username |
EMAIL_PASS |
No | SMTP authentication password |
By default, the API runs on port 4000. If this port is already in use, you can:
-
Change it in
.env:PORT=5000
-
Or pass it as environment variable:
PORT=5000 npm run dev
The API uses MariaDB with Sequelize ORM for database management. Database schema is version-controlled through migrations.
Create new migration:
npm run migrations:generate -- --name create_users_table
# Edit the generated file in ./app/database/migrations/Apply migrations:
npm run migrations:runRollback last migration:
npm run migrations:undoUsing phpMyAdmin (Docker setup):
- URL:
http://localhost:8080 - User:
radio_user - Password: (from
.envDB_PASSWORD) - Select database:
radio_db
Using MySQL CLI:
mysql -h localhost -u radio_user -p radio_dbStart with hot reload and debug logging:
npm run devFeatures:
- β Auto-reload on file changes (via nodemon)
- β TypeScript transpilation
- β Full error logging
- β Console output
Access the API: http://localhost:4000
Build and run optimized production code:
# Compile TypeScript to JavaScript
npm run build
# Start the built application
npm startThis creates a dist/ directory with compiled JavaScript and starts the server.
Verify the API is running:
curl http://localhost:4000
# Response: "400 - Enchufe Virtual - API - Bad Request"
# (The 400 is expected for non-existent routes, confirming the API is alive)radio-api/
βββ app/
β βββ index.ts # Server entry point
β βββ config/ # Configuration files
β β βββ index.ts
β β βββ config.js
β βββ database/
β β βββ config.js # Database connection config
β β βββ migrations/ # Version-controlled schema changes
β β βββ models/ # Sequelize data models
β βββ enchufevirtual/ # API modules (routes & controllers)
β β βββ index.ts # Route aggregator
β β βββ users/ # User management (auth, profiles)
β β βββ posts/ # Content/posts endpoints
β β βββ chat/ # Chat management
β β βββ radio/ # Radio streaming management
β β βββ social/ # Social features (follows, likes)
β βββ helpers/ # Utility functions
β β βββ auth.ts # Auth helpers (JWT, tokens)
β β βββ hashPassword.ts # Password hashing utilities
β β βββ generateId.ts # ID generation
β β βββ generateJWT.ts # JWT token generation
β β βββ emailRegister.ts # Email templates
β β βββ sanitizeText.ts # XSS prevention
β β βββ ...
β βββ libs/
β β βββ sequelize.ts # Sequelize ORM initialization
β βββ middlewares/ # Express middlewares
β β βββ checkAuth.ts # JWT verification
β β βββ checkRoleAuth.ts # Role-based access control
β β βββ checkOrigin.ts # CORS validation
β β βββ setupSocketIO.ts # WebSocket configuration
β β βββ upload.ts # File upload handling
β β βββ createImage.ts # Image optimization with Sharp
β β βββ error.handler.ts # Centralized error handling
β β βββ validator.handler.ts # Request validation (Joi)
β β βββ ...
β βββ Schemas/ # Joi validation schemas
β β βββ user.schema.ts
β βββ public/
β βββ uploads/ # User-uploaded files
βββ types/
β βββ types.d.ts # Global TypeScript definitions
βββ .env.example # Environment variables template
βββ .env # Environment variables (gitignored)
βββ docker-compose.yml # Docker services configuration
βββ package.json # Project dependencies
βββ tsconfig.json # TypeScript configuration
βββ .eslintrc.json # ESLint rules
βββ .sequelizerc # Sequelize CLI config
βββ README.md # This file
- users/: User registration, login, profile management, password reset
- posts/: Create, read, update, delete posts with images
- chat/: WebSocket-powered real-time messaging between users
- radio/: Stream management, station information, now playing data
- social/: Follow relationships, likes, user recommendations
The API uses JWT (JSON Web Tokens) for authentication.
Login endpoint:
POST /api/auth/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "password123"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "uuid",
"email": "[email protected]",
"username": "username"
}
}Using the token:
GET /api/user/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...See individual module documentation for complete API reference:
- Users: Registration, login, profile, password reset
- Posts: Create, list, update, delete posts
- Chat: Send messages, get chat history (WebSocket)
- Radio: Get station info, streaming status
- Social: Follow/unfollow users, like content
The API returns consistent error responses:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Validation failed"
}Common HTTP Status Codes:
200- Success201- Created400- Bad Request (validation failed)401- Unauthorized (invalid/missing token)403- Forbidden (insufficient permissions)404- Not Found500- Internal Server Error
npm run dev # Start development server with hot reload
npm run build # Compile TypeScript to JavaScript
npm start # Run compiled production build
npm run migrations:run # Apply pending database migrations
npm run migrations:generate --name create_table # Generate new migration
tsc # Type-check TypeScript without buildingThe project uses ESLint and Prettier for code consistency:
npm run lint # Check code style
npm run format # Auto-format code with PrettierTypeScript provides type safety across the codebase. Configuration in tsconfig.json:
{
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}# All containers
docker-compose logs
# Specific container
docker-compose logs mariadb
docker-compose logs phpmyadmin
# Follow logs in real-time
docker-compose logs -f mariadb# Stop containers (preserve data)
docker-compose stop
# Stop and remove containers
docker-compose down
# Remove containers and volumes (WARNING: deletes database data!)
docker-compose down -v# Remove database container and volume
docker-compose down -v
# Recreate and start fresh
docker-compose up -d
npm run migrations:runProblem: Port 4000 already in use
# Solution 1: Use different port
PORT=5000 npm run dev
# Solution 2: Kill the process using port 4000
lsof -ti:4000 | xargs kill -9Problem: Database connection refused
# Check if database is running
docker-compose ps
# If not, start it
docker-compose up -d
# Check database logs
docker-compose logs mariadbProblem: Migrations fail
# Verify database exists and connection works
mysql -h localhost -u radio_user -p radio_db -e "SHOW TABLES;"
# Check migration files are in correct directory
ls app/database/migrations/Problem: TypeScript compilation errors
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
# Rebuild
npm run buildWe welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes and test thoroughly
- Commit with clear messages:
git commit -m 'Add amazing feature' - Push to your fork:
git push origin feature/amazing-feature - Open a Pull Request
- Follow the existing code style (ESLint + Prettier)
- Write TypeScript with strict mode enabled
- Add proper error handling
- Update this README for new features
- Test your changes before submitting
- π§ Email: [email protected]
- π Social Media: @enchufevirtual
- π± GitHub: enchufevirtual
- π¬ Issues: Open an issue on GitHub for bugs or feature requests
This project is licensed under the ISC License - see the LICENSE file for details.
Made with β€οΈ by the Enchufe Virtual Team
This project represents knowledge acquired through experience. It improves over time with your contributions. Be free, be happy! π