Last Updated: November 2025
This is the backend API server for Silah, an AI-augmented full-stack B2B platform that connects suppliers and buyers. Built using NestJS, a progressive Node.js framework for building efficient and scalable server-side applications.
Silah (Arabic: Ψ΅ΩΩΩΨ©) [noun] Connection, bond, link; often used to describe the ties between people, family, or communities.
This NestJS backend handles:
- User Management & Authentication (with Commercial Registration verification)
- Product & Service Catalog Management
- Order Processing & Management
- Request for Proposals (RFP) System
- Real-time Chat & Notifications
- File Upload & Storage (Cloudflare R2 integration)
- Payment Processing (Tap Payments integration)
- Multi-language Support (DeepL Translate API)
Note: AI features (semantic search, demand forecasting) are handled by a separate FastAPI backend.
- Framework: NestJS (Node.js)
- Database: PostgreSQL with Prisma ORM
- Authentication: JWT + Wathq API (Commercial Registration verification)
- Storage: Cloudflare R2 (for file/image storage)
- Payments: Tap Payments Gateway
- Translation: DeepL Translate API
- Real-time: WebSockets for chat and notifications
- Testing: Jest (Unit, Integration, E2E)
- DevOps: Docker & Docker Compose
Before you start, make sure you have:
- Node.js >= 20
- npm >= 10
- Docker & Docker Compose >= 2 (strongly recommended)
- PostgreSQL >= 16 (if not using Docker)
You'll need accounts and API keys for:
- SendGrid (sending emails)
- Tap Payments (payment processing)
- Cloudflare R2 (file storage)
- Wathq API (Saudi Commercial Registration verification)
- DeepL Translate API (for auto-translation of products and services data)
Docker simplifies setup by handling the database and environment automatically.
git clone https://github.com/GP-Silah/silah-backend.git
cd silah-backendnpm installCreate your environment configuration files:
# Copy the example files
cp .env.example .env
cp .env.dev.example .env.dev
cp .env.test.example .env.testUnderstanding the Environment Files:
.envused for shared variables (database credentials, API keys).env.devused for development database connection.env.testused for test database connection (separate from dev)
Why seperate database config? Prisma only accepts one DATABASE_URL at a time, but we need different databases for development and testing. Our setup dynamically switches between them.
Edit the .env files with your actual values.
npm run docker:devThis single command will:
- Start PostgreSQL database on port 5432
- Start NestJS backend on port 3000 with hot reload
- Run database migrations automatically
- Seed the database with categories
- Set up health checks to ensure everything is connected
Important: The category seeding step is crucial. It inserts ~50 predefined categories that the application relies on. Skipping this will break category-related features.
What you'll see (simplified):
Creating silah_db ... done
Creating silah_backend ... done
Attaching to silah_db, silah_backend
silah_backend | Database connected successfully
silah_backend | Migrations applied
silah_backend | Categories seeded
silah_backend | π Server running on http://localhost:3000- API:
http://localhost:3000/api - Health Check:
http://localhost:3000/api/health - API Documentation:
http://localhost:3000/api/docs
If you prefer to run PostgreSQL locally or have specific requirements.
Make sure PostgreSQL is running locally and create the database:
# Connect to PostgreSQL
psql -U postgres
# Create user and databases
CREATE USER silah_user WITH PASSWORD 'your_secure_password';
CREATE DATABASE silah_dev OWNER silah_user;
CREATE DATABASE silah_test OWNER silah_user;
GRANT ALL PRIVILEGES ON DATABASE silah_dev TO silah_user;
GRANT ALL PRIVILEGES ON DATABASE silah_test TO silah_user;To enable typo-tolerant search (e.g., "Candle" β "Candl"), you must enable the pg_trgm extension in both databases:
\c silah_dev
CREATE EXTENSION IF NOT EXISTS pg_trgm;
\c silah_test
CREATE EXTENSION IF NOT EXISTS pg_trgm;
```
> Warning: This extension is required for full-text fuzzy search in products, suppliers, and categories. Without it, search queries will fail.
#### 5. Set Up Prisma and Database
```bash
# Generate Prisma client
npx prisma generate
# Run migrations (development)
npm run prisma:dev
# Seed the database with categories (REQUIRED)
npm run prisma:seed:categoryImportant: The category seeding step is crucial. It inserts ~50 predefined categories that the application relies on. Skipping this will break category-related features.
npm run start:dev| Command | Description | Use Case |
|---|---|---|
npm run docker:dev |
Start development environment | Daily development |
npm run docker:dev:d |
Start dev environment in background | When you want to free up terminal |
npm run docker:test |
Start test environment | Running integration/e2e tests |
npm run docker:down |
Stop all containers | Cleanup when done |
npm run docker:logs |
View container logs | Debugging issues |
npm run docker:cleanup |
Remove containers & clean system | Full reset |
# Two separate databases for isolation
postgres_dev: # Development DB on port 5432
postgres_test: # Test DB on port 5433 (ephemeral data)
# One application container
app: # NestJS backend on port 3000Why separate test database?
- Isolation: Tests doon't interfere with development data
- Clean slate: Each test run starts fresh
- Speed: No need to clean up test data
- Safety: Can't accidentally delete dev data during testing
Our Docker setup intelligently switches between development and test configurations:
# Development mode
npm run docker:dev
# β Uses .env.dev, connects to postgres_dev, hot reload enabled
# Test mode
npm run docker:test
# β Uses .env.test, connects to postgres_test, optimized for testingPort 5432 already in use:
# Kill any processes using the port
npm run kill:5432
# Or stop local PostgreSQL service
brew services stop postgresql # macOS
sudo systemctl stop postgresql # LinuxContainers won't start:
# Full cleanup and restart
npm run docker:cleanup
npm run docker:devDatabase connection issues:
# Check container logs
npm run docker:logs
# Check if database is ready
npm run db:wait:dev# View real-time logs
npm run docker:logs
# View specific service logs
docker logs silah_backend -f
docker logs silah_db -f
# Search logs for specific events (e.g., errors)
docker logs silah_backend 2>&1 | grep "ERROR"# Connect to database
docker exec -it silah_db psql -U silah_user -d silah_dev
# View active connections
SELECT * FROM pg_stat_activity;
# Monitor query performance
SELECT * FROM pg_stat_statements ORDER BY mean_time DESC;We use a comprehensive 3-tier testing approach:
Test individual components in isolation with mocked dependencies.
# Run all unit tests
npm test
# Run in watch mode (for development)
npm run test:watch
# Run with coverage report
npm run test:cov
# Debug tests
npm run test:debugWhat unit tests cover:
- Individual service methods
- Controller endpoints (mocked dependencies)
- Utility functions
- Validation logic
Test multiple components working together with real database connections.
# Run integration tests (automatically manages test database)
npm run test:intWhat integration tests cover:
- Controller + Service workflows
- Service + Database interactions
- Real database operations
How integration tests work:
- Automatically starts test database container
- Waits for database to be ready
- Runs migrations and seeds data
- Executes tests with real database connections
- Cleans up after completion
Test complete user workflows through HTTP requests.
# Run e2e tests
npm run test:e2eWhat E2E tests cover:
- Complete API workflows
- Authentication & Authorization
- Cross-module interaction
- Real HTTP request/response cycles
- Unit Tests: Uses default Jest configuration in
package.json - Integration Tests:
test/jest-int.json - E2E Tests:
test/jest-e2e.json
Development Database (postgres_dev):
- Local Port: 5432
- Persistent data (survives container restarts)
- Used for: Manual testing, development
Test Database (postgres_test):
- Local Port: 5433
- Ephemeral data (fresh start each time)
- Used for: Integration and E2E tests
- Automatically managed by test scripts
# Quick feedback loop during development
npm run test:watch
# Before committing changes
npm run test && npm run test:int
# Full test suite (CI/CD pipeline)
npm test && npm run test:int && npm run test:e2e
# Coverage report
npm run test:cov# Start development environment
npm run docker:dev
# Watch code changes
npm run start:dev # (if not using Docker)
# Run tests as you develop
npm run test:watch
# Check code quality
npm run lint
npm run format
# Database operations
npm run prisma:dev # Run new migrations
npm run prisma:seed:category # Reseed categories# Development database migrations
npm run prisma:dev
# Test database migrations
npm run prisma:test
# Generate Prisma client (after schema changes)
npx prisma generate
# Reset database (β οΈ destroys all data)
npx prisma migrate reset
# View database in Prisma Studio
npx prisma studio# Lint and auto-fix issues
npm run lint
# Format code consistently
npm run format
# Type checking
npm run build
# Pre-commit checks (recommended)
npm run lint && npm run test && npm run buildOnce your server is running, comprehensive API documentation is available:
URL: http://localhost:3000/api/docs
Features:
- Interactive API explorer
- Request/response schemas
- Try-it-out functionality
- Authentication examples
- Detailed endpoint descriptions
# Solution 1: Kill process using the port
npm run kill:5432
# Solution 2: Stop local PostgreSQL
brew services stop postgresql # macOS
sudo systemctl stop postgresql # Linux
# Solution 3: Use different port in .env
DATABASE_URL=postgresql://user:pass@localhost:5433/db# Check if database container is running
docker ps | grep silah_db
# Restart database
npm run docker:down
npm run docker:dev
# Check database logs
docker logs silah_db# Generate Prisma client
npx prisma generate
# Restart your application
npm run start:dev# Reseed categories
npm run prisma:seed:category
# Or reset and reseed entire database (this destroys all data)
npx prisma migrate reset# Full cleanup
npm run docker:cleanup
# Check Docker daemon
docker --version
docker info
# Restart Docker service
sudo systemctl restart docker # Linux
# Restart Docker Desktop on macOS/Windows# Clear Jest cache
npx jest --clearCache
# Run tests individually
npm test -- --testNamePattern="specific test name"
# Check test database
npm run docker:test
docker logs silah_db_test# Check volume mounts in docker-compose.override.yml
# Ensure you're using the override file:
npm run docker:dev # This includes the override file
# If still not working, restart with clean build:
npm run docker:down
npm run docker:devIf you're still experiencing issues:
- Check the logs first:
npm run docker:logs - Verify environment variables are set correctly
- Ensure all required services are running
- Check GitHub Issues for known problems
- Contact the development team
This project is licensed under the terms specified in the LICENSE file.
Built with care by Silah's Backend Team, as a requirement of a Graduation Project.