Pular para o conteúdo principal

@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, GameRange
  • Provider, CustomCategory
  • HomeRow, HomeRowType, BaseData
  • GameListParams, GameListResponse
  • StartGamePlatform, StartGameParams, StartGameResponse
  • TopWin, LastWin
  • StatsPeriod, GameStatistics
  • GameVote, GameVoteCount
  • GamesService, 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 leitura
  • post — usado por vote (criar voto)
  • delete — usado por removeVote (remover voto)

O createGamesFromClient adapta o ApiClient para essa interface automaticamente.

Endpoints do GamesService

MetodoVerboEndpointObservacao
getHome()GET/casino-games/homeLayout da homepage (rows com jogos)
getBase()GET/casino-games/list/baseCategorias + providers
getList(params?)GET/casino-games/listPaginado: categories[], providers[], term, page, per_page
getDetail(slug)GET/casino-games?slug={slug}Detalhe de um jogo
startGame(params)GET/start-game-v2slug, platform, use_demo — autenticado
getTopWins()GET/bff/games/top-winsMaiores ganhos recentes
getLastWins()GET/bff/games/last-winsUltimos 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 /mobile e /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

  • transformGame converte demo: 0|1 para boolean e normaliza provider, casino_game_type, range
  • transformProvider converte games (count) para gameCount
  • transformCategory mapeia campos 1:1 incluindo icon
  • transformHomeRow classifica type como widget, custom-category ou custom-section
  • transformGameListResponse converte paginacao snake_case para camelCase
  • transformStartGameResponse extrai gameUrl de multiplos formatos possiveis da API (SoftSwiss vs padrao)

Legacy Service

Funcoes para integrar com o endpoint legado de jogos:

  • createLegacyGamesService(fetcher, homeConfig) — cria service usando GamesFetcher diretamente
  • createLegacyGamesFromClient(client, homeConfig) — cria service a partir de ApiClient

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:

TipoDescricao
"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 — boolean
  • launchMode — 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" → acao exit
  • amusnet: detecta acoes exit e reload
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:

ParamTipoDescricao
termstring?Busca por nome do jogo
categoriesstring[]?Filtro por categorias
providersstring[]?Filtro por providers
tagsstring[]?Filtro por tags
pagenumber?Pagina atual
perPagenumber?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