ghinfe 0.6.0 → 0.6.2

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.
Files changed (110) hide show
  1. package/.env.example +24 -15
  2. package/LICENSE +21 -21
  3. package/README.md +491 -413
  4. package/docs/developer-guide.html +421 -421
  5. package/docs/openapi.yaml +428 -428
  6. package/examples/dce-homologacao.js +141 -0
  7. package/examples/emitir-nfce.js +51 -51
  8. package/examples/emitir-nfe.js +83 -83
  9. package/examples/emitir-nfse.js +46 -46
  10. package/examples/endpoints-sefaz.js +14 -14
  11. package/examples/eventos-nfe.js +49 -49
  12. package/examples/gerar-chave.js +25 -25
  13. package/examples/gerar-dace.js +59 -0
  14. package/examples/gerar-danfe.js +75 -75
  15. package/examples/gerar-dce.js +58 -0
  16. package/examples/layouts-nfse.js +51 -51
  17. package/examples/mock-sefaz.js +52 -52
  18. package/examples/nfse-eventos.js +57 -57
  19. package/examples/reforma-ibscbs.js +27 -27
  20. package/examples/reforma-nfe-xml.js +52 -52
  21. package/examples/status-sefaz.js +12 -12
  22. package/examples/validar-xsd.js +48 -48
  23. package/package.json +59 -68
  24. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consSitDCeTiposBasico_v1.00.xsd +123 -0
  25. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consSitDCe_v1.00.xsd +10 -0
  26. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consStatServDCeTiposBasico_v1.00.xsd +110 -0
  27. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consStatServDCe_v1.00.xsd +10 -0
  28. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/dceTiposBasico_v1.00.xsd +1388 -0
  29. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/retConsSitDCe_v1.00.xsd +10 -0
  30. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/retConsStatServDCe_v1.00.xsd +10 -0
  31. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/tiposGeralDCe_v1.00.xsd +712 -0
  32. package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/xmldsig-core-schema_v1.01.xsd +98 -0
  33. package/schemas/dce/PL_DCe_100a_NT2024.001/dceTiposBasico_v1.00.xsd +1410 -0
  34. package/schemas/dce/PL_DCe_100a_NT2024.001/dce_v1.00.xsd +10 -0
  35. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/evCancDCe_v1.00.xsd +36 -0
  36. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/eventoDCeTiposBasico_v1.00.xsd +283 -0
  37. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/eventoDCe_v1.00.xsd +9 -0
  38. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/procEventoDCe_v1.00.xsd +10 -0
  39. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/retEventoDCe_v1.00.xsd +9 -0
  40. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/tiposGeralDCe_v1.00.xsd +712 -0
  41. package/schemas/dce/PL_DCe_100a_NT2024.001/evento/xmldsig-core-schema_v1.01.xsd +98 -0
  42. package/schemas/dce/PL_DCe_100a_NT2024.001/procDCe_v1.00.xsd +37 -0
  43. package/schemas/dce/PL_DCe_100a_NT2024.001/retDCe_v1.00.xsd +9 -0
  44. package/schemas/dce/PL_DCe_100a_NT2024.001/tiposGeralDCe_v1.00.xsd +712 -0
  45. package/schemas/dce/PL_DCe_100a_NT2024.001/xmldsig-core-schema_v1.01.xsd +98 -0
  46. package/schemas/nfe/PL_009_V4/enviNFe_v3.10.xsd +8 -8
  47. package/schemas/nfe/PL_009_V4/xmldsig-core-schema_v1.01.xsd +97 -97
  48. package/scripts/download-schemas.js +39 -39
  49. package/scripts/test-xsd.js +34 -34
  50. package/src/api/server.js +316 -316
  51. package/src/constants/sefaz.js +69 -69
  52. package/src/danfe/DanfeService.js +205 -205
  53. package/src/danfe/xml-extract.js +69 -69
  54. package/src/dce/builders/DCeEventoXmlBuilder.js +86 -0
  55. package/src/dce/builders/DCeXmlBuilder.js +345 -0
  56. package/src/dce/constants/dce.js +87 -0
  57. package/src/dce/dace/DaceService.js +356 -0
  58. package/src/dce/dace/dace-extract.js +114 -0
  59. package/src/dce/services/DCeService.js +263 -0
  60. package/src/dce/services/DCeSoapService.js +235 -0
  61. package/src/dce/services/DCeXmlService.js +67 -0
  62. package/src/dce/types/DCeDocument.js +106 -0
  63. package/src/dce/utils/qrcode.utils.js +59 -0
  64. package/src/errors/GhinfeError.js +13 -13
  65. package/src/errors/SefazError.js +25 -25
  66. package/src/errors/XsdValidationError.js +15 -15
  67. package/src/index.js +84 -60
  68. package/src/nfce/builders/NFCeXmlBuilder.js +178 -178
  69. package/src/nfce/constants/qrcode.js +26 -26
  70. package/src/nfce/services/NFCeService.js +188 -188
  71. package/src/nfce/services/NFCeXmlService.js +38 -38
  72. package/src/nfce/types/NFCeDocument.js +42 -42
  73. package/src/nfce/utils/qrcode.utils.js +92 -92
  74. package/src/nfe/builders/NFeEventoXmlBuilder.js +110 -110
  75. package/src/nfe/builders/NFeXmlBuilder.js +215 -215
  76. package/src/nfe/mocks/sefaz-responses.js +195 -195
  77. package/src/nfe/services/NFeEventoService.js +95 -95
  78. package/src/nfe/services/NFeService.js +196 -196
  79. package/src/nfe/services/NFeSignService.js +127 -111
  80. package/src/nfe/services/NFeSoapService.js +437 -437
  81. package/src/nfe/services/NFeXmlService.js +41 -41
  82. package/src/nfe/services/NFeXsdService.js +56 -56
  83. package/src/nfe/types/NFeDocument.js +92 -92
  84. package/src/nfe/types/NFeEvento.js +44 -44
  85. package/src/nfse/NFSeMunicipioResolver.js +42 -42
  86. package/src/nfse/builders/NFSeEventoXmlBuilder.js +92 -92
  87. package/src/nfse/builders/NFSeXmlBuilder.js +16 -16
  88. package/src/nfse/constants/municipios.js +82 -82
  89. package/src/nfse/layouts/adapters.js +202 -202
  90. package/src/nfse/mocks/nfse-responses.js +142 -142
  91. package/src/nfse/services/NFSeService.js +191 -191
  92. package/src/nfse/services/NFSeSoapService.js +232 -232
  93. package/src/nfse/services/NFSeXmlService.js +12 -12
  94. package/src/nfse/types/NFSeDocument.js +54 -54
  95. package/src/queue/NFCeQueue.js +63 -63
  96. package/src/queue/NFSeQueue.js +59 -59
  97. package/src/queue/NFeQueue.js +76 -76
  98. package/src/reforma/ibscbs.js +175 -175
  99. package/src/sefaz/SefazEndpointResolver.js +95 -95
  100. package/src/sefaz/ca/icp-brasil-raiz-v10.pem +38 -0
  101. package/src/sefaz/endpoints.registry.js +205 -205
  102. package/src/sefaz/httpsAgent.js +33 -0
  103. package/src/shared/fiscal.helpers.js +53 -53
  104. package/src/utils/certificate.utils.js +69 -47
  105. package/src/utils/chave.utils.js +205 -117
  106. package/src/utils/code128.utils.js +67 -0
  107. package/src/utils/date.utils.js +26 -26
  108. package/src/utils/xml.utils.js +44 -44
  109. package/src/validation/XsdValidator.js +133 -114
  110. package/src/validation/schemas.js +18 -14
@@ -1,114 +1,133 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import libxmljs from 'libxmljs2';
4
- import { pathToFileURL } from 'url';
5
- import { XsdValidationError } from '../errors/XsdValidationError.js';
6
- import { GhinfeError } from '../errors/GhinfeError.js';
7
-
8
- const schemaCache = new Map();
9
-
10
- /**
11
- * Validador XSD genérico usando libxmljs2 e schemas oficiais SEFAZ.
12
- */
13
- export class XsdValidator {
14
- /**
15
- * @param {string} xsdPath Caminho absoluto do arquivo .xsd
16
- */
17
- static loadSchema(xsdPath) {
18
- if (schemaCache.has(xsdPath)) {
19
- return schemaCache.get(xsdPath);
20
- }
21
-
22
- if (!fs.existsSync(xsdPath)) {
23
- throw new GhinfeError(
24
- `Schema XSD não encontrado: ${xsdPath}. Execute: node scripts/download-schemas.js`,
25
- 'XSD_SCHEMA_NOT_FOUND'
26
- );
27
- }
28
-
29
- const dir = path.dirname(xsdPath);
30
- const baseUrl = pathToFileURL(dir + path.sep).href;
31
- const content = fs.readFileSync(xsdPath, 'utf8');
32
- const schema = libxmljs.parseXml(content, { baseUrl });
33
-
34
- schemaCache.set(xsdPath, schema);
35
- return schema;
36
- }
37
-
38
- /**
39
- * Valida XML contra schema XSD.
40
- * @param {string} xml
41
- * @param {string} xsdPath
42
- * @param {{ injetarAssinaturaStub?: boolean, modelo?: '55'|'65' }} [options]
43
- * @returns {{ valido: true, avisos: string[] }}
44
- */
45
- static validar(xml, xsdPath, options = {}) {
46
- let xmlParaValidar = xml;
47
-
48
- if (options.injetarAssinaturaStub) {
49
- xmlParaValidar = this.#prepararXmlEstrutural(xml, options.modelo ?? '55');
50
- }
51
-
52
- const schema = this.loadSchema(xsdPath);
53
- const doc = libxmljs.parseXml(xmlParaValidar);
54
-
55
- const valido = doc.validate(schema);
56
- if (valido) {
57
- return { valido: true, avisos: [] };
58
- }
59
-
60
- const erros = doc.validationErrors.map((e) => e.message).filter(Boolean);
61
- throw new XsdValidationError(erros, path.basename(xsdPath));
62
- }
63
-
64
- /**
65
- * Valida e retorna boolean (sem lançar exceção).
66
- * @param {string} xml
67
- * @param {string} xsdPath
68
- * @param {object} [options]
69
- */
70
- static tentarValidar(xml, xsdPath, options = {}) {
71
- try {
72
- return this.validar(xml, xsdPath, options);
73
- } catch (error) {
74
- if (error instanceof XsdValidationError) {
75
- return { valido: false, erros: error.erros };
76
- }
77
- throw error;
78
- }
79
- }
80
-
81
- /**
82
- * Injeta elementos exigidos pelo XSD para validação estrutural pré-assinatura.
83
- * O schema exige Signature (NF-e) ou infNFeSupl + Signature (NFC-e).
84
- * @param {string} xml
85
- * @param {'55'|'65'} modelo
86
- */
87
- static #prepararXmlEstrutural(xml, modelo) {
88
- if (xml.includes('</Signature>')) return xml;
89
-
90
- const idMatch = xml.match(/Id="(NFe\d{44})"/);
91
- const id = idMatch?.[1];
92
- if (!id) return xml;
93
-
94
- let complemento = '';
95
-
96
- if (modelo === '65' && !xml.includes('infNFeSupl')) {
97
- const qrStub = 'https://nfce.sefaz.example/qr?p=STUB';
98
- complemento += `<infNFeSupl><qrCode><![CDATA[${qrStub}]]></qrCode><urlChave>${qrStub}</urlChave></infNFeSupl>`;
99
- }
100
-
101
- complemento += this.#assinaturaStub(id);
102
- return xml.replace('</NFe>', `${complemento}</NFe>`);
103
- }
104
-
105
- /** @param {string} id */
106
- static #assinaturaStub(id) {
107
- return `<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="#${id}"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>WCF0TVY=</DigestValue></Reference></SignedInfo><SignatureValue>WCF0TVY=</SignatureValue><KeyInfo><X509Data><X509Certificate>WCF0TVY=</X509Certificate></X509Data></KeyInfo></Signature>`;
108
- }
109
-
110
- /** Limpa cache de schemas (útil em testes). */
111
- static limparCache() {
112
- schemaCache.clear();
113
- }
114
- }
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import libxmljs from 'libxmljs2';
4
+ import { pathToFileURL } from 'url';
5
+ import { XsdValidationError } from '../errors/XsdValidationError.js';
6
+ import { GhinfeError } from '../errors/GhinfeError.js';
7
+
8
+ const schemaCache = new Map();
9
+
10
+ /**
11
+ * Validador XSD genérico usando libxmljs2 e schemas oficiais SEFAZ.
12
+ */
13
+ export class XsdValidator {
14
+ /**
15
+ * @param {string} xsdPath Caminho absoluto do arquivo .xsd
16
+ */
17
+ static loadSchema(xsdPath) {
18
+ if (schemaCache.has(xsdPath)) {
19
+ return schemaCache.get(xsdPath);
20
+ }
21
+
22
+ if (!fs.existsSync(xsdPath)) {
23
+ throw new GhinfeError(
24
+ `Schema XSD não encontrado: ${xsdPath}. Execute: node scripts/download-schemas.js`,
25
+ 'XSD_SCHEMA_NOT_FOUND'
26
+ );
27
+ }
28
+
29
+ const dir = path.dirname(xsdPath);
30
+ const baseUrl = pathToFileURL(dir + path.sep).href;
31
+ const content = fs.readFileSync(xsdPath, 'utf8');
32
+ const schema = libxmljs.parseXml(content, { baseUrl });
33
+
34
+ schemaCache.set(xsdPath, schema);
35
+ return schema;
36
+ }
37
+
38
+ /**
39
+ * Valida XML contra schema XSD.
40
+ * @param {string} xml
41
+ * @param {string} xsdPath
42
+ * @param {{ injetarAssinaturaStub?: boolean, modelo?: '55'|'65'|'99' }} [options]
43
+ * @returns {{ valido: true, avisos: string[] }}
44
+ */
45
+ static validar(xml, xsdPath, options = {}) {
46
+ let xmlParaValidar = xml;
47
+
48
+ if (options.modelo === '99') {
49
+ xmlParaValidar = this.#compatibilizarDCe(xmlParaValidar);
50
+ }
51
+
52
+ if (options.injetarAssinaturaStub) {
53
+ xmlParaValidar = this.#prepararXmlEstrutural(xmlParaValidar, options.modelo ?? '55');
54
+ }
55
+
56
+ const schema = this.loadSchema(xsdPath);
57
+ const doc = libxmljs.parseXml(xmlParaValidar);
58
+
59
+ const valido = doc.validate(schema);
60
+ if (valido) {
61
+ return { valido: true, avisos: [] };
62
+ }
63
+
64
+ const erros = doc.validationErrors.map((e) => e.message).filter(Boolean);
65
+ throw new XsdValidationError(erros, path.basename(xsdPath));
66
+ }
67
+
68
+ /**
69
+ * Valida e retorna boolean (sem lançar exceção).
70
+ * @param {string} xml
71
+ * @param {string} xsdPath
72
+ * @param {object} [options]
73
+ */
74
+ static tentarValidar(xml, xsdPath, options = {}) {
75
+ try {
76
+ return this.validar(xml, xsdPath, options);
77
+ } catch (error) {
78
+ if (error instanceof XsdValidationError) {
79
+ return { valido: false, erros: error.erros };
80
+ }
81
+ throw error;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * O XSD da DC-e exige infSolicDCe, mas o grupo é exclusivo do Fisco (tpEmit=0):
87
+ * informá-lo nos demais casos gera rejeição 229. Para validar a estrutura sem
88
+ * enviar o grupo, injeta-se um infSolicDCe vazio apenas na cópia validada.
89
+ * @param {string} xml
90
+ */
91
+ static #compatibilizarDCe(xml) {
92
+ if (xml.includes('<infSolicDCe>')) return xml;
93
+ return xml.replace('</infDCe>', '</infDCe><infSolicDCe><xSolic></xSolic></infSolicDCe>');
94
+ }
95
+
96
+ /**
97
+ * Injeta elementos exigidos pelo XSD para validação estrutural pré-assinatura.
98
+ * O schema exige Signature (NF-e/DC-e) ou infNFeSupl + Signature (NFC-e).
99
+ * @param {string} xml
100
+ * @param {'55'|'65'|'99'} modelo
101
+ */
102
+ static #prepararXmlEstrutural(xml, modelo) {
103
+ if (xml.includes('</Signature>')) return xml;
104
+
105
+ const idMatch = xml.match(/Id="((?:NFe|DCe)\d{44})"/);
106
+ const id = idMatch?.[1];
107
+ if (!id) return xml;
108
+
109
+ if (modelo === '99') {
110
+ return xml.replace('</DCe>', `${this.#assinaturaStub(id)}</DCe>`);
111
+ }
112
+
113
+ let complemento = '';
114
+
115
+ if (modelo === '65' && !xml.includes('infNFeSupl')) {
116
+ const qrStub = 'https://nfce.sefaz.example/qr?p=STUB';
117
+ complemento += `<infNFeSupl><qrCode><![CDATA[${qrStub}]]></qrCode><urlChave>${qrStub}</urlChave></infNFeSupl>`;
118
+ }
119
+
120
+ complemento += this.#assinaturaStub(id);
121
+ return xml.replace('</NFe>', `${complemento}</NFe>`);
122
+ }
123
+
124
+ /** @param {string} id */
125
+ static #assinaturaStub(id) {
126
+ return `<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="#${id}"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>WCF0TVY=</DigestValue></Reference></SignedInfo><SignatureValue>WCF0TVY=</SignatureValue><KeyInfo><X509Data><X509Certificate>WCF0TVY=</X509Certificate></X509Data></KeyInfo></Signature>`;
127
+ }
128
+
129
+ /** Limpa cache de schemas (útil em testes). */
130
+ static limparCache() {
131
+ schemaCache.clear();
132
+ }
133
+ }
@@ -1,14 +1,18 @@
1
- import path from 'path';
2
- import { fileURLToPath } from 'url';
3
-
4
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const SCHEMAS_ROOT = path.resolve(__dirname, '../../schemas');
6
-
7
- /** Caminhos dos schemas XSD oficiais (PL_009_V4 — NF-e/NFC-e 4.00). */
8
- export const XSD_SCHEMAS = {
9
- NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/nfe_v4.00.xsd'),
10
- ENVI_NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/enviNFe_v4.00.xsd'),
11
- EVENTO: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/leiauteNFe_v4.00.xsd'),
12
- };
13
-
14
- export const SCHEMAS_ROOT_PATH = SCHEMAS_ROOT;
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+
4
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
+ const SCHEMAS_ROOT = path.resolve(__dirname, '../../schemas');
6
+
7
+ /** Caminhos dos schemas XSD oficiais (NF-e/NFC-e PL_009_V4 e DC-e PL_DCe_v1.00a + NT 2024.001). */
8
+ export const XSD_SCHEMAS = {
9
+ NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/nfe_v4.00.xsd'),
10
+ ENVI_NFE: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/enviNFe_v4.00.xsd'),
11
+ EVENTO: path.join(SCHEMAS_ROOT, 'nfe/PL_009_V4/leiauteNFe_v4.00.xsd'),
12
+ DCE: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/dce_v1.00.xsd'),
13
+ DCE_PROC: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/procDCe_v1.00.xsd'),
14
+ DCE_EVENTO: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/evento/eventoDCe_v1.00.xsd'),
15
+ DCE_EVENTO_CANCELAMENTO: path.join(SCHEMAS_ROOT, 'dce/PL_DCe_100a_NT2024.001/evento/evCancDCe_v1.00.xsd'),
16
+ };
17
+
18
+ export const SCHEMAS_ROOT_PATH = SCHEMAS_ROOT;