cosmemilton-acbr-node 0.1.1 → 0.2.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.
Files changed (52) hide show
  1. package/LICENSE +502 -502
  2. package/NOTICE +8 -8
  3. package/README.md +137 -106
  4. package/acbr.config.json +16 -16
  5. package/acbr.lock.json +0 -0
  6. package/dist/cli.js +1345 -973
  7. package/dist/cli.js.map +4 -4
  8. package/dist/contract.json +1 -0
  9. package/dist/index.cjs +36 -11
  10. package/dist/index.cjs.map +2 -2
  11. package/dist/index.js +36 -11
  12. package/dist/index.js.map +2 -2
  13. package/dist/runtime.cjs +36 -11
  14. package/dist/runtime.cjs.map +2 -2
  15. package/dist/runtime.js +36 -11
  16. package/dist/runtime.js.map +2 -2
  17. package/dist/types/generated/acbr/index.d.ts +3 -2
  18. package/dist/types/generated/acbr/models.d.ts +0 -0
  19. package/dist/types/src/cli.d.ts +4 -2
  20. package/dist/types/src/config.d.ts +0 -0
  21. package/dist/types/src/contract-help.d.ts +53 -0
  22. package/dist/types/src/diagnostics.d.ts +2 -0
  23. package/dist/types/src/generator.d.ts +2 -0
  24. package/dist/types/src/index.d.ts +3 -2
  25. package/dist/types/src/native-build.d.ts +1 -0
  26. package/dist/types/src/offline-check.d.ts +0 -0
  27. package/dist/types/src/offline-fixture.d.ts +0 -0
  28. package/dist/types/src/runtime.d.ts +1 -0
  29. package/dist/types/src/source.d.ts +0 -0
  30. package/dist/types/src/types.d.ts +4 -2
  31. package/docs/API.md +26 -0
  32. package/docs/ARQUITETURA.md +19 -15
  33. package/docs/CI.md +60 -60
  34. package/docs/CLI.md +52 -32
  35. package/docs/DEPENDENCIAS-NATIVAS.md +93 -93
  36. package/docs/VALIDACAO.md +67 -67
  37. package/docs/examples/recuperar-xml.mjs +54 -0
  38. package/docs/licenses/fpc/COPYING.FPC +25 -25
  39. package/docs/licenses/fpc/COPYING.GPL.txt +340 -340
  40. package/docs/licenses/fpc/COPYING.LGPL.txt +504 -504
  41. package/docs/licenses/fpc/ORIGIN.json +21 -21
  42. package/docs/licenses/lazarus/COPYING.LGPL.txt +481 -481
  43. package/docs/licenses/lazarus/COPYING.modifiedLGPL.txt +26 -26
  44. package/docs/licenses/lazarus/COPYING.txt +46 -46
  45. package/docs/licenses/lazarus/ORIGIN.json +1 -1
  46. package/native/NativeMotor.pas +55 -3
  47. package/native/NativeProtocol.pas +3 -2
  48. package/native/NativeRecovery.pas +274 -0
  49. package/native/generated/AcbrModels.pas +0 -0
  50. package/package.json +76 -74
  51. package/scripts/build-native-deps.mjs +237 -237
  52. package/tools/extract-model.lpr +119 -119
package/dist/cli.js CHANGED
@@ -9,645 +9,266 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
- // src/generator.ts
13
- var generator_exports = {};
14
- __export(generator_exports, {
15
- buildModelIR: () => buildModelIR,
16
- compareContracts: () => compareContracts,
17
- generateModel: () => generateModel,
18
- renderClientIndex: () => renderClientIndex,
19
- renderModelValidation: () => renderModelValidation,
20
- renderPascal: () => renderPascal,
21
- renderTypeScript: () => renderTypeScript
12
+ // src/config.ts
13
+ var config_exports = {};
14
+ __export(config_exports, {
15
+ OFFICIAL_ACBR_URL: () => OFFICIAL_ACBR_URL,
16
+ SOURCE_PARTS: () => SOURCE_PARTS,
17
+ defaultConfig: () => defaultConfig,
18
+ initializeConfig: () => initializeConfig,
19
+ loadConfig: () => loadConfig,
20
+ parseConfig: () => parseConfig
22
21
  });
23
- import { createHash as createHash3 } from "node:crypto";
24
- import { execFile } from "node:child_process";
25
- import { promisify } from "node:util";
26
- import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4, readdir as readdir4 } from "node:fs/promises";
27
- import path2 from "node:path";
28
- import { fileURLToPath as fileURLToPath2 } from "node:url";
29
- function buildModelIR(raw) {
30
- const declarations = /* @__PURE__ */ new Map();
31
- for (const unit of raw.units) for (const type of unit.types) declarations.set((unit.name + "." + type.name).toLowerCase(), { unit, type });
32
- function find(name, unit) {
33
- for (const key of [unit.name + "." + name, ...[...unit.uses].reverse().map((u) => u + "." + name), name]) {
34
- const item = declarations.get(key.toLowerCase());
35
- if (item) return item;
36
- }
37
- throw new Error("Tipo Pascal n\xE3o resolvido: " + unit.name + "." + name);
22
+ import { readFile as readFile2, writeFile, mkdir, readdir, access } from "node:fs/promises";
23
+ import { dirname, isAbsolute, resolve } from "node:path";
24
+ function defaultConfig() {
25
+ return structuredClone(DEFAULT);
26
+ }
27
+ function record(value, name) {
28
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${name} deve ser um objeto.`);
29
+ return value;
30
+ }
31
+ function keys(value, allowed, name) {
32
+ const unexpected = Object.keys(value).filter((key) => !allowed.includes(key));
33
+ if (unexpected.length) throw new Error(`Campo desconhecido em ${name}: ${unexpected.join(", ")}.`);
34
+ }
35
+ function string(value, name) {
36
+ if (typeof value !== "string" || !value.trim() || value.includes("\0")) throw new Error(`${name} deve ser um texto n\xE3o vazio.`);
37
+ return value;
38
+ }
39
+ function parseConfig(input, configPath) {
40
+ const root = record(input, "configura\xE7\xE3o");
41
+ keys(root, ["formatVersion", "source", "generator", "native"], "configura\xE7\xE3o");
42
+ if (root.formatVersion !== 1) throw new Error("formatVersion deve ser 1.");
43
+ const source = record(root.source, "source");
44
+ keys(source, ["url", "revision", "directory"], "source");
45
+ const generator = record(root.generator, "generator");
46
+ keys(generator, ["outputDir"], "generator");
47
+ const native = record(root.native, "native");
48
+ keys(native, ["project", "outputDir", "fpc", "lazarusRoot", "libraryFiles", "providerFiles"], "native");
49
+ const url = string(source.url, "source.url").replace(/\/+$/, "");
50
+ if (url !== OFFICIAL_ACBR_URL) throw new Error(`source.url deve apontar ao reposit\xF3rio oficial ${OFFICIAL_ACBR_URL}.`);
51
+ const revision2 = source.revision;
52
+ if (revision2 !== "HEAD" && (!Number.isSafeInteger(revision2) || Number(revision2) < 1)) throw new Error("source.revision deve ser HEAD ou uma revis\xE3o SVN positiva.");
53
+ const absoluteConfig = resolve(configPath);
54
+ const projectRoot = dirname(absoluteConfig);
55
+ const localPath = (value, label) => resolve(projectRoot, string(value, label));
56
+ const fpcInput = string(native.fpc, "native.fpc");
57
+ const fpc = isAbsolute(fpcInput) || /[\\/]/.test(fpcInput) ? resolve(projectRoot, fpcInput) : fpcInput;
58
+ let libraryFiles;
59
+ if (native.libraryFiles !== void 0) {
60
+ if (!Array.isArray(native.libraryFiles)) throw new Error("native.libraryFiles deve ser uma lista de caminhos.");
61
+ libraryFiles = native.libraryFiles.map((item, i) => localPath(item, `native.libraryFiles[${i}]`));
38
62
  }
39
- function resolve5(name, unit, trail = /* @__PURE__ */ new Set()) {
40
- if (primitives[name.toLowerCase()]) return { primitive: name.toLowerCase() };
41
- const found = find(name, unit), key = (found.unit.name + "." + found.type.name).toLowerCase();
42
- if (trail.has(key)) throw new Error("Alias Pascal c\xEDclico: " + key);
43
- if (found.type.kind === "alias") {
44
- trail.add(key);
45
- return resolve5(found.type.target, found.unit, trail);
46
- }
47
- return found;
63
+ let providerFiles;
64
+ if (native.providerFiles !== void 0) {
65
+ if (!Array.isArray(native.providerFiles)) throw new Error("native.providerFiles deve ser uma lista de caminhos.");
66
+ providerFiles = native.providerFiles.map((item, i) => localPath(item, `native.providerFiles[${i}]`));
48
67
  }
49
- const rootUnit = raw.units.find((u) => u.types.some((t) => t.name === raw.root));
50
- if (!rootUnit) throw new Error("Modelo raiz ausente: " + raw.root);
51
- const generated = /* @__PURE__ */ new Map();
52
- function visit(name, unit) {
53
- const found = resolve5(name, unit);
54
- if ("primitive" in found) return primitives[found.primitive];
55
- const { type, unit: declUnit } = found, key = type.name;
56
- if (generated.has(key)) {
57
- const node2 = generated.get(key);
58
- if (node2.unit !== declUnit.name) throw new Error("Tipos hom\xF4nimos incompat\xEDveis: " + key);
59
- return { kind: node2.kind === "object" ? "object" : node2.kind === "list" ? "list" : "enum", ref: key };
60
- }
61
- if (type.kind === "enum") {
62
- const values = type.values.map((v) => v.name);
63
- if (!values.length) throw new Error("Enum sem valores: " + key);
64
- generated.set(key, { name: key, unit: declUnit.name, kind: "enum", values });
65
- return { kind: "enum", ref: key };
68
+ return {
69
+ formatVersion: 1,
70
+ configPath: absoluteConfig,
71
+ projectRoot,
72
+ lockPath: resolve(projectRoot, "acbr.lock.json"),
73
+ source: { url, revision: revision2, directory: localPath(source.directory, "source.directory") },
74
+ generator: { outputDir: localPath(generator.outputDir, "generator.outputDir") },
75
+ native: {
76
+ project: localPath(native.project, "native.project"),
77
+ outputDir: localPath(native.outputDir, "native.outputDir"),
78
+ fpc,
79
+ ...native.lazarusRoot !== void 0 ? { lazarusRoot: localPath(native.lazarusRoot, "native.lazarusRoot") } : {},
80
+ ...libraryFiles !== void 0 ? { libraryFiles } : {},
81
+ ...providerFiles !== void 0 ? { providerFiles } : {}
66
82
  }
67
- if (type.kind !== "class") throw new Error("Declara\xE7\xE3o Pascal n\xE3o suportada: " + declUnit.name + "." + key + " (" + (type.declarationKind ?? type.kind) + ")");
68
- const creator = type.methods?.find((m) => m.name.toLowerCase() === "new" && m.arguments === 0);
69
- const indexed = type.properties?.find((p) => p.indexed && p.name.toLowerCase() === "items");
70
- if (creator || indexed) {
71
- if (!creator || !indexed || !indexed.readable) throw new Error("Cole\xE7\xE3o sem contrato New/Items tipado: " + key);
72
- const item = resolve5(creator.result, declUnit), itemProperty = resolve5(indexed.type, declUnit);
73
- if ("primitive" in item || "primitive" in itemProperty || item.type.name !== itemProperty.type.name) throw new Error("Cole\xE7\xE3o com tipos New/Items divergentes: " + key);
74
- generated.set(key, { name: key, unit: declUnit.name, kind: "list", item: item.type.name, factory: creator.name });
75
- if (visit(creator.result, declUnit).kind !== "object") throw new Error("Item de cole\xE7\xE3o n\xE3o \xE9 objeto: " + key);
76
- return { kind: "list", ref: key };
83
+ };
84
+ }
85
+ async function loadConfig(path4 = "acbr.config.json") {
86
+ const configPath = resolve(path4);
87
+ let contents;
88
+ try {
89
+ contents = await readFile2(configPath, "utf8");
90
+ } catch (error) {
91
+ throw new Error(`N\xE3o foi poss\xEDvel ler ${configPath}. Execute acbr-node init.`, { cause: error });
92
+ }
93
+ let value;
94
+ try {
95
+ value = JSON.parse(contents);
96
+ } catch (error) {
97
+ throw new Error(`JSON inv\xE1lido em ${configPath}.`, { cause: error });
98
+ }
99
+ return parseConfig(value, configPath);
100
+ }
101
+ async function initializeConfig(path4 = "acbr.config.json", revision2 = "HEAD", assetRoot) {
102
+ const configPath = resolve(path4);
103
+ const config = defaultConfig();
104
+ config.source.revision = revision2;
105
+ parseConfig(config, configPath);
106
+ await mkdir(dirname(configPath), { recursive: true });
107
+ try {
108
+ await access(configPath);
109
+ throw Object.assign(new Error(`EEXIST: configura\xE7\xE3o j\xE1 existe: ${configPath}`), { code: "EEXIST" });
110
+ } catch (error) {
111
+ if (error.code !== "ENOENT") throw error;
112
+ }
113
+ const resolved = parseConfig(config, configPath);
114
+ if (assetRoot) await copyInitAssets(assetRoot, resolved.projectRoot);
115
+ await writeFile(configPath, `${JSON.stringify(config, null, 2)}
116
+ `, { flag: "wx" });
117
+ await mkdir(resolve(resolved.projectRoot, ".acbr/generated"), { recursive: true });
118
+ await mkdir(resolve(resolved.projectRoot, "generated/acbr"), { recursive: true });
119
+ return resolved;
120
+ }
121
+ async function copyInitAssets(assetRoot, targetRoot) {
122
+ const entries = [];
123
+ async function scan(current, target) {
124
+ for (const entry of await readdir(current, { withFileTypes: true })) {
125
+ if (entry.name === "generated" || entry.name.startsWith(".")) continue;
126
+ const source = resolve(current, entry.name);
127
+ const destination = resolve(target, entry.name);
128
+ if (entry.isDirectory()) await scan(source, destination);
129
+ else if (entry.isFile() && /\.(pas|lpr|inc|lpi)$/i.test(entry.name)) entries.push({ source, destination, content: await readFile2(source) });
77
130
  }
78
- const node = { name: key, unit: declUnit.name, kind: "object", properties: [] };
79
- generated.set(key, node);
80
- let inherited = [];
81
- if (type.ancestor && !bases.has(type.ancestor.toLowerCase())) {
82
- const ancestor = visit(type.ancestor, declUnit);
83
- if (ancestor.kind !== "object") throw new Error("Heran\xE7a n\xE3o suportada: " + key);
84
- inherited = generated.get(ancestor.ref).properties;
131
+ }
132
+ await scan(resolve(assetRoot, "native"), resolve(targetRoot, "native"));
133
+ if (!entries.some((entry) => entry.source.endsWith("acbr-worker.lpr"))) throw new Error("Assets do pacote n\xE3o cont\xEAm native/acbr-worker.lpr.");
134
+ entries.push({ source: resolve(assetRoot, "tools/extract-model.lpr"), destination: resolve(targetRoot, "tools/extract-model.lpr"), content: await readFile2(resolve(assetRoot, "tools/extract-model.lpr")) });
135
+ for (const entry of entries) {
136
+ try {
137
+ const existing = await readFile2(entry.destination);
138
+ if (!existing.equals(entry.content)) throw new Error(`init preservou arquivo existente divergente: ${entry.destination}.`);
139
+ } catch (error) {
140
+ if (error.code !== "ENOENT") throw error;
85
141
  }
86
- const props = new Map(inherited.map((p) => [p.name.toLowerCase(), p]));
87
- for (const p of type.properties ?? []) {
88
- if (p.indexed) throw new Error("Propriedade indexada fora de cole\xE7\xE3o: " + key + "." + p.name);
89
- if (!p.readable) throw new Error("Propriedade sem leitura: " + key + "." + p.name);
90
- const resolved = visit(p.type, declUnit);
91
- const readonly = !p.writable && !["object", "list"].includes(resolved.kind) || key === raw.root && ["signature", "procnfe", "infnfesupl"].includes(p.name.toLowerCase());
92
- props.set(p.name.toLowerCase(), { name: p.name, type: p.type, ...resolved, readonly, ...p.default ? { declaredDefault: p.default } : {} });
142
+ }
143
+ for (const entry of entries) {
144
+ await mkdir(dirname(entry.destination), { recursive: true });
145
+ try {
146
+ await writeFile(entry.destination, entry.content, { flag: "wx" });
147
+ } catch (error) {
148
+ if (error.code !== "EEXIST") throw error;
93
149
  }
94
- node.properties = [...props.values()].sort((a, b) => a.name.localeCompare(b.name, "en"));
95
- return { kind: "object", ref: key };
96
150
  }
97
- visit(raw.root, rootUnit);
98
- return { schemaVersion: 1, root: raw.root, types: [...generated.values()].sort((a, b) => a.name.localeCompare(b.name, "en")) };
99
151
  }
100
- function compareContracts(previous, current) {
101
- const old = new Map(previous?.types.map((t) => [t.name, t]) ?? []), now = new Map(current.types.map((t) => [t.name, t]));
102
- const additions = [], removals = [], changes = [];
103
- for (const [name, type] of now) {
104
- const before = old.get(name);
105
- if (!before) {
106
- additions.push(name);
107
- continue;
108
- }
109
- if (type.kind !== before.kind) {
110
- changes.push(name + ":kind");
111
- continue;
112
- }
113
- if (type.kind === "object") {
114
- const a = new Map(before.properties.map((p) => [p.name, p])), b = new Map(type.properties.map((p) => [p.name, p]));
115
- for (const [field, p] of b) {
116
- if (!a.has(field)) additions.push(name + "." + field);
117
- else if (stable(a.get(field)) !== stable(p)) changes.push(name + "." + field);
118
- }
119
- for (const field of a.keys()) if (!b.has(field)) removals.push(name + "." + field);
120
- } else if (type.kind === "enum") {
121
- for (const v of type.values) if (!before.values.includes(v)) additions.push(name + "." + v);
122
- for (const v of before.values) if (!type.values.includes(v)) removals.push(name + "." + v);
123
- } else if (type.item !== before.item) changes.push(name + ":item");
152
+ var OFFICIAL_ACBR_URL, SOURCE_PARTS, DEFAULT;
153
+ var init_config = __esm({
154
+ "src/config.ts"() {
155
+ "use strict";
156
+ OFFICIAL_ACBR_URL = "https://svn.code.sf.net/p/acbr/code/trunk2";
157
+ SOURCE_PARTS = ["Fontes", "Exemplos/ACBrDFe/Schemas/NFe", "Doctos/LICENSE.TXT"];
158
+ DEFAULT = {
159
+ formatVersion: 1,
160
+ source: { url: OFFICIAL_ACBR_URL, revision: "HEAD", directory: ".acbr/source" },
161
+ generator: { outputDir: "." },
162
+ native: { project: "native/acbr-worker.lpr", outputDir: ".acbr/runtime", fpc: "fpc" }
163
+ };
124
164
  }
125
- for (const name of old.keys()) if (!now.has(name)) removals.push(name);
126
- return { additions: additions.sort(), removals: removals.sort(), changes: changes.sort(), breaking: removals.length > 0 || changes.length > 0 };
165
+ });
166
+
167
+ // src/source.ts
168
+ var source_exports = {};
169
+ __export(source_exports, {
170
+ fileHash: () => fileHash,
171
+ lockExistingSource: () => lockExistingSource,
172
+ readSourceLock: () => readSourceLock,
173
+ resolveSourceRevision: () => resolveSourceRevision,
174
+ runCommand: () => runCommand,
175
+ snapshotSource: () => snapshotSource,
176
+ updateSource: () => updateSource,
177
+ verifySource: () => verifySource
178
+ });
179
+ import { spawn } from "node:child_process";
180
+ import { createHash as createHash2, randomUUID } from "node:crypto";
181
+ import { createReadStream } from "node:fs";
182
+ import { access as access2, mkdir as mkdir2, readdir as readdir2, readFile as readFile3, rename, rm, stat, writeFile as writeFile2 } from "node:fs/promises";
183
+ import { dirname as dirname2, join, relative, resolve as resolve2, sep } from "node:path";
184
+ async function runCommand(command, args, options = {}) {
185
+ return new Promise((done, fail3) => {
186
+ const child = spawn(command, args, { cwd: options.cwd, env: options.env ?? process.env, stdio: ["ignore", "pipe", "pipe"], windowsHide: true, shell: false });
187
+ let stdout = "";
188
+ let stderr = "";
189
+ let overflow = false;
190
+ const maximum = options.maxOutputBytes ?? 16 * 1024 * 1024;
191
+ const append = (kind, data) => {
192
+ if (overflow) return;
193
+ if (kind === "stdout") stdout += data.toString("utf8");
194
+ else stderr += data.toString("utf8");
195
+ if (Buffer.byteLength(stdout) + Buffer.byteLength(stderr) > maximum) {
196
+ overflow = true;
197
+ child.kill();
198
+ }
199
+ };
200
+ child.stdout.on("data", (data) => append("stdout", data));
201
+ child.stderr.on("data", (data) => append("stderr", data));
202
+ child.on("error", (error) => fail3(new Error(`N\xE3o foi poss\xEDvel executar ${command}: ${error.message}`, { cause: error })));
203
+ child.on("close", (code) => {
204
+ if (overflow) fail3(new Error(`Sa\xEDda de ${command} excedeu o limite de ${maximum} bytes.`));
205
+ else if (code !== 0) {
206
+ const diagnostic = (stderr || stdout).split("\n").slice(-80).join("\n").slice(-16e3);
207
+ fail3(Object.assign(new Error(`${command} terminou com c\xF3digo ${code}:
208
+ ${diagnostic}`), { stdout, stderr }));
209
+ } else done({ stdout, stderr });
210
+ });
211
+ });
127
212
  }
128
- function renderModelValidation() {
129
- return String.raw`
130
- export type CodigoValidacaoModelo = 'MODELO_DESCONHECIDO'|'ENUM_INVALIDO'|'ARRAY_ESPERADO'|'OBJETO_ESPERADO'|'CAMPO_DESCONHECIDO'|'CAMPO_SOMENTE_LEITURA'|'INTEIRO_INVALIDO'|'BOOLEANO_ESPERADO'|'DECIMAL_INVALIDO'|'DATA_HORA_INVALIDA'|'DATA_INVALIDA'|'TEXTO_ESPERADO';
131
- function campoConhecido(at: unknown): string | undefined {
132
- if(typeof at!=='string'||at.length>512||! /^[A-Za-z_]\w*(?:(?:\.[A-Za-z_]\w*)|(?:\[\d{1,7}\]))*$/.test(at))return undefined;
133
- const parts=at.replace(/\[(\d+)\]/g,'.$1').split('.');let schema=Object.hasOwn(MODEL_SCHEMA,parts[0])?MODEL_SCHEMA[parts[0]]:undefined;
134
- if(!schema)return undefined;
135
- for(const part of parts.slice(1)){
136
- if(schema.kind==='list'){if(! /^\d+$/.test(part))return undefined;schema=MODEL_SCHEMA[schema.item];}
137
- else if(schema.kind==='object'){const p=schema.properties.find((p:any)=>p.name===part);if(!p)return undefined;schema=p.ref?MODEL_SCHEMA[p.ref]:{kind:p.kind};}
138
- else return undefined;
139
- }
140
- return at;
141
- }
142
- /** TypeError compatível, com contexto seguro e sem o valor informado ou chaves desconhecidas. */
143
- export class ErroValidacaoModelo extends TypeError {
144
- readonly codigo: CodigoValidacaoModelo;
145
- readonly diagnostico: Readonly<{codigo:CodigoValidacaoModelo;etapa:'documento';campo?:string;mensagem:string;acao:string;statusEnvio:'nao_enviado';causa:Readonly<{codigo:CodigoValidacaoModelo;etapa:'documento';campo?:string}>}>;
146
- constructor(codigo: CodigoValidacaoModelo, at?: string) {
147
- const catalogo:Record<CodigoValidacaoModelo,[string,string]>={
148
- MODELO_DESCONHECIDO:['Modelo desconhecido.','Use um modelo exportado pelo cliente gerado.'],
149
- ENUM_INVALIDO:['enum inválido','Use um dos valores textuais do enum exportado pelo cliente.'],
150
- ARRAY_ESPERADO:['esperado array','Informe uma lista JSON entre colchetes.'],
151
- OBJETO_ESPERADO:['esperado objeto','Informe um objeto JSON entre chaves.'],
152
- CAMPO_DESCONHECIDO:['propriedade desconhecida','Confira os nomes permitidos neste grupo; a chave desconhecida não é registrada.'],
153
- CAMPO_SOMENTE_LEITURA:['propriedade somente leitura','Remova este campo da entrada; o motor preenche seu resultado.'],
154
- INTEIRO_INVALIDO:['inteiro fora do intervalo','Informe um número inteiro dentro do intervalo do campo.'],
155
- BOOLEANO_ESPERADO:['esperado boolean','Informe true ou false como valor JSON, sem aspas.'],
156
- DECIMAL_INVALIDO:['esperado decimal em string','Informe o decimal entre aspas, com ponto e a escala permitida pelo campo.'],
157
- DATA_HORA_INVALIDA:['esperado data/hora civil ISO (sem timezone)','Informe a data/hora civil da UF como AAAA-MM-DDTHH:mm:ss, sem Z ou offset. Confira a data antes do envio.'],
158
- DATA_INVALIDA:['data inválida','Confira dia, mês, ano e horário usando uma data civil válida.'],
159
- TEXTO_ESPERADO:['esperado string','Informe texto entre aspas no JSON.']
160
- };
161
- const safeCode=Object.hasOwn(catalogo,codigo)?codigo:'MODELO_DESCONHECIDO';
162
- const campo=campoConhecido(at),[texto,acao]=catalogo[safeCode],mensagem=(campo?campo+': ':'')+texto;
163
- super(mensagem);this.codigo=safeCode;
164
- const causa=Object.freeze({codigo:safeCode,etapa:'documento' as const,...(campo?{campo}:{})});
165
- this.diagnostico=Object.freeze({codigo:safeCode,etapa:'documento' as const,...(campo?{campo}:{}),mensagem,acao,statusEnvio:'nao_enviado' as const,causa});
166
- Object.defineProperty(this,'cause',{value:causa,enumerable:false});
167
- }
168
- toJSON(){return this.diagnostico;}
169
- }
170
- export function validateModel(model: string, value: unknown, at=model): void {
171
- const schema=Object.hasOwn(MODEL_SCHEMA,model)?MODEL_SCHEMA[model]:undefined;
172
- if(!schema)throw new ErroValidacaoModelo('MODELO_DESCONHECIDO');
173
- at=campoConhecido(at)??model;
174
- if(schema.kind==='enum'){if(typeof value!=='string'||!schema.values.includes(value))throw new ErroValidacaoModelo('ENUM_INVALIDO',at);return;}
175
- if(schema.kind==='list'){if(!Array.isArray(value))throw new ErroValidacaoModelo('ARRAY_ESPERADO',at);value.forEach((item,index)=>validateModel(schema.item,item,at+'['+index+']'));return;}
176
- if(value===null||typeof value!=='object'||Array.isArray(value))throw new ErroValidacaoModelo('OBJETO_ESPERADO',at);
177
- const fields=new Map<string,any>(schema.properties.filter((p:any)=>!p.readonly).map((p:any)=>[p.name,p]));
178
- for(const [name,v] of Object.entries(value)){
179
- if(v===undefined)continue;
180
- const p=fields.get(name);
181
- if(!p){const readonly=schema.properties.some((p:any)=>p.name===name&&p.readonly);throw new ErroValidacaoModelo(readonly?'CAMPO_SOMENTE_LEITURA':'CAMPO_DESCONHECIDO',readonly?at+'.'+name:at);}
182
- const field=at+'.'+name;
183
- if(p.ref){validateModel(p.ref,v,field);continue;}
184
- if(p.kind==='integer'){if(typeof v!=='number'||!Number.isSafeInteger(v)||v<p.min||v>p.max)throw new ErroValidacaoModelo('INTEIRO_INVALIDO',field);}
185
- else if(p.kind==='boolean'){if(typeof v!=='boolean')throw new ErroValidacaoModelo('BOOLEANO_ESPERADO',field);}
186
- else if(p.kind==='decimal'){if(typeof v!=='string'||v.length>64||! /^-?\d+(?:\.\d+)?$/.test(v)||p.scale!==undefined&&(v.split('.')[1]?.length??0)>p.scale)throw new ErroValidacaoModelo('DECIMAL_INVALIDO',field);}
187
- else if(p.kind==='datetime'){
188
- if(typeof v!=='string'||! /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?)?$/.test(v)||Number.isNaN(Date.parse(v+(v.length===10?'T00:00:00Z':'Z'))))throw new ErroValidacaoModelo('DATA_HORA_INVALIDA',field);
189
- const date=new Date(v+(v.length===10?'T00:00:00Z':'Z'));if(date.toISOString().slice(0,10)!==v.slice(0,10))throw new ErroValidacaoModelo('DATA_INVALIDA',field);
190
- }else if(typeof v!=='string')throw new ErroValidacaoModelo('TEXTO_ESPERADO',field);
191
- }
192
- }
193
- export function validateTNFe(value: unknown): asserts value is TNFeInput { validateModel('TNFe',value); }
194
- `;
195
- }
196
- function renderTypeScript(ir, revision2, contractHash) {
197
- const out = ["// Generated from ACBr AST. LGPL-2.1-or-later. Do not edit.", "export const ACBR_CONTRACT = " + stable({ sourceRevision: revision2, contractHash }) + " as const;", "export const SOURCE_REVISION=ACBR_CONTRACT.sourceRevision;", "export const CONTRACT_HASH=ACBR_CONTRACT.contractHash;"];
198
- for (const t of ir.types) {
199
- if (t.kind === "enum") {
200
- out.push("export const " + t.name + " = Object.freeze(" + stable(Object.fromEntries(t.values.map((v) => [v, v]))) + " as const);", "export type " + t.name + " = typeof " + t.name + "[keyof typeof " + t.name + "];");
201
- } else if (t.kind === "list") {
202
- out.push("export type " + t.name + "Input = " + t.item + "Input[];", "export class " + t.name + " extends Array<" + t.item + "> {", " New(input: " + t.item + "Input = {}): " + t.item + " { const item=new " + t.item + "(input); this.push(item); return item; }", "}");
203
- } else {
204
- out.push("export interface " + t.name + "Input {");
205
- for (const p of t.properties.filter((p2) => !p2.readonly)) out.push(" " + JSON.stringify(p.name) + "?: " + tsType(p) + ";");
206
- out.push("}", "export class " + t.name + " {");
207
- for (const p of t.properties) {
208
- if (p.readonly) {
209
- out.push(" readonly " + JSON.stringify(p.name) + "?: " + tsType(p) + ";");
210
- continue;
211
- }
212
- if (p.declaredDefault) out.push(" /** Pascal streaming default: " + p.declaredDefault.replaceAll("*/", "") + ". Omission preserves the native constructor. */");
213
- if (p.kind === "object" || p.kind === "list") out.push(" " + JSON.stringify(p.name) + " = new " + p.ref + "();");
214
- else out.push(" " + JSON.stringify(p.name) + "?: " + tsType(p) + ";");
215
- }
216
- out.push(" constructor(input: " + t.name + "Input = {}) {", " validateModel(" + JSON.stringify(t.name) + ", input);");
217
- for (const p of t.properties.filter((p2) => !p2.readonly)) {
218
- const access5 = "input[" + JSON.stringify(p.name) + "]", target = "this[" + JSON.stringify(p.name) + "]";
219
- out.push(" if (" + access5 + " !== undefined) " + target + " = " + (p.kind === "object" ? "new " + p.ref + "(" + access5 + ")" : p.kind === "list" ? "Object.assign(new " + p.ref + "(), " + access5 + ".map(v=>new " + ir.types.find((t2) => t2.name === p.ref).item + "(v)))" : access5) + ";");
220
- }
221
- out.push(" }", "}");
222
- }
223
- }
224
- out.push("const MODEL_SCHEMA: Record<string, any> = " + stable(Object.fromEntries(ir.types.map((t) => [t.name, t]))) + ";");
225
- out.push(renderModelValidation());
226
- return out.join("\n") + "\n";
213
+ async function fileHash(path4) {
214
+ const hash2 = createHash2("sha256");
215
+ for await (const chunk of createReadStream(path4)) hash2.update(chunk);
216
+ return hash2.digest("hex");
227
217
  }
228
- function renderPascal(ir, revision2, contractHash) {
229
- const classes = ir.types.filter((t) => t.kind === "object"), byName = new Map(ir.types.map((t) => [t.name, t]));
230
- const units = [...new Set(ir.types.map((t) => t.unit))].sort();
231
- const out = ["{ Generated from ACBr AST. LGPL-2.1-or-later. Do not edit. }", "unit AcbrModels;", "{$mode delphi}{$H+}", "interface", "uses SysUtils, Classes, fpjson, DateUtils, Math, " + units.join(", ") + ";", "const SourceRevision = " + revision2 + ";", " ContractHash = '" + contractHash + "';", "procedure preencherTNFe(documento:TJSONObject; destino:TNFe);", "implementation"];
232
- out.push(String.raw`
233
- procedure Bad(const P,M:string); begin raise Exception.Create(P+': '+M) end;
234
- function Obj(D:TJSONData;const P:string):TJSONObject;
235
- begin if (D=nil) or (D.JSONType<>jtObject) then Bad(P,'esperado objeto');Result:=TJSONObject(D) end;
236
- function Arr(D:TJSONData;const P:string):TJSONArray;
237
- begin if (D=nil) or (D.JSONType<>jtArray) then Bad(P,'esperado array');Result:=TJSONArray(D) end;
238
- function Text(D:TJSONData;const P:string):string;
239
- begin if (D=nil) or (D.JSONType<>jtString) then Bad(P,'esperado string');Result:=D.AsString end;
240
- function IntValue(D:TJSONData;const P:string;MinV,MaxV:Int64):Int64;
241
- var V:Extended;
242
- begin
243
- if (D=nil) or (D.JSONType<>jtNumber) then Bad(P,'esperado inteiro');
244
- V:=D.AsFloat;if IsNan(V) or IsInfinite(V) or (Frac(V)<>0) or (V<MinV) or (V>MaxV) then Bad(P,'inteiro fora do intervalo');
245
- Result:=D.AsInt64;
246
- end;
247
- function BoolValue(D:TJSONData;const P:string):boolean;
248
- begin if (D=nil) or (D.JSONType<>jtBoolean) then Bad(P,'esperado boolean');Result:=D.AsBoolean end;
249
- function DecimalText(D:TJSONData;const P:string;Scale:integer):string;
250
- var I,PointPos:integer;
251
- begin
252
- Result:=Text(D,P);PointPos:=0;
253
- if (Result='') or (Length(Result)>64) then Bad(P,'decimal inválido');
254
- for I:=1 to Length(Result) do begin
255
- if Result[I]='.' then begin if (PointPos>0) or (I=1) or ((I=2) and (Result[1]='-')) or (I=Length(Result)) then Bad(P,'decimal inválido');PointPos:=I end
256
- else if (Result[I]='-') and (I=1) then begin if Length(Result)=1 then Bad(P,'decimal inválido') end
257
- else if not (Result[I] in ['0'..'9']) then Bad(P,'decimal inválido');
258
- end;
259
- if (PointPos>0) and (Scale>=0) and (Length(Result)-PointPos>Scale) then Bad(P,'casas decimais excedidas');
260
- end;
261
- function FloatValue(D:TJSONData;const P:string):Extended;
262
- var F:TFormatSettings;S:string;
263
- begin F:=DefaultFormatSettings;F.DecimalSeparator:='.';F.ThousandSeparator:=#0;S:=DecimalText(D,P,-1);
264
- if not TryStrToFloat(S,Result,F) or IsNan(Result) or IsInfinite(Result) then Bad(P,'decimal fora do intervalo');
265
- end;
266
- function CurrencyValue(D:TJSONData;const P:string):Currency;
267
- var F:TFormatSettings;S:string;
268
- begin F:=DefaultFormatSettings;F.DecimalSeparator:='.';F.ThousandSeparator:=#0;S:=DecimalText(D,P,4);
269
- if not TryStrToCurr(S,Result,F) then Bad(P,'currency fora do intervalo');
270
- end;
271
- function DateValue(D:TJSONData;const P:string):TDateTime;
272
- var S:string;I:integer;
273
- begin
274
- S:=Text(D,P);
275
- if not (Length(S) in [10,19,21,22,23]) then Bad(P,'esperado data/hora civil ISO sem timezone');
276
- for I:=1 to Length(S) do if not ((S[I] in ['0'..'9']) or ((I in [5,8]) and (S[I]='-')) or ((I=11) and (S[I]='T')) or ((I in [14,17]) and (S[I]=':')) or ((I=20) and (S[I]='.'))) then Bad(P,'data ISO inválida');
277
- if not TryISO8601ToDate(S,Result,true) then Bad(P,'data ISO inválida');
278
- end;
279
- `);
280
- const q = (s) => "'" + s.replaceAll("'", "''") + "'";
281
- for (const t of classes) out.push("procedure Load_" + t.name + "(D:TJSONObject;destino:" + t.unit + "." + t.name + ";const P:string); forward;");
282
- for (const t of classes) {
283
- out.push("procedure Load_" + t.name + "(D:TJSONObject;destino:" + t.unit + "." + t.name + ";const P:string);", "var I,J:integer;V:TJSONData;A:TJSONArray;K,At:string;", "begin", " if destino=nil then Bad(P,'objeto ACBr n\xE3o inicializado');", " for I:=0 to D.Count-1 do begin", " K:=D.Names[I];V:=D.Items[I];At:=P+'.'+K;");
284
- let index = 0;
285
- for (const p of t.properties.filter((p2) => !p2.readonly)) {
286
- out.push(" " + (index++ ? "else " : "") + "if K=" + q(p.name) + " then begin");
287
- const target = "destino." + p.name;
288
- if (p.kind === "object") out.push(" Load_" + p.ref + "(Obj(V,At)," + target + ",At);");
289
- else if (p.kind === "list") {
290
- const list = byName.get(p.ref);
291
- out.push(" A:=Arr(V,At);if " + target + "=nil then Bad(At,'cole\xE7\xE3o n\xE3o inicializada');" + target + ".Clear;", " for J:=0 to A.Count-1 do Load_" + list.item + "(Obj(A.Items[J],At+'['+IntToStr(J)+']')," + target + "." + list.factory + ",At+'['+IntToStr(J)+']');");
292
- } else if (p.kind === "enum") {
293
- const enumeration = byName.get(p.ref);
294
- out.push(...enumeration.values.map((v, i) => " " + (i ? "else " : "") + "if Text(V,At)=" + q(v) + " then " + target + ":=" + enumeration.unit + "." + v), " else Bad(At,'enum inv\xE1lido');");
295
- } else out.push(" " + target + ":=" + { string: "Text(V,At)", integer: "IntValue(V,At," + p.min + "," + p.max + ")", boolean: "BoolValue(V,At)", datetime: "DateValue(V,At)", decimal: p.scale === 4 ? "CurrencyValue(V,At)" : "FloatValue(V,At)" }[p.kind] + ";");
296
- out.push(" end");
218
+ async function snapshotSource(directory) {
219
+ const files = /* @__PURE__ */ Object.create(null);
220
+ async function scan(current) {
221
+ const entries = (await readdir2(current, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name, "en"));
222
+ for (const entry of entries) {
223
+ if (entry.name === ".svn") continue;
224
+ const path4 = join(current, entry.name);
225
+ if (entry.isSymbolicLink()) throw new Error(`Fonte ACBr cont\xE9m link simb\xF3lico: ${path4}.`);
226
+ if (entry.isDirectory()) await scan(path4);
227
+ else if (entry.isFile()) files[relative(directory, path4).split(sep).join("/")] = await fileHash(path4);
228
+ else throw new Error(`Fonte ACBr cont\xE9m arquivo especial: ${path4}.`);
297
229
  }
298
- out.push((index ? " else " : " ") + "Bad(At,'propriedade desconhecida ou somente leitura');", " end;", "end;");
299
230
  }
300
- out.push("procedure preencherTNFe(documento:TJSONObject;destino:TNFe);", "begin if documento=nil then Bad('TNFe','esperado objeto');Load_TNFe(documento,destino,'TNFe') end;", "end.");
301
- return out.join("\n") + "\n";
302
- }
303
- function renderClientIndex() {
304
- return [
305
- "// Generated client bound to its own ACBr contract. Do not edit.",
306
- "import { criarEmissor as criarRuntime, diagnosticarErro as diagnosticarErroRuntime, diagnosticarResultado, type OpcoesEmissor, type OpcoesOperacao } from " + JSON.stringify("cosmemilton-acbr-node/runtime") + ";",
307
- "import { ACBR_CONTRACT, validateTNFe, ErroValidacaoModelo, type TNFeInput } from " + JSON.stringify("./models.js") + ";",
308
- "export * from " + JSON.stringify("./models.js") + ";",
309
- "export { diagnosticarResultado };",
310
- "export function diagnosticarErro(erro:unknown) { return erro instanceof ErroValidacaoModelo ? erro.diagnostico : diagnosticarErroRuntime(erro); }",
311
- "export function criarEmissor(options: Omit<OpcoesEmissor, " + JSON.stringify("contrato") + " | " + JSON.stringify("validaDocumento") + ">) {",
312
- " const emissor=criarRuntime({...options, contrato:ACBR_CONTRACT, validaDocumento:validateTNFe});",
313
- " return {...emissor, gerarXml(documento:TNFeInput, opcoes?:OpcoesOperacao) { return emissor.gerarXml(documento as unknown as Record<string,unknown>, opcoes); }};",
314
- "}"
315
- ].join("\n") + "\n";
231
+ await scan(resolve2(directory));
232
+ const sortedFiles = Object.fromEntries(Object.entries(files).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
233
+ const treeHash = createHash2("sha256").update(JSON.stringify(sortedFiles)).digest("hex");
234
+ return { treeHash, files: sortedFiles };
316
235
  }
317
- async function fingerprint(dir) {
318
- const files = [];
319
- async function walk(d) {
320
- for (const entry of await readdir4(d, { withFileTypes: true })) {
321
- const f = path2.join(d, entry.name);
322
- if (entry.isDirectory()) await walk(f);
323
- else if (/\.(pas|pp|inc|xsd)$/i.test(entry.name)) files.push(f);
324
- }
325
- }
326
- await walk(dir);
327
- const digest = createHash3("sha256");
328
- for (const f of files.sort()) {
329
- digest.update(path2.relative(dir, f).replaceAll("\\", "/"));
330
- digest.update(await readFile5(f));
236
+ function validateLock(value) {
237
+ if (!value || typeof value !== "object") throw new Error("Lock ACBr inv\xE1lido.");
238
+ const lock = value;
239
+ if (lock.formatVersion !== 1 || !lock.source || !Number.isSafeInteger(lock.source.revision) || lock.source.revision < 1 || !Array.isArray(lock.source.parts) || !lock.source.files || typeof lock.source.files !== "object" || Array.isArray(lock.source.files) || !/^[a-f0-9]{64}$/.test(lock.source.treeHash)) throw new Error("Formato inv\xE1lido em acbr.lock.json.");
240
+ for (const [path4, hash2] of Object.entries(lock.source.files)) {
241
+ if (path4.startsWith("/") || path4.includes("\\") || path4.split("/").includes("..") || !/^[a-f0-9]{64}$/.test(hash2)) throw new Error("Caminho ou hash inv\xE1lido no lock ACBr.");
331
242
  }
332
- return digest.digest("hex");
243
+ if (lock.source.parts.join("\n") !== SOURCE_PARTS.join("\n")) throw new Error("Partes ACBr divergentes no lock.");
244
+ return lock;
333
245
  }
334
- async function generateModel(options) {
335
- const root = path2.resolve(options.outputDir), cache = path2.join(root, ".acbr/generated"), bin = path2.join(root, ".acbr/bin");
336
- const models = path2.resolve(root, options.modelOutputDir ?? "generated/acbr"), native = path2.resolve(root, options.nativeOutputDir ?? "native/generated");
337
- await Promise.all([mkdir4(cache, { recursive: true }), mkdir4(bin, { recursive: true }), mkdir4(models, { recursive: true }), mkdir4(native, { recursive: true })]);
338
- const extractor = options.extractorPath ?? fileURLToPath2(new URL("../tools/extract-model.lpr", import.meta.url));
339
- const executable = path2.join(bin, "extract-model" + (process.platform === "win32" ? ".exe" : ""));
246
+ async function readSourceLock(config) {
247
+ let lock;
340
248
  try {
341
- await execute(options.fpcPath ?? "fpc", ["-Mobjfpc", "-Sh", "-FU" + bin, "-FE" + bin, extractor], { cwd: root, maxBuffer: 8 * 1024 * 1024 });
342
- await execute(executable, [path2.resolve(options.acbrRoot), path2.join(cache, "raw-model.json"), process.platform === "win32" ? "win64" : "linux"], { cwd: root, maxBuffer: 8 * 1024 * 1024 });
249
+ lock = validateLock(JSON.parse(await readFile3(config.lockPath, "utf8")));
343
250
  } catch (error) {
344
- const e = error;
345
- throw new Error("Extra\xE7\xE3o FCL-passrc falhou: " + (e.stderr ?? "") + (e.stdout ?? "") + e.message);
251
+ throw new Error(`N\xE3o foi poss\xEDvel ler ${config.lockPath}. Execute acbr-node source update.`, { cause: error });
346
252
  }
347
- const raw = JSON.parse(await readFile5(path2.join(cache, "raw-model.json"), "utf8"));
348
- const ir = buildModelIR(raw), sourceRevision = Number(options.revision);
349
- if (!Number.isSafeInteger(sourceRevision) || sourceRevision < 1) throw new Error("Revis\xE3o SVN inv\xE1lida");
350
- const sourceHash = options.sourceHash ?? await fingerprint(options.acbrRoot), contractHash = hash(stable({ sourceRevision, sourceHash, ir }));
351
- let previous;
253
+ if (lock.source.url !== config.source.url) throw new Error("URL ACBr do lock diverge da configura\xE7\xE3o.");
254
+ if (config.source.revision !== "HEAD" && lock.source.revision !== config.source.revision) throw new Error("Revis\xE3o ACBr do lock diverge da configura\xE7\xE3o. Execute source update explicitamente.");
255
+ return lock;
256
+ }
257
+ async function verifySource(config) {
352
258
  try {
353
- previous = JSON.parse(await readFile5(path2.join(cache, "model.ir.json"), "utf8"));
259
+ await access2(`${config.lockPath}.operation`);
354
260
  } catch (error) {
355
- if (error.code !== "ENOENT") throw error;
261
+ if (error.code === "ENOENT") return verifySourceContents(config);
262
+ throw error;
356
263
  }
357
- const report = compareContracts(previous, ir), reportPath = path2.join(cache, "changes.json"), manifestPath = path2.join(cache, "manifest.json");
358
- const files = [path2.relative(root, path2.join(models, "models.ts")), path2.relative(root, path2.join(models, "index.ts")), path2.relative(root, path2.join(native, "AcbrModels.pas"))].map((f) => f.replaceAll("\\", "/"));
359
- const content = [renderTypeScript(ir, sourceRevision, contractHash), renderClientIndex(), renderPascal(ir, sourceRevision, contractHash)];
360
- const fileHashes = Object.fromEntries(files.map((file, index) => [file, hash(content[index])]));
361
- await Promise.all([
362
- ...files.map((file, index) => writeFile4(path2.resolve(root, file), content[index], "utf8")),
363
- writeFile4(path2.join(cache, "model.ir.json"), JSON.stringify(ir, null, 2) + "\n", "utf8"),
364
- writeFile4(reportPath, JSON.stringify(report, null, 2) + "\n", "utf8"),
365
- writeFile4(manifestPath, JSON.stringify({ schemaVersion: 1, sourceRevision, sourceHash, contractHash, root: ir.root, models: ir.types.length, files, fileHashes }, null, 2) + "\n", "utf8")
366
- ]);
367
- return { contractHash, sourceHash, models: ir.types.length, reportPath, manifestPath };
368
- }
369
- var execute, bases, primitives, stable, hash, tsType;
370
- var init_generator = __esm({
371
- "src/generator.ts"() {
372
- "use strict";
373
- execute = promisify(execFile);
374
- bases = /* @__PURE__ */ new Set(["tobject", "tpersistent", "tacbrobjectlist"]);
375
- primitives = {
376
- string: { kind: "string" },
377
- ansistring: { kind: "string" },
378
- unicodestring: { kind: "string" },
379
- widestring: { kind: "string" },
380
- boolean: { kind: "boolean" },
381
- byte: { kind: "integer", min: 0, max: 255 },
382
- word: { kind: "integer", min: 0, max: 65535 },
383
- integer: { kind: "integer", min: -2147483648, max: 2147483647 },
384
- longint: { kind: "integer", min: -2147483648, max: 2147483647 },
385
- smallint: { kind: "integer", min: -32768, max: 32767 },
386
- shortint: { kind: "integer", min: -128, max: 127 },
387
- cardinal: { kind: "integer", min: 0, max: 4294967295 },
388
- longword: { kind: "integer", min: 0, max: 4294967295 },
389
- int64: { kind: "integer", min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
390
- qword: { kind: "integer", min: 0, max: Number.MAX_SAFE_INTEGER },
391
- double: { kind: "decimal" },
392
- extended: { kind: "decimal" },
393
- single: { kind: "decimal" },
394
- currency: { kind: "decimal", scale: 4 },
395
- tdatetime: { kind: "datetime" },
396
- tdate: { kind: "datetime" },
397
- ttime: { kind: "datetime" }
398
- };
399
- stable = (value) => JSON.stringify(value);
400
- hash = (value) => createHash3("sha256").update(value).digest("hex");
401
- tsType = (p) => p.kind === "object" ? p.ref + "Input" : p.kind === "list" ? p.ref + "Input" : p.kind === "enum" ? p.ref : p.kind === "integer" ? "number" : p.kind === "boolean" ? "boolean" : "string";
402
- }
403
- });
404
-
405
- // src/cli.ts
406
- import { realpathSync } from "node:fs";
407
- import { access as access4 } from "node:fs/promises";
408
- import { resolve as resolve4 } from "node:path";
409
- import { fileURLToPath as fileURLToPath3 } from "node:url";
410
-
411
- // src/config.ts
412
- import { readFile, writeFile, mkdir, readdir, access } from "node:fs/promises";
413
- import { dirname, isAbsolute, resolve } from "node:path";
414
- var OFFICIAL_ACBR_URL = "https://svn.code.sf.net/p/acbr/code/trunk2";
415
- var SOURCE_PARTS = ["Fontes", "Exemplos/ACBrDFe/Schemas/NFe", "Doctos/LICENSE.TXT"];
416
- var DEFAULT = {
417
- formatVersion: 1,
418
- source: { url: OFFICIAL_ACBR_URL, revision: "HEAD", directory: ".acbr/source" },
419
- generator: { outputDir: "." },
420
- native: { project: "native/acbr-worker.lpr", outputDir: ".acbr/runtime", fpc: "fpc" }
421
- };
422
- function defaultConfig() {
423
- return structuredClone(DEFAULT);
424
- }
425
- function record(value, name) {
426
- if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${name} deve ser um objeto.`);
427
- return value;
428
- }
429
- function keys(value, allowed, name) {
430
- const unexpected = Object.keys(value).filter((key) => !allowed.includes(key));
431
- if (unexpected.length) throw new Error(`Campo desconhecido em ${name}: ${unexpected.join(", ")}.`);
432
- }
433
- function string(value, name) {
434
- if (typeof value !== "string" || !value.trim() || value.includes("\0")) throw new Error(`${name} deve ser um texto n\xE3o vazio.`);
435
- return value;
436
- }
437
- function parseConfig(input, configPath) {
438
- const root = record(input, "configura\xE7\xE3o");
439
- keys(root, ["formatVersion", "source", "generator", "native"], "configura\xE7\xE3o");
440
- if (root.formatVersion !== 1) throw new Error("formatVersion deve ser 1.");
441
- const source = record(root.source, "source");
442
- keys(source, ["url", "revision", "directory"], "source");
443
- const generator = record(root.generator, "generator");
444
- keys(generator, ["outputDir"], "generator");
445
- const native = record(root.native, "native");
446
- keys(native, ["project", "outputDir", "fpc", "lazarusRoot", "libraryFiles", "providerFiles"], "native");
447
- const url = string(source.url, "source.url").replace(/\/+$/, "");
448
- if (url !== OFFICIAL_ACBR_URL) throw new Error(`source.url deve apontar ao reposit\xF3rio oficial ${OFFICIAL_ACBR_URL}.`);
449
- const revision2 = source.revision;
450
- if (revision2 !== "HEAD" && (!Number.isSafeInteger(revision2) || Number(revision2) < 1)) throw new Error("source.revision deve ser HEAD ou uma revis\xE3o SVN positiva.");
451
- const absoluteConfig = resolve(configPath);
452
- const projectRoot = dirname(absoluteConfig);
453
- const localPath = (value, label) => resolve(projectRoot, string(value, label));
454
- const fpcInput = string(native.fpc, "native.fpc");
455
- const fpc = isAbsolute(fpcInput) || /[\\/]/.test(fpcInput) ? resolve(projectRoot, fpcInput) : fpcInput;
456
- let libraryFiles;
457
- if (native.libraryFiles !== void 0) {
458
- if (!Array.isArray(native.libraryFiles)) throw new Error("native.libraryFiles deve ser uma lista de caminhos.");
459
- libraryFiles = native.libraryFiles.map((item, i) => localPath(item, `native.libraryFiles[${i}]`));
460
- }
461
- let providerFiles;
462
- if (native.providerFiles !== void 0) {
463
- if (!Array.isArray(native.providerFiles)) throw new Error("native.providerFiles deve ser uma lista de caminhos.");
464
- providerFiles = native.providerFiles.map((item, i) => localPath(item, `native.providerFiles[${i}]`));
465
- }
466
- return {
467
- formatVersion: 1,
468
- configPath: absoluteConfig,
469
- projectRoot,
470
- lockPath: resolve(projectRoot, "acbr.lock.json"),
471
- source: { url, revision: revision2, directory: localPath(source.directory, "source.directory") },
472
- generator: { outputDir: localPath(generator.outputDir, "generator.outputDir") },
473
- native: {
474
- project: localPath(native.project, "native.project"),
475
- outputDir: localPath(native.outputDir, "native.outputDir"),
476
- fpc,
477
- ...native.lazarusRoot !== void 0 ? { lazarusRoot: localPath(native.lazarusRoot, "native.lazarusRoot") } : {},
478
- ...libraryFiles !== void 0 ? { libraryFiles } : {},
479
- ...providerFiles !== void 0 ? { providerFiles } : {}
480
- }
481
- };
482
- }
483
- async function loadConfig(path3 = "acbr.config.json") {
484
- const configPath = resolve(path3);
485
- let contents;
486
- try {
487
- contents = await readFile(configPath, "utf8");
488
- } catch (error) {
489
- throw new Error(`N\xE3o foi poss\xEDvel ler ${configPath}. Execute acbr-node init.`, { cause: error });
490
- }
491
- let value;
492
- try {
493
- value = JSON.parse(contents);
494
- } catch (error) {
495
- throw new Error(`JSON inv\xE1lido em ${configPath}.`, { cause: error });
496
- }
497
- return parseConfig(value, configPath);
498
- }
499
- async function initializeConfig(path3 = "acbr.config.json", revision2 = "HEAD", assetRoot) {
500
- const configPath = resolve(path3);
501
- const config = defaultConfig();
502
- config.source.revision = revision2;
503
- parseConfig(config, configPath);
504
- await mkdir(dirname(configPath), { recursive: true });
505
- try {
506
- await access(configPath);
507
- throw Object.assign(new Error(`EEXIST: configura\xE7\xE3o j\xE1 existe: ${configPath}`), { code: "EEXIST" });
508
- } catch (error) {
509
- if (error.code !== "ENOENT") throw error;
510
- }
511
- const resolved = parseConfig(config, configPath);
512
- if (assetRoot) await copyInitAssets(assetRoot, resolved.projectRoot);
513
- await writeFile(configPath, `${JSON.stringify(config, null, 2)}
514
- `, { flag: "wx" });
515
- await mkdir(resolve(resolved.projectRoot, ".acbr/generated"), { recursive: true });
516
- await mkdir(resolve(resolved.projectRoot, "generated/acbr"), { recursive: true });
517
- return resolved;
518
- }
519
- async function copyInitAssets(assetRoot, targetRoot) {
520
- const entries = [];
521
- async function scan(current, target) {
522
- for (const entry of await readdir(current, { withFileTypes: true })) {
523
- if (entry.name === "generated" || entry.name.startsWith(".")) continue;
524
- const source = resolve(current, entry.name);
525
- const destination = resolve(target, entry.name);
526
- if (entry.isDirectory()) await scan(source, destination);
527
- else if (entry.isFile() && /\.(pas|lpr|inc|lpi)$/i.test(entry.name)) entries.push({ source, destination, content: await readFile(source) });
528
- }
529
- }
530
- await scan(resolve(assetRoot, "native"), resolve(targetRoot, "native"));
531
- if (!entries.some((entry) => entry.source.endsWith("acbr-worker.lpr"))) throw new Error("Assets do pacote n\xE3o cont\xEAm native/acbr-worker.lpr.");
532
- entries.push({ source: resolve(assetRoot, "tools/extract-model.lpr"), destination: resolve(targetRoot, "tools/extract-model.lpr"), content: await readFile(resolve(assetRoot, "tools/extract-model.lpr")) });
533
- for (const entry of entries) {
534
- try {
535
- const existing = await readFile(entry.destination);
536
- if (!existing.equals(entry.content)) throw new Error(`init preservou arquivo existente divergente: ${entry.destination}.`);
537
- } catch (error) {
538
- if (error.code !== "ENOENT") throw error;
539
- }
540
- }
541
- for (const entry of entries) {
542
- await mkdir(dirname(entry.destination), { recursive: true });
543
- try {
544
- await writeFile(entry.destination, entry.content, { flag: "wx" });
545
- } catch (error) {
546
- if (error.code !== "EEXIST") throw error;
547
- }
548
- }
549
- }
550
-
551
- // src/native-build.ts
552
- import { copyFile as copyFile2, mkdir as mkdir3, readdir as readdir3, readFile as readFile3, rename as rename2, rm as rm2, stat as stat2, chmod, realpath, access as access3, writeFile as writeFile3 } from "node:fs/promises";
553
- import { basename, dirname as dirname3, join as join2, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
554
- import { randomUUID as randomUUID2 } from "node:crypto";
555
- import { fileURLToPath } from "node:url";
556
-
557
- // src/source.ts
558
- import { spawn } from "node:child_process";
559
- import { createHash, randomUUID } from "node:crypto";
560
- import { createReadStream } from "node:fs";
561
- import { access as access2, mkdir as mkdir2, readdir as readdir2, readFile as readFile2, rename, rm, stat, writeFile as writeFile2 } from "node:fs/promises";
562
- import { dirname as dirname2, join, relative, resolve as resolve2, sep } from "node:path";
563
- async function runCommand(command, args, options = {}) {
564
- return new Promise((done, fail2) => {
565
- const child = spawn(command, args, { cwd: options.cwd, env: options.env ?? process.env, stdio: ["ignore", "pipe", "pipe"], windowsHide: true, shell: false });
566
- let stdout = "";
567
- let stderr = "";
568
- let overflow = false;
569
- const maximum = options.maxOutputBytes ?? 16 * 1024 * 1024;
570
- const append = (kind, data) => {
571
- if (overflow) return;
572
- if (kind === "stdout") stdout += data.toString("utf8");
573
- else stderr += data.toString("utf8");
574
- if (Buffer.byteLength(stdout) + Buffer.byteLength(stderr) > maximum) {
575
- overflow = true;
576
- child.kill();
577
- }
578
- };
579
- child.stdout.on("data", (data) => append("stdout", data));
580
- child.stderr.on("data", (data) => append("stderr", data));
581
- child.on("error", (error) => fail2(new Error(`N\xE3o foi poss\xEDvel executar ${command}: ${error.message}`, { cause: error })));
582
- child.on("close", (code) => {
583
- if (overflow) fail2(new Error(`Sa\xEDda de ${command} excedeu o limite de ${maximum} bytes.`));
584
- else if (code !== 0) {
585
- const diagnostic = (stderr || stdout).split("\n").slice(-80).join("\n").slice(-16e3);
586
- fail2(Object.assign(new Error(`${command} terminou com c\xF3digo ${code}:
587
- ${diagnostic}`), { stdout, stderr }));
588
- } else done({ stdout, stderr });
589
- });
590
- });
591
- }
592
- async function fileHash(path3) {
593
- const hash2 = createHash("sha256");
594
- for await (const chunk of createReadStream(path3)) hash2.update(chunk);
595
- return hash2.digest("hex");
596
- }
597
- async function snapshotSource(directory) {
598
- const files = /* @__PURE__ */ Object.create(null);
599
- async function scan(current) {
600
- const entries = (await readdir2(current, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name, "en"));
601
- for (const entry of entries) {
602
- if (entry.name === ".svn") continue;
603
- const path3 = join(current, entry.name);
604
- if (entry.isSymbolicLink()) throw new Error(`Fonte ACBr cont\xE9m link simb\xF3lico: ${path3}.`);
605
- if (entry.isDirectory()) await scan(path3);
606
- else if (entry.isFile()) files[relative(directory, path3).split(sep).join("/")] = await fileHash(path3);
607
- else throw new Error(`Fonte ACBr cont\xE9m arquivo especial: ${path3}.`);
608
- }
609
- }
610
- await scan(resolve2(directory));
611
- const sortedFiles = Object.fromEntries(Object.entries(files).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
612
- const treeHash = createHash("sha256").update(JSON.stringify(sortedFiles)).digest("hex");
613
- return { treeHash, files: sortedFiles };
614
- }
615
- function validateLock(value) {
616
- if (!value || typeof value !== "object") throw new Error("Lock ACBr inv\xE1lido.");
617
- const lock = value;
618
- if (lock.formatVersion !== 1 || !lock.source || !Number.isSafeInteger(lock.source.revision) || lock.source.revision < 1 || !Array.isArray(lock.source.parts) || !lock.source.files || typeof lock.source.files !== "object" || Array.isArray(lock.source.files) || !/^[a-f0-9]{64}$/.test(lock.source.treeHash)) throw new Error("Formato inv\xE1lido em acbr.lock.json.");
619
- for (const [path3, hash2] of Object.entries(lock.source.files)) {
620
- if (path3.startsWith("/") || path3.includes("\\") || path3.split("/").includes("..") || !/^[a-f0-9]{64}$/.test(hash2)) throw new Error("Caminho ou hash inv\xE1lido no lock ACBr.");
621
- }
622
- if (lock.source.parts.join("\n") !== SOURCE_PARTS.join("\n")) throw new Error("Partes ACBr divergentes no lock.");
623
- return lock;
624
- }
625
- async function readSourceLock(config) {
626
- let lock;
627
- try {
628
- lock = validateLock(JSON.parse(await readFile2(config.lockPath, "utf8")));
629
- } catch (error) {
630
- throw new Error(`N\xE3o foi poss\xEDvel ler ${config.lockPath}. Execute acbr-node source update.`, { cause: error });
631
- }
632
- if (lock.source.url !== config.source.url) throw new Error("URL ACBr do lock diverge da configura\xE7\xE3o.");
633
- if (config.source.revision !== "HEAD" && lock.source.revision !== config.source.revision) throw new Error("Revis\xE3o ACBr do lock diverge da configura\xE7\xE3o. Execute source update explicitamente.");
634
- return lock;
635
- }
636
- async function verifySource(config) {
637
- try {
638
- await access2(`${config.lockPath}.operation`);
639
- } catch (error) {
640
- if (error.code === "ENOENT") return verifySourceContents(config);
641
- throw error;
642
- }
643
- throw new Error("Atualiza\xE7\xE3o de fontes ACBr em andamento. Aguarde o CLI concluir.");
264
+ throw new Error("Atualiza\xE7\xE3o de fontes ACBr em andamento. Aguarde o CLI concluir.");
644
265
  }
645
266
  async function verifySourceContents(config) {
646
267
  const lock = await readSourceLock(config);
647
268
  const snapshot = await snapshotSource(config.source.directory);
648
269
  if (snapshot.treeHash !== lock.source.treeHash) {
649
270
  const names = /* @__PURE__ */ new Set([...Object.keys(snapshot.files), ...Object.keys(lock.source.files)]);
650
- const changed = [...names].filter((path3) => snapshot.files[path3] !== lock.source.files[path3]);
271
+ const changed = [...names].filter((path4) => snapshot.files[path4] !== lock.source.files[path4]);
651
272
  throw new Error(`Fontes ACBr divergem do lock (${changed.length} arquivo(s)): ${changed.slice(0, 10).join(", ")}. Preserve as altera\xE7\xF5es antes de atualizar.`);
652
273
  }
653
274
  return lock;
@@ -718,7 +339,7 @@ async function performUpdateSource(config, revision2, runner) {
718
339
  await mkdir2(stage, { recursive: true });
719
340
  let previousLock;
720
341
  try {
721
- previousLock = await readFile2(config.lockPath, "utf8");
342
+ previousLock = await readFile3(config.lockPath, "utf8");
722
343
  } catch (error) {
723
344
  if (error.code !== "ENOENT") throw error;
724
345
  }
@@ -757,7 +378,7 @@ async function performUpdateSource(config, revision2, runner) {
757
378
  }
758
379
  }
759
380
  async function persistRevision(config, revision2) {
760
- const original = JSON.parse(await readFile2(config.configPath, "utf8"));
381
+ const original = JSON.parse(await readFile3(config.configPath, "utf8"));
761
382
  original.source.revision = revision2;
762
383
  const temporary = `${config.configPath}.${randomUUID()}.tmp`;
763
384
  await writeFile2(temporary, `${JSON.stringify(original, null, 2)}
@@ -768,29 +389,47 @@ async function persistRevision(config, revision2) {
768
389
  await rm(temporary, { force: true });
769
390
  }
770
391
  }
392
+ var init_source = __esm({
393
+ "src/source.ts"() {
394
+ "use strict";
395
+ init_config();
396
+ }
397
+ });
771
398
 
772
399
  // src/native-build.ts
400
+ var native_build_exports = {};
401
+ __export(native_build_exports, {
402
+ buildNative: () => buildNative,
403
+ checkBuild: () => checkBuild,
404
+ doctor: () => doctor,
405
+ findLazarus: () => findLazarus,
406
+ runtimeDirectory: () => runtimeDirectory
407
+ });
408
+ import { copyFile as copyFile2, mkdir as mkdir3, readdir as readdir3, readFile as readFile4, rename as rename2, rm as rm2, stat as stat2, chmod, realpath, access as access3, writeFile as writeFile3 } from "node:fs/promises";
409
+ import { basename, dirname as dirname3, join as join2, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
410
+ import { randomUUID as randomUUID2 } from "node:crypto";
411
+ import { fileURLToPath } from "node:url";
773
412
  function runtimeDirectory(config) {
774
413
  return join2(config.native.outputDir, `${process.platform}-${process.arch}`);
775
414
  }
776
- async function exists(path3) {
415
+ async function exists(path4) {
777
416
  try {
778
- await access3(path3);
417
+ await access3(path4);
779
418
  return true;
780
419
  } catch {
781
420
  return false;
782
421
  }
783
422
  }
784
423
  async function findLazarus(config) {
785
- const candidates = config.native.lazarusRoot ? [config.native.lazarusRoot] : [process.env.LAZARUS_ROOT, "/usr/lib/lazarus/default", "/usr/lib/lazarus/3.0", "C:\\lazarus"].filter((path3) => Boolean(path3));
424
+ const candidates = config.native.lazarusRoot ? [config.native.lazarusRoot] : [process.env.LAZARUS_ROOT, "/usr/lib/lazarus/default", "/usr/lib/lazarus/3.0", "C:\\lazarus"].filter((path4) => Boolean(path4));
786
425
  for (const candidate of candidates) if (await exists(join2(candidate, "components/lazutils"))) return realpath(candidate);
787
426
  throw new Error("Lazarus n\xE3o encontrado. Defina native.lazarusRoot em acbr.config.json ou LAZARUS_ROOT.");
788
427
  }
789
428
  async function generatedManifest(config) {
790
- const path3 = join2(config.generator.outputDir, ".acbr/generated/manifest.json");
429
+ const path4 = join2(config.generator.outputDir, ".acbr/generated/manifest.json");
791
430
  let value;
792
431
  try {
793
- value = JSON.parse(await readFile3(path3, "utf8"));
432
+ value = JSON.parse(await readFile4(path4, "utf8"));
794
433
  } catch (error) {
795
434
  throw new Error("Contrato gerado ausente ou inv\xE1lido. Execute acbr-node generate.", { cause: error });
796
435
  }
@@ -804,23 +443,21 @@ async function generatedManifest(config) {
804
443
  }
805
444
  return value;
806
445
  }
807
- async function subdirectories(path3) {
808
- const result = [path3];
809
- for (const entry of (await readdir3(path3, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
810
- if (entry.isDirectory()) result.push(...await subdirectories(join2(path3, entry.name)));
446
+ async function subdirectories(path4) {
447
+ const result = [path4];
448
+ for (const entry of (await readdir3(path4, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
449
+ if (entry.isDirectory()) result.push(...await subdirectories(join2(path4, entry.name)));
811
450
  }
812
451
  return result;
813
452
  }
814
- var REQUIRED_DYNAMIC = ["libssl.so.3", "libcrypto.so.3", "libxml2.so.2"];
815
- var CORE_SYSTEM = /^(?:lib(?:c|m|pthread|dl|rt|resolv|anl|util)\.so(?:\.|$)|ld-linux|linux-vdso)/;
816
453
  async function copyLinuxLibraries(stage) {
817
454
  const { stdout } = await runCommand("ldconfig", ["-p"]);
818
455
  const libraries = /* @__PURE__ */ new Map();
819
456
  for (const name of REQUIRED_DYNAMIC) {
820
457
  const line = stdout.split("\n").find((value) => value.trim().startsWith(`${name} `) && value.includes("x86-64"));
821
- const path3 = line?.split("=>")[1]?.trim();
822
- if (!path3) throw new Error(`Depend\xEAncia din\xE2mica ausente: ${name}. Instale OpenSSL 3 e libxml2 compat\xEDveis.`);
823
- libraries.set(name, await realpath(path3));
458
+ const path4 = line?.split("=>")[1]?.trim();
459
+ if (!path4) throw new Error(`Depend\xEAncia din\xE2mica ausente: ${name}. Instale OpenSSL 3 e libxml2 compat\xEDveis.`);
460
+ libraries.set(name, await realpath(path4));
824
461
  }
825
462
  const modules = "/usr/lib/x86_64-linux-gnu/ossl-modules";
826
463
  if (!await exists(join2(modules, "legacy.so"))) throw new Error("Provider legacy OpenSSL 3 ausente. Instale o pacote libssl3/libssl3t64 completo.");
@@ -828,9 +465,9 @@ async function copyLinuxLibraries(stage) {
828
465
  const systemDependencies = /* @__PURE__ */ new Set();
829
466
  const inspected = /* @__PURE__ */ new Set();
830
467
  while (inspected.size < libraries.size) {
831
- const [name, path3] = [...libraries].find(([name2]) => !inspected.has(name2));
468
+ const [name, path4] = [...libraries].find(([name2]) => !inspected.has(name2));
832
469
  inspected.add(name);
833
- const dependencies = await runCommand("ldd", [path3]);
470
+ const dependencies = await runCommand("ldd", [path4]);
834
471
  for (const line of dependencies.stdout.split("\n")) {
835
472
  if (line.includes("not found")) throw new Error(`Depend\xEAncia transitiva ausente: ${line.trim()}.`);
836
473
  const match = /^\s*(\S+)\s+=>\s+(\S+)/.exec(line);
@@ -848,17 +485,17 @@ async function copyLinuxLibraries(stage) {
848
485
  const licenseDir = join2(stage, "licenses");
849
486
  await mkdir3(licenseDir, { recursive: true });
850
487
  const provenance = {};
851
- for (const [name, path3] of libraries) {
488
+ for (const [name, path4] of libraries) {
852
489
  const destination = name.startsWith("ossl-modules/") ? join2(stage, name) : join2(stage, "lib", name);
853
490
  await mkdir3(dirname3(destination), { recursive: true });
854
- await copyFile2(path3, destination);
491
+ await copyFile2(path4, destination);
855
492
  const aliases = name === "libssl.so.3" ? ["libssl.so"] : name === "libcrypto.so.3" ? ["libcrypto.so"] : name === "libxml2.so.2" ? ["libxml2.so"] : [];
856
- for (const alias of aliases) await copyFile2(path3, join2(stage, "lib", alias));
493
+ for (const alias of aliases) await copyFile2(path4, join2(stage, "lib", alias));
857
494
  let owner;
858
495
  try {
859
- owner = (await runCommand("dpkg-query", ["-S", path3])).stdout.split("\n")[0].split(": ")[0];
496
+ owner = (await runCommand("dpkg-query", ["-S", path4])).stdout.split("\n")[0].split(": ")[0];
860
497
  } catch (error) {
861
- throw new Error(`N\xE3o foi poss\xEDvel identificar pacote/licen\xE7a de ${path3}. Build requer Debian/Ubuntu com depend\xEAncias registradas pelo dpkg.`, { cause: error });
498
+ throw new Error(`N\xE3o foi poss\xEDvel identificar pacote/licen\xE7a de ${path4}. Build requer Debian/Ubuntu com depend\xEAncias registradas pelo dpkg.`, { cause: error });
862
499
  }
863
500
  const pkg = owner.split(":")[0];
864
501
  const copyright = `/usr/share/doc/${pkg}/copyright`;
@@ -900,10 +537,10 @@ async function copyExplicitLibraries(config, stage) {
900
537
  for (const source of files) {
901
538
  await copyFile2(source, join2(stage, directory, basename(source)));
902
539
  await copyFile2(`${source}.LICENSE`, join2(stage, "licenses", `${basename(source)}.txt`));
903
- if (await exists(`${source}.SOURCE.json`)) sources[`${directory}/${basename(source)}`] = JSON.parse(await readFile3(`${source}.SOURCE.json`, "utf8"));
540
+ if (await exists(`${source}.SOURCE.json`)) sources[`${directory}/${basename(source)}`] = JSON.parse(await readFile4(`${source}.SOURCE.json`, "utf8"));
904
541
  }
905
542
  }
906
- if (!config.native.providerFiles?.some((path3) => basename(path3).toLowerCase() === "legacy.dll")) throw new Error("Windows requer native.providerFiles com o provider legacy.dll de OpenSSL 3 e licen\xE7a adjacente.");
543
+ if (!config.native.providerFiles?.some((path4) => basename(path4).toLowerCase() === "legacy.dll")) throw new Error("Windows requer native.providerFiles com o provider legacy.dll de OpenSSL 3 e licen\xE7a adjacente.");
907
544
  await mkdir3(join2(stage, "sources"), { recursive: true });
908
545
  await writeFile3(join2(stage, "sources/native-dependencies.json"), `${JSON.stringify(sources, null, 2)}
909
546
  `);
@@ -940,8 +577,8 @@ async function buildNative(config, options = {}) {
940
577
  `-FU${units}`,
941
578
  `-FE${stage}`,
942
579
  `-o${executable}`,
943
- ...searchPaths.map((path3) => `-Fu${path3}`),
944
- ...fontPaths.map((path3) => `-Fi${path3}`),
580
+ ...searchPaths.map((path4) => `-Fu${path4}`),
581
+ ...fontPaths.map((path4) => `-Fi${path4}`),
945
582
  config.native.project
946
583
  ];
947
584
  const responseFile = join2(stage, ".compiler.rsp");
@@ -1010,6 +647,7 @@ Log completo: ${logPath}`, { cause: compilation });
1010
647
  executable,
1011
648
  files,
1012
649
  generatedFileHashes: contract.fileHashes,
650
+ capabilities: ["recuperarXml"],
1013
651
  systemDependencies,
1014
652
  ...options.testOnly ? { testOnly: true } : {}
1015
653
  };
@@ -1046,148 +684,504 @@ async function replaceRuntime(stage, target) {
1046
684
  if (hadTarget) await rename2(backup, target);
1047
685
  throw error;
1048
686
  }
1049
- if (hadTarget) await rm2(backup, { recursive: true, force: true });
687
+ if (hadTarget) await rm2(backup, { recursive: true, force: true });
688
+ }
689
+ async function checkBuild(config) {
690
+ const lock = await verifySource(config);
691
+ const generated = await generatedManifest(config);
692
+ const directory = runtimeDirectory(config);
693
+ const manifest = JSON.parse(await readFile4(join2(directory, "manifest.json"), "utf8"));
694
+ if (manifest.formatVersion !== 1 || manifest.platform !== process.platform || manifest.arch !== process.arch || manifest.sourceRevision !== lock.source.revision || generated.sourceHash !== lock.source.treeHash || manifest.contractHash !== generated.contractHash || !manifest.generatedFileHashes || Object.entries(generated.fileHashes).some(([name, hash2]) => manifest.generatedFileHashes[name] !== hash2) || !Array.isArray(manifest.capabilities) || !manifest.capabilities.includes("recuperarXml") || typeof manifest.executable !== "string" || !manifest.files || !Object.hasOwn(manifest.files, manifest.executable)) throw new Error("Runtime diverge das fontes ou contrato. Execute build.");
695
+ for (const [path4, expected] of Object.entries(manifest.files)) {
696
+ if (path4.startsWith("/") || path4.includes("\\") || path4.split("/").includes("..") || !/^[a-f0-9]{64}$/.test(expected)) throw new Error(`Caminho/hash inv\xE1lido no runtime: ${path4}.`);
697
+ if (await fileHash(join2(directory, path4)) !== expected) throw new Error(`Hash inv\xE1lido no runtime: ${path4}.`);
698
+ }
699
+ return manifest;
700
+ }
701
+ async function doctor(config) {
702
+ const items = [{ name: "Node.js", ok: Number(process.versions.node.split(".")[0]) > 22 || Number(process.versions.node.split(".")[0]) === 22 && Number(process.versions.node.split(".")[1]) >= 12, detail: process.versions.node }];
703
+ for (const [name, command, args] of [["SVN", "svn", ["--version", "--quiet"]], ["Free Pascal", config?.native.fpc ?? "fpc", ["-iV"]]]) {
704
+ try {
705
+ const result = await runCommand(command, [...args]);
706
+ items.push({ name, ok: true, detail: result.stdout.trim() });
707
+ } catch (error) {
708
+ items.push({ name, ok: false, detail: error.message });
709
+ }
710
+ }
711
+ if (config) {
712
+ try {
713
+ items.push({ name: "Lazarus", ok: true, detail: await findLazarus(config) });
714
+ } catch (error) {
715
+ items.push({ name: "Lazarus", ok: false, detail: error.message });
716
+ }
717
+ try {
718
+ const lock = await verifySource(config);
719
+ items.push({ name: "Fontes ACBr", ok: true, detail: `revis\xE3o ${lock.source.revision}, ${lock.source.treeHash}` });
720
+ } catch (error) {
721
+ items.push({ name: "Fontes ACBr", ok: false, detail: error.message });
722
+ }
723
+ }
724
+ if (process.platform === "linux") {
725
+ try {
726
+ const result = await runCommand("ldconfig", ["-p"]);
727
+ const missing = REQUIRED_DYNAMIC.filter((name) => !result.stdout.includes(name));
728
+ items.push({ name: "OpenSSL/libxml2 din\xE2micos", ok: missing.length === 0, detail: missing.length ? `Ausentes: ${missing.join(", ")}` : REQUIRED_DYNAMIC.join(", ") });
729
+ } catch (error) {
730
+ items.push({ name: "OpenSSL/libxml2 din\xE2micos", ok: false, detail: error.message });
731
+ }
732
+ }
733
+ return items;
734
+ }
735
+ async function copyCompilerLicenses(config, stage, lazarus) {
736
+ const packagedLazarus = fileURLToPath(new URL("../docs/licenses/lazarus/", import.meta.url));
737
+ const packagedFpc = fileURLToPath(new URL("../docs/licenses/fpc/", import.meta.url));
738
+ const notices = {};
739
+ async function copyNotice(name, candidates2) {
740
+ for (const source of candidates2) if (await exists(source)) {
741
+ await copyFile2(source, join2(stage, "licenses", name));
742
+ notices[name] = { source, sha256: await fileHash(source) };
743
+ return;
744
+ }
745
+ throw new Error(`Notice obrigat\xF3rio ausente: ${name}.`);
746
+ }
747
+ for (const name of ["COPYING.txt", "COPYING.LGPL.txt", "COPYING.modifiedLGPL.txt"]) {
748
+ await copyNotice(`Lazarus-${name}`, [join2(lazarus, name), join2(lazarus, "docs", name), join2(packagedLazarus, name)]);
749
+ }
750
+ if (await exists(join2(packagedLazarus, "ORIGIN.json"))) await copyFile2(join2(packagedLazarus, "ORIGIN.json"), join2(stage, "licenses/Lazarus-notice-origin.json"));
751
+ const fpcRoot = resolve3(dirname3(config.native.fpc), "../..");
752
+ const sourceRoots = [join2(fpcRoot, "source"), join2(lazarus, "fpc/3.2.2/source"), "/usr/share/fpcsrc/3.2.2"];
753
+ for (const [name, sourceRelative] of [["COPYING.GPL.txt", "compiler/COPYING.txt"], ["COPYING.LGPL.txt", "rtl/COPYING.txt"], ["COPYING.FPC", "rtl/COPYING.FPC"]]) {
754
+ await copyNotice(`FPC-${name}`, [...sourceRoots.map((directory) => join2(directory, sourceRelative)), join2(packagedFpc, name)]);
755
+ }
756
+ if (await exists(join2(packagedFpc, "ORIGIN.json"))) await copyFile2(join2(packagedFpc, "ORIGIN.json"), join2(stage, "licenses/FPC-notice-origin.json"));
757
+ const candidates = [join2(fpcRoot, "doc"), fpcRoot, join2(lazarus, "fpc"), "/usr/share/doc/fp-compiler-3.2.2", "/usr/share/doc/fp-units-rtl-3.2.2"];
758
+ for (const directory of candidates) {
759
+ if (!await exists(directory)) continue;
760
+ for (const name of await readdir3(directory)) {
761
+ if (/^(?:copying|license|copyright)/i.test(name) && (await stat2(join2(directory, name))).isFile()) await copyFile2(join2(directory, name), join2(stage, "licenses", `FPC-${basename(directory)}-${name}`));
762
+ }
763
+ }
764
+ await writeFile3(join2(stage, "licenses/toolchain-notices.json"), `${JSON.stringify(notices, null, 2)}
765
+ `);
766
+ }
767
+ var REQUIRED_DYNAMIC, CORE_SYSTEM;
768
+ var init_native_build = __esm({
769
+ "src/native-build.ts"() {
770
+ "use strict";
771
+ init_source();
772
+ REQUIRED_DYNAMIC = ["libssl.so.3", "libcrypto.so.3", "libxml2.so.2"];
773
+ CORE_SYSTEM = /^(?:lib(?:c|m|pthread|dl|rt|resolv|anl|util)\.so(?:\.|$)|ld-linux|linux-vdso)/;
774
+ }
775
+ });
776
+
777
+ // src/generator.ts
778
+ var generator_exports = {};
779
+ __export(generator_exports, {
780
+ buildModelIR: () => buildModelIR,
781
+ compareContracts: () => compareContracts,
782
+ generateModel: () => generateModel,
783
+ renderClientIndex: () => renderClientIndex,
784
+ renderContractMetadata: () => renderContractMetadata,
785
+ renderModelValidation: () => renderModelValidation,
786
+ renderPascal: () => renderPascal,
787
+ renderTypeScript: () => renderTypeScript
788
+ });
789
+ import { createHash as createHash3 } from "node:crypto";
790
+ import { execFile } from "node:child_process";
791
+ import { promisify } from "node:util";
792
+ import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4, readdir as readdir4 } from "node:fs/promises";
793
+ import path2 from "node:path";
794
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
795
+ function buildModelIR(raw) {
796
+ const declarations = /* @__PURE__ */ new Map();
797
+ for (const unit of raw.units) for (const type of unit.types) declarations.set((unit.name + "." + type.name).toLowerCase(), { unit, type });
798
+ function find(name, unit) {
799
+ for (const key of [unit.name + "." + name, ...[...unit.uses].reverse().map((u) => u + "." + name), name]) {
800
+ const item = declarations.get(key.toLowerCase());
801
+ if (item) return item;
802
+ }
803
+ throw new Error("Tipo Pascal n\xE3o resolvido: " + unit.name + "." + name);
804
+ }
805
+ function resolve5(name, unit, trail = /* @__PURE__ */ new Set()) {
806
+ if (primitives[name.toLowerCase()]) return { primitive: name.toLowerCase() };
807
+ const found = find(name, unit), key = (found.unit.name + "." + found.type.name).toLowerCase();
808
+ if (trail.has(key)) throw new Error("Alias Pascal c\xEDclico: " + key);
809
+ if (found.type.kind === "alias") {
810
+ trail.add(key);
811
+ return resolve5(found.type.target, found.unit, trail);
812
+ }
813
+ return found;
814
+ }
815
+ const rootUnit = raw.units.find((u) => u.types.some((t) => t.name === raw.root));
816
+ if (!rootUnit) throw new Error("Modelo raiz ausente: " + raw.root);
817
+ const generated = /* @__PURE__ */ new Map();
818
+ function visit(name, unit) {
819
+ const found = resolve5(name, unit);
820
+ if ("primitive" in found) return primitives[found.primitive];
821
+ const { type, unit: declUnit } = found, key = type.name;
822
+ if (generated.has(key)) {
823
+ const node2 = generated.get(key);
824
+ if (node2.unit !== declUnit.name) throw new Error("Tipos hom\xF4nimos incompat\xEDveis: " + key);
825
+ return { kind: node2.kind === "object" ? "object" : node2.kind === "list" ? "list" : "enum", ref: key };
826
+ }
827
+ if (type.kind === "enum") {
828
+ const values = type.values.map((v) => v.name);
829
+ if (!values.length) throw new Error("Enum sem valores: " + key);
830
+ generated.set(key, { name: key, unit: declUnit.name, kind: "enum", values });
831
+ return { kind: "enum", ref: key };
832
+ }
833
+ if (type.kind !== "class") throw new Error("Declara\xE7\xE3o Pascal n\xE3o suportada: " + declUnit.name + "." + key + " (" + (type.declarationKind ?? type.kind) + ")");
834
+ const creator = type.methods?.find((m) => m.name.toLowerCase() === "new" && m.arguments === 0);
835
+ const indexed = type.properties?.find((p) => p.indexed && p.name.toLowerCase() === "items");
836
+ if (creator || indexed) {
837
+ if (!creator || !indexed || !indexed.readable) throw new Error("Cole\xE7\xE3o sem contrato New/Items tipado: " + key);
838
+ const item = resolve5(creator.result, declUnit), itemProperty = resolve5(indexed.type, declUnit);
839
+ if ("primitive" in item || "primitive" in itemProperty || item.type.name !== itemProperty.type.name) throw new Error("Cole\xE7\xE3o com tipos New/Items divergentes: " + key);
840
+ generated.set(key, { name: key, unit: declUnit.name, kind: "list", item: item.type.name, factory: creator.name });
841
+ if (visit(creator.result, declUnit).kind !== "object") throw new Error("Item de cole\xE7\xE3o n\xE3o \xE9 objeto: " + key);
842
+ return { kind: "list", ref: key };
843
+ }
844
+ const node = { name: key, unit: declUnit.name, kind: "object", properties: [] };
845
+ generated.set(key, node);
846
+ let inherited = [];
847
+ if (type.ancestor && !bases.has(type.ancestor.toLowerCase())) {
848
+ const ancestor = visit(type.ancestor, declUnit);
849
+ if (ancestor.kind !== "object") throw new Error("Heran\xE7a n\xE3o suportada: " + key);
850
+ inherited = generated.get(ancestor.ref).properties;
851
+ }
852
+ const props = new Map(inherited.map((p) => [p.name.toLowerCase(), p]));
853
+ for (const p of type.properties ?? []) {
854
+ if (p.indexed) throw new Error("Propriedade indexada fora de cole\xE7\xE3o: " + key + "." + p.name);
855
+ if (!p.readable) throw new Error("Propriedade sem leitura: " + key + "." + p.name);
856
+ const resolved = visit(p.type, declUnit);
857
+ const readonly = !p.writable && !["object", "list"].includes(resolved.kind) || key === raw.root && ["signature", "procnfe", "infnfesupl"].includes(p.name.toLowerCase());
858
+ props.set(p.name.toLowerCase(), { name: p.name, type: p.type, ...resolved, readonly, ...p.default ? { declaredDefault: p.default } : {} });
859
+ }
860
+ node.properties = [...props.values()].sort((a, b) => a.name.localeCompare(b.name, "en"));
861
+ return { kind: "object", ref: key };
862
+ }
863
+ visit(raw.root, rootUnit);
864
+ return { schemaVersion: 1, root: raw.root, types: [...generated.values()].sort((a, b) => a.name.localeCompare(b.name, "en")) };
865
+ }
866
+ function compareContracts(previous, current) {
867
+ const old = new Map(previous?.types.map((t) => [t.name, t]) ?? []), now = new Map(current.types.map((t) => [t.name, t]));
868
+ const additions = [], removals = [], changes = [];
869
+ for (const [name, type] of now) {
870
+ const before = old.get(name);
871
+ if (!before) {
872
+ additions.push(name);
873
+ continue;
874
+ }
875
+ if (type.kind !== before.kind) {
876
+ changes.push(name + ":kind");
877
+ continue;
878
+ }
879
+ if (type.kind === "object") {
880
+ const a = new Map(before.properties.map((p) => [p.name, p])), b = new Map(type.properties.map((p) => [p.name, p]));
881
+ for (const [field, p] of b) {
882
+ if (!a.has(field)) additions.push(name + "." + field);
883
+ else if (stable(a.get(field)) !== stable(p)) changes.push(name + "." + field);
884
+ }
885
+ for (const field of a.keys()) if (!b.has(field)) removals.push(name + "." + field);
886
+ } else if (type.kind === "enum") {
887
+ for (const v of type.values) if (!before.values.includes(v)) additions.push(name + "." + v);
888
+ for (const v of before.values) if (!type.values.includes(v)) removals.push(name + "." + v);
889
+ } else if (type.item !== before.item) changes.push(name + ":item");
890
+ }
891
+ for (const name of old.keys()) if (!now.has(name)) removals.push(name);
892
+ return { additions: additions.sort(), removals: removals.sort(), changes: changes.sort(), breaking: removals.length > 0 || changes.length > 0 };
893
+ }
894
+ function renderModelValidation() {
895
+ return String.raw`
896
+ export type CodigoValidacaoModelo = 'MODELO_DESCONHECIDO'|'ENUM_INVALIDO'|'ARRAY_ESPERADO'|'OBJETO_ESPERADO'|'CAMPO_DESCONHECIDO'|'CAMPO_SOMENTE_LEITURA'|'INTEIRO_INVALIDO'|'BOOLEANO_ESPERADO'|'DECIMAL_INVALIDO'|'DATA_HORA_INVALIDA'|'DATA_INVALIDA'|'TEXTO_ESPERADO';
897
+ function campoConhecido(at: unknown): string | undefined {
898
+ if(typeof at!=='string'||at.length>512||! /^[A-Za-z_]\w*(?:(?:\.[A-Za-z_]\w*)|(?:\[\d{1,7}\]))*$/.test(at))return undefined;
899
+ const parts=at.replace(/\[(\d+)\]/g,'.$1').split('.');let schema=Object.hasOwn(MODEL_SCHEMA,parts[0])?MODEL_SCHEMA[parts[0]]:undefined;
900
+ if(!schema)return undefined;
901
+ for(const part of parts.slice(1)){
902
+ if(schema.kind==='list'){if(! /^\d+$/.test(part))return undefined;schema=MODEL_SCHEMA[schema.item];}
903
+ else if(schema.kind==='object'){const p=schema.properties.find((p:any)=>p.name===part);if(!p)return undefined;schema=p.ref?MODEL_SCHEMA[p.ref]:{kind:p.kind};}
904
+ else return undefined;
905
+ }
906
+ return at;
907
+ }
908
+ /** TypeError compatível, com contexto seguro e sem o valor informado ou chaves desconhecidas. */
909
+ export class ErroValidacaoModelo extends TypeError {
910
+ readonly codigo: CodigoValidacaoModelo;
911
+ readonly diagnostico: Readonly<{codigo:CodigoValidacaoModelo;etapa:'documento';campo?:string;mensagem:string;acao:string;statusEnvio:'nao_enviado';causa:Readonly<{codigo:CodigoValidacaoModelo;etapa:'documento';campo?:string}>}>;
912
+ constructor(codigo: CodigoValidacaoModelo, at?: string) {
913
+ const catalogo:Record<CodigoValidacaoModelo,[string,string]>={
914
+ MODELO_DESCONHECIDO:['Modelo desconhecido.','Use um modelo exportado pelo cliente gerado.'],
915
+ ENUM_INVALIDO:['enum inválido','Use um dos valores textuais do enum exportado pelo cliente.'],
916
+ ARRAY_ESPERADO:['esperado array','Informe uma lista JSON entre colchetes.'],
917
+ OBJETO_ESPERADO:['esperado objeto','Informe um objeto JSON entre chaves.'],
918
+ CAMPO_DESCONHECIDO:['propriedade desconhecida','Confira os nomes permitidos neste grupo; a chave desconhecida não é registrada.'],
919
+ CAMPO_SOMENTE_LEITURA:['propriedade somente leitura','Remova este campo da entrada; o motor preenche seu resultado.'],
920
+ INTEIRO_INVALIDO:['inteiro fora do intervalo','Informe um número inteiro dentro do intervalo do campo.'],
921
+ BOOLEANO_ESPERADO:['esperado boolean','Informe true ou false como valor JSON, sem aspas.'],
922
+ DECIMAL_INVALIDO:['esperado decimal em string','Informe o decimal entre aspas, com ponto e a escala permitida pelo campo.'],
923
+ DATA_HORA_INVALIDA:['esperado data/hora civil ISO (sem timezone)','Informe a data/hora civil da UF como AAAA-MM-DDTHH:mm:ss, sem Z ou offset. Confira a data antes do envio.'],
924
+ DATA_INVALIDA:['data inválida','Confira dia, mês, ano e horário usando uma data civil válida.'],
925
+ TEXTO_ESPERADO:['esperado string','Informe texto entre aspas no JSON.']
926
+ };
927
+ const safeCode=Object.hasOwn(catalogo,codigo)?codigo:'MODELO_DESCONHECIDO';
928
+ const campo=campoConhecido(at),[texto,acao]=catalogo[safeCode],mensagem=(campo?campo+': ':'')+texto;
929
+ super(mensagem);this.codigo=safeCode;
930
+ const causa=Object.freeze({codigo:safeCode,etapa:'documento' as const,...(campo?{campo}:{})});
931
+ this.diagnostico=Object.freeze({codigo:safeCode,etapa:'documento' as const,...(campo?{campo}:{}),mensagem,acao,statusEnvio:'nao_enviado' as const,causa});
932
+ Object.defineProperty(this,'cause',{value:causa,enumerable:false});
933
+ }
934
+ toJSON(){return this.diagnostico;}
935
+ }
936
+ export function validateModel(model: string, value: unknown, at=model): void {
937
+ const schema=Object.hasOwn(MODEL_SCHEMA,model)?MODEL_SCHEMA[model]:undefined;
938
+ if(!schema)throw new ErroValidacaoModelo('MODELO_DESCONHECIDO');
939
+ at=campoConhecido(at)??model;
940
+ if(schema.kind==='enum'){if(typeof value!=='string'||!schema.values.includes(value))throw new ErroValidacaoModelo('ENUM_INVALIDO',at);return;}
941
+ if(schema.kind==='list'){if(!Array.isArray(value))throw new ErroValidacaoModelo('ARRAY_ESPERADO',at);value.forEach((item,index)=>validateModel(schema.item,item,at+'['+index+']'));return;}
942
+ if(value===null||typeof value!=='object'||Array.isArray(value))throw new ErroValidacaoModelo('OBJETO_ESPERADO',at);
943
+ const fields=new Map<string,any>(schema.properties.filter((p:any)=>!p.readonly).map((p:any)=>[p.name,p]));
944
+ for(const [name,v] of Object.entries(value)){
945
+ if(v===undefined)continue;
946
+ const p=fields.get(name);
947
+ if(!p){const readonly=schema.properties.some((p:any)=>p.name===name&&p.readonly);throw new ErroValidacaoModelo(readonly?'CAMPO_SOMENTE_LEITURA':'CAMPO_DESCONHECIDO',readonly?at+'.'+name:at);}
948
+ const field=at+'.'+name;
949
+ if(p.ref){validateModel(p.ref,v,field);continue;}
950
+ if(p.kind==='integer'){if(typeof v!=='number'||!Number.isSafeInteger(v)||v<p.min||v>p.max)throw new ErroValidacaoModelo('INTEIRO_INVALIDO',field);}
951
+ else if(p.kind==='boolean'){if(typeof v!=='boolean')throw new ErroValidacaoModelo('BOOLEANO_ESPERADO',field);}
952
+ else if(p.kind==='decimal'){if(typeof v!=='string'||v.length>64||! /^-?\d+(?:\.\d+)?$/.test(v)||p.scale!==undefined&&(v.split('.')[1]?.length??0)>p.scale)throw new ErroValidacaoModelo('DECIMAL_INVALIDO',field);}
953
+ else if(p.kind==='datetime'){
954
+ if(typeof v!=='string'||! /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?)?$/.test(v)||Number.isNaN(Date.parse(v+(v.length===10?'T00:00:00Z':'Z'))))throw new ErroValidacaoModelo('DATA_HORA_INVALIDA',field);
955
+ const date=new Date(v+(v.length===10?'T00:00:00Z':'Z'));if(date.toISOString().slice(0,10)!==v.slice(0,10))throw new ErroValidacaoModelo('DATA_INVALIDA',field);
956
+ }else if(typeof v!=='string')throw new ErroValidacaoModelo('TEXTO_ESPERADO',field);
957
+ }
958
+ }
959
+ export function validateTNFe(value: unknown): asserts value is TNFeInput { validateModel('TNFe',value); }
960
+ `;
961
+ }
962
+ function renderTypeScript(ir, revision2, contractHash) {
963
+ const out = ["// Generated from ACBr AST. LGPL-2.1-or-later. Do not edit.", "export const ACBR_CONTRACT = " + stable({ sourceRevision: revision2, contractHash }) + " as const;", "export const SOURCE_REVISION=ACBR_CONTRACT.sourceRevision;", "export const CONTRACT_HASH=ACBR_CONTRACT.contractHash;"];
964
+ for (const t of ir.types) {
965
+ if (t.kind === "enum") {
966
+ out.push("export const " + t.name + " = Object.freeze(" + stable(Object.fromEntries(t.values.map((v) => [v, v]))) + " as const);", "export type " + t.name + " = typeof " + t.name + "[keyof typeof " + t.name + "];");
967
+ } else if (t.kind === "list") {
968
+ out.push("export type " + t.name + "Input = " + t.item + "Input[];", "export class " + t.name + " extends Array<" + t.item + "> {", " New(input: " + t.item + "Input = {}): " + t.item + " { const item=new " + t.item + "(input); this.push(item); return item; }", "}");
969
+ } else {
970
+ out.push("export interface " + t.name + "Input {");
971
+ for (const p of t.properties.filter((p2) => !p2.readonly)) out.push(" " + JSON.stringify(p.name) + "?: " + tsType(p) + ";");
972
+ out.push("}", "export class " + t.name + " {");
973
+ for (const p of t.properties) {
974
+ if (p.readonly) {
975
+ out.push(" readonly " + JSON.stringify(p.name) + "?: " + tsType(p) + ";");
976
+ continue;
977
+ }
978
+ if (p.declaredDefault) out.push(" /** Pascal streaming default: " + p.declaredDefault.replaceAll("*/", "") + ". Omission preserves the native constructor. */");
979
+ if (p.kind === "object" || p.kind === "list") out.push(" " + JSON.stringify(p.name) + " = new " + p.ref + "();");
980
+ else out.push(" " + JSON.stringify(p.name) + "?: " + tsType(p) + ";");
981
+ }
982
+ out.push(" constructor(input: " + t.name + "Input = {}) {", " validateModel(" + JSON.stringify(t.name) + ", input);");
983
+ for (const p of t.properties.filter((p2) => !p2.readonly)) {
984
+ const access5 = "input[" + JSON.stringify(p.name) + "]", target = "this[" + JSON.stringify(p.name) + "]";
985
+ out.push(" if (" + access5 + " !== undefined) " + target + " = " + (p.kind === "object" ? "new " + p.ref + "(" + access5 + ")" : p.kind === "list" ? "Object.assign(new " + p.ref + "(), " + access5 + ".map(v=>new " + ir.types.find((t2) => t2.name === p.ref).item + "(v)))" : access5) + ";");
986
+ }
987
+ out.push(" }", "}");
988
+ }
989
+ }
990
+ out.push("const MODEL_SCHEMA: Record<string, any> = " + stable(Object.fromEntries(ir.types.map((t) => [t.name, t]))) + ";");
991
+ out.push(renderModelValidation());
992
+ return out.join("\n") + "\n";
993
+ }
994
+ function renderContractMetadata(ir, sourceRevision, sourceHash, contractHash) {
995
+ if (hash(stable({ sourceRevision, sourceHash, ir })) !== contractHash) throw new Error("Hash do contrato diverge dos metadados gerados.");
996
+ return stable({ formatVersion: 1, sourceRevision, sourceHash, contractHash, ir }) + "\n";
997
+ }
998
+ function renderPascal(ir, revision2, contractHash) {
999
+ const classes = ir.types.filter((t) => t.kind === "object"), byName = new Map(ir.types.map((t) => [t.name, t]));
1000
+ const units = [...new Set(ir.types.map((t) => t.unit))].sort();
1001
+ const out = ["{ Generated from ACBr AST. LGPL-2.1-or-later. Do not edit. }", "unit AcbrModels;", "{$mode delphi}{$H+}", "interface", "uses SysUtils, Classes, fpjson, DateUtils, Math, " + units.join(", ") + ";", "const SourceRevision = " + revision2 + ";", " ContractHash = '" + contractHash + "';", "procedure preencherTNFe(documento:TJSONObject; destino:TNFe);", "implementation"];
1002
+ out.push(String.raw`
1003
+ procedure Bad(const P,M:string); begin raise Exception.Create(P+': '+M) end;
1004
+ function Obj(D:TJSONData;const P:string):TJSONObject;
1005
+ begin if (D=nil) or (D.JSONType<>jtObject) then Bad(P,'esperado objeto');Result:=TJSONObject(D) end;
1006
+ function Arr(D:TJSONData;const P:string):TJSONArray;
1007
+ begin if (D=nil) or (D.JSONType<>jtArray) then Bad(P,'esperado array');Result:=TJSONArray(D) end;
1008
+ function Text(D:TJSONData;const P:string):string;
1009
+ begin if (D=nil) or (D.JSONType<>jtString) then Bad(P,'esperado string');Result:=D.AsString end;
1010
+ function IntValue(D:TJSONData;const P:string;MinV,MaxV:Int64):Int64;
1011
+ var V:Extended;
1012
+ begin
1013
+ if (D=nil) or (D.JSONType<>jtNumber) then Bad(P,'esperado inteiro');
1014
+ V:=D.AsFloat;if IsNan(V) or IsInfinite(V) or (Frac(V)<>0) or (V<MinV) or (V>MaxV) then Bad(P,'inteiro fora do intervalo');
1015
+ Result:=D.AsInt64;
1016
+ end;
1017
+ function BoolValue(D:TJSONData;const P:string):boolean;
1018
+ begin if (D=nil) or (D.JSONType<>jtBoolean) then Bad(P,'esperado boolean');Result:=D.AsBoolean end;
1019
+ function DecimalText(D:TJSONData;const P:string;Scale:integer):string;
1020
+ var I,PointPos:integer;
1021
+ begin
1022
+ Result:=Text(D,P);PointPos:=0;
1023
+ if (Result='') or (Length(Result)>64) then Bad(P,'decimal inválido');
1024
+ for I:=1 to Length(Result) do begin
1025
+ if Result[I]='.' then begin if (PointPos>0) or (I=1) or ((I=2) and (Result[1]='-')) or (I=Length(Result)) then Bad(P,'decimal inválido');PointPos:=I end
1026
+ else if (Result[I]='-') and (I=1) then begin if Length(Result)=1 then Bad(P,'decimal inválido') end
1027
+ else if not (Result[I] in ['0'..'9']) then Bad(P,'decimal inválido');
1028
+ end;
1029
+ if (PointPos>0) and (Scale>=0) and (Length(Result)-PointPos>Scale) then Bad(P,'casas decimais excedidas');
1030
+ end;
1031
+ function FloatValue(D:TJSONData;const P:string):Extended;
1032
+ var F:TFormatSettings;S:string;
1033
+ begin F:=DefaultFormatSettings;F.DecimalSeparator:='.';F.ThousandSeparator:=#0;S:=DecimalText(D,P,-1);
1034
+ if not TryStrToFloat(S,Result,F) or IsNan(Result) or IsInfinite(Result) then Bad(P,'decimal fora do intervalo');
1035
+ end;
1036
+ function CurrencyValue(D:TJSONData;const P:string):Currency;
1037
+ var F:TFormatSettings;S:string;
1038
+ begin F:=DefaultFormatSettings;F.DecimalSeparator:='.';F.ThousandSeparator:=#0;S:=DecimalText(D,P,4);
1039
+ if not TryStrToCurr(S,Result,F) then Bad(P,'currency fora do intervalo');
1040
+ end;
1041
+ function DateValue(D:TJSONData;const P:string):TDateTime;
1042
+ var S:string;I:integer;
1043
+ begin
1044
+ S:=Text(D,P);
1045
+ if not (Length(S) in [10,19,21,22,23]) then Bad(P,'esperado data/hora civil ISO sem timezone');
1046
+ for I:=1 to Length(S) do if not ((S[I] in ['0'..'9']) or ((I in [5,8]) and (S[I]='-')) or ((I=11) and (S[I]='T')) or ((I in [14,17]) and (S[I]=':')) or ((I=20) and (S[I]='.'))) then Bad(P,'data ISO inválida');
1047
+ if not TryISO8601ToDate(S,Result,true) then Bad(P,'data ISO inválida');
1048
+ end;
1049
+ `);
1050
+ const q = (s) => "'" + s.replaceAll("'", "''") + "'";
1051
+ for (const t of classes) out.push("procedure Load_" + t.name + "(D:TJSONObject;destino:" + t.unit + "." + t.name + ";const P:string); forward;");
1052
+ for (const t of classes) {
1053
+ out.push("procedure Load_" + t.name + "(D:TJSONObject;destino:" + t.unit + "." + t.name + ";const P:string);", "var I,J:integer;V:TJSONData;A:TJSONArray;K,At:string;", "begin", " if destino=nil then Bad(P,'objeto ACBr n\xE3o inicializado');", " for I:=0 to D.Count-1 do begin", " K:=D.Names[I];V:=D.Items[I];At:=P+'.'+K;");
1054
+ let index = 0;
1055
+ for (const p of t.properties.filter((p2) => !p2.readonly)) {
1056
+ out.push(" " + (index++ ? "else " : "") + "if K=" + q(p.name) + " then begin");
1057
+ const target = "destino." + p.name;
1058
+ if (p.kind === "object") out.push(" Load_" + p.ref + "(Obj(V,At)," + target + ",At);");
1059
+ else if (p.kind === "list") {
1060
+ const list = byName.get(p.ref);
1061
+ out.push(" A:=Arr(V,At);if " + target + "=nil then Bad(At,'cole\xE7\xE3o n\xE3o inicializada');" + target + ".Clear;", " for J:=0 to A.Count-1 do Load_" + list.item + "(Obj(A.Items[J],At+'['+IntToStr(J)+']')," + target + "." + list.factory + ",At+'['+IntToStr(J)+']');");
1062
+ } else if (p.kind === "enum") {
1063
+ const enumeration = byName.get(p.ref);
1064
+ out.push(...enumeration.values.map((v, i) => " " + (i ? "else " : "") + "if Text(V,At)=" + q(v) + " then " + target + ":=" + enumeration.unit + "." + v), " else Bad(At,'enum inv\xE1lido');");
1065
+ } else out.push(" " + target + ":=" + { string: "Text(V,At)", integer: "IntValue(V,At," + p.min + "," + p.max + ")", boolean: "BoolValue(V,At)", datetime: "DateValue(V,At)", decimal: p.scale === 4 ? "CurrencyValue(V,At)" : "FloatValue(V,At)" }[p.kind] + ";");
1066
+ out.push(" end");
1067
+ }
1068
+ out.push((index ? " else " : " ") + "Bad(At,'propriedade desconhecida ou somente leitura');", " end;", "end;");
1069
+ }
1070
+ out.push("procedure preencherTNFe(documento:TJSONObject;destino:TNFe);", "begin if documento=nil then Bad('TNFe','esperado objeto');Load_TNFe(documento,destino,'TNFe') end;", "end.");
1071
+ return out.join("\n") + "\n";
1050
1072
  }
1051
- async function checkBuild(config) {
1052
- const lock = await verifySource(config);
1053
- const generated = await generatedManifest(config);
1054
- const directory = runtimeDirectory(config);
1055
- const manifest = JSON.parse(await readFile3(join2(directory, "manifest.json"), "utf8"));
1056
- if (manifest.formatVersion !== 1 || manifest.platform !== process.platform || manifest.arch !== process.arch || manifest.sourceRevision !== lock.source.revision || generated.sourceHash !== lock.source.treeHash || manifest.contractHash !== generated.contractHash || !manifest.generatedFileHashes || Object.entries(generated.fileHashes).some(([name, hash2]) => manifest.generatedFileHashes[name] !== hash2) || typeof manifest.executable !== "string" || !manifest.files || !Object.hasOwn(manifest.files, manifest.executable)) throw new Error("Runtime diverge das fontes ou contrato. Execute build.");
1057
- for (const [path3, expected] of Object.entries(manifest.files)) {
1058
- if (path3.startsWith("/") || path3.includes("\\") || path3.split("/").includes("..") || !/^[a-f0-9]{64}$/.test(expected)) throw new Error(`Caminho/hash inv\xE1lido no runtime: ${path3}.`);
1059
- if (await fileHash(join2(directory, path3)) !== expected) throw new Error(`Hash inv\xE1lido no runtime: ${path3}.`);
1060
- }
1061
- return manifest;
1073
+ function renderClientIndex() {
1074
+ return [
1075
+ "// Generated client bound to its own ACBr contract. Do not edit.",
1076
+ "import { criarEmissor as criarRuntime, diagnosticarErro as diagnosticarErroRuntime, diagnosticarResultado, type OpcoesEmissor, type OpcoesOperacao } from " + JSON.stringify("cosmemilton-acbr-node/runtime") + ";",
1077
+ "import { ACBR_CONTRACT, validateTNFe, ErroValidacaoModelo, type TNFeInput } from " + JSON.stringify("./models.js") + ";",
1078
+ "export * from " + JSON.stringify("./models.js") + ";",
1079
+ "export { diagnosticarResultado };",
1080
+ "export function diagnosticarErro(erro:unknown) { return erro instanceof ErroValidacaoModelo ? erro.diagnostico : diagnosticarErroRuntime(erro); }",
1081
+ "export function criarEmissor(options: Omit<OpcoesEmissor, " + JSON.stringify("contrato") + " | " + JSON.stringify("validaDocumento") + ">) {",
1082
+ " const emissor=criarRuntime({...options, contrato:ACBR_CONTRACT, validaDocumento:validateTNFe});",
1083
+ " return {...emissor, gerarXml(documento:TNFeInput, opcoes?:OpcoesOperacao) { return emissor.gerarXml(documento as unknown as Record<string,unknown>, opcoes); }};",
1084
+ "}"
1085
+ ].join("\n") + "\n";
1062
1086
  }
1063
- async function doctor(config) {
1064
- const items = [{ name: "Node.js", ok: Number(process.versions.node.split(".")[0]) > 22 || Number(process.versions.node.split(".")[0]) === 22 && Number(process.versions.node.split(".")[1]) >= 12, detail: process.versions.node }];
1065
- for (const [name, command, args] of [["SVN", "svn", ["--version", "--quiet"]], ["Free Pascal", config?.native.fpc ?? "fpc", ["-iV"]]]) {
1066
- try {
1067
- const result = await runCommand(command, [...args]);
1068
- items.push({ name, ok: true, detail: result.stdout.trim() });
1069
- } catch (error) {
1070
- items.push({ name, ok: false, detail: error.message });
1071
- }
1072
- }
1073
- if (config) {
1074
- try {
1075
- items.push({ name: "Lazarus", ok: true, detail: await findLazarus(config) });
1076
- } catch (error) {
1077
- items.push({ name: "Lazarus", ok: false, detail: error.message });
1078
- }
1079
- try {
1080
- const lock = await verifySource(config);
1081
- items.push({ name: "Fontes ACBr", ok: true, detail: `revis\xE3o ${lock.source.revision}, ${lock.source.treeHash}` });
1082
- } catch (error) {
1083
- items.push({ name: "Fontes ACBr", ok: false, detail: error.message });
1087
+ async function fingerprint(dir) {
1088
+ const files = [];
1089
+ async function walk(d) {
1090
+ for (const entry of await readdir4(d, { withFileTypes: true })) {
1091
+ const f = path2.join(d, entry.name);
1092
+ if (entry.isDirectory()) await walk(f);
1093
+ else if (/\.(pas|pp|inc|xsd)$/i.test(entry.name)) files.push(f);
1084
1094
  }
1085
1095
  }
1086
- if (process.platform === "linux") {
1087
- try {
1088
- const result = await runCommand("ldconfig", ["-p"]);
1089
- const missing = REQUIRED_DYNAMIC.filter((name) => !result.stdout.includes(name));
1090
- items.push({ name: "OpenSSL/libxml2 din\xE2micos", ok: missing.length === 0, detail: missing.length ? `Ausentes: ${missing.join(", ")}` : REQUIRED_DYNAMIC.join(", ") });
1091
- } catch (error) {
1092
- items.push({ name: "OpenSSL/libxml2 din\xE2micos", ok: false, detail: error.message });
1093
- }
1096
+ await walk(dir);
1097
+ const digest = createHash3("sha256");
1098
+ for (const f of files.sort()) {
1099
+ digest.update(path2.relative(dir, f).replaceAll("\\", "/"));
1100
+ digest.update(await readFile5(f));
1094
1101
  }
1095
- return items;
1102
+ return digest.digest("hex");
1096
1103
  }
1097
- async function copyCompilerLicenses(config, stage, lazarus) {
1098
- const packagedLazarus = fileURLToPath(new URL("../docs/licenses/lazarus/", import.meta.url));
1099
- const packagedFpc = fileURLToPath(new URL("../docs/licenses/fpc/", import.meta.url));
1100
- const notices = {};
1101
- async function copyNotice(name, candidates2) {
1102
- for (const source of candidates2) if (await exists(source)) {
1103
- await copyFile2(source, join2(stage, "licenses", name));
1104
- notices[name] = { source, sha256: await fileHash(source) };
1105
- return;
1106
- }
1107
- throw new Error(`Notice obrigat\xF3rio ausente: ${name}.`);
1108
- }
1109
- for (const name of ["COPYING.txt", "COPYING.LGPL.txt", "COPYING.modifiedLGPL.txt"]) {
1110
- await copyNotice(`Lazarus-${name}`, [join2(lazarus, name), join2(lazarus, "docs", name), join2(packagedLazarus, name)]);
1111
- }
1112
- if (await exists(join2(packagedLazarus, "ORIGIN.json"))) await copyFile2(join2(packagedLazarus, "ORIGIN.json"), join2(stage, "licenses/Lazarus-notice-origin.json"));
1113
- const fpcRoot = resolve3(dirname3(config.native.fpc), "../..");
1114
- const sourceRoots = [join2(fpcRoot, "source"), join2(lazarus, "fpc/3.2.2/source"), "/usr/share/fpcsrc/3.2.2"];
1115
- for (const [name, sourceRelative] of [["COPYING.GPL.txt", "compiler/COPYING.txt"], ["COPYING.LGPL.txt", "rtl/COPYING.txt"], ["COPYING.FPC", "rtl/COPYING.FPC"]]) {
1116
- await copyNotice(`FPC-${name}`, [...sourceRoots.map((directory) => join2(directory, sourceRelative)), join2(packagedFpc, name)]);
1104
+ async function generateModel(options) {
1105
+ const root = path2.resolve(options.outputDir), cache = path2.join(root, ".acbr/generated"), bin = path2.join(root, ".acbr/bin");
1106
+ const models = path2.resolve(root, options.modelOutputDir ?? "generated/acbr"), native = path2.resolve(root, options.nativeOutputDir ?? "native/generated");
1107
+ await Promise.all([mkdir4(cache, { recursive: true }), mkdir4(bin, { recursive: true }), mkdir4(models, { recursive: true }), mkdir4(native, { recursive: true })]);
1108
+ const extractor = options.extractorPath ?? fileURLToPath2(new URL("../tools/extract-model.lpr", import.meta.url));
1109
+ const executable = path2.join(bin, "extract-model" + (process.platform === "win32" ? ".exe" : ""));
1110
+ try {
1111
+ await execute(options.fpcPath ?? "fpc", ["-Mobjfpc", "-Sh", "-FU" + bin, "-FE" + bin, extractor], { cwd: root, maxBuffer: 8 * 1024 * 1024 });
1112
+ await execute(executable, [path2.resolve(options.acbrRoot), path2.join(cache, "raw-model.json"), process.platform === "win32" ? "win64" : "linux"], { cwd: root, maxBuffer: 8 * 1024 * 1024 });
1113
+ } catch (error) {
1114
+ const e = error;
1115
+ throw new Error("Extra\xE7\xE3o FCL-passrc falhou: " + (e.stderr ?? "") + (e.stdout ?? "") + e.message);
1117
1116
  }
1118
- if (await exists(join2(packagedFpc, "ORIGIN.json"))) await copyFile2(join2(packagedFpc, "ORIGIN.json"), join2(stage, "licenses/FPC-notice-origin.json"));
1119
- const candidates = [join2(fpcRoot, "doc"), fpcRoot, join2(lazarus, "fpc"), "/usr/share/doc/fp-compiler-3.2.2", "/usr/share/doc/fp-units-rtl-3.2.2"];
1120
- for (const directory of candidates) {
1121
- if (!await exists(directory)) continue;
1122
- for (const name of await readdir3(directory)) {
1123
- if (/^(?:copying|license|copyright)/i.test(name) && (await stat2(join2(directory, name))).isFile()) await copyFile2(join2(directory, name), join2(stage, "licenses", `FPC-${basename(directory)}-${name}`));
1124
- }
1117
+ const raw = JSON.parse(await readFile5(path2.join(cache, "raw-model.json"), "utf8"));
1118
+ const ir = buildModelIR(raw), sourceRevision = Number(options.revision);
1119
+ if (!Number.isSafeInteger(sourceRevision) || sourceRevision < 1) throw new Error("Revis\xE3o SVN inv\xE1lida");
1120
+ const sourceHash = options.sourceHash ?? await fingerprint(options.acbrRoot), contractHash = hash(stable({ sourceRevision, sourceHash, ir }));
1121
+ let previous;
1122
+ try {
1123
+ previous = JSON.parse(await readFile5(path2.join(cache, "model.ir.json"), "utf8"));
1124
+ } catch (error) {
1125
+ if (error.code !== "ENOENT") throw error;
1125
1126
  }
1126
- await writeFile3(join2(stage, "licenses/toolchain-notices.json"), `${JSON.stringify(notices, null, 2)}
1127
- `);
1127
+ const report = compareContracts(previous, ir), reportPath = path2.join(cache, "changes.json"), manifestPath = path2.join(cache, "manifest.json");
1128
+ const files = [path2.relative(root, path2.join(models, "models.ts")), path2.relative(root, path2.join(models, "index.ts")), path2.relative(root, path2.join(native, "AcbrModels.pas"))].map((f) => f.replaceAll("\\", "/"));
1129
+ const content = [renderTypeScript(ir, sourceRevision, contractHash), renderClientIndex(), renderPascal(ir, sourceRevision, contractHash)];
1130
+ const fileHashes = Object.fromEntries(files.map((file, index) => [file, hash(content[index])]));
1131
+ const metadataPath = path2.join(models, "contract.json"), metadataContent = renderContractMetadata(ir, sourceRevision, sourceHash, contractHash);
1132
+ await Promise.all([
1133
+ ...files.map((file, index) => writeFile4(path2.resolve(root, file), content[index], "utf8")),
1134
+ writeFile4(path2.join(cache, "model.ir.json"), JSON.stringify(ir, null, 2) + "\n", "utf8"),
1135
+ writeFile4(metadataPath, metadataContent, "utf8"),
1136
+ writeFile4(reportPath, JSON.stringify(report, null, 2) + "\n", "utf8"),
1137
+ writeFile4(manifestPath, JSON.stringify({ schemaVersion: 1, sourceRevision, sourceHash, contractHash, root: ir.root, models: ir.types.length, files, fileHashes, metadata: { file: path2.relative(root, metadataPath).replaceAll("\\", "/"), sha256: hash(metadataContent) } }, null, 2) + "\n", "utf8")
1138
+ ]);
1139
+ return { contractHash, sourceHash, models: ir.types.length, reportPath, manifestPath, metadataPath };
1128
1140
  }
1129
-
1130
- // src/runtime.ts
1131
- import { spawn as spawn2 } from "node:child_process";
1132
- import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
1133
- import path from "node:path";
1134
- import { createRequire } from "node:module";
1135
- import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
1136
- import { TextDecoder } from "node:util";
1141
+ var execute, bases, primitives, stable, hash, tsType;
1142
+ var init_generator = __esm({
1143
+ "src/generator.ts"() {
1144
+ "use strict";
1145
+ execute = promisify(execFile);
1146
+ bases = /* @__PURE__ */ new Set(["tobject", "tpersistent", "tacbrobjectlist"]);
1147
+ primitives = {
1148
+ string: { kind: "string" },
1149
+ ansistring: { kind: "string" },
1150
+ unicodestring: { kind: "string" },
1151
+ widestring: { kind: "string" },
1152
+ boolean: { kind: "boolean" },
1153
+ byte: { kind: "integer", min: 0, max: 255 },
1154
+ word: { kind: "integer", min: 0, max: 65535 },
1155
+ integer: { kind: "integer", min: -2147483648, max: 2147483647 },
1156
+ longint: { kind: "integer", min: -2147483648, max: 2147483647 },
1157
+ smallint: { kind: "integer", min: -32768, max: 32767 },
1158
+ shortint: { kind: "integer", min: -128, max: 127 },
1159
+ cardinal: { kind: "integer", min: 0, max: 4294967295 },
1160
+ longword: { kind: "integer", min: 0, max: 4294967295 },
1161
+ int64: { kind: "integer", min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
1162
+ qword: { kind: "integer", min: 0, max: Number.MAX_SAFE_INTEGER },
1163
+ double: { kind: "decimal" },
1164
+ extended: { kind: "decimal" },
1165
+ single: { kind: "decimal" },
1166
+ currency: { kind: "decimal", scale: 4 },
1167
+ tdatetime: { kind: "datetime" },
1168
+ tdate: { kind: "datetime" },
1169
+ ttime: { kind: "datetime" }
1170
+ };
1171
+ stable = (value) => JSON.stringify(value);
1172
+ hash = (value) => createHash3("sha256").update(value).digest("hex");
1173
+ tsType = (p) => p.kind === "object" ? p.ref + "Input" : p.kind === "list" ? p.ref + "Input" : p.kind === "enum" ? p.ref : p.kind === "integer" ? "number" : p.kind === "boolean" ? "boolean" : "string";
1174
+ }
1175
+ });
1137
1176
 
1138
1177
  // src/diagnostics.ts
1139
- var ETAPAS = /* @__PURE__ */ new Set(["configuracao", "documento", "runtime", "geracao", "validacao", "assinatura", "transmissao", "consulta", "cancelamento", "carta_correcao", "inutilizacao", "operacao", "limpeza"]);
1140
- 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"]);
1141
- var CATALOGO = {
1142
- CONFIGURACAO_INVALIDA: ["configuracao", "A configura\xE7\xE3o cont\xE9m um campo inv\xE1lido.", "Confira o campo indicado e seu tipo antes de continuar."],
1143
- CONTRATO_INVALIDO: ["configuracao", "O contrato do cliente \xE9 inv\xE1lido.", "Use o contrato gerado junto com o cliente."],
1144
- 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."],
1145
- CERTIFICADO_DIVERGENTE: ["assinatura", "O certificado n\xE3o corresponde \xE0 raiz CNPJ do emitente.", "Confira o CNPJ configurado e selecione o A1 correspondente ao emitente."],
1146
- 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."],
1147
- SCHEMAS_AUSENTES: ["runtime", "Os schemas fiscais n\xE3o est\xE3o dispon\xEDveis.", "Reinstale o runtime completo da plataforma."],
1148
- SERVICOS_AUSENTES: ["runtime", "A configura\xE7\xE3o dos servi\xE7os fiscais n\xE3o est\xE1 dispon\xEDvel.", "Reinstale o runtime completo da plataforma."],
1149
- 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."],
1150
- 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."],
1151
- 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."],
1152
- ASSINATURA_INVALIDA: ["assinatura", "A assinatura do XML n\xE3o foi validada.", "Confira o A1 correspondente e use o XML assinado sem altera\xE7\xF5es."],
1153
- XML_NAO_ASSINADO: ["assinatura", "A opera\xE7\xE3o exige XML previamente assinado.", "Conclua a assinatura e a valida\xE7\xE3o antes de transmitir."],
1154
- XML_ALTERADO: ["assinatura", "O XML assinado foi alterado.", "Use exatamente o XML assinado e persistido; n\xE3o edite seu conte\xFAdo."],
1155
- 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."],
1156
- 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."],
1157
- 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."],
1158
- CSC_INVALIDO: ["configuracao", "A configura\xE7\xE3o do CSC \xE9 inv\xE1lida.", "Confira id e valor do CSC sem registrar seu conte\xFAdo."],
1159
- PLATAFORMA_NAO_SUPORTADA: ["runtime", "A plataforma n\xE3o \xE9 suportada.", "Execute em Windows ou Linux x64 com Node.js 22.12 ou superior."],
1160
- RUNTIME_AUSENTE: ["runtime", "O motor fiscal n\xE3o foi encontrado.", "Instale o runtime da plataforma incluindo depend\xEAncias opcionais."],
1161
- RUNTIME_INVALIDO: ["runtime", "O runtime fiscal \xE9 inv\xE1lido.", "Use um runtime distribu\xEDdo e compat\xEDvel com a plataforma."],
1162
- RUNTIME_INCOMPLETO: ["runtime", "Falta um arquivo do runtime fiscal.", "Reinstale o runtime da plataforma."],
1163
- RUNTIME_ALTERADO: ["runtime", "A integridade do runtime fiscal n\xE3o foi confirmada.", "Reinstale o runtime; n\xE3o desative a verifica\xE7\xE3o dos hashes."],
1164
- CONTRATO_DIVERGENTE: ["runtime", "Cliente e motor usam contratos diferentes.", "Use vers\xF5es compat\xEDveis ou regenere e recompile ambos."],
1165
- 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."],
1166
- 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."],
1167
- OPERACAO_CANCELADA: ["operacao", "A opera\xE7\xE3o foi cancelada.", "Confira o estado do envio antes de decidir continuar."],
1168
- TIMEOUT_MOTOR: ["runtime", "O motor excedeu o tempo de espera.", "Confira o estado do envio antes de repetir a opera\xE7\xE3o."],
1169
- EMISSOR_FECHADO: ["operacao", "O emissor foi encerrado.", "Crie um novo emissor para continuar."],
1170
- 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."],
1171
- 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."],
1172
- RESPOSTA_EXCESSIVA: ["runtime", "A resposta do motor excedeu o limite.", "Confira o tamanho da opera\xE7\xE3o e a vers\xE3o do runtime."],
1173
- RESPOSTA_INVALIDA: ["runtime", "O motor devolveu uma resposta inv\xE1lida.", "Confira a compatibilidade do runtime e o estado do envio."],
1174
- 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."],
1175
- 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."],
1176
- CERTIFICADO_EXCESSIVO: ["configuracao", "O certificado excede o limite de tamanho.", "Use um arquivo A1 de at\xE9 2 MiB."],
1177
- 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."],
1178
- FILA_CHEIA: ["operacao", "A fila fiscal est\xE1 cheia.", "Aguarde a opera\xE7\xE3o atual terminar antes de iniciar outra."],
1179
- 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."],
1180
- CHAVE_INVALIDA: ["documento", "A chave fiscal tem formato inv\xE1lido.", "Informe a chave como texto com 44 d\xEDgitos."],
1181
- RECIBO_INVALIDO: ["documento", "O recibo tem formato inv\xE1lido.", "Informe o recibo como texto com 15 d\xEDgitos."],
1182
- JUSTIFICATIVA_INVALIDA: ["documento", "A justificativa tem tamanho inv\xE1lido.", "Informe uma justificativa com 15 a 255 caracteres."],
1183
- PROTOCOLO_INVALIDO: ["documento", "O protocolo tem formato inv\xE1lido.", "Informe o protocolo como texto com 15 d\xEDgitos."],
1184
- 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."],
1185
- 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."],
1186
- INUTILIZACAO_INVALIDA: ["documento", "A faixa de inutiliza\xE7\xE3o \xE9 inv\xE1lida.", "Confira ano, s\xE9rie e n\xFAmeros inicial e final."],
1187
- 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."]
1188
- };
1178
+ function base64XmlRecuperadoValido(value) {
1179
+ if (typeof value !== "string" || value.length === 0 || value.length > Math.ceil(MAX_RECOVERED_XML_BYTES / 3) * 4) return false;
1180
+ const bytes = Buffer.from(value, "base64");
1181
+ return bytes.length > 0 && bytes.length <= MAX_RECOVERED_XML_BYTES && bytes.toString("base64") === value;
1182
+ }
1189
1183
  function etapaDaOperacao(comando) {
1190
- return { gerarXml: "geracao", validar: "validacao", assinar: "assinatura", transmitir: "transmissao", consultar: "consulta", cancelar: "cancelamento", cartaCorrecao: "carta_correcao", inutilizar: "inutilizacao" }[comando] ?? "operacao";
1184
+ return { gerarXml: "geracao", validar: "validacao", assinar: "assinatura", transmitir: "transmissao", consultar: "consulta", recuperarXml: "consulta", cancelar: "cancelamento", cartaCorrecao: "carta_correcao", inutilizar: "inutilizacao" }[comando] ?? "operacao";
1191
1185
  }
1192
1186
  function criarDiagnosticoErro(codigo, desconhecido = false, detalhes = {}) {
1193
1187
  const safeCode = Object.hasOwn(CATALOGO, codigo) ? codigo : "FALHA_LOCAL";
@@ -1224,18 +1218,30 @@ function diagnosticarResultado(resultado, comando) {
1224
1218
  const protocolo = typeof resultado.protocolo === "string" && /^\d{15}$/.test(resultado.protocolo);
1225
1219
  const chave = typeof resultado.chave === "string" && /^\d{44}$/.test(resultado.chave);
1226
1220
  const autorizacao = (comando === "transmitir" || comando === "consultar") && resultado.estado === "AUTORIZADO" && [100, 150].includes(resultado.cStat) && protocolo && chave && (comando === "consultar" || resultado.envioIniciado !== false);
1221
+ const xmlRecuperado = comando === "recuperarXml" && base64XmlRecuperadoValido(resultado.xmlBase64);
1222
+ const recuperacao = comando === "recuperarXml" && resultado.estado === "XML_RECUPERADO" && resultado.cStat === 100 && protocolo && chave && semEvento && xmlRecuperado;
1227
1223
  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;
1228
1224
  if (local && resultado.sucesso === true && semEvento) {
1229
1225
  statusEnvio = "nao_enviado";
1230
1226
  codigo = "ETAPA_LOCAL_CONCLUIDA";
1231
1227
  mensagem = "A etapa local foi conclu\xEDda; esta opera\xE7\xE3o n\xE3o transmitiu a nota.";
1232
1228
  acao = "Confira o resultado antes de seguir para a pr\xF3xima etapa.";
1229
+ } else if (resultado.sucesso === true && recuperacao) {
1230
+ statusEnvio = "autorizado";
1231
+ codigo = "XML_RECUPERADO";
1232
+ mensagem = "O XML autorizado foi recuperado por consulta; esta opera\xE7\xE3o n\xE3o transmitiu a nota.";
1233
+ acao = "Guarde o XML recuperado com o protocolo de autoriza\xE7\xE3o.";
1234
+ } else if (comando === "recuperarXml" && resultado.sucesso === false && resultado.codigo === "RECUPERACAO_NAO_COMPROVADA" && ["CONSULTADO", "ERRO"].includes(resultado.estado) && semEvento) {
1235
+ statusEnvio = "nao_enviado";
1236
+ codigo = "RECUPERACAO_NAO_COMPROVADA";
1237
+ mensagem = CATALOGO.RECUPERACAO_NAO_COMPROVADA[1];
1238
+ acao = CATALOGO.RECUPERACAO_NAO_COMPROVADA[2];
1233
1239
  } else if (resultado.sucesso === true && (autorizacao || evento && protocolo && resultado.envioIniciado !== false)) {
1234
1240
  statusEnvio = "autorizado";
1235
1241
  codigo = "OPERACAO_CONFIRMADA";
1236
1242
  mensagem = { AUTORIZADO: "A nota foi autorizada.", CANCELADO: "O cancelamento foi confirmado.", EVENTO_REGISTRADO: "O evento foi registrado.", INUTILIZADO: "A faixa foi inutilizada." }[resultado.estado];
1237
1243
  acao = "Guarde o resultado fiscal. N\xE3o repita esta opera\xE7\xE3o.";
1238
- } 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))) {
1244
+ } else if (resultado.sucesso === false && (comando === "consultar" || comando === "recuperarXml" || resultado.envioIniciado !== false) && ["transmitir", "consultar", "recuperarXml", "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))) {
1239
1245
  statusEnvio = "rejeitado";
1240
1246
  codigo = resultado.estado === "DENEGADO" ? "NOTA_DENEGADA" : "OPERACAO_REJEITADA";
1241
1247
  mensagem = resultado.estado === "DENEGADO" ? "A nota foi denegada." : "A opera\xE7\xE3o foi rejeitada.";
@@ -1250,97 +1256,164 @@ function diagnosticarResultado(resultado, comando) {
1250
1256
  const cStat = Number.isInteger(resultado.cStat) && Number(resultado.cStat) > 0 && Number(resultado.cStat) <= 9999 ? resultado.cStat : void 0;
1251
1257
  return Object.freeze({ codigo, etapa, mensagem, acao, statusEnvio, ...cStat !== void 0 ? { cStat } : {} });
1252
1258
  }
1259
+ var ETAPAS, CAMPOS, MAX_RECOVERED_XML_BYTES, CATALOGO;
1260
+ var init_diagnostics = __esm({
1261
+ "src/diagnostics.ts"() {
1262
+ "use strict";
1263
+ init_types();
1264
+ ETAPAS = /* @__PURE__ */ new Set(["configuracao", "documento", "runtime", "geracao", "validacao", "assinatura", "transmissao", "consulta", "cancelamento", "carta_correcao", "inutilizacao", "operacao", "limpeza"]);
1265
+ 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"]);
1266
+ MAX_RECOVERED_XML_BYTES = 4 * 1024 * 1024;
1267
+ CATALOGO = {
1268
+ CONFIGURACAO_INVALIDA: ["configuracao", "A configura\xE7\xE3o cont\xE9m um campo inv\xE1lido.", "Confira o campo indicado e seu tipo antes de continuar."],
1269
+ CONTRATO_INVALIDO: ["configuracao", "O contrato do cliente \xE9 inv\xE1lido.", "Use o contrato gerado junto com o cliente."],
1270
+ 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."],
1271
+ CERTIFICADO_DIVERGENTE: ["assinatura", "O certificado n\xE3o corresponde \xE0 raiz CNPJ do emitente.", "Confira o CNPJ configurado e selecione o A1 correspondente ao emitente."],
1272
+ 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."],
1273
+ SCHEMAS_AUSENTES: ["runtime", "Os schemas fiscais n\xE3o est\xE3o dispon\xEDveis.", "Reinstale o runtime completo da plataforma."],
1274
+ SERVICOS_AUSENTES: ["runtime", "A configura\xE7\xE3o dos servi\xE7os fiscais n\xE3o est\xE1 dispon\xEDvel.", "Reinstale o runtime completo da plataforma."],
1275
+ 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."],
1276
+ 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."],
1277
+ 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."],
1278
+ ASSINATURA_INVALIDA: ["assinatura", "A assinatura do XML n\xE3o foi validada.", "Confira o A1 correspondente e use o XML assinado sem altera\xE7\xF5es."],
1279
+ XML_NAO_ASSINADO: ["assinatura", "A opera\xE7\xE3o exige XML previamente assinado.", "Conclua a assinatura e a valida\xE7\xE3o antes de transmitir."],
1280
+ XML_ALTERADO: ["assinatura", "O XML assinado foi alterado.", "Use exatamente o XML assinado e persistido; n\xE3o edite seu conte\xFAdo."],
1281
+ 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."],
1282
+ RECUPERACAO_NAO_COMPROVADA: ["consulta", "A consulta n\xE3o comprovou a recupera\xE7\xE3o do XML autorizado.", "Preserve o XML assinado original e confira a situa\xE7\xE3o fiscal. N\xE3o transmita a nota para tentar recuperar o protocolo."],
1283
+ 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."],
1284
+ 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."],
1285
+ CSC_INVALIDO: ["configuracao", "A configura\xE7\xE3o do CSC \xE9 inv\xE1lida.", "Confira id e valor do CSC sem registrar seu conte\xFAdo."],
1286
+ PLATAFORMA_NAO_SUPORTADA: ["runtime", "A plataforma n\xE3o \xE9 suportada.", "Execute em Windows ou Linux x64 com Node.js 22.12 ou superior."],
1287
+ RUNTIME_AUSENTE: ["runtime", "O motor fiscal n\xE3o foi encontrado.", "Instale o runtime da plataforma incluindo depend\xEAncias opcionais."],
1288
+ RUNTIME_INVALIDO: ["runtime", "O runtime fiscal \xE9 inv\xE1lido.", "Use um runtime distribu\xEDdo e compat\xEDvel com a plataforma."],
1289
+ RUNTIME_INCOMPLETO: ["runtime", "Falta um arquivo do runtime fiscal.", "Reinstale o runtime da plataforma."],
1290
+ RUNTIME_ALTERADO: ["runtime", "A integridade do runtime fiscal n\xE3o foi confirmada.", "Reinstale o runtime; n\xE3o desative a verifica\xE7\xE3o dos hashes."],
1291
+ RUNTIME_SEM_CAPACIDADE: ["runtime", "O runtime instalado n\xE3o oferece esta opera\xE7\xE3o.", "Atualize o pacote principal e o runtime da plataforma para vers\xF5es compat\xEDveis com a opera\xE7\xE3o solicitada."],
1292
+ CONTRATO_DIVERGENTE: ["runtime", "Cliente e motor usam contratos diferentes.", "Use vers\xF5es compat\xEDveis ou regenere e recompile ambos."],
1293
+ 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."],
1294
+ 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."],
1295
+ OPERACAO_CANCELADA: ["operacao", "A opera\xE7\xE3o foi cancelada.", "Confira o estado do envio antes de decidir continuar."],
1296
+ TIMEOUT_MOTOR: ["runtime", "O motor excedeu o tempo de espera.", "Confira o estado do envio antes de repetir a opera\xE7\xE3o."],
1297
+ EMISSOR_FECHADO: ["operacao", "O emissor foi encerrado.", "Crie um novo emissor para continuar."],
1298
+ 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."],
1299
+ 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."],
1300
+ RESPOSTA_EXCESSIVA: ["runtime", "A resposta do motor excedeu o limite.", "Confira o tamanho da opera\xE7\xE3o e a vers\xE3o do runtime."],
1301
+ RESPOSTA_INVALIDA: ["runtime", "O motor devolveu uma resposta inv\xE1lida.", "Confira a compatibilidade do runtime e o estado do envio."],
1302
+ 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."],
1303
+ 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."],
1304
+ CERTIFICADO_EXCESSIVO: ["configuracao", "O certificado excede o limite de tamanho.", "Use um arquivo A1 de at\xE9 2 MiB."],
1305
+ 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."],
1306
+ FILA_CHEIA: ["operacao", "A fila fiscal est\xE1 cheia.", "Aguarde a opera\xE7\xE3o atual terminar antes de iniciar outra."],
1307
+ 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."],
1308
+ CHAVE_INVALIDA: ["documento", "A chave fiscal tem formato inv\xE1lido.", "Informe a chave como texto com 44 d\xEDgitos."],
1309
+ RECIBO_INVALIDO: ["documento", "O recibo tem formato inv\xE1lido.", "Informe o recibo como texto com 15 d\xEDgitos."],
1310
+ JUSTIFICATIVA_INVALIDA: ["documento", "A justificativa tem tamanho inv\xE1lido.", "Informe uma justificativa com 15 a 255 caracteres."],
1311
+ PROTOCOLO_INVALIDO: ["documento", "O protocolo tem formato inv\xE1lido.", "Informe o protocolo como texto com 15 d\xEDgitos."],
1312
+ 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."],
1313
+ 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."],
1314
+ INUTILIZACAO_INVALIDA: ["documento", "A faixa de inutiliza\xE7\xE3o \xE9 inv\xE1lida.", "Confira ano, s\xE9rie e n\xFAmeros inicial e final."],
1315
+ 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."]
1316
+ };
1317
+ }
1318
+ });
1253
1319
 
1254
1320
  // src/types.ts
1255
- var ErroAcbrNode = class extends Error {
1256
- constructor(codigo, mensagem, resultadoDesconhecido = false, xmlBase64, detalhes) {
1257
- super(mensagem);
1258
- this.codigo = codigo;
1259
- this.resultadoDesconhecido = resultadoDesconhecido;
1260
- this.xmlBase64 = xmlBase64;
1261
- this.#diagnostico = criarDiagnosticoErro(codigo, resultadoDesconhecido, detalhes);
1262
- Object.defineProperty(this, "xmlBase64", { value: xmlBase64, enumerable: false });
1263
- Object.defineProperty(this, "cause", { value: this.diagnostico.causa, enumerable: false });
1264
- }
1265
- name = "ErroAcbrNode";
1266
- #diagnostico;
1267
- get diagnostico() {
1268
- return this.#diagnostico;
1269
- }
1270
- /** Acrescenta apenas o aviso estático de limpeza, preservando o erro da operação. */
1271
- anotarFalhaLimpeza() {
1272
- this.#diagnostico = adicionarDiagnosticoLimpeza(this.#diagnostico);
1273
- }
1274
- toJSON() {
1275
- return this.diagnostico;
1321
+ var ErroAcbrNode;
1322
+ var init_types = __esm({
1323
+ "src/types.ts"() {
1324
+ "use strict";
1325
+ init_diagnostics();
1326
+ ErroAcbrNode = class extends Error {
1327
+ constructor(codigo, mensagem, resultadoDesconhecido = false, xmlBase64, detalhes) {
1328
+ super(mensagem);
1329
+ this.codigo = codigo;
1330
+ this.resultadoDesconhecido = resultadoDesconhecido;
1331
+ this.xmlBase64 = xmlBase64;
1332
+ this.#diagnostico = criarDiagnosticoErro(codigo, resultadoDesconhecido, detalhes);
1333
+ Object.defineProperty(this, "xmlBase64", { value: xmlBase64, enumerable: false });
1334
+ Object.defineProperty(this, "cause", { value: this.diagnostico.causa, enumerable: false });
1335
+ }
1336
+ name = "ErroAcbrNode";
1337
+ #diagnostico;
1338
+ get diagnostico() {
1339
+ return this.#diagnostico;
1340
+ }
1341
+ /** Acrescenta apenas o aviso estático de limpeza, preservando o erro da operação. */
1342
+ anotarFalhaLimpeza() {
1343
+ this.#diagnostico = adicionarDiagnosticoLimpeza(this.#diagnostico);
1344
+ }
1345
+ toJSON() {
1346
+ return this.diagnostico;
1347
+ }
1348
+ };
1276
1349
  }
1277
- };
1350
+ });
1278
1351
 
1279
1352
  // src/runtime.ts
1280
- var STATES = /* @__PURE__ */ new Set(["DENEGADO", "XML_GERADO", "VALIDADO", "ASSINADO", "AUTORIZADO", "REJEITADO", "PENDENTE", "INDETERMINADO", "CONSULTADO", "CANCELADO", "EVENTO_REGISTRADO", "INUTILIZADO", "ERRO"]);
1281
- 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(" "));
1282
- var MAX_BYTES = 8 * 1024 * 1024;
1283
- var MAX_TEARDOWN_MS = 1e3;
1284
- var plain = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
1285
- var validContract = (v) => plain(v) && Number.isInteger(v.sourceRevision) && Number(v.sourceRevision) > 0 && typeof v.contractHash === "string" && /^[a-f0-9]{64}$/.test(v.contractHash);
1286
- 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 });
1353
+ import { spawn as spawn2 } from "node:child_process";
1354
+ import { readFile as readFile6, stat as stat3 } from "node:fs/promises";
1355
+ import path3 from "node:path";
1356
+ import { createRequire } from "node:module";
1357
+ import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
1358
+ import { TextDecoder } from "node:util";
1287
1359
  function confined(root, relative3) {
1288
- const file = path.resolve(root, relative3), part = path.relative(root, file);
1289
- if (!relative3 || path.isAbsolute(relative3) || part === ".." || part.startsWith(".." + path.sep)) throw fail("RUNTIME_INVALIDO", "Caminho inv\xE1lido no runtime.");
1360
+ const file = path3.resolve(root, relative3), part = path3.relative(root, file);
1361
+ if (!relative3 || path3.isAbsolute(relative3) || part === ".." || part.startsWith(".." + path3.sep)) throw fail2("RUNTIME_INVALIDO", "Caminho inv\xE1lido no runtime.");
1290
1362
  return file;
1291
1363
  }
1292
1364
  async function resolveRuntime(directory, contract) {
1293
- if (!validContract(contract)) throw fail("CONTRATO_INVALIDO", "Contrato gerado inv\xE1lido.");
1365
+ if (!validContract(contract)) throw fail2("CONTRATO_INVALIDO", "Contrato gerado inv\xE1lido.");
1294
1366
  let root = directory;
1295
1367
  if (!root) {
1296
- if (!["linux", "win32"].includes(process.platform) || process.arch !== "x64") throw fail("PLATAFORMA_NAO_SUPORTADA", "Esta vers\xE3o exige Linux ou Windows x64.");
1368
+ if (!["linux", "win32"].includes(process.platform) || process.arch !== "x64") throw fail2("PLATAFORMA_NAO_SUPORTADA", "Esta vers\xE3o exige Linux ou Windows x64.");
1297
1369
  try {
1298
1370
  const require2 = createRequire(typeof __filename !== "undefined" ? __filename : import.meta.url);
1299
- root = path.join(path.dirname(require2.resolve("cosmemilton-acbr-node-" + process.platform + "-x64/package.json")), "runtime");
1371
+ root = path3.join(path3.dirname(require2.resolve("cosmemilton-acbr-node-" + process.platform + "-x64/package.json")), "runtime");
1300
1372
  } catch {
1301
- throw fail("RUNTIME_AUSENTE", "Instale o pacote de runtime da plataforma ou informe runtimeDirectory.");
1373
+ throw fail2("RUNTIME_AUSENTE", "Instale o pacote de runtime da plataforma ou informe runtimeDirectory.");
1302
1374
  }
1303
1375
  }
1304
- root = path.resolve(root);
1376
+ root = path3.resolve(root);
1305
1377
  let m;
1306
1378
  try {
1307
- m = JSON.parse(await readFile4(path.join(root, "manifest.json"), "utf8"));
1379
+ m = JSON.parse(await readFile6(path3.join(root, "manifest.json"), "utf8"));
1308
1380
  } catch {
1309
- throw fail("RUNTIME_AUSENTE", "Manifesto do runtime n\xE3o encontrado.");
1381
+ throw fail2("RUNTIME_AUSENTE", "Manifesto do runtime n\xE3o encontrado.");
1310
1382
  }
1311
- if (!validContract(m) || m.formatVersion !== 1 || !plain(m.files) || typeof m.executable !== "string" || m.platform !== process.platform || m.arch !== process.arch) throw fail("RUNTIME_INVALIDO", "Manifesto ou plataforma do runtime inv\xE1lidos.");
1312
- if (m.sourceRevision !== contract.sourceRevision || m.contractHash !== contract.contractHash) throw fail("CONTRATO_DIVERGENTE", "Cliente e motor foram gerados de contratos diferentes; regenere e recompile.");
1383
+ if (!validContract(m) || m.formatVersion !== 1 || !plain(m.files) || typeof m.executable !== "string" || m.platform !== process.platform || m.arch !== process.arch) throw fail2("RUNTIME_INVALIDO", "Manifesto ou plataforma do runtime inv\xE1lidos.");
1384
+ if (m.capabilities !== void 0 && (!Array.isArray(m.capabilities) || !m.capabilities.every((value) => typeof value === "string" && /^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(value)))) throw fail2("RUNTIME_INVALIDO", "Capacidades do runtime inv\xE1lidas.");
1385
+ if (m.sourceRevision !== contract.sourceRevision || m.contractHash !== contract.contractHash) throw fail2("CONTRATO_DIVERGENTE", "Cliente e motor foram gerados de contratos diferentes; regenere e recompile.");
1313
1386
  for (const [name, hash2] of Object.entries(m.files)) {
1314
- if (typeof hash2 !== "string" || !/^[a-f0-9]{64}$/.test(hash2)) throw fail("RUNTIME_INVALIDO", "Hash inv\xE1lido no runtime.");
1387
+ if (typeof hash2 !== "string" || !/^[a-f0-9]{64}$/.test(hash2)) throw fail2("RUNTIME_INVALIDO", "Hash inv\xE1lido no runtime.");
1315
1388
  const file = confined(root, name);
1316
1389
  let data;
1317
1390
  try {
1318
1391
  if (!(await stat3(file)).isFile()) throw Error();
1319
- data = await readFile4(file);
1392
+ data = await readFile6(file);
1320
1393
  } catch {
1321
- throw fail("RUNTIME_INCOMPLETO", "Arquivo do runtime ausente.");
1394
+ throw fail2("RUNTIME_INCOMPLETO", "Arquivo do runtime ausente.");
1322
1395
  }
1323
- if (createHash2("sha256").update(data).digest("hex") !== hash2) throw fail("RUNTIME_ALTERADO", "O runtime n\xE3o corresponde ao manifesto distribu\xEDdo.");
1396
+ if (createHash4("sha256").update(data).digest("hex") !== hash2) throw fail2("RUNTIME_ALTERADO", "O runtime n\xE3o corresponde ao manifesto distribu\xEDdo.");
1324
1397
  }
1325
- if (!m.files[m.executable]) throw fail("RUNTIME_INVALIDO", "O execut\xE1vel n\xE3o consta no invent\xE1rio.");
1326
- return { directory: root, executable: confined(root, m.executable) };
1398
+ if (!m.files[m.executable]) throw fail2("RUNTIME_INVALIDO", "O execut\xE1vel n\xE3o consta no invent\xE1rio.");
1399
+ return { directory: root, executable: confined(root, m.executable), capabilities: new Set(m.capabilities ?? []) };
1327
1400
  }
1328
1401
  function criarEmissor(options) {
1329
- const configFail = (campo) => fail("CONFIGURACAO_INVALIDA", "Informe campos e tipos v\xE1lidos na configura\xE7\xE3o.", void 0, false, { etapa: "configuracao", campo });
1402
+ const configFail = (campo) => fail2("CONFIGURACAO_INVALIDA", "Informe campos e tipos v\xE1lidos na configura\xE7\xE3o.", void 0, false, { etapa: "configuracao", campo });
1330
1403
  if (!plain(options)) throw configFail();
1331
1404
  if (typeof options.cnpj !== "string" || !/^\d{14}$/.test(options.cnpj)) throw configFail("cnpj");
1332
1405
  if (typeof options.uf !== "string" || !UFS.has(options.uf)) throw configFail("uf");
1333
1406
  if (![55, 65].includes(options.modelo)) throw configFail("modelo");
1334
1407
  if (![1, 2].includes(options.ambiente)) throw configFail("ambiente");
1335
- if (!validContract(options.contrato)) throw fail("CONTRATO_INVALIDO", "Contrato gerado inv\xE1lido.");
1408
+ if (!validContract(options.contrato)) throw fail2("CONTRATO_INVALIDO", "Contrato gerado inv\xE1lido.");
1336
1409
  const cert = options.certificado;
1337
- 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" });
1338
- 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" });
1410
+ 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 fail2("CERTIFICADO_INVALIDO", "Informe A1 em pfx ou arquivo e sua senha.", void 0, false, { campo: "certificado" });
1411
+ 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 fail2("CSC_INVALIDO", "CSC inv\xE1lido.", void 0, false, { campo: "csc" });
1339
1412
  if (options.runtimeDirectory !== void 0 && (typeof options.runtimeDirectory !== "string" || !options.runtimeDirectory)) throw configFail("runtimeDirectory");
1340
1413
  if (options.validaDocumento !== void 0 && typeof options.validaDocumento !== "function" || options.criaProcesso !== void 0 && typeof options.criaProcesso !== "function") throw configFail();
1341
1414
  const cfg = { cnpj: options.cnpj, uf: options.uf, modelo: options.modelo, ambiente: options.ambiente, csc: options.csc ? { ...options.csc } : void 0 };
1342
1415
  const certificate = cert ? { ...cert, pfx: cert.pfx ? Buffer.from(cert.pfx) : void 0 } : void 0;
1343
- const contract = { ...options.contrato };
1416
+ const contract = { sourceRevision: options.contrato.sourceRevision, contractHash: options.contrato.contractHash };
1344
1417
  const timeout = options.timeoutMs ?? 12e4, capacity = options.limiteFila ?? 32, bytesLimit = options.limiteBytes ?? MAX_BYTES;
1345
1418
  if (!Number.isInteger(timeout) || timeout < 1 || timeout > 12e4) throw configFail("timeoutMs");
1346
1419
  if (!Number.isInteger(capacity) || capacity < 0 || capacity > 1e3) throw configFail("limiteFila");
@@ -1349,7 +1422,7 @@ function criarEmissor(options) {
1349
1422
  let runtimePromise, closed = false, teardownFailed = false, current;
1350
1423
  const queue = [];
1351
1424
  const closedError = () => {
1352
- const error = fail("EMISSOR_FECHADO", "Emissor encerrado.");
1425
+ const error = fail2("EMISSOR_FECHADO", "Emissor encerrado.");
1353
1426
  if (teardownFailed) error.anotarFalhaLimpeza();
1354
1427
  return error;
1355
1428
  };
@@ -1361,9 +1434,10 @@ function criarEmissor(options) {
1361
1434
  }
1362
1435
  };
1363
1436
  async function execute2(item) {
1364
- if (closed || item.signal?.aborted) throw fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
1437
+ if (closed || item.signal?.aborted) throw fail2("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
1365
1438
  const runtime = await (runtimePromise ??= resolveRuntime(options.runtimeDirectory, contract));
1366
- if (closed || item.signal?.aborted) throw fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
1439
+ if (item.req.comando === "recuperarXml" && !runtime.capabilities.has("recuperarXml")) throw fail2("RUNTIME_SEM_CAPACIDADE", "O runtime n\xE3o oferece recupera\xE7\xE3o de XML; atualize o pacote e o runtime compat\xEDvel.", item.req, false, { etapa: "runtime" });
1440
+ if (closed || item.signal?.aborted) throw fail2("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
1367
1441
  return await new Promise((done, rejectExecution) => {
1368
1442
  let stopError;
1369
1443
  let child, finished = false, started = false, sending = false, total = 0, rest = Buffer.alloc(0), result;
@@ -1402,7 +1476,7 @@ function criarEmissor(options) {
1402
1476
  };
1403
1477
  const teardownFallback = () => {
1404
1478
  if (finished) return;
1405
- stopError ??= fail("FALHA_MOTOR", "O motor n\xE3o foi encerrado.", item.req, uncertain());
1479
+ stopError ??= fail2("FALHA_MOTOR", "O motor n\xE3o foi encerrado.", item.req, uncertain());
1406
1480
  stopError.anotarFalhaLimpeza();
1407
1481
  teardownFailed = true;
1408
1482
  closed = true;
@@ -1413,7 +1487,7 @@ function criarEmissor(options) {
1413
1487
  };
1414
1488
  const stop = (code, message) => {
1415
1489
  if (finished || stopError) return;
1416
- stopError = fail(code, message, item.req, uncertain());
1490
+ stopError = fail2(code, message, item.req, uncertain());
1417
1491
  if (!child?.pid) {
1418
1492
  finish(stopError);
1419
1493
  detachOwnedChild();
@@ -1431,20 +1505,20 @@ function criarEmissor(options) {
1431
1505
  current = { stop: () => stop("EMISSOR_FECHADO", "Emissor encerrado."), done: doneCurrent };
1432
1506
  const env = {};
1433
1507
  for (const key of ["PATH", "Path", "SystemRoot", "WINDIR", "TEMP", "TMP", "HOME", "LANG", "LC_ALL"]) if (process.env[key] !== void 0) env[key] = process.env[key];
1434
- if (process.platform === "linux") env.LD_LIBRARY_PATH = path.join(runtime.directory, "lib");
1508
+ if (process.platform === "linux") env.LD_LIBRARY_PATH = path3.join(runtime.directory, "lib");
1435
1509
  if (process.platform === "win32") {
1436
1510
  const inheritedPath = env.Path ?? env.PATH ?? "";
1437
1511
  delete env.Path;
1438
- env.PATH = path.join(runtime.directory, "lib") + ";" + runtime.directory + ";" + inheritedPath;
1512
+ env.PATH = path3.join(runtime.directory, "lib") + ";" + runtime.directory + ";" + inheritedPath;
1439
1513
  }
1440
- const modules = path.join(runtime.directory, "ossl-modules");
1514
+ const modules = path3.join(runtime.directory, "ossl-modules");
1441
1515
  env.OPENSSL_MODULES = modules;
1442
- env.OPENSSL_CONF = path.join(runtime.directory, "openssl.cnf");
1516
+ env.OPENSSL_CONF = path3.join(runtime.directory, "openssl.cnf");
1443
1517
  try {
1444
1518
  child = launch(runtime.executable, ["--parent-pid", String(process.pid)], { cwd: runtime.directory, env, windowsHide: true, shell: false, stdio: ["pipe", "pipe", "pipe"] });
1445
1519
  started = typeof child.pid === "number";
1446
1520
  } catch {
1447
- finish(fail("FALHA_INICIAR_MOTOR", "N\xE3o foi poss\xEDvel iniciar o motor.", item.req));
1521
+ finish(fail2("FALHA_INICIAR_MOTOR", "N\xE3o foi poss\xEDvel iniciar o motor.", item.req));
1448
1522
  return;
1449
1523
  }
1450
1524
  item.signal?.addEventListener("abort", abort, { once: true });
@@ -1485,9 +1559,11 @@ function criarEmissor(options) {
1485
1559
  continue;
1486
1560
  }
1487
1561
  if (result || frame.versao !== 1 || frame.sourceRevision !== contract.sourceRevision || frame.contractHash !== contract.contractHash || typeof frame.sucesso !== "boolean" || !STATES.has(String(frame.estado))) throw Error();
1488
- if (frame.xmlBase64 !== void 0 && (typeof frame.xmlBase64 !== "string" || !frame.xmlBase64.length || Buffer.from(frame.xmlBase64, "base64").toString("base64") !== frame.xmlBase64)) throw Error();
1562
+ if (frame.xmlBase64 !== void 0 && (item.req.comando === "recuperarXml" ? !base64XmlRecuperadoValido(frame.xmlBase64) : typeof frame.xmlBase64 !== "string" || !frame.xmlBase64.length || Buffer.from(frame.xmlBase64, "base64").toString("base64") !== frame.xmlBase64)) throw Error();
1489
1563
  if (frame.cStat !== void 0 && (!Number.isInteger(frame.cStat) || Number(frame.cStat) < 1 || Number(frame.cStat) > 9999)) throw Error();
1490
1564
  if (frame.envioIniciado !== void 0 && typeof frame.envioIniciado !== "boolean" || sending && frame.envioIniciado === false) throw Error();
1565
+ if (frame.estado === "XML_RECUPERADO" && item.req.comando !== "recuperarXml") throw Error();
1566
+ if (item.req.comando === "recuperarXml" && (frame.sucesso === true || frame.estado === "XML_RECUPERADO") && (frame.sucesso !== true || frame.estado !== "XML_RECUPERADO" || frame.cStat !== 100 || typeof frame.chave !== "string" || !/^\d{44}$/.test(frame.chave) || typeof frame.protocolo !== "string" || !/^\d{15}$/.test(frame.protocolo) || typeof frame.xmlBase64 !== "string" || frame.envioIniciado === true || sending)) throw Error();
1491
1567
  const fiscal = frame;
1492
1568
  result = { ...fiscal, diagnostico: diagnosticarResultado(sending ? { ...fiscal, envioIniciado: true } : fiscal, item.req.comando) };
1493
1569
  } catch {
@@ -1503,7 +1579,7 @@ function criarEmissor(options) {
1503
1579
  return;
1504
1580
  }
1505
1581
  if (code !== 0 || rest.length || !result) {
1506
- finish(fail("FALHA_MOTOR", "O motor encerrou sem resposta fiscal v\xE1lida.", item.req, uncertain()));
1582
+ finish(fail2("FALHA_MOTOR", "O motor encerrou sem resposta fiscal v\xE1lida.", item.req, uncertain()));
1507
1583
  return;
1508
1584
  }
1509
1585
  finish();
@@ -1532,31 +1608,31 @@ function criarEmissor(options) {
1532
1608
  }
1533
1609
  async function request(command, data, operation = {}) {
1534
1610
  const rawOperation = operation;
1535
- 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" });
1611
+ if (!plain(rawOperation)) throw fail2("OPERACAO_INVALIDA", "Informe op\xE7\xF5es v\xE1lidas para a opera\xE7\xE3o.", void 0, false, { etapa: etapaDaOperacao(command), campo: "operacao" });
1536
1612
  const signal = operation.signal;
1537
- 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" });
1613
+ if (signal !== void 0 && (!plain(signal) || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function" || typeof signal.removeEventListener !== "function")) throw fail2("OPERACAO_INVALIDA", "Informe op\xE7\xF5es v\xE1lidas para a opera\xE7\xE3o.", void 0, false, { etapa: etapaDaOperacao(command), campo: "signal" });
1538
1614
  if (closed) throw closedError();
1539
- if (operation.signal?.aborted) throw fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
1540
- if (["assinar", "transmitir", "consultar", "cancelar", "cartaCorrecao", "inutilizar"].includes(command) && !certificate) throw fail("CERTIFICADO_AUSENTE", "A opera\xE7\xE3o exige um certificado A1.");
1615
+ if (operation.signal?.aborted) throw fail2("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o.");
1616
+ if (["assinar", "transmitir", "consultar", "recuperarXml", "cancelar", "cartaCorrecao", "inutilizar"].includes(command) && !certificate) throw fail2("CERTIFICADO_AUSENTE", "A opera\xE7\xE3o exige um certificado A1.", void 0, false, { etapa: etapaDaOperacao(command) });
1541
1617
  if (command === "gerarXml") options.validaDocumento?.(data.documento);
1542
1618
  const config = { ...cfg };
1543
1619
  if (certificate) {
1544
1620
  let pfx;
1545
1621
  try {
1546
- pfx = certificate.pfx ?? await readFile4(certificate.arquivo);
1622
+ pfx = certificate.pfx ?? await readFile6(certificate.arquivo);
1547
1623
  } catch {
1548
- throw fail("CERTIFICADO_AUSENTE", "N\xE3o foi poss\xEDvel ler o A1 configurado.");
1624
+ throw fail2("CERTIFICADO_AUSENTE", "N\xE3o foi poss\xEDvel ler o A1 configurado.");
1549
1625
  }
1550
- if (pfx.length > 2 * 1024 * 1024) throw fail("CERTIFICADO_EXCESSIVO", "Certificado excede o limite.");
1626
+ if (pfx.length > 2 * 1024 * 1024) throw fail2("CERTIFICADO_EXCESSIVO", "Certificado excede o limite.");
1551
1627
  config.certificado = { pfxBase64: pfx.toString("base64"), senha: certificate.senha };
1552
1628
  }
1553
1629
  let bytes, req;
1554
1630
  try {
1555
- bytes = Buffer.from(JSON.stringify({ versao: 1, id: randomUUID3(), ...contract, comando: command, config, ...data }) + "\n", "utf8");
1631
+ bytes = Buffer.from(JSON.stringify({ ...data, ...contract, versao: 1, id: randomUUID3(), comando: command, config }) + "\n", "utf8");
1556
1632
  if (bytes.length > bytesLimit) throw Error();
1557
1633
  req = JSON.parse(bytes.toString("utf8"));
1558
1634
  } catch {
1559
- throw fail("REQUISICAO_INVALIDA", "Dados da opera\xE7\xE3o inv\xE1lidos ou acima do limite.");
1635
+ throw fail2("REQUISICAO_INVALIDA", "Dados da opera\xE7\xE3o inv\xE1lidos ou acima do limite.");
1560
1636
  }
1561
1637
  return new Promise((resolve5, reject) => {
1562
1638
  if (closed) {
@@ -1566,7 +1642,7 @@ function criarEmissor(options) {
1566
1642
  }
1567
1643
  if (busy && queue.length >= capacity) {
1568
1644
  bytes.fill(0);
1569
- reject(fail("FILA_CHEIA", "A fila fiscal est\xE1 cheia."));
1645
+ reject(fail2("FILA_CHEIA", "A fila fiscal est\xE1 cheia."));
1570
1646
  return;
1571
1647
  }
1572
1648
  const item = { req, bytes, signal: operation.signal, resolve: resolve5, reject };
@@ -1576,7 +1652,7 @@ function criarEmissor(options) {
1576
1652
  queue.splice(i, 1);
1577
1653
  bytes.fill(0);
1578
1654
  operation.signal?.removeEventListener("abort", item.abort);
1579
- reject(fail("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o."));
1655
+ reject(fail2("OPERACAO_CANCELADA", "Opera\xE7\xE3o cancelada antes da execu\xE7\xE3o."));
1580
1656
  }
1581
1657
  };
1582
1658
  operation.signal?.addEventListener("abort", item.abort, { once: true });
@@ -1586,47 +1662,48 @@ function criarEmissor(options) {
1586
1662
  });
1587
1663
  }
1588
1664
  const xmlData = (xml) => {
1589
- 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" });
1665
+ if (typeof xml !== "string" || !xml.trim() || Buffer.byteLength(xml, "utf8") > 2 * 1024 * 1024) throw fail2("XML_INVALIDO", "XML vazio ou acima do limite.", void 0, false, { campo: "xml" });
1590
1666
  return { xmlBase64: Buffer.from(xml, "utf8").toString("base64") };
1591
1667
  };
1592
1668
  const checkKey = (key) => {
1593
- if (typeof key !== "string" || !/^\d{44}$/.test(key)) throw fail("CHAVE_INVALIDA", "Chave fiscal inv\xE1lida.", void 0, false, { campo: "chave" });
1669
+ if (typeof key !== "string" || !/^\d{44}$/.test(key)) throw fail2("CHAVE_INVALIDA", "Chave fiscal inv\xE1lida.", void 0, false, { campo: "chave" });
1594
1670
  };
1595
1671
  const reason = (value) => {
1596
- 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" });
1672
+ if (typeof value !== "string" || value.length < 15 || value.length > 255) throw fail2("JUSTIFICATIVA_INVALIDA", "Justificativa deve ter de 15 a 255 caracteres.", void 0, false, { campo: "justificativa" });
1597
1673
  };
1598
1674
  const checkObject = (data, campo) => {
1599
- if (!plain(data)) throw fail("OPERACAO_INVALIDA", "Informe os par\xE2metros da opera\xE7\xE3o como objeto.", void 0, false, { campo });
1675
+ if (!plain(data)) throw fail2("OPERACAO_INVALIDA", "Informe os par\xE2metros da opera\xE7\xE3o como objeto.", void 0, false, { campo });
1600
1676
  };
1601
1677
  return {
1602
1678
  gerarXml: (documento, op) => request("gerarXml", { documento }, op),
1603
1679
  validar: (xml, op) => request("validar", xmlData(xml), op),
1604
1680
  assinar: (xml, op) => request("assinar", xmlData(xml), op),
1605
1681
  transmitir: (xml, op) => request("transmitir", xmlData(xml), op),
1682
+ recuperarXml: (xmlAssinado, opcoes) => request("recuperarXml", xmlData(xmlAssinado), opcoes),
1606
1683
  consultar: (consulta, op) => {
1607
1684
  checkObject(consulta, "consulta");
1608
1685
  checkKey(consulta.chave);
1609
- 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" });
1610
- return request("consultar", consulta, op);
1686
+ if (consulta.recibo !== void 0 && (typeof consulta.recibo !== "string" || !/^\d{15}$/.test(consulta.recibo))) throw fail2("RECIBO_INVALIDO", "Recibo inv\xE1lido.", void 0, false, { campo: "recibo" });
1687
+ return request("consultar", { chave: consulta.chave, ...consulta.recibo !== void 0 ? { recibo: consulta.recibo } : {} }, op);
1611
1688
  },
1612
1689
  cancelar: (data, op) => {
1613
1690
  checkObject(data, "cancelamento");
1614
1691
  checkKey(data.chave);
1615
1692
  reason(data.justificativa);
1616
- if (typeof data.protocolo !== "string" || !/^\d{15}$/.test(data.protocolo)) throw fail("PROTOCOLO_INVALIDO", "Protocolo inv\xE1lido.", void 0, false, { campo: "protocolo" });
1617
- return request("cancelar", data, op);
1693
+ if (typeof data.protocolo !== "string" || !/^\d{15}$/.test(data.protocolo)) throw fail2("PROTOCOLO_INVALIDO", "Protocolo inv\xE1lido.", void 0, false, { campo: "protocolo" });
1694
+ return request("cancelar", { chave: data.chave, protocolo: data.protocolo, justificativa: data.justificativa }, op);
1618
1695
  },
1619
1696
  cartaCorrecao: (data, op) => {
1620
1697
  checkObject(data, "cartaCorrecao");
1621
- if (cfg.modelo !== 55) throw fail("OPERACAO_NAO_SUPORTADA", "Carta de corre\xE7\xE3o exige NF-e modelo 55.");
1698
+ if (cfg.modelo !== 55) throw fail2("OPERACAO_NAO_SUPORTADA", "Carta de corre\xE7\xE3o exige NF-e modelo 55.");
1622
1699
  checkKey(data.chave);
1623
- 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" });
1624
- return request("cartaCorrecao", { ...data, sequenciaEvento: data.sequenciaEvento ?? 1 }, op);
1700
+ 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 fail2("CORRECAO_INVALIDA", "Dados da carta de corre\xE7\xE3o inv\xE1lidos.", void 0, false, { campo: "cartaCorrecao" });
1701
+ return request("cartaCorrecao", { chave: data.chave, correcao: data.correcao, sequenciaEvento: data.sequenciaEvento ?? 1 }, op);
1625
1702
  },
1626
1703
  inutilizar: (data, op) => {
1627
1704
  checkObject(data, "inutilizacao");
1628
1705
  reason(data.justificativa);
1629
- 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" });
1706
+ 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 fail2("INUTILIZACAO_INVALIDA", "Faixa de inutiliza\xE7\xE3o inv\xE1lida.", void 0, false, { campo: "inutilizacao" });
1630
1707
  return request("inutilizar", { inutilizacao: { ano: data.ano, serie: data.serie, numeroInicial: data.numeroInicial, numeroFinal: data.numeroFinal }, justificativa: data.justificativa }, op);
1631
1708
  },
1632
1709
  async fechar() {
@@ -1644,118 +1721,145 @@ function criarEmissor(options) {
1644
1721
  }
1645
1722
  };
1646
1723
  }
1724
+ var STATES, UFS, MAX_BYTES, MAX_TEARDOWN_MS, plain, validContract, fail2;
1725
+ var init_runtime = __esm({
1726
+ "src/runtime.ts"() {
1727
+ "use strict";
1728
+ init_types();
1729
+ init_diagnostics();
1730
+ init_types();
1731
+ init_diagnostics();
1732
+ STATES = /* @__PURE__ */ new Set(["DENEGADO", "XML_GERADO", "VALIDADO", "ASSINADO", "XML_RECUPERADO", "AUTORIZADO", "REJEITADO", "PENDENTE", "INDETERMINADO", "CONSULTADO", "CANCELADO", "EVENTO_REGISTRADO", "INUTILIZADO", "ERRO"]);
1733
+ 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(" "));
1734
+ MAX_BYTES = 8 * 1024 * 1024;
1735
+ MAX_TEARDOWN_MS = 1e3;
1736
+ plain = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
1737
+ validContract = (v) => plain(v) && Number.isInteger(v.sourceRevision) && Number(v.sourceRevision) > 0 && typeof v.contractHash === "string" && /^[a-f0-9]{64}$/.test(v.contractHash);
1738
+ fail2 = (code, message, req, unknown = false, detalhes) => new ErroAcbrNode(code, message, unknown, req?.comando === "transmitir" ? req.xmlBase64 : void 0, { ...req ? { etapa: etapaDaOperacao(req.comando) } : {}, ...detalhes });
1739
+ }
1740
+ });
1647
1741
 
1648
1742
  // src/offline-fixture.ts
1649
- var OFFLINE_DOCUMENT = {
1650
- "infNFe": {
1651
- "Versao": "4.00"
1652
- },
1653
- "Ide": {
1654
- "cUF": 23,
1655
- "cNF": 12345678,
1656
- "natOp": "VENDA TESTE OFFLINE",
1657
- "modelo": 55,
1658
- "serie": 1,
1659
- "nNF": 1,
1660
- "dEmi": "2026-10-08T12:00:00",
1661
- "tpNF": "tnSaida",
1662
- "idDest": "doInterna",
1663
- "cMunFG": 2304400,
1664
- "tpImp": "tiRetrato",
1665
- "tpEmis": "teNormal",
1666
- "tpAmb": "taHomologacao",
1667
- "finNFe": "fnNormal",
1668
- "indFinal": "cfConsumidorFinal",
1669
- "indPres": "pcPresencial",
1670
- "procEmi": "peAplicativoContribuinte",
1671
- "verProc": "ACBR-NODE-OFFLINE"
1672
- },
1673
- "Emit": {
1674
- "CNPJCPF": "11222333000181",
1675
- "xNome": "Caf\xE9 S\xE3o Jos\xE9 TESTE OFFLINE SEM VALOR FISCAL",
1676
- "IE": "123456789",
1677
- "CRT": "crtSimplesNacional",
1678
- "EnderEmit": {
1679
- "xLgr": "RUA TESTE",
1680
- "nro": "1",
1681
- "xBairro": "TESTE",
1682
- "cMun": 2304400,
1683
- "xMun": "FORTALEZA",
1684
- "UF": "CE",
1685
- "CEP": 6e7,
1686
- "cPais": 1058,
1687
- "xPais": "BRASIL"
1688
- }
1689
- },
1690
- "Dest": {
1691
- "CNPJCPF": "12345678909",
1692
- "xNome": "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL",
1693
- "indIEDest": "inNaoContribuinte",
1694
- "EnderDest": {
1695
- "xLgr": "RUA TESTE",
1696
- "nro": "2",
1697
- "xBairro": "TESTE",
1698
- "cMun": 2304400,
1699
- "xMun": "FORTALEZA",
1700
- "UF": "CE",
1701
- "CEP": 6e7,
1702
- "cPais": 1058,
1703
- "xPais": "BRASIL"
1704
- }
1705
- },
1706
- "Det": [
1707
- {
1708
- "Prod": {
1709
- "nItem": 1,
1710
- "cProd": "TESTE",
1711
- "cEAN": "SEM GTIN",
1712
- "xProd": "Caf\xE9 S\xE3o Jos\xE9 PRODUTO SINT\xC9TICO OFFLINE",
1713
- "NCM": "22021000",
1714
- "CFOP": "5102",
1715
- "uCom": "UN",
1716
- "qCom": "1",
1717
- "vUnCom": "10",
1718
- "vProd": "10",
1719
- "cEANTrib": "SEM GTIN",
1720
- "uTrib": "UN",
1721
- "qTrib": "1",
1722
- "vUnTrib": "10",
1723
- "IndTot": "itSomaTotalNFe"
1743
+ var OFFLINE_DOCUMENT, OFFLINE_SIGNED_XML;
1744
+ var init_offline_fixture = __esm({
1745
+ "src/offline-fixture.ts"() {
1746
+ "use strict";
1747
+ OFFLINE_DOCUMENT = {
1748
+ "infNFe": {
1749
+ "Versao": "4.00"
1750
+ },
1751
+ "Ide": {
1752
+ "cUF": 23,
1753
+ "cNF": 12345678,
1754
+ "natOp": "VENDA TESTE OFFLINE",
1755
+ "modelo": 55,
1756
+ "serie": 1,
1757
+ "nNF": 1,
1758
+ "dEmi": "2026-10-08T12:00:00",
1759
+ "tpNF": "tnSaida",
1760
+ "idDest": "doInterna",
1761
+ "cMunFG": 2304400,
1762
+ "tpImp": "tiRetrato",
1763
+ "tpEmis": "teNormal",
1764
+ "tpAmb": "taHomologacao",
1765
+ "finNFe": "fnNormal",
1766
+ "indFinal": "cfConsumidorFinal",
1767
+ "indPres": "pcPresencial",
1768
+ "procEmi": "peAplicativoContribuinte",
1769
+ "verProc": "ACBR-NODE-OFFLINE"
1724
1770
  },
1725
- "Imposto": {
1726
- "ICMS": {
1727
- "orig": "oeNacional",
1728
- "CSOSN": "csosn102"
1729
- },
1730
- "PIS": {
1731
- "CST": "pis07"
1732
- },
1733
- "COFINS": {
1734
- "CST": "cof07"
1771
+ "Emit": {
1772
+ "CNPJCPF": "11222333000181",
1773
+ "xNome": "Caf\xE9 S\xE3o Jos\xE9 TESTE OFFLINE SEM VALOR FISCAL",
1774
+ "IE": "123456789",
1775
+ "CRT": "crtSimplesNacional",
1776
+ "EnderEmit": {
1777
+ "xLgr": "RUA TESTE",
1778
+ "nro": "1",
1779
+ "xBairro": "TESTE",
1780
+ "cMun": 2304400,
1781
+ "xMun": "FORTALEZA",
1782
+ "UF": "CE",
1783
+ "CEP": 6e7,
1784
+ "cPais": 1058,
1785
+ "xPais": "BRASIL"
1735
1786
  }
1736
- }
1737
- }
1738
- ],
1739
- "Total": {
1740
- "ICMSTot": {
1741
- "vProd": "10",
1742
- "vNF": "10"
1743
- }
1744
- },
1745
- "Transp": {
1746
- "modFrete": "mfSemFrete"
1747
- },
1748
- "pag": [
1749
- {
1750
- "tPag": "fpDinheiro",
1751
- "indPag": "ipVista",
1752
- "vPag": "10"
1753
- }
1754
- ]
1755
- };
1756
- var OFFLINE_SIGNED_XML = '<?xml version="1.0" encoding="UTF-8"?><NFe xmlns="http://www.portalfiscal.inf.br/nfe"><infNFe Id="NFe23261011222333000181550010000000011123456780" versao="4.00"><ide><cUF>23</cUF><cNF>12345678</cNF><natOp>VENDA TESTE OFFLINE</natOp><mod>55</mod><serie>1</serie><nNF>1</nNF><dhEmi>2026-10-08T12:00:00-03:00</dhEmi><tpNF>1</tpNF><idDest>1</idDest><cMunFG>2304400</cMunFG><tpImp>1</tpImp><tpEmis>1</tpEmis><cDV>0</cDV><tpAmb>2</tpAmb><finNFe>1</finNFe><indFinal>1</indFinal><indPres>1</indPres><procEmi>0</procEmi><verProc>ACBR-NODE-OFFLINE</verProc></ide><emit><CNPJ>11222333000181</CNPJ><xNome>Caf\xE9 S\xE3o Jos\xE9 TESTE OFFLINE SEM VALOR FISCAL</xNome><enderEmit><xLgr>RUA TESTE</xLgr><nro>1</nro><xBairro>TESTE</xBairro><cMun>2304400</cMun><xMun>FORTALEZA</xMun><UF>CE</UF><CEP>60000000</CEP><cPais>1058</cPais><xPais>BRASIL</xPais></enderEmit><IE>123456789</IE><CRT>1</CRT></emit><dest><CPF>12345678909</CPF><xNome>NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL</xNome><enderDest><xLgr>RUA TESTE</xLgr><nro>2</nro><xBairro>TESTE</xBairro><cMun>2304400</cMun><xMun>FORTALEZA</xMun><UF>CE</UF><CEP>60000000</CEP><cPais>1058</cPais><xPais>BRASIL</xPais></enderDest><indIEDest>9</indIEDest></dest><det nItem="1"><prod><cProd>TESTE</cProd><cEAN>SEM GTIN</cEAN><xProd>Caf\xE9 S\xE3o Jos\xE9 PRODUTO SINT\xC9TICO OFFLINE</xProd><NCM>22021000</NCM><CFOP>5102</CFOP><uCom>UN</uCom><qCom>1.0000</qCom><vUnCom>10.0000000000</vUnCom><vProd>10.00</vProd><cEANTrib>SEM GTIN</cEANTrib><uTrib>UN</uTrib><qTrib>1.0000</qTrib><vUnTrib>10.0000000000</vUnTrib><indTot>1</indTot></prod><imposto><ICMS><ICMSSN102><orig>0</orig><CSOSN>102</CSOSN></ICMSSN102></ICMS><PIS><PISNT><CST>07</CST></PISNT></PIS><COFINS><COFINSNT><CST>07</CST></COFINSNT></COFINS></imposto></det><total><ICMSTot><vBC>0.00</vBC><vICMS>0.00</vICMS><vICMSDeson>0.00</vICMSDeson><vFCP>0.00</vFCP><vBCST>0.00</vBCST><vST>0.00</vST><vFCPST>0.00</vFCPST><vFCPSTRet>0.00</vFCPSTRet><vProd>10.00</vProd><vFrete>0.00</vFrete><vSeg>0.00</vSeg><vDesc>0.00</vDesc><vII>0.00</vII><vIPI>0.00</vIPI><vIPIDevol>0.00</vIPIDevol><vPIS>0.00</vPIS><vCOFINS>0.00</vCOFINS><vOutro>0.00</vOutro><vNF>10.00</vNF></ICMSTot></total><transp><modFrete>9</modFrete></transp><pag><detPag><indPag>0</indPag><tPag>01</tPag><vPag>10.00</vPag></detPag></pag></infNFe><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI="#NFe23261011222333000181550010000000011123456780"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>Ya5kXhcEibOVfcyOI0BzqcYzyMM=</DigestValue></Reference></SignedInfo><SignatureValue>mirdDvdV+VId/zsstW/6lVFsSVxdyWkdkY1NPd2ynLHpjtolFoIhaBGlfxxs7IhU/AzcNQmR6ivr9YkH1HXaMAypvvx9M6GR/T4du/Zqab4gx3YInVybjJTeQ7BKEDnLhde2TUKoXrxmfrrmBUw6K4nTNufVjUjFJBfGcwhJ57T72x7ssdoYuPvZCphb0IR8WxHRKhvKAQhjW61qfh33csTabelgVZSLuTC2I2k9+a+ARd88CLTlfhYNCAPItOdUnAjgrhAhtiDi2FjXKjywgRqx0zay8DxF9Y2iyTJd3IAoWOERGdI9whgsuzWiZUr2I0I5QGGBELVabfjXm/Bneg==</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIDhjCCAm6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMSswKQYDVQQDEyJBQ0JSIE5PREUgU1lOVEhFVElDOjExMjIyMzMzMDAwMTgxMQswCQYDVQQGEwJCUjEfMB0GA1UEChMWU1lOVEhFVElDIE9GRkxJTkUgVEVTVDAeFw0yNjEwMDYyMjIzMzNaFw0yNzEwMDgyMjIzMzNaMFsxKzApBgNVBAMTIkFDQlIgTk9ERSBTWU5USEVUSUM6MTEyMjIzMzMwMDAxODExCzAJBgNVBAYTAkJSMR8wHQYDVQQKExZTWU5USEVUSUMgT0ZGTElORSBURVNUMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsOwRzuW4de7jrv1IkcNgT311292NR5NNIHt6Fncarm2iJX6mYsIjPWriFQmrU88p7bfRI3EsXJrlK0oGCuMafbNf1nBZ6Tu8aV1ixbAIgu9ZIbWoDqDNbYJBucQRuKsI1ytFbY7eI0juhcdAlBHw3TNdgSbuv/8kEGgTTJ803wBcC+emGZHdpb4Bwx6Db0Fio0lWLlBaep9+MFNZZiEYmDA3dwgZF14MAr5MpzcNDUVYh/g95Ks8x+mhErOPdtmL1A6cDg+xtjiApeMJZqjMrdsXP4yQ34h5VRy03ZUJkXVAquOfWhXpQL/qjoSzXfHvij2wB0pVn89FzVZh7GzStQIDAQABo1UwUzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDAjAkBgNVHREEHTAboBkGBWBMAQMDoBAMDjExMjIyMzMzMDAwMTgxMA0GCSqGSIb3DQEBCwUAA4IBAQBDhbpxphiuAUlQWXkcVt22Nc+g2UM6GCZyC3v9o21llLSCyK/nhkrRCQzM75/86kbnYZ1zdulC9N4XQFgATwm16Sf/nDZw8s5EsXqZ8mwbauDs/aQvWrbQnyawB7c+aXvlUDkcfNq+3hLQ5ep8/bmGh4eueiNoPD0fjf/jUVmrS6KyHb6/FyIZGP6fEYAO6XrqJPMSPxpJHnbPXZXKW2vcCh3qaG1vTSeN8PLfN2Q/mp1XUH8VqHgl3jzssx/zwb1NKuKEz9WL+6ilLc1ZfIqUakJyQNMqMz2KIjqGKGp7TtpNHZ7mz+kBX4Xw7D5fFVrXYb7DN6KylyKLmXoEzs1B</X509Certificate></X509Data></KeyInfo></Signature></NFe>';
1787
+ },
1788
+ "Dest": {
1789
+ "CNPJCPF": "12345678909",
1790
+ "xNome": "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL",
1791
+ "indIEDest": "inNaoContribuinte",
1792
+ "EnderDest": {
1793
+ "xLgr": "RUA TESTE",
1794
+ "nro": "2",
1795
+ "xBairro": "TESTE",
1796
+ "cMun": 2304400,
1797
+ "xMun": "FORTALEZA",
1798
+ "UF": "CE",
1799
+ "CEP": 6e7,
1800
+ "cPais": 1058,
1801
+ "xPais": "BRASIL"
1802
+ }
1803
+ },
1804
+ "Det": [
1805
+ {
1806
+ "Prod": {
1807
+ "nItem": 1,
1808
+ "cProd": "TESTE",
1809
+ "cEAN": "SEM GTIN",
1810
+ "xProd": "Caf\xE9 S\xE3o Jos\xE9 PRODUTO SINT\xC9TICO OFFLINE",
1811
+ "NCM": "22021000",
1812
+ "CFOP": "5102",
1813
+ "uCom": "UN",
1814
+ "qCom": "1",
1815
+ "vUnCom": "10",
1816
+ "vProd": "10",
1817
+ "cEANTrib": "SEM GTIN",
1818
+ "uTrib": "UN",
1819
+ "qTrib": "1",
1820
+ "vUnTrib": "10",
1821
+ "IndTot": "itSomaTotalNFe"
1822
+ },
1823
+ "Imposto": {
1824
+ "ICMS": {
1825
+ "orig": "oeNacional",
1826
+ "CSOSN": "csosn102"
1827
+ },
1828
+ "PIS": {
1829
+ "CST": "pis07"
1830
+ },
1831
+ "COFINS": {
1832
+ "CST": "cof07"
1833
+ }
1834
+ }
1835
+ }
1836
+ ],
1837
+ "Total": {
1838
+ "ICMSTot": {
1839
+ "vProd": "10",
1840
+ "vNF": "10"
1841
+ }
1842
+ },
1843
+ "Transp": {
1844
+ "modFrete": "mfSemFrete"
1845
+ },
1846
+ "pag": [
1847
+ {
1848
+ "tPag": "fpDinheiro",
1849
+ "indPag": "ipVista",
1850
+ "vPag": "10"
1851
+ }
1852
+ ]
1853
+ };
1854
+ OFFLINE_SIGNED_XML = '<?xml version="1.0" encoding="UTF-8"?><NFe xmlns="http://www.portalfiscal.inf.br/nfe"><infNFe Id="NFe23261011222333000181550010000000011123456780" versao="4.00"><ide><cUF>23</cUF><cNF>12345678</cNF><natOp>VENDA TESTE OFFLINE</natOp><mod>55</mod><serie>1</serie><nNF>1</nNF><dhEmi>2026-10-08T12:00:00-03:00</dhEmi><tpNF>1</tpNF><idDest>1</idDest><cMunFG>2304400</cMunFG><tpImp>1</tpImp><tpEmis>1</tpEmis><cDV>0</cDV><tpAmb>2</tpAmb><finNFe>1</finNFe><indFinal>1</indFinal><indPres>1</indPres><procEmi>0</procEmi><verProc>ACBR-NODE-OFFLINE</verProc></ide><emit><CNPJ>11222333000181</CNPJ><xNome>Caf\xE9 S\xE3o Jos\xE9 TESTE OFFLINE SEM VALOR FISCAL</xNome><enderEmit><xLgr>RUA TESTE</xLgr><nro>1</nro><xBairro>TESTE</xBairro><cMun>2304400</cMun><xMun>FORTALEZA</xMun><UF>CE</UF><CEP>60000000</CEP><cPais>1058</cPais><xPais>BRASIL</xPais></enderEmit><IE>123456789</IE><CRT>1</CRT></emit><dest><CPF>12345678909</CPF><xNome>NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL</xNome><enderDest><xLgr>RUA TESTE</xLgr><nro>2</nro><xBairro>TESTE</xBairro><cMun>2304400</cMun><xMun>FORTALEZA</xMun><UF>CE</UF><CEP>60000000</CEP><cPais>1058</cPais><xPais>BRASIL</xPais></enderDest><indIEDest>9</indIEDest></dest><det nItem="1"><prod><cProd>TESTE</cProd><cEAN>SEM GTIN</cEAN><xProd>Caf\xE9 S\xE3o Jos\xE9 PRODUTO SINT\xC9TICO OFFLINE</xProd><NCM>22021000</NCM><CFOP>5102</CFOP><uCom>UN</uCom><qCom>1.0000</qCom><vUnCom>10.0000000000</vUnCom><vProd>10.00</vProd><cEANTrib>SEM GTIN</cEANTrib><uTrib>UN</uTrib><qTrib>1.0000</qTrib><vUnTrib>10.0000000000</vUnTrib><indTot>1</indTot></prod><imposto><ICMS><ICMSSN102><orig>0</orig><CSOSN>102</CSOSN></ICMSSN102></ICMS><PIS><PISNT><CST>07</CST></PISNT></PIS><COFINS><COFINSNT><CST>07</CST></COFINSNT></COFINS></imposto></det><total><ICMSTot><vBC>0.00</vBC><vICMS>0.00</vICMS><vICMSDeson>0.00</vICMSDeson><vFCP>0.00</vFCP><vBCST>0.00</vBCST><vST>0.00</vST><vFCPST>0.00</vFCPST><vFCPSTRet>0.00</vFCPSTRet><vProd>10.00</vProd><vFrete>0.00</vFrete><vSeg>0.00</vSeg><vDesc>0.00</vDesc><vII>0.00</vII><vIPI>0.00</vIPI><vIPIDevol>0.00</vIPIDevol><vPIS>0.00</vPIS><vCOFINS>0.00</vCOFINS><vOutro>0.00</vOutro><vNF>10.00</vNF></ICMSTot></total><transp><modFrete>9</modFrete></transp><pag><detPag><indPag>0</indPag><tPag>01</tPag><vPag>10.00</vPag></detPag></pag></infNFe><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI="#NFe23261011222333000181550010000000011123456780"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>Ya5kXhcEibOVfcyOI0BzqcYzyMM=</DigestValue></Reference></SignedInfo><SignatureValue>mirdDvdV+VId/zsstW/6lVFsSVxdyWkdkY1NPd2ynLHpjtolFoIhaBGlfxxs7IhU/AzcNQmR6ivr9YkH1HXaMAypvvx9M6GR/T4du/Zqab4gx3YInVybjJTeQ7BKEDnLhde2TUKoXrxmfrrmBUw6K4nTNufVjUjFJBfGcwhJ57T72x7ssdoYuPvZCphb0IR8WxHRKhvKAQhjW61qfh33csTabelgVZSLuTC2I2k9+a+ARd88CLTlfhYNCAPItOdUnAjgrhAhtiDi2FjXKjywgRqx0zay8DxF9Y2iyTJd3IAoWOERGdI9whgsuzWiZUr2I0I5QGGBELVabfjXm/Bneg==</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIDhjCCAm6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMSswKQYDVQQDEyJBQ0JSIE5PREUgU1lOVEhFVElDOjExMjIyMzMzMDAwMTgxMQswCQYDVQQGEwJCUjEfMB0GA1UEChMWU1lOVEhFVElDIE9GRkxJTkUgVEVTVDAeFw0yNjEwMDYyMjIzMzNaFw0yNzEwMDgyMjIzMzNaMFsxKzApBgNVBAMTIkFDQlIgTk9ERSBTWU5USEVUSUM6MTEyMjIzMzMwMDAxODExCzAJBgNVBAYTAkJSMR8wHQYDVQQKExZTWU5USEVUSUMgT0ZGTElORSBURVNUMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsOwRzuW4de7jrv1IkcNgT311292NR5NNIHt6Fncarm2iJX6mYsIjPWriFQmrU88p7bfRI3EsXJrlK0oGCuMafbNf1nBZ6Tu8aV1ixbAIgu9ZIbWoDqDNbYJBucQRuKsI1ytFbY7eI0juhcdAlBHw3TNdgSbuv/8kEGgTTJ803wBcC+emGZHdpb4Bwx6Db0Fio0lWLlBaep9+MFNZZiEYmDA3dwgZF14MAr5MpzcNDUVYh/g95Ks8x+mhErOPdtmL1A6cDg+xtjiApeMJZqjMrdsXP4yQ34h5VRy03ZUJkXVAquOfWhXpQL/qjoSzXfHvij2wB0pVn89FzVZh7GzStQIDAQABo1UwUzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDAjAkBgNVHREEHTAboBkGBWBMAQMDoBAMDjExMjIyMzMzMDAwMTgxMA0GCSqGSIb3DQEBCwUAA4IBAQBDhbpxphiuAUlQWXkcVt22Nc+g2UM6GCZyC3v9o21llLSCyK/nhkrRCQzM75/86kbnYZ1zdulC9N4XQFgATwm16Sf/nDZw8s5EsXqZ8mwbauDs/aQvWrbQnyawB7c+aXvlUDkcfNq+3hLQ5ep8/bmGh4eueiNoPD0fjf/jUVmrS6KyHb6/FyIZGP6fEYAO6XrqJPMSPxpJHnbPXZXKW2vcCh3qaG1vTSeN8PLfN2Q/mp1XUH8VqHgl3jzssx/zwb1NKuKEz9WL+6ilLc1ZfIqUakJyQNMqMz2KIjqGKGp7TtpNHZ7mz+kBX4Xw7D5fFVrXYb7DN6KylyKLmXoEzs1B</X509Certificate></X509Data></KeyInfo></Signature></NFe>';
1855
+ }
1856
+ });
1757
1857
 
1758
1858
  // src/offline-check.ts
1859
+ var offline_check_exports = {};
1860
+ __export(offline_check_exports, {
1861
+ checkOffline: () => checkOffline
1862
+ });
1759
1863
  async function checkOffline(config, manifest) {
1760
1864
  const emitter = criarEmissor({
1761
1865
  cnpj: "11222333000181",
@@ -1790,11 +1894,246 @@ async function checkOffline(config, manifest) {
1790
1894
  await emitter.fechar();
1791
1895
  }
1792
1896
  }
1897
+ var init_offline_check = __esm({
1898
+ "src/offline-check.ts"() {
1899
+ "use strict";
1900
+ init_native_build();
1901
+ init_runtime();
1902
+ init_offline_fixture();
1903
+ }
1904
+ });
1905
+
1906
+ // src/cli.ts
1907
+ import { realpathSync } from "node:fs";
1908
+ import { access as access4 } from "node:fs/promises";
1909
+ import { resolve as resolve4 } from "node:path";
1910
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
1911
+
1912
+ // src/contract-help.ts
1913
+ import { createHash } from "node:crypto";
1914
+ import { readFile } from "node:fs/promises";
1915
+ import path from "node:path";
1916
+
1917
+ // generated/acbr/models.ts
1918
+ var ACBR_CONTRACT = { "sourceRevision": 48590, "contractHash": "e5a497cefe8e0e350a30da5cc04e88b35c38a98535893d52f878890260d1346d" };
1919
+ var SOURCE_REVISION = ACBR_CONTRACT.sourceRevision;
1920
+ var CONTRACT_HASH = ACBR_CONTRACT.contractHash;
1921
+ var TACBrProcessoEmissao = Object.freeze({ "peAplicativoContribuinte": "peAplicativoContribuinte", "peAvulsaFisco": "peAvulsaFisco", "peAvulsaContribuinte": "peAvulsaContribuinte", "peContribuinteAplicativoFisco": "peContribuinteAplicativoFisco", "peProvedorAssinaturaAutorizacao": "peProvedorAssinaturaAutorizacao" });
1922
+ var TACBrTipoAmbiente = Object.freeze({ "taProducao": "taProducao", "taHomologacao": "taHomologacao" });
1923
+ var TACBrTipoEmissao = Object.freeze({ "teNormal": "teNormal", "teContingencia": "teContingencia", "teSCAN": "teSCAN", "teDPEC": "teDPEC", "teFSDA": "teFSDA", "teSVCAN": "teSVCAN", "teSVCRS": "teSVCRS", "teSVCSP": "teSVCSP", "teOffLine": "teOffLine" });
1924
+ var TACBrTipoImpressao = Object.freeze({ "tiSemGeracao": "tiSemGeracao", "tiRetrato": "tiRetrato", "tiPaisagem": "tiPaisagem", "tiSimplificado": "tiSimplificado", "tiNFCe": "tiNFCe", "tiMsgEletronica": "tiMsgEletronica", "tiSimplificadoTipo2": "tiSimplificadoTipo2" });
1925
+ var TcCredPres = Object.freeze({ "cpNenhum": "cpNenhum", "cp01": "cp01", "cp02": "cp02", "cp03": "cp03", "cp04": "cp04", "cp05": "cp05", "cp06": "cp06", "cp07": "cp07", "cp08": "cp08", "cp09": "cp09", "cp10": "cp10", "cp11": "cp11", "cp12": "cp12", "cp13": "cp13" });
1926
+ var TCSOSNIcms = Object.freeze({ "csosnVazio": "csosnVazio", "csosn101": "csosn101", "csosn102": "csosn102", "csosn103": "csosn103", "csosn201": "csosn201", "csosn202": "csosn202", "csosn203": "csosn203", "csosn300": "csosn300", "csosn400": "csosn400", "csosn500": "csosn500", "csosn900": "csosn900" });
1927
+ var TCSTCofins = Object.freeze({ "cof01": "cof01", "cof02": "cof02", "cof03": "cof03", "cof04": "cof04", "cof05": "cof05", "cof06": "cof06", "cof07": "cof07", "cof08": "cof08", "cof09": "cof09", "cof49": "cof49", "cof50": "cof50", "cof51": "cof51", "cof52": "cof52", "cof53": "cof53", "cof54": "cof54", "cof55": "cof55", "cof56": "cof56", "cof60": "cof60", "cof61": "cof61", "cof62": "cof62", "cof63": "cof63", "cof64": "cof64", "cof65": "cof65", "cof66": "cof66", "cof67": "cof67", "cof70": "cof70", "cof71": "cof71", "cof72": "cof72", "cof73": "cof73", "cof74": "cof74", "cof75": "cof75", "cof98": "cof98", "cof99": "cof99" });
1928
+ var TCSTIBSCBS = Object.freeze({ "cstNenhum": "cstNenhum", "cst000": "cst000", "cst010": "cst010", "cst011": "cst011", "cst200": "cst200", "cst220": "cst220", "cst221": "cst221", "cst222": "cst222", "cst400": "cst400", "cst410": "cst410", "cst510": "cst510", "cst515": "cst515", "cst550": "cst550", "cst620": "cst620", "cst800": "cst800", "cst810": "cst810", "cst811": "cst811", "cst820": "cst820", "cst830": "cst830" });
1929
+ var TCSTIcms = Object.freeze({ "cstVazio": "cstVazio", "cst00": "cst00", "cst10": "cst10", "cst20": "cst20", "cst30": "cst30", "cst40": "cst40", "cst41": "cst41", "cst45": "cst45", "cst50": "cst50", "cst51": "cst51", "cst60": "cst60", "cst70": "cst70", "cst80": "cst80", "cst81": "cst81", "cst90": "cst90", "cstICMSOutraUF": "cstICMSOutraUF", "cstICMSSN": "cstICMSSN", "cstPart10": "cstPart10", "cstPart90": "cstPart90", "cstRep41": "cstRep41", "cstRep60": "cstRep60", "cst02": "cst02", "cst15": "cst15", "cst53": "cst53", "cst61": "cst61", "cst01": "cst01", "cst12": "cst12", "cst13": "cst13", "cst14": "cst14", "cst21": "cst21", "cst72": "cst72", "cst73": "cst73", "cst74": "cst74", "cstPart20": "cstPart20" });
1930
+ var TCSTPis = Object.freeze({ "pis01": "pis01", "pis02": "pis02", "pis03": "pis03", "pis04": "pis04", "pis05": "pis05", "pis06": "pis06", "pis07": "pis07", "pis08": "pis08", "pis09": "pis09", "pis49": "pis49", "pis50": "pis50", "pis51": "pis51", "pis52": "pis52", "pis53": "pis53", "pis54": "pis54", "pis55": "pis55", "pis56": "pis56", "pis60": "pis60", "pis61": "pis61", "pis62": "pis62", "pis63": "pis63", "pis64": "pis64", "pis65": "pis65", "pis66": "pis66", "pis67": "pis67", "pis70": "pis70", "pis71": "pis71", "pis72": "pis72", "pis73": "pis73", "pis74": "pis74", "pis75": "pis75", "pis98": "pis98", "pis99": "pis99" });
1931
+ var TIndicadorEx = Object.freeze({ "tieNenhum": "tieNenhum", "tieSim": "tieSim", "tieNao": "tieNao" });
1932
+ var TindIEDest = Object.freeze({ "inContribuinte": "inContribuinte", "inIsento": "inIsento", "inNaoContribuinte": "inNaoContribuinte" });
1933
+ var TindImport = Object.freeze({ "iiNacional": "iiNacional", "iiImportado": "iiImportado" });
1934
+ var TindIncentivo = Object.freeze({ "iiSim": "iiSim", "iiNao": "iiNao" });
1935
+ var TindIntermed = Object.freeze({ "iiSemOperacao": "iiSemOperacao", "iiOperacaoSemIntermediador": "iiOperacaoSemIntermediador", "iiOperacaoComIntermediador": "iiOperacaoComIntermediador" });
1936
+ var TIndSomaCOFINSST = Object.freeze({ "iscNenhum": "iscNenhum", "iscCOFINSSTNaoCompoe": "iscCOFINSSTNaoCompoe", "iscCOFINSSTCompoe": "iscCOFINSSTCompoe" });
1937
+ var TIndSomaPISST = Object.freeze({ "ispNenhum": "ispNenhum", "ispPISSTNaoCompoe": "ispPISSTNaoCompoe", "ispPISSTCompoe": "ispPISSTCompoe" });
1938
+ var TmotRedAdRem = Object.freeze({ "motTranspColetivo": "motTranspColetivo", "motOutros": "motOutros" });
1939
+ var TOrigemMercadoria = Object.freeze({ "oeNacional": "oeNacional", "oeEstrangeiraImportacaoDireta": "oeEstrangeiraImportacaoDireta", "oeEstrangeiraAdquiridaBrasil": "oeEstrangeiraAdquiridaBrasil", "oeNacionalConteudoImportacaoSuperior40": "oeNacionalConteudoImportacaoSuperior40", "oeNacionalProcessosBasicos": "oeNacionalProcessosBasicos", "oeNacionalConteudoImportacaoInferiorIgual40": "oeNacionalConteudoImportacaoInferiorIgual40", "oeEstrangeiraImportacaoDiretaSemSimilar": "oeEstrangeiraImportacaoDiretaSemSimilar", "oeEstrangeiraAdquiridaBrasilSemSimilar": "oeEstrangeiraAdquiridaBrasilSemSimilar", "oeNacionalConteudoImportacaoSuperior70": "oeNacionalConteudoImportacaoSuperior70", "oeReservadoParaUsoFuturo": "oeReservadoParaUsoFuturo", "oeVazio": "oeVazio" });
1940
+ var TpcnBandeiraCartao = Object.freeze({ "bcVisa": "bcVisa", "bcMasterCard": "bcMasterCard", "bcAmericanExpress": "bcAmericanExpress", "bcSorocred": "bcSorocred", "bcDinersClub": "bcDinersClub", "bcElo": "bcElo", "bcHipercard": "bcHipercard", "bcAura": "bcAura", "bcCabal": "bcCabal", "bcAlelo": "bcAlelo", "bcBanesCard": "bcBanesCard", "bcCalCard": "bcCalCard", "bcCredz": "bcCredz", "bcDiscover": "bcDiscover", "bcGoodCard": "bcGoodCard", "bcGreenCard": "bcGreenCard", "bcHiper": "bcHiper", "bcJcB": "bcJcB", "bcMais": "bcMais", "bcMaxVan": "bcMaxVan", "bcPolicard": "bcPolicard", "bcRedeCompras": "bcRedeCompras", "bcSodexo": "bcSodexo", "bcValeCard": "bcValeCard", "bcVerocheque": "bcVerocheque", "bcVR": "bcVR", "bcTicket": "bcTicket", "bcOutros": "bcOutros" });
1941
+ var TpcnCondicaoVeiculo = Object.freeze({ "cvAcabado": "cvAcabado", "cvInacabado": "cvInacabado", "cvSemiAcabado": "cvSemiAcabado" });
1942
+ var TpcnConsumidorFinal = Object.freeze({ "cfNao": "cfNao", "cfConsumidorFinal": "cfConsumidorFinal" });
1943
+ var TpcnCRT = Object.freeze({ "crtSimplesNacional": "crtSimplesNacional", "crtSimplesExcessoReceita": "crtSimplesExcessoReceita", "crtRegimeNormal": "crtRegimeNormal", "crtMEI": "crtMEI" });
1944
+ var TpcnCstIpi = Object.freeze({ "ipi00": "ipi00", "ipi49": "ipi49", "ipi50": "ipi50", "ipi99": "ipi99", "ipi01": "ipi01", "ipi02": "ipi02", "ipi03": "ipi03", "ipi04": "ipi04", "ipi05": "ipi05", "ipi51": "ipi51", "ipi52": "ipi52", "ipi53": "ipi53", "ipi54": "ipi54", "ipi55": "ipi55" });
1945
+ var TpcnDestinoOperacao = Object.freeze({ "doInterna": "doInterna", "doInterestadual": "doInterestadual", "doExterior": "doExterior" });
1946
+ var TpcnDeterminacaoBaseIcms = Object.freeze({ "dbiMargemValorAgregado": "dbiMargemValorAgregado", "dbiPauta": "dbiPauta", "dbiPrecoTabelado": "dbiPrecoTabelado", "dbiValorOperacao": "dbiValorOperacao", "dbiNenhum": "dbiNenhum" });
1947
+ var TpcnDeterminacaoBaseIcmsST = Object.freeze({ "dbisPrecoTabelado": "dbisPrecoTabelado", "dbisListaNegativa": "dbisListaNegativa", "dbisListaPositiva": "dbisListaPositiva", "dbisListaNeutra": "dbisListaNeutra", "dbisMargemValorAgregado": "dbisMargemValorAgregado", "dbisPauta": "dbisPauta", "dbisValordaOperacao": "dbisValordaOperacao" });
1948
+ var TpcnECFModRef = Object.freeze({ "ECFModRefVazio": "ECFModRefVazio", "ECFModRef2B": "ECFModRef2B", "ECFModRef2C": "ECFModRef2C", "ECFModRef2D": "ECFModRef2D" });
1949
+ var TpcnFinalidadeNFe = Object.freeze({ "fnNormal": "fnNormal", "fnComplementar": "fnComplementar", "fnAjuste": "fnAjuste", "fnDevolucao": "fnDevolucao", "fnCredito": "fnCredito", "fnDebito": "fnDebito" });
1950
+ var TpcnFormaPagamento = Object.freeze({ "fpDinheiro": "fpDinheiro", "fpCheque": "fpCheque", "fpCartaoCredito": "fpCartaoCredito", "fpCartaoDebito": "fpCartaoDebito", "fpCreditoLoja": "fpCreditoLoja", "fpValeAlimentacao": "fpValeAlimentacao", "fpValeRefeicao": "fpValeRefeicao", "fpValePresente": "fpValePresente", "fpValeCombustivel": "fpValeCombustivel", "fpDuplicataMercantil": "fpDuplicataMercantil", "fpBoletoBancario": "fpBoletoBancario", "fpDepositoBancario": "fpDepositoBancario", "fpPagamentoInstantaneo": "fpPagamentoInstantaneo", "fpTransfBancario": "fpTransfBancario", "fpProgramaFidelidade": "fpProgramaFidelidade", "fpSemPagamento": "fpSemPagamento", "fpRegimeEspecial": "fpRegimeEspecial", "fpOutro": "fpOutro", "fpPagamentoInstantaneoEstatico": "fpPagamentoInstantaneoEstatico", "fpCreditoEmLojaPorDevolucao": "fpCreditoEmLojaPorDevolucao", "fpFalhaHardware": "fpFalhaHardware", "fpPagamentoPosterior": "fpPagamentoPosterior", "fpPagInstantaneoPIXAutomatico": "fpPagInstantaneoPIXAutomatico", "fpTEFBookTransfer": "fpTEFBookTransfer" });
1951
+ var TpcnIndEscala = Object.freeze({ "ieRelevante": "ieRelevante", "ieNaoRelevante": "ieNaoRelevante", "ieNenhum": "ieNenhum" });
1952
+ var TpcnIndicadorPagamento = Object.freeze({ "ipVista": "ipVista", "ipPrazo": "ipPrazo", "ipOutras": "ipOutras", "ipNenhum": "ipNenhum" });
1953
+ var TpcnIndicadorProcesso = Object.freeze({ "ipSEFAZ": "ipSEFAZ", "ipJusticaFederal": "ipJusticaFederal", "ipJusticaEstadual": "ipJusticaEstadual", "ipSecexRFB": "ipSecexRFB", "ipCONFAZ": "ipCONFAZ", "ipOutros": "ipOutros" });
1954
+ var TpcnIndicadorTotal = Object.freeze({ "itSomaTotalNFe": "itSomaTotalNFe", "itNaoSomaTotalNFe": "itNaoSomaTotalNFe" });
1955
+ var TpcnindISS = Object.freeze({ "iiExigivel": "iiExigivel", "iiNaoIncidencia": "iiNaoIncidencia", "iiIsencao": "iiIsencao", "iiExportacao": "iiExportacao", "iiImunidade": "iiImunidade", "iiExigSuspDecisaoJudicial": "iiExigSuspDecisaoJudicial", "iiExigSuspProcessoAdm": "iiExigSuspProcessoAdm" });
1956
+ var TpcnindISSRet = Object.freeze({ "iirSim": "iirSim", "iirNao": "iirNao" });
1957
+ var TpcnISSQNcSitTrib = Object.freeze({ "ISSQNcSitTribVazio": "ISSQNcSitTribVazio", "ISSQNcSitTribNORMAL": "ISSQNcSitTribNORMAL", "ISSQNcSitTribRETIDA": "ISSQNcSitTribRETIDA", "ISSQNcSitTribSUBSTITUTA": "ISSQNcSitTribSUBSTITUTA", "ISSQNcSitTribISENTA": "ISSQNcSitTribISENTA" });
1958
+ var TpcnModalidadeFrete = Object.freeze({ "mfContaEmitente": "mfContaEmitente", "mfContaDestinatario": "mfContaDestinatario", "mfContaTerceiros": "mfContaTerceiros", "mfProprioRemetente": "mfProprioRemetente", "mfProprioDestinatario": "mfProprioDestinatario", "mfSemFrete": "mfSemFrete" });
1959
+ var TpcnMotivoDesoneracaoICMS = Object.freeze({ "mdiTaxi": "mdiTaxi", "mdiDeficienteFisico": "mdiDeficienteFisico", "mdiProdutorAgropecuario": "mdiProdutorAgropecuario", "mdiFrotistaLocadora": "mdiFrotistaLocadora", "mdiDiplomaticoConsular": "mdiDiplomaticoConsular", "mdiAmazoniaLivreComercio": "mdiAmazoniaLivreComercio", "mdiSuframa": "mdiSuframa", "mdiVendaOrgaosPublicos": "mdiVendaOrgaosPublicos", "mdiOutros": "mdiOutros", "mdiDeficienteCondutor": "mdiDeficienteCondutor", "mdiDeficienteNaoCondutor": "mdiDeficienteNaoCondutor", "mdiOrgaoFomento": "mdiOrgaoFomento", "mdiOlimpiadaRio2016": "mdiOlimpiadaRio2016", "mdiSolicitadoFisco": "mdiSolicitadoFisco" });
1960
+ var TpcnPresencaComprador = Object.freeze({ "pcNao": "pcNao", "pcPresencial": "pcPresencial", "pcInternet": "pcInternet", "pcTeleatendimento": "pcTeleatendimento", "pcEntregaDomicilio": "pcEntregaDomicilio", "pcPresencialForaEstabelecimento": "pcPresencialForaEstabelecimento", "pcOutros": "pcOutros" });
1961
+ var TpcnTipoArma = Object.freeze({ "taUsoPermitido": "taUsoPermitido", "taUsoRestrito": "taUsoRestrito" });
1962
+ var TpcnTipoIntermedio = Object.freeze({ "tiContaPropria": "tiContaPropria", "tiContaOrdem": "tiContaOrdem", "tiEncomenda": "tiEncomenda" });
1963
+ var TpcnTipoOperacao = Object.freeze({ "toVendaConcessionaria": "toVendaConcessionaria", "toFaturamentoDireto": "toFaturamentoDireto", "toVendaDireta": "toVendaDireta", "toOutros": "toOutros" });
1964
+ var TpcnTipoViaTransp = Object.freeze({ "tvMaritima": "tvMaritima", "tvFluvial": "tvFluvial", "tvLacustre": "tvLacustre", "tvAerea": "tvAerea", "tvPostal": "tvPostal", "tvFerroviaria": "tvFerroviaria", "tvRodoviaria": "tvRodoviaria", "tvConduto": "tvConduto", "tvMeiosProprios": "tvMeiosProprios", "tvEntradaSaidaFicta": "tvEntradaSaidaFicta", "tvCourier": "tvCourier", "tvEmMaos": "tvEmMaos", "tvPorReboque": "tvPorReboque" });
1965
+ var TRegTribISSQN = Object.freeze({ "RTISSMicroempresaMunicipal": "RTISSMicroempresaMunicipal", "RTISSEstimativa": "RTISSEstimativa", "RTISSSociedadeProfissionais": "RTISSSociedadeProfissionais", "RTISSCooperativa": "RTISSCooperativa", "RTISSMEI": "RTISSMEI", "RTISSMEEPP": "RTISSMEEPP", "RTISSNenhum": "RTISSNenhum" });
1966
+ var TTipoNFe = Object.freeze({ "tnEntrada": "tnEntrada", "tnSaida": "tnSaida" });
1967
+ var TtpALCZFMCBS = Object.freeze({ "tpALCZFMCBSnOpInd": "tpALCZFMCBSnOpInd", "tpALCZFMCBSOpInd": "tpALCZFMCBSOpInd" });
1968
+ var TtpAto = Object.freeze({ "taNenhum": "taNenhum", "taTermoAcordo": "taTermoAcordo", "taRegimeEspecial": "taRegimeEspecial", "taAutorizacaoEspecifica": "taAutorizacaoEspecifica", "taAjusteSNIEF": "taAjusteSNIEF", "taConvenioICMS": "taConvenioICMS" });
1969
+ var TTpCredPresIBSZFM = Object.freeze({ "tcpNenhum": "tcpNenhum", "tcpSemCredito": "tcpSemCredito", "tcpBensConsumoFinal": "tcpBensConsumoFinal", "tcpBensCapital": "tcpBensCapital", "tcpBensIntermediarios": "tcpBensIntermediarios", "tcpBensInformaticaOutros": "tcpBensInformaticaOutros" });
1970
+ var TtpEnteGov = Object.freeze({ "tcgNenhum": "tcgNenhum", "tcgUniao": "tcgUniao", "tcgEstados": "tcgEstados", "tcgDistritoFederal": "tcgDistritoFederal", "tcgMunicipios": "tcgMunicipios", "tcgConsorcioPublico": "tcgConsorcioPublico", "tcgComiteGestorIBS": "tcgComiteGestorIBS" });
1971
+ var TtpGuia = Object.freeze({ "tpgNenhum": "tpgNenhum", "tpgGTA": "tpgGTA", "tpgTTA": "tpgTTA", "tpgDTA": "tpgDTA", "tpgATV": "tpgATV", "tpgPTV": "tpgPTV", "tpgGTV": "tpgGTV", "tpgGuiaFlorestal": "tpgGuiaFlorestal" });
1972
+ var TtpIntegra = Object.freeze({ "tiNaoInformado": "tiNaoInformado", "tiPagIntegrado": "tiPagIntegrado", "tiPagNaoIntegrado": "tiPagNaoIntegrado" });
1973
+ var TtpNFCredito = Object.freeze({ "tcNenhum": "tcNenhum", "tcMultaJuros": "tcMultaJuros", "tcApropriacaoCreditoPresumido": "tcApropriacaoCreditoPresumido", "tcRetorno": "tcRetorno", "tcReducaoValores": "tcReducaoValores", "tcTransferenciaCreditoSucessao": "tcTransferenciaCreditoSucessao", "tcRetornoRecusaParcial": "tcRetornoRecusaParcial" });
1974
+ var TtpNFDebito = Object.freeze({ "tdNenhum": "tdNenhum", "tdTransferenciaCreditoCooperativa": "tdTransferenciaCreditoCooperativa", "tdAnulacao": "tdAnulacao", "tdDebitosNaoProcessadas": "tdDebitosNaoProcessadas", "tdMultaJuros": "tdMultaJuros", "tdTransferenciaCreditoSucessao": "tdTransferenciaCreditoSucessao", "tdPagamentoAntecipado": "tdPagamentoAntecipado", "tdPerdaEmEstoque": "tdPerdaEmEstoque", "tdDesenquadramentodoSN": "tdDesenquadramentodoSN" });
1975
+ var TtpOperGov = Object.freeze({ "togNenhum": "togNenhum", "togFornecimento": "togFornecimento", "togRecebimentoPag": "togRecebimentoPag", "togFornecimentoPagRealizado": "togFornecimentoPagRealizado", "togRecebimentoPagFornecPosterior": "togRecebimentoPagFornecPosterior" });
1976
+
1977
+ // src/contract-help.ts
1978
+ var FieldHelpError = class extends Error {
1979
+ constructor(code, message, details) {
1980
+ super(message);
1981
+ this.code = code;
1982
+ this.details = details;
1983
+ this.name = "FieldHelpError";
1984
+ }
1985
+ };
1986
+ var kinds = /* @__PURE__ */ new Set(["string", "integer", "decimal", "datetime", "boolean", "enum", "object", "list"]);
1987
+ var identifier = /^[A-Za-z_]\w*$/;
1988
+ var sha256 = /^[a-f0-9]{64}$/;
1989
+ var fail = (message = "Os metadados do contrato s\xE3o inv\xE1lidos.") => {
1990
+ throw new FieldHelpError("CONTRATO_INVALIDO", message);
1991
+ };
1992
+ function validateContractMetadata(value) {
1993
+ const metadata = value;
1994
+ if (!metadata || metadata.formatVersion !== 1 || !Number.isSafeInteger(metadata.sourceRevision) || metadata.sourceRevision < 1 || !sha256.test(metadata.sourceHash ?? "") || !sha256.test(metadata.contractHash ?? "") || metadata.ir?.schemaVersion !== 1 || !identifier.test(metadata.ir.root ?? "") || !Array.isArray(metadata.ir.types) || metadata.ir.types.length === 0) fail();
1995
+ const digest = createHash("sha256").update(JSON.stringify({ sourceRevision: metadata.sourceRevision, sourceHash: metadata.sourceHash, ir: metadata.ir })).digest("hex");
1996
+ if (digest !== metadata.contractHash) fail("O hash dos metadados diverge do contrato gerado.");
1997
+ const types = /* @__PURE__ */ new Map();
1998
+ for (const node of metadata.ir.types) {
1999
+ if (!node || typeof node.name !== "string" || !identifier.test(node.name) || types.has(node.name) || !["object", "list", "enum"].includes(node.kind)) fail();
2000
+ types.set(node.name, node);
2001
+ }
2002
+ if (types.get(metadata.ir.root)?.kind !== "object") fail();
2003
+ for (const node of types.values()) {
2004
+ if (node.kind === "enum") {
2005
+ if (!Array.isArray(node.values) || node.values.length === 0 || node.values.some((v) => typeof v !== "string" || !identifier.test(v)) || new Set(node.values).size !== node.values.length) fail();
2006
+ } else if (node.kind === "list") {
2007
+ if (!node.item || types.get(node.item)?.kind !== "object") fail();
2008
+ } else {
2009
+ if (!Array.isArray(node.properties)) fail();
2010
+ const names = /* @__PURE__ */ new Set();
2011
+ for (const property of node.properties) {
2012
+ if (!property || typeof property.name !== "string" || !identifier.test(property.name) || names.has(property.name.toLowerCase()) || !kinds.has(property.kind) || typeof property.type !== "string" || typeof property.readonly !== "boolean") fail();
2013
+ names.add(property.name.toLowerCase());
2014
+ if (["object", "list", "enum"].includes(property.kind) && (!property.ref || types.get(property.ref)?.kind !== property.kind)) fail();
2015
+ if (!["object", "list", "enum"].includes(property.kind) && property.ref !== void 0) fail();
2016
+ if (property.declaredDefault !== void 0 && typeof property.declaredDefault !== "string") fail();
2017
+ for (const key of ["min", "max", "scale"]) if (property[key] !== void 0 && !Number.isFinite(property[key])) fail();
2018
+ }
2019
+ }
2020
+ }
2021
+ return metadata;
2022
+ }
2023
+ function matchingPaths(types, root, field) {
2024
+ const paths = [];
2025
+ let incomplete = false;
2026
+ function visit(name, prefix, trail) {
2027
+ if (trail.has(name) || trail.size > 128 || paths.length > 1e3) {
2028
+ incomplete = true;
2029
+ return;
2030
+ }
2031
+ const node = types.get(name);
2032
+ const next = new Set(trail).add(name);
2033
+ if (node.kind === "list") {
2034
+ visit(node.item, prefix + "[]", next);
2035
+ return;
2036
+ }
2037
+ if (node.kind !== "object") return;
2038
+ for (const property of node.properties) {
2039
+ const candidate = prefix ? prefix + "." + property.name : property.name;
2040
+ if (property.name === field) paths.push(candidate);
2041
+ if (property.ref && property.kind !== "enum") visit(property.ref, candidate, next);
2042
+ }
2043
+ }
2044
+ visit(root, "", /* @__PURE__ */ new Set());
2045
+ if (incomplete) throw new FieldHelpError("CAMINHO_COMPLETO_NECESSARIO", "O contrato cont\xE9m caminhos recursivos ou extensos. Informe o caminho completo.");
2046
+ return paths.sort();
2047
+ }
2048
+ function describeField(metadata, sdkVersion, query) {
2049
+ validateContractMetadata(metadata);
2050
+ if (typeof query !== "string" || query.length > 512 || !/^[A-Za-z_]\w*(?:\[(?:\d*)\])?(?:\.[A-Za-z_]\w*(?:\[(?:\d*)\])?)*$/.test(query))
2051
+ throw new FieldHelpError("CAMINHO_INVALIDO", "Use nomes de campos separados por ponto e [] para elementos de cole\xE7\xE3o.");
2052
+ const types = new Map(metadata.ir.types.map((node2) => [node2.name, node2]));
2053
+ const root = metadata.ir.root;
2054
+ const base = { formatVersion: 1, sdkVersion, sourceRevision: metadata.sourceRevision, sourceHash: metadata.sourceHash, contractHash: metadata.contractHash, root };
2055
+ let relative3 = query === root ? "" : query.startsWith(root + ".") ? query.slice(root.length + 1) : query;
2056
+ if (identifier.test(relative3) && !types.get(root).properties.some((property2) => property2.name === relative3)) {
2057
+ const matches = matchingPaths(types, root, relative3);
2058
+ if (matches.length > 1) throw new FieldHelpError("CAMPO_AMBIGUO", "O nome aparece em mais de um caminho. Informe o caminho completo.", { candidates: matches });
2059
+ if (matches.length === 1) relative3 = matches[0];
2060
+ }
2061
+ let node = types.get(root);
2062
+ let property;
2063
+ let readonly = false;
2064
+ const canonical = [];
2065
+ const parts = relative3 ? relative3.split(".") : [];
2066
+ for (let index = 0; index < parts.length; index++) {
2067
+ const segment = parts[index];
2068
+ const parsed = /^([A-Za-z_]\w*)(\[(?:\d*)\])?$/.exec(segment);
2069
+ if (node.kind !== "object") throw new FieldHelpError("CAMINHO_INVALIDO", "O caminho tenta acessar um campo de um valor simples.");
2070
+ property = node.properties.find((item) => item.name === parsed[1]);
2071
+ if (!property) throw new FieldHelpError("CAMPO_INEXISTENTE", "O campo n\xE3o existe nesse objeto do contrato.", { segment: parsed[1], ownerType: node.name, candidates: node.properties.map((item) => item.name) });
2072
+ readonly ||= property.readonly;
2073
+ canonical.push(property.name);
2074
+ const selected = parsed[2] !== void 0;
2075
+ if (selected && property.kind !== "list") throw new FieldHelpError("CAMPO_NAO_COLECAO", "[] ou \xEDndice foi usado em um campo que n\xE3o \xE9 cole\xE7\xE3o.");
2076
+ if (property.kind === "list") {
2077
+ node = types.get(property.ref);
2078
+ if (selected) {
2079
+ canonical[canonical.length - 1] += "[]";
2080
+ node = types.get(node.item);
2081
+ } else if (index < parts.length - 1) throw new FieldHelpError("COLECAO_REQUER_INDICE", "Use [] ou um \xEDndice para consultar campos do elemento da cole\xE7\xE3o.");
2082
+ } else if (property.ref) node = types.get(property.ref);
2083
+ else if (index < parts.length - 1) throw new FieldHelpError("CAMINHO_INVALIDO", "Um valor simples n\xE3o cont\xE9m outros campos.");
2084
+ }
2085
+ const selectedListItem = property?.kind === "list" && canonical[canonical.length - 1]?.endsWith("[]");
2086
+ const kind = selectedListItem ? "object" : property?.kind ?? "object";
2087
+ const description = {
2088
+ ...base,
2089
+ path: [root, ...canonical].join("."),
2090
+ kind,
2091
+ pascalType: selectedListItem ? node.name : property?.type ?? node.name,
2092
+ inputType: kind === "integer" ? "number" : kind === "boolean" ? "boolean" : kind === "object" ? "object" : kind === "list" ? "array" : "string",
2093
+ readonly
2094
+ };
2095
+ if (property?.declaredDefault !== void 0) description.declaredDefault = property.declaredDefault;
2096
+ if (property?.ref) description.typeReference = selectedListItem ? node.name : property.ref;
2097
+ if (kind === "enum") description.values = [...node.values];
2098
+ const constraints = property && Object.fromEntries(["min", "max", "scale"].filter((key) => property[key] !== void 0).map((key) => [key, property[key]]));
2099
+ if (constraints && Object.keys(constraints).length) description.constraints = constraints;
2100
+ if (kind === "list") description.itemType = node.item;
2101
+ if (kind === "object") description.members = node.properties.map((item) => ({ name: item.name, kind: item.kind, pascalType: item.type, readonly: readonly || item.readonly }));
2102
+ return description;
2103
+ }
2104
+ async function describeInstalledField(query, packageRoot) {
2105
+ let metadata, pkg, lock;
2106
+ try {
2107
+ [metadata, pkg, lock] = await Promise.all(["dist/contract.json", "package.json", "acbr.lock.json"].map(async (filename) => JSON.parse(await readFile(path.join(packageRoot, filename), "utf8"))));
2108
+ } catch {
2109
+ throw new FieldHelpError("CONTRATO_INDISPONIVEL", "Os metadados empacotados n\xE3o est\xE3o dispon\xEDveis. Reinstale o pacote ou gere e compile o checkout.");
2110
+ }
2111
+ validateContractMetadata(metadata);
2112
+ if (typeof pkg.version !== "string" || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(pkg.version) || metadata.sourceRevision !== lock.source?.revision || metadata.sourceHash !== lock.source?.treeHash || metadata.sourceRevision !== ACBR_CONTRACT.sourceRevision || metadata.contractHash !== ACBR_CONTRACT.contractHash)
2113
+ throw new FieldHelpError("CONTRATO_INCOMPATIVEL", "Os metadados divergem da vers\xE3o instalada, do lock ou do validador gerado.");
2114
+ return describeField(metadata, pkg.version, query);
2115
+ }
2116
+ function formatFieldDescription(description) {
2117
+ const lines = [
2118
+ description.path,
2119
+ `Tipo: ${description.pascalType}${description.typeReference && description.typeReference !== description.pascalType ? ` [${description.typeReference}]` : ""} (${description.kind}; entrada ${description.inputType})`,
2120
+ `Somente leitura: ${description.readonly ? "sim" : "n\xE3o"}`
2121
+ ];
2122
+ if (description.values) lines.push(`Valores permitidos na API: ${description.values.join(", ")}`);
2123
+ if (description.declaredDefault !== void 0) lines.push(`Padr\xE3o declarado no Pascal: ${description.declaredDefault} (n\xE3o substitui regras fiscais ou o construtor nativo).`);
2124
+ if (description.constraints) lines.push(`Limites do tipo: ${JSON.stringify(description.constraints)}`);
2125
+ if (description.itemType) lines.push(`Tipo do elemento: ${description.itemType}`);
2126
+ if (description.members) lines.push(`Campos: ${description.members.map((member) => member.name).join(", ")}`);
2127
+ lines.push(`SDK: ${description.sdkVersion}; revis\xE3o ACBr: ${description.sourceRevision}`, `Contrato: ${description.contractHash}`);
2128
+ return lines.join("\n");
2129
+ }
1793
2130
 
1794
2131
  // src/cli.ts
1795
2132
  var HELP = `acbr-node \u2014 compila\xE7\xE3o e contrato Node/ACBr NF-e
1796
2133
 
1797
2134
  Uso:
2135
+ acbr-node help TAG Ide.tpNF [--json]
2136
+ acbr-node help TAG 'Det[].Imposto.PIS.CST' [--json]
1798
2137
  acbr-node init [--config caminho] [--revision HEAD|n\xFAmero]
1799
2138
  acbr-node source update [--config caminho] [--revision HEAD|n\xFAmero]
1800
2139
  acbr-node source lock --revision n\xFAmero [--config caminho]
@@ -1806,6 +2145,7 @@ Uso:
1806
2145
  source update consulta o SVN oficial e substitui apenas fontes verificadas pelo lock.
1807
2146
  source lock registra um export existente cuja origem/revis\xE3o o operador j\xE1 conferiu.
1808
2147
  generate/build/check nunca atualizam fontes. Nenhum comando transmite NF-e.
2148
+ help TAG consulta somente o contrato da vers\xE3o instalada, offline e sem runtime ou certificado.
1809
2149
  `;
1810
2150
  function revision(value) {
1811
2151
  if (value === void 0) return void 0;
@@ -1835,9 +2175,17 @@ function parseArguments(args) {
1835
2175
  }
1836
2176
  return result;
1837
2177
  }
1838
- async function main(args = process.argv.slice(2), io = process) {
2178
+ async function main(args = process.argv.slice(2), io = process, dependencies = {}) {
2179
+ const initialCommand = args.filter((arg) => !["--json", "--help", "-h"].includes(arg));
2180
+ let jsonTag = args.includes("--json") && initialCommand[0]?.toLowerCase() === "help" && initialCommand[1]?.toLowerCase() === "tag";
1839
2181
  try {
1840
- const options = parseArguments(args);
2182
+ let options;
2183
+ try {
2184
+ options = parseArguments(args);
2185
+ } catch (error) {
2186
+ if (jsonTag) throw new FieldHelpError("USO_INVALIDO", "Argumentos inv\xE1lidos. Use acbr-node help TAG caminho [--json].");
2187
+ throw error;
2188
+ }
1841
2189
  const command = options.command.join(" ");
1842
2190
  if (options.help || !command) {
1843
2191
  io.stdout.write(HELP);
@@ -1846,8 +2194,17 @@ async function main(args = process.argv.slice(2), io = process) {
1846
2194
  const output = (value, text) => io.stdout.write(options.json ? `${JSON.stringify(value, null, 2)}
1847
2195
  ` : `${text}
1848
2196
  `);
2197
+ if (options.command[0]?.toLowerCase() === "help" && options.command[1]?.toLowerCase() === "tag") {
2198
+ jsonTag = options.json;
2199
+ if (options.command.length !== 3) throw new FieldHelpError("USO_INVALIDO", "Use acbr-node help TAG caminho [--json].");
2200
+ if (options.revision !== void 0 || args.includes("--config")) throw new FieldHelpError("USO_INVALIDO", "help TAG usa o contrato instalado e n\xE3o aceita --config ou --revision.");
2201
+ const description = await describeInstalledField(options.command[2], dependencies.contractRoot ?? fileURLToPath3(new URL("../", import.meta.url)));
2202
+ output(description, formatFieldDescription(description));
2203
+ return 0;
2204
+ }
1849
2205
  if (command === "init") {
1850
- const config2 = await initializeConfig(options.config, options.revision, fileURLToPath3(new URL("../", import.meta.url)));
2206
+ const { initializeConfig: initializeConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
2207
+ const config2 = await initializeConfig2(options.config, options.revision, fileURLToPath3(new URL("../", import.meta.url)));
1851
2208
  output({ configPath: config2.configPath }, `Configura\xE7\xE3o criada: ${config2.configPath}
1852
2209
  Pr\xF3ximo passo: acbr-node source update.`);
1853
2210
  return 0;
@@ -1855,46 +2212,61 @@ Pr\xF3ximo passo: acbr-node source update.`);
1855
2212
  if (!["source update", "source lock", "generate", "build", "check", "doctor"].includes(command)) throw new Error(`Comando desconhecido: ${command}. Use --help.`);
1856
2213
  if (options.revision !== void 0 && !command.startsWith("source ")) throw new Error("--revision \xE9 aceito somente em init e source.");
1857
2214
  if (command === "doctor") {
2215
+ const { loadConfig: loadConfig3 } = await Promise.resolve().then(() => (init_config(), config_exports));
2216
+ const { doctor: doctor2 } = await Promise.resolve().then(() => (init_native_build(), native_build_exports));
1858
2217
  let config2;
1859
2218
  try {
1860
2219
  await access4(resolve4(options.config));
1861
- config2 = await loadConfig(options.config);
2220
+ config2 = await loadConfig3(options.config);
1862
2221
  } catch (error) {
1863
2222
  if (error.code !== "ENOENT") throw error;
1864
2223
  }
1865
- const report = await doctor(config2);
2224
+ const report = await doctor2(config2);
1866
2225
  output(report, report.map((item) => `${item.ok ? "OK" : "FALHA"} ${item.name}: ${item.detail}`).join("\n"));
1867
2226
  return report.every((item) => item.ok) ? 0 : 1;
1868
2227
  }
1869
- const config = await loadConfig(options.config);
2228
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
2229
+ const config = await loadConfig2(options.config);
1870
2230
  if (command === "source update") {
1871
- const lock = await updateSource(config, options.revision);
2231
+ const { updateSource: updateSource2 } = await Promise.resolve().then(() => (init_source(), source_exports));
2232
+ const lock = await updateSource2(config, options.revision);
1872
2233
  output(lock, `Fontes oficiais registradas na revis\xE3o ${lock.source.revision}.
1873
2234
  SHA256 da \xE1rvore: ${lock.source.treeHash}
1874
2235
  Execute generate para atualizar o contrato.`);
1875
2236
  } else if (command === "source lock") {
2237
+ const { lockExistingSource: lockExistingSource2 } = await Promise.resolve().then(() => (init_source(), source_exports));
1876
2238
  if (typeof options.revision !== "number") throw new Error("source lock exige --revision com o n\xFAmero verificado do export SVN.");
1877
2239
  if (config.source.revision !== "HEAD" && config.source.revision !== options.revision) throw new Error("Revis\xE3o do export diverge da configura\xE7\xE3o.");
1878
- const lock = await lockExistingSource(config, options.revision);
2240
+ const lock = await lockExistingSource2(config, options.revision);
1879
2241
  output(lock, `Export existente registrado na revis\xE3o ${lock.source.revision}; ${Object.keys(lock.source.files).length} arquivos protegidos por SHA256.`);
1880
2242
  } else if (command === "generate") {
1881
- const lock = await verifySource(config);
2243
+ const { verifySource: verifySource2 } = await Promise.resolve().then(() => (init_source(), source_exports));
2244
+ const lock = await verifySource2(config);
1882
2245
  const { generateModel: generateModel2 } = await Promise.resolve().then(() => (init_generator(), generator_exports));
1883
2246
  const result = await generateModel2({ acbrRoot: config.source.directory, outputDir: config.generator.outputDir, revision: String(lock.source.revision), sourceHash: lock.source.treeHash, fpcPath: config.native.fpc });
1884
2247
  output(result, `Contrato ${result.contractHash}; ${result.models} modelos gerados.
1885
2248
  Revise o relat\xF3rio: ${result.reportPath}`);
1886
2249
  } else if (command === "build") {
1887
- const result = await buildNative(config);
1888
- output(result, `Runtime compilado: ${runtimeDirectory(config)}
2250
+ const { buildNative: buildNative2, runtimeDirectory: runtimeDirectory2 } = await Promise.resolve().then(() => (init_native_build(), native_build_exports));
2251
+ const result = await buildNative2(config);
2252
+ output(result, `Runtime compilado: ${runtimeDirectory2(config)}
1889
2253
  ACBr revis\xE3o ${result.sourceRevision}; contrato ${result.contractHash}.`);
1890
2254
  } else {
1891
- const result = await checkBuild(config);
1892
- const offlineChecks = await checkOffline(config, result);
2255
+ const { checkBuild: checkBuild2 } = await Promise.resolve().then(() => (init_native_build(), native_build_exports));
2256
+ const { checkOffline: checkOffline2 } = await Promise.resolve().then(() => (init_offline_check(), offline_check_exports));
2257
+ const result = await checkBuild2(config);
2258
+ const offlineChecks = await checkOffline2(config, result);
1893
2259
  output({ ...result, offlineChecks }, `Fontes, contrato e ${Object.keys(result.files).length} arquivos do runtime conferidos por SHA256.
1894
2260
  ${offlineChecks.length} verifica\xE7\xF5es offline do motor aprovadas; nenhuma transmiss\xE3o.`);
1895
2261
  }
1896
2262
  return 0;
1897
2263
  } catch (error) {
2264
+ if (jsonTag) {
2265
+ const problem = error instanceof FieldHelpError ? { code: error.code, message: error.message, ...error.details } : { code: "HELP_INDISPONIVEL", message: "N\xE3o foi poss\xEDvel consultar o contrato instalado." };
2266
+ io.stderr.write(`${JSON.stringify({ ok: false, error: problem }, null, 2)}
2267
+ `);
2268
+ return 1;
2269
+ }
1898
2270
  io.stderr.write(`Erro: ${error.message}
1899
2271
  `);
1900
2272
  return 1;