Add composable for interacting with Challonge API

This commit is contained in:
2026-01-29 05:09:33 +00:00
parent cb23c5e923
commit 568224f2d9
2 changed files with 197 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
/**
* Challonge Client Composable
*
* Manages Challonge API client initialization with support for:
* - API v1 and v2.1
* - Multiple authentication methods (API Key, OAuth, Client Credentials)
* - Smart auth selection based on tournament scope
* - Reactive client updates
*
* @example
* ```js
* const {
* client,
* apiVersion,
* tournamentScope,
* switchVersion,
* setScope
* } = useChallongeClient();
*
* // Use client for API calls
* await client.value.tournaments.list();
* ```
*/
import { ref, computed } from 'vue';
import { useChallongeApiKey } from './useChallongeApiKey.js';
import { useChallongeOAuth } from './useChallongeOAuth.js';
import { useChallongeClientCredentials } from './useChallongeClientCredentials.js';
import {
createChallongeV1Client,
createChallongeV2Client,
AuthType,
ScopeType
} from '../services/challonge.service.js';
export function useChallongeClient(options = {}) {
const { debug = false } = options;
// Get authentication sources
const { getApiKey } = useChallongeApiKey();
const {
isAuthenticated: isOAuthAuthenticated,
accessToken: oauthToken
} = useChallongeOAuth();
const {
isAuthenticated: isClientCredsAuthenticated,
accessToken: clientCredsToken
} = useChallongeClientCredentials();
// Configuration state
const apiVersion = ref('v2.1'); // 'v1' or 'v2.1'
const tournamentScope = ref(ScopeType.USER);
const debugMode = ref(debug);
// Reactive API key
const apiKey = computed(() => getApiKey());
// Masked API key for display
const maskedApiKey = computed(() => {
if (!apiKey.value) return '';
return apiKey.value.slice(0, 4) + '•••••••' + apiKey.value.slice(-4);
});
/**
* Create API client reactively based on version, auth method, and scope
*/
const client = computed(() => {
if (apiVersion.value === 'v1') {
// v1 only supports API key
if (!apiKey.value) return null;
return createChallongeV1Client(apiKey.value);
} else {
// v2.1 supports OAuth, client credentials, and API key
// Smart priority based on scope selection:
// - APPLICATION scope: prefer client credentials (designed for this)
// - USER scope: prefer OAuth user tokens or API key
if (tournamentScope.value === ScopeType.APPLICATION) {
// APPLICATION scope - prefer client credentials
if (isClientCredsAuthenticated.value && clientCredsToken.value) {
if (debugMode.value) {
console.log('🔐 Using Client Credentials token for APPLICATION scope');
}
return createChallongeV2Client(
{ token: clientCredsToken.value, type: AuthType.OAUTH },
{ debug: debugMode.value }
);
} else if (isOAuthAuthenticated.value && oauthToken.value) {
if (debugMode.value) {
console.log('🔐 Using OAuth user token for APPLICATION scope');
}
return createChallongeV2Client(
{ token: oauthToken.value, type: AuthType.OAUTH },
{ debug: debugMode.value }
);
}
} else {
// USER scope - prefer OAuth user tokens or API key
if (isOAuthAuthenticated.value && oauthToken.value) {
if (debugMode.value) {
console.log('🔐 Using OAuth user token for USER scope');
}
return createChallongeV2Client(
{ token: oauthToken.value, type: AuthType.OAUTH },
{ debug: debugMode.value }
);
} else if (apiKey.value) {
if (debugMode.value) {
console.log('🔑 Using API Key for USER scope');
}
return createChallongeV2Client(
{ token: apiKey.value, type: AuthType.API_KEY },
{ debug: debugMode.value }
);
}
}
// Fallback: try API key
if (apiKey.value) {
if (debugMode.value) {
console.log('🔑 Using API Key (fallback)');
}
return createChallongeV2Client(
{ token: apiKey.value, type: AuthType.API_KEY },
{ debug: debugMode.value }
);
}
return null;
}
});
/**
* Current authentication type being used
*/
const authType = computed(() => {
if (apiVersion.value === 'v1') {
return 'API Key';
}
if (isClientCredsAuthenticated.value) {
return 'Client Credentials';
}
if (isOAuthAuthenticated.value) {
return 'OAuth';
}
return 'API Key';
});
/**
* Switch API version
*/
function switchVersion(version) {
if (version !== 'v1' && version !== 'v2.1') {
throw new Error('Invalid API version. Must be "v1" or "v2.1"');
}
apiVersion.value = version;
}
/**
* Set tournament scope (v2.1 only)
*/
function setScope(scope) {
if (scope !== ScopeType.USER && scope !== ScopeType.APPLICATION) {
throw new Error('Invalid scope type');
}
tournamentScope.value = scope;
}
/**
* Toggle debug mode
*/
function setDebugMode(enabled) {
debugMode.value = enabled;
}
return {
// State
apiVersion,
tournamentScope,
debugMode,
apiKey,
maskedApiKey,
client,
authType,
isOAuthAuthenticated,
isClientCredsAuthenticated,
// Methods
switchVersion,
setScope,
setDebugMode,
// Constants
ScopeType,
AuthType
};
}