JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q35816F
  • License MIT

Biblioteca Node.js

Package Exports

  • @otempo/search
  • @otempo/search/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@otempo/search) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

🗞️ O Tempo Search

Uma biblioteca Node.js moderna e tipada para integração com a API de pesquisa da O Tempo, oferecendo funcionalidades de busca com sugestões em tempo real.

✨ Características

  • 🔍 Pesquisa em tempo real com sugestões automáticas
  • 📄 Paginação completa com navegação entre páginas
  • Debounce inteligente para otimizar requisições
  • 📊 Estatísticas de pesquisa com análises detalhadas
  • 🏷️ Filtros por categoria (versal)
  • 🔧 Configuração flexível com timeouts e headers customizados
  • 📝 TypeScript completo com tipos bem definidos
  • 🚀 Performance otimizada com axios
  • 🛡️ Tratamento de erros robusto

📦 Instalação

Via NPM (Recomendado)

npm install @otempo/search

Via CDN (Navegador)

<!-- Carregando via unpkg -->
<script src="https://unpkg.com/axios@1.6.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/@otempo/search@latest/dist/otempo-search.umd.min.js"></script>

<!-- Ou via jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/axios@1.6.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@otempo/search@latest/dist/otempo-search.umd.min.js"></script>

🚀 Uso Rápido

Pesquisa Básica

const { search } = require('otempo-search');

// Pesquisa simples
const resultados = await search('bomba');
console.log(`Encontrados ${resultados.meta.count} resultados`);

Com TypeScript

import { search, SearchResponse } from '@otempo/search';

const resultados: SearchResponse = await search('guerra');
resultados.data.forEach(item => {
  console.log(`${item.titulo} - ${item.versal}`);
});

Via CDN (Navegador)

// Após carregar os scripts, a biblioteca fica disponível globalmente
const resultados = await window.OtempoSearch.search('tecnologia');
console.log(`Encontrados ${resultados.meta.count} resultados`);

// Usando funções helper
const sugestoes = await window.OtempoSearch.getSuggestions('politica', 5);

// Criando instância customizada
const cliente = new window.OtempoSearch.OtempoSearch({
  clientId: 'meu-app-123',
  searchIndex: 'news-index'
});

📚 Exemplos Detalhados

🔑 Client ID

A biblioteca suporta o envio de um Client ID em todas as requisições para identificação e rastreamento. O ID é enviado como header X-Client-ID.

// Configurando clientId na instância
const cliente = new OtempoSearch({
  clientId: 'meu-app-123'
});

// Todas as requisições incluirão o clientId
const resultados = await cliente.search('tecnologia');

// Ou passando clientId por chamada específica
const resultados2 = await cliente.search('esportes', {
  clientId: 'app-esportes-456'
});

// Com funções helper
const sugestoes = await getSuggestions('politica', 5, {
  clientId: 'app-politica-789'
});

🔍 Search Index

A biblioteca suporta o envio de um Search Index como query parameter para especificar qual índice de pesquisa usar. O índice é enviado como parâmetro searchIndex na URL.

// Configurando searchIndex na instância
const cliente = new OtempoSearch({
  searchIndex: 'news-index'
});

// Todas as requisições incluirão o searchIndex
const resultados = await cliente.search('tecnologia');

// Ou passando searchIndex por chamada específica
const resultados2 = await cliente.search('esportes', {
  searchIndex: 'sports-index'
});

// Com funções helper
const sugestoes = await getSuggestions('politica', 5, {
  searchIndex: 'politics-index'
});

// Combinando clientId e searchIndex
const clienteCompleto = new OtempoSearch({
  clientId: 'meu-app-123',
  searchIndex: 'main-index'
});

1. Pesquisa com Opções

const { OtempoSearch } = require('otempo-search');

const cliente = new OtempoSearch({
  timeout: 10000,
  headers: {
    'X-Custom-Header': 'meu-app'
  }
});

const resultados = await cliente.search('política', {
  limit: 10
});

1.1. Pesquisa com Client ID

const { OtempoSearch } = require('otempo-search');

// Configurando clientId na instância
const cliente = new OtempoSearch({
  clientId: 'meu-app-123',
  timeout: 10000
});

// Todas as requisições deste cliente incluirão o clientId
const resultados = await cliente.search('tecnologia');

// Ou passando clientId por chamada
const resultados2 = await cliente.search('esportes', {
  clientId: 'app-esportes-456',
  limit: 10
});

2. Sugestões em Tempo Real

const { getSuggestions } = require('otempo-search');

// Busca 5 sugestões para "economia"
const sugestoes = await getSuggestions('economia', 5);
sugestoes.forEach(sugestao => {
  console.log(sugestao.titulo);
});

// Com clientId
const sugestoesComId = await getSuggestions('politica', 5, {
  clientId: 'app-politica-789'
});

3. Pesquisa com Debounce

const { OtempoSearch } = require('otempo-search');

const cliente = new OtempoSearch();

// Simula digitação do usuário
cliente.searchWithDebounce('tecnologia', (response) => {
  console.log(`📊 ${response.meta.totalResults} resultados encontrados`);
  console.log(`📄 Página ${response.meta.page} de ${response.meta.totalPages}`);
  
  // Acessa os resultados
  response.data.forEach(item => {
    console.log(`- ${item.titulo} (${item.versal})`);
  });
  
  // Verifica paginação
  if (response.meta.hasNextPage) {
    console.log('⏭️ Tem próxima página');
  }
}, 300); // 300ms de delay

4. Filtros por Categoria

const { OtempoSearch } = require('otempo-search');

const cliente = new OtempoSearch();

// Busca apenas notícias de esporte
const noticiasEsporte = await cliente.searchByCategory('ESPORTE');

5. Estatísticas da Pesquisa

const { OtempoSearch } = require('otempo-search');

const cliente = new OtempoSearch();

const stats = await cliente.getSearchStats('cultura');
console.log(`Total: ${stats.totalResults}`);
console.log(`Média de caracteres: ${stats.averageTitleLength}`);
console.log('Categorias:', stats.categories);

6. Paginação

const { search, getNextPage, getPage, getPaginationInfo } = require('otempo-search');

// Pesquisa com paginação
const resultado = await search('hugo', { limit: 5, page: 1 });
console.log(`Página ${resultado.meta.page} de ${resultado.meta.totalPages}`);

// Buscar próxima página
if (resultado.meta.hasNextPage) {
  const proximaPagina = await getNextPage('hugo', resultado.meta.page, { limit: 5 });
  console.log(`Próxima página: ${proximaPagina.data.length} resultados`);
}

// Buscar página específica
const pagina2 = await getPage('hugo', 2, { limit: 5 });

// Obter informações de paginação
const info = await getPaginationInfo('hugo', { limit: 10 });
console.log(`Total: ${info.totalResults}, Páginas: ${info.totalPages}`);

🔧 API Reference

Classe OtempoSearch

Construtor

new OtempoSearch(config?: OtempoSearchConfig)

Configurações:

  • baseURL?: string - URL base da API (padrão: https://searchapi.otempo.com.br/api)
  • timeout?: number - Timeout em ms (padrão: 5000)
  • headers?: Record<string, string> - Headers customizados
  • showSuggestions?: boolean - Mostrar dropdown de sugestões por padrão (padrão: true)
  • showSuggestionsInResults?: boolean - Mostrar sugestões na lista por padrão (padrão: false)
  • clientId?: string - ID do cliente para incluir em todas as requisições (enviado como header X-Client-ID)
  • searchIndex?: string - Índice de pesquisa para incluir como query parameter

Métodos

search(query: string, options?: SearchOptions): Promise<SearchResponse>

Realiza uma pesquisa na API.

Parâmetros:

  • query: string - Termo de pesquisa (mínimo 2 caracteres)
  • options?: SearchOptions - Opções da pesquisa

Opções:

  • limit?: number - Número máximo de resultados
  • page?: number - Número da página (padrão: 1)
  • timeout?: number - Timeout específico para esta requisição
  • headers?: Record<string, string> - Headers específicos
  • showSuggestions?: boolean - Mostrar dropdown de sugestões (padrão: true)
  • showSuggestionsInResults?: boolean - Mostrar sugestões na lista de resultados (padrão: false)
  • clientId?: string - ID do cliente para incluir nesta requisição (enviado como header X-Client-ID)
  • searchIndex?: string - Índice de pesquisa para incluir como query parameter

Observações:

  • A query deve ter pelo menos 2 caracteres para otimizar o uso da API
searchWithDebounce(query: string, callback: Function, delay?: number, options?: SearchOptions): void

Realiza pesquisa com debounce para sugestões em tempo real.

Parâmetros:

  • query: string - Termo de pesquisa
  • callback: (response: SearchResponse) => void - Função de callback com resposta completa (incluindo metadados de paginação)
  • delay?: number - Delay em ms (padrão: 300)
  • options?: SearchOptions - Opções da pesquisa

Observações:

  • O callback recebe a resposta completa da API, incluindo metadados de paginação
  • Para acessar apenas os resultados, use response.data
  • Para acessar os metadados, use response.meta
getSuggestions(query: string, maxSuggestions?: number, options?: SearchOptions): Promise<SearchResult[]>

Busca sugestões para um termo.

Parâmetros:

  • query: string - Termo de pesquisa (mínimo 2 caracteres)
  • maxSuggestions?: number - Máximo de sugestões (padrão: 5)
  • options?: SearchOptions - Opções da pesquisa
searchByCategory(versal: string, options?: SearchOptions): Promise<SearchResult[]>

Busca notícias por categoria específica.

getSearchStats(query: string, options?: SearchOptions): Promise<SearchStats>

Obtém estatísticas da pesquisa.

cancelSearch(): void

Cancela a pesquisa com debounce pendente.

getNextPage(query: string, currentPage: number, options?: SearchOptions): Promise<SearchResponse>

Busca a próxima página de resultados.

Parâmetros:

  • query: string - Termo de pesquisa original
  • currentPage: number - Página atual
  • options?: SearchOptions - Opções da pesquisa
getPrevPage(query: string, currentPage: number, options?: SearchOptions): Promise<SearchResponse>

Busca a página anterior de resultados.

Parâmetros:

  • query: string - Termo de pesquisa original
  • currentPage: number - Página atual
  • options?: SearchOptions - Opções da pesquisa

Observações:

  • Lança erro se tentar buscar página anterior à primeira
getPage(query: string, page: number, options?: SearchOptions): Promise<SearchResponse>

Busca uma página específica de resultados.

Parâmetros:

  • query: string - Termo de pesquisa
  • page: number - Número da página
  • options?: SearchOptions - Opções da pesquisa

Observações:

  • Lança erro se o número da página for menor que 1
getAllPages(query: string, options?: SearchOptions): Promise<SearchResult[]>

Obtém todas as páginas de resultados para uma pesquisa.

Parâmetros:

  • query: string - Termo de pesquisa
  • options?: SearchOptions - Opções da pesquisa

Observações:

  • Busca automaticamente todas as páginas disponíveis
  • Inclui limite de segurança de 100 páginas para evitar loops infinitos
getPaginationInfo(query: string, options?: SearchOptions): Promise<PaginationInfo>

Obtém informações de paginação para uma pesquisa.

Parâmetros:

  • query: string - Termo de pesquisa
  • options?: SearchOptions - Opções da pesquisa

Retorna:

{
  currentPage: number;
  totalPages: number;
  totalResults: number;
  hasNextPage: boolean;
  hasPrevPage: boolean;
  resultsPerPage: number;
}

Funções Helper

search(query: string, options?: SearchOptions): Promise<SearchResponse>

Função helper para pesquisa rápida usando instância padrão.

getSuggestions(query: string, maxSuggestions?: number, options?: SearchOptions): Promise<SearchResult[]>

Função helper para sugestões rápidas.

getNextPage(query: string, currentPage: number, options?: SearchOptions): Promise<SearchResponse>

Função helper para buscar próxima página.

getPrevPage(query: string, currentPage: number, options?: SearchOptions): Promise<SearchResponse>

Função helper para buscar página anterior.

getPage(query: string, page: number, options?: SearchOptions): Promise<SearchResponse>

Função helper para buscar página específica.

getAllPages(query: string, options?: SearchOptions): Promise<SearchResult[]>

Função helper para obter todas as páginas.

getPaginationInfo(query: string, options?: SearchOptions): Promise<PaginationInfo>

Função helper para obter informações de paginação.

📊 Tipos TypeScript

SearchResult

interface SearchResult {
  titulo: string;      // Título da notícia
  versal: string;      // Categoria/versal
  bigode: string;      // Resumo/descrição
  imagem: string;      // URL da imagem
  path: string;        // Caminho/URL da notícia
}

SearchResponse

interface SearchResponse {
  success: boolean;           // Sucesso da requisição
  data: SearchResult[];       // Array de resultados
  meta: SearchMeta;          // Metadados da pesquisa
}

SearchMeta

interface SearchMeta {
  query: string;              // Query executada
  count: number;              // Total de resultados
  limit: number;              // Limite por página
  page: number;               // Página atual
  totalPages: number;         // Número total de páginas
  totalResults: number;       // Número total de resultados
  hasNextPage: boolean;       // Indica se existe próxima página
  hasPrevPage: boolean;       // Indica se existe página anterior
  timestamp: string;          // Timestamp da resposta
}

🛠️ Desenvolvimento

Instalação das Dependências

npm install

Compilação

npm run build

Desenvolvimento com Watch

npm run dev

Testes

npm test

Linting

npm run lint

📦 Publicação

Configuração do Azure Artifacts

Este pacote é publicado no Azure Artifacts. Para configurar a autenticação localmente:

  1. Gerar um Personal Access Token (PAT) com permissões de Packaging (Read & Write)

  2. Configurar a variável de ambiente:

    export AZURE_PAT='seu_pat_aqui'
  3. Testar a autenticação:

    ./scripts/test-auth.sh
  4. Publicar o pacote:

    npm run publish:azure

Pipeline de CI/CD

O projeto usa Azure DevOps Pipeline para publicação automática. O pipeline:

  • Executa testes e linting
  • Compila o código TypeScript
  • Publica automaticamente no Azure Artifacts quando há commits na branch master

Estrutura do Feed

  • Registry: https://pkgs.dev.azure.com/gruposada/0ac0f368-01b8-4a03-8223-f071ef20141a/_packaging/Otempo-Search/npm/registry/
  • Escopo: @otempo
  • Nome do pacote: @otempo/search

🎨 Frontend de Teste

Para testar a biblioteca de forma interativa, você pode usar o frontend incluído:

Iniciar o Frontend

# Usando npm script (recomendado)
npm run frontend

# Ou navegando para a pasta
cd frontend && node server.js

Acessar o Frontend

Abra seu navegador e acesse: http://localhost:3000

Funcionalidades do Frontend

  • 🔍 Pesquisa em tempo real com sugestões automáticas
  • 💡 Sugestões inteligentes que aparecem enquanto você digita
  • 📊 Estatísticas detalhadas dos resultados da pesquisa
  • 🎨 Interface moderna e responsiva
  • Performance otimizada com debounce

Para mais detalhes, consulte o README do Frontend.

📁 Estrutura do Projeto

otempo_search/
├── src/
│   ├── types/
│   │   └── index.ts          # Definições de tipos
│   ├── OtempoSearch.ts       # Classe principal
│   └── index.ts              # Exports principais
├── examples/
│   ├── basic-usage.js        # Exemplos JavaScript
│   └── typescript-usage.ts   # Exemplos TypeScript
├── frontend/                 # Frontend de teste
│   ├── index.html            # Página principal
│   ├── app.js                # Lógica da aplicação
│   ├── server.js             # Servidor Node.js
│   └── README.md             # Documentação do frontend
├── tests/                    # Testes unitários
│   ├── setup.ts              # Configuração dos testes
│   └── OtempoSearch.test.ts  # Testes da biblioteca
├── dist/                     # Código compilado
├── package.json
├── tsconfig.json
└── README.md

🌐 Uso via CDN

A biblioteca está disponível via CDN para uso direto no navegador, sem necessidade de instalação via NPM.

URLs dos CDNs

unpkg:

  • https://unpkg.com/@otempo/search@latest/dist/otempo-search.umd.min.js

jsdelivr:

  • https://cdn.jsdelivr.net/npm/@otempo/search@latest/dist/otempo-search.umd.min.js

Exemplo Completo

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>O Tempo Search - Exemplo CDN</title>
</head>
<body>
    <h1>🗞️ O Tempo Search</h1>
    <input type="text" id="searchInput" placeholder="Digite sua pesquisa...">
    <button onclick="search()">🔍 Pesquisar</button>
    <div id="results"></div>

    <!-- Carregando a biblioteca via CDN -->
    <script src="https://unpkg.com/axios@1.6.0/dist/axios.min.js"></script>
    <script src="https://unpkg.com/@otempo/search@latest/dist/otempo-search.umd.min.js"></script>
    
    <script>
        async function search() {
            const query = document.getElementById('searchInput').value;
            try {
                const results = await window.OtempoSearch.search(query);
                document.getElementById('results').innerHTML = 
                    `<p>Encontrados ${results.meta.count} resultados</p>`;
            } catch (error) {
                console.error('Erro:', error);
            }
        }
    </script>
</body>
</html>

Funcionalidades Disponíveis via CDN

  • Pesquisa básica: window.OtempoSearch.search(query, options)
  • Sugestões: window.OtempoSearch.getSuggestions(query, maxSuggestions, options)
  • Paginação: window.OtempoSearch.getPage(query, page, options)
  • Instância customizada: new window.OtempoSearch.OtempoSearch(config)
  • Todas as funções helper disponíveis no objeto global

Exemplos de Uso via CDN

// Pesquisa básica
const results = await window.OtempoSearch.search('tecnologia');

// Com configurações
const results = await window.OtempoSearch.search('esportes', {
    limit: 10,
    clientId: 'meu-app-123',
    searchIndex: 'news-index'
});

// Sugestões
const suggestions = await window.OtempoSearch.getSuggestions('politica', 5);

// Instância customizada
const client = new window.OtempoSearch.OtempoSearch({
    clientId: 'custom-app',
    timeout: 10000
});

Exemplos Prontos

🔗 Endpoint da API

A biblioteca consome o endpoint:

https://searchapi.otempo.com.br/api/search?q={query}

Resposta esperada:

{
  "success": true,
  "data": [
    {
      "titulo": "Título da notícia",
      "versal": "CATEGORIA",
      "bigode": "Resumo da notícia",
      "imagem": "/path/to/image.jpg",
      "path": "/path/to/news"
    }
  ],
  "meta": {
    "query": "termo pesquisado",
    "count": 1,
    "limit": 20,
    "page": 1,
    "totalPages": 1,
    "totalResults": 1,
    "hasNextPage": false,
    "hasPrevPage": false,
    "timestamp": "2025-07-02T11:52:18.510Z"
  }
}

🤝 Contribuindo

  1. Fork o projeto
  2. Crie uma branch para sua feature (git checkout -b feature/AmazingFeature)
  3. Commit suas mudanças (git commit -m 'Add some AmazingFeature')
  4. Push para a branch (git push origin feature/AmazingFeature)
  5. Abra um Pull Request

📄 Licença

Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para detalhes.

🆘 Suporte

Se você encontrar algum problema ou tiver dúvidas, por favor abra uma issue.


Desenvolvido com ❤️ para a comunidade de desenvolvedores brasileiros.