cosmemilton-acbr-node 0.1.0 → 0.1.2

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