From ed4d0447abd81aafaf96cbe5e70d49ba228ec9a2 Mon Sep 17 00:00:00 2001 From: thaninbew Date: Sat, 13 Sep 2025 02:10:05 -0400 Subject: [PATCH 01/11] docker setup + docs --- .dockerignore | 126 +++++++++++ DOCKER.md | 322 +++++++++++++++++++++++++++++ apps/backend/Dockerfile | 39 ++++ apps/backend/src/app.controller.ts | 10 + docker-compose.dev.yml | 135 ++++++++++++ package.json | 17 +- scripts/docker-dev.bat | 140 +++++++++++++ scripts/docker-dev.sh | 187 +++++++++++++++++ scripts/init-db.sql | 43 ++++ yarn.lock | 69 ++++++- 10 files changed, 1085 insertions(+), 3 deletions(-) create mode 100644 .dockerignore create mode 100644 DOCKER.md create mode 100644 apps/backend/Dockerfile create mode 100644 docker-compose.dev.yml create mode 100644 scripts/docker-dev.bat create mode 100644 scripts/docker-dev.sh create mode 100644 scripts/init-db.sql diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..48836ed8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,126 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env.local +.env.production + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Nx generated files +.nx/cache +.nx/workspace-data + +# Build outputs +dist/ +build/ +tmp/ + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Git +.git +.gitignore +README.md + +# Docker +.dockerignore +Dockerfile +docker-compose*.yml + +# Database files +*.sqlite +*.db + +# Test files and coverage +coverage/ +.nyc_output/ +test-results/ +playwright-report/ + +# Storybook +storybook-static/ + +# Cypress +cypress/videos/ +cypress/screenshots/ + +# Temporary files +*.tmp +temp/ diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 00000000..5c07ee93 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,322 @@ +# Docker Development Setup + +## Overview + +**Docker** is like a shipping container for software. Instead of worrying about "works on my machine" problems, Docker packages your entire application with everything it needs to run - code, dependencies, and settings - into portable containers. + +**Why Docker?** + +- Consistent Environment: Everyone runs the same setup +- Easy Setup: No complex local installations +- Isolated Services: Database, backend, and tools run separately +- Resource Efficient: Start/stop services as needed +- Team Friendly: Same environment for all developers + +## Prerequisites + +### Required Software + +- **Docker Desktop** - The main Docker application ([download here](https://www.docker.com/products/docker-desktop/)) +- **Git** - For downloading the project code +- **Node.js & Yarn** - For running project scripts + +### Quick Check + +1. Open Docker Desktop and make sure it's running +2. Open a terminal/command prompt +3. Run `docker --version` to verify Docker is installed + +## Quick Start + +Follow these steps to get your development environment running: + +### Step 1: Get the Project Code + +```bash +git clone +cd fcc +yarn install +``` + +### Step 2: Start Services + +```bash +# Start development services (recommended) +yarn docker:up:dev + +# Or start all services +yarn docker:up:all + +# Alternative: Using Docker Compose directly +docker-compose -f docker-compose.dev.yml up -d postgres adminer backend-dev +``` + +### Step 3: Set Up the Database + +```bash +# Run migrations on development backend +yarn docker:migrate:dev + +# Alternative: Manual command +docker-compose -f docker-compose.dev.yml exec backend-dev sh -c "cd /app && npm run migration:run" +``` + +### Step 4: Verify Everything Works + +- **API**: Visit `http://localhost:3001/api` (development server) +- **Database Viewer**: Visit `http://localhost:8080` (Adminer) +- **Login to Adminer**: System: `PostgreSQL`, Server: `postgres`, Username: `postgres`, Password: `postgres`, Database: `fcc_dev` + +## Services Overview + +### Backend Development Server (Port 3001) + +**Purpose:** Runs your API code with live reloading + +**Use cases:** Development, testing new features, running migrations + +**Features:** + +- Hot Reload: Changes appear instantly without restarting +- Source Access: Can read your TypeScript files +- Development Tools: Better error messages and debugging + +### Backend Production Server (Port 3000) + +**Purpose:** Runs optimized, compiled version of your API + +**Use cases:** Testing production builds, performance testing + +**Features:** + +- Fast: Optimized for speed +- Secure: Production-ready settings +- Compiled: Runs pre-built JavaScript (not source code) + +### PostgreSQL Database (Port 5432) + +**Purpose:** Stores all your application data + +**Database Credentials:** + +- System: `PostgreSQL` +- Host: `postgres` +- Port: `5432` +- Database: `fcc_dev` +- Username: `postgres` +- Password: `postgres` + +**Storage:** Uses `postgres_data` volume to persist database files +**Features:** + +- Persistent: Data survives container restarts via `postgres_data` volume +- Health Checks: Automatically verifies it's working +- Auto Setup: Creates initial database structure + +### Adminer (Port 8080) + +**Purpose:** Web interface to view and edit database data +**Use cases:** Checking data, running quick queries, debugging + +## Docker Volumes + +**What are volumes?** Special folders that persist data outside containers + +**Why do we have 2 volumes?** + +### 1. postgres_data Volume + +- **Purpose:** Stores your database files permanently +- **Location:** `/var/lib/postgresql/data` inside PostgreSQL container +- **Why needed:** Database data must survive container restarts/crashes +- **Size:** Usually small unless you have lots of data + +### 2. backend_logs Volume + +- **Purpose:** Stores application log files +- **Location:** `/app/logs` inside backend containers +- **Why needed:** Logs help debug issues and track application behavior +- **Size:** Usually very small + +**Volume Creation Messages:** + +```bash +Volume "fcc_postgres_data" Created # Database storage +Volume "fcc_backend_logs" Created # Application logs +``` + +## Commands + +### Starting & Stopping Services + +```bash +# Start all services +yarn docker:up + +# Shorthand commands +yarn docker:up:dev # Start only dev services (postgres, adminer, backend-dev) +yarn docker:down # Stop everything +yarn docker:restart # Restart all services +``` + +### Checking Status & Logs + +```bash +# See which services are running +docker-compose -f docker-compose.dev.yml ps + +# View logs from all services +yarn docker:logs + +# View logs from specific service +docker-compose -f docker-compose.dev.yml logs -f backend-dev +``` + +## Database Operations & Migrations + +```bash +# RECOMMENDED: Run migrations on development backend +yarn docker:migrate:dev + +# Alternative: Run migrations on production backend (not recommended for dev) +yarn docker:migrate + +# Run migrations in isolated container (advanced) +yarn docker:migrate:oneoff +``` + +### Why One-off Migrations Are Powerful + +**What happens behind the scenes:** + +```bash +# 1. Build fresh image with source code +docker build --file apps/backend/Dockerfile --target build -t fcc-backend-build . + +# 2. Run temporary container (auto-deleted when done) +docker run --rm --network fcc_fcc-network \ + -e NX_DB_HOST=postgres \ + -e NX_DB_PORT=5432 \ + -e NX_DB_USERNAME=postgres \ + -e NX_DB_PASSWORD=postgres \ + -e NX_DB_DATABASE=fcc_dev \ + fcc-backend-build npm run migration:run +``` + +**Key Benefits:** + +- Isolated: Doesn't touch your running containers +- Clean: Fresh build every time - no cached issues +- Recoverable: Works when other containers fail +- CI/CD Ready: Perfect for automated deployments +- Testable: Safe to test migrations without affecting dev environment +- Zero Cleanup: Container disappears automatically + +**Perfect for:** + +- Container crashes or corruption +- Automated deployment pipelines +- Testing migrations safely +- Recovery from migration failures +- Ensuring clean migration runs + +## Maintenance & Cleanup + +```bash +# Build/rebuild Docker images +yarn docker:build + +# Clean up everything (containers, volumes, networks) +yarn docker:clean + +# Validate Docker setup +yarn docker:validate +``` + +### Getting Inside Containers + +```bash +# Access development backend (for debugging, running commands) +docker-compose -f docker-compose.dev.yml exec backend-dev sh + +# Access production backend (rarely needed) +docker-compose -f docker-compose.dev.yml exec backend sh + +# Access database (advanced users) +docker-compose -f docker-compose.dev.yml exec postgres bash +``` + +## Troubleshooting + +### "Command not found" or "docker: command not found" + +**Problem:** Docker isn't installed or not in PATH + +**Solution:** + +1. Install Docker Desktop +2. Restart your terminal/command prompt +3. Try `docker --version` to verify + +### "Port already in use" + +**Problem:** Another application is using ports 3000, 3001, 5432, or 8080 + +**Solution:** + +1. Find what's using the port: `netstat -ano | findstr :3000` (Windows) or `lsof -i :3000` (Mac/Linux) +2. Stop the conflicting application or change Docker ports in `docker-compose.dev.yml` + +### "No space left on device" + +**Problem:** Docker is using too much disk space + +**Solution:** + +```bash +# Clean up unused Docker resources +docker system prune -a +yarn docker:clean +``` + +### Migration Errors + +**Problem:** Database migrations failing + +**Solution:** + +1. Make sure you're using `backend-dev` (not `backend`) for migrations +2. Check database is healthy first +3. Verify migration files exist in `apps/backend/src/migrations/` + +**If regular migrations fail, try:** + +```bash +# Use isolated one-off container (most reliable) +yarn docker:migrate:oneoff + +# Or restart services and try again +yarn docker:restart +yarn docker:migrate:dev +``` + +## Development Workflow Tips + +### Production Testing + +```bash +# Start production backend alongside development +docker-compose -f docker-compose.dev.yml up -d backend + +# Test production at http://localhost:3000 +# Development still available at http://localhost:3001 +``` + +## Notes + +- Volumes keep Postgres data between restarts. Do not remove unless you want a fresh DB. +- Adminer runs in a container so it can reach the Postgres service using the internal Docker hostname `postgres`. + +### Security + +- This compose file is for development only. Replace default passwords and use secrets in production. diff --git a/apps/backend/Dockerfile b/apps/backend/Dockerfile new file mode 100644 index 00000000..f73de0d9 --- /dev/null +++ b/apps/backend/Dockerfile @@ -0,0 +1,39 @@ +# Simplified Dockerfile for NestJS backend +FROM node:20 AS build +WORKDIR /app + +# Copy package files +COPY package.json yarn.lock ./ +COPY apps/backend/package.json* ./apps/backend/ +COPY shared/package.json* ./shared/ + +# Install all dependencies +RUN yarn install --frozen-lockfile + +# Copy source code and build +COPY . . +RUN npx nx build backend + +# Production stage +FROM node:20-slim AS runtime +WORKDIR /app + +# Install only production dependencies +COPY package.json yarn.lock ./ +RUN yarn install --production --frozen-lockfile && yarn cache clean + +# Copy built application +COPY --from=build /app/dist/apps/backend ./dist + +# Create non-root user +RUN groupadd -g 1001 nodejs && useradd -r -u 1001 -g nodejs nestjs +RUN chown -R nestjs:nodejs /app +USER nestjs + +# Set environment +ENV NODE_ENV=production +ENV PORT=3000 + +EXPOSE 3000 + +CMD ["node", "dist/main.js"] diff --git a/apps/backend/src/app.controller.ts b/apps/backend/src/app.controller.ts index dff210a8..2550acd0 100644 --- a/apps/backend/src/app.controller.ts +++ b/apps/backend/src/app.controller.ts @@ -10,4 +10,14 @@ export class AppController { getData() { return this.appService.getData(); } + + @Get('health') + getHealth() { + return { + status: 'ok', + timestamp: new Date().toISOString(), + service: 'fcc-backend', + message: 'Service is UPPPP', + }; + } } diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 00000000..cfa4cf27 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,135 @@ +services: + # PostgreSQL Database + postgres: + image: postgres:15-alpine + restart: unless-stopped + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: fcc_dev + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro + networks: + - fcc-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d fcc_dev"] + interval: 10s + timeout: 5s + retries: 5 + + # NestJS Backend + backend: + build: + context: . + dockerfile: apps/backend/Dockerfile + target: runtime + restart: unless-stopped + environment: + NX_DB_HOST: postgres + NX_DB_PORT: 5432 + NX_DB_USERNAME: postgres + NX_DB_PASSWORD: postgres + NX_DB_DATABASE: fcc_dev + + NODE_ENV: development + PORT: 3000 + + # JWT and Auth (add secrets in prod) + JWT_SECRET: dev-secret-change-in-prod + + ports: + - "3000:3000" + depends_on: + postgres: + condition: service_healthy + networks: + - fcc-network + volumes: + # For development: mount source code for hot reload (optional) + # - ../../apps/backend/src:/app/src:ro + # - ../../apps/backend/dist:/app/dist + - backend_logs:/app/logs + # health check without wget dependency + # healthcheck: + # test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api || exit 1"] + # interval: 30s + # timeout: 10s + # retries: 3 + # start_period: 60s + + # NestJS Backend - Development + backend-dev: + build: + context: . + dockerfile: apps/backend/Dockerfile + target: build + restart: unless-stopped + environment: + NX_DB_HOST: postgres + NX_DB_PORT: 5432 + NX_DB_USERNAME: postgres + NX_DB_PASSWORD: postgres + NX_DB_DATABASE: fcc_dev + + NODE_ENV: development + PORT: 3001 + + # JWT and Auth (add secrets in prod) + JWT_SECRET: dev-secret-change-in-prod + + ports: + - "3001:3001" + depends_on: + postgres: + condition: service_healthy + networks: + - fcc-network + volumes: + - ./apps:/app/apps + - ./nx.json:/app/nx.json + - ./tsconfig.base.json:/app/tsconfig.base.json + - ./package.json:/app/package.json + - backend_logs:/app/logs + command: sh -c "cd /app && npm run start:dev:docker" + + # Adminer - Database Admin Tool + adminer: + image: adminer:4-standalone + restart: unless-stopped + ports: + - "8080:8080" + depends_on: + - postgres + networks: + - fcc-network + environment: + ADMINER_DEFAULT_SERVER: postgres + ADMINER_DESIGN: lucas + +volumes: + postgres_data: + driver: local + backend_logs: + driver: local + +networks: + fcc-network: + driver: bridge + + # E2E Testing (soon) + # e2e: + # build: + # context: . + # dockerfile: apps/frontend-e2e/Dockerfile + # depends_on: + # - backend + # - frontend + # networks: + # - fcc-network + # volumes: + # - ./apps/frontend-e2e/cypress/videos:/app/cypress/videos + # - ./apps/frontend-e2e/cypress/screenshots:/app/cypress/screenshots \ No newline at end of file diff --git a/package.json b/package.json index 4c063fa0..1e0c490a 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,21 @@ "migration:generate": "npm run typeorm -- migration:generate apps/backend/src/migrations/$npm_config_name -d apps/backend/src/data-source.ts", "migration:run": "npm run typeorm -- migration:run -d apps/backend/src/data-source.ts", "migration:revert": "npm run typeorm -- migration:revert -d apps/backend/src/data-source.ts", - "migration:create": "npm run typeorm -- migration:create apps/backend/src/migrations/$npm_config_name" + "migration:create": "npm run typeorm -- migration:create apps/backend/src/migrations/$npm_config_name", + "start:dev": "npx nx serve backend", + "start:dev:docker": "npx nodemon --watch apps/backend/src --ext ts --exec \"ts-node --project apps/backend/tsconfig.app.json -r tsconfig-paths/register apps/backend/src/main.ts\"", + "docker:build": "docker-compose -f docker-compose.dev.yml build", + "docker:up": "docker-compose -f docker-compose.dev.yml up -d", + "docker:up:dev": "docker-compose -f docker-compose.dev.yml up -d postgres adminer backend-dev", + "docker:up:all": "docker-compose -f docker-compose.dev.yml up -d", + "docker:down": "docker-compose -f docker-compose.dev.yml down", + "docker:logs": "docker-compose -f docker-compose.dev.yml logs -f", + "docker:restart": "npm run docker:down && npm run docker:up", + "docker:clean": "docker-compose -f docker-compose.dev.yml down -v --remove-orphans", + "docker:validate": "node scripts/validate-docker.js", + "docker:migrate": "docker-compose -f docker-compose.dev.yml exec backend npm run migration:run", + "docker:migrate:dev": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run migration:run", + "docker:migrate:oneoff": "docker build --file apps/backend/Dockerfile --target build -t fcc-backend-build . && docker run --rm --network fcc_fcc-network -e NX_DB_HOST=postgres -e NX_DB_PORT=5432 -e NX_DB_USERNAME=postgres -e NX_DB_PASSWORD=postgres -e NX_DB_DATABASE=fcc_dev fcc-backend-build npm run migration:run" }, "private": true, "dependencies": { @@ -77,6 +91,7 @@ "jest": "^29.4.1", "jsdom": "^22.1.0", "lint-staged": "^14.0.1", + "nodemon": "^3.0.1", "nx": "^16.8.1", "nx-cloud": "^16.4.0", "prettier": "^2.6.2", diff --git a/scripts/docker-dev.bat b/scripts/docker-dev.bat new file mode 100644 index 00000000..719401f2 --- /dev/null +++ b/scripts/docker-dev.bat @@ -0,0 +1,140 @@ +@echo off +REM Docker Development Helper for Windows +REM This script provides easy commands for Docker development + +setlocal enabledelayedexpansion + +REM Define colors (Windows) +set "GREEN=[92m" +set "YELLOW=[93m" +set "RED=[91m" +set "NC=[0m" + +REM Helper functions +:print_status +echo %GREEN%[INFO]%NC% %~1 +goto :eof + +:print_warning +echo %YELLOW%[WARNING]%NC% %~1 +goto :eof + +:print_error +echo %RED%[ERROR]%NC% %~1 +goto :eof + +REM Check if Docker is running +:check_docker +docker info >nul 2>&1 +if %errorlevel% neq 0 ( + call :print_error "Docker is not running. Please start Docker Desktop." + echo. + echo To install Docker Desktop: + echo 1. Download from https://www.docker.com/products/docker-desktop + echo 2. Install and restart your computer + echo 3. Start Docker Desktop + echo 4. Wait for Docker to be ready (check system tray icon) + echo. + pause + exit /b 1 +) +goto :eof + +REM Setup environment file +:setup_env +if not exist .env.docker ( + call :print_status "Creating .env.docker from template..." + copy .env.docker.example .env.docker >nul + call :print_warning "Please review and update .env.docker with your configuration" +) +goto :eof + +REM Build images +:build +call :print_status "Building Docker images..." +docker-compose -f docker-compose.dev.yml build --no-cache +goto :eof + +REM Start services +:up +call :print_status "Starting development services..." +call :setup_env +docker-compose -f docker-compose.dev.yml up -d +call :print_status "Services started! Backend: http://localhost:3000/api" +call :print_status "Database admin: http://localhost:8080 (user: postgres, pass: postgres, server: postgres)" +goto :eof + +REM Stop services +:down +call :print_status "Stopping development services..." +docker-compose -f docker-compose.dev.yml down +goto :eof + +REM Restart services +:restart +call :print_status "Restarting development services..." +call :down +call :up +goto :eof + +REM View logs +:logs +set service=%~1 +if "%service%"=="" set service=backend +call :print_status "Showing logs for %service%..." +docker-compose -f docker-compose.dev.yml logs -f %service% +goto :eof + +REM Run migrations +:migrate +call :print_status "Running database migrations..." +docker-compose -f docker-compose.dev.yml exec backend sh -c "cd /app && npm run migration:run" +goto :eof + +REM Show status +:status +call :print_status "Docker services status:" +docker-compose -f docker-compose.dev.yml ps +goto :eof + +REM Main script logic +if "%1"=="build" ( + call :check_docker + call :build +) else if "%1"=="up" ( + call :check_docker + call :up +) else if "%1"=="down" ( + call :down +) else if "%1"=="restart" ( + call :check_docker + call :restart +) else if "%1"=="logs" ( + call :logs %2 +) else if "%1"=="migrate" ( + call :migrate +) else if "%1"=="status" ( + call :status +) else ( + echo Docker Development Helper for Windows + echo. + echo Usage: %0 {command} + echo. + echo Commands: + echo build Build Docker images + echo up Start development services + echo down Stop development services + echo restart Restart development services + echo logs [service] Show logs (default: backend) + echo migrate Run database migrations + echo status Show services status + echo. + echo Examples: + echo %0 up Start all services + echo %0 logs backend Show backend logs + echo %0 migrate Run migrations + echo. + echo Prerequisites: + echo - Docker Desktop installed and running + echo - Download from: https://www.docker.com/products/docker-desktop +) diff --git a/scripts/docker-dev.sh b/scripts/docker-dev.sh new file mode 100644 index 00000000..69e97831 --- /dev/null +++ b/scripts/docker-dev.sh @@ -0,0 +1,187 @@ +#!/bin/bash + +# Docker Development Helper Script +# This script provides easy commands for Docker development + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Helper function to print colored output +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to check if Docker is running +check_docker() { + if ! docker info > /dev/null 2>&1; then + print_error "Docker is not running. Please start Docker Desktop." + exit 1 + fi +} + +# Function to setup environment file +setup_env() { + if [ ! -f .env.docker ]; then + print_status "Creating .env.docker from template..." + cp .env.docker.example .env.docker + print_warning "Please review and update .env.docker with your configuration" + fi +} + +# Function to build images +build() { + print_status "Building Docker images..." + docker-compose -f docker-compose.dev.yml build --no-cache +} + +# Function to start services +up() { + print_status "Starting development services..." + setup_env + docker-compose -f docker-compose.dev.yml up -d + print_status "Services started! Backend: http://localhost:3000/api" + print_status "Database admin: http://localhost:8080 (user: postgres, pass: postgres, server: postgres)" +} + +# Function to stop services +down() { + print_status "Stopping development services..." + docker-compose -f docker-compose.dev.yml down +} + +# Function to restart services +restart() { + print_status "Restarting development services..." + down + up +} + +# Function to view logs +logs() { + service=${1:-backend} + print_status "Showing logs for $service..." + docker-compose -f docker-compose.dev.yml logs -f "$service" +} + +# Function to run migrations +migrate() { + print_status "Running database migrations..." + docker-compose -f docker-compose.dev.yml exec backend sh -c "cd /app && npm run migration:run" +} + +# Function to generate migration +migrate_generate() { + if [ -z "$1" ]; then + print_error "Please provide a migration name: ./docker-dev.sh migrate:generate add_users" + exit 1 + fi + print_status "Generating migration: $1" + docker-compose -f docker-compose.dev.yml exec backend sh -c "cd /app && npm run migration:generate --name=$1" +} + +# Function to run backend shell +shell() { + print_status "Opening shell in backend container..." + docker-compose -f docker-compose.dev.yml exec backend sh +} + +# Function to run tests +test() { + service=${1:-backend} + print_status "Running tests for $service..." + docker-compose -f docker-compose.dev.yml exec "$service" sh -c "cd /app && npm run test:$service" +} + +# Function to clean up everything +clean() { + print_warning "This will remove all containers, volumes, and images. Are you sure? (y/N)" + read -r response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then + print_status "Cleaning up Docker resources..." + docker-compose -f docker-compose.dev.yml down -v --remove-orphans + docker system prune -f + print_status "Cleanup complete!" + fi +} + +# Function to show status +status() { + print_status "Docker services status:" + docker-compose -f docker-compose.dev.yml ps +} + +# Main script logic +case "$1" in + "build") + check_docker + build + ;; + "up") + check_docker + up + ;; + "down") + down + ;; + "restart") + check_docker + restart + ;; + "logs") + logs "$2" + ;; + "migrate") + migrate + ;; + "migrate:generate") + migrate_generate "$2" + ;; + "shell") + shell + ;; + "test") + test "$2" + ;; + "clean") + clean + ;; + "status") + status + ;; + *) + echo "Docker Development Helper" + echo "" + echo "Usage: $0 {command}" + echo "" + echo "Commands:" + echo " build Build Docker images" + echo " up Start development services" + echo " down Stop development services" + echo " restart Restart development services" + echo " logs [service] Show logs (default: backend)" + echo " migrate Run database migrations" + echo " migrate:generate Generate new migration" + echo " shell Open shell in backend container" + echo " test [service] Run tests (default: backend)" + echo " status Show services status" + echo " clean Clean up all Docker resources" + echo "" + echo "Examples:" + echo " $0 up # Start all services" + echo " $0 logs backend # Show backend logs" + echo " $0 migrate:generate add_users # Generate migration" + ;; +esac diff --git a/scripts/init-db.sql b/scripts/init-db.sql new file mode 100644 index 00000000..dfdbe21f --- /dev/null +++ b/scripts/init-db.sql @@ -0,0 +1,43 @@ +-- Database initialization script +-- This script runs when the PostgreSQL container starts for the first time + +-- Create user first if not exists +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'fcc_user') THEN + CREATE USER fcc_user WITH PASSWORD 'fcc_password'; + END IF; +END +$$; + +-- Create the main database if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'fcc_dev') THEN + CREATE DATABASE fcc_dev OWNER fcc_user; + END IF; +END +$$; + +-- Create a test database for running tests +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'fcc_test') THEN + CREATE DATABASE fcc_test OWNER fcc_user; + END IF; +END +$$; + +-- Grant permissions +GRANT ALL PRIVILEGES ON DATABASE fcc_dev TO fcc_user; +GRANT ALL PRIVILEGES ON DATABASE fcc_test TO fcc_user; + +-- Enable necessary PostgreSQL extensions +\c fcc_dev; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +\c fcc_test; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- Log completion +\echo 'Database initialization completed!' diff --git a/yarn.lock b/yarn.lock index 75ce8f81..8f3f2bc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4795,6 +4795,21 @@ chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.5.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -5451,6 +5466,13 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" @@ -7174,6 +7196,11 @@ ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + ignore@^5.0.4, ignore@^5.1.9, ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" @@ -8860,7 +8887,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -8986,6 +9013,22 @@ node-releases@^2.0.13: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +nodemon@^3.0.1: + version "3.1.10" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1" + integrity sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw== + dependencies: + chokidar "^3.5.2" + debug "^4" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -10015,6 +10058,11 @@ psl@^1.1.33: resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -10685,6 +10733,13 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + sirv@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.3.tgz#ca5868b87205a74bef62a469ed0296abceccd446" @@ -11066,7 +11121,7 @@ stylus@^0.59.0: sax "~1.2.4" source-map "^0.7.3" -supports-color@^5.3.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -11272,6 +11327,11 @@ totalist@^3.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== +touch@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" + integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== + tough-cookie@^4.1.2, tough-cookie@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" @@ -11570,6 +11630,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" From 38cd27ec2b78eabda8fc7b17b8f9f02c176befd5 Mon Sep 17 00:00:00 2001 From: thaninbew Date: Sat, 13 Sep 2025 20:21:38 -0400 Subject: [PATCH 02/11] hot reloading --- apps/backend/src/app.controller.ts | 4 +++- apps/backend/src/app.module.ts | 9 ++++++-- apps/backend/src/auth/auth.controller.spec.ts | 21 +++++++++++++++++++ apps/backend/src/data-source.ts | 4 ++-- package.json | 2 +- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/apps/backend/src/app.controller.ts b/apps/backend/src/app.controller.ts index 2550acd0..d0c1e7d1 100644 --- a/apps/backend/src/app.controller.ts +++ b/apps/backend/src/app.controller.ts @@ -17,7 +17,9 @@ export class AppController { status: 'ok', timestamp: new Date().toISOString(), service: 'fcc-backend', - message: 'Service is UPPPP', + message: 'Real-time hot reload test!', + version: '3.0', + test: 'live-update', }; } } diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts index 54fb044e..b5fd0d30 100644 --- a/apps/backend/src/app.module.ts +++ b/apps/backend/src/app.module.ts @@ -3,11 +3,16 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { TaskModule } from './task/task.module'; +import { UsersModule } from './users/users.module'; +import { AuthModule } from './auth/auth.module'; import AppDataSource from './data-source'; @Module({ - imports: [TypeOrmModule.forRoot(AppDataSource.options), TaskModule], + imports: [ + TypeOrmModule.forRoot(AppDataSource.options), + UsersModule, + AuthModule, + ], controllers: [AppController], providers: [AppService], }) diff --git a/apps/backend/src/auth/auth.controller.spec.ts b/apps/backend/src/auth/auth.controller.spec.ts index 27a31e61..0b6b00ba 100644 --- a/apps/backend/src/auth/auth.controller.spec.ts +++ b/apps/backend/src/auth/auth.controller.spec.ts @@ -1,12 +1,33 @@ import { Test, TestingModule } from '@nestjs/testing'; import { AuthController } from './auth.controller'; +import { AuthService } from './auth.service'; +import { UsersService } from '../users/users.service'; describe('AuthController', () => { let controller: AuthController; + // Create mock implementations + const mockAuthService = { + signup: jest.fn(), + }; + + const mockUsersService = { + create: jest.fn(), + }; + beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [AuthController], + providers: [ + { + provide: AuthService, + useValue: mockAuthService, + }, + { + provide: UsersService, + useValue: mockUsersService, + }, + ], }).compile(); controller = module.get(AuthController); diff --git a/apps/backend/src/data-source.ts b/apps/backend/src/data-source.ts index 4cd06624..ec2b5c5b 100644 --- a/apps/backend/src/data-source.ts +++ b/apps/backend/src/data-source.ts @@ -1,6 +1,6 @@ import { DataSource } from 'typeorm'; import { PluralNamingStrategy } from './strategies/plural-naming.strategy'; -import { Task } from './task/types/task.entity'; +import { User } from './users/user.entity'; import * as dotenv from 'dotenv'; dotenv.config(); @@ -12,7 +12,7 @@ const AppDataSource = new DataSource({ username: process.env.NX_DB_USERNAME, password: process.env.NX_DB_PASSWORD, database: process.env.NX_DB_DATABASE, - entities: [Task], + entities: [User], migrations: ['apps/backend/src/migrations/*.js'], // Setting synchronize: true shouldn't be used in production - otherwise you can lose production data synchronize: false, diff --git a/package.json b/package.json index a346c86b..2c5a64a5 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "migration:create": "npm run typeorm -- migration:create apps/backend/src/migrations/$npm_config_name", "test": "jest", "start:dev": "npx nx serve backend", - "start:dev:docker": "npx nodemon --watch apps/backend/src --ext ts --exec \"ts-node --project apps/backend/tsconfig.app.json -r tsconfig-paths/register apps/backend/src/main.ts\"", + "start:dev:docker": "npx nodemon --watch apps/backend/src --ext ts --legacy-watch --poll-interval 1000 --exec \"ts-node --project apps/backend/tsconfig.app.json -r tsconfig-paths/register apps/backend/src/main.ts\"", "docker:build": "docker-compose -f docker-compose.dev.yml build", "docker:up": "docker-compose -f docker-compose.dev.yml up -d", "docker:up:dev": "docker-compose -f docker-compose.dev.yml up -d postgres adminer backend-dev", From a75f7914c09c67ecc7e5c6819c9a822412c737b1 Mon Sep 17 00:00:00 2001 From: thaninbew Date: Sat, 13 Sep 2025 21:00:51 -0400 Subject: [PATCH 03/11] new PR template --- .github/pull_request_template.md | 39 +++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ed7ce673..dc7f0212 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,22 +1,35 @@ -### â„šī¸ Issue +## Description -Closes +Briefly describe the changes and why they are needed. -### 📝 Description +## Changes Made -Write a short summary of what you added. Why is it important? Any member of C4C should be able to read this and understand your contribution -- not just your team members. +- [ ] Backend changes +- [ ] Frontend changes +- [ ] Database schema changes +- [ ] Configuration updates +- [ ] Other -Briefly list the changes made to the code: -1. Added support for this. -2. And removed redunant use of that. -3. Also this was included for reasons. +## Testing -### âœ”ī¸ Verification +- [ ] Unit tests pass +- [ ] Manual testing completed +- [ ] No breaking changes -What steps did you take to verify your changes work? These should be clear enough for someone to be able to clone the branch and follow the steps themselves. +## Screenshots (if relevant) -Provide screenshots of any new components, styling changes, or pages. + -### đŸ•ī¸ (Optional) Future Work / Notes +## Related Issues -Did you notice anything ugly during the course of this ticket? Any bugs, design challenges, or unexpected behavior? Write it down so we can clean it up in a future ticket! +Closes # + +## Checklist + +- [ ] Code follows project standards +- [ ] Documentation updated if needed +- [ ] Ready for review + +## Notes + + From 248d0bef3f3cb4603b4b28507f2ed2aea49b857e Mon Sep 17 00:00:00 2001 From: thaninbew Date: Sat, 13 Sep 2025 21:05:34 -0400 Subject: [PATCH 04/11] update pr pull_request_template --- .github/pull_request_template.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index dc7f0212..1061d42a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -10,26 +10,25 @@ Briefly describe the changes and why they are needed. - [ ] Configuration updates - [ ] Other -## Testing +## Testing & Verification - [ ] Unit tests pass - [ ] Manual testing completed - [ ] No breaking changes +**Verification Steps:** + + + ## Screenshots (if relevant) -## Related Issues - -Closes # +## Future Improvements/Notes -## Checklist + + -- [ ] Code follows project standards -- [ ] Documentation updated if needed -- [ ] Ready for review - -## Notes +## Related Issues - +Closes # From 031d549d3c39c7427eaed7df56cc329b9d442183 Mon Sep 17 00:00:00 2001 From: thaninbew Date: Sun, 14 Sep 2025 22:48:20 -0400 Subject: [PATCH 05/11] fix migrate command --- DOCKER.md | 9 --------- package.json | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/DOCKER.md b/DOCKER.md index 5c07ee93..5020e122 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -180,9 +180,6 @@ yarn docker:migrate:dev # Alternative: Run migrations on production backend (not recommended for dev) yarn docker:migrate - -# Run migrations in isolated container (advanced) -yarn docker:migrate:oneoff ``` ### Why One-off Migrations Are Powerful @@ -228,9 +225,6 @@ yarn docker:build # Clean up everything (containers, volumes, networks) yarn docker:clean - -# Validate Docker setup -yarn docker:validate ``` ### Getting Inside Containers @@ -292,9 +286,6 @@ yarn docker:clean **If regular migrations fail, try:** ```bash -# Use isolated one-off container (most reliable) -yarn docker:migrate:oneoff - # Or restart services and try again yarn docker:restart yarn docker:migrate:dev diff --git a/package.json b/package.json index 2c5a64a5..06c7e15d 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,10 @@ "docker:logs": "docker-compose -f docker-compose.dev.yml logs -f", "docker:restart": "npm run docker:down && npm run docker:up", "docker:clean": "docker-compose -f docker-compose.dev.yml down -v --remove-orphans", - "docker:validate": "node scripts/validate-docker.js", "docker:migrate": "docker-compose -f docker-compose.dev.yml exec backend npm run migration:run", "docker:migrate:dev": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run migration:run", - "docker:migrate:oneoff": "docker build --file apps/backend/Dockerfile --target build -t fcc-backend-build . && docker run --rm --network fcc_fcc-network -e NX_DB_HOST=postgres -e NX_DB_PORT=5432 -e NX_DB_USERNAME=postgres -e NX_DB_PASSWORD=postgres -e NX_DB_DATABASE=fcc_dev fcc-backend-build npm run migration:run" + "docker:migrate:status": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run typeorm -- migration:show -d apps/backend/src/data-source.ts", + "docker:migrate:revert": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run migration:revert" }, "private": true, "dependencies": { From 4f28b32e74c63d9a2254500caa3bc0d18d4a2226 Mon Sep 17 00:00:00 2001 From: thaninbew Date: Mon, 15 Sep 2025 17:12:45 -0400 Subject: [PATCH 06/11] fix proxy file --- apps/frontend/proxy.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/proxy.conf.json b/apps/frontend/proxy.conf.json index 63dd6275..84c3f18e 100644 --- a/apps/frontend/proxy.conf.json +++ b/apps/frontend/proxy.conf.json @@ -1,6 +1,6 @@ { "/api": { - "target": "http://localhost:3000", + "target": "http://localhost:3001", "secure": false } } From 0a675a9feea04fcc6538ae6c96b7a61b9c3af148 Mon Sep 17 00:00:00 2001 From: thaninbew Date: Mon, 15 Sep 2025 23:56:44 -0400 Subject: [PATCH 07/11] fix docker command --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 06c7e15d..aa86cbf0 100644 --- a/package.json +++ b/package.json @@ -18,18 +18,18 @@ "test": "jest", "start:dev": "npx nx serve backend", "start:dev:docker": "npx nodemon --watch apps/backend/src --ext ts --legacy-watch --poll-interval 1000 --exec \"ts-node --project apps/backend/tsconfig.app.json -r tsconfig-paths/register apps/backend/src/main.ts\"", - "docker:build": "docker-compose -f docker-compose.dev.yml build", - "docker:up": "docker-compose -f docker-compose.dev.yml up -d", - "docker:up:dev": "docker-compose -f docker-compose.dev.yml up -d postgres adminer backend-dev", - "docker:up:all": "docker-compose -f docker-compose.dev.yml up -d", - "docker:down": "docker-compose -f docker-compose.dev.yml down", - "docker:logs": "docker-compose -f docker-compose.dev.yml logs -f", + "docker:build": "docker compose -f docker-compose.dev.yml build", + "docker:up": "docker compose -f docker-compose.dev.yml up -d", + "docker:up:dev": "docker compose -f docker-compose.dev.yml up -d postgres adminer backend-dev", + "docker:up:all": "docker compose -f docker-compose.dev.yml up -d", + "docker:down": "docker compose -f docker-compose.dev.yml down", + "docker:logs": "docker compose -f docker-compose.dev.yml logs -f", "docker:restart": "npm run docker:down && npm run docker:up", - "docker:clean": "docker-compose -f docker-compose.dev.yml down -v --remove-orphans", - "docker:migrate": "docker-compose -f docker-compose.dev.yml exec backend npm run migration:run", - "docker:migrate:dev": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run migration:run", - "docker:migrate:status": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run typeorm -- migration:show -d apps/backend/src/data-source.ts", - "docker:migrate:revert": "docker-compose -f docker-compose.dev.yml exec backend-dev npm run migration:revert" + "docker:clean": "docker compose -f docker-compose.dev.yml down -v --remove-orphans", + "docker:migrate": "docker compose -f docker-compose.dev.yml exec backend npm run migration:run", + "docker:migrate:dev": "docker compose -f docker-compose.dev.yml exec backend-dev npm run migration:run", + "docker:migrate:status": "docker compose -f docker-compose.dev.yml exec backend-dev npm run typeorm -- migration:show -d apps/backend/src/data-source.ts", + "docker:migrate:revert": "docker compose -f docker-compose.dev.yml exec backend-dev npm run migration:revert" }, "private": true, "dependencies": { From 0c4e0af3ea22b2181ba07b57459415b293435a3c Mon Sep 17 00:00:00 2001 From: Sam Nie <147653722+SamNie2027@users.noreply.github.com> Date: Mon, 22 Sep 2025 18:47:53 -0400 Subject: [PATCH 08/11] Initialized donation entity --- apps/backend/src/donations/donation.entity.ts | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 apps/backend/src/donations/donation.entity.ts diff --git a/apps/backend/src/donations/donation.entity.ts b/apps/backend/src/donations/donation.entity.ts new file mode 100644 index 00000000..0e8de5d0 --- /dev/null +++ b/apps/backend/src/donations/donation.entity.ts @@ -0,0 +1,59 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + + +export enum donationType { + 'one_time', + 'recurring', +} + + +@Entity() +export class Donation { + @PrimaryGeneratedColumn('identity', { + generatedIdentity: 'ALWAYS', + }) + id: number; + + + @Column() + firstName: string; + + + @Column() + lastName: string; + + + @Column() + email: string; + + + @Column({ type: 'numeric', precision: 10, scale: 2 }) + amount: number; + + + @Column({ default: false }) + isAnonymous: boolean; + + + @Column() + donationType: donationType; + + + @Column({ nullable: true }) + recurringInterval: 'monthly' | 'yearly' | 'weekly' | 'bimonthly' | 'biweekly'; + + + @Column({ nullable: true }) + dedicationMessage: string; + + + @Column() + createdAt: Date; + + + @Column() + updatedAt: Date; +} + + + From 6ec89505811c0b7db472a55757dbc4a6317ed610 Mon Sep 17 00:00:00 2001 From: Sam Nie <147653722+SamNie2027@users.noreply.github.com> Date: Mon, 22 Sep 2025 18:50:30 -0400 Subject: [PATCH 09/11] Merging main's changes --- apps/backend/src/donations/donation.entity.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/apps/backend/src/donations/donation.entity.ts b/apps/backend/src/donations/donation.entity.ts index 0e8de5d0..df478e82 100644 --- a/apps/backend/src/donations/donation.entity.ts +++ b/apps/backend/src/donations/donation.entity.ts @@ -1,12 +1,10 @@ import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; - export enum donationType { 'one_time', 'recurring', } - @Entity() export class Donation { @PrimaryGeneratedColumn('identity', { @@ -14,46 +12,33 @@ export class Donation { }) id: number; - @Column() firstName: string; - @Column() lastName: string; - @Column() email: string; - @Column({ type: 'numeric', precision: 10, scale: 2 }) amount: number; - @Column({ default: false }) isAnonymous: boolean; - @Column() donationType: donationType; - @Column({ nullable: true }) recurringInterval: 'monthly' | 'yearly' | 'weekly' | 'bimonthly' | 'biweekly'; - @Column({ nullable: true }) dedicationMessage: string; - @Column() createdAt: Date; - @Column() updatedAt: Date; } - - - From f5383e70ed0bc017cbfad8d908d6971a4417ff09 Mon Sep 17 00:00:00 2001 From: Sam Nie <147653722+SamNie2027@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:04:58 -0400 Subject: [PATCH 10/11] Update data-source.ts with donation entity --- apps/backend/src/data-source.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/backend/src/data-source.ts b/apps/backend/src/data-source.ts index 4cd06624..d7486ef6 100644 --- a/apps/backend/src/data-source.ts +++ b/apps/backend/src/data-source.ts @@ -1,6 +1,7 @@ import { DataSource } from 'typeorm'; import { PluralNamingStrategy } from './strategies/plural-naming.strategy'; import { Task } from './task/types/task.entity'; +import { Donation } from './donations/donation.entity'; import * as dotenv from 'dotenv'; dotenv.config(); @@ -12,8 +13,8 @@ const AppDataSource = new DataSource({ username: process.env.NX_DB_USERNAME, password: process.env.NX_DB_PASSWORD, database: process.env.NX_DB_DATABASE, - entities: [Task], - migrations: ['apps/backend/src/migrations/*.js'], + entities: [Task, Donation], + migrations: ['apps/backend/src/migrations/*.js', 'apps/backend/src/migrations/*-add_donations.ts'], // Setting synchronize: true shouldn't be used in production - otherwise you can lose production data synchronize: false, namingStrategy: new PluralNamingStrategy(), From 8e594f5fcaedad97030bd73b8673af1ae60742a9 Mon Sep 17 00:00:00 2001 From: Sam Nie <147653722+SamNie2027@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:34:06 -0400 Subject: [PATCH 11/11] Add donations migration --- .../migrations/1758917198934-add_donations.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 apps/backend/src/migrations/1758917198934-add_donations.ts diff --git a/apps/backend/src/migrations/1758917198934-add_donations.ts b/apps/backend/src/migrations/1758917198934-add_donations.ts new file mode 100644 index 00000000..c2e74764 --- /dev/null +++ b/apps/backend/src/migrations/1758917198934-add_donations.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddDonations1758917198934 implements MigrationInterface { + name = 'AddDonations1758917198934'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "donations" ("id" integer GENERATED ALWAYS AS IDENTITY NOT NULL, "firstName" character varying NOT NULL, "lastName" character varying NOT NULL, "email" character varying NOT NULL, "amount" numeric(10,2) NOT NULL, "isAnonymous" boolean NOT NULL DEFAULT false, "donationType" integer NOT NULL, "recurringInterval" character varying, "dedicationMessage" character varying, "createdAt" TIMESTAMP NOT NULL, "updatedAt" TIMESTAMP NOT NULL, CONSTRAINT "PK_c01355d6f6f50fc6d1b4a946abf" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TABLE "users" ("id" integer NOT NULL, "status" character varying NOT NULL, "firstName" character varying NOT NULL, "lastName" character varying NOT NULL, "email" character varying NOT NULL, CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "users"`); + await queryRunner.query(`DROP TABLE "donations"`); + } +}