Skip to content

Releases: nfe/client-nodejs

3.0.1

19 Jan 02:46
b63ad1f

Choose a tag to compare

🐛 Correções

  • Testes: Adicionada propriedade status como alias de code em NfeError para compatibilidade
  • Service Invoices: Corrigida extração de path do location header para preservar prefixo /v1
  • Service Invoices: Corrigido getStatus para identificar corretamente status de falha como terminal
  • Testes de Integração: Agora são pulados gracefully quando NFE_API_KEY não está definida
  • Testes Unitários: Corrigidas múltiplas assertions e timeouts
  • Mensagens de Erro: Melhoradas mensagens de erro para respostas async sem Location header

📝 Documentação

  • Melhorada documentação de extração de path do location header

3.0.0

19 Jan 01:24
7927be2

Choose a tag to compare

🎉 NFE.io SDK v3.0.0 - Release Notes


📣 Anúncio

Estamos muito felizes em anunciar o lançamento da versão 3.0 do SDK oficial NFE.io para Node.js! Esta é uma reescrita completa do SDK, modernizando completamente a base de código com TypeScript, eliminando dependências em runtime e oferecendo uma API limpa baseada em async/await.

🌟 Destaques Principais

  • TypeScript Nativo - Segurança de tipos completa e IntelliSense rico
  • 🚀 Zero Dependências em Runtime - Usa Fetch API nativa do Node.js
  • API Moderna Async/Await - Sem callbacks, código mais limpo
  • 🔄 Retry Automático - Lógica de retry inteligente com exponential backoff
  • 📦 Suporte Dual ESM/CommonJS - Funciona com ambos os sistemas de módulos
  • 🧪 Bem Testado - Mais de 80 testes com 88% de cobertura de código
  • 📖 Documentação Completa - JSDoc em todas as APIs públicas

🎯 O Que É Novo

✨ Recursos Principais

1. TypeScript Nativo com Segurança de Tipos Completa

import { NfeClient, ServiceInvoice } from 'nfe-io';

const nfe = new NfeClient({ 
  apiKey: 'sua-chave-api',
  environment: 'production' 
});

// IntelliSense completo e validação de tipos
const invoice: ServiceInvoice = await nfe.serviceInvoices.create(companyId, {
  borrower: {
    federalTaxNumber: '12345678000190',
    name: 'Cliente LTDA',
    email: 'cliente@exemplo.com.br'
  },
  cityServiceCode: '12345',
  servicesAmount: 1000.00
});

2. Zero Dependências em Runtime

  • Antes (v2): Dependia de when@3.1.0 (biblioteca desatualizada de promises)
  • Agora (v3): Usa apenas APIs nativas do Node.js 18+
  • Benefício: Menor superfície de ataque, menos vulnerabilidades, instalação mais rápida

3. API Moderna Async/Await

Antes (v2 - Callbacks):

nfe.serviceInvoices.create('company-id', data, function(err, invoice) {
  if (err) {
    console.error('Erro:', err);
    return;
  }
  console.log('Nota criada:', invoice);
});

Agora (v3 - Async/Await):

try {
  const invoice = await nfe.serviceInvoices.create('company-id', data);
  console.log('Nota criada:', invoice);
} catch (error) {
  console.error('Erro:', error);
}

4. Retry Automático com Exponential Backoff

const nfe = new NfeClient({
  apiKey: 'sua-chave-api',
  retryConfig: {
    maxRetries: 5,        // Até 5 tentativas
    baseDelay: 1000,      // Delay inicial de 1 segundo
    maxDelay: 30000,      // Delay máximo de 30 segundos
    retryableStatuses: [408, 429, 500, 502, 503, 504]
  }
});

// Retries automáticos em caso de erros temporários
const invoice = await nfe.serviceInvoices.create(companyId, data);

5. Polling Automático para Processamento Assíncrono

Novidade: Método createAndWait() para polling automático!

// Cria a nota e aguarda automaticamente o processamento
const invoice = await nfe.serviceInvoices.createAndWait(companyId, data, {
  maxAttempts: 30,   // Até 30 tentativas
  interval: 2000,    // Verifica a cada 2 segundos
  onProgress: (attempt) => {
    console.log(`Tentativa ${attempt} de 30...`);
  }
});

console.log('Nota processada:', invoice);

Alternativa - Polling Manual:

const result = await nfe.serviceInvoices.create(companyId, data);

if (result.status === 'pending') {
  const invoice = await nfe.pollUntilComplete(
    () => nfe.serviceInvoices.retrieve(companyId, result.id),
    { maxAttempts: 30, interval: 2000 }
  );
}

📦 Recursos Implementados

✅ Service Invoices (Notas Fiscais de Serviço)

  • create() - Criar nota fiscal com suporte a resposta 202
  • createAndWait() - NOVO! Criar e aguardar processamento
  • list() - Listar notas com paginação manual
  • retrieve() - Buscar nota específica
  • cancel() - Cancelar nota emitida
  • sendEmail() - Enviar nota por email
  • downloadPdf() - Download do PDF da nota
  • downloadXml() - Download do XML da nota

✅ Companies (Empresas)

  • create() - Criar empresa
  • list() - Listar empresas
  • retrieve() - Buscar empresa específica
  • update() - Atualizar empresa
  • uploadCertificate() - Upload de certificado digital (A1)

✅ Legal People (Pessoas Jurídicas)

  • create() - Criar pessoa jurídica
  • list() - Listar pessoas jurídicas
  • retrieve() - Buscar pessoa jurídica específica
  • update() - Atualizar pessoa jurídica
  • delete() - Deletar pessoa jurídica
  • findByTaxNumber() - NOVO! Buscar por CNPJ
  • createBatch() - NOVO! Criar múltiplas em lote

✅ Natural People (Pessoas Físicas)

  • create() - Criar pessoa física
  • list() - Listar pessoas físicas
  • retrieve() - Buscar pessoa física específica
  • update() - Atualizar pessoa física
  • delete() - Deletar pessoa física
  • findByTaxNumber() - NOVO! Buscar por CPF
  • createBatch() - NOVO! Criar múltiplas em lote

✅ Webhooks

  • create() - Criar webhook
  • list() - Listar webhooks
  • retrieve() - Buscar webhook específico
  • update() - Atualizar webhook
  • delete() - Deletar webhook
  • validateSignature() - NOVO! Validar assinatura do webhook

🛡️ Sistema de Erros Melhorado

Erros tipados com classes específicas para melhor tratamento:

import {
  AuthenticationError,
  ValidationError,
  NotFoundError,
  RateLimitError,
  ServerError,
  ConnectionError,
  TimeoutError
} from 'nfe-io';

try {
  const invoice = await nfe.serviceInvoices.create(companyId, data);
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('❌ Chave de API inválida');
  } else if (error instanceof ValidationError) {
    console.error('❌ Dados inválidos:', error.details);
    console.error('Campos com erro:', error.fields);
  } else if (error instanceof RateLimitError) {
    console.error('⏳ Rate limit atingido. Aguarde:', error.retryAfter, 'segundos');
  } else if (error instanceof NotFoundError) {
    console.error('❌ Recurso não encontrado');
  } else if (error instanceof ServerError) {
    console.error('❌ Erro no servidor NFE.io');
  } else if (error instanceof ConnectionError) {
    console.error('❌ Erro de conexão');
  } else if (error instanceof TimeoutError) {
    console.error('⏱️ Timeout na requisição');
  }
}

Estrutura dos Erros:

  • message - Mensagem descritiva do erro
  • statusCode - Código HTTP do erro
  • requestId - ID da requisição para suporte
  • details - Detalhes adicionais do erro
  • fields - (ValidationError) Campos com erro

🔧 Configuração Flexível

const nfe = new NfeClient({
  // Chave de API (obrigatória)
  apiKey: 'sua-chave-api', // ou use NFE_API_KEY env var
  
  // Ambiente (opcional, padrão: 'production')
  environment: 'production', // ou 'development'
  
  // URL base customizada (opcional)
  baseUrl: 'https://api.nfe.io/v1',
  
  // Timeout de requisições (opcional, padrão: 30000ms)
  timeout: 60000, // 60 segundos
  
  // Configuração de retry (opcional)
  retryConfig: {
    maxRetries: 5,
    baseDelay: 1000,
    maxDelay: 30000,
    retryableStatuses: [408, 429, 500, 502, 503, 504]
  }
});

// Configuração dinâmica
nfe.updateConfig({
  timeout: 90000,
  environment: 'development'
});

📖 Documentação e IntelliSense

Toda API pública tem JSDoc completo com exemplos:

/**
 * Create a new service invoice
 *
 * @param companyId - Company ID
 * @param data - Invoice data
 * @returns Created invoice or pending response
 *
 * @example
 * ```typescript
 * const invoice = await nfe.serviceInvoices.create('company-id', {
 *   borrower: { federalTaxNumber: '12345678000190', name: 'Cliente' },
 *   cityServiceCode: '12345',
 *   servicesAmount: 1000.00
 * });
 * ```
 */
create(companyId: string, data: CreateServiceInvoiceRequest): Promise<ServiceInvoice>;

🧪 Testes Completos

  • 80+ testes automatizados
  • 88% de cobertura de código
  • Testes unitários para toda lógica de negócio
  • Testes de integração com mocks da API
  • Testes de erro cobrindo todos os cenários
# Rodar testes
npm test

# Rodar com cobertura
npm run test:coverage

# Rodar em modo watch
npm run test:watch

🚨 Mudanças Incompatíveis (Breaking Changes)

1. Requisito de Node.js

  • Antes: Node.js >= 12.0.0
  • Agora: Node.js >= 18.0.0 (necessário para Fetch API nativo)

Ação necessária: Atualize para Node.js 18 ou superior

# Verificar versão
node --version

# Se < 18, atualize via nvm
nvm install 18
nvm use 18

2. Inicialização do Cliente

Antes (v2):

var nfe = require('nfe-io')('sua-chave-api');

Agora (v3):

// CommonJS
const { NfeClient } = require('nfe-io');
const nfe = new NfeClient({ apiKey: 'sua-chave-api' });

// ESM
import { NfeClient } from 'nfe-io';
const nfe = new NfeClient({ apiKey: 'sua-chave-api' });

3. Callbacks Removidos

Antes (v2):

nfe.serviceInvoices.create('company-id', data, function(err, invoice) {
  if (err) return console.error(err);
  console.log(invoice);
});

Agora (v3):

try {
  const invoice = await nfe.serviceInvoices.create('company-id', data);
  console.log(invoice);
} catch (error) {
  console.error(error);
}

4. Tratamento de Erros

Antes (v2):

if (err.type === 'AuthenticationError') {
  // tratar
}

Agora (v3):

import { AuthenticationError } from 'nfe-io';

if (error instanceof AuthenticationError) {
  // tratar
}

5. Configuração

Antes (v2):

var nfe = require('nfe-io')('api-key');
n...
Read more