diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b5183f..e73a083 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,114 +1,73 @@ # Contributing to Outray -Thanks for your interest in contributing to Outray! This guide will help you get started. +Thanks for your interest in contributing to Outray! This guide will help you get set up and start shipping features quickly. ## Project Structure +Our monorepo is organized to keep logic decoupled and reusable: + ``` outray/ ├── apps/ -│ ├── cli/ # CLI client for creating tunnels -│ ├── cron/ # Background jobs (tunnel snapshots) -│ ├── internal-check/ # Domain verification for Caddy on-demand TLS -│ ├── landing/ # Marketing website (Astro) -│ ├── tunnel/ # Tunnel server (HTTP, TCP, UDP proxying) -│ └── web/ # Dashboard & API (React + TanStack Router) -├── shared/ # Shared utilities and types -└── deploy/ # Deployment scripts and configs +│ ├── cli/ # Main Outray CLI (TypeScript) +│ ├── web/ # Dashboard & API (React + TanStack Start) +│ ├── tunnel/ # High-performance Tunnel Server +│ ├── cron/ # Maintenance snapshots & background tasks +│ └── internal-check/ # Caddy domain verification service +├── packages/ +│ ├── core/ # Shared tunnel core logic +│ ├── vite-plugin/ # Outray integration for Vite +│ └── ...plugins/ # Next.js, Express, NestJS plugins +├── shared/ # Global types and utility helpers +└── deploy/ # Infrastructure-as-Code & scripts ``` -## Prerequisites - -- Node.js 20+ -- npm -- Redis (for tunnel state) -- PostgreSQL (for user data) -- Tiger Data / TimescaleDB (for analytics) +## Quick Start (Local Setup) -## Getting Started - -1. **Clone the repository** +Prepare your environment in three simple steps: +1. **Clone & Install** ```bash git clone https://github.com/akinloluwami/outray.git cd outray - ``` - -2. **Install dependencies** - - ```bash npm install ``` -3. **Set up environment variables** - - Copy `.env.example` to `.env` in each app directory and fill in the values: - - ```bash - cp apps/web/.env.example apps/web/.env - cp apps/tunnel/.env.example apps/tunnel/.env - cp apps/cron/.env.example apps/cron/.env - cp apps/internal-check/.env.example apps/internal-check/.env - ``` - -4. **Run database migrations** - - ```bash - cd apps/web - npx drizzle-kit push - ``` - -5. **Set up Tiger Data (TimescaleDB) tables** - - Run the schema file against your TimescaleDB instance: - +2. **Initialize Environment** + We provide a helper script to set up all `.env` files across the monorepo: ```bash - psql "$TIMESCALE_URL" -f deploy/setup_tigerdata.sql + npm run setup:envs ``` -6. **Start development servers** - +3. **Spin Up Infrastructure** + Outray requires Redis, Postgres, and TimescaleDB. Use Docker to start them instantly: ```bash - # Terminal 1: Web dashboard - cd apps/web && npm run dev - - # Terminal 2: Tunnel server - cd apps/tunnel && npm run dev - - # Terminal 3: CLI (for testing) - cd apps/cli && npm run dev + docker compose up -d ``` -## Development - -### Web Dashboard (`apps/web`) - -- React with TanStack Router -- Drizzle ORM for database -- Better Auth for authentication +## Development Workflow -### Tunnel Server (`apps/tunnel`) +Instead of managing multiple terminals, use our root commands: -- Handles HTTP, TCP, and UDP tunneling -- WebSocket-based protocol for client communication -- Redis for tunnel state management +- **Full Application**: Run `npm run dev` in the root to start the Web Dashboard, Tunnel Server, and CLI in parallel. +- **Specific App**: Run `npm run dev -w apps/web` (or any other app). +- **Database Migrations**: + ```bash + cd apps/web + npm run db:migrate + ``` -### CLI (`apps/cli`) +## Code Guidelines -- TypeScript CLI for creating tunnels -- Supports HTTP, TCP, and UDP protocols - -## Code Style - -- Use TypeScript -- Follow existing code patterns -- Run `npm run lint` before committing +- **TypeScript First**: All new code must be type-safe. +- **Consistency**: Follow the patterns in `packages/core` for any tunnel logic. +- **Linting**: Run `npm run lint` at the root before pushing. ## Pull Requests -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/my-feature`) -3. Make your changes -4. Test your changes locally -5. Commit with a descriptive message -6. Push and open a PR. Add a detailed description of your changes and attach a screenshot if you made UI changes. +1. **Branching**: Use `feat/`, `fix/`, or `docs/` prefixes (e.g., `feat/add-github-oauth`). +2. **Quality**: Ensure your code builds locally with `npm run build`. +3. **Description**: Describe *what* changed and *why*. Attach screenshots if you've touched the Dashboard UI. + +--- +*Stay sharp and happy coding!* diff --git a/README.md b/README.md index 77beef2..ecaed5a 100644 --- a/README.md +++ b/README.md @@ -49,12 +49,12 @@ outray udp 53 ``` outray/ ├── apps/ -│ ├── cli/ # CLI client -│ ├── cron/ # Background jobs -│ ├── internal-check/ # Domain verification for Caddy -│ ├── landing/ # Marketing website +│ ├── cli/ # Main CLI client +│ ├── web/ # Dashboard & API │ ├── tunnel/ # Tunnel server -│ └── web/ # Dashboard & API +│ ├── cron/ # Background jobs +│ └── internal-check/ # Caddy domain verification +├── packages/ # Core logic & plugins ├── shared/ # Shared utilities └── deploy/ # Deployment configs ``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..25f569c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,34 @@ +version: '3.8' + +services: + postgres: + image: postgres:16 + ports: + - "5432:5432" + environment: + POSTGRES_USER: user + POSTGRES_PASSWORD: password + POSTGRES_DB: outray + volumes: + - postgres_data:/var/lib/postgresql/data + + redis: + image: redis:alpine + ports: + - "6379:6379" + + timescale: + image: timescale/timescaledb-ha:pg16 + ports: + - "5433:5432" + environment: + POSTGRES_USER: user + POSTGRES_PASSWORD: password + POSTGRES_DB: outray_analytics + volumes: + - timescale_data:/var/lib/postgresql/data + +volumes: + postgres_data: + redis_data: + timescale_data: diff --git a/package.json b/package.json index a420a22..d4c0d83 100644 --- a/package.json +++ b/package.json @@ -3,21 +3,23 @@ "version": "1.0.0", "private": true, "workspaces": [ - "apps/tunnel", - "apps/cli", - "apps/web" + "apps/*", + "packages/*", + "shared" ], "scripts": { - "install:all": "npm install && cd apps/tunnel && npm install && cd ../cli && npm install && cd ../web && npm install", - "dev:tunnel": "cd apps/tunnel && npm run dev", - "dev:web": "cd apps/web && npm run dev", - "build": "cd apps/tunnel && npm run build && cd ../cli && npm run build && cd ../web && npm run build" + "dev": "concurrently \"npm run dev -w apps/web\" \"npm run dev -w apps/tunnel\" \"npm run dev -w apps/cli\"", + "install:all": "npm install", + "setup:envs": "node ./scripts/setup-envs.js", + "build": "npm run build --workspaces --if-present", + "lint": "npm run lint --workspaces --if-present" }, "devDependencies": { + "concurrently": "^9.1.0", "typescript": "^5.7.2" }, "dependencies": { "axios": "^1.13.2", "zustand": "^5.0.9" } -} +} \ No newline at end of file diff --git a/scripts/setup-envs.js b/scripts/setup-envs.js new file mode 100644 index 0000000..c47f213 --- /dev/null +++ b/scripts/setup-envs.js @@ -0,0 +1,25 @@ +const fs = require('fs'); +const path = require('path'); + +const apps = [ + 'apps/web', + 'apps/tunnel', + 'apps/cron', + 'apps/internal-check' +]; + +apps.forEach(appDir => { + const examplePath = path.join(appDir, '.env.example'); + const envPath = path.join(appDir, '.env'); + + if (fs.existsSync(examplePath)) { + if (!fs.existsSync(envPath)) { + fs.copyFileSync(examplePath, envPath); + console.log(`✅ Created .env for ${appDir}`); + } else { + console.log(`ℹ️ .env already exists for ${appDir}, skipping.`); + } + } +}); + +console.log('✨ Environment variable setup complete!');