challenge-place-client
v1.0.4
Published
Cliente Node.js no oficial para Challenge Place usando REST y Socket.IO.
Maintainers
Readme
challenge-place-client
Cliente Node.js no oficial para Challenge Place. La web usa Socket.IO sobre WebSocket contra https://api.challengeplace.com/challenge y obtiene la mayoría de datos públicos entrando a rooms como room-challenge-dashboard.
Instalacion
npm installUso rapido
const { ChallengeClient } = require("challenge-place-client");
const challenge = new ChallengeClient({
linkCode: "6a089bd13961bb98b50a0c62",
lang: "es",
});
challenge.getSettings((settings) => {
console.log(settings.name);
});
const dashboard = await challenge.getDashboard();
console.log(Object.keys(dashboard.competitors || {}).length);
console.log(challenge.assetUrl(dashboard.img));
challenge.disconnect();Opciones
Opciones del constructor:
const challenge = new ChallengeClient({
linkCode: "6a089bd13961bb98b50a0c62",
lang: "es",
tokenId: null,
timeoutMs: 15000,
apiUrl: "https://api.challengeplace.com",
staticUrl: "https://static.challengeplace.com",
});linkCode: codigo del torneo. Requerido.lang: idioma enviado al socket. Por defecto"en".tokenId: token Firebase/Bearer cuando necesitas endpoints privados. Por defectonull.timeoutMs: timeout de ack/conexion WebSocket en milisegundos.apiUrl: API base. Por seguridad solohttps://api.challengeplace.compor defecto.staticUrl: base para convertir imagenes relativas en URLs absolutas.allowCustomApiUrl: permite usar unapiUrlcustom HTTPS.socketOptions: opciones extra parasocket.io-client.
Opciones por llamada:
timeoutMs: override del timeout para esa llamada.roundTimeoutMs: timeout por ronda engetMatches().strictRoundDetails: hace quegetMatches()falle si una ronda no responde.includeUndated: incluye partidos sin fecha engetUpcomingMatches().includeGroup: completa grupo engetCompetitorDetails().includeRoundNames: completa nombres de ronda engetCompetitorDetails().includeRaw: agrega la respuesta cruda del socket agetCompetitorDetails().
WebSocket
El cliente reproduce lo observado en la web:
- URL base:
https://api.challengeplace.com - Namespace de challenges:
/challenge - Transporte:
websocket - Auth:
{ tokenId, linkCode, challengeLinkCode, lang } - Eventos de room:
enter-roomyexit-room - Evento inicial de settings:
challenge-settings
Rooms publicas utiles:
const { CHALLENGE_ROOMS } = require("challenge-place-client");
await challenge.getRoom(CHALLENGE_ROOMS.dashboard);
await challenge.getRoom(CHALLENGE_ROOMS.competitors);
await challenge.getRoom(CHALLENGE_ROOMS.stages);
await challenge.getRoom(CHALLENGE_ROOMS.statistics);
await challenge.getRoom(CHALLENGE_ROOMS.news);
await challenge.getRoom(CHALLENGE_ROOMS.transfers);
await challenge.getRoom(CHALLENGE_ROOMS.champions);Algunos rooms de detalle requieren roomId:
await challenge.getStageDetails("STAGE_ID");
await challenge.getRoom(CHALLENGE_ROOMS.matchDetails, { roomId: "MATCH_ID" });Tambien puedes pedir partidos ya normalizados, con fecha ISO, competidores resueltos y URLs de fotos:
const match = await challenge.getMatchBetween("Francia", "Países Bajos");
console.log(match.dateIso);
console.log(match.homeCompetitorInfo.name);
console.log(match.awayCompetitorInfo.imgUrl);Metodos disponibles:
await challenge.getRoundDetails("ROUND_ID");
await challenge.getMatches();
await challenge.getUpcomingMatches({ from: Date.now() });
await challenge.findMatches({ competitors: ["Francia", "Países Bajos"] });
await challenge.getMatchBetween("FRAN", "PAIB");getMatches() continua si una ronda no responde por WebSocket. Para modo estricto:
await challenge.getMatches({ strictRoundDetails: true });Para cargar datos de un equipo especifico, incluyendo participantes, foto, grupo, estadisticas y partidos:
const germany = await challenge.getCompetitorDetails("6a089da679d491a490d95623");
console.log(germany.competitor.name);
console.log(germany.competitor.imgUrl);
console.log(Object.values(germany.players).map((player) => player.name));
console.log(germany.matches);Ese metodo usa el room rapido de la pagina /competitor/:id (room-challenge-competitor-details). Tambien acepta nombre o acronimo, resolviendo primero la lista de competidores:
const france = await challenge.getCompetitorDetails("Francia", {
includeGroup: true,
includeRoundNames: true,
includeRaw: false,
});Opciones utiles:
includeGroup: consulta datos de fase/grupo adicionales. Es mas lento, pero devuelvegroup.includeRoundNames: consulta metadata de fase para completarmatch.round.name.includeRaw: incluye la respuesta original del WebSocket enraw.timeoutMs: cambia el timeout general de cada llamada socket.roundTimeoutMs: timeout para detalles de rondas cuando usasgetMatches().strictRoundDetails: sitrue,getMatches()falla cuando una ronda no responde.
Para maxima velocidad, pasa el id del competidor y no actives opciones extra:
const germany = await challenge.getCompetitorDetails("6a089da679d491a490d95623");REST
La web tambien usa https://api.challengeplace.com para endpoints auxiliares:
await challenge.checkLinkCode();
await challenge.fetchCompetitors({ withPlayers: true });
await challenge.fetchCompetitorPlayers("COMPETITOR_ID");Por seguridad, la libreria solo permite https://api.challengeplace.com por defecto. Si necesitas un proxy o entorno de pruebas, debes habilitarlo explicitamente:
const challenge = new ChallengeClient({
linkCode: "6a089bd13961bb98b50a0c62",
apiUrl: "https://mi-proxy.example.com",
allowCustomApiUrl: true,
});Las URLs http:// se rechazan siempre.
Ejemplo real
npm run example:challenge
npm run example:find-match
npm run example:teamPara exportar un reporte JSON con fechas, fases, fase de grupos, fase eliminatoria, competidores, estadisticas y noticias:
npm run example:reportTambien puedes pasar otro link code:
node examples/challenge-dashboard.js 6a089bd13961bb98b50a0c62
node examples/challenge-report.js 6a089bd13961bb98b50a0c62 reports/world-cup.jsonEl reporte normaliza fotos y resultados:
{
"name": "Francia",
"img": "/2026/5/16/13/competitor/example.jpg",
"imgUrl": "https://static.challengeplace.com/2026/5/16/13/competitor/example.jpg",
"latestResults": ["win", "draw", "loss"]
}Errores
La libreria exporta errores especificos para manejar fallos sin depender de strings:
const {
ChallengePlaceHttpError,
ChallengePlaceSocketError,
ChallengePlaceTimeoutError,
ChallengePlaceValidationError,
} = require("challenge-place-client");ChallengePlaceHttpError: falla REST o respuesta HTTP con error.ChallengePlaceSocketError: falla de conexion/evento Socket.IO.ChallengePlaceTimeoutError: timeout conectando o esperando ack.ChallengePlaceValidationError: parametros faltantes comolinkCodeoroom.
Nota
Esto no es un SDK oficial. Los nombres de rooms y eventos salen del bundle web actual de Challenge Place y pueden cambiar si la plataforma actualiza su frontend.
