diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..4927283 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,65 @@ +name: Build and Test + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run linting + run: npm run lint + + - name: Build frontend + run: npm run build + + - name: Build API + run: npm run build:api + + docker-build: + runs-on: ubuntu-latest + needs: test + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build frontend Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: false + tags: scriptshare-frontend:latest + + - name: Build API Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile.api + push: false + tags: scriptshare-api:latest + + - name: Test Docker containers + run: | + # Test that images were built successfully + docker images | grep scriptshare diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index cfa5b87..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Deploy to DigitalOcean - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - # Test job to run before deployment - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run linter - run: npm run lint - - - name: Build frontend - run: npm run build - env: - VITE_APP_NAME: ScriptShare - VITE_APP_URL: https://scriptshare.example.com - VITE_ANALYTICS_ENABLED: true - - # Deploy job (only on main branch) - deploy: - needs: test - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - - steps: - - uses: actions/checkout@v4 - - - name: Install doctl - uses: digitalocean/action-doctl@v2 - with: - token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} - - - name: Get app info - id: app-info - run: | - APP_ID=$(doctl apps list --format ID,Spec.Name --no-header | grep scriptshare | cut -d' ' -f1) - echo "app-id=$APP_ID" >> $GITHUB_OUTPUT - - - name: Trigger deployment - run: | - doctl apps create-deployment ${{ steps.app-info.outputs.app-id }} --wait - - - name: Run database migrations - run: | - # Wait for deployment to complete - sleep 60 - - # Run migrations via the app console (if needed) - echo "Deployment completed. Please run database migrations manually if this is the first deployment." - echo "Command: npm run db:setup:prod" - - # Database migration job (manual trigger) - migrate: - runs-on: ubuntu-latest - if: github.event_name == 'workflow_dispatch' - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run migrations - run: npm run db:migrate:prod - env: - DATABASE_URL: ${{ secrets.DATABASE_URL }} - -# Manual workflow dispatch for running migrations -on: - workflow_dispatch: - inputs: - action: - description: 'Action to perform' - required: true - default: 'migrate' - type: choice - options: - - migrate - - setup diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 539c2bd..96b3797 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,248 +1,261 @@ -# DigitalOcean Deployment Guide +# πŸš€ ScriptShare - Platform Deployment Guide -This guide walks you through deploying ScriptShare to DigitalOcean App Platform with a managed MySQL database. +## Overview -## Prerequisites +ScriptShare is a modern React application with a Node.js API backend, designed to work seamlessly with any deployment platform including **Vercel**, **Coolify**, **DigitalOcean App Platform**, **Railway**, **Render**, and others. -- DigitalOcean account -- GitHub repository containing your code -- Basic familiarity with DigitalOcean App Platform +## πŸ“¦ Application Structure -## Architecture Overview +### Frontend (React + Vite) +- **Dockerfile**: `Dockerfile` +- **Build**: Vite-based React application +- **Output**: Static files served by Nginx +- **Port**: 80 -The deployment consists of: -- **Frontend**: Static site (React/Vite build) -- **Backend API**: Node.js service with Express -- **Database**: DigitalOcean Managed MySQL Database +### Backend API (Node.js + Express) +- **Dockerfile**: `Dockerfile.api` +- **Runtime**: Node.js 18 with TypeScript +- **Port**: 3000 +- **Health Check**: `/api/health` -## Step 1: Prepare Your Repository +## πŸ”§ Deployment Options -1. Ensure all the deployment files are in your GitHub repository: +### Option 1: Vercel (Recommended for Frontend) + +**Frontend Deployment:** +1. Connect your repository to Vercel +2. Set build command: `npm run build` +3. Set output directory: `dist` +4. Configure environment variables: ``` - .do/app.yaml # App Platform configuration - Dockerfile.api # Backend API container - drizzle.config.production.ts # Production DB config - scripts/migrate-production.js # Migration script - scripts/setup-production-db.js # DB setup script - env.production.example # Environment variables template + VITE_APP_NAME=ScriptShare + VITE_APP_URL=https://your-domain.vercel.app + VITE_ANALYTICS_ENABLED=true ``` -2. Commit and push all changes to your main branch. +**API Deployment:** +- Deploy API separately to platforms like Railway, Render, or DigitalOcean +- Or use Vercel Functions (requires code modification) -## Step 2: Create the DigitalOcean App +### Option 2: Coolify (Full Stack) -### Option A: Using the DigitalOcean Console +**Deploy both frontend and API:** +1. Create application from Git repository +2. **Frontend**: + - Use `Dockerfile` + - Port: 80 +3. **API**: + - Use `Dockerfile.api` + - Port: 3000 +4. Configure environment variables -1. Go to the [DigitalOcean App Platform](https://cloud.digitalocean.com/apps) -2. Click **"Create App"** -3. Choose **"GitHub"** as your source -4. Select your repository and branch (usually `main`) -5. DigitalOcean will automatically detect the `app.yaml` configuration +### Option 3: DigitalOcean App Platform -### Option B: Using the CLI +Create `app.yaml`: +```yaml +name: scriptshare +services: +- name: frontend + source_dir: / + dockerfile_path: Dockerfile + github: + repo: your-username/scriptshare-cursor + branch: main + http_port: 80 + routes: + - path: / +- name: api + source_dir: / + dockerfile_path: Dockerfile.api + github: + repo: your-username/scriptshare-cursor + branch: main + http_port: 3000 + routes: + - path: /api + envs: + - key: NODE_ENV + value: production + - key: DATABASE_URL + value: ${DATABASE_URL} +databases: +- name: scriptshare-db + engine: MYSQL + version: "8" +``` +### Option 4: Railway + +1. **Frontend**: Connect repo, Railway auto-detects Dockerfile +2. **API**: Deploy from same repo using `Dockerfile.api` +3. **Database**: Add MySQL service +4. Configure environment variables + +### Option 5: Render + +1. **Frontend**: + - Static Site + - Build Command: `npm run build` + - Publish Directory: `dist` +2. **API**: + - Web Service + - Docker build using `Dockerfile.api` +3. **Database**: Add MySQL database + +## πŸ—οΈ Build Commands + +### Frontend ```bash -# Install doctl CLI -# On macOS: brew install doctl -# On Linux: snap install doctl +# Install dependencies +npm install -# Authenticate -doctl auth init +# Build for production +npm run build -# Create the app -doctl apps create --spec .do/app.yaml +# Preview build +npm run preview ``` -## Step 3: Configure Environment Variables - -In the DigitalOcean dashboard, go to your app's Settings > Environment Variables and set: - -### Required Variables -``` -JWT_SECRET=your-super-secret-jwt-key-here-change-this-in-production -ADMIN_EMAIL=admin@yourcompany.com -ADMIN_USERNAME=admin -ADMIN_PASSWORD=your-secure-password -``` - -### Optional Variables -``` -VITE_ANALYTICS_ENABLED=true -RATE_LIMIT_ENABLED=true -RATE_LIMIT_WINDOW_MS=900000 -RATE_LIMIT_MAX_REQUESTS=100 -``` - -⚠️ **Security Note**: Generate a strong JWT secret: +### API ```bash -node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" +# Install dependencies +npm install + +# Build TypeScript +npm run build:api + +# Start API server +npm run start:api ``` -## Step 4: Database Setup +## πŸ” Environment Variables -The managed MySQL database will be automatically created. After the first deployment: +### Frontend (Build-time) +- `VITE_APP_NAME` - Application name +- `VITE_APP_URL` - Frontend URL +- `VITE_ANALYTICS_ENABLED` - Enable analytics (true/false) -1. **Run Database Migrations**: - ```bash - # In your app's console (or via GitHub Actions) - npm run db:setup:prod - ``` +### API (Runtime) +- `NODE_ENV` - Environment (production/development) +- `PORT` - Server port (default: 3000) +- `DATABASE_URL` - MySQL connection string +- `JWT_SECRET` - JWT secret key +- `CORS_ORIGIN` - Allowed CORS origins -2. **Verify Database Connection**: - Check the API health endpoint: `https://your-api-url/api/health` +## πŸ—„οΈ Database Setup -## Step 5: Update App Configuration - -1. **Update Frontend URLs**: After deployment, update the environment variables with actual URLs: - ``` - VITE_APP_URL=https://your-frontend-url.ondigitalocean.app - VITE_API_URL=https://your-api-url.ondigitalocean.app/api - CORS_ORIGIN=https://your-frontend-url.ondigitalocean.app - ``` - -2. **Redeploy**: The app will automatically redeploy when you change environment variables. - -## Step 6: Custom Domain (Optional) - -1. In your app settings, go to **Domains** -2. Click **Add Domain** -3. Enter your domain name -4. Configure DNS records as instructed - -## Database Management - -### Connecting to the Database +### MySQL Connection String Format: +``` +DATABASE_URL=mysql://username:password@host:port/database +``` +### Required Tables: +The application uses Drizzle ORM. Run migrations after deployment: ```bash -# Get connection string from DigitalOcean dashboard -mysql -h your-db-host -P 25060 -u your-username -p your-database-name --ssl-mode=REQUIRED +npm run db:migrate ``` -### Running Migrations +## πŸ” Health Checks +### Frontend Health Check: +``` +GET /health +``` + +### API Health Check: +``` +GET /api/health +``` + +## πŸ“ Platform-Specific Notes + +### Vercel +- Frontend deploys automatically +- Use Vercel Functions for API (requires modification) +- Environment variables in Vercel dashboard + +### Coolify +- Supports full Docker deployment +- Easy environment variable management +- Built-in SSL and domain management + +### DigitalOcean App Platform +- Use `app.yaml` for configuration +- Automatic HTTPS +- Managed database available + +### Railway +- Auto-deployment from Git +- Environment variables in dashboard +- Add-on database services + +### Render +- Separate frontend (static) and backend (web service) +- Auto-deployment from Git +- Environment variables in dashboard + +## 🐳 Docker Commands + +### Build Frontend: ```bash -# Production migration -npm run db:migrate:prod - -# Create new migration -npm run db:generate +docker build -t scriptshare-frontend . +docker run -p 3000:80 scriptshare-frontend ``` -### Backup and Restore - -DigitalOcean provides automatic daily backups. For manual backups: - +### Build API: ```bash -# Create backup -mysqldump -h your-db-host -P 25060 -u your-username -p your-database-name --ssl-mode=REQUIRED > backup.sql - -# Restore backup -mysql -h your-db-host -P 25060 -u your-username -p your-database-name --ssl-mode=REQUIRED < backup.sql +docker build -f Dockerfile.api -t scriptshare-api . +docker run -p 3001:3000 scriptshare-api ``` -## Monitoring and Logs +### Local Development: +```bash +docker-compose up +``` -### Application Logs -- View logs in DigitalOcean Console: App β†’ Runtime Logs -- Or via CLI: `doctl apps logs --type=run` +## πŸ”§ Local Development -### Database Monitoring -- Database metrics available in DigitalOcean dashboard -- Set up alerts for CPU, memory, and connection usage +### Frontend: +```bash +npm run dev +``` -### Health Checks -- API: `https://your-api-url/api/health` -- Frontend: Built-in App Platform health checks +### API: +```bash +npm run build:api +npm run start:api +``` -## Scaling +### Database: +```bash +npm run db:studio # Drizzle Studio +npm run db:migrate # Run migrations +``` -### Vertical Scaling -- Increase instance size in App Platform settings -- Database can be scaled up (not down) in database settings +## πŸš€ Quick Deploy Examples -### Horizontal Scaling -- Increase instance count for API service -- Frontend is automatically scaled as a static site +### Deploy to Vercel (Frontend): +```bash +vercel --prod +``` -## Security Best Practices +### Deploy to Railway: +```bash +railway deploy +``` -1. **Environment Variables**: Never commit secrets to Git -2. **Database Access**: Use DigitalOcean's private networking -3. **SSL/TLS**: Enabled by default on App Platform -4. **Database Backups**: Verify daily backups are working -5. **Access Control**: Use DigitalOcean teams for access management +### Deploy to Render: +Connect GitHub repository in Render dashboard -## Troubleshooting +## πŸ“ž Support -### Common Issues +- **Documentation**: Check platform-specific documentation +- **Environment**: Ensure all required environment variables are set +- **Health Checks**: Monitor `/health` and `/api/health` endpoints +- **Logs**: Check platform logs for deployment issues -1. **Build Failures**: - ```bash - # Check build logs - doctl apps logs --type=build - ``` +--- -2. **Database Connection Issues**: - - Verify DATABASE_URL format - - Check firewall settings - - Ensure SSL is enabled +**Your ScriptShare application is ready for deployment on any modern platform! πŸŽ‰** -3. **CORS Errors**: - - Verify CORS_ORIGIN matches frontend URL - - Check environment variable casing - -4. **Missing Dependencies**: - ```bash - # Clear npm cache and rebuild - npm ci --clean-cache - ``` - -### Getting Support - -- DigitalOcean Community: https://www.digitalocean.com/community -- Support tickets: https://cloud.digitalocean.com/support -- Documentation: https://docs.digitalocean.com/products/app-platform/ - -## Cost Optimization - -### Current Configuration Costs (Approximate) -- **API Service**: $5/month (Basic plan) -- **Database**: $15/month (1GB RAM, 1 vCPU) -- **Static Site**: $0 (included with API service) -- **Total**: ~$20/month - -### Cost Reduction Tips -1. Use development database for testing -2. Scale down during low usage periods -3. Monitor and optimize database queries -4. Use CDN for static assets - -## Deployment Checklist - -- [ ] Repository configured with deployment files -- [ ] Environment variables set in DigitalOcean -- [ ] JWT secret generated and configured -- [ ] Database migrations run successfully -- [ ] Health check endpoints responding -- [ ] Frontend can communicate with API -- [ ] Admin user created and accessible -- [ ] Custom domain configured (if applicable) -- [ ] Monitoring and alerts set up -- [ ] Backup strategy verified - -## Next Steps - -1. **Set up CI/CD**: Configure GitHub Actions for automated deployments -2. **Monitoring**: Set up application performance monitoring -3. **CDN**: Configure CDN for static assets -4. **Analytics**: Integrate application analytics -5. **Error Tracking**: Set up error monitoring service - -## Support - -For issues specific to this deployment setup, please check: -1. DigitalOcean App Platform documentation -2. Application logs in the DigitalOcean console -3. Database connection and query logs - -Remember to regularly update dependencies and monitor security advisories for your application stack. +Choose the platform that best fits your needs - from simple static hosting to full-stack container deployments. \ No newline at end of file diff --git a/DOCKER_DEPLOYMENT.md b/DOCKER_DEPLOYMENT.md deleted file mode 100644 index bc24b6a..0000000 --- a/DOCKER_DEPLOYMENT.md +++ /dev/null @@ -1,365 +0,0 @@ -# 🐳 ScriptShare Docker Deployment Guide - -## Overview - -This guide covers deploying ScriptShare to any generic Docker server using Docker Compose. The setup includes: - -- **Frontend**: React application served by Nginx -- **Backend API**: Node.js Express server -- **Database**: MySQL 8.0 -- **Reverse Proxy**: Nginx with load balancing -- **Cache**: Redis (optional) -- **Monitoring**: Health checks and logging - -## Prerequisites - -- Docker Engine 20.10+ -- Docker Compose 2.0+ -- At least 2GB RAM -- 10GB+ disk space -- Linux/macOS server (Windows with WSL2) - -## Quick Start - -### 1. **Prepare Environment** - -```bash -# Clone the repository -git clone -cd scriptshare-cursor - -# Copy and configure environment -cp env.production .env -# Edit .env with your specific settings -nano .env -``` - -### 2. **Deploy Application** - -```bash -# Make scripts executable (Linux/macOS) -chmod +x scripts/*.sh - -# Run deployment -./scripts/deploy.sh -``` - -### 3. **Verify Deployment** - -```bash -# Check service status -./scripts/manage.sh status - -# View logs -./scripts/manage.sh logs -``` - -## Configuration - -### Environment Variables - -Edit `env.production` before deployment: - -```bash -# Domain Configuration -APP_URL=https://your-domain.com -FRONTEND_URL=https://your-domain.com -CORS_ORIGIN=https://your-domain.com - -# Security (CHANGE THESE!) -JWT_SECRET=your-super-secret-jwt-key -DB_PASSWORD=your-secure-database-password -DB_ROOT_PASSWORD=your-root-password -REDIS_PASSWORD=your-redis-password - -# Ports (adjust if needed) -PROXY_PORT=80 -PROXY_SSL_PORT=443 -API_PORT=3001 -``` - -### SSL Configuration - -1. **Place SSL certificates** in `./certs/`: - ``` - certs/ - β”œβ”€β”€ fullchain.pem - └── privkey.pem - ``` - -2. **Enable HTTPS** in `nginx/conf.d/scriptshare.conf`: - - Uncomment the SSL server block - - Update `server_name` with your domain - -3. **Restart proxy**: - ```bash - ./scripts/manage.sh restart scriptshare-proxy - ``` - -## Service Architecture - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Nginx Proxy │────│ Frontend β”‚ -β”‚ Port 80/443 β”‚ β”‚ (React+Nginx) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ - β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - └──────────────│ Backend API β”‚ - β”‚ (Node.js) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ MySQL 8.0 β”‚ - β”‚ Database β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Redis Cache β”‚ - β”‚ (Optional) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -## Management Commands - -### Service Management - -```bash -# Start all services -./scripts/manage.sh start - -# Stop all services -./scripts/manage.sh stop - -# Restart services -./scripts/manage.sh restart - -# View service status -./scripts/manage.sh status - -# View logs (all services) -./scripts/manage.sh logs - -# View logs (specific service) -./scripts/manage.sh logs scriptshare-api -``` - -### Database Management - -```bash -# Connect to database -./scripts/manage.sh db - -# Create backup -./scripts/manage.sh backup - -# Run migrations (from API container) -docker-compose -f docker-compose.prod.yml exec scriptshare-api npm run db:migrate:prod -``` - -### Maintenance - -```bash -# Update application -./scripts/manage.sh update - -# Clean up Docker resources -./scripts/manage.sh clean - -# Open shell in container -./scripts/manage.sh shell scriptshare-api -``` - -## Port Configuration - -| Service | Internal Port | External Port | Description | -|---------|---------------|---------------|-------------| -| Proxy | 80, 443 | 8080, 8443 | Main entry point | -| Frontend | 80 | - | React application | -| API | 3000 | 3001 | REST API | -| Database | 3306 | 3306 | MySQL database | -| Redis | 6379 | 6379 | Cache store | - -## Monitoring - -### Health Checks - -All services include health checks: - -```bash -# Check health status -curl http://localhost:8080/health - -# API health -curl http://localhost:3001/api/health - -# Individual service health -docker ps --format "table {{.Names}}\t{{.Status}}" -``` - -### Logging - -Logs are stored in Docker volumes and can be accessed via: - -```bash -# All services -docker-compose -f docker-compose.prod.yml logs -f - -# Specific service -docker-compose -f docker-compose.prod.yml logs -f scriptshare-api - -# Save logs to file -docker-compose -f docker-compose.prod.yml logs > scriptshare.log -``` - -## Backup & Recovery - -### Automated Backups - -Configure automated backups by adding to crontab: - -```bash -# Edit crontab -crontab -e - -# Add daily backup at 2 AM -0 2 * * * /path/to/scriptshare/scripts/backup.sh -``` - -### Manual Backup - -```bash -# Create backup -./scripts/backup.sh - -# Backups are stored in ./backups/ -ls -la backups/ -``` - -### Recovery - -```bash -# Stop database -docker-compose -f docker-compose.prod.yml stop scriptshare-db - -# Restore from backup -gunzip -c backups/scriptshare_backup_YYYYMMDD_HHMMSS.sql.gz | \ -docker exec -i scriptshare-db mysql -u root -p'your-root-password' - -# Start database -docker-compose -f docker-compose.prod.yml start scriptshare-db -``` - -## Security Considerations - -### 1. **Change Default Passwords** -- Update all passwords in `env.production` -- Use strong, unique passwords -- Consider using environment variable files - -### 2. **Network Security** -- Configure firewall rules -- Use reverse proxy for SSL termination -- Implement rate limiting (configured in nginx) - -### 3. **SSL/TLS** -- Use Let's Encrypt for free SSL certificates -- Configure HSTS headers -- Use modern TLS protocols only - -### 4. **Container Security** -- Keep Docker images updated -- Run containers with non-root users where possible -- Use Docker secrets for sensitive data - -## Troubleshooting - -### Common Issues - -1. **Services won't start**: - ```bash - # Check logs - docker-compose -f docker-compose.prod.yml logs - - # Check disk space - df -h - - # Check memory - free -h - ``` - -2. **Database connection errors**: - ```bash - # Test database connectivity - docker exec scriptshare-db mysqladmin ping -u root -p'password' - - # Check database logs - docker-compose -f docker-compose.prod.yml logs scriptshare-db - ``` - -3. **API not responding**: - ```bash - # Check API health - curl http://localhost:3001/api/health - - # Check API logs - docker-compose -f docker-compose.prod.yml logs scriptshare-api - ``` - -### Performance Tuning - -1. **Database Optimization**: - - Adjust `innodb_buffer_pool_size` in MySQL configuration - - Monitor slow query log - - Add database indexes as needed - -2. **Nginx Optimization**: - - Enable gzip compression (configured) - - Adjust worker processes - - Configure caching headers - -3. **Resource Limits**: - - Set memory and CPU limits in docker-compose.prod.yml - - Monitor resource usage with `docker stats` - -## Scaling - -### Horizontal Scaling - -To scale the application: - -```bash -# Scale API containers -docker-compose -f docker-compose.prod.yml up -d --scale scriptshare-api=3 - -# Scale frontend containers -docker-compose -f docker-compose.prod.yml up -d --scale scriptshare-frontend=2 -``` - -### Load Balancing - -Nginx automatically load balances between multiple container instances. - -## Production Checklist - -- [ ] Update all default passwords -- [ ] Configure SSL certificates -- [ ] Set up automated backups -- [ ] Configure monitoring and alerting -- [ ] Set up log rotation -- [ ] Configure firewall rules -- [ ] Test disaster recovery procedures -- [ ] Set up domain and DNS -- [ ] Configure SMTP for emails (if applicable) -- [ ] Set up monitoring dashboard - -## Support - -For issues and questions: - -1. Check the logs first -2. Review this documentation -3. Check Docker and system resources -4. Create an issue in the repository - -**Your ScriptShare application is now ready for production deployment! πŸš€** diff --git a/Dockerfile.api b/Dockerfile.api index 3cdb497..cdabd8f 100644 --- a/Dockerfile.api +++ b/Dockerfile.api @@ -1,8 +1,8 @@ -# Production API Dockerfile for DigitalOcean +# ScriptShare API Dockerfile FROM node:18-alpine # Install system dependencies for native modules -RUN apk add --no-cache python3 make g++ libc6-compat +RUN apk add --no-cache python3 make g++ libc6-compat curl WORKDIR /app @@ -10,208 +10,13 @@ WORKDIR /app COPY package*.json ./ # Install dependencies -RUN npm ci --only=production=false --silent +RUN npm ci --only=production=false # Copy source code COPY . . -# Create API-only build by removing frontend dependencies and files -RUN npm uninstall @vitejs/plugin-react-swc vite -RUN rm -rf src/components src/pages src/contexts src/hooks/use-toast.ts src/utils/toast.ts -RUN rm -rf src/main.tsx src/App.tsx src/index.css -RUN rm -rf public index.html vite.config.ts tailwind.config.ts postcss.config.js - -# Keep only API and database files -# The structure will be: src/lib/api/* and src/lib/db/* - -# Create a simple Express server -RUN cat > src/server.ts << 'EOF' -import express from 'express'; -import cors from 'cors'; -import { createUser, getUserByEmail, updateUser, getAllUsers, getUserById } from './lib/api/users.js'; -import { getScripts, getScriptById, createScript, updateScript, deleteScript, moderateScript } from './lib/api/scripts.js'; -import { login, register, refreshToken } from './lib/api/auth.js'; -import { rateScript, getUserRating, getScriptRatingStats } from './lib/api/ratings.js'; -import { getPlatformAnalytics, getScriptAnalytics, trackEvent } from './lib/api/analytics.js'; -import { createCollection, getUserCollections, getPublicCollections, addScriptToCollection } from './lib/api/collections.js'; - -const app = express(); -const PORT = process.env.PORT || 3000; - -// Middleware -app.use(cors({ - origin: process.env.CORS_ORIGIN || '*', - credentials: true -})); -app.use(express.json({ limit: '10mb' })); -app.use(express.urlencoded({ extended: true })); - -// Health check endpoint -app.get('/api/health', (req, res) => { - res.json({ status: 'ok', timestamp: new Date().toISOString() }); -}); - -// Auth routes -app.post('/api/auth/login', async (req, res) => { - try { - const result = await login(req.body); - res.json(result); - } catch (error) { - console.error('Login error:', error); - res.status(401).json({ error: 'Invalid credentials' }); - } -}); - -app.post('/api/auth/register', async (req, res) => { - try { - const result = await register(req.body); - res.json(result); - } catch (error) { - console.error('Register error:', error); - res.status(400).json({ error: 'Registration failed' }); - } -}); - -// Scripts routes -app.get('/api/scripts', async (req, res) => { - try { - const result = await getScripts(req.query); - res.json(result); - } catch (error) { - console.error('Get scripts error:', error); - res.status(500).json({ error: 'Failed to fetch scripts' }); - } -}); - -app.get('/api/scripts/:id', async (req, res) => { - try { - const script = await getScriptById(req.params.id); - if (!script) { - return res.status(404).json({ error: 'Script not found' }); - } - res.json(script); - } catch (error) { - console.error('Get script error:', error); - res.status(500).json({ error: 'Failed to fetch script' }); - } -}); - -app.post('/api/scripts', async (req, res) => { - try { - const userId = req.headers['x-user-id'] as string; - if (!userId) { - return res.status(401).json({ error: 'Unauthorized' }); - } - const result = await createScript(req.body, userId); - res.json(result); - } catch (error) { - console.error('Create script error:', error); - res.status(500).json({ error: 'Failed to create script' }); - } -}); - -// Users routes -app.get('/api/users', async (req, res) => { - try { - const result = await getAllUsers(); - res.json(result); - } catch (error) { - console.error('Get users error:', error); - res.status(500).json({ error: 'Failed to fetch users' }); - } -}); - -app.get('/api/users/:id', async (req, res) => { - try { - const user = await getUserById(req.params.id); - if (!user) { - return res.status(404).json({ error: 'User not found' }); - } - res.json(user); - } catch (error) { - console.error('Get user error:', error); - res.status(500).json({ error: 'Failed to fetch user' }); - } -}); - -// Analytics routes -app.get('/api/analytics/platform', async (req, res) => { - try { - const days = parseInt(req.query.days as string) || 30; - const result = await getPlatformAnalytics(days); - res.json(result); - } catch (error) { - console.error('Analytics error:', error); - res.status(500).json({ error: 'Failed to fetch analytics' }); - } -}); - -app.post('/api/analytics/track', async (req, res) => { - try { - const result = await trackEvent(req.body); - res.json(result); - } catch (error) { - console.error('Track event error:', error); - res.status(500).json({ error: 'Failed to track event' }); - } -}); - -// Collections routes -app.get('/api/collections', async (req, res) => { - try { - const userId = req.headers['x-user-id'] as string; - const result = userId ? await getUserCollections(userId) : await getPublicCollections(); - res.json(result); - } catch (error) { - console.error('Get collections error:', error); - res.status(500).json({ error: 'Failed to fetch collections' }); - } -}); - -// Ratings routes -app.post('/api/ratings', async (req, res) => { - try { - const result = await rateScript(req.body); - res.json(result); - } catch (error) { - console.error('Rate script error:', error); - res.status(500).json({ error: 'Failed to rate script' }); - } -}); - -app.get('/api/scripts/:id/ratings', async (req, res) => { - try { - const result = await getScriptRatingStats(req.params.id); - res.json(result); - } catch (error) { - console.error('Get ratings error:', error); - res.status(500).json({ error: 'Failed to fetch ratings' }); - } -}); - -// Error handling middleware -app.use((error: any, req: express.Request, res: express.Response, next: express.NextFunction) => { - console.error('Unhandled error:', error); - res.status(500).json({ error: 'Internal server error' }); -}); - -// 404 handler -app.use('*', (req, res) => { - res.status(404).json({ error: 'Endpoint not found' }); -}); - -app.listen(PORT, () => { - console.log(`ScriptShare API server running on port ${PORT}`); - console.log(`Environment: ${process.env.NODE_ENV}`); - console.log(`Database URL configured: ${!!process.env.DATABASE_URL}`); -}); -EOF - -# Install Express and CORS for the API server -RUN npm install express cors @types/express @types/cors - -# Build TypeScript (if any TS files remain) -RUN npx tsc --build || echo "TypeScript build completed with warnings" +# Build TypeScript +RUN npx tsc --build # Expose port EXPOSE 3000 @@ -221,4 +26,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD curl -f http://localhost:3000/api/health || exit 1 # Start the API server -CMD ["node", "src/server.js"] +CMD ["npm", "run", "start:api"] \ No newline at end of file diff --git a/README_DEPLOYMENT.md b/README_DEPLOYMENT.md deleted file mode 100644 index f4176ac..0000000 --- a/README_DEPLOYMENT.md +++ /dev/null @@ -1,180 +0,0 @@ -# πŸš€ ScriptShare - Generic Docker Server Deployment - -## 🎯 Deployment Summary - -Your ScriptShare application has been successfully reconfigured for deployment on any generic Docker server! The setup provides a complete, production-ready environment with all necessary components. - -## πŸ“¦ What's Included - -### **🐳 Docker Infrastructure** -- **Production Docker Compose**: Complete multi-service stack -- **Frontend Container**: React app with Nginx -- **Backend API Container**: Node.js Express server -- **Database Container**: MySQL 8.0 with optimizations -- **Reverse Proxy**: Nginx with load balancing & SSL support -- **Cache Layer**: Redis for session/data caching -- **Health Monitoring**: All services include health checks - -### **βš™οΈ Configuration Files** -- `docker-compose.prod.yml` - Production environment setup -- `env.production` - Environment variables template -- `nginx/nginx.conf` - Main Nginx configuration -- `nginx/conf.d/scriptshare.conf` - Application-specific routing - -### **πŸ› οΈ Management Tools** -- `scripts/deploy.sh` - Automated deployment script -- `scripts/manage.sh` - Service management (Linux/macOS) -- `scripts/manage.ps1` - Service management (Windows) -- `scripts/backup.sh` - Database backup automation - -### **πŸ“š Documentation** -- `DOCKER_DEPLOYMENT.md` - Comprehensive deployment guide -- Complete configuration examples -- Troubleshooting and maintenance guides - -## πŸš€ Quick Deployment - -### **Prerequisites** -- Docker Engine 20.10+ -- Docker Compose 2.0+ -- 2GB+ RAM, 10GB+ disk space - -### **Deploy in 3 Steps** - -1. **Configure Environment**: - ```bash - cp env.production .env - # Edit .env with your domain and passwords - ``` - -2. **Deploy Application**: - ```bash - # Linux/macOS - chmod +x scripts/*.sh - ./scripts/deploy.sh - - # Windows PowerShell - .\scripts\manage.ps1 start - ``` - -3. **Verify Deployment**: - ```bash - # Check status - ./scripts/manage.sh status - - # View application - http://localhost:8080 - ``` - -## 🌐 Service Architecture - -``` -Internet - ↓ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” Port 80/443 -β”‚ Nginx Proxy β”‚ (Load Balancer) -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - ↓ ↓ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚Frontend β”‚ β”‚ Backend API β”‚ -β”‚(React) β”‚ β”‚ (Node.js) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - ↓ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ MySQL 8.0 β”‚ - β”‚ Database β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - ↓ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Redis Cache β”‚ - β”‚ (Optional) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -## πŸ”§ Key Features - -### **Production Ready** -- βœ… Multi-container architecture -- βœ… Health checks and monitoring -- βœ… Automated backup system -- βœ… SSL/HTTPS support -- βœ… Rate limiting and security headers -- βœ… Database optimizations -- βœ… Log management -- βœ… Resource management - -### **Easy Management** -- βœ… One-command deployment -- βœ… Service start/stop/restart -- βœ… Real-time log viewing -- βœ… Database backup/restore -- βœ… Application updates -- βœ… Resource cleanup -- βœ… Health monitoring - -### **Scalable** -- βœ… Horizontal scaling support -- βœ… Load balancing configured -- βœ… Container orchestration -- βœ… Resource limits -- βœ… Performance monitoring - -## πŸ“‹ Post-Deployment Checklist - -1. **Security Configuration**: - - [ ] Update all default passwords in `.env` - - [ ] Configure SSL certificates - - [ ] Set up firewall rules - - [ ] Review security headers - -2. **Domain Setup**: - - [ ] Point your domain to the server - - [ ] Update `APP_URL` in environment - - [ ] Configure SSL certificates - - [ ] Test HTTPS redirect - -3. **Monitoring & Maintenance**: - - [ ] Set up automated backups (cron) - - [ ] Configure log rotation - - [ ] Test disaster recovery - - [ ] Set up monitoring alerts - -4. **Application Setup**: - - [ ] Run database migrations - - [ ] Create admin user - - [ ] Test all functionality - - [ ] Configure SMTP (if needed) - -## πŸ†˜ Quick Commands - -### **Service Management** -```bash -./scripts/manage.sh start # Start all services -./scripts/manage.sh stop # Stop all services -./scripts/manage.sh status # Check service status -./scripts/manage.sh logs # View logs -``` - -### **Database Operations** -```bash -./scripts/manage.sh backup # Create database backup -./scripts/manage.sh db # Connect to database -``` - -### **Maintenance** -```bash -./scripts/manage.sh update # Update application -./scripts/manage.sh clean # Clean Docker resources -``` - -## πŸ“ž Support - -- **Documentation**: See `DOCKER_DEPLOYMENT.md` for detailed instructions -- **Troubleshooting**: Check logs with `./scripts/manage.sh logs` -- **Updates**: Use `./scripts/manage.sh update` for application updates - ---- - -**πŸŽ‰ Your ScriptShare application is now ready for production deployment on any Docker server!** - -The setup provides enterprise-grade reliability, security, and scalability while maintaining simplicity for day-to-day operations. All components are containerized, monitored, and ready for production workloads. diff --git a/REVERT_SUMMARY.md b/REVERT_SUMMARY.md new file mode 100644 index 0000000..1e17b1e --- /dev/null +++ b/REVERT_SUMMARY.md @@ -0,0 +1,128 @@ +# βœ… ScriptShare - Reverted to Standard Docker Deployment + +## πŸ”„ Reversion Complete + +Your ScriptShare application has been successfully reverted from the complex DigitalOcean-specific setup back to a **clean, standard Docker deployment** that works with **any platform**. + +## πŸ—‘οΈ Removed Files + +### Complex Infrastructure Files: +- ❌ `docker-compose.prod.yml` - Complex production setup +- ❌ `env.production` - Production environment file +- ❌ `nginx/nginx.conf` - Custom nginx configuration +- ❌ `nginx/conf.d/scriptshare.conf` - Site-specific nginx config +- ❌ `nginx/` directory - Removed entirely + +### Management Scripts: +- ❌ `scripts/deploy.sh` - Complex deployment automation +- ❌ `scripts/backup.sh` - Database backup scripts +- ❌ `scripts/init-db.sql` - Database initialization +- ❌ `scripts/manage.sh` - Linux/macOS management +- ❌ `scripts/manage.ps1` - Windows PowerShell management + +### Documentation: +- ❌ `DOCKER_DEPLOYMENT.md` - Complex deployment guide +- ❌ `README_DEPLOYMENT.md` - Deployment summary +- ❌ `DEPLOYMENT_SUCCESS.md` - DigitalOcean success page +- ❌ `.github/workflows/deploy.yml` - DigitalOcean workflow + +## βœ… What You Now Have + +### 🐳 Clean Docker Setup: +- **`Dockerfile`** - Simple frontend build (React + Nginx) +- **`Dockerfile.api`** - Clean API server (Node.js + Express) +- **`docker-compose.yml`** - Basic local development setup +- **`src/server.ts`** - Standalone API server + +### πŸ“š Universal Documentation: +- **`DEPLOYMENT.md`** - Platform-agnostic deployment guide +- **`.github/workflows/build.yml`** - Universal CI/CD pipeline + +### πŸš€ Platform Compatibility: +- βœ… **Vercel** - Frontend deployment ready +- βœ… **Coolify** - Full Docker deployment +- βœ… **DigitalOcean App Platform** - Docker + app.yaml +- βœ… **Railway** - Auto-detect Docker builds +- βœ… **Render** - Static + web service deployment +- βœ… **Any Docker platform** - Standard Dockerfiles + +## πŸ—οΈ Current Architecture + +``` +Simple & Clean: + +Frontend (Dockerfile) API (Dockerfile.api) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ React + Vite β”‚ β”‚ Node.js Express β”‚ +β”‚ Built to Dist β”‚ β”‚ TypeScript β”‚ +β”‚ Served by β”‚ β”‚ Port 3000 β”‚ +β”‚ Nginx β”‚ β”‚ /api/health β”‚ +β”‚ Port 80 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## πŸš€ Quick Deployment Options + +### Option 1: Vercel (Frontend) +```bash +vercel --prod +``` + +### Option 2: Coolify (Full Stack) +- Import from Git +- Auto-detect Dockerfiles +- Deploy both services + +### Option 3: DigitalOcean App Platform +- Create app.yaml (see DEPLOYMENT.md) +- Deploy from repository + +### Option 4: Railway +- Connect repository +- Auto-deploy both services + +### Option 5: Docker Compose (Local) +```bash +docker-compose up +``` + +## 🎯 Benefits of This Approach + +### βœ… **Platform Agnostic** +- Works with **any** deployment platform +- No vendor lock-in +- Standard Docker practices + +### βœ… **Simple & Clean** +- Minimal configuration +- Easy to understand +- Standard build processes + +### βœ… **Flexible** +- Deploy frontend and API separately +- Scale components independently +- Choose best platform for each service + +### βœ… **Maintainable** +- No complex orchestration +- Standard Docker patterns +- Platform-native features + +## πŸ“ Next Steps + +1. **Choose Your Platform**: Vercel, Coolify, Railway, Render, etc. +2. **Configure Environment Variables**: See DEPLOYMENT.md +3. **Deploy**: Follow platform-specific instructions +4. **Monitor**: Use platform-native monitoring tools + +## πŸŽ‰ Summary + +Your ScriptShare application is now **clean, simple, and ready for deployment on any modern platform**. The complex Docker Compose setup has been removed in favor of standard Dockerfiles that work everywhere. + +**Key Files:** +- `Dockerfile` - Frontend build +- `Dockerfile.api` - API server +- `DEPLOYMENT.md` - Platform guide +- `src/server.ts` - API entry point + +**Ready for:** Vercel, Coolify, DigitalOcean, Railway, Render, and any Docker platform! diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml deleted file mode 100644 index b60c1db..0000000 --- a/docker-compose.prod.yml +++ /dev/null @@ -1,156 +0,0 @@ -version: '3.8' - -services: - # MySQL Database - scriptshare-db: - image: mysql:8.0 - container_name: scriptshare-db - restart: unless-stopped - environment: - MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-ScriptShare_Root_2024_Secure_Password} - MYSQL_DATABASE: ${DB_NAME:-scriptshare} - MYSQL_USER: ${DB_USER:-scriptshare_user} - MYSQL_PASSWORD: ${DB_PASSWORD:-ScriptShare_App_2024_Secure!} - MYSQL_CHARSET: utf8mb4 - MYSQL_COLLATION: utf8mb4_unicode_ci - volumes: - - scriptshare_db_data:/var/lib/mysql - - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro - ports: - - "${DB_PORT:-3306}:3306" - networks: - - scriptshare-network - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DB_ROOT_PASSWORD:-ScriptShare_Root_2024_Secure_Password}"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 60s - command: > - --default-authentication-plugin=mysql_native_password - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - --innodb-file-per-table=1 - --max-connections=200 - - # Backend API - scriptshare-api: - build: - context: . - dockerfile: Dockerfile.api - container_name: scriptshare-api - restart: unless-stopped - environment: - - NODE_ENV=production - - DATABASE_URL=mysql://${DB_USER:-scriptshare_user}:${DB_PASSWORD:-ScriptShare_App_2024_Secure!}@scriptshare-db:3306/${DB_NAME:-scriptshare} - - JWT_SECRET=${JWT_SECRET:-production-super-secret-jwt-key-scriptshare-2024-secure} - - CORS_ORIGIN=${FRONTEND_URL:-http://localhost} - - PORT=3000 - - DB_HOST=scriptshare-db - - DB_PORT=3306 - - DB_USER=${DB_USER:-scriptshare_user} - - DB_PASSWORD=${DB_PASSWORD:-ScriptShare_App_2024_Secure!} - - DB_NAME=${DB_NAME:-scriptshare} - ports: - - "${API_PORT:-3001}:3000" - networks: - - scriptshare-network - depends_on: - scriptshare-db: - condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 60s - volumes: - - scriptshare_api_logs:/app/logs - - # Frontend - scriptshare-frontend: - build: - context: . - dockerfile: Dockerfile - args: - - VITE_APP_NAME=${APP_NAME:-ScriptShare} - - VITE_APP_URL=${APP_URL:-https://scriptshare.example.com} - - VITE_ANALYTICS_ENABLED=${ANALYTICS_ENABLED:-false} - - VITE_API_URL=${API_URL:-http://localhost:3001} - container_name: scriptshare-frontend - restart: unless-stopped - ports: - - "${FRONTEND_PORT:-80}:80" - networks: - - scriptshare-network - depends_on: - - scriptshare-api - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost/"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - volumes: - - scriptshare_frontend_logs:/var/log/nginx - - # Reverse Proxy (Nginx) - scriptshare-proxy: - image: nginx:alpine - container_name: scriptshare-proxy - restart: unless-stopped - ports: - - "${PROXY_PORT:-8080}:80" - - "${PROXY_SSL_PORT:-8443}:443" - volumes: - - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - - ./nginx/conf.d:/etc/nginx/conf.d:ro - - scriptshare_proxy_logs:/var/log/nginx - - ${SSL_CERT_PATH:-./certs}:/etc/nginx/certs:ro - networks: - - scriptshare-network - depends_on: - - scriptshare-frontend - - scriptshare-api - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 3 - - # Redis Cache (Optional) - scriptshare-redis: - image: redis:7-alpine - container_name: scriptshare-redis - restart: unless-stopped - command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-ScriptShare_Redis_2024} - ports: - - "${REDIS_PORT:-6379}:6379" - volumes: - - scriptshare_redis_data:/data - networks: - - scriptshare-network - healthcheck: - test: ["CMD", "redis-cli", "--raw", "incr", "ping"] - interval: 30s - timeout: 10s - retries: 3 - -volumes: - scriptshare_db_data: - driver: local - scriptshare_api_logs: - driver: local - scriptshare_frontend_logs: - driver: local - scriptshare_proxy_logs: - driver: local - scriptshare_redis_data: - driver: local - -networks: - scriptshare-network: - driver: bridge - ipam: - config: - - subnet: 172.20.0.0/16 diff --git a/env.production b/env.production deleted file mode 100644 index 31da6db..0000000 --- a/env.production +++ /dev/null @@ -1,52 +0,0 @@ -# ScriptShare Production Environment Configuration - -# Application Settings -APP_NAME=ScriptShare -APP_URL=https://your-domain.com -ANALYTICS_ENABLED=true -NODE_ENV=production - -# Database Configuration -DB_HOST=scriptshare-db -DB_PORT=3306 -DB_NAME=scriptshare -DB_USER=scriptshare_user -DB_PASSWORD=ScriptShare_App_2024_Secure! -DB_ROOT_PASSWORD=ScriptShare_Root_2024_Secure_Password -DATABASE_URL=mysql://scriptshare_user:ScriptShare_App_2024_Secure!@scriptshare-db:3306/scriptshare - -# Security -JWT_SECRET=production-super-secret-jwt-key-scriptshare-2024-secure-change-this-in-production - -# API Configuration -API_PORT=3001 -API_URL=http://localhost:3001 -CORS_ORIGIN=https://your-domain.com - -# Frontend Configuration -FRONTEND_PORT=80 -FRONTEND_URL=https://your-domain.com -VITE_APP_NAME=ScriptShare -VITE_APP_URL=https://your-domain.com -VITE_ANALYTICS_ENABLED=true -VITE_API_URL=https://your-domain.com/api - -# Proxy Configuration -PROXY_PORT=8080 -PROXY_SSL_PORT=8443 - -# Redis Configuration (Optional) -REDIS_PORT=6379 -REDIS_PASSWORD=ScriptShare_Redis_2024 - -# SSL Configuration -SSL_CERT_PATH=./certs - -# Logging -LOG_LEVEL=info -LOG_FILE=/app/logs/scriptshare.log - -# Backup Configuration -BACKUP_ENABLED=true -BACKUP_SCHEDULE=0 2 * * * -BACKUP_RETENTION_DAYS=30 diff --git a/nginx/conf.d/scriptshare.conf b/nginx/conf.d/scriptshare.conf deleted file mode 100644 index 199771d..0000000 --- a/nginx/conf.d/scriptshare.conf +++ /dev/null @@ -1,129 +0,0 @@ -# ScriptShare Main Configuration -upstream scriptshare_api { - server scriptshare-api:3000; -} - -upstream scriptshare_frontend { - server scriptshare-frontend:80; -} - -# HTTP to HTTPS redirect (when SSL is configured) -server { - listen 80; - server_name _; - - # Health check endpoint - location /health { - access_log off; - return 200 "healthy\n"; - add_header Content-Type text/plain; - } - - # API routes - location /api/ { - # Rate limiting for API - limit_req zone=api burst=20 nodelay; - - # Proxy headers - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - # Proxy settings - proxy_pass http://scriptshare_api; - proxy_redirect off; - proxy_buffering off; - proxy_read_timeout 60s; - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - - # CORS headers (if needed) - add_header 'Access-Control-Allow-Origin' '*' always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,X-User-Id' always; - - # Handle preflight requests - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,X-User-Id'; - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain; charset=utf-8'; - add_header 'Content-Length' 0; - return 204; - } - } - - # Special rate limiting for auth endpoints - location /api/auth/ { - limit_req zone=login burst=5 nodelay; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - proxy_pass http://scriptshare_api; - proxy_redirect off; - proxy_buffering off; - proxy_read_timeout 60s; - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - } - - # Frontend routes - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - proxy_pass http://scriptshare_frontend; - proxy_redirect off; - - # Handle SPA routing - try_files $uri $uri/ @fallback; - } - - # Fallback for SPA routing - location @fallback { - proxy_pass http://scriptshare_frontend; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # Static assets caching - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - proxy_pass http://scriptshare_frontend; - proxy_cache_valid 200 1y; - add_header Cache-Control "public, immutable"; - expires 1y; - } - - # Security headers - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header Referrer-Policy "strict-origin-when-cross-origin" always; - - # Hide nginx version - server_tokens off; -} - -# HTTPS Configuration (uncomment and configure when SSL certificates are ready) -# server { -# listen 443 ssl http2; -# server_name your-domain.com; -# -# ssl_certificate /etc/nginx/certs/fullchain.pem; -# ssl_certificate_key /etc/nginx/certs/privkey.pem; -# ssl_protocols TLSv1.2 TLSv1.3; -# ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384; -# ssl_prefer_server_ciphers off; -# -# # Include the same location blocks as above -# include /etc/nginx/conf.d/common-locations.conf; -# } diff --git a/nginx/nginx.conf b/nginx/nginx.conf deleted file mode 100644 index 3bd9d11..0000000 --- a/nginx/nginx.conf +++ /dev/null @@ -1,47 +0,0 @@ -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Logging format - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - error_log /var/log/nginx/error.log warn; - - # Performance settings - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - client_max_body_size 10M; - - # Gzip compression - gzip on; - gzip_vary on; - gzip_min_length 1000; - gzip_types - text/plain - text/css - text/xml - text/javascript - application/json - application/javascript - application/xml - application/rss+xml - application/atom+xml - image/svg+xml; - - # Rate limiting - limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; - limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m; - - # Include additional configurations - include /etc/nginx/conf.d/*.conf; -} diff --git a/scripts/backup.sh b/scripts/backup.sh deleted file mode 100644 index 1fef049..0000000 --- a/scripts/backup.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# ScriptShare Database Backup Script - -set -e - -# Load environment variables -if [ -f ".env" ]; then - source .env -fi - -# Default values -DB_CONTAINER=${DB_CONTAINER:-scriptshare-db} -BACKUP_DIR=${BACKUP_DIR:-./backups} -RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-30} - -# Create backup directory -mkdir -p "$BACKUP_DIR" - -# Generate backup filename with timestamp -TIMESTAMP=$(date +"%Y%m%d_%H%M%S") -BACKUP_FILE="$BACKUP_DIR/scriptshare_backup_$TIMESTAMP.sql" - -echo "πŸ—„οΈ Starting database backup..." -echo "Backup file: $BACKUP_FILE" - -# Create database backup -docker exec "$DB_CONTAINER" mysqldump \ - --single-transaction \ - --routines \ - --triggers \ - --all-databases \ - -u root \ - -p"${DB_ROOT_PASSWORD}" > "$BACKUP_FILE" - -# Compress the backup -gzip "$BACKUP_FILE" -BACKUP_FILE="$BACKUP_FILE.gz" - -echo "βœ… Database backup completed: $BACKUP_FILE" - -# Calculate backup size -BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1) -echo "πŸ“¦ Backup size: $BACKUP_SIZE" - -# Clean up old backups -echo "🧹 Cleaning up old backups (older than $RETENTION_DAYS days)..." -find "$BACKUP_DIR" -name "scriptshare_backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete - -# List remaining backups -echo "πŸ“‹ Current backups:" -ls -lh "$BACKUP_DIR"/scriptshare_backup_*.sql.gz 2>/dev/null || echo "No backups found" - -echo "βœ… Backup process completed successfully!" diff --git a/scripts/deploy.sh b/scripts/deploy.sh deleted file mode 100644 index 5343692..0000000 --- a/scripts/deploy.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -# ScriptShare Production Deployment Script - -set -e - -echo "πŸš€ Starting ScriptShare deployment..." - -# Check if Docker and Docker Compose are installed -if ! command -v docker &> /dev/null; then - echo "❌ Docker is not installed. Please install Docker first." - exit 1 -fi - -if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then - echo "❌ Docker Compose is not installed. Please install Docker Compose first." - exit 1 -fi - -# Check if environment file exists -if [ ! -f "env.production" ]; then - echo "❌ Environment file 'env.production' not found." - echo "Please copy 'env.production' and configure your settings." - exit 1 -fi - -# Create necessary directories -echo "πŸ“ Creating required directories..." -mkdir -p logs -mkdir -p certs -mkdir -p backups - -# Copy environment file -cp env.production .env - -# Pull latest images -echo "πŸ“₯ Pulling Docker images..." -docker-compose -f docker-compose.prod.yml pull - -# Build custom images -echo "πŸ”¨ Building application images..." -docker-compose -f docker-compose.prod.yml build --no-cache - -# Stop existing containers if running -echo "πŸ›‘ Stopping existing containers..." -docker-compose -f docker-compose.prod.yml down - -# Start the application -echo "πŸš€ Starting ScriptShare application..." -docker-compose -f docker-compose.prod.yml up -d - -# Wait for services to be healthy -echo "⏳ Waiting for services to start..." -sleep 30 - -# Check service health -echo "πŸ₯ Checking service health..." -services=("scriptshare-db" "scriptshare-api" "scriptshare-frontend" "scriptshare-proxy") - -for service in "${services[@]}"; do - if docker-compose -f docker-compose.prod.yml ps | grep -q "$service.*Up"; then - echo "βœ… $service is running" - else - echo "❌ $service failed to start" - echo "Checking logs for $service:" - docker-compose -f docker-compose.prod.yml logs "$service" - exit 1 - fi -done - -# Run database migrations if needed -echo "πŸ—ƒοΈ Running database migrations..." -docker-compose -f docker-compose.prod.yml exec -T scriptshare-api npm run db:migrate:prod || echo "⚠️ Database migrations not available or failed" - -# Display deployment information -echo "" -echo "πŸŽ‰ ScriptShare deployment completed successfully!" -echo "" -echo "πŸ“Š Service URLs:" -echo " Frontend: http://localhost:$(grep PROXY_PORT .env | cut -d'=' -f2 | tr -d '"')" -echo " API: http://localhost:$(grep API_PORT .env | cut -d'=' -f2 | tr -d '"')/api/health" -echo " Database: localhost:$(grep DB_PORT .env | cut -d'=' -f2 | tr -d '"')" -echo "" -echo "πŸ”§ Management commands:" -echo " View logs: docker-compose -f docker-compose.prod.yml logs -f" -echo " Stop: docker-compose -f docker-compose.prod.yml down" -echo " Restart: docker-compose -f docker-compose.prod.yml restart" -echo "" -echo "πŸ“ Next steps:" -echo " 1. Configure your domain DNS to point to this server" -echo " 2. Set up SSL certificates in ./certs/" -echo " 3. Update env.production with your domain settings" -echo " 4. Run: docker-compose -f docker-compose.prod.yml restart scriptshare-proxy" diff --git a/scripts/init-db.sql b/scripts/init-db.sql deleted file mode 100644 index 05a8e44..0000000 --- a/scripts/init-db.sql +++ /dev/null @@ -1,47 +0,0 @@ --- ScriptShare Database Initialization Script --- This script sets up the initial database structure and default data - -USE scriptshare; - --- Create tables if they don't exist (will be handled by Drizzle migrations) --- This file can be used for any initial data setup - --- Insert default admin user (optional) --- Note: Password should be properly hashed in production -INSERT IGNORE INTO users (id, email, username, displayName, isAdmin, isModerator, createdAt, updatedAt) -VALUES ( - 'admin-default-id', - 'admin@scriptshare.local', - 'admin', - 'Administrator', - true, - true, - NOW(), - NOW() -); - --- Insert sample categories -INSERT IGNORE INTO script_categories (name, description) VALUES -('System Administration', 'Scripts for system administration tasks'), -('Development', 'Development and build automation scripts'), -('Backup & Recovery', 'Backup and recovery automation'), -('Monitoring', 'System and application monitoring scripts'), -('Security', 'Security and audit scripts'), -('Database', 'Database management and maintenance'), -('Network', 'Network configuration and management'), -('DevOps', 'DevOps and CI/CD automation'); - --- Create indexes for performance -CREATE INDEX IF NOT EXISTS idx_scripts_author ON scripts(authorId); -CREATE INDEX IF NOT EXISTS idx_scripts_created ON scripts(createdAt); -CREATE INDEX IF NOT EXISTS idx_scripts_approved ON scripts(isApproved); -CREATE INDEX IF NOT EXISTS idx_ratings_script ON ratings(scriptId); -CREATE INDEX IF NOT EXISTS idx_analytics_script ON script_analytics(scriptId); -CREATE INDEX IF NOT EXISTS idx_analytics_created ON script_analytics(createdAt); - --- Set up database optimization -SET GLOBAL innodb_buffer_pool_size = 268435456; -- 256MB -SET GLOBAL max_connections = 200; - --- Print initialization complete message -SELECT 'ScriptShare database initialization completed!' as message; diff --git a/scripts/manage.ps1 b/scripts/manage.ps1 deleted file mode 100644 index 878b080..0000000 --- a/scripts/manage.ps1 +++ /dev/null @@ -1,142 +0,0 @@ -# ScriptShare Management Script for Windows PowerShell - -param( - [Parameter(Mandatory=$true, Position=0)] - [string]$Command, - [Parameter(Position=1)] - [string]$Service -) - -$ComposeFile = "docker-compose.prod.yml" - -function Show-Help { - Write-Host "ScriptShare Management Script" -ForegroundColor Green - Write-Host "" - Write-Host "Usage: .\scripts\manage.ps1 [COMMAND] [SERVICE]" -ForegroundColor Yellow - Write-Host "" - Write-Host "Commands:" -ForegroundColor Cyan - Write-Host " start Start all services" - Write-Host " stop Stop all services" - Write-Host " restart Restart all services" - Write-Host " logs Show logs for all services" - Write-Host " logs [svc] Show logs for specific service" - Write-Host " status Show status of all services" - Write-Host " backup Create database backup" - Write-Host " update Update application (pull, build, restart)" - Write-Host " clean Clean up unused Docker resources" - Write-Host " shell [svc] Open shell in service container" - Write-Host " db Connect to database" - Write-Host " help Show this help message" - Write-Host "" - Write-Host "Services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy, scriptshare-redis" -ForegroundColor Gray -} - -switch ($Command.ToLower()) { - "start" { - Write-Host "πŸš€ Starting ScriptShare services..." -ForegroundColor Green - docker-compose -f $ComposeFile up -d - Write-Host "βœ… Services started" -ForegroundColor Green - } - - "stop" { - Write-Host "πŸ›‘ Stopping ScriptShare services..." -ForegroundColor Yellow - docker-compose -f $ComposeFile down - Write-Host "βœ… Services stopped" -ForegroundColor Green - } - - "restart" { - Write-Host "πŸ”„ Restarting ScriptShare services..." -ForegroundColor Yellow - docker-compose -f $ComposeFile restart - Write-Host "βœ… Services restarted" -ForegroundColor Green - } - - "logs" { - if ($Service) { - Write-Host "πŸ“‹ Showing logs for $Service..." -ForegroundColor Cyan - docker-compose -f $ComposeFile logs -f $Service - } else { - Write-Host "πŸ“‹ Showing logs for all services..." -ForegroundColor Cyan - docker-compose -f $ComposeFile logs -f - } - } - - "status" { - Write-Host "πŸ“Š Service Status:" -ForegroundColor Cyan - docker-compose -f $ComposeFile ps - Write-Host "" - Write-Host "πŸ₯ Health Status:" -ForegroundColor Cyan - $services = @("scriptshare-db", "scriptshare-api", "scriptshare-frontend", "scriptshare-proxy") - foreach ($svc in $services) { - try { - $health = docker inspect --format='{{.State.Health.Status}}' $svc 2>$null - if (-not $health) { $health = "not found" } - Write-Host " $svc`: $health" -ForegroundColor Gray - } catch { - Write-Host " $svc`: not found" -ForegroundColor Red - } - } - } - - "backup" { - Write-Host "πŸ—„οΈ Creating database backup..." -ForegroundColor Cyan - if (Test-Path ".\scripts\backup.sh") { - bash .\scripts\backup.sh - } else { - Write-Host "❌ Backup script not found. Please run manually:" -ForegroundColor Red - Write-Host "docker exec scriptshare-db mysqladmin ping" -ForegroundColor Gray - } - } - - "update" { - Write-Host "πŸ”„ Updating ScriptShare application..." -ForegroundColor Cyan - docker-compose -f $ComposeFile pull - docker-compose -f $ComposeFile build --no-cache - docker-compose -f $ComposeFile up -d - Write-Host "βœ… Application updated" -ForegroundColor Green - } - - "clean" { - Write-Host "🧹 Cleaning up Docker resources..." -ForegroundColor Yellow - docker system prune -f - docker volume prune -f - Write-Host "βœ… Cleanup completed" -ForegroundColor Green - } - - "shell" { - if (-not $Service) { - Write-Host "❌ Please specify service name" -ForegroundColor Red - Write-Host "Available services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy" -ForegroundColor Gray - exit 1 - } - Write-Host "πŸ’» Opening shell in $Service..." -ForegroundColor Cyan - docker-compose -f $ComposeFile exec $Service /bin/sh - } - - "db" { - Write-Host "πŸ—ƒοΈ Connecting to database..." -ForegroundColor Cyan - $envFile = ".env" - $dbUser = "scriptshare_user" - $dbPassword = "ScriptShare_App_2024_Secure!" - $dbName = "scriptshare" - - if (Test-Path $envFile) { - $env = Get-Content $envFile | ConvertFrom-StringData - if ($env.DB_USER) { $dbUser = $env.DB_USER } - if ($env.DB_PASSWORD) { $dbPassword = $env.DB_PASSWORD } - if ($env.DB_NAME) { $dbName = $env.DB_NAME } - } - - docker-compose -f $ComposeFile exec scriptshare-db mysql -u $dbUser -p$dbPassword $dbName - } - - "help" { - Show-Help - } - - default { - Write-Host "❌ Unknown command: $Command" -ForegroundColor Red - Write-Host "" - Show-Help - exit 1 - } -} diff --git a/scripts/manage.sh b/scripts/manage.sh deleted file mode 100644 index 107da67..0000000 --- a/scripts/manage.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/bash -# ScriptShare Management Script - -set -e - -COMPOSE_FILE="docker-compose.prod.yml" - -show_help() { - echo "ScriptShare Management Script" - echo "" - echo "Usage: $0 [COMMAND]" - echo "" - echo "Commands:" - echo " start Start all services" - echo " stop Stop all services" - echo " restart Restart all services" - echo " logs Show logs for all services" - echo " logs [svc] Show logs for specific service" - echo " status Show status of all services" - echo " backup Create database backup" - echo " restore Restore database from backup" - echo " update Update application (pull, build, restart)" - echo " clean Clean up unused Docker resources" - echo " shell [svc] Open shell in service container" - echo " db Connect to database" - echo " help Show this help message" - echo "" - echo "Services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy, scriptshare-redis" -} - -case "$1" in - start) - echo "πŸš€ Starting ScriptShare services..." - docker-compose -f "$COMPOSE_FILE" up -d - echo "βœ… Services started" - ;; - - stop) - echo "πŸ›‘ Stopping ScriptShare services..." - docker-compose -f "$COMPOSE_FILE" down - echo "βœ… Services stopped" - ;; - - restart) - echo "πŸ”„ Restarting ScriptShare services..." - docker-compose -f "$COMPOSE_FILE" restart - echo "βœ… Services restarted" - ;; - - logs) - if [ -n "$2" ]; then - echo "πŸ“‹ Showing logs for $2..." - docker-compose -f "$COMPOSE_FILE" logs -f "$2" - else - echo "πŸ“‹ Showing logs for all services..." - docker-compose -f "$COMPOSE_FILE" logs -f - fi - ;; - - status) - echo "πŸ“Š Service Status:" - docker-compose -f "$COMPOSE_FILE" ps - echo "" - echo "πŸ₯ Health Status:" - for service in scriptshare-db scriptshare-api scriptshare-frontend scriptshare-proxy; do - health=$(docker inspect --format='{{.State.Health.Status}}' "$service" 2>/dev/null || echo "not found") - echo " $service: $health" - done - ;; - - backup) - echo "πŸ—„οΈ Creating database backup..." - ./scripts/backup.sh - ;; - - restore) - if [ -z "$2" ]; then - echo "❌ Please specify backup file to restore" - echo "Usage: $0 restore " - exit 1 - fi - echo "πŸ”„ Restoring database from $2..." - # Implementation for restore would go here - echo "⚠️ Restore functionality not yet implemented" - ;; - - update) - echo "πŸ”„ Updating ScriptShare application..." - docker-compose -f "$COMPOSE_FILE" pull - docker-compose -f "$COMPOSE_FILE" build --no-cache - docker-compose -f "$COMPOSE_FILE" up -d - echo "βœ… Application updated" - ;; - - clean) - echo "🧹 Cleaning up Docker resources..." - docker system prune -f - docker volume prune -f - echo "βœ… Cleanup completed" - ;; - - shell) - if [ -z "$2" ]; then - echo "❌ Please specify service name" - echo "Available services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy" - exit 1 - fi - echo "πŸ’» Opening shell in $2..." - docker-compose -f "$COMPOSE_FILE" exec "$2" /bin/sh - ;; - - db) - echo "πŸ—ƒοΈ Connecting to database..." - if [ -f ".env" ]; then - source .env - fi - docker-compose -f "$COMPOSE_FILE" exec scriptshare-db mysql -u "${DB_USER:-scriptshare_user}" -p"${DB_PASSWORD:-ScriptShare_App_2024_Secure!}" "${DB_NAME:-scriptshare}" - ;; - - help|--help|-h) - show_help - ;; - - *) - echo "❌ Unknown command: $1" - echo "" - show_help - exit 1 - ;; -esac diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..f76aca9 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,179 @@ +import express from 'express'; +import cors from 'cors'; +import { createUser, getUserByEmail, updateUser, getAllUsers, getUserById } from './lib/api/users.js'; +import { getScripts, getScriptById, createScript, updateScript, deleteScript, moderateScript } from './lib/api/scripts.js'; +import { login, register, refreshToken } from './lib/api/auth.js'; +import { rateScript, getUserRating, getScriptRatingStats } from './lib/api/ratings.js'; +import { getPlatformAnalytics, getScriptAnalytics, trackEvent } from './lib/api/analytics.js'; +import { createCollection, getUserCollections, getPublicCollections, addScriptToCollection } from './lib/api/collections.js'; + +const app = express(); +const PORT = process.env.PORT || 3000; + +// Middleware +app.use(cors({ + origin: process.env.CORS_ORIGIN || '*', + credentials: true +})); +app.use(express.json({ limit: '10mb' })); +app.use(express.urlencoded({ extended: true })); + +// Health check endpoint +app.get('/api/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString() }); +}); + +// Auth routes +app.post('/api/auth/login', async (req, res) => { + try { + const result = await login(req.body); + res.json(result); + } catch (error) { + console.error('Login error:', error); + res.status(401).json({ error: 'Invalid credentials' }); + } +}); + +app.post('/api/auth/register', async (req, res) => { + try { + const result = await register(req.body); + res.json(result); + } catch (error) { + console.error('Register error:', error); + res.status(400).json({ error: 'Registration failed' }); + } +}); + +// Scripts routes +app.get('/api/scripts', async (req, res) => { + try { + const result = await getScripts(req.query); + res.json(result); + } catch (error) { + console.error('Get scripts error:', error); + res.status(500).json({ error: 'Failed to fetch scripts' }); + } +}); + +app.get('/api/scripts/:id', async (req, res) => { + try { + const script = await getScriptById(req.params.id); + if (!script) { + return res.status(404).json({ error: 'Script not found' }); + } + res.json(script); + } catch (error) { + console.error('Get script error:', error); + res.status(500).json({ error: 'Failed to fetch script' }); + } +}); + +app.post('/api/scripts', async (req, res) => { + try { + const userId = req.headers['x-user-id'] as string; + if (!userId) { + return res.status(401).json({ error: 'Unauthorized' }); + } + const result = await createScript(req.body, userId); + res.json(result); + } catch (error) { + console.error('Create script error:', error); + res.status(500).json({ error: 'Failed to create script' }); + } +}); + +// Users routes +app.get('/api/users', async (req, res) => { + try { + const result = await getAllUsers(); + res.json(result); + } catch (error) { + console.error('Get users error:', error); + res.status(500).json({ error: 'Failed to fetch users' }); + } +}); + +app.get('/api/users/:id', async (req, res) => { + try { + const user = await getUserById(req.params.id); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + res.json(user); + } catch (error) { + console.error('Get user error:', error); + res.status(500).json({ error: 'Failed to fetch user' }); + } +}); + +// Analytics routes +app.get('/api/analytics/platform', async (req, res) => { + try { + const days = parseInt(req.query.days as string) || 30; + const result = await getPlatformAnalytics(days); + res.json(result); + } catch (error) { + console.error('Analytics error:', error); + res.status(500).json({ error: 'Failed to fetch analytics' }); + } +}); + +app.post('/api/analytics/track', async (req, res) => { + try { + const result = await trackEvent(req.body); + res.json(result); + } catch (error) { + console.error('Track event error:', error); + res.status(500).json({ error: 'Failed to track event' }); + } +}); + +// Collections routes +app.get('/api/collections', async (req, res) => { + try { + const userId = req.headers['x-user-id'] as string; + const result = userId ? await getUserCollections(userId) : await getPublicCollections(); + res.json(result); + } catch (error) { + console.error('Get collections error:', error); + res.status(500).json({ error: 'Failed to fetch collections' }); + } +}); + +// Ratings routes +app.post('/api/ratings', async (req, res) => { + try { + const result = await rateScript(req.body); + res.json(result); + } catch (error) { + console.error('Rate script error:', error); + res.status(500).json({ error: 'Failed to rate script' }); + } +}); + +app.get('/api/scripts/:id/ratings', async (req, res) => { + try { + const result = await getScriptRatingStats(req.params.id); + res.json(result); + } catch (error) { + console.error('Get ratings error:', error); + res.status(500).json({ error: 'Failed to fetch ratings' }); + } +}); + +// Error handling middleware +app.use((error: any, req: express.Request, res: express.Response, next: express.NextFunction) => { + console.error('Unhandled error:', error); + res.status(500).json({ error: 'Internal server error' }); +}); + +// 404 handler +app.use('*', (req, res) => { + res.status(404).json({ error: 'Endpoint not found' }); +}); + +app.listen(PORT, () => { + console.log(`ScriptShare API server running on port ${PORT}`); + console.log(`Environment: ${process.env.NODE_ENV}`); + console.log(`Database URL configured: ${!!process.env.DATABASE_URL}`); +});