Skip to content

RubensGJ/AgroSmartAPI

Repository files navigation

AgroSmart API

API Node.js/Express para coletar, salvar e consultar cotacoes de graos das fontes Coamo, C.Vale, LAR e Granos.

A aplicacao usa Puppeteer para scraping, cache em memoria para respostas rapidas e Neon/Postgres para manter historico e ultimo snapshot valido por fonte.

Funcionalidades

  • Coleta de cotacoes via scraping com Puppeteer.
  • Consulta atual por fonte: Coamo, C.Vale, LAR e Granos.
  • Consulta consolidada com contrato parcial por fonte em /api/cotacoes/todos.
  • Filtros por grao, local, descricao, fornecedor e unidade.
  • Melhor preco, comparativo entre fontes, variacao historica e exportacao CSV.
  • Persistencia em Neon/Postgres com historico e ultima cotacao por fonte.
  • Cache em memoria aquecido a partir do banco na subida da API.
  • Scheduler automatico com node-cron.
  • Health check simples para uptime e health check profundo para operacao.
  • Documentacao OpenAPI servida via Swagger UI.

Stack

  • Node.js >=18 <25
  • Express
  • Puppeteer
  • node-cron
  • PostgreSQL/Neon via pg
  • Swagger UI + OpenAPI

Requisitos

  • Node.js >=18 <25
  • npm
  • Banco PostgreSQL/Neon acessivel por DATABASE_URL
  • Chrome do Puppeteer instalado ou disponivel no ambiente

Instalacao

git clone <URL_DO_REPOSITORIO>
cd AgroSmartAPI
npm install

Crie o .env com base no exemplo:

Copy-Item .env.example .env

No Linux/macOS:

cp .env.example .env

Depois valide o Chrome usado pelo Puppeteer:

npm run check:chrome

O npm install executa o postinstall e baixa para .cache/puppeteer a revisao de Chrome esperada pela versao do Puppeteer. Em deploys como Render, mantenha a faixa de Node do package.json para evitar versoes atuais demais, como Node 26, antes das dependencias estarem validadas.

Variaveis de ambiente

Use .env.example como referencia.

PORT=3000
APP_TIMEZONE=America/Sao_Paulo
AUTH_ENABLED=true
API_TOKEN=troque-este-token-por-um-valor-seguro
DATABASE_URL=postgresql://USER:PASSWORD@HOST/DBNAME?sslmode=require
DATABASE_SSL=true
PUPPETEER_HEADLESS=true
SCHEDULER_ENABLED=true
SCHEDULER_TIMEZONE=America/Sao_Paulo
SCHEDULER_CRON_1=0 11 * * *
SCHEDULER_CRON_2=0 14 * * *
SCRAPER_PARALLEL_COLLECTION=false
SCRAPER_NAV_TIMEOUT_MS=90000
SCRAPER_SELECTOR_TIMEOUT_MS=45000
SCRAPER_RETRY_MAX_ATTEMPTS=3
SCRAPER_RETRY_DELAY_MS=180000

Observacoes importantes:

  • AUTH_ENABLED=true protege as rotas /api/cotacoes/*.
  • DATABASE_SSL=true e recomendado para Neon.
  • SCHEDULER_ENABLED=false desliga coletas automaticas.
  • SCRAPER_PARALLEL_COLLECTION=false e mais conservador para ambientes pequenos.
  • /api/cotacoes/todos respeita SCRAPER_PARALLEL_COLLECTION mesmo usando resposta parcial por fonte.
  • force=true em rotas de consulta dispara scraping ao vivo, trafego externo e escrita no banco.

Comandos

npm start

Sobe a API em modo producao com node src/app.js.

npm run dev

Sobe a API em modo desenvolvimento com node --watch.

npm run check:chrome

Verifica se o Chrome do Puppeteer esta disponivel.

npm test

Atualmente falha de proposito com no test specified; ainda nao ha suite de testes configurada.

Rotas publicas

Base local: http://localhost:3000

  • GET /: status simples da API.
  • GET /health: health check leve para uptime.
  • GET /health/deep: diagnostico operacional completo.
  • GET /docs: Swagger UI.
  • GET /openapi.yaml: contrato OpenAPI bruto.

/health/deep verifica banco, snapshots recentes, Chrome do Puppeteer e scheduler. Ele retorna ok, degraded ou fail e nao executa scraping.

Autenticacao

Quando AUTH_ENABLED=true, todas as rotas em /api/cotacoes/* exigem token.

Formatos aceitos:

  • Authorization: Bearer <API_TOKEN>
  • x-api-token: <API_TOKEN>

Exemplo:

curl -H "Authorization: Bearer SEU_TOKEN" http://localhost:3000/api/cotacoes/todos

Rotas de cotacoes

Fontes aceitas em parametros: all, coamo, cvale, lar, granos.

  • GET /api/cotacoes/coamo: cotacoes atuais da Coamo.
  • GET /api/cotacoes/cvale: cotacoes atuais da C.Vale.
  • GET /api/cotacoes/lar: cotacoes atuais da LAR.
  • GET /api/cotacoes/granos: cotacoes atuais da Granos.
  • GET /api/cotacoes/todos: resposta consolidada das fontes oficiais.
  • GET /api/cotacoes/filtro: cotacoes atuais filtradas.
  • GET /api/cotacoes/melhor-preco: maior preco encontrado para um grao.
  • GET /api/cotacoes/comparativo: comparativo entre fontes para um grao.
  • GET /api/cotacoes/variacao: variacao historica de uma fonte especifica.
  • GET /api/cotacoes/periodo: itens historicos dentro de um periodo.
  • GET /api/cotacoes/exportar: exporta cotacoes filtradas em CSV.
  • GET /api/cotacoes/historico: snapshots historicos salvos.

Parametros comuns:

  • force=true: ignora cache e tenta uma nova coleta.
  • fonte=all|coamo|cvale|lar|granos: seleciona a origem quando a rota permite.
  • grao, local, descricao, fornecedor, unidade: filtros textuais.
  • dataInicio=YYYY-MM-DD e dataFim=YYYY-MM-DD: periodo historico.
  • limit=50: limite de snapshots ou itens, conforme a rota.

Exemplos:

curl -H "Authorization: Bearer SEU_TOKEN" "http://localhost:3000/api/cotacoes/filtro?fonte=all&grao=soja"
curl -H "Authorization: Bearer SEU_TOKEN" "http://localhost:3000/api/cotacoes/melhor-preco?fonte=all&grao=milho"
curl -H "Authorization: Bearer SEU_TOKEN" "http://localhost:3000/api/cotacoes/periodo?fonte=coamo&dataInicio=2026-06-01&dataFim=2026-06-24"

Contrato parcial de /api/cotacoes/todos

A rota consolidada nao deve derrubar a resposta inteira quando uma fonte falha. Ela retorna version: 2, partial e um envelope por fonte:

{
  "version": 2,
  "partial": true,
  "coamo": {
    "ok": true,
    "data": [],
    "stale": false,
    "error": null
  },
  "cvale": {
    "ok": true,
    "data": [],
    "stale": true,
    "error": {
      "message": "Falha ao coletar cotacoes da C.Vale",
      "statusCode": 502,
      "details": null
    }
  },
  "larAgro": {
    "ok": false,
    "data": [],
    "stale": false,
    "error": {
      "message": "Falha ao coletar cotacoes da LAR",
      "statusCode": 502,
      "details": null
    }
  },
  "granos": {
    "ok": true,
    "data": [],
    "stale": false,
    "error": null
  }
}

stale=true significa que a API devolveu o ultimo dado valido conhecido porque a coleta atual falhou.

Fluxo de dados

  1. A API sobe, valida configuracoes, valida Chrome, inicializa o banco e aquece o cache com cotacoes_ultima.
  2. Uma consulta sem force=true usa cache em memoria, depois banco, depois scraping se nao houver dado salvo.
  3. Uma consulta com force=true executa scraping ao vivo.
  4. Coleta bem-sucedida:
    • insere um snapshot em cotacoes_historico;
    • atualiza o ultimo snapshot em cotacoes_ultima;
    • atualiza o cache em memoria.
  5. Coleta com erro ou payload vazio nao salva dado novo.

Tabelas criadas automaticamente na subida:

  • cotacoes_historico
  • cotacoes_ultima
  • logs_requisicoes

Estrutura principal

  • src/app.js: bootstrap da API, middlewares, Swagger, health e rotas.
  • src/routes/cotacoesRoutes.js: definicao das rotas HTTP de cotacoes.
  • src/services/cotacaoService.js: ponto unico de exportacao dos services.
  • src/services/cotacoes/currentCotacaoService.js: cache, scraping, retry e snapshots atuais.
  • src/services/cotacoes/analysisCotacaoService.js: filtros, melhor preco, comparativo e CSV.
  • src/services/cotacoes/historyCotacaoService.js: historico, periodo e variacao.
  • src/services/healthService.js: diagnostico operacional profundo.
  • src/scrapers/: scrapers Puppeteer de Coamo, C.Vale, LAR, Granos e fontes experimentais.
  • src/database/: conexao, schema e repositorios Postgres.
  • src/utils/: normalizacao, filtros, datas, CSV e utilitarios do Puppeteer.
  • src/jobs/cotacaoScheduler.js: jobs automaticos de coleta.
  • scripts/: instalacao e verificacao do Chrome do Puppeteer.
  • openapi.yaml: contrato publico da API.
  • docs/: documentacao tecnica e relatorios.

Operacao e deploy

  • O scheduler roda dentro do mesmo processo da API.
  • Em plataformas com sleep/scale-to-zero, os jobs nao executam enquanto o processo estiver parado.
  • Em ambiente limitado, mantenha SCRAPER_PARALLEL_COLLECTION=false.
  • Se houver timeout de scraping, ajuste SCRAPER_NAV_TIMEOUT_MS e SCRAPER_SELECTOR_TIMEOUT_MS.
  • A C.Vale pode ficar indisponivel fora dos horarios aceitos pelo site de origem.
  • Nao exponha .env, DATABASE_URL, API_TOKEN ou tokens de plataforma.

Documentacao da API

  • Swagger UI: http://localhost:3000/docs
  • OpenAPI bruto: http://localhost:3000/openapi.yaml
  • Arquivo fonte: openapi.yaml

Quando uma rota, parametro, contrato de resposta ou variavel de ambiente mudar, atualize este README e o openapi.yaml.

Licenca

ISC

About

API auxiliar do projeto AgroSmart, responsavel pela coleta de cotação de grãos, além da população do banco para historico

Topics

Resources

Stars

Watchers

Forks

Contributors