✨ 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