@bitize/bitmde 0.17.1 → 0.18.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [Não publicado]
4
+
5
+ ## [0.18.0] / 2026-10-01
6
+
7
+ ### Corrigido
8
+
9
+ - **Um `docZip` corrompido na distribuição DF-e encerrava o processo de quem consome a biblioteca.** `Gzip.unzip` rejeitava a Promise mas seguia executando e lançava um `TypeError` fora dela, como `uncaughtException`, antes de qualquer `.catch` do chamador
10
+ - Um documento ilegível no lote deixa de derrubar a consulta inteira. Antes, `consultaUltNSU`, `consultaNSU` e `consultaChNFe` perderiam os documentos válidos e o `ultNSU`/`maxNSU`, e a varredura ficaria presa no mesmo NSU. Ver [ADR 0013](https://github.com/bitize/bitmde/blob/main/.docs/arquitetura/decisoes/0013-falha-de-doczip-vira-item-de-doczip-errors.md)
11
+ - `<loteDistDFeInt/>` vazio na resposta deixa de lançar `TypeError` e vira lote sem documentos. Um `loteDistDFeInt` em qualquer outra forma que não seja um lote — texto no lugar dos `docZip`, elemento repetido — passa a devolver `error: 'loteDistDFeInt inválido.'` em vez de lançar
12
+
13
+ ### Adicionado
14
+
15
+ - Campo `data.docZipErrors: [{ nsu, schema, error }]` no retorno da distribuição DF-e, com os documentos do lote que não puderam ser descompactados ou interpretados. Sempre presente; `[]` quando todos abrem. `docZip` mantém o formato de sempre e passa a trazer só os documentos válidos. Falha de documento não preenche o `error` de topo
16
+
17
+ ### Modificado
18
+
19
+ - `actions/checkout` e `actions/setup-node` atualizadas da v4 para a v7 nos três workflows. A v4 roda em Node 20, deprecado nos runners do GitHub e já forçado a executar em Node 24 — o aviso aparecia em todo run. Nenhuma quebra das v5/v6/v7 se aplica a este repositório: o cache automático da v5 do `setup-node` depende do campo `packageManager` no `package.json`, que não existe aqui, e a remoção do `NODE_AUTH_TOKEN` fictício na v7 não afeta quem publica por OIDC
20
+
3
21
  ## [0.17.1] / 2026-09-10
4
22
 
5
23
  ### Adicionado
package/README.md CHANGED
@@ -108,6 +108,7 @@ console.log(consulta)
108
108
  // schema: 'procNFe_v4.00.xsd',
109
109
  // },
110
110
  // ],
111
+ // docZipErrors: [],
111
112
  // },
112
113
  // reqXml: '<?xml version="1.0" encoding="utf-8"?> ... </soap12:Body></soap12:Envelope>',
113
114
  // resXml: '<?xml version="1.0" encoding="utf-8"?> ... </soap:Body></soap:Envelope>',
@@ -115,6 +116,20 @@ console.log(consulta)
115
116
  // }
116
117
  ```
117
118
 
119
+ `docZip` traz só os documentos que puderam ser abertos. Um documento do lote que não descompacta ou não é XML válido não derruba a consulta: ele vai para `docZipErrors`, com o motivo, e `ultNSU`/`maxNSU` continuam preenchidos para a varredura avançar. O formato é o mesmo nas três consultas:
120
+
121
+ ```js
122
+ // docZipErrors: [
123
+ // {
124
+ // nsu: '000000000000051',
125
+ // schema: 'procNFe_v4.00.xsd',
126
+ // error: 'Falha ao descompactar o docZip: incorrect header check',
127
+ // },
128
+ // ]
129
+ ```
130
+
131
+ As mensagens possíveis em `error` são `docZip sem conteúdo.`, `Falha ao descompactar o docZip: <motivo>` e `Falha ao interpretar o XML do docZip: <motivo>`.
132
+
118
133
  ### Consulta por chNFe
119
134
 
120
135
  | Campo | Tipo | Tamanho | Descrição |
@@ -161,6 +176,7 @@ console.log(consulta)
161
176
  // schema: 'procNFe_v4.00.xsd',
162
177
  // },
163
178
  // ],
179
+ // docZipErrors: [],
164
180
  // },
165
181
  // reqXml: '<?xml version="1.0" encoding="utf-8"?> ... </soap12:Body></soap12:Envelope>',
166
182
  // resXml: '<?xml version="1.0" encoding="utf-8"?> ... </soap:Body></soap:Envelope>',
@@ -212,6 +228,7 @@ console.log(consulta)
212
228
  // schema: 'resNFe_v1.01.xsd',
213
229
  // },
214
230
  // ],
231
+ // docZipErrors: [],
215
232
  // },
216
233
  // reqXml: '<?xml version="1.0" encoding="utf-8"?> ... </soap12:Body></soap12:Envelope>',
217
234
  // resXml: '<?xml version="1.0" encoding="utf-8"?> ... </soap:Body></soap:Envelope>',
@@ -56,6 +56,11 @@ declare class DistribuicaoDFe {
56
56
  nsu: string;
57
57
  schema: string;
58
58
  }];
59
+ docZipErrors: [{
60
+ nsu: string;
61
+ schema: string;
62
+ error: string;
63
+ }];
59
64
  };
60
65
  error: string;
61
66
  reqXml: string;
@@ -80,6 +85,11 @@ declare class DistribuicaoDFe {
80
85
  nsu: string;
81
86
  schema: string;
82
87
  }];
88
+ docZipErrors: [{
89
+ nsu: string;
90
+ schema: string;
91
+ error: string;
92
+ }];
83
93
  };
84
94
  error: string;
85
95
  reqXml: string;
@@ -104,6 +114,11 @@ declare class DistribuicaoDFe {
104
114
  nsu: string;
105
115
  schema: string;
106
116
  }];
117
+ docZipErrors: [{
118
+ nsu: string;
119
+ schema: string;
120
+ error: string;
121
+ }];
107
122
  };
108
123
  error: string;
109
124
  reqXml: string;
@@ -4,7 +4,7 @@ declare class DistribuicaoController {
4
4
  /**
5
5
  *
6
6
  * @param {Object} opts
7
- * @returns {Promise<{data:{tpAmb: string,verAplic: string,cStat: string,xMotivo: string,dhResp: string,ultNSU: string,maxNSU: string, docZip:[{xml: string,json: Object,nsu: string,schema: string}]}, error: string, reqXml: string, resXml: string, status: number}>}
7
+ * @returns {Promise<{data:{tpAmb: string,verAplic: string,cStat: string,xMotivo: string,dhResp: string,ultNSU: string,maxNSU: string, docZip:[{xml: string,json: Object,nsu: string,schema: string}], docZipErrors:[{nsu: string,schema: string,error: string}]}, error: string, reqXml: string, resXml: string, status: number}>}
8
8
  */
9
9
  static enviar(opts: any): Promise<{
10
10
  data: {
@@ -21,6 +21,11 @@ declare class DistribuicaoController {
21
21
  nsu: string;
22
22
  schema: string;
23
23
  }];
24
+ docZipErrors: [{
25
+ nsu: string;
26
+ schema: string;
27
+ error: string;
28
+ }];
24
29
  };
25
30
  error: string;
26
31
  reqXml: string;
@@ -17,6 +17,11 @@ declare const controller: Readonly<{
17
17
  nsu: string;
18
18
  schema: string;
19
19
  }];
20
+ docZipErrors: [{
21
+ nsu: string;
22
+ schema: string;
23
+ error: string;
24
+ }];
20
25
  };
21
26
  error: string;
22
27
  reqXml: string;
@@ -20,7 +20,7 @@ declare class DistribuicaoHelper {
20
20
  /**
21
21
  *
22
22
  * @param {string} data
23
- * @returns {Promise<{tpAmb: string,verAplic: string,cStat: string,xMotivo: string,dhResp: string,ultNSU: string,maxNSU: string, docZip:[{xml: string,json: Object,nsu: string,schema: string}], error: string}>}
23
+ * @returns {Promise<{tpAmb: string,verAplic: string,cStat: string,xMotivo: string,dhResp: string,ultNSU: string,maxNSU: string, docZip:[{xml: string,json: Object,nsu: string,schema: string}], docZipErrors:[{nsu: string,schema: string,error: string}], error: string}>}
24
24
  */
25
25
  static montarResponse(data: string): Promise<{
26
26
  tpAmb: string;
@@ -36,6 +36,28 @@ declare class DistribuicaoHelper {
36
36
  nsu: string;
37
37
  schema: string;
38
38
  }];
39
+ docZipErrors: [{
40
+ nsu: string;
41
+ schema: string;
42
+ error: string;
43
+ }];
44
+ error: string;
45
+ }>;
46
+ /**
47
+ * Descompacta e interpreta um docZip sem nunca rejeitar: a falha vira
48
+ * um item com `error`, para não derrubar o restante do lote.
49
+ *
50
+ * @param {Object} doc
51
+ * @returns {Promise<{xml: string,json: Object,nsu: string,schema: string} | {nsu: string,schema: string,error: string}>}
52
+ */
53
+ static abrirDocZip(doc: any): Promise<{
54
+ xml: string;
55
+ json: any;
56
+ nsu: string;
57
+ schema: string;
58
+ } | {
59
+ nsu: string;
60
+ schema: string;
39
61
  error: string;
40
62
  }>;
41
63
  }
@@ -21,6 +21,21 @@ declare const helper: Readonly<{
21
21
  nsu: string;
22
22
  schema: string;
23
23
  }];
24
+ docZipErrors: [{
25
+ nsu: string;
26
+ schema: string;
27
+ error: string;
28
+ }];
29
+ error: string;
30
+ }>;
31
+ abrirDocZip(doc: any): Promise<{
32
+ xml: string;
33
+ json: any;
34
+ nsu: string;
35
+ schema: string;
36
+ } | {
37
+ nsu: string;
38
+ schema: string;
24
39
  error: string;
25
40
  }>;
26
41
  };
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
- VERSION: "0.17.1"
2
+ VERSION: "0.18.0"
3
3
  };
@@ -7,19 +7,19 @@ let {
7
7
  } = require("../util");
8
8
 
9
9
  class DistribuicaoHelper {
10
- static async enviarConsulta(e, t) {
11
- var r = DISTRIBUICAO[t.tpAmb], e = {
10
+ static async enviarConsulta(e, r) {
11
+ var t = DISTRIBUICAO[r.tpAmb], e = {
12
12
  method: "POST",
13
13
  data: e
14
14
  };
15
15
  return await new SefazService({
16
- baseURL: r,
16
+ baseURL: t,
17
17
  ca: CA,
18
- cert: t.cert,
19
- key: t.key,
20
- tpAmb: t.tpAmb,
21
- requestOptions: t.requestOptions,
22
- httpsOptions: t.httpsOptions
18
+ cert: r.cert,
19
+ key: r.key,
20
+ tpAmb: r.tpAmb,
21
+ requestOptions: r.requestOptions,
22
+ httpsOptions: r.httpsOptions
23
23
  }).request(e);
24
24
  }
25
25
  static montarRequest(e) {
@@ -27,7 +27,7 @@ class DistribuicaoHelper {
27
27
  return Xml.envelopar(e);
28
28
  }
29
29
  static async montarResponse(e) {
30
- var t = {}, e = Xml.xmlToJson(e), {
30
+ var r = {}, e = Xml.xmlToJson(e), {
31
31
  "soap:Envelope": {
32
32
  "soap:Body": {
33
33
  nfeDistDFeInteresseResponse: {
@@ -37,21 +37,51 @@ class DistribuicaoHelper {
37
37
  } = {}
38
38
  } = {}
39
39
  } = {}
40
- } = (e.error && (t.error = e.error), e), {
41
- loteDistDFeInt: r = {}
42
- } = e, r = (r.docZip ? Array.isArray(r.docZip) || (r.docZip = [ r.docZip ]) : r.docZip = [],
43
- await Promise.all(r.docZip.map(async e => {
44
- var t = await Gzip.unzip(e.value);
40
+ } = (e.error && (r.error = e.error), e);
41
+ let {
42
+ loteDistDFeInt: t = {}
43
+ } = e;
44
+ "" === t ? t = {} : "object" == typeof t && !Array.isArray(t) || (r.error = "loteDistDFeInt inválido.",
45
+ t = {}), t.docZip ? Array.isArray(t.docZip) || (t.docZip = [ t.docZip ]) : t.docZip = [];
46
+ var a, s = [], i = [];
47
+ for (a of await Promise.all(t.docZip.map(e => DistribuicaoHelper.abrirDocZip(e)))) (a.error ? i : s).push(a);
48
+ return r.tpAmb = e.tpAmb || "", r.verAplic = e.verAplic || "", r.cStat = e.cStat || "",
49
+ r.xMotivo = e.xMotivo || "", r.dhResp = e.dhResp || "", r.ultNSU = e.ultNSU || "",
50
+ r.maxNSU = e.maxNSU || "", r.docZip = s, r.docZipErrors = i, r;
51
+ }
52
+ static async abrirDocZip(e) {
53
+ var r = e["@_NSU"] || "", t = e["@_schema"] || "";
54
+ if (!e.value) return {
55
+ nsu: r,
56
+ schema: t,
57
+ error: "docZip sem conteúdo."
58
+ };
59
+ let a;
60
+ try {
61
+ a = await Gzip.unzip(e.value);
62
+ } catch (e) {
45
63
  return {
46
- xml: t,
47
- json: Xml.xmlToJson(t),
48
- nsu: e["@_NSU"],
49
- schema: e["@_schema"]
64
+ nsu: r,
65
+ schema: t,
66
+ error: "Falha ao descompactar o docZip: " + e.message
50
67
  };
51
- })));
52
- return t.tpAmb = e.tpAmb || "", t.verAplic = e.verAplic || "", t.cStat = e.cStat || "",
53
- t.xMotivo = e.xMotivo || "", t.dhResp = e.dhResp || "", t.ultNSU = e.ultNSU || "",
54
- t.maxNSU = e.maxNSU || "", t.docZip = r, t;
68
+ }
69
+ let s;
70
+ try {
71
+ s = Xml.xmlToJson(a);
72
+ } catch (e) {
73
+ return {
74
+ nsu: r,
75
+ schema: t,
76
+ error: "Falha ao interpretar o XML do docZip: " + e.message
77
+ };
78
+ }
79
+ return {
80
+ xml: a,
81
+ json: s,
82
+ nsu: r,
83
+ schema: t
84
+ };
55
85
  }
56
86
  }
57
87
 
package/lib/util/gzip.js CHANGED
@@ -3,11 +3,11 @@ let zlib = require("zlib");
3
3
  class Gzip {
4
4
  static unzip(e) {
5
5
  let i = Buffer.from(e, "base64");
6
- return new Promise((t, r) => {
6
+ return new Promise((r, t) => {
7
7
  zlib.unzip(i, function(e, i) {
8
- e && r(e);
8
+ if (e) return t(e);
9
9
  e = i.toString("utf8");
10
- t(e);
10
+ r(e);
11
11
  });
12
12
  });
13
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitize/bitmde",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "Biblioteca para consultar notas destinadas e enviar evento de manifestação do destinatário",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./dist/index.d.ts",