npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

loterias-caixa

v0.2.0

Published

Biblioteca Node.js para consultar os resultados das loterias da Caixa Econômica Federal. Zero dependências de runtime.

Readme

loterias-caixa

CI

Biblioteca Node.js para consultar os resultados das loterias da Caixa Econômica Federal (Mega-Sena, Quina, Lotofácil e outras 8 modalidades).

A Caixa não publica uma API oficial de consulta. Esta lib encapsula o acesso à API interna do Portal de Loterias e devolve os dados já normalizados em tipos TypeScript estáveis, para que aplicações não precisem lidar com o formato bruto da Caixa (datas dd/MM/yyyy, campos com lixo, nomes de campo em português).

Zero dependências de runtime. Só usa o que já vem no Node.

Escrita em TypeScript, distribuída como ESM. Consumidores CommonJS podem usar require() normalmente (Node 22.12+).

Instalação

npm install loterias-caixa

Requer Node.js >= 22.12.0.

Uso

import { getLatestDraw, getDraw, getAllLatestDraws } from 'loterias-caixa';

// Último resultado de uma loteria
const draw = await getLatestDraw('megasena');
draw.contestNumber;         // 3050
draw.isAccumulated;         // true
draw.drawDate;              // Date (meia-noite UTC do dia do sorteio)
draw.drawnNumbers;          // ['11', '14', '30', '38', '49', '55']
draw.drawDaysOfWeek;        // ['SUN', 'TUE', 'THU']
draw.nextDrawPrizeEstimate; // 30000000
draw.nextDrawTime;          // '11:00' — horário de Brasília (DRAW_TIME_ZONE)
draw.nextSpecialDrawDate;   // Date — projeção do próximo concurso especial
draw.topPrize;              // { tier, winners, valuePerWinner } — o maior prêmio pago

// Modalidades com resultado além das dezenas
(await getLatestDraw('duplasena')).secondDrawNumbers;   // ['07', '11', ...] 2º sorteio
(await getLatestDraw('maismilionaria')).bonusNumbers;   // ['1', '6'] trevos
(await getLatestDraw('timemania')).bonusName;           // 'ATHLETICO/PR' time do coração
(await getLatestDraw('diadesorte')).bonusName;          // 'Abril' mês da sorte

// Um concurso específico
const antigo = await getDraw('quina', 7000);

// Todas as modalidades de uma vez, em paralelo e tolerante a falha parcial
const { draws, failures } = await getAllLatestDraws();
for (const falha of failures) {
  console.warn(falha.code, falha.error.message);
}

API

| Função | Descrição | | --- | --- | | getLatestDraw(code, options?) | Resultado do último concurso de uma loteria. | | getDraw(code, contestNumber, options?) | Resultado de um concurso específico. | | getAllLatestDraws(options?) | Último resultado de todas as modalidades, em paralelo. | | getSupportedLotteries() | Lista as modalidades suportadas (código + nome). | | isSupportedLottery(code) | Type guard para código de modalidade. | | getLotteryName(code) | Nome de exibição de uma modalidade. |

options aceita timeoutMs (10s), retries (2), retryDelayMs (300ms, com backoff exponencial) e fetch — este último existe para teste, não para uso em produção.

getAllLatestDraws nunca rejeita por falha de uma modalidade. Ela devolve { draws, failures }: quem falhou entra em failures com o erro, quem respondeu entra em draws, na ordem do catálogo. Um cronjob que atualiza 11 loterias não deve perder as 10 boas porque uma caiu.

Quatro modalidades têm resultado além das dezenas, e a lib devolve todos: secondDrawNumbers (o segundo sorteio da Dupla Sena), bonusNumbers (os trevos da +Milionária) e bonusName (o time do coração da Timemania e o mês da sorte do Dia de Sorte, que a Caixa manda no mesmo campo). Os campos só existem nas modalidades a que se aplicam — nas outras não vêm.

topPrize é o maior prêmio que o concurso de fato pagou, e não a faixa principal: quando ela acumula, o maior prêmio distribuído é o da faixa seguinte que teve ganhador — na Mega acumulada, a quina. Fica ausente quando nenhuma faixa teve ganhador. Não confunda com prizeValue, que é a faixa principal e vem 0 justamente nesse caso.

getLatestDraw projeta nextSpecialDrawDate. A projeção usa o calendário de hoje, que não vale para concurso antigo — a Mega sorteava às quartas e sábados até 2024.

Tratamento de erros

Toda falha lançada pela lib é instância de LotteryError, para que dê para distinguir "a Caixa caiu" de "esse concurso não existe" sem inspecionar a mensagem:

LotteryError
  ├── UnsupportedLotteryError   código de loteria fora do catálogo
  ├── NetworkError              falha de comunicação com a Caixa
  │     └── TimeoutError        a requisição estourou o tempo limite
  ├── HttpError                 a Caixa respondeu com status não-2xx
  ├── DrawNotFoundError         o concurso pedido não existe
  └── InvalidResponseError      resposta ilegível ou fora do formato
import { getDraw, DrawNotFoundError, NetworkError } from 'loterias-caixa';

try {
  await getDraw('megasena', 9999);
} catch (error) {
  if (error instanceof DrawNotFoundError) return null; // concurso ainda não sorteado
  if (error instanceof NetworkError) throw error;      // vale tentar de novo depois
  throw error;
}

Cada classe carrega o contexto da falha em campos próprios (status e url em HttpError, timeoutMs em TimeoutError, lotteryCode/contestNumber em DrawNotFoundError) e preserva a causa original em cause.

Todas retornam dados suficientes para popular a entidade draw do schema do backend, usando tipos nativos (Date, number) — a conversão para Timestamp do Firestore é responsabilidade de quem consome.

Calendário de sorteios

A Caixa não informa em que dias cada modalidade sorteia — o payload só traz a data do próximo concurso. Esses dados moram numa tabela estática em src/calendar.ts, e a lib os junta à resposta da API para preencher drawDaysOfWeek.

Ser estático tem um custo conhecido: quando a Caixa muda a agenda (como fez em julho de 2026, movendo os sorteios de sábado para a manhã de domingo), a tabela envelhece até alguém atualizá-la. A aposta é que um arquivo único, sem lógica dentro, é fácil de corrigir por qualquer pessoa — se você notou uma agenda errada, abra um PR mudando só esse arquivo. Os testes conferem a tabela contra o dia da semana real das respostas guardadas em test/fixtures/.

O calendário também é a origem de nextDrawTime, o horário do próximo sorteio. Ele é o horário do próximo concurso, não um horário fixo da modalidade, porque para a maioria delas esse valor único não existe: a Mega-Sena sorteia às 21h de terça e quinta e às 11h aos domingos.

Todo horário é de Brasília, e o fuso é exportado como DRAW_TIME_ZONE ('America/Sao_Paulo') em vez de ficar implícito — horário de parede sem fuso declarado é bug garantido em quem roda em UTC.

nextDrawTime fica ausente quando não há próximo concurso agendado (o caso da Federal) ou quando a data dele não cai em dia de sorteio conhecido: a Loteca apura às segundas, mas a API devolve a data da rodada de jogos, que cai no sábado. Sem saber o horário, a lib não chuta um.

Desenvolvimento

npm install
npm test                     # suíte de testes (roda direto no fonte TypeScript)
npm run test:coverage        # com relatório de cobertura
npm run test:coverage:strict # o mesmo, falhando abaixo de 100% (é o gate do CI)
npm run typecheck            # valida tipos de src/ e test/
npm run build                # gera dist/

Os testes rodam sobre os arquivos .ts sem etapa de build, usando o suporte nativo do Node a TypeScript e o runner node:test. Nenhum teste acessa a rede — a suíte passa offline, sobre as respostas reais guardadas em test/fixtures/.

O CI roda typecheck, a suíte com gate de 100% de cobertura e o build em Node 22.x e 24.x, e ainda confere que o dist/ publicado carrega por require() e por import() na versão mínima declarada (22.12). Rode npm run test:coverage:strict antes de abrir PR — é exatamente o que o CI vai executar.

Convenções e decisões de arquitetura estão em CLAUDE.md.

Licença

MIT © Daniel Campos

Projeto independente, sem qualquer vínculo com a Caixa Econômica Federal. Os dados consultados são de origem pública.