@mmachadosantos/nfe-danfe-pdf 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +719 -0
- package/lib/application/helpers/generate-pdf/fontes/Times New Roman Bold Italic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/Times New Roman Bold.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/Times New Roman Italic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/Times New Roman.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Black.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-BlackItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Bold.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-BoldItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-ExtraBold.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-ExtraBoldItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-ExtraLight.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-ExtraLightItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Italic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Light.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-LightItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Medium.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-MediumItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Regular.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-SemiBold.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-SemiBoldItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-Thin.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/barlow-condensed/BarlowCondensed-ThinItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/roboto-condensed/RobotoCondensed-Bold.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/roboto-condensed/RobotoCondensed-BoldItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/roboto-condensed/RobotoCondensed-Italic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/roboto-condensed/RobotoCondensed-Light.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/roboto-condensed/RobotoCondensed-LightItalic.ttf +0 -0
- package/lib/application/helpers/generate-pdf/fontes/roboto-condensed/RobotoCondensed-Regular.ttf +0 -0
- package/lib/application/helpers/generate-pdf/nfe/campo.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/campo.js +15 -0
- package/lib/application/helpers/generate-pdf/nfe/cria-layout.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/cria-layout.js +149 -0
- package/lib/application/helpers/generate-pdf/nfe/default.d.ts +23 -0
- package/lib/application/helpers/generate-pdf/nfe/default.js +26 -0
- package/lib/application/helpers/generate-pdf/nfe/gerar-itens.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/gerar-itens.js +291 -0
- package/lib/application/helpers/generate-pdf/nfe/get-dados-adicionais.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-dados-adicionais.js +269 -0
- package/lib/application/helpers/generate-pdf/nfe/get-dados-emitente.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-dados-emitente.js +319 -0
- package/lib/application/helpers/generate-pdf/nfe/get-destinatario-remetente.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-destinatario-remetente.js +154 -0
- package/lib/application/helpers/generate-pdf/nfe/get-fatura-duplicata.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-fatura-duplicata.js +118 -0
- package/lib/application/helpers/generate-pdf/nfe/get-homologacao.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-homologacao.js +36 -0
- package/lib/application/helpers/generate-pdf/nfe/get-imposto.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-imposto.js +219 -0
- package/lib/application/helpers/generate-pdf/nfe/get-iss.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-iss.js +73 -0
- package/lib/application/helpers/generate-pdf/nfe/get-menu-itens.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-menu-itens.js +199 -0
- package/lib/application/helpers/generate-pdf/nfe/get-nota-cancelada.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-nota-cancelada.js +16 -0
- package/lib/application/helpers/generate-pdf/nfe/get-recibo.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-recibo.js +101 -0
- package/lib/application/helpers/generate-pdf/nfe/get-transporte.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/get-transporte.js +179 -0
- package/lib/application/helpers/generate-pdf/nfe/italico.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/italico.js +16 -0
- package/lib/application/helpers/generate-pdf/nfe/linha-horizontal-tracejada.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/linha-horizontal-tracejada.js +7 -0
- package/lib/application/helpers/generate-pdf/nfe/linha-horizontal.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/linha-horizontal.js +26 -0
- package/lib/application/helpers/generate-pdf/nfe/linha-vertical.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/linha-vertical.js +14 -0
- package/lib/application/helpers/generate-pdf/nfe/load-fontes.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/load-fontes.js +30 -0
- package/lib/application/helpers/generate-pdf/nfe/negrito.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/negrito.js +16 -0
- package/lib/application/helpers/generate-pdf/nfe/normal.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/normal.js +16 -0
- package/lib/application/helpers/generate-pdf/nfe/options-doc.d.ts +10 -0
- package/lib/application/helpers/generate-pdf/nfe/options-doc.js +14 -0
- package/lib/application/helpers/generate-pdf/nfe/secao.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/secao.js +16 -0
- package/lib/application/helpers/generate-pdf/nfe/titulo.d.ts +2 -0
- package/lib/application/helpers/generate-pdf/nfe/titulo.js +17 -0
- package/lib/application/helpers/xml/deserialize.d.ts +2 -0
- package/lib/application/helpers/xml/deserialize.js +24 -0
- package/lib/application/helpers/xml/index.d.ts +1 -0
- package/lib/application/helpers/xml/index.js +17 -0
- package/lib/domain/use-cases/pdf/index.d.ts +2 -0
- package/lib/domain/use-cases/pdf/index.js +25 -0
- package/lib/domain/use-cases/pdf/pdf-NFCe.d.ts +2 -0
- package/lib/domain/use-cases/pdf/pdf-NFCe.js +687 -0
- package/lib/domain/use-cases/pdf/pdf-NFe.d.ts +2 -0
- package/lib/domain/use-cases/pdf/pdf-NFe.js +54 -0
- package/lib/domain/use-cases/utils/clean-html-entities.d.ts +2 -0
- package/lib/domain/use-cases/utils/clean-html-entities.js +45 -0
- package/lib/domain/use-cases/utils/current-date.d.ts +1 -0
- package/lib/domain/use-cases/utils/current-date.js +7 -0
- package/lib/domain/use-cases/utils/format-cnpj.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-cnpj.js +8 -0
- package/lib/domain/use-cases/utils/format-cpf.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-cpf.js +8 -0
- package/lib/domain/use-cases/utils/format-date-time.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-date-time.js +10 -0
- package/lib/domain/use-cases/utils/format-date.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-date.js +9 -0
- package/lib/domain/use-cases/utils/format-key.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-key.js +6 -0
- package/lib/domain/use-cases/utils/format-number.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-number.js +6 -0
- package/lib/domain/use-cases/utils/format-phone.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-phone.js +20 -0
- package/lib/domain/use-cases/utils/format-plate.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-plate.js +16 -0
- package/lib/domain/use-cases/utils/format-postal-code.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-postal-code.js +8 -0
- package/lib/domain/use-cases/utils/format-protocol.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-protocol.js +8 -0
- package/lib/domain/use-cases/utils/format-state-registration.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-state-registration.js +152 -0
- package/lib/domain/use-cases/utils/format-time.d.ts +1 -0
- package/lib/domain/use-cases/utils/format-time.js +8 -0
- package/lib/domain/use-cases/utils/index.d.ts +15 -0
- package/lib/domain/use-cases/utils/index.js +31 -0
- package/lib/domain/use-cases/utils/return-font-size-carrier.d.ts +1 -0
- package/lib/domain/use-cases/utils/return-font-size-carrier.js +23 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +5 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types/generate-pdf.d.ts +266 -0
- package/lib/types/generate-pdf.js +2 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.js +19 -0
- package/lib/types/nfe-proc.d.ts +42 -0
- package/lib/types/nfe-proc.js +2 -0
- package/lib/types/schema.d.ts +876 -0
- package/lib/types/schema.js +2 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +6 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
# 🧾 NFe DANFE PDF
|
|
2
|
+
|
|
3
|
+
> **Biblioteca robusta e completa para geração de DANFE (NF-e e NFC-e) em PDF para aplicações Node.js**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/nfe-danfe-pdf)
|
|
6
|
+
[](https://www.typescriptlang.org)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
## 🚀 **Funcionalidades Principais**
|
|
10
|
+
|
|
11
|
+
### ✅ **Suporte Completo**
|
|
12
|
+
|
|
13
|
+
- **NF-e (Modelo 55)**: Documentos fiscais eletrônicos com layout profissional
|
|
14
|
+
- **NFC-e (Modelo 65)**: Cupom fiscal eletrônico otimizado
|
|
15
|
+
- **Conformidade 100%**: Atende às especificações técnicas da Receita Federal (MOC)
|
|
16
|
+
- **TypeScript Nativo**: Tipagem completa e IntelliSense
|
|
17
|
+
|
|
18
|
+
### 🎨 **Recursos Avançados**
|
|
19
|
+
|
|
20
|
+
- **Layout Responsivo**: Adapta-se automaticamente ao conteúdo
|
|
21
|
+
- **Quebra Inteligente de Texto**: Processa informações complementares longas
|
|
22
|
+
- **Logos Personalizadas**: Suporte a imagens em diferentes formatos
|
|
23
|
+
- **Código de Barras**: Geração automática conforme padrões oficiais
|
|
24
|
+
- **QR Code**: Para NFC-e com validação automática
|
|
25
|
+
- **Múltiplas Páginas**: Suporte a documentos com muitos itens
|
|
26
|
+
|
|
27
|
+
### 🛡️ **Qualidade e Conformidade**
|
|
28
|
+
|
|
29
|
+
- **Validação XML**: Parser robusto com tratamento de erros
|
|
30
|
+
- **Campos Obrigatórios**: Verificação automática de dados essenciais
|
|
31
|
+
- **Formatação Automática**: CNPJ, CPF, CEP, datas e valores monetários
|
|
32
|
+
- **Notas Canceladas**: Marcação visual clara para documentos cancelados
|
|
33
|
+
- **Homologação**: Marca d'água automática para ambiente de testes
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 📦 **Instalação**
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# NPM
|
|
41
|
+
npm install nfe-danfe-pdf
|
|
42
|
+
|
|
43
|
+
# Yarn
|
|
44
|
+
yarn add nfe-danfe-pdf
|
|
45
|
+
|
|
46
|
+
# PNPM
|
|
47
|
+
pnpm add nfe-danfe-pdf
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🎯 **Uso Básico**
|
|
53
|
+
|
|
54
|
+
### **Exemplo Simples**
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { gerarPDF } from 'nfe-danfe-pdf';
|
|
58
|
+
import fs from 'fs';
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
try {
|
|
62
|
+
// Carregando XML da NFe
|
|
63
|
+
const xmlContent = fs.readFileSync('./nota-fiscal.xml', 'utf8');
|
|
64
|
+
|
|
65
|
+
// Gerando PDF
|
|
66
|
+
const pdfDoc = await gerarPDF(xmlContent);
|
|
67
|
+
|
|
68
|
+
// Salvando arquivo
|
|
69
|
+
const writeStream = fs.createWriteStream('./danfe.pdf');
|
|
70
|
+
pdfDoc.pipe(writeStream);
|
|
71
|
+
|
|
72
|
+
// Aguardar finalização do arquivo
|
|
73
|
+
await new Promise<void>((resolve, reject) => {
|
|
74
|
+
writeStream.on('finish', () => {
|
|
75
|
+
console.log('PDF gerado com sucesso!');
|
|
76
|
+
resolve();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
writeStream.on('error', reject);
|
|
80
|
+
pdfDoc.on('error', reject);
|
|
81
|
+
});
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('Erro:', error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
main();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### **Exemplo Avançado**
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { gerarPDF } from 'nfe-danfe-pdf';
|
|
94
|
+
import fs from 'fs';
|
|
95
|
+
|
|
96
|
+
const xmlContent = fs.readFileSync('./nfe.xml', 'utf8');
|
|
97
|
+
|
|
98
|
+
// Opções personalizadas
|
|
99
|
+
const opcoes = {
|
|
100
|
+
pathLogo: './assets/logo-empresa.png', // Logo da empresa
|
|
101
|
+
cancelada: false, // Nota não cancelada
|
|
102
|
+
textoRodape: 'Meu Sistema Danfe' // Texto personalizado no rodapé
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const pdfDoc = await gerarPDF(xmlContent, opcoes);
|
|
106
|
+
|
|
107
|
+
// Salvando com callback
|
|
108
|
+
pdfDoc.pipe(fs.createWriteStream('./danfe-personalizado.pdf'));
|
|
109
|
+
pdfDoc.on('end', () => {
|
|
110
|
+
console.log('✅ DANFE gerado com sucesso!');
|
|
111
|
+
});
|
|
112
|
+
pdfDoc.end();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## ⚙️ **API Completa**
|
|
118
|
+
|
|
119
|
+
### **`gerarPDF(xml, opcoes?)`**
|
|
120
|
+
|
|
121
|
+
**Parâmetros:**
|
|
122
|
+
|
|
123
|
+
- **`xml`** `string`: Conteúdo XML da NF-e/NFC-e
|
|
124
|
+
- **`opcoes`** `OpcoesPDF` _(opcional)_: Configurações personalizadas
|
|
125
|
+
|
|
126
|
+
**Retorna:** `Promise<PDFKit.PDFDocument>`
|
|
127
|
+
|
|
128
|
+
### **Tipo `OpcoesPDF`**
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
type OpcoesPDF = {
|
|
132
|
+
pathLogo?: string; // Caminho para logo da empresa
|
|
133
|
+
cancelada?: boolean; // Marcar nota como cancelada
|
|
134
|
+
textoRodape?: string; // Texto personalizado no rodapé do documento
|
|
135
|
+
};
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### **Detalhes dos Parâmetros:**
|
|
139
|
+
|
|
140
|
+
- **`pathLogo`**: Caminho para arquivo de imagem da logo da empresa (PNG, JPG, etc.)
|
|
141
|
+
- **`cancelada`**: Define se a nota deve ser marcada visualmente como cancelada
|
|
142
|
+
- **`textoRodape`**: Texto personalizado que aparece no rodapé direito do documento (ex: "Meu Sistema Danfe")
|
|
143
|
+
|
|
144
|
+
#### **Exemplo com Rodapé Personalizado:**
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { gerarPDF } from 'nfe-danfe-pdf';
|
|
148
|
+
import fs from 'fs';
|
|
149
|
+
|
|
150
|
+
const xmlContent = fs.readFileSync('./nfe.xml', 'utf8');
|
|
151
|
+
|
|
152
|
+
// Opções com texto personalizado no rodapé
|
|
153
|
+
const opcoes = {
|
|
154
|
+
pathLogo: './assets/logo-empresa.png',
|
|
155
|
+
cancelada: false,
|
|
156
|
+
textoRodape: 'Meu Sistema Danfe' // Texto que aparece no canto inferior direito
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const pdfDoc = await gerarPDF(xmlContent, opcoes);
|
|
160
|
+
pdfDoc.pipe(fs.createWriteStream('./danfe-com-rodape.pdf'));
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**💡 Resultado Visual do Rodapé:**
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Impresso em 27/09/2025 às 15:30:45 Meu Sistema Danfe
|
|
167
|
+
↑ (lado esquerdo) ↑ (lado direito)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 🎨 **Recursos Visuais**
|
|
173
|
+
|
|
174
|
+
### **Layout Profissional**
|
|
175
|
+
|
|
176
|
+
- ✅ Cabeçalho com dados do emitente e logo
|
|
177
|
+
- ✅ Seções organizadas e bem delimitadas
|
|
178
|
+
- ✅ Tabela de itens com colunas alinhadas
|
|
179
|
+
- ✅ Informações fiscais destacadas
|
|
180
|
+
- ✅ Dados adicionais com altura dinâmica
|
|
181
|
+
- ✅ **Rodapé personalizado** com data/hora e texto customizável
|
|
182
|
+
|
|
183
|
+
### **Formatações Automáticas**
|
|
184
|
+
|
|
185
|
+
- 📄 **CNPJ/CPF**: `12.345.678/0001-90` | `123.456.789-00`
|
|
186
|
+
- 📅 **Datas**: `26/09/2025 15:30:45`
|
|
187
|
+
- 💰 **Valores**: `R$ 1.234,56`
|
|
188
|
+
- 📮 **CEP**: `12345-678`
|
|
189
|
+
- 🔑 **Chave NFe**: `1234 5678 9012 3456 7890 1234 5678 9012 3456 7890 1234`
|
|
190
|
+
|
|
191
|
+
### **Tratamento Inteligente**
|
|
192
|
+
|
|
193
|
+
- 📝 **Textos Longos**: Quebra automática em múltiplas linhas
|
|
194
|
+
- 🔄 **Altura Dinâmica**: Seções expandem conforme o conteúdo
|
|
195
|
+
- 🎯 **Alinhamentos**: Centro, esquerda, direita, justificado
|
|
196
|
+
- 🎨 **Fontes**: Times New Roman e Barlow Condensed incluídas
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 📋 **Campos Suportados**
|
|
201
|
+
|
|
202
|
+
### **Identificação**
|
|
203
|
+
|
|
204
|
+
- ✅ Dados do emitente (razão social, CNPJ, endereço)
|
|
205
|
+
- ✅ Destinatário/remetente completo
|
|
206
|
+
- ✅ Dados da nota (número, série, data, chave)
|
|
207
|
+
- ✅ Protocolo de autorização
|
|
208
|
+
|
|
209
|
+
### **Produtos/Serviços**
|
|
210
|
+
|
|
211
|
+
- ✅ Tabela completa de itens
|
|
212
|
+
- ✅ Código, descrição, quantidade, valor unitário
|
|
213
|
+
- ✅ Valores de ICMS, IPI, PIS, COFINS
|
|
214
|
+
- ✅ Classificação fiscal (NCM, CEST)
|
|
215
|
+
|
|
216
|
+
### **Valores e Impostos**
|
|
217
|
+
|
|
218
|
+
- ✅ Totais da nota (produtos, impostos, desconto)
|
|
219
|
+
- ✅ Tributos aproximados (Lei da Transparência)
|
|
220
|
+
- ✅ Informações de ICMS, ISS, substituição tributária
|
|
221
|
+
- ✅ Modalidades de pagamento
|
|
222
|
+
|
|
223
|
+
### **Informações Adicionais**
|
|
224
|
+
|
|
225
|
+
- ✅ Fatura e duplicatas (com vencimentos)
|
|
226
|
+
- ✅ Dados de transporte (transportadora, volumes)
|
|
227
|
+
- ✅ Informações complementares (campo livre)
|
|
228
|
+
- ✅ Informações do fisco
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 🔧 **Integração com Frameworks**
|
|
233
|
+
|
|
234
|
+
### **Express.js**
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import express from 'express';
|
|
238
|
+
import { gerarPDF } from 'nfe-danfe-pdf';
|
|
239
|
+
|
|
240
|
+
const app = express();
|
|
241
|
+
|
|
242
|
+
app.post('/gerar-danfe', async (req, res) => {
|
|
243
|
+
try {
|
|
244
|
+
const { xml, pathLogo, textoRodape } = req.body;
|
|
245
|
+
const pdfDoc = await gerarPDF(xml, { pathLogo, textoRodape });
|
|
246
|
+
|
|
247
|
+
res.setHeader('Content-Type', 'application/pdf');
|
|
248
|
+
res.setHeader('Content-Disposition', 'attachment; filename="danfe.pdf"');
|
|
249
|
+
|
|
250
|
+
pdfDoc.pipe(res);
|
|
251
|
+
pdfDoc.end();
|
|
252
|
+
} catch (error) {
|
|
253
|
+
res.status(500).json({ erro: 'Erro ao gerar DANFE' });
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### **NestJS**
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { Controller, Post, Body, Res, HttpStatus } from '@nestjs/common';
|
|
262
|
+
import { Response } from 'express';
|
|
263
|
+
import { gerarPDF } from 'nfe-danfe-pdf';
|
|
264
|
+
|
|
265
|
+
@Controller('danfe')
|
|
266
|
+
export class DanfeController {
|
|
267
|
+
@Post('gerar')
|
|
268
|
+
async gerarDanfe(
|
|
269
|
+
@Body('xml') xml: string,
|
|
270
|
+
@Body('pathLogo') pathLogo?: string,
|
|
271
|
+
@Body('textoRodape') textoRodape?: string,
|
|
272
|
+
@Res() res: Response
|
|
273
|
+
) {
|
|
274
|
+
try {
|
|
275
|
+
const pdfDoc = await gerarPDF(xml, { pathLogo, textoRodape });
|
|
276
|
+
|
|
277
|
+
res.setHeader('Content-Type', 'application/pdf');
|
|
278
|
+
pdfDoc.pipe(res);
|
|
279
|
+
pdfDoc.end();
|
|
280
|
+
} catch (error) {
|
|
281
|
+
res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Erro ao gerar DANFE' });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 🌐 **Implementação em Projetos Front-end**
|
|
290
|
+
|
|
291
|
+
### **React + TypeScript**
|
|
292
|
+
|
|
293
|
+
Para usar em projetos React, você precisa de um endpoint backend que gere o PDF:
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import React, { useState } from 'react';
|
|
297
|
+
import axios from 'axios';
|
|
298
|
+
|
|
299
|
+
interface DanfeGeneratorProps {
|
|
300
|
+
xmlContent: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const DanfeGenerator: React.FC<DanfeGeneratorProps> = ({ xmlContent }) => {
|
|
304
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
305
|
+
|
|
306
|
+
const gerarDanfe = async () => {
|
|
307
|
+
setIsGenerating(true);
|
|
308
|
+
try {
|
|
309
|
+
const response = await axios.post(
|
|
310
|
+
'/api/gerar-danfe',
|
|
311
|
+
{
|
|
312
|
+
xml: xmlContent,
|
|
313
|
+
pathLogo: '/assets/logo.png',
|
|
314
|
+
textoRodape: 'Meu Sistema Danfe'
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
responseType: 'blob' // Importante para receber PDF
|
|
318
|
+
}
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
// Criar URL do blob e fazer download
|
|
322
|
+
const blob = new Blob([response.data], { type: 'application/pdf' });
|
|
323
|
+
const url = window.URL.createObjectURL(blob);
|
|
324
|
+
|
|
325
|
+
// Criar link de download
|
|
326
|
+
const link = document.createElement('a');
|
|
327
|
+
link.href = url;
|
|
328
|
+
link.download = 'danfe.pdf';
|
|
329
|
+
document.body.appendChild(link);
|
|
330
|
+
link.click();
|
|
331
|
+
|
|
332
|
+
// Cleanup
|
|
333
|
+
document.body.removeChild(link);
|
|
334
|
+
window.URL.revokeObjectURL(url);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.error('Erro ao gerar DANFE:', error);
|
|
337
|
+
alert('Erro ao gerar DANFE');
|
|
338
|
+
} finally {
|
|
339
|
+
setIsGenerating(false);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
return (
|
|
344
|
+
<button
|
|
345
|
+
onClick={gerarDanfe}
|
|
346
|
+
disabled={isGenerating}
|
|
347
|
+
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-50"
|
|
348
|
+
>
|
|
349
|
+
{isGenerating ? 'Gerando...' : 'Gerar DANFE'}
|
|
350
|
+
</button>
|
|
351
|
+
);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
export default DanfeGenerator;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### **Vue.js + TypeScript**
|
|
358
|
+
|
|
359
|
+
```vue
|
|
360
|
+
<template>
|
|
361
|
+
<div>
|
|
362
|
+
<button
|
|
363
|
+
@click="gerarDanfe"
|
|
364
|
+
:disabled="isGenerating"
|
|
365
|
+
class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 disabled:opacity-50"
|
|
366
|
+
>
|
|
367
|
+
{{ isGenerating ? 'Gerando...' : 'Gerar DANFE' }}
|
|
368
|
+
</button>
|
|
369
|
+
</div>
|
|
370
|
+
</template>
|
|
371
|
+
|
|
372
|
+
<script setup lang="ts">
|
|
373
|
+
import { ref } from 'vue';
|
|
374
|
+
import axios from 'axios';
|
|
375
|
+
|
|
376
|
+
interface Props {
|
|
377
|
+
xmlContent: string;
|
|
378
|
+
logoPath?: string;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const props = defineProps<Props>();
|
|
382
|
+
const isGenerating = ref(false);
|
|
383
|
+
|
|
384
|
+
const gerarDanfe = async () => {
|
|
385
|
+
isGenerating.value = true;
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
const response = await axios.post(
|
|
389
|
+
'/api/gerar-danfe',
|
|
390
|
+
{
|
|
391
|
+
xml: props.xmlContent,
|
|
392
|
+
pathLogo: props.logoPath
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
responseType: 'blob'
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
// Download do PDF
|
|
400
|
+
const blob = new Blob([response.data], { type: 'application/pdf' });
|
|
401
|
+
const url = URL.createObjectURL(blob);
|
|
402
|
+
|
|
403
|
+
const link = document.createElement('a');
|
|
404
|
+
link.href = url;
|
|
405
|
+
link.download = 'danfe.pdf';
|
|
406
|
+
link.click();
|
|
407
|
+
|
|
408
|
+
URL.revokeObjectURL(url);
|
|
409
|
+
} catch (error) {
|
|
410
|
+
console.error('Erro ao gerar DANFE:', error);
|
|
411
|
+
} finally {
|
|
412
|
+
isGenerating.value = false;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
</script>
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### **Angular + TypeScript**
|
|
419
|
+
|
|
420
|
+
**Serviço (danfe.service.ts):**
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
import { Injectable } from '@angular/core';
|
|
424
|
+
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
425
|
+
import { Observable } from 'rxjs';
|
|
426
|
+
|
|
427
|
+
@Injectable({
|
|
428
|
+
providedIn: 'root'
|
|
429
|
+
})
|
|
430
|
+
export class DanfeService {
|
|
431
|
+
constructor(private http: HttpClient) {}
|
|
432
|
+
|
|
433
|
+
gerarDanfe(xmlContent: string, logoPath?: string): Observable<Blob> {
|
|
434
|
+
const headers = new HttpHeaders({
|
|
435
|
+
'Content-Type': 'application/json'
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
return this.http.post(
|
|
439
|
+
'/api/gerar-danfe',
|
|
440
|
+
{
|
|
441
|
+
xml: xmlContent,
|
|
442
|
+
pathLogo: logoPath
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
headers,
|
|
446
|
+
responseType: 'blob'
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
downloadPdf(blob: Blob, filename: string = 'danfe.pdf'): void {
|
|
452
|
+
const url = window.URL.createObjectURL(blob);
|
|
453
|
+
const link = document.createElement('a');
|
|
454
|
+
link.href = url;
|
|
455
|
+
link.download = filename;
|
|
456
|
+
document.body.appendChild(link);
|
|
457
|
+
link.click();
|
|
458
|
+
document.body.removeChild(link);
|
|
459
|
+
window.URL.revokeObjectURL(url);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Componente (danfe.component.ts):**
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
import { Component } from '@angular/core';
|
|
468
|
+
import { DanfeService } from './danfe.service';
|
|
469
|
+
|
|
470
|
+
@Component({
|
|
471
|
+
selector: 'app-danfe',
|
|
472
|
+
template: `
|
|
473
|
+
<button
|
|
474
|
+
(click)="gerarDanfe()"
|
|
475
|
+
[disabled]="isGenerating"
|
|
476
|
+
class="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 disabled:opacity-50"
|
|
477
|
+
>
|
|
478
|
+
{{ isGenerating ? 'Gerando...' : 'Gerar DANFE' }}
|
|
479
|
+
</button>
|
|
480
|
+
`
|
|
481
|
+
})
|
|
482
|
+
export class DanfeComponent {
|
|
483
|
+
isGenerating = false;
|
|
484
|
+
|
|
485
|
+
constructor(private danfeService: DanfeService) {}
|
|
486
|
+
|
|
487
|
+
gerarDanfe(): void {
|
|
488
|
+
this.isGenerating = true;
|
|
489
|
+
|
|
490
|
+
this.danfeService.gerarDanfe(this.xmlContent).subscribe({
|
|
491
|
+
next: (blob) => {
|
|
492
|
+
this.danfeService.downloadPdf(blob);
|
|
493
|
+
this.isGenerating = false;
|
|
494
|
+
},
|
|
495
|
+
error: (error) => {
|
|
496
|
+
console.error('Erro ao gerar DANFE:', error);
|
|
497
|
+
this.isGenerating = false;
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Propriedade que deve ser definida com o XML
|
|
503
|
+
xmlContent = ''; // Seu XML aqui
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### **Next.js (App Router)**
|
|
508
|
+
|
|
509
|
+
**API Route (app/api/gerar-danfe/route.ts):**
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
import { gerarPDF } from 'nfe-danfe-pdf';
|
|
513
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
514
|
+
|
|
515
|
+
export async function POST(request: NextRequest) {
|
|
516
|
+
try {
|
|
517
|
+
const { xml, pathLogo } = await request.json();
|
|
518
|
+
|
|
519
|
+
const pdfDoc = await gerarPDF(xml, { pathLogo });
|
|
520
|
+
|
|
521
|
+
// Converter PDFKit document para Buffer
|
|
522
|
+
const chunks: Buffer[] = [];
|
|
523
|
+
|
|
524
|
+
return new Promise((resolve) => {
|
|
525
|
+
pdfDoc.on('data', (chunk) => chunks.push(chunk));
|
|
526
|
+
pdfDoc.on('end', () => {
|
|
527
|
+
const pdfBuffer = Buffer.concat(chunks);
|
|
528
|
+
|
|
529
|
+
resolve(
|
|
530
|
+
new NextResponse(pdfBuffer, {
|
|
531
|
+
status: 200,
|
|
532
|
+
headers: {
|
|
533
|
+
'Content-Type': 'application/pdf',
|
|
534
|
+
'Content-Disposition': 'attachment; filename="danfe.pdf"'
|
|
535
|
+
}
|
|
536
|
+
})
|
|
537
|
+
);
|
|
538
|
+
});
|
|
539
|
+
pdfDoc.end();
|
|
540
|
+
});
|
|
541
|
+
} catch (error) {
|
|
542
|
+
return NextResponse.json({ error: 'Erro ao gerar DANFE' }, { status: 500 });
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
**Cliente (components/DanfeButton.tsx):**
|
|
548
|
+
|
|
549
|
+
```tsx
|
|
550
|
+
'use client';
|
|
551
|
+
|
|
552
|
+
import { useState } from 'react';
|
|
553
|
+
|
|
554
|
+
interface DanfeButtonProps {
|
|
555
|
+
xmlContent: string;
|
|
556
|
+
logoPath?: string;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export default function DanfeButton({ xmlContent, logoPath }: DanfeButtonProps) {
|
|
560
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
561
|
+
|
|
562
|
+
const handleDownload = async () => {
|
|
563
|
+
setIsGenerating(true);
|
|
564
|
+
|
|
565
|
+
try {
|
|
566
|
+
const response = await fetch('/api/gerar-danfe', {
|
|
567
|
+
method: 'POST',
|
|
568
|
+
headers: {
|
|
569
|
+
'Content-Type': 'application/json'
|
|
570
|
+
},
|
|
571
|
+
body: JSON.stringify({
|
|
572
|
+
xml: xmlContent,
|
|
573
|
+
pathLogo: logoPath,
|
|
574
|
+
textoRodape: 'Meu Sistema Danfe'
|
|
575
|
+
})
|
|
576
|
+
});
|
|
577
|
+
if (!response.ok) {
|
|
578
|
+
throw new Error('Erro ao gerar DANFE');
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const blob = await response.blob();
|
|
582
|
+
const url = URL.createObjectURL(blob);
|
|
583
|
+
|
|
584
|
+
const link = document.createElement('a');
|
|
585
|
+
link.href = url;
|
|
586
|
+
link.download = 'danfe.pdf';
|
|
587
|
+
link.click();
|
|
588
|
+
|
|
589
|
+
URL.revokeObjectURL(url);
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.error('Erro:', error);
|
|
592
|
+
alert('Erro ao gerar DANFE');
|
|
593
|
+
} finally {
|
|
594
|
+
setIsGenerating(false);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
return (
|
|
599
|
+
<button
|
|
600
|
+
onClick={handleDownload}
|
|
601
|
+
disabled={isGenerating}
|
|
602
|
+
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50"
|
|
603
|
+
>
|
|
604
|
+
{isGenerating ? 'Gerando DANFE...' : 'Download DANFE'}
|
|
605
|
+
</button>
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### **🔑 Pontos Importantes para Front-end**
|
|
611
|
+
|
|
612
|
+
#### **Segurança**
|
|
613
|
+
|
|
614
|
+
- ⚠️ **Nunca processe XMLs no cliente**: Sempre use um backend
|
|
615
|
+
- 🔐 **Validação**: Valide XMLs no servidor antes do processamento
|
|
616
|
+
- 🛡️ **Autenticação**: Proteja endpoints de geração de PDF
|
|
617
|
+
|
|
618
|
+
#### **UX/UI**
|
|
619
|
+
|
|
620
|
+
- ⏳ **Loading States**: Sempre mostre feedback durante geração
|
|
621
|
+
- 📱 **Responsivo**: Considere diferentes dispositivos
|
|
622
|
+
- 💾 **Download Automático**: Use `Content-Disposition: attachment`
|
|
623
|
+
- ❌ **Tratamento de Erros**: Exiba mensagens claras ao usuário
|
|
624
|
+
|
|
625
|
+
#### **Performance**
|
|
626
|
+
|
|
627
|
+
- 🚀 **Cache**: Considere cache de PDFs gerados recentemente
|
|
628
|
+
- 📊 **Limite**: Implemente rate limiting nos endpoints
|
|
629
|
+
- 🔄 **Timeout**: Configure timeouts adequados para requisições
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## 🧪 **Requisitos e Compatibilidade**
|
|
634
|
+
|
|
635
|
+
### **Node.js**
|
|
636
|
+
|
|
637
|
+
- ✅ **Versão Mínima**: Node.js 14+
|
|
638
|
+
- ✅ **Recomendado**: Node.js 18+ LTS
|
|
639
|
+
- ✅ **TypeScript**: 4.0+
|
|
640
|
+
|
|
641
|
+
### **Formatos XML Suportados**
|
|
642
|
+
|
|
643
|
+
- ✅ **NFe Processada**: `<nfeProc>` (com protocolo)
|
|
644
|
+
- ✅ **NFCe Processada**: `<nfceProc>` (com protocolo)
|
|
645
|
+
- ✅ **Encoding**: UTF-8, ISO-8859-1
|
|
646
|
+
- ✅ **Versões**: Layout 4.00 (atual)
|
|
647
|
+
|
|
648
|
+
### **Dependências Principais**
|
|
649
|
+
|
|
650
|
+
- **PDFKit**: Geração de PDF de alta qualidade
|
|
651
|
+
- **xml2js**: Parser XML robusto
|
|
652
|
+
- **date-fns**: Manipulação de datas
|
|
653
|
+
- **qrcode**: Geração de QR codes
|
|
654
|
+
- **bwip-js**: Códigos de barras
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## 📊 **Performance**
|
|
659
|
+
|
|
660
|
+
- ⚡ **Velocidade**: ~500ms para NFe média (20 itens)
|
|
661
|
+
- 💾 **Memória**: ~10MB para documentos complexos
|
|
662
|
+
- 📄 **Tamanho**: PDFs otimizados (~50KB-200KB)
|
|
663
|
+
- 🔄 **Concorrência**: Suporte a múltiplas instâncias simultâneas
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
667
|
+
## 🛠️ **Desenvolvimento**
|
|
668
|
+
|
|
669
|
+
### **Scripts Disponíveis**
|
|
670
|
+
|
|
671
|
+
```bash
|
|
672
|
+
npm run build # Compilar TypeScript
|
|
673
|
+
npm run test # Executar testes
|
|
674
|
+
npm run prettier # Formatar código
|
|
675
|
+
npm run type # Verificar tipos
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
### **Estrutura do Projeto**
|
|
679
|
+
|
|
680
|
+
```
|
|
681
|
+
src/
|
|
682
|
+
├── domain/ # Lógica de negócio
|
|
683
|
+
├── application/ # Casos de uso
|
|
684
|
+
├── types/ # Definições TypeScript
|
|
685
|
+
└── utils/ # Utilitários
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## 📄 **Licença**
|
|
691
|
+
|
|
692
|
+
Este projeto está licenciado sob a **MIT License** - veja o arquivo [LICENSE](LICENSE) para detalhes.
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## 🤝 **Contribuição**
|
|
697
|
+
|
|
698
|
+
Contribuições são bem-vindas! Por favor:
|
|
699
|
+
|
|
700
|
+
1. Faça um fork do projeto
|
|
701
|
+
2. Crie sua feature branch (`git checkout -b feature/nova-funcionalidade`)
|
|
702
|
+
3. Commit suas mudanças (`git commit -am 'Adiciona nova funcionalidade'`)
|
|
703
|
+
4. Push para a branch (`git push origin feature/nova-funcionalidade`)
|
|
704
|
+
5. Abra um Pull Request
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## 📞 **Suporte**
|
|
709
|
+
|
|
710
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/flaviosoliver/nfe-danfe-pdf/issues)
|
|
711
|
+
- 📧 **Email**: [flavsoliver@gmail.com](mailto:flavsoliver@gmail.com)
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
<div align="center">
|
|
716
|
+
|
|
717
|
+
**⭐ Se este projeto te ajudou, considere dar uma estrela no repositório! ⭐**
|
|
718
|
+
|
|
719
|
+
</div>
|
|
Binary file
|
|
Binary file
|