🗑️ Remove outdated documentation files and consolidate content into a single README for improved organization and maintainability
This commit is contained in:
374
docs/projects/Pokedex.Online/api-reference/gamemaster-api.md
Normal file
374
docs/projects/Pokedex.Online/api-reference/gamemaster-api.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# Gamemaster API Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Gamemaster API provides access to processed Pokemon GO gamemaster data. Once gamemaster data is generated and saved via the GamemasterManager UI, it becomes available to all apps on the site.
|
||||
|
||||
**Data Types:**
|
||||
- **Pokemon (Filtered)** - Base forms + regional variants (Alola, Galarian, Hisuian, Paldea)
|
||||
- **All Forms & Costumes** - Complete dataset with all variants, costumes, events, shadows
|
||||
- **Moves** - All quick and charged moves available in Pokemon GO
|
||||
- **Raw** - Unmodified gamemaster data from PokeMiners
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Base URL
|
||||
```
|
||||
/api/gamemaster
|
||||
```
|
||||
|
||||
### GET /api/gamemaster/status
|
||||
Get information about available files and their storage status.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"available": [
|
||||
{
|
||||
"filename": "pokemon.json",
|
||||
"size": 1234567,
|
||||
"sizeKb": "1234.57",
|
||||
"modified": "2026-01-28T12:34:56.000Z"
|
||||
}
|
||||
],
|
||||
"lastUpdate": "2026-01-28T12:34:56.000Z",
|
||||
"totalFiles": 4
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/gamemaster/pokemon
|
||||
Get filtered pokemon data (base forms + regional variants).
|
||||
|
||||
**Response:**
|
||||
Array of gamemaster items with pokemon settings.
|
||||
|
||||
### GET /api/gamemaster/pokemon/allForms
|
||||
Get all pokemon forms including costumes, event forms, shadows, etc.
|
||||
|
||||
**Response:**
|
||||
Array of all gamemaster pokemon items.
|
||||
|
||||
### GET /api/gamemaster/moves
|
||||
Get all pokemon moves (quick and charged).
|
||||
|
||||
**Response:**
|
||||
Array of gamemaster move items.
|
||||
|
||||
### GET /api/gamemaster/raw
|
||||
Get raw unmodified gamemaster data from PokeMiners.
|
||||
|
||||
**Response:**
|
||||
Complete raw gamemaster array.
|
||||
|
||||
### POST /api/gamemaster/save
|
||||
Save processed gamemaster data to server storage.
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"pokemon": [...],
|
||||
"pokemonAllForms": [...],
|
||||
"moves": [...],
|
||||
"raw": [...]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Files saved successfully",
|
||||
"files": {
|
||||
"pokemon": { "filename": "...", "size": ... },
|
||||
"pokemonAllForms": { ... },
|
||||
"moves": { ... },
|
||||
"raw": { ... }
|
||||
},
|
||||
"timestamp": "2026-01-28T12:34:56.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/gamemaster/download/:filename
|
||||
Download a specific file directly.
|
||||
|
||||
**Parameters:**
|
||||
- `filename` - One of: `pokemon.json`, `pokemon-allFormsCostumes.json`, `pokemon-moves.json`, `latest-raw.json`
|
||||
|
||||
**Response:**
|
||||
Binary JSON file with appropriate headers for download.
|
||||
|
||||
## Client Library
|
||||
|
||||
### Installation
|
||||
|
||||
Use the `GamemasterClient` class from `src/utilities/gamemaster-client.js`:
|
||||
|
||||
```javascript
|
||||
import { GamemasterClient } from './gamemaster-client.js';
|
||||
```
|
||||
|
||||
Or use the singleton instance:
|
||||
|
||||
```javascript
|
||||
import { gamemasterClient } from './gamemaster-client.js';
|
||||
```
|
||||
|
||||
### Usage Examples
|
||||
|
||||
#### Get filtered pokemon
|
||||
```javascript
|
||||
const gm = new GamemasterClient('/api/gamemaster');
|
||||
const pokemon = await gm.getPokemon();
|
||||
console.log(`Loaded ${pokemon.length} pokemon`);
|
||||
```
|
||||
|
||||
#### Get all forms with caching
|
||||
```javascript
|
||||
// First call fetches from server
|
||||
const allForms = await gm.getAllForms({ useCache: true });
|
||||
|
||||
// Subsequent calls use cache
|
||||
const cachedForms = await gm.getAllForms({ useCache: true });
|
||||
```
|
||||
|
||||
#### Get moves
|
||||
```javascript
|
||||
const moves = await gm.getMoves();
|
||||
console.log(`Available moves: ${moves.length}`);
|
||||
```
|
||||
|
||||
#### Get raw unmodified data
|
||||
```javascript
|
||||
const raw = await gm.getRaw();
|
||||
```
|
||||
|
||||
#### Check server status
|
||||
```javascript
|
||||
const status = await gm.getStatus();
|
||||
console.log(`Last update: ${status.lastUpdate}`);
|
||||
console.log(`Files available: ${status.totalFiles}`);
|
||||
```
|
||||
|
||||
#### Find specific pokemon
|
||||
```javascript
|
||||
const arcanine = await gm.getPokemonById('growlithe_alola');
|
||||
if (arcanine) {
|
||||
console.log(arcanine.data.pokemonSettings);
|
||||
}
|
||||
```
|
||||
|
||||
#### Find specific move
|
||||
```javascript
|
||||
const thunderbolt = await gm.getMoveById('thunderbolt');
|
||||
if (thunderbolt) {
|
||||
console.log(thunderbolt.data.moveSettings);
|
||||
}
|
||||
```
|
||||
|
||||
#### Download file
|
||||
```javascript
|
||||
// Download to user's downloads folder
|
||||
await gm.downloadFile('pokemon.json');
|
||||
```
|
||||
|
||||
#### Clear cache
|
||||
```javascript
|
||||
// Clear specific data
|
||||
gm.clearCache('pokemon');
|
||||
|
||||
// Clear all cached data
|
||||
gm.clearCache();
|
||||
```
|
||||
|
||||
### API Reference
|
||||
|
||||
#### `new GamemasterClient(baseUrl = '/api/gamemaster')`
|
||||
Create a new client instance.
|
||||
|
||||
**Parameters:**
|
||||
- `baseUrl` - Base URL for the API (defaults to `/api/gamemaster`)
|
||||
|
||||
#### `getPokemon(options = {})`
|
||||
Get filtered pokemon data.
|
||||
|
||||
**Options:**
|
||||
- `useCache` - (boolean) Use cached data if available
|
||||
|
||||
**Returns:** `Promise<Array>`
|
||||
|
||||
#### `getAllForms(options = {})`
|
||||
Get all pokemon forms including costumes.
|
||||
|
||||
**Returns:** `Promise<Array>`
|
||||
|
||||
#### `getMoves(options = {})`
|
||||
Get all pokemon moves.
|
||||
|
||||
**Returns:** `Promise<Array>`
|
||||
|
||||
#### `getRaw(options = {})`
|
||||
Get raw unmodified gamemaster data.
|
||||
|
||||
**Returns:** `Promise<Array>`
|
||||
|
||||
#### `getStatus()`
|
||||
Get server storage status and available files.
|
||||
|
||||
**Returns:** `Promise<Object>`
|
||||
|
||||
#### `getPokemonById(pokemonId)`
|
||||
Find a specific pokemon in the filtered dataset.
|
||||
|
||||
**Parameters:**
|
||||
- `pokemonId` - Pokemon ID string (e.g., "growlithe", "growlithe_alola")
|
||||
|
||||
**Returns:** `Promise<Object|null>`
|
||||
|
||||
#### `getMoveById(moveId)`
|
||||
Find a specific move.
|
||||
|
||||
**Parameters:**
|
||||
- `moveId` - Move ID string (e.g., "thunderbolt")
|
||||
|
||||
**Returns:** `Promise<Object|null>`
|
||||
|
||||
#### `downloadFile(filename)`
|
||||
Download a file directly to the browser.
|
||||
|
||||
**Parameters:**
|
||||
- `filename` - File to download (see POST /api/gamemaster/save)
|
||||
|
||||
**Returns:** `Promise<void>`
|
||||
|
||||
#### `clearCache(key = null)`
|
||||
Clear cached data.
|
||||
|
||||
**Parameters:**
|
||||
- `key` - (optional) Specific cache key to clear, or clears all if not provided
|
||||
|
||||
## Server Setup
|
||||
|
||||
### Required Environment Variables
|
||||
None - the API runs with defaults.
|
||||
|
||||
### File Storage
|
||||
Processed gamemaster files are stored in:
|
||||
```
|
||||
server/data/gamemaster/
|
||||
```
|
||||
|
||||
Directory is created automatically on first save.
|
||||
|
||||
### Initialization
|
||||
|
||||
The gamemaster API is automatically integrated into the main server:
|
||||
|
||||
```javascript
|
||||
// In server/oauth-proxy.js
|
||||
import gamemasterRouter from './gamemaster-api.js';
|
||||
app.use('/api/gamemaster', gamemasterRouter);
|
||||
```
|
||||
|
||||
Run the OAuth proxy server:
|
||||
```bash
|
||||
npm run oauth-proxy
|
||||
```
|
||||
|
||||
Or run dev with both frontend and server:
|
||||
```bash
|
||||
npm run dev:full
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Generate Data**
|
||||
- Open GamemasterManager at `/gamemaster`
|
||||
- Click "Fetch from PokeMiners"
|
||||
- Click "Process & Break Up Data"
|
||||
- Click "Save All Files to Server"
|
||||
|
||||
2. **Access from Other Apps**
|
||||
- Import GamemasterClient in any app
|
||||
- Call `getPokemon()`, `getAllForms()`, `getMoves()`, etc.
|
||||
- Data is available immediately
|
||||
|
||||
3. **Refresh Data**
|
||||
- Repeat generation process when PokeMiners releases updates
|
||||
- Files are overwritten, maintaining consistency across apps
|
||||
|
||||
## Data Structure
|
||||
|
||||
### Pokemon Item
|
||||
```javascript
|
||||
{
|
||||
templateId: "V0001_POKEMON_BULBASAUR",
|
||||
data: {
|
||||
pokemonSettings: {
|
||||
pokemonId: "bulbasaur",
|
||||
form: "NORMAL",
|
||||
// ... other pokemon data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Move Item
|
||||
```javascript
|
||||
{
|
||||
templateId: "V0002_MOVE_POUND",
|
||||
data: {
|
||||
moveSettings: {
|
||||
movementId: "pound",
|
||||
// ... other move data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All endpoints return appropriate HTTP status codes:
|
||||
|
||||
- `200 OK` - Success
|
||||
- `400 Bad Request` - Invalid parameters
|
||||
- `404 Not Found` - Data not available (hasn't been generated yet)
|
||||
- `500 Server Error` - Server error
|
||||
|
||||
### Example Error Response
|
||||
```json
|
||||
{
|
||||
"error": "Pokemon data not available. Generate from GamemasterManager."
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- All data is cached in memory after first request
|
||||
- Files are stored as plain JSON for quick access
|
||||
- Use `useCache: true` option in client to avoid repeated fetches
|
||||
- Clear cache when refreshing data: `gm.clearCache()`
|
||||
|
||||
## Security
|
||||
|
||||
- No authentication required (adjust if deploying publicly)
|
||||
- Filename validation prevents path traversal attacks
|
||||
- Large payloads supported (50MB limit)
|
||||
- CORS configured for local development
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Data not available" error
|
||||
- Run GamemasterManager to generate and save data first
|
||||
- Check that `/server/data/gamemaster/` directory exists
|
||||
|
||||
### Files not persisting
|
||||
- Ensure server has write permissions to `/server/data/gamemaster/`
|
||||
- Restart server after manual directory creation
|
||||
|
||||
### Large file downloads timing out
|
||||
- Check network connection
|
||||
- Try downloading individual files instead of all at once
|
||||
355
docs/projects/Pokedex.Online/api-reference/oauth-setup.md
Normal file
355
docs/projects/Pokedex.Online/api-reference/oauth-setup.md
Normal file
@@ -0,0 +1,355 @@
|
||||
# Challonge OAuth Setup Guide
|
||||
|
||||
Complete guide to implementing OAuth authentication for Challonge API v2.1 APPLICATION scope.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Development Setup (5 minutes)
|
||||
|
||||
1. **Register OAuth Application**
|
||||
- Visit https://connect.challonge.com
|
||||
- Create new application
|
||||
- Set redirect URI: `http://localhost:5173/oauth/callback`
|
||||
- Note your Client ID and Client Secret
|
||||
|
||||
2. **Configure Environment**
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env`:
|
||||
```bash
|
||||
# Frontend (Vite variables)
|
||||
VITE_CHALLONGE_CLIENT_ID=your_client_id_here
|
||||
VITE_CHALLONGE_REDIRECT_URI=http://localhost:5173/oauth/callback
|
||||
|
||||
# Backend (OAuth Proxy)
|
||||
CHALLONGE_CLIENT_ID=your_client_id_here
|
||||
CHALLONGE_CLIENT_SECRET=your_client_secret_here
|
||||
CHALLONGE_REDIRECT_URI=http://localhost:5173/oauth/callback
|
||||
OAUTH_PROXY_PORT=3001
|
||||
```
|
||||
|
||||
3. **Install Dependencies**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
4. **Run Development Servers**
|
||||
```bash
|
||||
# Option 1: Run both servers with one command
|
||||
npm run dev:full
|
||||
|
||||
# Option 2: Run separately in two terminals
|
||||
# Terminal 1 - Frontend
|
||||
npm run dev
|
||||
|
||||
# Terminal 2 - OAuth Proxy
|
||||
npm run oauth-proxy
|
||||
```
|
||||
|
||||
5. **Test OAuth Flow**
|
||||
- Visit http://localhost:5173/challonge-test
|
||||
- Click "Connect with OAuth"
|
||||
- Authorize the app on Challonge
|
||||
- You'll be redirected back with tokens
|
||||
- Now you can use APPLICATION scope!
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Vue Frontend │
|
||||
│ localhost:5173 │
|
||||
└────────┬────────┘
|
||||
│
|
||||
├─→ User clicks "Connect with OAuth"
|
||||
│ Redirect to Challonge authorization URL
|
||||
│
|
||||
├─→ User authorizes on Challonge
|
||||
│ Redirect back to /oauth/callback?code=xxx&state=yyy
|
||||
│
|
||||
├─→ Frontend calls /api/oauth/token
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ OAuth Proxy │
|
||||
│ localhost:3001 │
|
||||
└────────┬────────┘
|
||||
│
|
||||
├─→ Exchange code for tokens (includes client_secret)
|
||||
│ POST https://api.challonge.com/oauth/token
|
||||
│
|
||||
└─→ Return tokens to frontend
|
||||
Frontend stores in localStorage
|
||||
Creates v2.1 client with Bearer token
|
||||
```
|
||||
|
||||
## Files Created
|
||||
|
||||
### Backend
|
||||
- **server/oauth-proxy.js** - Express server for OAuth token exchange
|
||||
- `/oauth/token` - Exchange authorization code
|
||||
- `/oauth/refresh` - Refresh expired tokens
|
||||
- `/health` - Health check endpoint
|
||||
|
||||
### Frontend
|
||||
- **src/composables/useChallongeOAuth.js** - OAuth state management
|
||||
- Token storage and retrieval
|
||||
- Authorization URL generation
|
||||
- Automatic token refresh
|
||||
- CSRF protection
|
||||
|
||||
- **src/views/OAuthCallback.vue** - OAuth redirect handler
|
||||
- Processes authorization callback
|
||||
- Displays loading/success/error states
|
||||
- Auto-redirects to Challonge Test
|
||||
|
||||
### Configuration
|
||||
- **vite.config.js** - Added `/api/oauth` proxy
|
||||
- **src/router/index.js** - Added `/oauth/callback` route
|
||||
- **package.json** - Added dependencies and scripts
|
||||
- **.env.example** - OAuth configuration template
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### Frontend (Vite - PUBLIC)
|
||||
```bash
|
||||
VITE_CHALLONGE_CLIENT_ID=xxx # OAuth Client ID (public)
|
||||
VITE_CHALLONGE_REDIRECT_URI=xxx # Callback URL
|
||||
```
|
||||
|
||||
### Backend (OAuth Proxy - PRIVATE)
|
||||
```bash
|
||||
CHALLONGE_CLIENT_ID=xxx # OAuth Client ID
|
||||
CHALLONGE_CLIENT_SECRET=xxx # OAuth Client Secret (NEVER expose)
|
||||
CHALLONGE_REDIRECT_URI=xxx # Must match registered URL
|
||||
OAUTH_PROXY_PORT=3001 # Proxy server port
|
||||
```
|
||||
|
||||
### Production (Optional)
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
FRONTEND_URL=https://yourdomain.com
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Option 1: Express Server (Simple)
|
||||
|
||||
Deploy `server/oauth-proxy.js` to:
|
||||
- Heroku
|
||||
- Railway
|
||||
- DigitalOcean App Platform
|
||||
- AWS EC2/ECS
|
||||
|
||||
Update production `.env`:
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
FRONTEND_URL=https://yourdomain.com
|
||||
CHALLONGE_CLIENT_ID=xxx
|
||||
CHALLONGE_CLIENT_SECRET=xxx
|
||||
CHALLONGE_REDIRECT_URI=https://yourdomain.com/oauth/callback
|
||||
PORT=3000
|
||||
```
|
||||
|
||||
Update frontend build environment:
|
||||
```bash
|
||||
VITE_CHALLONGE_CLIENT_ID=xxx
|
||||
VITE_CHALLONGE_REDIRECT_URI=https://yourdomain.com/oauth/callback
|
||||
```
|
||||
|
||||
### Option 2: Serverless Functions (Scalable)
|
||||
|
||||
Convert `server/oauth-proxy.js` to serverless functions:
|
||||
|
||||
**Netlify Functions** (`netlify/functions/oauth-token.js`):
|
||||
```javascript
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export async function handler(event) {
|
||||
if (event.httpMethod !== 'POST') {
|
||||
return { statusCode: 405, body: 'Method Not Allowed' };
|
||||
}
|
||||
|
||||
const { code } = JSON.parse(event.body);
|
||||
|
||||
const response = await fetch('https://api.challonge.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: process.env.CHALLONGE_CLIENT_ID,
|
||||
client_secret: process.env.CHALLONGE_CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: process.env.CHALLONGE_REDIRECT_URI,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return {
|
||||
statusCode: response.status,
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Vercel Functions** (`api/oauth/token.js`):
|
||||
```javascript
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ error: 'Method Not Allowed' });
|
||||
}
|
||||
|
||||
const { code } = req.body;
|
||||
|
||||
const response = await fetch('https://api.challonge.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: process.env.CHALLONGE_CLIENT_ID,
|
||||
client_secret: process.env.CHALLONGE_CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: process.env.CHALLONGE_REDIRECT_URI,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
res.status(response.status).json(data);
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: Cloudflare Workers (Edge)
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request, env) {
|
||||
if (request.method !== 'POST') {
|
||||
return new Response('Method Not Allowed', { status: 405 });
|
||||
}
|
||||
|
||||
const { code } = await request.json();
|
||||
|
||||
const response = await fetch('https://api.challonge.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: env.CHALLONGE_CLIENT_ID,
|
||||
client_secret: env.CHALLONGE_CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: env.CHALLONGE_REDIRECT_URI,
|
||||
}),
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### ✅ DO
|
||||
- Store client_secret ONLY on backend (never in frontend)
|
||||
- Use HTTPS in production
|
||||
- Validate state parameter for CSRF protection
|
||||
- Store tokens in localStorage (XSS protection via CSP)
|
||||
- Set appropriate token expiration
|
||||
- Implement token refresh before expiration
|
||||
- Use environment variables for secrets
|
||||
|
||||
### ❌ DON'T
|
||||
- Never commit `.env` to version control
|
||||
- Never expose client_secret in frontend code
|
||||
- Never log tokens in production
|
||||
- Don't use OAuth without SSL in production
|
||||
- Don't store tokens in cookies (CSRF risk)
|
||||
|
||||
## Testing
|
||||
|
||||
### Test OAuth Flow
|
||||
1. Start both servers: `npm run dev:full`
|
||||
2. Visit http://localhost:5173/challonge-test
|
||||
3. Click "Connect with OAuth"
|
||||
4. Should redirect to Challonge
|
||||
5. Authorize the app
|
||||
6. Should redirect back to callback
|
||||
7. Should see success message
|
||||
8. Should redirect to Challonge Test
|
||||
9. OAuth status should show "Connected"
|
||||
10. Try listing tournaments with "Show all tournaments" checked
|
||||
|
||||
### Test Token Refresh
|
||||
```javascript
|
||||
// In browser console after connecting
|
||||
const { refreshToken } = useChallongeOAuth();
|
||||
await refreshToken(); // Should refresh token
|
||||
```
|
||||
|
||||
### Test Logout
|
||||
```javascript
|
||||
// In browser console
|
||||
const { logout } = useChallongeOAuth();
|
||||
logout(); // Should clear tokens
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Missing required environment variables"
|
||||
- Check `.env` file exists in project root
|
||||
- Verify `CHALLONGE_CLIENT_ID` and `CHALLONGE_CLIENT_SECRET` are set
|
||||
- Restart OAuth proxy after changing `.env`
|
||||
|
||||
### "Invalid state parameter"
|
||||
- Clear browser storage and try again
|
||||
- Verify redirect URI matches exactly
|
||||
|
||||
### "Token exchange failed"
|
||||
- Check client ID and secret are correct
|
||||
- Verify redirect URI matches registered URL exactly
|
||||
- Check OAuth proxy is running on port 3001
|
||||
- Look at OAuth proxy console for error details
|
||||
|
||||
### "CORS errors"
|
||||
- Verify Vite proxy is configured correctly
|
||||
- Check OAuth proxy CORS settings
|
||||
- Ensure frontend URL is allowed in production
|
||||
|
||||
### "Token expired"
|
||||
- Token should auto-refresh when needed
|
||||
- Manually refresh: `useChallongeOAuth().refreshToken()`
|
||||
- If refresh fails, user must re-authenticate
|
||||
|
||||
## API Scopes
|
||||
|
||||
Available scopes for Challonge OAuth:
|
||||
|
||||
- `tournaments:read` - Read tournament data
|
||||
- `tournaments:write` - Create/update tournaments
|
||||
- `participants:read` - Read participant data
|
||||
- `participants:write` - Manage participants
|
||||
- `matches:read` - Read match data
|
||||
- `matches:write` - Update match results
|
||||
- `user:read` - Read user profile
|
||||
|
||||
Default scope in app: `tournaments:read tournaments:write`
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Basic OAuth flow working
|
||||
2. ✅ Token storage and refresh
|
||||
3. ✅ APPLICATION scope access
|
||||
4. 🔄 Add scope selector in UI (optional)
|
||||
5. 🔄 Implement token refresh UI indicator
|
||||
6. 🔄 Add "time until expiration" display
|
||||
7. 🔄 Deploy to production
|
||||
8. 🔄 Add more scopes as needed
|
||||
|
||||
## Support
|
||||
|
||||
- Challonge API Docs: https://challonge.apidog.io
|
||||
- OAuth 2.0 Spec: https://oauth.net/2/
|
||||
- Register Apps: https://connect.challonge.com
|
||||
Reference in New Issue
Block a user