node-fiscal
v0.1.0
Published
Motor fiscal TypeScript/Node para NF-e, NFC-e e NFS-e: XML, assinatura, transmissão, journal durável e recuperação
Maintainers
Readme
node-fiscal
Motor fiscal TypeScript/Node para NF-e, NFC-e e NFS-e: geração e validação de XML, assinatura, transmissão (SOAP/REST com mTLS), journal durável com idempotência e recuperação sem reenvio, distribuição e documentos auxiliares. Regras, schemas e endpoints vêm das fontes oficiais (Portal NF-e, portal NFC-e/ENCAT, gov.br NFS-e).
Versão 0.1.0: contratos ainda podem mudar em versões 0.x. Homologada até aqui: NFS-e nacional (emissão, consulta, DANFSe e cancelamento na produção restrita) e status da SEFAZ em homologação para MG, SP, PR, GO, BA, SVRS, SVC-AN e SVC-RS. Veja docs/STATUS.md.
npm install node-fiscalNode >= 22.16 (usa node:sqlite; no Node 22 ele ainda emite um aviso de recurso experimental); ESM e CommonJS, com tipos para ambos; também roda em Bun (usa bun:sqlite).
Uso
import { criarFiscal } from 'node-fiscal';
const fiscal = criarFiscal({
paths: { xml: './storage/fiscal' }, // journal SQLite padrão fica nesta raiz
certificado: {
tipo: 'A1', caminho: './certificados/empresa.pfx',
senha: () => obterSenhaDoSeuSecretManager(),
},
perfil: {
empresa: 'empresa-1', ambiente: '2', // homologação por padrão
nfse: {
provider: 'nacional', municipio: 3118601, serie: 1,
prestador: {
cnpj: 'SEU_CNPJ', inscricaoMunicipal: '',
optanteSimplesNacional: 2, regimeEspecialTributacao: 0,
},
},
},
});
try {
const resultado = await fiscal.nfse!.emitir({
dCompet: '2026-09-27',
tomador: dadosDoTomador,
servico: dadosDoServico,
}, { idempotencia: 'proposta:123:emissao' });
// Grave operacaoId no seu banco. Apenas estado === 'autorizada'
// confirma emissão. 'processando'/'resultadoDesconhecido' não confirmam.
console.log(resultado.operacaoId, resultado.estado, resultado.arquivos);
} finally { await fiscal.fechar(); }Paths e certificado são a configuração de infraestrutura. Perfil do emitente, ambiente, regime tributário e dados fiscais da operação continuam obrigatórios: não podem ser deduzidos do certificado. A biblioteca não decide enquadramento tributário ou regras comerciais.
Para NF-e configure perfil.nfe.emitente. O pacote inclui os schemas NF-e oficiais (PL_010f_v1.04, eventos, RTC, distribuição e GTIN; origem e SHA-256 em resources/schemas/nfe/manifesto.json), usados por padrão via schemasNfe(); perfil.nfe.validator permite outro SchemaValidator. A validação XSD acontece antes de qualquer transmissão e não há flag para ignorá-la. Os schemas NFS-e 1.00/1.01 estão incluídos, com origem e ajustes descritos em resources/schemas/README.md.
APIs
fiscal.nfe:emitir,consultar,consultarRecibo,statusServico,cancelar,corrigir,inutilizar,manifestar,distribuir.fiscal.nfse:emitir,substituir,cancelar,consultar,consultarEventos,consultarProtocolo,consultarParametros.consultarOperacao,listarPendencias,certificado.inspecionar,certificado.atualizar,fechar.- Subpaths:
/nfe(API compatível com ERP, XMLDSig e DANFE HTML),/nfse(builders e clients),/calculos(funções compatíveis e decimais exatos),/xml,/certificados,/catalogos,/storage.
As APIs de baixo nível preservam contratos legados: não oferecem, por si, journal, reserva de numeração ou recuperação. Use criarFiscal para essas garantias. Os cálculos compatíveis preservam o modelo tributário simplificado do ERP; não são um motor tributário universal.
Segurança e recuperação
Na API durável, a numeração é reservada antes do envio, o XML assinado é persistido e arquivado antes da rede e a chave de idempotência não pode mudar de payload. Repetir a mesma chamada devolve o resultado gravado ou consulta o protocolo/DPS. Timeout nunca provoca reenvio automático. HTTP 401/403/500 não significa DPS ausente.
Locks SQLite persistem após crash. Confirme que o worker antigo encerrou e reconcilie a operação antes de usar SqliteStateStore.desbloquearAposCrash(id). Não remova o journal para resolver erros; faça backup dele e dos XMLs. SQLite local não coordena múltiplas máquinas: nesses ambientes implemente FiscalStateStore compartilhado, transacional e equivalente.
XMLs têm nomes por hash, assinaturas recusam IDs duplicados, parsing proíbe DTD/XXE e gzip tem limite. TLS sempre valida o servidor: a confiança padrão são as raízes públicas do Node mais as raízes ICP-Brasil publicadas pelo ITI, embutidas no pacote (várias SEFAZ usam essa cadeia); ca explícito substitui ambas. Senhas/chaves privadas não são gravadas no journal. Isso não substitui validar a cadeia e a revogação do certificado do emitente, autorização do certificado para a empresa, criptografia/ACL do volume ou política de retenção; tais pontos ainda precisam ser concluídos antes de produção.
Distribuição arquiva cada XML antes de avançar NSU e respeita espera de uma hora após 137/656 ou ao atingir maxNSU. Eventos/inutilizações e Contagem sem protocolo após timeout exigem reconciliação manual; ainda não há recuperação automática completa desses casos. Faixas de inutilização ainda precisam ser coordenadas com todos os emissores antes de transmitir.
Documentação
- STATUS.md: cobertura, pendências e verificações executadas.
- NFE-IMPLEMENTACAO.md e NFSE-IMPLEMENTACAO.md: detalhes e limites por documento.
- ESTADO-E-RECUPERACAO.md: journal, backup, locks e PostgreSQL.
Desenvolvimento
npm run check verifica tipos, testes e build. npm run catalogos regenera os endpoints NF-e/NFC-e a partir das páginas oficiais; npm run catalogos:icp-brasil <dir> regenera as raízes ICP-Brasil a partir dos .crt do ITI.
A biblioteca não decide enquadramento tributário, não substitui a homologação de cada UF/município e não envia nada ao Fisco sem chamada explícita.
Licença
MIT. Schemas oficiais, schema XMLDSig do W3C e certificados da ICP-Brasil incluídos no pacote têm origem e avisos em NOTICE.md.
