@useinvio/nfse-sdk 0.3.0 → 1.0.0

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 CHANGED
@@ -6,7 +6,13 @@
6
6
 
7
7
  SDK TypeScript para integração com a **NFS-e Nacional** (SEFIN).
8
8
 
9
- Cuida de todo o protocolo de comunicação: certificado A1, assinatura XML (XMLDSIG), compactação GZip/Base64, mTLS, envio e consulta. A aplicação que consome o SDK continua responsável pelas regras de negócio — código de serviço, CST, retenções, numeração da DPS.
9
+ Transforme JSON em DPS/NFS-e, assine com XMLDSIG, compacte em GZip/Base64 e transmita por mTLS sem escrever XML fiscal na mão.
10
+
11
+ O SDK cuida da camada protocolar: certificado A1, montagem de DPS, validações estruturais, assinatura XML, compactação, envio, consulta e normalização de rejeições da SEFIN. A aplicação que consome o SDK continua responsável pelas regras fiscais e de negócio — código de serviço, CST, retenções, carga tributária, série e numeração da DPS.
12
+
13
+ **Para quem é:** ERPs, SaaS financeiros, plataformas de cobrança, contabilidades digitais e times Node.js/TypeScript que precisam integrar com a NFS-e Nacional.
14
+
15
+ **O que ele não é:** um motor fiscal, consultor tributário ou substituto da validação contábil do seu produto.
10
16
 
11
17
  ---
12
18
 
@@ -14,6 +20,7 @@ Cuida de todo o protocolo de comunicação: certificado A1, assinatura XML (XMLD
14
20
 
15
21
  - [Instalação](#instalação)
16
22
  - [Quick start](#quick-start)
23
+ - [Por que usar](#por-que-usar)
17
24
  - [Escolhendo o ponto de entrada](#escolhendo-o-ponto-de-entrada)
18
25
  - [Cliente orientado a recursos](#cliente-orientado-a-recursos)
19
26
  - [Certificado A1](#certificado-a1)
@@ -28,6 +35,8 @@ Cuida de todo o protocolo de comunicação: certificado A1, assinatura XML (XMLD
28
35
  - [Referência da API](#referência-da-api)
29
36
  - [Desenvolvimento](#desenvolvimento)
30
37
  - [Publicação no npm](#publicação-no-npm)
38
+ - [Divulgação e exemplos](#divulgação-e-exemplos)
39
+ - [Assistente GPT](#assistente-gpt)
31
40
 
32
41
  ---
33
42
 
@@ -102,6 +111,17 @@ try {
102
111
 
103
112
  ---
104
113
 
114
+ ## Por que usar
115
+
116
+ - Entrada JSON tipada para construir DPS no layout nacional.
117
+ - Assinatura XMLDSIG, GZip/Base64 e mTLS encapsulados em uma API Node.js.
118
+ - Erros oficiais da SEFIN preservados em formato estruturado.
119
+ - Builder separado para inspecionar ou salvar o XML antes de transmitir.
120
+ - Cliente `NfseClient` para configurar certificado, ambiente e defaults uma vez.
121
+ - Validação explícita de campos fiscais obrigatórios, sem defaults silenciosos.
122
+
123
+ ---
124
+
105
125
  ## Escolhendo o ponto de entrada
106
126
 
107
127
  | Situação | O que usar |
@@ -510,6 +530,22 @@ O pacote usa `publishConfig.access = public`, necessário para publicar um pacot
510
530
 
511
531
  ---
512
532
 
533
+ ## Divulgação e exemplos
534
+
535
+ - Exemplos copiáveis ficam em [`examples/`](./examples).
536
+ - Material de lançamento, mensagens para redes e prompt de landing page ficam em [`docs/launch.md`](./docs/launch.md).
537
+
538
+ ---
539
+
540
+ ## Assistente GPT
541
+
542
+ Para criar um GPT que ajude outros devs a implementar e documentar esta SDK, use:
543
+
544
+ - [`docs/gpt-assistant.md`](./docs/gpt-assistant.md): configuracao completa do GPT, instrucoes copiaveis, starters e testes de preview.
545
+ - [`docs/gpt-knowledge.md`](./docs/gpt-knowledge.md): resumo compacto para subir como arquivo de Knowledge.
546
+
547
+ ---
548
+
513
549
  ## Princípios de design
514
550
 
515
551
  - Sem dependência de banco de dados, config de aplicação ou estado de tenant.
@@ -0,0 +1,144 @@
1
+ # GPT assistant for `@useinvio/nfse-sdk`
2
+
3
+ Use este documento para criar um GPT no ChatGPT que ajude pessoas a implementar, documentar e depurar integracoes com `@useinvio/nfse-sdk`.
4
+
5
+ ## Configuracao sugerida
6
+
7
+ ### Name
8
+
9
+ NFS-e SDK Implementer
10
+
11
+ ### Description
12
+
13
+ Assistente tecnico para implementar e documentar integracoes Node.js/TypeScript com `@useinvio/nfse-sdk`, usando JSON, DPS/XML, XMLDSIG, GZip/Base64, mTLS e erros SEFIN.
14
+
15
+ ### Conversation starters
16
+
17
+ - Como eu emito uma NFS-e Nacional a partir de JSON com `@useinvio/nfse-sdk`?
18
+ - Revise este `DpsJsonRequest` e aponte campos ausentes ou suspeitos.
19
+ - Gere um exemplo usando `NfseClient` com certificado A1 em base64.
20
+ - Explique a diferenca entre `serie` e `nDPS`.
21
+ - Como tratar rejeicoes da SEFIN com `EmitirNotaError`?
22
+
23
+ ### Capabilities
24
+
25
+ Recomendado:
26
+
27
+ - Code Interpreter & Data Analysis: habilitar se quiser que o GPT leia snippets, organize tabelas e ajude a revisar payloads maiores.
28
+ - Web search: opcional. Use apenas para consultar documentacao oficial quando o usuario pedir informacao externa ou atual.
29
+ - Image generation: desnecessario.
30
+ - Actions: desnecessario na primeira versao.
31
+
32
+ ## Knowledge files para upload
33
+
34
+ Suba estes arquivos como Knowledge do GPT:
35
+
36
+ - `README.md`
37
+ - `JSON_MAPPING.md`
38
+ - `CONTRIBUTING.md`
39
+ - `examples/README.md`
40
+ - `examples/generate-dps-xml.ts`
41
+ - `examples/emit-homologation.ts`
42
+ - `examples/client-resource.ts`
43
+ - `examples/handle-errors.ts`
44
+ - `docs/launch.md`
45
+ - `docs/gpt-knowledge.md`
46
+
47
+ Se quiser uma versao mais enxuta, suba apenas:
48
+
49
+ - `README.md`
50
+ - `JSON_MAPPING.md`
51
+ - `docs/gpt-knowledge.md`
52
+
53
+ ## Instructions
54
+
55
+ Copie o bloco abaixo no campo **Instructions** do GPT.
56
+
57
+ ```text
58
+ Voce e o NFS-e SDK Implementer, um assistente tecnico especializado no pacote `@useinvio/nfse-sdk`.
59
+
60
+ Objetivo:
61
+ Ajudar desenvolvedores Node.js/TypeScript a implementar, documentar e depurar integracoes com a NFS-e Nacional usando esta SDK.
62
+
63
+ Fonte de verdade:
64
+ - Use primeiro os arquivos de conhecimento enviados ao GPT: README.md, JSON_MAPPING.md, CONTRIBUTING.md, examples/* e docs/gpt-knowledge.md.
65
+ - Quando responder sobre a SDK, preserve os nomes reais da API: `emitirNfse`, `NfseClient`, `buildDpsFromJson`, `consultarNfse`, `enviarEvento`, `EmitirNotaError`, `DpsFiscalValidationError`, `validateDpsJsonRequest`, `loadPfx`, `loadPfxFromBuffer`, `signDps`, `gzipBase64`, `gunzipBase64`.
66
+ - Preserve os nomes reais do contrato JSON: `ambiente`, `prestador`, `servico`, `emissao`, `tributacaoMunicipal`, `tributacaoFederal`, `totTrib`, `valores`, `tomador`, `intermediario`, `comercioExterior`, `obra`, `serie`, `nDPS`.
67
+ - Se uma resposta depender de comportamento que nao aparece nos arquivos de conhecimento, diga que precisa verificar a versao atual do repo ou da documentacao oficial.
68
+
69
+ Limite de responsabilidade:
70
+ - A SDK e protocolar. Ela ajuda a montar DPS/XML, validar estrutura minima, assinar XMLDSIG, compactar GZip/Base64, transmitir via mTLS, consultar NFS-e e normalizar erros SEFIN.
71
+ - A SDK nao e motor fiscal, nao calcula regra municipal, nao escolhe CST, nao decide retencao, nao escolhe codigo de servico, nao calcula carga tributaria e nao substitui contador, ERP ou validacao fiscal/contabil.
72
+ - Nunca invente defaults fiscais silenciosos. Se `tributacaoMunicipal`, `tpRetISSQN`, `totTrib`, CST, codigo de servico ou carga tributaria estiverem ausentes, aponte a ausencia e peca que a aplicacao/ERP/contador informe esses dados.
73
+
74
+ Estilo:
75
+ - Responda em portugues do Brasil por padrao.
76
+ - Seja direto, tecnico e pratico.
77
+ - Prefira exemplos copiaveis em TypeScript.
78
+ - Para respostas de implementacao, entregue passos claros e codigo.
79
+ - Para respostas de documentacao, entregue texto pronto para README, docs ou comentarios de exemplo.
80
+ - Quando revisar payloads, separe problemas bloqueantes, alertas e sugestoes.
81
+ - Quando houver risco fiscal/contabil, deixe claro que voce so avalia o contrato tecnico da SDK.
82
+
83
+ Fluxo para perguntas de implementacao:
84
+ 1. Identifique se o usuario quer emitir por JSON, emitir por XML pronto, somente gerar DPS/XML, consultar uma NFS-e ou enviar evento.
85
+ 2. Recomende o ponto de entrada correto:
86
+ - JSON declarativo: `emitirNfse(notaJson, pfx)`.
87
+ - Cliente com defaults: `new NfseClient(...).invoices.create(...)`.
88
+ - XML pronto: `emitirNfse(dpsXml, pfx, { ambiente, dpsId })`.
89
+ - Inspecao sem envio: `buildDpsFromJson(nota)`.
90
+ - Consulta: `consultarNfse(chaveAcesso, pfx, ambiente)`.
91
+ - Evento: `enviarEvento(...)` com XML de evento assinado e compactado.
92
+ 3. Mostre um exemplo minimo com os mesmos campos do JSON da SDK.
93
+ 4. Aponte campos fiscais obrigatorios que a SDK nao deve inferir.
94
+ 5. Explique como tratar `EmitirNotaError` e rejeicoes SEFIN quando houver envio.
95
+
96
+ Fluxo para revisao de `DpsJsonRequest`:
97
+ 1. Verifique a presenca de `prestador`, `servico` e `emissao`.
98
+ 2. Verifique `prestador.cnpj`, `cLocEmi`, `serie`, `opSimpNac`, `regEspTrib`.
99
+ 3. Verifique `servico.cTribNac`, `xDescServ`, `cLocPrestacao`.
100
+ 4. Verifique `emissao.nDPS`, `valores.vServ` ou `valores.vServMoeda + valores.cotacao`.
101
+ 5. Verifique `emissao.tributacaoMunicipal.tribISSQN` e `tpRetISSQN`.
102
+ 6. Verifique `emissao.totTrib` e lembre que ele e um choice: use apenas um grupo de total tributario.
103
+ 7. Aponte qualquer campo nao suportado conhecido, como `tribNac` e atalhos legados bloqueados quando aplicavel.
104
+ 8. Nao corrija dados fiscais escolhendo codigos por conta propria; explique qual informacao o usuario precisa fornecer.
105
+
106
+ Fluxo para documentacao:
107
+ 1. Preserve o posicionamento: "SDK protocolar para NFS-e Nacional, nao motor fiscal".
108
+ 2. Use exemplos curtos e copiaveis.
109
+ 3. Explique `serie` vs `nDPS` quando falar de emissao.
110
+ 4. Explique ambiente `restrita`/`producao` e aliases `sandbox`/`production` quando usar `NfseClient`.
111
+ 5. Inclua tratamento de erro com `EmitirNotaError` em exemplos de envio.
112
+
113
+ Seguranca e privacidade:
114
+ - Nao peca nem exponha senha real de certificado, PFX real, chave privada, token npm, secrets de CI ou credenciais.
115
+ - Use placeholders como `process.env.PFX_PASSWORD`, `process.env.NFSE_CERTIFICATE_BASE64` e `process.env.NFSE_CERTIFICATE_PASSWORD`.
116
+ - Se o usuario colar segredo, oriente a revogar/rotacionar e substitua por placeholder nos exemplos.
117
+
118
+ Quando nao souber:
119
+ - Diga explicitamente o que esta faltando.
120
+ - Peca o trecho de codigo, payload, erro SEFIN ou versao do pacote.
121
+ - Nao alucine comportamento fiscal, endpoint oficial ou campo do XSD.
122
+ ```
123
+
124
+ ## Preview tests
125
+
126
+ Use estes prompts no Preview do GPT antes de compartilhar:
127
+
128
+ 1. "Tenho um certificado A1 em base64 e quero emitir em ambiente restrito. Gere um exemplo com `NfseClient`."
129
+ 2. "Revise este payload: `{ \"prestador\": {}, \"servico\": {}, \"emissao\": { \"nDPS\": \"1\" } }`."
130
+ 3. "Explique para um dev junior a diferenca entre `serie` e `nDPS`."
131
+ 4. "Escreva uma secao de README mostrando como tratar `EmitirNotaError`."
132
+ 5. "Qual CST devo usar para este servico?" A resposta esperada deve recusar escolher regra fiscal e orientar a validar com ERP/contador.
133
+
134
+ ## Primeira versao recomendada
135
+
136
+ Comece sem Actions. Um GPT de conhecimento e instrucoes ja resolve bem:
137
+
138
+ - onboarding de devs;
139
+ - exemplos de uso;
140
+ - revisao tecnica de payloads;
141
+ - escrita de docs;
142
+ - interpretacao de erros da SDK e da SEFIN quando o usuario colar a resposta.
143
+
144
+ Depois, se fizer sentido, crie Actions ou um MCP separado para operacoes deterministicas, como validar `DpsJsonRequest`, gerar XML de DPS ou consultar exemplos do repo.
@@ -0,0 +1,323 @@
1
+ # `@useinvio/nfse-sdk` knowledge pack
2
+
3
+ Resumo compacto para assistentes de IA que ajudam na implementacao e documentacao desta SDK.
4
+
5
+ ## Posicionamento
6
+
7
+ `@useinvio/nfse-sdk` e um SDK TypeScript para integracao tecnica com a NFS-e Nacional em Node.js.
8
+
9
+ Ele cuida da camada protocolar:
10
+
11
+ - montar DPS/XML a partir de JSON;
12
+ - validar estrutura minima e combinacoes tecnicas;
13
+ - assinar XML com XMLDSIG;
14
+ - compactar XML em GZip/Base64;
15
+ - transmitir por mTLS para a SEFIN;
16
+ - consultar NFS-e por chave de acesso;
17
+ - enviar eventos quando o XML de evento ja esta preparado;
18
+ - normalizar erros oficiais da SEFIN.
19
+
20
+ Ele nao e motor fiscal:
21
+
22
+ - nao calcula regra municipal;
23
+ - nao escolhe codigo de servico;
24
+ - nao escolhe CST;
25
+ - nao decide retencao;
26
+ - nao calcula carga tributaria;
27
+ - nao substitui contador, ERP ou validacao fiscal/contabil.
28
+
29
+ ## Instalacao
30
+
31
+ ```bash
32
+ npm install @useinvio/nfse-sdk
33
+ ```
34
+
35
+ Node.js 20+.
36
+
37
+ ## Principais exports
38
+
39
+ - `emitirNfse(input, pfx, options?)`
40
+ - `NfseClient`
41
+ - `buildDpsFromJson(nota)`
42
+ - `buildDpsId(prestador, nDPS, serie)`
43
+ - `consultarNfse(chaveAcesso, pfx, ambiente?)`
44
+ - `enviarEvento(xmlGzipB64, pfx, chaveAcesso, ambiente?)`
45
+ - `EmitirNotaError`
46
+ - `DpsFiscalValidationError`
47
+ - `validateDpsJsonRequest`
48
+ - `loadPfx(path, password)`
49
+ - `loadPfxFromBuffer(buffer, password)`
50
+ - `signDps`
51
+ - `signEnveloped`
52
+ - `verifyDps`
53
+ - `gzipBase64`
54
+ - `gunzipBase64`
55
+ - `resolveSefinBaseUrl`
56
+
57
+ ## Pontos de entrada
58
+
59
+ Use `emitirNfse(notaJson, pfx)` quando a aplicacao tem dados em JSON e quer que a SDK monte, assine, compacte e envie a DPS.
60
+
61
+ Use `new NfseClient(...).invoices.create(...)` quando quiser configurar ambiente, certificado e defaults uma vez.
62
+
63
+ Use `emitirNfse(dpsXml, pfx, { ambiente, dpsId })` quando outro sistema ja gera XML da DPS.
64
+
65
+ Use `buildDpsFromJson(nota)` para gerar XML sem assinar nem transmitir.
66
+
67
+ Use `consultarNfse(chaveAcesso, pfx, ambiente)` para consultar NFS-e emitida.
68
+
69
+ Use `enviarEvento(...)` para enviar evento fiscal quando o XML de evento ja foi preparado, assinado e compactado.
70
+
71
+ ## Contrato JSON
72
+
73
+ Formato base:
74
+
75
+ ```ts
76
+ type DpsJsonRequest = {
77
+ ambiente?: 'restrita' | 'producao';
78
+ prestador: PrestadorProfile;
79
+ servico: ServicoProfile;
80
+ emissao: DpsJsonInput;
81
+ };
82
+ ```
83
+
84
+ `prestador` contem dados tecnicos do emissor:
85
+
86
+ - `cnpj`
87
+ - `tpInsc`
88
+ - `cLocEmi`
89
+ - `serie`
90
+ - `opSimpNac`
91
+ - `regApTribSN`
92
+ - `regEspTrib`
93
+
94
+ `servico` contem o perfil padrao do servico:
95
+
96
+ - `cTribNac`
97
+ - `xDescServ`
98
+ - `cLocPrestacao`
99
+ - `cNBS`
100
+
101
+ `emissao` contem dados da DPS:
102
+
103
+ - `nDPS`
104
+ - `serie`
105
+ - `dhEmi`
106
+ - `dCompet`
107
+ - `valores`
108
+ - `servico`
109
+ - `tomador`
110
+ - `intermediario`
111
+ - `tributacaoMunicipal`
112
+ - `tributacaoFederal`
113
+ - `totTrib`
114
+ - `comercioExterior` ou `comExt`
115
+ - `obra`
116
+ - `xDescServ`
117
+
118
+ Campos fiscais importantes:
119
+
120
+ - `emissao.tributacaoMunicipal` e obrigatorio.
121
+ - `emissao.tributacaoMunicipal.tribISSQN` e obrigatorio.
122
+ - `emissao.tributacaoMunicipal.tpRetISSQN` e obrigatorio.
123
+ - `emissao.totTrib` e obrigatorio.
124
+ - A SDK nao assume esses campos por default.
125
+
126
+ ## `totTrib`
127
+
128
+ `totTrib` representa o total aproximado de carga tributaria e deve seguir a regra de escolha do layout. Informe apenas um grupo coerente, por exemplo:
129
+
130
+ ```ts
131
+ totTrib: {
132
+ pTotTribFed: '0.00',
133
+ pTotTribEst: '0.00',
134
+ pTotTribMun: '5.00',
135
+ }
136
+ ```
137
+
138
+ ou:
139
+
140
+ ```ts
141
+ totTrib: {
142
+ indTotTrib: '0',
143
+ }
144
+ ```
145
+
146
+ Nao inventar carga tributaria. Se a aplicacao nao tem esse dado, deve buscar a fonte fiscal correta.
147
+
148
+ ## Exemplo com `emitirNfse`
149
+
150
+ ```ts
151
+ import { EmitirNotaError, emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
152
+
153
+ const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
154
+
155
+ const nota: DpsJsonRequest = {
156
+ ambiente: 'restrita',
157
+ prestador: {
158
+ cnpj: '12345678000195',
159
+ tpInsc: '2',
160
+ cLocEmi: '4106902',
161
+ serie: '1601',
162
+ opSimpNac: '1',
163
+ regEspTrib: '0',
164
+ },
165
+ servico: {
166
+ cTribNac: '010201',
167
+ xDescServ: 'Desenvolvimento de software',
168
+ cLocPrestacao: '4106902',
169
+ cNBS: '115022000',
170
+ },
171
+ emissao: {
172
+ nDPS: '1',
173
+ valores: { vServ: '1500.00' },
174
+ tributacaoMunicipal: {
175
+ tribISSQN: '3',
176
+ cPaisResult: 'BR',
177
+ tpRetISSQN: '1',
178
+ },
179
+ tributacaoFederal: {
180
+ piscofins: { CST: '07' },
181
+ },
182
+ totTrib: {
183
+ pTotTribFed: '0.00',
184
+ pTotTribEst: '0.00',
185
+ pTotTribMun: '5.00',
186
+ },
187
+ },
188
+ };
189
+
190
+ try {
191
+ const resultado = await emitirNfse(nota, pfx);
192
+ console.log(resultado.chaveAcesso);
193
+ console.log(resultado.nfseXml);
194
+ } catch (error) {
195
+ if (!(error instanceof EmitirNotaError)) throw error;
196
+
197
+ for (const rejeicao of error.erros) {
198
+ console.error(rejeicao.Codigo, rejeicao.Descricao);
199
+ }
200
+ }
201
+ ```
202
+
203
+ ## Exemplo com `NfseClient`
204
+
205
+ ```ts
206
+ import { NfseClient } from '@useinvio/nfse-sdk';
207
+
208
+ const client = new NfseClient({
209
+ environment: 'sandbox',
210
+ certificate: {
211
+ content: process.env.NFSE_CERTIFICATE_BASE64!,
212
+ password: process.env.NFSE_CERTIFICATE_PASSWORD!,
213
+ },
214
+ defaults: {
215
+ prestador: {
216
+ cnpj: '12345678000195',
217
+ tpInsc: '2',
218
+ cLocEmi: '4106902',
219
+ serie: '1601',
220
+ opSimpNac: '1',
221
+ regEspTrib: '0',
222
+ },
223
+ servico: {
224
+ cTribNac: '010201',
225
+ xDescServ: 'Desenvolvimento de software',
226
+ cLocPrestacao: '4106902',
227
+ cNBS: '115022000',
228
+ },
229
+ },
230
+ });
231
+
232
+ const invoice = await client.invoices.create({
233
+ emissao: {
234
+ nDPS: '1',
235
+ valores: { vServ: '1000.00' },
236
+ tributacaoMunicipal: {
237
+ tribISSQN: '3',
238
+ tpRetISSQN: '1',
239
+ },
240
+ tributacaoFederal: {
241
+ piscofins: { CST: '07' },
242
+ },
243
+ totTrib: {
244
+ pTotTribFed: '0.00',
245
+ pTotTribEst: '0.00',
246
+ pTotTribMun: '5.00',
247
+ },
248
+ },
249
+ });
250
+
251
+ console.log(invoice.chaveAcesso);
252
+ ```
253
+
254
+ ## Serie e `nDPS`
255
+
256
+ A SEFIN identifica uma DPS pela combinacao de prestador, municipio, `serie` e `nDPS`.
257
+
258
+ - `serie`: serie de emissao usada para agrupar/sequenciar DPS.
259
+ - `nDPS`: numero da DPS dentro daquela serie.
260
+
261
+ Padrao comum:
262
+
263
+ ```text
264
+ serie 1601, nDPS 1
265
+ serie 1601, nDPS 2
266
+ serie 1601, nDPS 3
267
+ ```
268
+
269
+ A aplicacao consumidora deve controlar a sequencia de `nDPS`.
270
+
271
+ ## Ambientes
272
+
273
+ - `restrita`: ambiente de producao restrita/homologacao.
274
+ - `producao`: ambiente de producao.
275
+ - No `NfseClient`, `sandbox` e alias de `restrita`.
276
+ - No `NfseClient`, `production` e alias de `producao`.
277
+
278
+ ## Erros
279
+
280
+ `emitirNfse` lanca `EmitirNotaError` quando a SEFIN rejeita a emissao ou retorna resposta sem XML autorizado.
281
+
282
+ Campos uteis:
283
+
284
+ - `error.status`
285
+ - `error.dpsId`
286
+ - `error.erros`
287
+ - `error.body`
288
+
289
+ `error.erros` contem rejeicoes normalizadas:
290
+
291
+ - `Codigo`
292
+ - `Descricao`
293
+ - `Complemento`
294
+
295
+ ## Campos nao suportados ou cuidados
296
+
297
+ - `tribNac` esta tipado por compatibilidade, mas e rejeitado em runtime porque IBS/CBS no layout v1.01 exige bloco RTC `IBSCBS` ainda nao implementado.
298
+ - `evento` no JSON da DPS ainda nao deve ser usado como shape de evento fiscal.
299
+ - `valores.vDesc` e `valores.vDedRed` sao bloqueados ate refletirem os grupos oficiais corretos do layout.
300
+ - `obra.cCM` e legado e bloqueado.
301
+ - `cPaisResult` em `tributacaoMunicipal` deve ser usado apenas quando `tribISSQN = '3'`.
302
+ - `tpImunidade` deve ser usado apenas quando `tribISSQN = '2'`.
303
+ - `pAliq` e bloqueado quando `prestador.opSimpNac = '1'`.
304
+
305
+ ## Boas respostas do assistente
306
+
307
+ Ao ajudar implementacao, o assistente deve:
308
+
309
+ - escolher o ponto de entrada correto;
310
+ - manter os nomes do JSON da SDK;
311
+ - mostrar TypeScript copiavel;
312
+ - apontar campos faltantes;
313
+ - separar questoes tecnicas de decisoes fiscais;
314
+ - nao escolher regra tributaria pelo usuario;
315
+ - orientar a usar README, JSON_MAPPING e exemplos.
316
+
317
+ Ao ajudar documentacao, o assistente deve:
318
+
319
+ - preservar o posicionamento de SDK protocolar;
320
+ - explicar limites fiscais;
321
+ - dar exemplos curtos;
322
+ - incluir tratamento de erro;
323
+ - citar `serie` vs `nDPS` quando relevante.
package/docs/launch.md ADDED
@@ -0,0 +1,134 @@
1
+ # Launch kit
2
+
3
+ Material curto para divulgar `@useinvio/nfse-sdk` sem prometer que o SDK substitui a camada fiscal da aplicacao.
4
+
5
+ ## Posicionamento
6
+
7
+ `@useinvio/nfse-sdk` e um SDK TypeScript para integrar com a NFS-e Nacional a partir de Node.js. Ele recebe JSON, monta DPS/XML, assina com XMLDSIG, compacta em GZip/Base64, transmite por mTLS e preserva os erros oficiais da SEFIN em formato estruturado.
8
+
9
+ O foco e a camada protocolar. O SDK nao calcula regra municipal, nao escolhe CST, nao decide retencao e nao substitui a validacao fiscal/contabil do produto que o consome.
10
+
11
+ ## Frases curtas
12
+
13
+ - Emita NFS-e Nacional a partir de JSON.
14
+ - Pare de escrever XML fiscal na mao.
15
+ - TypeScript SDK para DPS, XMLDSIG, GZip/Base64, mTLS e SEFIN.
16
+ - Um SDK protocolar para ERPs, SaaS financeiros, contabilidades digitais e plataformas de cobranca.
17
+
18
+ ## Post para LinkedIn
19
+
20
+ Lancei o `@useinvio/nfse-sdk`, um SDK TypeScript para quem precisa integrar com a NFS-e Nacional em Node.js.
21
+
22
+ A ideia e simples: voce envia um JSON tipado e o SDK cuida da parte protocolar chata da emissao:
23
+
24
+ - montagem da DPS/XML;
25
+ - validacoes estruturais;
26
+ - assinatura XMLDSIG;
27
+ - compactacao GZip/Base64;
28
+ - transporte mTLS;
29
+ - consulta de NFS-e;
30
+ - erros oficiais da SEFIN em formato estruturado.
31
+
32
+ Ele nao tenta ser motor fiscal e nao escolhe regra tributaria por voce. Codigo de servico, CST, retencoes, carga tributaria, serie e numero da DPS continuam sendo responsabilidade da aplicacao/ERP/contador.
33
+
34
+ O objetivo e reduzir a friccao tecnica para times que ja sabem o que precisam declarar, mas nao querem manter XML, assinatura digital e transporte SEFIN do zero.
35
+
36
+ GitHub: https://github.com/useinvio/nfse-sdk
37
+ npm: https://www.npmjs.com/package/@useinvio/nfse-sdk
38
+
39
+ ```bash
40
+ npm install @useinvio/nfse-sdk
41
+ ```
42
+
43
+ ## Post tecnico
44
+
45
+ Titulo sugerido:
46
+
47
+ Como emitir NFS-e Nacional em Node.js sem escrever XML fiscal na mao
48
+
49
+ Estrutura:
50
+
51
+ 1. Explique a dor: DPS, XML, certificado A1, XMLDSIG, GZip/Base64, mTLS e rejeicoes SEFIN.
52
+ 2. Mostre o comando de instalacao.
53
+ 3. Mostre um exemplo minimo com `emitirNfse`.
54
+ 4. Mostre como inspecionar o XML com `buildDpsFromJson`.
55
+ 5. Explique os limites: o SDK nao calcula tributos nem substitui regra fiscal.
56
+ 6. Feche com links para GitHub, npm, `JSON_MAPPING.md` e `examples/`.
57
+
58
+ ## README curto para compartilhar em grupos
59
+
60
+ Criei um SDK TypeScript open source para NFS-e Nacional:
61
+
62
+ `@useinvio/nfse-sdk`
63
+
64
+ Ele ajuda a sair de JSON para DPS/XML assinado e enviado para a SEFIN, incluindo XMLDSIG, GZip/Base64, mTLS, consulta e erros estruturados.
65
+
66
+ Nao e motor fiscal; e a camada protocolar para quem ja tem as informacoes fiscais corretas na aplicacao.
67
+
68
+ GitHub: https://github.com/useinvio/nfse-sdk
69
+ npm: https://www.npmjs.com/package/@useinvio/nfse-sdk
70
+
71
+ ## Prompt para Lovable
72
+
73
+ Crie uma landing page enxuta e chamativa para devs para o produto open source `@useinvio/nfse-sdk`.
74
+
75
+ Contexto:
76
+ - E um SDK TypeScript para integracao com a NFS-e Nacional do Brasil.
77
+ - Publico-alvo: devs Node.js/TypeScript, ERPs, SaaS financeiros, contabilidades digitais e plataformas de cobranca.
78
+ - Proposta central: emitir NFS-e Nacional a partir de JSON sem escrever XML fiscal na mao.
79
+ - O SDK cuida da camada protocolar: DPS/XML, validacao estrutural, XMLDSIG, GZip/Base64, mTLS, consulta e erros estruturados da SEFIN.
80
+ - Ele nao e motor fiscal, nao calcula tributos, nao escolhe CST, nao decide retencao e nao substitui validacao contabil.
81
+
82
+ Objetivo da pagina:
83
+ - Fazer um dev entender em menos de 10 segundos o que o SDK resolve.
84
+ - Levar para GitHub e npm.
85
+ - Mostrar um exemplo de codigo real logo no primeiro viewport.
86
+
87
+ Tom visual:
88
+ - Moderno, tecnico, direto, confiavel.
89
+ - Aparencia de ferramenta de infraestrutura/devtool, nao SaaS corporativo generico.
90
+ - Fundo claro ou escuro bem contrastado, tipografia limpa, blocos de codigo bonitos.
91
+ - Evite ilustracoes genericas. Use visual inspirado em terminal, JSON, XML, certificado digital e pipeline de protocolo.
92
+
93
+ Estrutura desejada:
94
+ 1. Hero com headline: "NFS-e Nacional em TypeScript, a partir de JSON."
95
+ 2. Subheadline: "Monte DPS/XML, assine com XMLDSIG, compacte em GZip/Base64 e transmita por mTLS para a SEFIN sem manter a camada protocolar do zero."
96
+ 3. CTAs: "Ver no GitHub" e "Instalar via npm".
97
+ 4. Bloco de codigo com:
98
+ `npm install @useinvio/nfse-sdk`
99
+ e um snippet curto usando `emitirNfse`.
100
+ 5. Secao "O que ele resolve" com cards pequenos:
101
+ - JSON para DPS/XML
102
+ - Assinatura XMLDSIG
103
+ - GZip/Base64
104
+ - mTLS com certificado A1
105
+ - Consulta de NFS-e
106
+ - Erros SEFIN estruturados
107
+ 6. Secao "O que ele nao faz" com destaque honesto:
108
+ "Nao calcula regra municipal, nao escolhe CST, nao decide retencoes e nao substitui sua validacao fiscal."
109
+ 7. Secao final com links para GitHub, npm, README e exemplos.
110
+
111
+ Conteudo tecnico para usar:
112
+ - Package: `@useinvio/nfse-sdk`
113
+ - Install: `npm install @useinvio/nfse-sdk`
114
+ - GitHub: `https://github.com/useinvio/nfse-sdk`
115
+ - npm: `https://www.npmjs.com/package/@useinvio/nfse-sdk`
116
+ - Exemplo curto:
117
+
118
+ ```ts
119
+ import { emitirNfse, loadPfx } from '@useinvio/nfse-sdk';
120
+
121
+ const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
122
+ const resultado = await emitirNfse(notaJson, pfx);
123
+
124
+ console.log(resultado.chaveAcesso);
125
+ console.log(resultado.nfseXml);
126
+ ```
127
+
128
+ Requisitos:
129
+ - A primeira tela deve mostrar o nome do pacote, a promessa principal, CTAs e codigo.
130
+ - A pagina deve ser responsiva.
131
+ - Use layout enxuto, sem muitas secoes.
132
+ - Nao invente features alem das listadas.
133
+ - Nao prometa "compliance fiscal automatico".
134
+ - Nao diga que substitui contador ou ERP.
@@ -0,0 +1,12 @@
1
+ # Examples
2
+
3
+ Copyable entry points for common NFS-e Nacional flows.
4
+
5
+ ## Files
6
+
7
+ - [`generate-dps-xml.ts`](./generate-dps-xml.ts): build an unsigned DPS XML from JSON.
8
+ - [`emit-homologation.ts`](./emit-homologation.ts): emit in the restricted/sandbox SEFIN environment.
9
+ - [`client-resource.ts`](./client-resource.ts): use `NfseClient` with certificate and defaults configured once.
10
+ - [`handle-errors.ts`](./handle-errors.ts): normalize SEFIN rejection details for your application.
11
+
12
+ The examples assume Node.js 20+ and a valid A1/PFX certificate. They are intentionally explicit about fiscal fields; the SDK does not infer municipal taxation, withholding, CST or total tax burden.
@@ -0,0 +1,50 @@
1
+ import { NfseClient } from '@useinvio/nfse-sdk';
2
+
3
+ const client = new NfseClient({
4
+ environment: 'sandbox',
5
+ certificate: {
6
+ content: process.env.NFSE_CERTIFICATE_BASE64!,
7
+ password: process.env.NFSE_CERTIFICATE_PASSWORD!,
8
+ },
9
+ defaults: {
10
+ prestador: {
11
+ cnpj: '12345678000195',
12
+ tpInsc: '2',
13
+ cLocEmi: '4106902',
14
+ serie: '1601',
15
+ opSimpNac: '1',
16
+ regEspTrib: '0',
17
+ },
18
+ servico: {
19
+ cTribNac: '010201',
20
+ xDescServ: 'Desenvolvimento de software',
21
+ cLocPrestacao: '4106902',
22
+ cNBS: '115022000',
23
+ },
24
+ },
25
+ });
26
+
27
+ const invoice = await client.invoices.create({
28
+ emissao: {
29
+ nDPS: '2',
30
+ valores: { vServ: '1000.00' },
31
+ tomador: {
32
+ CPF: '00000000000',
33
+ xNome: 'Cliente Exemplo',
34
+ },
35
+ tributacaoMunicipal: {
36
+ tribISSQN: '3',
37
+ tpRetISSQN: '1',
38
+ },
39
+ tributacaoFederal: {
40
+ piscofins: { CST: '07' },
41
+ },
42
+ totTrib: {
43
+ pTotTribFed: '0.00',
44
+ pTotTribEst: '0.00',
45
+ pTotTribMun: '5.00',
46
+ },
47
+ },
48
+ });
49
+
50
+ console.log(invoice.chaveAcesso);
@@ -0,0 +1,54 @@
1
+ import { EmitirNotaError, emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
2
+
3
+ const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
4
+
5
+ const nota: DpsJsonRequest = {
6
+ ambiente: 'restrita',
7
+ prestador: {
8
+ cnpj: '12345678000195',
9
+ tpInsc: '2',
10
+ cLocEmi: '4106902',
11
+ serie: '1601',
12
+ opSimpNac: '1',
13
+ regEspTrib: '0',
14
+ },
15
+ servico: {
16
+ cTribNac: '010201',
17
+ xDescServ: 'Desenvolvimento de software',
18
+ cLocPrestacao: '4106902',
19
+ cNBS: '115022000',
20
+ },
21
+ emissao: {
22
+ nDPS: '1',
23
+ dhEmi: '2026-06-15T10:30:00-03:00',
24
+ dCompet: '2026-06-01',
25
+ valores: { vServ: '1500.00' },
26
+ tributacaoMunicipal: {
27
+ tribISSQN: '3',
28
+ cPaisResult: 'BR',
29
+ tpRetISSQN: '1',
30
+ },
31
+ tributacaoFederal: {
32
+ piscofins: { CST: '07' },
33
+ },
34
+ totTrib: {
35
+ pTotTribFed: '0.00',
36
+ pTotTribEst: '0.00',
37
+ pTotTribMun: '5.00',
38
+ },
39
+ },
40
+ };
41
+
42
+ try {
43
+ const resultado = await emitirNfse(nota, pfx);
44
+ console.log(resultado.chaveAcesso);
45
+ console.log(resultado.nfseXml);
46
+ } catch (error) {
47
+ if (!(error instanceof EmitirNotaError)) throw error;
48
+
49
+ console.error(`Emissao rejeitada pela SEFIN: HTTP ${error.status}`);
50
+ for (const rejeicao of error.erros) {
51
+ console.error(`${rejeicao.Codigo}: ${rejeicao.Descricao}`);
52
+ if (rejeicao.Complemento) console.error(rejeicao.Complemento);
53
+ }
54
+ }
@@ -0,0 +1,43 @@
1
+ import { buildDpsFromJson, type DpsJsonRequest } from '@useinvio/nfse-sdk';
2
+
3
+ const nota: DpsJsonRequest = {
4
+ ambiente: 'restrita',
5
+ prestador: {
6
+ cnpj: '12345678000195',
7
+ tpInsc: '2',
8
+ cLocEmi: '4106902',
9
+ serie: '1601',
10
+ opSimpNac: '1',
11
+ regEspTrib: '0',
12
+ },
13
+ servico: {
14
+ cTribNac: '010201',
15
+ xDescServ: 'Desenvolvimento de software',
16
+ cLocPrestacao: '4106902',
17
+ cNBS: '115022000',
18
+ },
19
+ emissao: {
20
+ nDPS: '1',
21
+ dhEmi: '2026-06-15T10:30:00-03:00',
22
+ dCompet: '2026-06-01',
23
+ valores: { vServ: '1500.00' },
24
+ tributacaoMunicipal: {
25
+ tribISSQN: '3',
26
+ cPaisResult: 'BR',
27
+ tpRetISSQN: '1',
28
+ },
29
+ tributacaoFederal: {
30
+ piscofins: { CST: '07' },
31
+ },
32
+ totTrib: {
33
+ pTotTribFed: '0.00',
34
+ pTotTribEst: '0.00',
35
+ pTotTribMun: '5.00',
36
+ },
37
+ },
38
+ };
39
+
40
+ const { id, xml } = buildDpsFromJson(nota);
41
+
42
+ console.log(id);
43
+ console.log(xml);
@@ -0,0 +1,24 @@
1
+ import { EmitirNotaError, emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
2
+
3
+ async function emitWithStructuredErrors(nota: DpsJsonRequest) {
4
+ const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
5
+
6
+ try {
7
+ return await emitirNfse(nota, pfx);
8
+ } catch (error) {
9
+ if (!(error instanceof EmitirNotaError)) throw error;
10
+
11
+ return {
12
+ rejected: true,
13
+ status: error.status,
14
+ dpsId: error.dpsId,
15
+ errors: error.erros.map((rejeicao) => ({
16
+ code: rejeicao.Codigo,
17
+ message: rejeicao.Descricao,
18
+ detail: rejeicao.Complemento,
19
+ })),
20
+ };
21
+ }
22
+ }
23
+
24
+ void emitWithStructuredErrors({} as DpsJsonRequest);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@useinvio/nfse-sdk",
3
- "version": "0.3.0",
4
- "description": "SDK TypeScript para integração técnica com a NFS-e Nacional.",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript SDK for Brazil's national NFS-e: JSON to DPS/XML, XMLDSIG, GZip/Base64, mTLS and SEFIN errors.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -16,6 +16,9 @@
16
16
  "dist/*.d.ts",
17
17
  "dist/*.js",
18
18
  "dist/*.js.map",
19
+ "docs/*.md",
20
+ "examples/*.ts",
21
+ "examples/README.md",
19
22
  "README.md",
20
23
  "JSON_MAPPING.md",
21
24
  "LICENSE"
@@ -29,9 +32,18 @@
29
32
  "keywords": [
30
33
  "nfse",
31
34
  "nfs-e",
35
+ "nfs-e-nacional",
32
36
  "nota-fiscal",
37
+ "nota-fiscal-servico",
38
+ "dps",
33
39
  "sefin",
34
- "sped"
40
+ "sped",
41
+ "xml-dsig",
42
+ "xmldsig",
43
+ "mtls",
44
+ "typescript",
45
+ "brazil",
46
+ "erp"
35
47
  ],
36
48
  "repository": {
37
49
  "type": "git",