@cactus-agents/games
SDK framework-agnostic para jogos de cassino, categorias, providers, busca, start-game, votos e estatisticas.
Instalacao
pnpm add @cactus-agents/games
Uso recomendado
Use createGamesFromClient quando voce ja estiver usando @cactus-agents/api-client:
import { createApiClient } from "@cactus-agents/api-client";
import { createGamesFromClient } from "@cactus-agents/games";
const client = createApiClient({ baseUrl, tenant, language });
const games = createGamesFromClient(client);
const home = await games.getHome();
const base = await games.getBase();
const list = await games.getList({ categories: ["slots"], page: 1, perPage: 24 });
API publica
Exports principais:
createGamesService(fetcher)createGamesFromClient(client)transformGame(raw),transformProvider(raw),transformCategory(raw)transformHomeRow(raw),transformBaseData(raw)transformGameListResponse(raw),transformStartGameResponse(raw)transformTopWin(raw),transformLastWin(raw)transformGameStatistics(raw)transformGameVote(raw)
Tipos principais:
Game,GameProvider,GameType,GameRangeProvider,CustomCategoryHomeRow,HomeRowType,BaseDataGameListParams,GameListResponseStartGamePlatform,StartGameParams,StartGameResponseTopWin,LastWinStatsPeriod,GameStatisticsGameVote,GameVoteCountGamesService,GamesFetcher
Referencia de exports: front-cactus-core/packages/games/src/index.ts.
GamesFetcher
O GamesFetcher e a interface de abstraction de HTTP usada pelo createGamesService. Deve implementar os metodos get, post e delete:
get— usado pela maioria dos endpoints de leiturapost— usado porvote(criar voto)delete— usado porremoveVote(remover voto)
O createGamesFromClient adapta o ApiClient para essa interface automaticamente.
Endpoints do GamesService
| Metodo | Verbo | Endpoint | Observacao |
|---|---|---|---|
getHome() | GET | /casino-games/home | Layout da homepage (rows com jogos) |
getBase() | GET | /casino-games/list/base | Categorias + providers |
getList(params?) | GET | /casino-games/list | Paginado: categories[], providers[], term, page, per_page |
getDetail(slug) | GET | /casino-games?slug={slug} | Detalhe de um jogo |
startGame(params) | GET | /start-game-v2 | slug, platform, use_demo — autenticado |
getTopWins() | GET | /bff/games/top-wins | Maiores ganhos recentes |
getLastWins() | GET | /bff/games/last-wins | Ultimos ganhos |
getStats(slug) | GET | /bff/games/statistics?slug={slug} | Stats por periodo (5min a 30d) |
getVote(casinoGameId) | GET | /casino-game-votes?casinoGameId={id} | Voto do usuario — autenticado |
getVoteCount(gameId) | GET | /casino-game-votes/count/{id} | Contagem likes/dislikes |
vote(casinoGameId, isLike) | POST | /casino-game-votes/store/ | Criar voto — autenticado |
removeVote(gameId) | DELETE | /casino-game-votes/destroy/{id} | Remover voto — autenticado |
Helpers de imagem
Os helpers de imagem foram centralizados em @cactus-agents/utils, para que o mesmo contrato sirva para qualquer imagem do projeto:
- Cloudflare
imagedelivery.net - thumbs legadas com
/mobilee/ipad /api/storage/...- imagens externas ou paths locais
import { getImageUrl, getResponsiveImageProps } from "@cactus-agents/utils";
const image = getResponsiveImageProps(game.image, {
widths: [200, 320, 400, 600],
fallbackWidth: 400,
sizes: "(max-width: 640px) 50vw, 200px",
});
const logoUrl = getImageUrl(brand.appearance.logo);
Estatisticas de jogo
transformGameStatistics converte os campos flat da API em periodos organizados:
import { transformGameStatistics } from "@cactus-agents/games";
const stats = transformGameStatistics(raw);
// stats.last5Minutes.bets, stats.last5Minutes.wins, stats.last5Minutes.players, stats.last5Minutes.rtp
// stats.last1Hour, stats.last24Hours, stats.last7Days, stats.last15Days, stats.last30Days
Cada StatsPeriod contem: bets, wins, players, rtp.
Integracao server-side (recomendado para cache)
No front-web-base, o servico e encapsulado por GamesCacheService que adiciona cache in-memory + CF Cache API com stale-while-revalidate:
import { getGamesCacheService } from "~/services/games.server";
export async function loader({ context }: Route.LoaderArgs) {
const gamesCacheService = getGamesCacheService(context);
const home = await gamesCacheService.getHome();
const base = await gamesCacheService.getBase();
return { home, base };
}
Para start-game (autenticado), a chamada vai direto na API sem cache:
import { createGamesFromClient } from "@cactus-agents/games";
const client = createClient(env, { request });
const games = createGamesFromClient(client);
const result = await games.startGame({ slug, platform: "WEB", useDemo: false });
Notas de transform
transformGameconvertedemo: 0|1para boolean e normalizaprovider,casino_game_type,rangetransformProviderconvertegames(count) paragameCounttransformCategorymapeia campos 1:1 incluindoicontransformHomeRowclassificatypecomowidget,custom-categoryoucustom-sectiontransformGameListResponseconverte paginacao snake_case para camelCasetransformStartGameResponseextraigameUrlde multiplos formatos possiveis da API (SoftSwiss vs padrao)
Legacy Service
Funcoes para integrar com o endpoint legado de jogos:
createLegacyGamesService(fetcher, homeConfig)— cria service usandoGamesFetcherdiretamentecreateLegacyGamesFromClient(client, homeConfig)— cria service a partir deApiClient
O legacy service usa /casino-games/filter em vez de /casino-games/list. O parametro homeConfig e do tipo LegacyHomeRowConfig[], onde cada item define uma row da home com um dos tipos:
| Tipo | Descricao |
|---|---|
"games-api" | Row populada via filtro na API de jogos |
"providers-api" | Row de providers via API |
"games-fixed" | Row com jogos fixos (slugs hardcoded) |
"widget" | Row de widget customizado |
Provider Config
Configuracao de iframe para providers de jogos:
getProviderIframeConfig(providerSlug, gameUrl?)
Retorna ProviderIframeConfig para o provider especificado:
allow— permissions do iframe (ex.:autoplay,fullscreen)allowFullscreen— booleanlaunchMode— modo de lancamento:"iframe"|"softswiss-sdk"|"srcdoc"
applyIsSoftSwiss(config, isSoftSwiss)
Sobrescreve o launchMode da config quando o jogo e SoftSwiss.
parseCasinoProviderMessage(providerSlug, raw)
Faz parse de postMessage recebidas de iframes de jogos. Retorna acao interpretada por provider:
- liveg24: mensagem
"closeGame"→ acaoexit - amusnet: detecta acoes
exitereload
import { parseCasinoProviderMessage } from "@cactus-agents/games";
window.addEventListener("message", (event) => {
const action = parseCasinoProviderMessage("liveg24", event.data);
if (action === "exit") {
// fechar iframe do jogo
}
});
Filtro in-memory
filterGames(games, params)
Filtra um array de Game[] em memoria (client-side). Util para buscas e filtros sem nova chamada a API.
Params:
| Param | Tipo | Descricao |
|---|---|---|
term | string? | Busca por nome do jogo |
categories | string[]? | Filtro por categorias |
providers | string[]? | Filtro por providers |
tags | string[]? | Filtro por tags |
page | number? | Pagina atual |
perPage | number? | Itens por pagina |
Retorno: GameFilterResult
interface GameFilterResult {
data: Game[];
total: number;
currentPage: number;
lastPage: number;
}
import { filterGames } from "@cactus-agents/games";
const result = filterGames(allGames, {
term: "sweet",
categories: ["slots"],
page: 1,
perPage: 20,
});
// result.data — jogos filtrados da pagina
// result.total — total de resultados
// result.lastPage — ultima pagina disponivel