✨ Add utility functions for interacting with the Game Master API
This commit is contained in:
189
code/websites/pokedex.online/src/utilities/gamemaster-client.js
Normal file
189
code/websites/pokedex.online/src/utilities/gamemaster-client.js
Normal file
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* Gamemaster Client Utility
|
||||
* Use this in any app on the site to access gamemaster data
|
||||
*
|
||||
* Usage:
|
||||
* import { GamemasterClient } from './gamemaster-client.js';
|
||||
* const gm = new GamemasterClient('/api/gamemaster');
|
||||
*
|
||||
* // Get filtered pokemon
|
||||
* const pokemon = await gm.getPokemon();
|
||||
*
|
||||
* // Get all forms with costumes
|
||||
* const allForms = await gm.getAllForms();
|
||||
*
|
||||
* // Get moves
|
||||
* const moves = await gm.getMoves();
|
||||
*
|
||||
* // Get raw unmodified data
|
||||
* const raw = await gm.getRaw();
|
||||
*
|
||||
* // Check what's available
|
||||
* const status = await gm.getStatus();
|
||||
*/
|
||||
|
||||
export class GamemasterClient {
|
||||
constructor(baseUrl = '/api/gamemaster') {
|
||||
this.baseUrl = baseUrl;
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a request to the gamemaster API
|
||||
* @private
|
||||
* @param {string} endpoint
|
||||
* @param {Object} options
|
||||
* @returns {Promise<Object|Array>}
|
||||
*/
|
||||
async request(endpoint, options = {}) {
|
||||
const url = `${this.baseUrl}${endpoint}`;
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
...options
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.error || `HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`Gamemaster API Error [${endpoint}]:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status of available files
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getStatus() {
|
||||
return this.request('/status');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered pokemon data (base forms + regional variants)
|
||||
* @param {Object} options
|
||||
* @param {boolean} options.useCache - Use cached data if available
|
||||
* @returns {Promise<Array>}
|
||||
*/
|
||||
async getPokemon(options = {}) {
|
||||
if (options.useCache && this.cache.has('pokemon')) {
|
||||
return this.cache.get('pokemon');
|
||||
}
|
||||
|
||||
const data = await this.request('/pokemon');
|
||||
this.cache.set('pokemon', data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all pokemon forms including costumes, shadows, events, etc.
|
||||
* @param {Object} options
|
||||
* @param {boolean} options.useCache - Use cached data if available
|
||||
* @returns {Promise<Array>}
|
||||
*/
|
||||
async getAllForms(options = {}) {
|
||||
if (options.useCache && this.cache.has('allForms')) {
|
||||
return this.cache.get('allForms');
|
||||
}
|
||||
|
||||
const data = await this.request('/pokemon/allForms');
|
||||
this.cache.set('allForms', data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all pokemon moves
|
||||
* @param {Object} options
|
||||
* @param {boolean} options.useCache - Use cached data if available
|
||||
* @returns {Promise<Array>}
|
||||
*/
|
||||
async getMoves(options = {}) {
|
||||
if (options.useCache && this.cache.has('moves')) {
|
||||
return this.cache.get('moves');
|
||||
}
|
||||
|
||||
const data = await this.request('/moves');
|
||||
this.cache.set('moves', data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get raw unmodified gamemaster data
|
||||
* @param {Object} options
|
||||
* @param {boolean} options.useCache - Use cached data if available
|
||||
* @returns {Promise<Array>}
|
||||
*/
|
||||
async getRaw(options = {}) {
|
||||
if (options.useCache && this.cache.has('raw')) {
|
||||
return this.cache.get('raw');
|
||||
}
|
||||
|
||||
const data = await this.request('/raw');
|
||||
this.cache.set('raw', data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file directly
|
||||
* @param {string} filename - One of: pokemon.json, pokemon-allFormsCostumes.json, pokemon-moves.json, latest-raw.json
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async downloadFile(filename) {
|
||||
const url = `${this.baseUrl}/download/${filename}`;
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to download ${filename}`);
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(link.href);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached data
|
||||
* @param {string} key - Optional specific key to clear, or clears all if not provided
|
||||
*/
|
||||
clearCache(key = null) {
|
||||
if (key) {
|
||||
this.cache.delete(key);
|
||||
} else {
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific pokemon from the filtered dataset
|
||||
* @param {string} pokemonId
|
||||
* @returns {Promise<Object|null>}
|
||||
*/
|
||||
async getPokemonById(pokemonId) {
|
||||
const pokemon = await this.getPokemon({ useCache: true });
|
||||
return pokemon.find(p => p.data?.pokemonSettings?.pokemonId === pokemonId) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific move
|
||||
* @param {string} moveId
|
||||
* @returns {Promise<Object|null>}
|
||||
*/
|
||||
async getMoveById(moveId) {
|
||||
const moves = await this.getMoves({ useCache: true });
|
||||
return moves.find(m => m.data?.moveSettings?.movementId === moveId) || null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton instance - use this for most cases
|
||||
*/
|
||||
export const gamemasterClient = new GamemasterClient();
|
||||
Reference in New Issue
Block a user