feat: implement multi-state tournament querying for Challonge API v2.1

- Add tournament-query.js utility with queryAllTournaments() and helper functions
  * Makes 3 parallel API calls (pending, in_progress, ended states)
  * Uses Promise.all() to wait for all requests
  * Deduplicates results by tournament ID using Map
  * Replaces invalid state: 'all' parameter (API doesn't support 'all' value)

- Implement 5 convenience functions:
  * queryAllTournaments() - Query all states with custom options
  * queryUserTournaments() - Query user's tournaments (shorthand)
  * queryCommunityTournaments() - Query community tournaments
  * queryActiveTournaments() - Query pending + in_progress only
  * queryCompletedTournaments() - Query ended tournaments only
  * queryTournamentsByStates() - Query custom state combinations

- Update ChallongeTest.vue to use queryAllTournaments()
  * Replace invalid state: 'all' with proper multi-state query
  * Now correctly fetches tournaments from all states
  * Update console logging to show all 3 states being queried

- Add comprehensive TOURNAMENT_QUERY_GUIDE.md documentation
  * Explains the problem and solution
  * API reference for all functions
  * Implementation details and performance notes
  * Testing instructions
  * Future enhancement ideas
This commit is contained in:
2026-01-28 18:10:29 +00:00
parent 66ffe17aed
commit 1944b43af8
3 changed files with 1996 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
/**
* Tournament Query Utilities
*
* Provides advanced querying capabilities for Challonge tournaments,
* including queries across multiple states with deduplication.
*
* Note: The Challonge API v2.1 only supports filtering by single state
* (pending, in_progress, or ended), so multi-state queries require
* multiple API calls that are Promise.all'd together.
*/
/**
* Query tournaments in ALL states
*
* Makes three parallel API calls (pending, in_progress, ended) and combines
* the results while deduplicating by tournament ID.
*
* @param {Object} client - Challonge API client (from createChallongeV2Client)
* @param {Object} [options] - Query options
* @param {string} [options.scopeType] - USER, COMMUNITY, or APPLICATION scope (default: USER)
* @param {string} [options.communityId] - Community ID (if using COMMUNITY scope)
* @param {number} [options.page] - Page number (default: 1)
* @param {number} [options.per_page] - Results per page (default: 25)
* @param {string[]} [options.states] - States to query (default: ['pending', 'in_progress', 'ended'])
* @param {boolean} [options.includeCommunities] - Also query community tournaments (default: false)
* @returns {Promise<any[]>} Combined and deduplicated tournament list
*
* @example
* import { queryAllTournaments } from '../utilities/tournament-query.js'
*
* const tournaments = await queryAllTournaments(client, {
* scopeType: 'USER',
* per_page: 100
* })
*/
export async function queryAllTournaments(client, options = {}) {
const {
scopeType = 'USER',
communityId,
page = 1,
per_page = 25,
states = ['pending', 'in_progress', 'ended'],
includeCommunities = false
} = options;
// Build base query options
const baseOptions = {
scopeType,
communityId,
page,
per_page
};
// Query all states in parallel
const promises = states.map(state =>
client.tournaments.list({
...baseOptions,
state
}).catch((err) => {
console.error(`Error querying ${state} tournaments:`, err);
return [];
})
);
// Wait for all requests
const results = await Promise.all(promises);
// Flatten and deduplicate by tournament ID
const tournamentMap = new Map();
results.forEach(tournamentArray => {
if (Array.isArray(tournamentArray)) {
tournamentArray.forEach((tournament) => {
// Handle both v1 and v2.1 response formats
const id = tournament.id || tournament.tournament?.id;
if (id && !tournamentMap.has(id)) {
tournamentMap.set(id, tournament);
}
});
}
});
return Array.from(tournamentMap.values());
}
/**
* Query tournaments you created + tournaments where you're admin
*
* For the USER scope, the Challonge API returns both created and admin tournaments,
* but optionally query across all states for completeness.
*
* @param {Object} client - Challonge API client
* @param {Object} [options] - Query options (same as queryAllTournaments)
* @returns {Promise<any[]>} User's created and admin tournaments
*/
export async function queryUserTournaments(client, options = {}) {
return queryAllTournaments(client, {
...options,
scopeType: 'USER'
});
}
/**
* Query all tournaments in a community (all states)
*
* @param {Object} client - Challonge API client
* @param {string} communityId - Community numeric ID
* @param {Object} [options] - Query options
* @returns {Promise<any[]>} Community tournaments across all states
*/
export async function queryCommunityTournaments(client, communityId, options = {}) {
return queryAllTournaments(client, {
...options,
scopeType: 'COMMUNITY',
communityId
});
}
/**
* Query tournaments with custom state list
*
* Useful if you only care about specific states or want to use
* a different set of states than the default.
*
* @param {Object} client - Challonge API client
* @param {string[]} states - States to query (e.g., ['pending', 'in_progress'])
* @param {Object} [options] - Query options
* @returns {Promise<any[]>} Tournaments matching the given states
*/
export async function queryTournamentsByStates(client, states, options = {}) {
return queryAllTournaments(client, {
...options,
states
});
}
/**
* Query active tournaments only (pending + in_progress)
*
* @param {Object} client - Challonge API client
* @param {Object} [options] - Query options
* @returns {Promise<any[]>} Active tournaments
*/
export async function queryActiveTournaments(client, options = {}) {
return queryTournamentsByStates(client, ['pending', 'in_progress'], options);
}
/**
* Query completed tournaments only (ended)
*
* @param {Object} client - Challonge API client
* @param {Object} [options] - Query options
* @returns {Promise<any[]>} Completed tournaments
*/
export async function queryCompletedTournaments(client, options = {}) {
return queryTournamentsByStates(client, ['ended'], options);
}