A Node.js Express backend application for Strix.
- User authentication with JWT tokens and role-based access control
- Admin user functionality with the first registered user becoming admin
- Hello World API endpoint: Returns a simple greeting message
- Swagger API documentation: Interactive API documentation
- Automated deployment workflow via GitHub Actions
- Build system with Babel for modern JavaScript
- Dynamic Swagger configuration that adapts to deployment environment
- PostgreSQL database integration with automatic migrations
- Environment variable configuration
- Licitations management: Create, read, update, and delete licitations with customizable price type selection
- Node.js (v14 or higher)
- npm (v6 or higher)
- PostgreSQL (v12 or higher)
# Clone the repository
git clone https://github.com/CleanCodeIt/strix-backend.git
# Navigate to the project directory
cd strix-backend
# Install dependencies
npm install
# Set up environment variables
# Copy the .env.example file to .env and update with your values
copy .env.example .env- Create a PostgreSQL database for the project
- Update the .env file with your database credentials:
DB_HOST=localhost
DB_PORT=5432
DB_NAME=strix_db
DB_USER=postgres
DB_PASSWORD=your_password
DB_DIALECT=postgres
# Build the application
npm run build
# Start in production mode
npm start
# Start in development mode (with auto-reload)
npm run dev
# Lint your code
npm run lintThe server will be available at: http://localhost:3000
# Create a new migration (replace migration_name with your migration name)
npm run migrate migration_name
# Reset and run all migrations
npm run migrate:reset
# Seed the database with sample data
npm run seed
# Reset and run all seeders
npm run seed:resetThe application automatically runs pending migrations on startup. This ensures that your database schema is always up-to-date with the latest changes.
Swagger API documentation is available at:
- Development: http://localhost:3000/api-docs
- Production: {deployedServerURL}/api-docs
The Swagger UI automatically detects the correct server URL based on the environment.
-
Register User
- URL:
/api/auth/register - Method:
POST - Description: Register a new user (first user becomes admin)
- Request Body:
{ "username": "johndoe", "email": "john.doe@example.com", "password": "securePassword123" } - Response (Success):
{ "status": "success", "message": "User registered successfully", "token": "jwt-token-here", "user": { "id": 1, "username": "johndoe", "email": "john.doe@example.com", "isAdmin": true } }
- URL:
-
Login User
- URL:
/api/auth/login - Method:
POST - Description: Authenticate a user and get JWT token
- Request Body:
{ "email": "john.doe@example.com", "password": "securePassword123" } - Response (Success):
{ "status": "success", "message": "Login successful", "token": "jwt-token-here", "user": { "id": 1, "username": "johndoe", "email": "john.doe@example.com", "isAdmin": true } }
- URL:
-
Get Current User
- URL:
/api/auth/me - Method:
GET - Description: Get information about the currently authenticated user
- Headers:
Authorization: Bearer jwt-token-here - Response (Success):
{ "status": "success", "user": { "id": 1, "username": "johndoe", "email": "john.doe@example.com", "isAdmin": true } }
- URL:
-
Get All Licitations
- URL:
/api/licitations - Method:
GET - Description: Get a list of all licitations
- Response (Success):
{ "status": "success", "data": [ { "id": 1, "title": "Office Supplies", "description": "Looking for office supplies for our company", "startDate": "2025-05-10T10:00:00.000Z", "endDate": "2025-05-20T10:00:00.000Z", "isLowestPrice": true, "userId": 1, "createdAt": "2025-05-06T12:30:45.000Z", "updatedAt": "2025-05-06T12:30:45.000Z", "creator": { "id": 1, "username": "johndoe", "email": "john.doe@example.com" } } ] }
- URL:
-
Get Licitation by ID
- URL:
/api/licitations/:id - Method:
GET - Description: Get details of a specific licitation
- Response (Success):
{ "status": "success", "data": { "id": 1, "title": "Office Supplies", "description": "Looking for office supplies for our company", "startDate": "2025-05-10T10:00:00.000Z", "endDate": "2025-05-20T10:00:00.000Z", "isLowestPrice": true, "userId": 1, "createdAt": "2025-05-06T12:30:45.000Z", "updatedAt": "2025-05-06T12:30:45.000Z", "creator": { "id": 1, "username": "johndoe", "email": "john.doe@example.com" } } }
- URL:
-
Create Licitation
- URL:
/api/licitations - Method:
POST - Description: Create a new licitation
- Authentication: Required
- Request Body:
{ "title": "Office Supplies", "description": "Looking for office supplies for our company", "startDate": "2025-05-10T10:00:00.000Z", "endDate": "2025-05-20T10:00:00.000Z", "isLowestPrice": true } - Response (Success):
{ "status": "success", "message": "Licitation created successfully", "data": { "id": 1, "title": "Office Supplies", "description": "Looking for office supplies for our company", "startDate": "2025-05-10T10:00:00.000Z", "endDate": "2025-05-20T10:00:00.000Z", "isLowestPrice": true, "userId": 1, "createdAt": "2025-05-06T12:30:45.000Z", "updatedAt": "2025-05-06T12:30:45.000Z" } }
- URL:
-
Update Licitation
- URL:
/api/licitations/:id - Method:
PUT - Description: Update an existing licitation
- Authentication: Required
- Request Body:
{ "title": "Updated Office Supplies", "description": "Updated description for office supplies", "startDate": "2025-05-12T10:00:00.000Z", "endDate": "2025-05-25T10:00:00.000Z", "isLowestPrice": false } - Response (Success):
{ "status": "success", "message": "Licitation updated successfully", "data": { "id": 1, "title": "Updated Office Supplies", "description": "Updated description for office supplies", "startDate": "2025-05-12T10:00:00.000Z", "endDate": "2025-05-25T10:00:00.000Z", "isLowestPrice": false, "userId": 1, "createdAt": "2025-05-06T12:30:45.000Z", "updatedAt": "2025-05-06T13:45:22.000Z" } }
- URL:
-
Delete Licitation
- URL:
/api/licitations/:id - Method:
DELETE - Description: Delete an existing licitation
- Authentication: Required
- Response (Success):
{ "status": "success", "message": "Licitation deleted successfully" }
- URL:
- URL:
/hello - Method:
GET - Description: Returns a Hello World message
- Response:
{ "message": "Hello World!" }
- URL:
/db-status - Method:
GET - Description: Checks the database connection status
- Response (Success):
{ "status": "success", "message": "Database connection established successfully" } - Response (Error):
{ "status": "error", "message": "Failed to connect to database" }
The project includes a GitHub Actions workflow for automated deployment. The deployment process is triggered when a commit message follows this specific format:
DEPLOY {version}: {commitMessage}
For example: DEPLOY 1.2.0: Added user authentication feature
When a properly formatted commit message is pushed to the main branch, the following steps are automatically executed:
- The project is built
- The build is deployed to the configured FTP server
- A GitHub release is created with:
- A tag matching the specified version
- Release notes from the releaseNotes.txt file
- The built project attached as an artifact
To use the deployment workflow, configure the following GitHub repository secrets:
FTP_SERVER: FTP server addressFTP_PORT: FTP server portFTP_USERNAME: FTP account usernameFTP_PASSWORD: FTP account passwordFTP_FOLDER_LOCATION: Target directory on the FTP server
- Don't use TypeScript
- Follow functional programming principles where possible
- Prefer immutable data
- Use try/catch blocks for async operations
- Document all endpoints in Swagger
The project uses a modern build system with the following features:
- Babel: Transpiles modern JavaScript to ensure compatibility
- ESLint: Enforces code quality and styling standards
- Build Script: Compiles the source code to the
distdirectory - Development Mode: Uses nodemon for automatic reloading during development
- Run
npm run buildto create a production build - The build process:
- Cleans the previous build (
distdirectory) - Transpiles JavaScript with Babel
- Copies necessary files to the
distdirectory - Ignores development files like tests and GitHub workflows
- Cleans the previous build (