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/searchVia 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 delay4. 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 customizadosshowSuggestions?: 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 headerX-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 resultadospage?: number- Número da página (padrão: 1)timeout?: number- Timeout específico para esta requisiçãoheaders?: Record<string, string>- Headers específicosshowSuggestions?: 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 headerX-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 pesquisacallback: (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 originalcurrentPage: number- Página atualoptions?: 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 originalcurrentPage: number- Página atualoptions?: 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 pesquisapage: number- Número da páginaoptions?: 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 pesquisaoptions?: 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 pesquisaoptions?: 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 installCompilação
npm run buildDesenvolvimento com Watch
npm run devTestes
npm testLinting
npm run lint📦 Publicação
Configuração do Azure Artifacts
Este pacote é publicado no Azure Artifacts. Para configurar a autenticação localmente:
Gerar um Personal Access Token (PAT) com permissões de Packaging (Read & Write)
Configurar a variável de ambiente:
export AZURE_PAT='seu_pat_aqui'
Testar a autenticação:
./scripts/test-auth.sh
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.jsAcessar 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
- Fork o projeto
- Crie uma branch para sua feature (
git checkout -b feature/AmazingFeature) - Commit suas mudanças (
git commit -m 'Add some AmazingFeature') - Push para a branch (
git push origin feature/AmazingFeature) - 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.