fix: Configure Vite proxy to eliminate CORS issues in development
Implemented a comprehensive CORS proxy solution that works with both
local and remote backends during development.
## Changes
### Vite Configuration (vite.config.ts)
- Use loadEnv() to properly read VITE_API_BASE_URL from .env
- Configure proxy to forward /api/* requests to backend
- Add detailed logging for proxy requests and responses
- Support changeOrigin, rewrite, secure=false, and websockets
### API Client (src/lib/api/client.ts)
- In development: Always use /api prefix (proxied)
- In production: Use direct VITE_API_BASE_URL
- Add console logging to show proxy configuration in dev mode
- Automatic detection of environment (DEV vs PROD)
### Error Handling (route loaders)
- Fix console.error() calls that caused TypeError with circular refs
- Use error.message instead of logging full error objects
- Affects: +page.ts, matches/+page.ts
### Documentation
- docs/LOCAL_DEVELOPMENT.md: Complete rewrite with proxy explanation
- Quick start guide for both production API and local backend
- Detailed proxy flow diagrams
- Comprehensive troubleshooting section
- Clear examples and logs
- docs/CORS_PROXY.md: Technical deep-dive on proxy implementation
- How the proxy works internally
- Configuration options explained
- Testing procedures
- Common issues and solutions
- .env.example: Updated with proxy documentation
## How It Works
Development Flow:
1. Frontend makes request: /api/matches
2. Vite proxy intercepts and forwards to: ${VITE_API_BASE_URL}/matches
3. Backend responds (no CORS headers needed)
4. Proxy returns response to frontend (same-origin)
Production Flow:
1. Frontend makes request directly to: https://api.csgow.tf/matches
2. Backend responds with CORS headers
3. Browser allows request (CORS enabled on backend)
## Benefits
✅ No CORS errors in development
✅ Works with local backend (localhost:8000)
✅ Works with remote backend (api.csgow.tf)
✅ Simple configuration (just set VITE_API_BASE_URL)
✅ Detailed logging for debugging
✅ Production build unaffected (direct requests)
## Testing
Verified with production API:
- curl https://api.csgow.tf/matches ✓
- Dev server proxy logs show successful forwarding ✓
- Browser Network tab shows /api/* requests ✓
- No CORS errors in console ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -7,8 +7,9 @@
|
|||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
# Backend API Base URL
|
# Backend API Base URL
|
||||||
# Default: http://localhost:8000 (local development)
|
# Development: Vite proxy forwards /api to this URL (default: http://localhost:8000)
|
||||||
# Production: https://api.csgow.tf or your backend URL
|
# Production: Set to your actual backend URL (e.g., https://api.csgow.tf)
|
||||||
|
# Note: In development, the frontend uses /api and Vite proxies to this URL
|
||||||
VITE_API_BASE_URL=http://localhost:8000
|
VITE_API_BASE_URL=http://localhost:8000
|
||||||
|
|
||||||
# API request timeout in milliseconds
|
# API request timeout in milliseconds
|
||||||
|
|||||||
234
docs/CORS_PROXY.md
Normal file
234
docs/CORS_PROXY.md
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
# CORS Proxy Configuration
|
||||||
|
|
||||||
|
This document explains how the CORS proxy works in the CS2.WTF frontend.
|
||||||
|
|
||||||
|
## Problem: CORS in Development
|
||||||
|
|
||||||
|
When developing a frontend that talks to an API on a different origin, browsers enforce CORS (Cross-Origin Resource Sharing) policies. This causes errors like:
|
||||||
|
|
||||||
|
```
|
||||||
|
Access to fetch at 'https://api.csgow.tf/matches' from origin 'http://localhost:5173'
|
||||||
|
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
|
||||||
|
on the requested resource.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Solution: Vite Development Proxy
|
||||||
|
|
||||||
|
The Vite dev server includes a built-in proxy that solves this problem by making all API requests appear same-origin.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
**File**: `vite.config.ts`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { loadEnv } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig(({ mode }) => {
|
||||||
|
const env = loadEnv(mode, process.cwd(), '');
|
||||||
|
const apiBaseUrl = env.VITE_API_BASE_URL || 'http://localhost:8000';
|
||||||
|
|
||||||
|
return {
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: apiBaseUrl,
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
|
secure: false,
|
||||||
|
ws: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
1. **API Client** (in development) makes requests to `/api/*`:
|
||||||
|
```typescript
|
||||||
|
// src/lib/api/client.ts
|
||||||
|
const API_BASE_URL = import.meta.env.DEV ? '/api' : VITE_API_BASE_URL;
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Vite Proxy** intercepts requests to `/api/*` and forwards them:
|
||||||
|
```
|
||||||
|
Browser Request: GET http://localhost:5173/api/matches?limit=6
|
||||||
|
↓
|
||||||
|
Vite Proxy: Intercepts /api/* requests
|
||||||
|
↓
|
||||||
|
Backend Request: GET https://api.csgow.tf/matches?limit=6
|
||||||
|
↓
|
||||||
|
Response: ← Returns data through proxy
|
||||||
|
↓
|
||||||
|
Browser: ← Receives response (appears same-origin)
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Browser sees same-origin request** - no CORS error!
|
||||||
|
|
||||||
|
### Configuration Options
|
||||||
|
|
||||||
|
| Option | Value | Purpose |
|
||||||
|
|--------|-------|---------|
|
||||||
|
| `target` | `env.VITE_API_BASE_URL` | Where to forward requests |
|
||||||
|
| `changeOrigin` | `true` | Updates `Origin` header to match target |
|
||||||
|
| `rewrite` | Remove `/api` prefix | Maps `/api/matches` → `/matches` |
|
||||||
|
| `secure` | `false` | Allow self-signed certificates |
|
||||||
|
| `ws` | `true` | Enable WebSocket proxying |
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
**`.env`**:
|
||||||
|
```env
|
||||||
|
# Proxy will forward /api/* to this URL
|
||||||
|
VITE_API_BASE_URL=https://api.csgow.tf
|
||||||
|
|
||||||
|
# Or use local backend
|
||||||
|
# VITE_API_BASE_URL=http://localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
The proxy logs all requests for debugging:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[Vite Config] API Proxy target: https://api.csgow.tf
|
||||||
|
[Proxy] GET /api/matches?limit=6 -> https://api.csgow.tf/matches?limit=6
|
||||||
|
[Proxy ✓] GET /api/matches?limit=6 -> 200
|
||||||
|
[Proxy] GET /api/match/123 -> https://api.csgow.tf/match/123
|
||||||
|
[Proxy ✓] GET /api/match/123 -> 200
|
||||||
|
```
|
||||||
|
|
||||||
|
Error logging:
|
||||||
|
```bash
|
||||||
|
[Proxy Error] ECONNREFUSED
|
||||||
|
[Proxy Error] Make sure backend is running at: http://localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Client Configuration
|
||||||
|
|
||||||
|
**File**: `src/lib/api/client.ts`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const getAPIBaseURL = (): string => {
|
||||||
|
// In production builds, use the configured URL directly
|
||||||
|
if (import.meta.env.PROD) {
|
||||||
|
return import.meta.env?.VITE_API_BASE_URL || 'https://api.csgow.tf';
|
||||||
|
}
|
||||||
|
|
||||||
|
// In development mode, ALWAYS use the Vite proxy to avoid CORS issues
|
||||||
|
// The proxy will forward /api requests to VITE_API_BASE_URL
|
||||||
|
return '/api';
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures:
|
||||||
|
- ✅ **Development**: Always uses `/api` (proxy handles CORS)
|
||||||
|
- ✅ **Production**: Uses direct URL (backend has CORS enabled)
|
||||||
|
|
||||||
|
## Testing the Proxy
|
||||||
|
|
||||||
|
### 1. Check Vite Config Loads Environment
|
||||||
|
|
||||||
|
Start dev server and look for:
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Should show:
|
||||||
|
[Vite Config] API Proxy target: https://api.csgow.tf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Check API Client Configuration
|
||||||
|
|
||||||
|
Open browser console, look for:
|
||||||
|
```
|
||||||
|
[API Client] Development mode - using Vite proxy
|
||||||
|
[API Client] Frontend requests: /api/*
|
||||||
|
[API Client] Proxy target: https://api.csgow.tf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Check Network Requests
|
||||||
|
|
||||||
|
Open DevTools → Network tab:
|
||||||
|
- ✅ Requests should go to `/api/*` (not full URL)
|
||||||
|
- ✅ Response should be `200 OK`
|
||||||
|
- ✅ No CORS errors in console
|
||||||
|
|
||||||
|
### 4. Check Proxy Logs
|
||||||
|
|
||||||
|
Terminal should show:
|
||||||
|
```
|
||||||
|
[Proxy] GET /api/matches -> https://api.csgow.tf/matches
|
||||||
|
[Proxy ✓] GET /api/matches -> 200
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Issue 1: Proxy Not Loading .env
|
||||||
|
|
||||||
|
**Symptom**: Proxy uses default `http://localhost:8000` instead of `.env` value
|
||||||
|
|
||||||
|
**Cause**: `vite.config.ts` not loading environment variables
|
||||||
|
|
||||||
|
**Fix**: Use `loadEnv()` in config:
|
||||||
|
```typescript
|
||||||
|
import { loadEnv } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig(({ mode }) => {
|
||||||
|
const env = loadEnv(mode, process.cwd(), '');
|
||||||
|
const apiBaseUrl = env.VITE_API_BASE_URL || 'http://localhost:8000';
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue 2: Still Getting CORS Errors
|
||||||
|
|
||||||
|
**Symptom**: Browser console shows CORS errors
|
||||||
|
|
||||||
|
**Possible Causes**:
|
||||||
|
1. API client not using `/api` prefix in development
|
||||||
|
2. Request bypassing proxy somehow
|
||||||
|
3. Running production build instead of dev server
|
||||||
|
|
||||||
|
**Fix**:
|
||||||
|
1. Check API client logs show: `Development mode - using Vite proxy`
|
||||||
|
2. Verify Network tab shows requests to `/api/*`
|
||||||
|
3. Run `npm run dev` (not `npm run preview`)
|
||||||
|
|
||||||
|
### Issue 3: Connection Refused
|
||||||
|
|
||||||
|
**Symptom**: `[Proxy Error] ECONNREFUSED`
|
||||||
|
|
||||||
|
**Cause**: Backend is not running at the configured URL
|
||||||
|
|
||||||
|
**Fix**:
|
||||||
|
- If using local backend: Start `csgowtfd` on port 8000
|
||||||
|
- If using production API: Check `VITE_API_BASE_URL=https://api.csgow.tf`
|
||||||
|
|
||||||
|
## Production Build
|
||||||
|
|
||||||
|
In production, the proxy is **not used**. The frontend makes direct requests to the backend:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Production build
|
||||||
|
const API_BASE_URL = 'https://api.csgow.tf';
|
||||||
|
|
||||||
|
// Direct request (no proxy)
|
||||||
|
fetch('https://api.csgow.tf/matches');
|
||||||
|
```
|
||||||
|
|
||||||
|
The production API must have CORS enabled:
|
||||||
|
```
|
||||||
|
Access-Control-Allow-Origin: https://cs2.wtf
|
||||||
|
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||||
|
Access-Control-Allow-Headers: Content-Type, Authorization
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| Environment | Frontend URL | API Requests | CORS |
|
||||||
|
|-------------|-------------|--------------|------|
|
||||||
|
| **Development** | `http://localhost:5173` | `/api/*` → Proxy → Backend | ✅ Proxy handles |
|
||||||
|
| **Production** | `https://cs2.wtf` | Direct to backend | ✅ Backend CORS |
|
||||||
|
|
||||||
|
The proxy is a **development-only** feature that makes local development smooth and eliminates CORS headaches.
|
||||||
318
docs/LOCAL_DEVELOPMENT.md
Normal file
318
docs/LOCAL_DEVELOPMENT.md
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
# Local Development Setup
|
||||||
|
|
||||||
|
This guide will help you set up the CS2.WTF frontend for local development.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **Node.js**: v18.x or v20.x (check with `node --version`)
|
||||||
|
- **npm**: v9.x or higher (comes with Node.js)
|
||||||
|
- **Backend API**: Either local csgowtfd service OR access to production API
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Install Dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Environment Configuration
|
||||||
|
|
||||||
|
The `.env` file already exists in the project. You can use it as-is or modify it:
|
||||||
|
|
||||||
|
**Option A: Use Production API** (Recommended for frontend development)
|
||||||
|
```env
|
||||||
|
# Use the live production API - no local backend needed
|
||||||
|
VITE_API_BASE_URL=https://api.csgow.tf
|
||||||
|
VITE_API_TIMEOUT=10000
|
||||||
|
VITE_DEBUG_MODE=true
|
||||||
|
VITE_ENABLE_ANALYTICS=false
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B: Use Local Backend** (For full-stack development)
|
||||||
|
```env
|
||||||
|
# Use local backend (requires csgowtfd running on port 8000)
|
||||||
|
VITE_API_BASE_URL=http://localhost:8000
|
||||||
|
VITE_API_TIMEOUT=10000
|
||||||
|
VITE_DEBUG_MODE=true
|
||||||
|
VITE_ENABLE_ANALYTICS=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Start the Development Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
The frontend will be available at `http://localhost:5173`
|
||||||
|
|
||||||
|
You should see output like:
|
||||||
|
```
|
||||||
|
[Vite Config] API Proxy target: https://api.csgow.tf
|
||||||
|
[API Client] Development mode - using Vite proxy
|
||||||
|
[API Client] Frontend requests: /api/*
|
||||||
|
[API Client] Proxy target: https://api.csgow.tf
|
||||||
|
|
||||||
|
➜ Local: http://localhost:5173/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. (Optional) Start Local Backend
|
||||||
|
|
||||||
|
Only needed if using `VITE_API_BASE_URL=http://localhost:8000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In the csgowtfd repository
|
||||||
|
cd ../csgowtfd
|
||||||
|
go run cmd/csgowtfd/main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use Docker:
|
||||||
|
```bash
|
||||||
|
docker-compose up csgowtfd
|
||||||
|
```
|
||||||
|
|
||||||
|
## How the CORS Proxy Works
|
||||||
|
|
||||||
|
The Vite dev server includes a **built-in proxy** that eliminates CORS issues during development:
|
||||||
|
|
||||||
|
### Development Mode Flow
|
||||||
|
```
|
||||||
|
1. Browser makes request to: http://localhost:5173/api/matches
|
||||||
|
2. Vite intercepts and proxies to: ${VITE_API_BASE_URL}/matches
|
||||||
|
3. Backend responds
|
||||||
|
4. Vite forwards response to browser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Benefits
|
||||||
|
- ✅ **No CORS errors** - All requests appear same-origin to the browser
|
||||||
|
- ✅ **Works with any backend** - Local or remote
|
||||||
|
- ✅ **No backend CORS config needed** - Proxy handles it
|
||||||
|
- ✅ **Simple configuration** - Just set `VITE_API_BASE_URL`
|
||||||
|
|
||||||
|
### Proxy Logs
|
||||||
|
|
||||||
|
You'll see detailed proxy activity in the terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[Proxy] GET /api/matches?limit=6 -> https://api.csgow.tf/matches?limit=6
|
||||||
|
[Proxy ✓] GET /api/matches?limit=6 -> 200
|
||||||
|
[Proxy] GET /api/match/123 -> https://api.csgow.tf/match/123
|
||||||
|
[Proxy ✓] GET /api/match/123 -> 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production vs Development
|
||||||
|
|
||||||
|
| Mode | API Base URL | CORS |
|
||||||
|
|------|-------------|------|
|
||||||
|
| **Development** (`npm run dev`) | `/api` (proxied to `VITE_API_BASE_URL`) | ✅ No issues |
|
||||||
|
| **Production** (`npm run build`) | `VITE_API_BASE_URL` (direct) | ✅ Backend has CORS enabled |
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### No Data Showing / Network Errors
|
||||||
|
|
||||||
|
**Problem**: Frontend loads but shows no matches, players show "Failed to load" errors.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Check what backend you're using**:
|
||||||
|
```bash
|
||||||
|
# Look at your .env file
|
||||||
|
cat .env | grep VITE_API_BASE_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **If using production API** (`https://api.csgow.tf`):
|
||||||
|
```bash
|
||||||
|
# Test if production API is accessible
|
||||||
|
curl https://api.csgow.tf/matches?limit=1
|
||||||
|
```
|
||||||
|
Should return JSON data. If not, production API may be down.
|
||||||
|
|
||||||
|
3. **If using local backend** (`http://localhost:8000`):
|
||||||
|
```bash
|
||||||
|
# Test if local backend is running
|
||||||
|
curl http://localhost:8000/matches?limit=1
|
||||||
|
```
|
||||||
|
If you get "Connection refused", start the backend service.
|
||||||
|
|
||||||
|
4. **Check proxy logs**:
|
||||||
|
- Look at the terminal running `npm run dev`
|
||||||
|
- You should see `[Proxy]` messages showing requests being forwarded
|
||||||
|
- If you see `[Proxy Error]`, check the error message
|
||||||
|
|
||||||
|
5. **Check browser console**:
|
||||||
|
- Open DevTools → Console tab
|
||||||
|
- Look for `[API Client]` messages showing proxy configuration
|
||||||
|
- Network tab should show requests to `/api/*` (not external URLs)
|
||||||
|
|
||||||
|
6. **Restart dev server**:
|
||||||
|
```bash
|
||||||
|
# Stop dev server (Ctrl+C)
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### CORS Errors (Should Not Happen)
|
||||||
|
|
||||||
|
If you see CORS errors in the browser console, the proxy isn't working:
|
||||||
|
|
||||||
|
**Symptoms**:
|
||||||
|
- Browser console shows: `CORS policy: No 'Access-Control-Allow-Origin' header`
|
||||||
|
- Network tab shows requests going to `https://api.csgow.tf` directly (not `/api`)
|
||||||
|
|
||||||
|
**Fix**:
|
||||||
|
1. Verify you're in development mode (not production build)
|
||||||
|
2. Check API client logs show: `Development mode - using Vite proxy`
|
||||||
|
3. Restart dev server with clean cache:
|
||||||
|
```bash
|
||||||
|
rm -rf .svelte-kit
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port Already in Use
|
||||||
|
|
||||||
|
If port 5173 is already in use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vite will automatically try the next available port
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Or specify a custom port
|
||||||
|
npm run dev -- --port 3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backend Connection Issues
|
||||||
|
|
||||||
|
If the backend is on a different host/port, update `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Custom backend location
|
||||||
|
VITE_API_BASE_URL=http://192.168.1.100:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Then restart the dev server.
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### 1. Make Changes
|
||||||
|
|
||||||
|
Edit files in `src/`. The dev server has hot module replacement (HMR):
|
||||||
|
- Component changes reload instantly
|
||||||
|
- Route changes reload the page
|
||||||
|
- Store changes reload affected components
|
||||||
|
|
||||||
|
### 2. Type Checking
|
||||||
|
|
||||||
|
Run TypeScript type checking:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run check # Check once
|
||||||
|
npm run check:watch # Watch mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Linting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint # Check for issues
|
||||||
|
npm run lint:fix # Auto-fix issues
|
||||||
|
npm run format # Run Prettier
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Unit tests
|
||||||
|
npm run test # Run once
|
||||||
|
npm run test:watch # Watch mode
|
||||||
|
npm run test:coverage # Generate coverage report
|
||||||
|
|
||||||
|
# E2E tests
|
||||||
|
npm run test:e2e # Headless
|
||||||
|
npm run test:e2e:ui # Playwright UI
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
The backend provides these endpoints (see `docs/API.md` for full details):
|
||||||
|
|
||||||
|
- `GET /matches` - List all matches
|
||||||
|
- `GET /match/:id` - Get match details
|
||||||
|
- `GET /match/:id/rounds` - Get round economy data
|
||||||
|
- `GET /match/:id/weapons` - Get weapon statistics
|
||||||
|
- `GET /match/:id/chat` - Get chat messages
|
||||||
|
- `GET /player/:id` - Get player profile
|
||||||
|
|
||||||
|
### How Requests Work
|
||||||
|
|
||||||
|
**In Development** (`npm run dev`):
|
||||||
|
```
|
||||||
|
Frontend code: api.matches.getMatches()
|
||||||
|
↓
|
||||||
|
API Client: GET /api/matches
|
||||||
|
↓
|
||||||
|
Vite Proxy: GET https://api.csgow.tf/matches
|
||||||
|
↓
|
||||||
|
Response: ← Data returned to frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
**In Production** (deployed app):
|
||||||
|
```
|
||||||
|
Frontend code: api.matches.getMatches()
|
||||||
|
↓
|
||||||
|
API Client: GET https://api.csgow.tf/matches (direct)
|
||||||
|
↓
|
||||||
|
Response: ← Data returned to frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
The API client automatically uses the correct URL based on environment.
|
||||||
|
|
||||||
|
## Mock Data (Alternative: No Backend)
|
||||||
|
|
||||||
|
If you want to develop without any backend (local or production), enable MSW mocking:
|
||||||
|
|
||||||
|
1. Update `.env`:
|
||||||
|
```env
|
||||||
|
VITE_ENABLE_MSW_MOCKING=true
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Restart dev server
|
||||||
|
|
||||||
|
The app will use mock data from `src/mocks/handlers/`.
|
||||||
|
|
||||||
|
**Note**: Mock data is limited and may not reflect all features. **Production API is recommended** for most development work.
|
||||||
|
|
||||||
|
## Building for Production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Preview production build locally
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
The preview server runs on `http://localhost:4173` and uses the production API configuration.
|
||||||
|
|
||||||
|
## Environment Variables Reference
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `VITE_API_BASE_URL` | `http://localhost:8000` | Backend API base URL |
|
||||||
|
| `VITE_API_TIMEOUT` | `10000` | Request timeout (ms) |
|
||||||
|
| `VITE_ENABLE_LIVE_MATCHES` | `false` | Enable live match polling |
|
||||||
|
| `VITE_ENABLE_ANALYTICS` | `false` | Enable analytics tracking |
|
||||||
|
| `VITE_DEBUG_MODE` | `false` | Enable debug logging |
|
||||||
|
| `VITE_ENABLE_MSW_MOCKING` | `false` | Use mock data instead of API |
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
- **Frontend Issues**: Check browser console for errors
|
||||||
|
- **API Issues**: Check backend logs and proxy output in terminal
|
||||||
|
- **Type Errors**: Run `npm run check` for detailed messages
|
||||||
|
- **Build Issues**: Delete `.svelte-kit/` and `node_modules/`, then `npm install`
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- Read `TODO.md` for current development status
|
||||||
|
- Check `docs/DESIGN.md` for design system documentation
|
||||||
|
- Review `docs/API.md` for complete API reference
|
||||||
|
- See `README.md` for project overview
|
||||||
@@ -5,13 +5,28 @@ import { APIException } from '$lib/types';
|
|||||||
/**
|
/**
|
||||||
* API Client Configuration
|
* API Client Configuration
|
||||||
*/
|
*/
|
||||||
const API_BASE_URL =
|
const getAPIBaseURL = (): string => {
|
||||||
typeof window !== 'undefined'
|
// In production builds, use the configured URL directly
|
||||||
? import.meta.env?.VITE_API_BASE_URL || 'http://localhost:8000'
|
if (import.meta.env.PROD) {
|
||||||
: 'http://localhost:8000';
|
return import.meta.env?.VITE_API_BASE_URL || 'https://api.csgow.tf';
|
||||||
|
}
|
||||||
|
|
||||||
|
// In development mode, ALWAYS use the Vite proxy to avoid CORS issues
|
||||||
|
// The proxy will forward /api requests to VITE_API_BASE_URL
|
||||||
|
// This works regardless of whether the backend is local or remote
|
||||||
|
return '/api';
|
||||||
|
};
|
||||||
|
|
||||||
|
const API_BASE_URL = getAPIBaseURL();
|
||||||
const API_TIMEOUT = Number(import.meta.env?.VITE_API_TIMEOUT) || 10000;
|
const API_TIMEOUT = Number(import.meta.env?.VITE_API_TIMEOUT) || 10000;
|
||||||
|
|
||||||
|
// Log the API configuration in development
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
console.log('[API Client] Development mode - using Vite proxy');
|
||||||
|
console.log('[API Client] Frontend requests: /api/*');
|
||||||
|
console.log('[API Client] Proxy target:', import.meta.env?.VITE_API_BASE_URL || 'http://localhost:8000');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base API Client
|
* Base API Client
|
||||||
* Provides centralized HTTP communication with error handling
|
* Provides centralized HTTP communication with error handling
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const load: PageLoad = async ({ parent }) => {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Log error but don't fail the page load
|
// Log error but don't fail the page load
|
||||||
console.error('Failed to load featured matches:', error);
|
console.error('Failed to load featured matches:', error instanceof Error ? error.message : String(error));
|
||||||
|
|
||||||
// Return empty data - page will show without featured matches
|
// Return empty data - page will show without featured matches
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const load: PageLoad = async ({ url }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load matches:', error);
|
console.error('Failed to load matches:', error instanceof Error ? error.message : String(error));
|
||||||
|
|
||||||
// Return empty state on error
|
// Return empty state on error
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,32 +1,65 @@
|
|||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vitest/config';
|
||||||
|
import { loadEnv } from 'vite';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig(({ mode }) => {
|
||||||
plugins: [sveltekit()],
|
// Load env file based on `mode` in the current working directory.
|
||||||
test: {
|
// Set the third parameter to '' to load all env regardless of the `VITE_` prefix.
|
||||||
include: ['src/**/*.{test,spec}.{js,ts}'],
|
const env = loadEnv(mode, process.cwd(), '');
|
||||||
globals: true,
|
const apiBaseUrl = env.VITE_API_BASE_URL || 'http://localhost:8000';
|
||||||
environment: 'jsdom',
|
|
||||||
setupFiles: ['./src/tests/setup.ts'],
|
console.log('[Vite Config] API Proxy target:', apiBaseUrl);
|
||||||
coverage: {
|
|
||||||
provider: 'v8',
|
return {
|
||||||
reporter: ['text', 'json', 'html'],
|
plugins: [sveltekit()],
|
||||||
exclude: [
|
test: {
|
||||||
'node_modules/',
|
include: ['src/**/*.{test,spec}.{js,ts}'],
|
||||||
'src/tests/',
|
globals: true,
|
||||||
'**/*.d.ts',
|
environment: 'jsdom',
|
||||||
'**/*.config.*',
|
setupFiles: ['./src/tests/setup.ts'],
|
||||||
'**/mockData',
|
coverage: {
|
||||||
'**/.svelte-kit'
|
provider: 'v8',
|
||||||
]
|
reporter: ['text', 'json', 'html'],
|
||||||
|
exclude: [
|
||||||
|
'node_modules/',
|
||||||
|
'src/tests/',
|
||||||
|
'**/*.d.ts',
|
||||||
|
'**/*.config.*',
|
||||||
|
'**/mockData',
|
||||||
|
'**/.svelte-kit'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
strictPort: false,
|
||||||
|
proxy: {
|
||||||
|
// Proxy API requests to backend to avoid CORS issues in development
|
||||||
|
// All requests to /api/* are forwarded to the backend
|
||||||
|
'/api': {
|
||||||
|
target: apiBaseUrl,
|
||||||
|
changeOrigin: true, // Updates the Origin header to match the target
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ''), // Remove /api prefix
|
||||||
|
secure: false, // Allow self-signed certificates
|
||||||
|
ws: true, // Proxy websockets
|
||||||
|
configure: (proxy, options) => {
|
||||||
|
proxy.on('error', (err, _req, _res) => {
|
||||||
|
console.error('[Proxy Error]', err.message);
|
||||||
|
console.error('[Proxy Error] Make sure backend is running at:', apiBaseUrl);
|
||||||
|
});
|
||||||
|
proxy.on('proxyReq', (proxyReq, req, _res) => {
|
||||||
|
console.log(`[Proxy] ${req.method} ${req.url} -> ${apiBaseUrl}${proxyReq.path}`);
|
||||||
|
});
|
||||||
|
proxy.on('proxyRes', (proxyRes, req, _res) => {
|
||||||
|
console.log(`[Proxy ✓] ${req.method} ${req.url} -> ${proxyRes.statusCode}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 4173,
|
||||||
|
strictPort: false
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
server: {
|
|
||||||
port: 5173,
|
|
||||||
strictPort: false
|
|
||||||
},
|
|
||||||
preview: {
|
|
||||||
port: 4173,
|
|
||||||
strictPort: false
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user