cosmemilton-acbr-node 0.1.0 → 0.1.1
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/dist/cli.js +330 -60
- package/dist/cli.js.map +3 -3
- package/dist/index.cjs +320 -46
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +317 -46
- package/dist/index.js.map +4 -4
- package/dist/runtime.cjs +254 -35
- package/dist/runtime.cjs.map +3 -3
- package/dist/runtime.js +251 -34
- package/dist/runtime.js.map +3 -3
- package/dist/types/generated/acbr/index.d.ts +15 -1
- package/dist/types/generated/acbr/models.d.ts +32 -0
- package/dist/types/src/diagnostics.d.ts +8 -0
- package/dist/types/src/generator.d.ts +1 -0
- package/dist/types/src/index.d.ts +13 -0
- package/dist/types/src/runtime.d.ts +1 -0
- package/dist/types/src/types.d.ts +34 -1
- package/docs/API.md +90 -32
- package/docs/CI.md +6 -0
- package/docs/VALIDACAO.md +3 -1
- package/package.json +3 -3
package/dist/runtime.cjs
CHANGED
|
@@ -32,7 +32,9 @@ var runtime_exports = {};
|
|
|
32
32
|
__export(runtime_exports, {
|
|
33
33
|
ErroAcbrNode: () => ErroAcbrNode,
|
|
34
34
|
PROTOCOL_VERSION: () => PROTOCOL_VERSION,
|
|
35
|
-
criarEmissor: () => criarEmissor
|
|
35
|
+
criarEmissor: () => criarEmissor,
|
|
36
|
+
diagnosticarErro: () => diagnosticarErro,
|
|
37
|
+
diagnosticarResultado: () => diagnosticarResultado
|
|
36
38
|
});
|
|
37
39
|
module.exports = __toCommonJS(runtime_exports);
|
|
38
40
|
var import_node_child_process = require("node:child_process");
|
|
@@ -42,16 +44,149 @@ var import_node_module = require("node:module");
|
|
|
42
44
|
var import_node_crypto = require("node:crypto");
|
|
43
45
|
var import_node_util = require("node:util");
|
|
44
46
|
|
|
47
|
+
// src/diagnostics.ts
|
|
48
|
+
var ETAPAS = /* @__PURE__ */ new Set(["configuracao", "documento", "runtime", "geracao", "validacao", "assinatura", "transmissao", "consulta", "cancelamento", "carta_correcao", "inutilizacao", "operacao", "limpeza"]);
|
|
49
|
+
var CAMPOS = /* @__PURE__ */ new Set(["cnpj", "uf", "modelo", "ambiente", "contrato", "certificado", "certificado.senha", "certificado.pfx", "certificado.arquivo", "csc", "csc.id", "csc.valor", "timeoutMs", "limiteFila", "limiteBytes", "runtimeDirectory", "documento", "xml", "consulta", "chave", "recibo", "cancelamento", "protocolo", "justificativa", "cartaCorrecao", "correcao", "sequenciaEvento", "inutilizacao", "ano", "serie", "numeroInicial", "numeroFinal", "operacao", "signal"]);
|
|
50
|
+
var CATALOGO = {
|
|
51
|
+
CONFIGURACAO_INVALIDA: ["configuracao", "A configura\xE7\xE3o cont\xE9m um campo inv\xE1lido.", "Confira o campo indicado e seu tipo antes de continuar."],
|
|
52
|
+
CONTRATO_INVALIDO: ["configuracao", "O contrato do cliente \xE9 inv\xE1lido.", "Use o contrato gerado junto com o cliente."],
|
|
53
|
+
CERTIFICADO_INVALIDO: ["configuracao", "O certificado A1 ou sua configura\xE7\xE3o \xE9 inv\xE1lido.", "Confira formato e validade do A1, pfx ou arquivo e a senha digitada, sem registrar esses dados."],
|
|
54
|
+
CERTIFICADO_DIVERGENTE: ["assinatura", "O certificado n\xE3o corresponde \xE0 raiz CNPJ do emitente.", "Confira o CNPJ configurado e selecione o A1 correspondente ao emitente."],
|
|
55
|
+
DEPENDENCIA_AUSENTE: ["runtime", "Uma depend\xEAncia do motor fiscal n\xE3o est\xE1 dispon\xEDvel.", "Reinstale o runtime completo da plataforma; confira a disponibilidade do OpenSSL distribu\xEDdo."],
|
|
56
|
+
SCHEMAS_AUSENTES: ["runtime", "Os schemas fiscais n\xE3o est\xE3o dispon\xEDveis.", "Reinstale o runtime completo da plataforma."],
|
|
57
|
+
SERVICOS_AUSENTES: ["runtime", "A configura\xE7\xE3o dos servi\xE7os fiscais n\xE3o est\xE1 dispon\xEDvel.", "Reinstale o runtime completo da plataforma."],
|
|
58
|
+
CSC_AUSENTE: ["configuracao", "A opera\xE7\xE3o de NFC-e exige CSC.", "Informe id e valor do CSC na configura\xE7\xE3o sem registrar seu conte\xFAdo."],
|
|
59
|
+
IDENTIDADE_DIVERGENTE: ["documento", "A identidade fiscal n\xE3o corresponde \xE0 configura\xE7\xE3o ou ao retorno.", "Confira emitente, UF, modelo, ambiente e chave do documento antes de continuar."],
|
|
60
|
+
XML_SCHEMA_INVALIDO: ["validacao", "O XML n\xE3o atende aos schemas fiscais.", "Confira os campos obrigat\xF3rios e os tributos; a valida\xE7\xE3o de XML assinado deve ocorrer ap\xF3s a assinatura."],
|
|
61
|
+
ASSINATURA_INVALIDA: ["assinatura", "A assinatura do XML n\xE3o foi validada.", "Confira o A1 correspondente e use o XML assinado sem altera\xE7\xF5es."],
|
|
62
|
+
XML_NAO_ASSINADO: ["assinatura", "A opera\xE7\xE3o exige XML previamente assinado.", "Conclua a assinatura e a valida\xE7\xE3o antes de transmitir."],
|
|
63
|
+
XML_ALTERADO: ["assinatura", "O XML assinado foi alterado.", "Use exatamente o XML assinado e persistido; n\xE3o edite seu conte\xFAdo."],
|
|
64
|
+
RETORNO_INVALIDO: ["transmissao", "A identidade ou o protocolo do retorno fiscal \xE9 inv\xE1lido.", "Consulte a situa\xE7\xE3o fiscal antes de decidir repetir a opera\xE7\xE3o."],
|
|
65
|
+
OPERACAO_FISCAL_FALHOU: ["operacao", "O motor n\xE3o conseguiu concluir a etapa fiscal.", "Confira a configura\xE7\xE3o da etapa, os dados do XML e as depend\xEAncias do runtime."],
|
|
66
|
+
TLS_SERVIDOR_INVALIDO: ["transmissao", "A verifica\xE7\xE3o TLS do servi\xE7o fiscal falhou.", "Confira o servi\xE7o e a cadeia de confian\xE7a; mantenha a verifica\xE7\xE3o TLS habilitada."],
|
|
67
|
+
CSC_INVALIDO: ["configuracao", "A configura\xE7\xE3o do CSC \xE9 inv\xE1lida.", "Confira id e valor do CSC sem registrar seu conte\xFAdo."],
|
|
68
|
+
PLATAFORMA_NAO_SUPORTADA: ["runtime", "A plataforma n\xE3o \xE9 suportada.", "Execute em Windows ou Linux x64 com Node.js 22.12 ou superior."],
|
|
69
|
+
RUNTIME_AUSENTE: ["runtime", "O motor fiscal n\xE3o foi encontrado.", "Instale o runtime da plataforma incluindo depend\xEAncias opcionais."],
|
|
70
|
+
RUNTIME_INVALIDO: ["runtime", "O runtime fiscal \xE9 inv\xE1lido.", "Use um runtime distribu\xEDdo e compat\xEDvel com a plataforma."],
|
|
71
|
+
RUNTIME_INCOMPLETO: ["runtime", "Falta um arquivo do runtime fiscal.", "Reinstale o runtime da plataforma."],
|
|
72
|
+
RUNTIME_ALTERADO: ["runtime", "A integridade do runtime fiscal n\xE3o foi confirmada.", "Reinstale o runtime; n\xE3o desative a verifica\xE7\xE3o dos hashes."],
|
|
73
|
+
CONTRATO_DIVERGENTE: ["runtime", "Cliente e motor usam contratos diferentes.", "Use vers\xF5es compat\xEDveis ou regenere e recompile ambos."],
|
|
74
|
+
DOCUMENTO_INVALIDO: ["documento", "O documento cont\xE9m dados incompat\xEDveis com o modelo.", "Valide os campos e tipos do documento antes de gerar o XML."],
|
|
75
|
+
OPERACAO_INVALIDA: ["operacao", "Os par\xE2metros da opera\xE7\xE3o s\xE3o inv\xE1lidos.", "Informe um objeto com os campos exigidos pela opera\xE7\xE3o."],
|
|
76
|
+
OPERACAO_CANCELADA: ["operacao", "A opera\xE7\xE3o foi cancelada.", "Confira o estado do envio antes de decidir continuar."],
|
|
77
|
+
TIMEOUT_MOTOR: ["runtime", "O motor excedeu o tempo de espera.", "Confira o estado do envio antes de repetir a opera\xE7\xE3o."],
|
|
78
|
+
EMISSOR_FECHADO: ["operacao", "O emissor foi encerrado.", "Crie um novo emissor para continuar."],
|
|
79
|
+
FALHA_INICIAR_MOTOR: ["runtime", "N\xE3o foi poss\xEDvel iniciar o motor fiscal.", "Confira a instala\xE7\xE3o e as permiss\xF5es de execu\xE7\xE3o do runtime."],
|
|
80
|
+
FALHA_PIPE: ["runtime", "A comunica\xE7\xE3o com o motor foi interrompida.", "Confira a instala\xE7\xE3o e o estado do envio antes de continuar."],
|
|
81
|
+
RESPOSTA_EXCESSIVA: ["runtime", "A resposta do motor excedeu o limite.", "Confira o tamanho da opera\xE7\xE3o e a vers\xE3o do runtime."],
|
|
82
|
+
RESPOSTA_INVALIDA: ["runtime", "O motor devolveu uma resposta inv\xE1lida.", "Confira a compatibilidade do runtime e o estado do envio."],
|
|
83
|
+
FALHA_MOTOR: ["runtime", "O motor encerrou sem uma resposta fiscal v\xE1lida.", "Confira a instala\xE7\xE3o e o estado do envio antes de continuar."],
|
|
84
|
+
CERTIFICADO_AUSENTE: ["configuracao", "O certificado A1 n\xE3o est\xE1 dispon\xEDvel para esta opera\xE7\xE3o.", "Configure um A1 acess\xEDvel e sua senha sem registrar esses dados."],
|
|
85
|
+
CERTIFICADO_EXCESSIVO: ["configuracao", "O certificado excede o limite de tamanho.", "Use um arquivo A1 de at\xE9 2 MiB."],
|
|
86
|
+
REQUISICAO_INVALIDA: ["operacao", "Os dados n\xE3o puderam ser serializados ou excedem o limite.", "Use dados JSON e reduza o tamanho da opera\xE7\xE3o."],
|
|
87
|
+
FILA_CHEIA: ["operacao", "A fila fiscal est\xE1 cheia.", "Aguarde a opera\xE7\xE3o atual terminar antes de iniciar outra."],
|
|
88
|
+
XML_INVALIDO: ["documento", "O XML est\xE1 vazio, tem tipo inv\xE1lido ou excede o limite.", "Informe o XML como texto UTF-8 de at\xE9 2 MiB."],
|
|
89
|
+
CHAVE_INVALIDA: ["documento", "A chave fiscal tem formato inv\xE1lido.", "Informe a chave como texto com 44 d\xEDgitos."],
|
|
90
|
+
RECIBO_INVALIDO: ["documento", "O recibo tem formato inv\xE1lido.", "Informe o recibo como texto com 15 d\xEDgitos."],
|
|
91
|
+
JUSTIFICATIVA_INVALIDA: ["documento", "A justificativa tem tamanho inv\xE1lido.", "Informe uma justificativa com 15 a 255 caracteres."],
|
|
92
|
+
PROTOCOLO_INVALIDO: ["documento", "O protocolo tem formato inv\xE1lido.", "Informe o protocolo como texto com 15 d\xEDgitos."],
|
|
93
|
+
OPERACAO_NAO_SUPORTADA: ["operacao", "A opera\xE7\xE3o n\xE3o \xE9 suportada para este modelo.", "Carta de corre\xE7\xE3o exige NF-e modelo 55."],
|
|
94
|
+
CORRECAO_INVALIDA: ["documento", "Os dados da carta de corre\xE7\xE3o s\xE3o inv\xE1lidos.", "Confira a corre\xE7\xE3o de 15 a 1000 caracteres e a sequ\xEAncia de 1 a 20."],
|
|
95
|
+
INUTILIZACAO_INVALIDA: ["documento", "A faixa de inutiliza\xE7\xE3o \xE9 inv\xE1lida.", "Confira ano, s\xE9rie e n\xFAmeros inicial e final."],
|
|
96
|
+
FALHA_LOCAL: ["operacao", "N\xE3o foi poss\xEDvel concluir a opera\xE7\xE3o local.", "Confira a etapa e os tipos dos dados; n\xE3o registre o erro bruto."]
|
|
97
|
+
};
|
|
98
|
+
function etapaDaOperacao(comando) {
|
|
99
|
+
return { gerarXml: "geracao", validar: "validacao", assinar: "assinatura", transmitir: "transmissao", consultar: "consulta", cancelar: "cancelamento", cartaCorrecao: "carta_correcao", inutilizar: "inutilizacao" }[comando] ?? "operacao";
|
|
100
|
+
}
|
|
101
|
+
function criarDiagnosticoErro(codigo, desconhecido = false, detalhes = {}) {
|
|
102
|
+
const safeCode = Object.hasOwn(CATALOGO, codigo) ? codigo : "FALHA_LOCAL";
|
|
103
|
+
const [defaultStage, mensagem, defaultAction] = CATALOGO[safeCode];
|
|
104
|
+
const etapa = detalhes.etapa && ETAPAS.has(detalhes.etapa) ? detalhes.etapa : defaultStage;
|
|
105
|
+
const campo = detalhes.campo && CAMPOS.has(detalhes.campo) ? detalhes.campo : void 0;
|
|
106
|
+
const acoesConfig = { cnpj: "Informe o CNPJ como texto com 14 d\xEDgitos.", uf: "Informe a sigla da UF em letras mai\xFAsculas, por exemplo PE.", modelo: "Informe o n\xFAmero 55 para NF-e ou 65 para NFC-e, sem aspas.", ambiente: "Informe o n\xFAmero 2 para homologa\xE7\xE3o ou 1 para produ\xE7\xE3o, sem aspas.", timeoutMs: "Informe um n\xFAmero inteiro de 1 a 120000 milissegundos.", limiteFila: "Informe um n\xFAmero inteiro de 0 a 1000.", limiteBytes: "Informe um n\xFAmero inteiro de 256 a 8388608 bytes.", runtimeDirectory: "Informe o diret\xF3rio do runtime como texto n\xE3o vazio." };
|
|
107
|
+
const acao = safeCode === "CONFIGURACAO_INVALIDA" && campo && Object.hasOwn(acoesConfig, campo) ? acoesConfig[campo] : defaultAction;
|
|
108
|
+
const causa = Object.freeze({ codigo: safeCode, etapa, ...campo ? { campo } : {} });
|
|
109
|
+
return Object.freeze({
|
|
110
|
+
codigo: safeCode,
|
|
111
|
+
etapa,
|
|
112
|
+
...campo ? { campo } : {},
|
|
113
|
+
mensagem,
|
|
114
|
+
acao: desconhecido ? "Consulte a situa\xE7\xE3o fiscal antes de repetir. O envio pode ter ocorrido; n\xE3o retransmita automaticamente." : acao,
|
|
115
|
+
statusEnvio: desconhecido ? "resultado_incerto" : "nao_enviado",
|
|
116
|
+
causa
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function diagnosticarErro(erro) {
|
|
120
|
+
return erro instanceof ErroAcbrNode ? erro.diagnostico : criarDiagnosticoErro("FALHA_LOCAL", true);
|
|
121
|
+
}
|
|
122
|
+
function adicionarDiagnosticoLimpeza(diagnostico) {
|
|
123
|
+
const acao = diagnostico.statusEnvio === "resultado_incerto" ? "Encerre esta aplica\xE7\xE3o antes de iniciar outro motor e consulte a situa\xE7\xE3o fiscal antes de repetir qualquer envio." : "Encerre esta aplica\xE7\xE3o antes de iniciar outro motor. As pr\xF3ximas opera\xE7\xF5es deste emissor foram bloqueadas.";
|
|
124
|
+
const limpeza = Object.freeze({ codigo: "ENCERRAMENTO_MOTOR_NAO_CONFIRMADO", etapa: "limpeza", mensagem: "N\xE3o foi poss\xEDvel confirmar o encerramento do motor fiscal.", acao });
|
|
125
|
+
return Object.freeze({ ...diagnostico, acao, limpeza });
|
|
126
|
+
}
|
|
127
|
+
function diagnosticarResultado(resultado, comando) {
|
|
128
|
+
const etapa = etapaDaOperacao(comando);
|
|
129
|
+
if (!resultado || typeof resultado !== "object") return criarDiagnosticoErro("FALHA_LOCAL", true, { etapa });
|
|
130
|
+
if (resultado.envioIniciado !== void 0 && typeof resultado.envioIniciado !== "boolean") return criarDiagnosticoErro("RESPOSTA_INVALIDA", true, { etapa });
|
|
131
|
+
let statusEnvio = "resultado_incerto", codigo = "RESULTADO_INCERTO";
|
|
132
|
+
let mensagem = "A situa\xE7\xE3o fiscal ainda n\xE3o foi confirmada.";
|
|
133
|
+
let acao = "Consulte a situa\xE7\xE3o fiscal antes de repetir. N\xE3o retransmita automaticamente.";
|
|
134
|
+
const local = comando === "gerarXml" && resultado.estado === "XML_GERADO" || comando === "validar" && resultado.estado === "VALIDADO" || comando === "assinar" && resultado.estado === "ASSINADO";
|
|
135
|
+
const semEvento = resultado.envioIniciado === false || resultado.envioIniciado === void 0;
|
|
136
|
+
const protocolo = typeof resultado.protocolo === "string" && /^\d{15}$/.test(resultado.protocolo);
|
|
137
|
+
const chave = typeof resultado.chave === "string" && /^\d{44}$/.test(resultado.chave);
|
|
138
|
+
const autorizacao = (comando === "transmitir" || comando === "consultar") && resultado.estado === "AUTORIZADO" && [100, 150].includes(resultado.cStat) && protocolo && chave && (comando === "consultar" || resultado.envioIniciado !== false);
|
|
139
|
+
const evento = comando === "cancelar" && resultado.estado === "CANCELADO" && [135, 136].includes(resultado.cStat) && chave || comando === "cartaCorrecao" && resultado.estado === "EVENTO_REGISTRADO" && resultado.cStat === 135 && chave || comando === "inutilizar" && resultado.estado === "INUTILIZADO" && resultado.cStat === 102;
|
|
140
|
+
if (local && resultado.sucesso === true && semEvento) {
|
|
141
|
+
statusEnvio = "nao_enviado";
|
|
142
|
+
codigo = "ETAPA_LOCAL_CONCLUIDA";
|
|
143
|
+
mensagem = "A etapa local foi conclu\xEDda; esta opera\xE7\xE3o n\xE3o transmitiu a nota.";
|
|
144
|
+
acao = "Confira o resultado antes de seguir para a pr\xF3xima etapa.";
|
|
145
|
+
} else if (resultado.sucesso === true && (autorizacao || evento && protocolo && resultado.envioIniciado !== false)) {
|
|
146
|
+
statusEnvio = "autorizado";
|
|
147
|
+
codigo = "OPERACAO_CONFIRMADA";
|
|
148
|
+
mensagem = { AUTORIZADO: "A nota foi autorizada.", CANCELADO: "O cancelamento foi confirmado.", EVENTO_REGISTRADO: "O evento foi registrado.", INUTILIZADO: "A faixa foi inutilizada." }[resultado.estado];
|
|
149
|
+
acao = "Guarde o resultado fiscal. N\xE3o repita esta opera\xE7\xE3o.";
|
|
150
|
+
} else if (resultado.sucesso === false && (comando === "consultar" || resultado.envioIniciado !== false) && ["transmitir", "consultar", "cancelar", "cartaCorrecao", "inutilizar"].includes(comando) && Number.isInteger(resultado.cStat) && Number(resultado.cStat) > 0 && Number(resultado.cStat) <= 9999 && (resultado.estado === "DENEGADO" && [110, 301, 302].includes(resultado.cStat) || resultado.estado === "REJEITADO" && ![100, 150, 110, 301, 302, 101, 151, 155, 103, 104, 105, 108, 109, 204, 539, 573, 135, 136, 102, 217].includes(resultado.cStat))) {
|
|
151
|
+
statusEnvio = "rejeitado";
|
|
152
|
+
codigo = resultado.estado === "DENEGADO" ? "NOTA_DENEGADA" : "OPERACAO_REJEITADA";
|
|
153
|
+
mensagem = resultado.estado === "DENEGADO" ? "A nota foi denegada." : "A opera\xE7\xE3o foi rejeitada.";
|
|
154
|
+
acao = resultado.estado === "DENEGADO" ? "Consulte a situa\xE7\xE3o fiscal e a orienta\xE7\xE3o respons\xE1vel antes de usar a numera\xE7\xE3o." : "Confira o cStat e revise os dados antes de decidir uma nova tentativa.";
|
|
155
|
+
} else if (resultado.estado === "ERRO" && resultado.envioIniciado === false) {
|
|
156
|
+
if (typeof resultado.codigo === "string" && Object.hasOwn(CATALOGO, resultado.codigo)) return criarDiagnosticoErro(resultado.codigo, false, { etapa });
|
|
157
|
+
statusEnvio = "nao_enviado";
|
|
158
|
+
codigo = "FALHA_ANTES_ENVIO";
|
|
159
|
+
mensagem = "O motor informou falha antes de iniciar o envio desta opera\xE7\xE3o.";
|
|
160
|
+
acao = "Revise a configura\xE7\xE3o e os dados antes de continuar.";
|
|
161
|
+
}
|
|
162
|
+
const cStat = Number.isInteger(resultado.cStat) && Number(resultado.cStat) > 0 && Number(resultado.cStat) <= 9999 ? resultado.cStat : void 0;
|
|
163
|
+
return Object.freeze({ codigo, etapa, mensagem, acao, statusEnvio, ...cStat !== void 0 ? { cStat } : {} });
|
|
164
|
+
}
|
|
165
|
+
|
|
45
166
|
// src/types.ts
|
|
46
167
|
var PROTOCOL_VERSION = 1;
|
|
47
168
|
var ErroAcbrNode = class extends Error {
|
|
48
|
-
constructor(codigo, mensagem, resultadoDesconhecido = false, xmlBase64) {
|
|
169
|
+
constructor(codigo, mensagem, resultadoDesconhecido = false, xmlBase64, detalhes) {
|
|
49
170
|
super(mensagem);
|
|
50
171
|
this.codigo = codigo;
|
|
51
172
|
this.resultadoDesconhecido = resultadoDesconhecido;
|
|
52
173
|
this.xmlBase64 = xmlBase64;
|
|
174
|
+
this.#diagnostico = criarDiagnosticoErro(codigo, resultadoDesconhecido, detalhes);
|
|
175
|
+
Object.defineProperty(this, "xmlBase64", { value: xmlBase64, enumerable: false });
|
|
176
|
+
Object.defineProperty(this, "cause", { value: this.diagnostico.causa, enumerable: false });
|
|
53
177
|
}
|
|
54
178
|
name = "ErroAcbrNode";
|
|
179
|
+
#diagnostico;
|
|
180
|
+
get diagnostico() {
|
|
181
|
+
return this.#diagnostico;
|
|
182
|
+
}
|
|
183
|
+
/** Acrescenta apenas o aviso estático de limpeza, preservando o erro da operação. */
|
|
184
|
+
anotarFalhaLimpeza() {
|
|
185
|
+
this.#diagnostico = adicionarDiagnosticoLimpeza(this.#diagnostico);
|
|
186
|
+
}
|
|
187
|
+
toJSON() {
|
|
188
|
+
return this.diagnostico;
|
|
189
|
+
}
|
|
55
190
|
};
|
|
56
191
|
|
|
57
192
|
// src/runtime.ts
|
|
@@ -59,9 +194,10 @@ var import_meta = {};
|
|
|
59
194
|
var STATES = /* @__PURE__ */ new Set(["DENEGADO", "XML_GERADO", "VALIDADO", "ASSINADO", "AUTORIZADO", "REJEITADO", "PENDENTE", "INDETERMINADO", "CONSULTADO", "CANCELADO", "EVENTO_REGISTRADO", "INUTILIZADO", "ERRO"]);
|
|
60
195
|
var UFS = new Set("AC AL AP AM BA CE DF ES GO MA MT MS MG PA PB PR PE PI RJ RN RS RO RR SC SP SE TO".split(" "));
|
|
61
196
|
var MAX_BYTES = 8 * 1024 * 1024;
|
|
197
|
+
var MAX_TEARDOWN_MS = 1e3;
|
|
62
198
|
var plain = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
63
199
|
var validContract = (v) => plain(v) && Number.isInteger(v.sourceRevision) && Number(v.sourceRevision) > 0 && typeof v.contractHash === "string" && /^[a-f0-9]{64}$/.test(v.contractHash);
|
|
64
|
-
var fail = (code, message, req, unknown = false) => new ErroAcbrNode(code, message, unknown, req?.comando === "transmitir" ? req.xmlBase64 : void 0);
|
|
200
|
+
var fail = (code, message, req, unknown = false, detalhes) => new ErroAcbrNode(code, message, unknown, req?.comando === "transmitir" ? req.xmlBase64 : void 0, { ...req ? { etapa: etapaDaOperacao(req.comando) } : {}, ...detalhes });
|
|
65
201
|
function confined(root, relative) {
|
|
66
202
|
const file = import_node_path.default.resolve(root, relative), part = import_node_path.default.relative(root, file);
|
|
67
203
|
if (!relative || import_node_path.default.isAbsolute(relative) || part === ".." || part.startsWith(".." + import_node_path.default.sep)) throw fail("RUNTIME_INVALIDO", "Caminho inv\xE1lido no runtime.");
|
|
@@ -104,26 +240,48 @@ async function resolveRuntime(directory, contract) {
|
|
|
104
240
|
return { directory: root, executable: confined(root, m.executable) };
|
|
105
241
|
}
|
|
106
242
|
function criarEmissor(options) {
|
|
107
|
-
|
|
243
|
+
const configFail = (campo) => fail("CONFIGURACAO_INVALIDA", "Informe campos e tipos v\xE1lidos na configura\xE7\xE3o.", void 0, false, { etapa: "configuracao", campo });
|
|
244
|
+
if (!plain(options)) throw configFail();
|
|
245
|
+
if (typeof options.cnpj !== "string" || !/^\d{14}$/.test(options.cnpj)) throw configFail("cnpj");
|
|
246
|
+
if (typeof options.uf !== "string" || !UFS.has(options.uf)) throw configFail("uf");
|
|
247
|
+
if (![55, 65].includes(options.modelo)) throw configFail("modelo");
|
|
248
|
+
if (![1, 2].includes(options.ambiente)) throw configFail("ambiente");
|
|
108
249
|
if (!validContract(options.contrato)) throw fail("CONTRATO_INVALIDO", "Contrato gerado inv\xE1lido.");
|
|
109
250
|
const cert = options.certificado;
|
|
110
|
-
if (cert && (typeof cert.senha !== "string" || !!cert.pfx === !!cert.arquivo || cert.pfx && !(cert.pfx instanceof Uint8Array))) throw fail("CERTIFICADO_INVALIDO", "Informe A1 em pfx ou arquivo e sua senha.");
|
|
111
|
-
if (options.csc && (!/^\d{1,6}$/.test(options.csc.id) || typeof options.csc.valor !== "string" || !options.csc.valor || options.csc.valor.length > 256)) throw fail("CSC_INVALIDO", "CSC inv\xE1lido.");
|
|
251
|
+
if (cert !== void 0 && (!plain(cert) || typeof cert.senha !== "string" || !!cert.pfx === !!cert.arquivo || cert.pfx !== void 0 && !(cert.pfx instanceof Uint8Array) || cert.arquivo !== void 0 && (typeof cert.arquivo !== "string" || !cert.arquivo))) throw fail("CERTIFICADO_INVALIDO", "Informe A1 em pfx ou arquivo e sua senha.", void 0, false, { campo: "certificado" });
|
|
252
|
+
if (options.csc !== void 0 && (!plain(options.csc) || typeof options.csc.id !== "string" || !/^\d{1,6}$/.test(options.csc.id) || typeof options.csc.valor !== "string" || !options.csc.valor || options.csc.valor.length > 256)) throw fail("CSC_INVALIDO", "CSC inv\xE1lido.", void 0, false, { campo: "csc" });
|
|
253
|
+
if (options.runtimeDirectory !== void 0 && (typeof options.runtimeDirectory !== "string" || !options.runtimeDirectory)) throw configFail("runtimeDirectory");
|
|
254
|
+
if (options.validaDocumento !== void 0 && typeof options.validaDocumento !== "function" || options.criaProcesso !== void 0 && typeof options.criaProcesso !== "function") throw configFail();
|
|
112
255
|
const cfg = { cnpj: options.cnpj, uf: options.uf, modelo: options.modelo, ambiente: options.ambiente, csc: options.csc ? { ...options.csc } : void 0 };
|
|
113
256
|
const certificate = cert ? { ...cert, pfx: cert.pfx ? Buffer.from(cert.pfx) : void 0 } : void 0;
|
|
114
257
|
const contract = { ...options.contrato };
|
|
115
258
|
const timeout = options.timeoutMs ?? 12e4, capacity = options.limiteFila ?? 32, bytesLimit = options.limiteBytes ?? MAX_BYTES;
|
|
116
|
-
if (!Number.isInteger(timeout) || timeout < 1 || timeout > 12e4
|
|
259
|
+
if (!Number.isInteger(timeout) || timeout < 1 || timeout > 12e4) throw configFail("timeoutMs");
|
|
260
|
+
if (!Number.isInteger(capacity) || capacity < 0 || capacity > 1e3) throw configFail("limiteFila");
|
|
261
|
+
if (!Number.isInteger(bytesLimit) || bytesLimit < 256 || bytesLimit > MAX_BYTES) throw configFail("limiteBytes");
|
|
117
262
|
const launch = options.criaProcesso ?? ((exe, args, config) => (0, import_node_child_process.spawn)(exe, args, { ...config, stdio: ["pipe", "pipe", "pipe"] }));
|
|
118
|
-
let runtimePromise, closed = false, current;
|
|
263
|
+
let runtimePromise, closed = false, teardownFailed = false, current;
|
|
119
264
|
const queue = [];
|
|
265
|
+
const closedError = () => {
|
|
266
|
+
const error = fail("EMISSOR_FECHADO", "Emissor encerrado.");
|
|
267
|
+
if (teardownFailed) error.anotarFalhaLimpeza();
|
|
268
|
+
return error;
|
|
269
|
+
};
|
|
270
|
+
const rejectQueue = () => {
|
|
271
|
+
for (const item of queue.splice(0)) {
|
|
272
|
+
item.signal?.removeEventListener("abort", item.abort);
|
|
273
|
+
item.bytes.fill(0);
|
|
274
|
+
item.reject(closedError());
|
|
275
|
+
}
|
|
276
|
+
};
|
|
120
277
|
async function execute(item) {
|
|
121
278
|
if (closed || item.signal?.aborted) throw fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
|
|
122
279
|
const runtime = await (runtimePromise ??= resolveRuntime(options.runtimeDirectory, contract));
|
|
123
280
|
if (closed || item.signal?.aborted) throw fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
|
|
124
|
-
await new Promise((done) => {
|
|
281
|
+
return await new Promise((done, rejectExecution) => {
|
|
125
282
|
let stopError;
|
|
126
283
|
let child, finished = false, started = false, sending = false, total = 0, rest = Buffer.alloc(0), result;
|
|
284
|
+
let teardownTimer;
|
|
127
285
|
let finishCurrent;
|
|
128
286
|
const doneCurrent = new Promise((r) => {
|
|
129
287
|
finishCurrent = r;
|
|
@@ -133,18 +291,54 @@ function criarEmissor(options) {
|
|
|
133
291
|
if (finished) return;
|
|
134
292
|
finished = true;
|
|
135
293
|
clearTimeout(timer);
|
|
294
|
+
clearTimeout(teardownTimer);
|
|
136
295
|
item.signal?.removeEventListener("abort", abort);
|
|
137
296
|
item.bytes.fill(0);
|
|
138
297
|
if (current?.done === doneCurrent) current = void 0;
|
|
139
298
|
finishCurrent();
|
|
140
|
-
error ?
|
|
141
|
-
|
|
299
|
+
error ? rejectExecution(error) : done(result);
|
|
300
|
+
};
|
|
301
|
+
const detachOwnedChild = () => {
|
|
302
|
+
for (const pipe of [child?.stdin, child?.stdout, child?.stderr]) {
|
|
303
|
+
try {
|
|
304
|
+
pipe?.destroy();
|
|
305
|
+
} catch {
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
pipe?.unref?.();
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
child?.unref();
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
const teardownFallback = () => {
|
|
318
|
+
if (finished) return;
|
|
319
|
+
stopError ??= fail("FALHA_MOTOR", "O motor n\xE3o foi encerrado.", item.req, uncertain());
|
|
320
|
+
stopError.anotarFalhaLimpeza();
|
|
321
|
+
teardownFailed = true;
|
|
322
|
+
closed = true;
|
|
323
|
+
rejectQueue();
|
|
324
|
+
certificate?.pfx?.fill(0);
|
|
325
|
+
finish(stopError);
|
|
326
|
+
detachOwnedChild();
|
|
142
327
|
};
|
|
143
328
|
const stop = (code, message) => {
|
|
144
329
|
if (finished || stopError) return;
|
|
145
330
|
stopError = fail(code, message, item.req, uncertain());
|
|
146
|
-
if (child?.pid)
|
|
147
|
-
|
|
331
|
+
if (!child?.pid) {
|
|
332
|
+
finish(stopError);
|
|
333
|
+
detachOwnedChild();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
teardownTimer = setTimeout(teardownFallback, MAX_TEARDOWN_MS);
|
|
337
|
+
try {
|
|
338
|
+
if (child.kill("SIGKILL") !== true) teardownFallback();
|
|
339
|
+
} catch {
|
|
340
|
+
teardownFallback();
|
|
341
|
+
}
|
|
148
342
|
};
|
|
149
343
|
const abort = () => stop("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada; confira a situa\xE7\xE3o fiscal quando o envio foi iniciado.");
|
|
150
344
|
const timer = setTimeout(() => stop("TIMEOUT_MOTOR", "O motor excedeu o prazo; consulte a situa\xE7\xE3o antes de transmitir novamente."), timeout);
|
|
@@ -171,8 +365,17 @@ function criarEmissor(options) {
|
|
|
171
365
|
child.on("spawn", () => {
|
|
172
366
|
started = true;
|
|
173
367
|
});
|
|
174
|
-
child.on("error", () =>
|
|
368
|
+
child.on("error", () => {
|
|
369
|
+
if (finished) return;
|
|
370
|
+
if (stopError) {
|
|
371
|
+
teardownFallback();
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
stop("FALHA_INICIAR_MOTOR", "N\xE3o foi poss\xEDvel iniciar o motor.");
|
|
375
|
+
});
|
|
175
376
|
child.stdin.on("error", () => stop("FALHA_PIPE", "N\xE3o foi poss\xEDvel comunicar com o motor."));
|
|
377
|
+
child.stdout.on("error", () => stop("FALHA_PIPE", "N\xE3o foi poss\xEDvel comunicar com o motor."));
|
|
378
|
+
child.stderr.on("error", () => stop("FALHA_PIPE", "N\xE3o foi poss\xEDvel comunicar com o motor."));
|
|
176
379
|
child.stderr.on("data", () => {
|
|
177
380
|
});
|
|
178
381
|
child.stdout.on("data", (chunk) => {
|
|
@@ -198,7 +401,9 @@ function criarEmissor(options) {
|
|
|
198
401
|
if (result || frame.versao !== 1 || frame.sourceRevision !== contract.sourceRevision || frame.contractHash !== contract.contractHash || typeof frame.sucesso !== "boolean" || !STATES.has(String(frame.estado))) throw Error();
|
|
199
402
|
if (frame.xmlBase64 !== void 0 && (typeof frame.xmlBase64 !== "string" || !frame.xmlBase64.length || Buffer.from(frame.xmlBase64, "base64").toString("base64") !== frame.xmlBase64)) throw Error();
|
|
200
403
|
if (frame.cStat !== void 0 && (!Number.isInteger(frame.cStat) || Number(frame.cStat) < 1 || Number(frame.cStat) > 9999)) throw Error();
|
|
201
|
-
|
|
404
|
+
if (frame.envioIniciado !== void 0 && typeof frame.envioIniciado !== "boolean" || sending && frame.envioIniciado === false) throw Error();
|
|
405
|
+
const fiscal = frame;
|
|
406
|
+
result = { ...fiscal, diagnostico: diagnosticarResultado(sending ? { ...fiscal, envioIniciado: true } : fiscal, item.req.comando) };
|
|
202
407
|
} catch {
|
|
203
408
|
stop("RESPOSTA_INVALIDA", "O motor retornou uma resposta inv\xE1lida.");
|
|
204
409
|
return;
|
|
@@ -229,7 +434,8 @@ function criarEmissor(options) {
|
|
|
229
434
|
busy = true;
|
|
230
435
|
item.signal?.removeEventListener("abort", item.abort);
|
|
231
436
|
try {
|
|
232
|
-
await execute(item);
|
|
437
|
+
const result = await execute(item);
|
|
438
|
+
item.resolve(result);
|
|
233
439
|
} catch (e) {
|
|
234
440
|
item.bytes.fill(0);
|
|
235
441
|
item.reject(e);
|
|
@@ -239,7 +445,11 @@ function criarEmissor(options) {
|
|
|
239
445
|
}
|
|
240
446
|
}
|
|
241
447
|
async function request(command, data, operation = {}) {
|
|
242
|
-
|
|
448
|
+
const rawOperation = operation;
|
|
449
|
+
if (!plain(rawOperation)) throw fail("OPERACAO_INVALIDA", "Informe op\xE7\xF5es v\xE1lidas para a opera\xE7\xE3o.", void 0, false, { etapa: etapaDaOperacao(command), campo: "operacao" });
|
|
450
|
+
const signal = operation.signal;
|
|
451
|
+
if (signal !== void 0 && (!plain(signal) || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function" || typeof signal.removeEventListener !== "function")) throw fail("OPERACAO_INVALIDA", "Informe op\xE7\xF5es v\xE1lidas para a opera\xE7\xE3o.", void 0, false, { etapa: etapaDaOperacao(command), campo: "signal" });
|
|
452
|
+
if (closed) throw closedError();
|
|
243
453
|
if (operation.signal?.aborted) throw fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
|
|
244
454
|
if (["assinar", "transmitir", "consultar", "cancelar", "cartaCorrecao", "inutilizar"].includes(command) && !certificate) throw fail("CERTIFICADO_AUSENTE", "A opera\xE7\xE3o exige um certificado A1.");
|
|
245
455
|
if (command === "gerarXml") options.validaDocumento?.(data.documento);
|
|
@@ -265,7 +475,7 @@ function criarEmissor(options) {
|
|
|
265
475
|
return new Promise((resolve, reject) => {
|
|
266
476
|
if (closed) {
|
|
267
477
|
bytes.fill(0);
|
|
268
|
-
reject(
|
|
478
|
+
reject(closedError());
|
|
269
479
|
return;
|
|
270
480
|
}
|
|
271
481
|
if (busy && queue.length >= capacity) {
|
|
@@ -290,14 +500,17 @@ function criarEmissor(options) {
|
|
|
290
500
|
});
|
|
291
501
|
}
|
|
292
502
|
const xmlData = (xml) => {
|
|
293
|
-
if (typeof xml !== "string" || !xml.trim() || Buffer.byteLength(xml, "utf8") > 2 * 1024 * 1024) throw fail("XML_INVALIDO", "XML vazio ou acima do limite.");
|
|
503
|
+
if (typeof xml !== "string" || !xml.trim() || Buffer.byteLength(xml, "utf8") > 2 * 1024 * 1024) throw fail("XML_INVALIDO", "XML vazio ou acima do limite.", void 0, false, { campo: "xml" });
|
|
294
504
|
return { xmlBase64: Buffer.from(xml, "utf8").toString("base64") };
|
|
295
505
|
};
|
|
296
506
|
const checkKey = (key) => {
|
|
297
|
-
if (!/^\d{44}$/.test(key)) throw fail("CHAVE_INVALIDA", "Chave fiscal inv\xE1lida.");
|
|
507
|
+
if (typeof key !== "string" || !/^\d{44}$/.test(key)) throw fail("CHAVE_INVALIDA", "Chave fiscal inv\xE1lida.", void 0, false, { campo: "chave" });
|
|
298
508
|
};
|
|
299
509
|
const reason = (value) => {
|
|
300
|
-
if (typeof value !== "string" || value.length < 15 || value.length > 255) throw fail("JUSTIFICATIVA_INVALIDA", "Justificativa deve ter de 15 a 255 caracteres.");
|
|
510
|
+
if (typeof value !== "string" || value.length < 15 || value.length > 255) throw fail("JUSTIFICATIVA_INVALIDA", "Justificativa deve ter de 15 a 255 caracteres.", void 0, false, { campo: "justificativa" });
|
|
511
|
+
};
|
|
512
|
+
const checkObject = (data, campo) => {
|
|
513
|
+
if (!plain(data)) throw fail("OPERACAO_INVALIDA", "Informe os par\xE2metros da opera\xE7\xE3o como objeto.", void 0, false, { campo });
|
|
301
514
|
};
|
|
302
515
|
return {
|
|
303
516
|
gerarXml: (documento, op) => request("gerarXml", { documento }, op),
|
|
@@ -305,39 +518,43 @@ function criarEmissor(options) {
|
|
|
305
518
|
assinar: (xml, op) => request("assinar", xmlData(xml), op),
|
|
306
519
|
transmitir: (xml, op) => request("transmitir", xmlData(xml), op),
|
|
307
520
|
consultar: (consulta, op) => {
|
|
521
|
+
checkObject(consulta, "consulta");
|
|
308
522
|
checkKey(consulta.chave);
|
|
309
|
-
if (consulta.recibo && !/^\d{15}$/.test(consulta.recibo)) throw fail("RECIBO_INVALIDO", "Recibo inv\xE1lido.");
|
|
523
|
+
if (consulta.recibo !== void 0 && (typeof consulta.recibo !== "string" || !/^\d{15}$/.test(consulta.recibo))) throw fail("RECIBO_INVALIDO", "Recibo inv\xE1lido.", void 0, false, { campo: "recibo" });
|
|
310
524
|
return request("consultar", consulta, op);
|
|
311
525
|
},
|
|
312
526
|
cancelar: (data, op) => {
|
|
527
|
+
checkObject(data, "cancelamento");
|
|
313
528
|
checkKey(data.chave);
|
|
314
529
|
reason(data.justificativa);
|
|
315
|
-
if (!/^\d{15}$/.test(data.protocolo)) throw fail("PROTOCOLO_INVALIDO", "Protocolo inv\xE1lido.");
|
|
530
|
+
if (typeof data.protocolo !== "string" || !/^\d{15}$/.test(data.protocolo)) throw fail("PROTOCOLO_INVALIDO", "Protocolo inv\xE1lido.", void 0, false, { campo: "protocolo" });
|
|
316
531
|
return request("cancelar", data, op);
|
|
317
532
|
},
|
|
318
533
|
cartaCorrecao: (data, op) => {
|
|
534
|
+
checkObject(data, "cartaCorrecao");
|
|
319
535
|
if (cfg.modelo !== 55) throw fail("OPERACAO_NAO_SUPORTADA", "Carta de corre\xE7\xE3o exige NF-e modelo 55.");
|
|
320
536
|
checkKey(data.chave);
|
|
321
|
-
if (typeof data.correcao !== "string" || data.correcao.length < 15 || data.correcao.length > 1e3 || !Number.isInteger(data.sequenciaEvento ?? 1) || (data.sequenciaEvento ?? 1) < 1 || (data.sequenciaEvento ?? 1) > 20) throw fail("CORRECAO_INVALIDA", "Dados da carta de corre\xE7\xE3o inv\xE1lidos.");
|
|
537
|
+
if (typeof data.correcao !== "string" || data.correcao.length < 15 || data.correcao.length > 1e3 || !Number.isInteger(data.sequenciaEvento ?? 1) || (data.sequenciaEvento ?? 1) < 1 || (data.sequenciaEvento ?? 1) > 20) throw fail("CORRECAO_INVALIDA", "Dados da carta de corre\xE7\xE3o inv\xE1lidos.", void 0, false, { campo: "cartaCorrecao" });
|
|
322
538
|
return request("cartaCorrecao", { ...data, sequenciaEvento: data.sequenciaEvento ?? 1 }, op);
|
|
323
539
|
},
|
|
324
540
|
inutilizar: (data, op) => {
|
|
541
|
+
checkObject(data, "inutilizacao");
|
|
325
542
|
reason(data.justificativa);
|
|
326
|
-
if (!Number.isInteger(data.ano) || data.ano < 0 || data.ano > 99 || !Number.isInteger(data.serie) || data.serie < 0 || data.serie > 999 || !Number.isInteger(data.numeroInicial) || data.numeroInicial < 1 || !Number.isInteger(data.numeroFinal) || data.numeroFinal < data.numeroInicial || data.numeroFinal > 999999999) throw fail("INUTILIZACAO_INVALIDA", "Faixa de inutiliza\xE7\xE3o inv\xE1lida.");
|
|
543
|
+
if (!Number.isInteger(data.ano) || data.ano < 0 || data.ano > 99 || !Number.isInteger(data.serie) || data.serie < 0 || data.serie > 999 || !Number.isInteger(data.numeroInicial) || data.numeroInicial < 1 || !Number.isInteger(data.numeroFinal) || data.numeroFinal < data.numeroInicial || data.numeroFinal > 999999999) throw fail("INUTILIZACAO_INVALIDA", "Faixa de inutiliza\xE7\xE3o inv\xE1lida.", void 0, false, { campo: "inutilizacao" });
|
|
327
544
|
return request("inutilizar", { inutilizacao: { ano: data.ano, serie: data.serie, numeroInicial: data.numeroInicial, numeroFinal: data.numeroFinal }, justificativa: data.justificativa }, op);
|
|
328
545
|
},
|
|
329
546
|
async fechar() {
|
|
330
|
-
if (closed)
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
item.signal?.removeEventListener("abort", item.abort);
|
|
334
|
-
item.bytes.fill(0);
|
|
335
|
-
item.reject(fail("EMISSOR_FECHADO", "Emissor encerrado."));
|
|
547
|
+
if (!closed) {
|
|
548
|
+
closed = true;
|
|
549
|
+
rejectQueue();
|
|
336
550
|
}
|
|
337
551
|
const running = current;
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
552
|
+
try {
|
|
553
|
+
running?.stop();
|
|
554
|
+
if (running) await running.done;
|
|
555
|
+
} finally {
|
|
556
|
+
certificate?.pfx?.fill(0);
|
|
557
|
+
}
|
|
341
558
|
}
|
|
342
559
|
};
|
|
343
560
|
}
|
|
@@ -345,6 +562,8 @@ function criarEmissor(options) {
|
|
|
345
562
|
0 && (module.exports = {
|
|
346
563
|
ErroAcbrNode,
|
|
347
564
|
PROTOCOL_VERSION,
|
|
348
|
-
criarEmissor
|
|
565
|
+
criarEmissor,
|
|
566
|
+
diagnosticarErro,
|
|
567
|
+
diagnosticarResultado
|
|
349
568
|
});
|
|
350
569
|
//# sourceMappingURL=runtime.cjs.map
|