Pular para o conteúdo principal
← Voltar aos projetos

@herowcode/utils

Node.js TypeScript React Next.js

Visão Geral

@herowcode/utils nasceu para resolver um problema recorrente em projetos web: as mesmas funções utilitárias (formatar datas, gerar slugs, debouce/throttle, wrappers de API, helpers de YouTube, compressão de imagem) sendo copiadas e coladas entre vários repositórios. Cada correção ou melhoria precisava ser replicada manualmente, o que aumentava o risco de inconsistência e bugs difíceis de rastrear.

Implementei uma biblioteca única, escrita em TypeScript e pensada para ser tree‑shakable, que agrupa esses utilitários em módulos focados (/api/date/string/youtube/files/function/array/nextjs). Os consumidores podem importar apenas o que precisam, seja a partir da raiz ou via subpaths, mantendo o bundle enxuto. O build é feito com tsup, gerando CJS, ESM e declarações .d.ts, com configuração de sideEffects: false para facilitar tree‑shaking.

Um ponto central foi garantir que a mesma lib funcionasse bem em Node.js e no browser. Para isso, usei exports condicionais no package.json, expondo implementações específicas para cada ambiente em módulos sensíveis, como files e youtube. Além disso, a API segue um padrão que favorece segurança em produção, como o apiClient que sempre retorna { data, error } e encapsula retry, backoff e injeção de token sem lançar exceções que quebrem a aplicação.

Hoje, @herowcode/utils funciona como base compartilhada para múltiplos projetos do ecossistema HerowCode, reduzindo duplicação de código e permitindo que correções e melhorias sejam centralizadas em um único pacote.

Diferencial Principal

O diferencial do @herowcode/utils é o foco explícito em dois eixos: uso universal (Node + browser) e impacto mínimo de bundle. Em vez de ser apenas “mais um pacote de helpers”, a biblioteca foi desenhada para suportar cenários reais de frontend moderno, SSR e serviços Node, usando exports condicionais para expor implementações específicas por ambiente sem exigir configuração manual do consumidor.

Outro ponto que se destaca é o módulo de YouTube e o cliente HTTP. Em youtube, implementei um fluxo de fallback em três níveis para obter metadados de vídeo sem depender de uma API key: primeiro tenta extrair o ytInitialPlayerResponse da página de watch, depois o oEmbed oficial e por fim o NoEmbed. As requisições são cacheadas por ID como Promises compartilhadas, evitando chamadas duplicadas quando múltiplas partes do sistema pedem o mesmo dado ao mesmo tempo. Já o apiClient segue um padrão “never throw”: todas as operações retornam { data, error }, com retry/backoff configurável e injeção assíncrona de token, o que simplifica bastante o tratamento de erro em aplicações grandes.

Arquitetura

  • /api module: Cliente HTTP tipado (apiClient) com retry, backoff, injeção assíncrona de token e callback onSignoutUnauthorized em 401, sempre retornando { data, error }. Inclui wrappers como apiWrapper para padronizar operações assíncronas.
  • /date module: Utilitários de datas baseados em dayjs, como formatDategetRelativeTimeparseTimeSpent e helpers de correção de timezone (fixTimezoneOffsetgetCurrentDateInUTCgetDateInUTC).
  • /string module: Funções de transformação de string (como camelCasekebabCasesnakeCaseslugifycapitalize), truncamento, conversão de markdown para texto e formatadores de tempo (H:M:S).
  • /youtube module: Helpers para extrair ID (extractYouTubeId), gerar URLs (generateYoutubeURL), buscar metadata com fallback em três fontes (getYoutubeVideoInfo), obter thumbnail (getYoutubeThumbnail), validar links e ler duração do vídeo no browser (getYoutubeVideoDuration via IFrame API).
  • /files module: No browser, oferece compressImage (conversão para WebP via canvas offscreen), downloadUrl e formatBytes; em Node, expõe funções como fileExists e fileDelete via exports condicionais.
  • /function module: Utilitários de controle de fluxo como debouncethrottle e um tryCatch seguro que converte exceções em { data, error }.
  • /array module: Funções como shuffleunique e markdownToText aplicadas a coleções.
  • /nextjs module: Componente OptimizedImage para projetos Next.js, com react e next como peer dependencies, focado em DX e otimização de imagem.

Destaques Técnicos

  • Uso de exports condicionais no package.json para escolher automaticamente implementações específicas de browser ou Node.js em módulos como files e youtube, sem esforço extra do consumidor.
  • Pacote tree‑shakable com sideEffects: false e incentivo a imports por submódulo (@herowcode/utils/date@herowcode/utils/api), reduzindo o impacto no bundle final.
  • Build unificado com tsup, gerando CJS, ESM e declarações .d.ts, facilitando integração com diferentes bundlers (Vite, Webpack, etc.) e garantindo boa DX em TypeScript.
  • Cliente HTTP apiClient que nunca lança exceções, padronizando o retorno em { data, error }, com retry/backoff configurável, injeção de token e callback para deslogar em 401.
  • Estratégia de fallback em três níveis para metadados de YouTube (getYoutubeVideoInfo) com cache de Promises em andamento, evitando a necessidade de API key e prevenindo requisições duplicadas.
  • Utilitários de compressão de imagem no browser (compressImage) usando canvas offscreen para gerar WebP com controle de qualidade e tamanho máximo, mantendo o build de Node livre de dependências de DOM via exports condicionais.
  • Infra de qualidade com Vitest + jsdom para testes, Biome para lint/format e GitHub Actions para CI, garantindo consistência no pacote publicado.