@br-validators/cli 1.8.3 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/constants.ts
9
2
  var SUPPORTED_TYPES = ["cnpj", "cpf", "cep", "telefone", "cnh", "renavam", "titulo-eleitor", "processo-judicial", "rg", "nfe-chave", "brcode", "placa", "pis-pasep", "pix", "boleto", "cartao", "ie"];
10
3
  var EXIT = {
@@ -16,41 +9,45 @@ var EXIT = {
16
9
  // src/commands/reference-lookup/registry.ts
17
10
  import {
18
11
  CEST_DATA_VERSION,
19
- getCestPorCodigo
12
+ lookupCestPorCodigo
20
13
  } from "@br-validators/core/cest";
21
14
  import {
22
15
  INCOTERMS_DATA_VERSION,
23
- getIncotermPorCodigo
16
+ lookupIncotermPorCodigo
24
17
  } from "@br-validators/core/incoterms";
25
18
  import {
26
19
  MOEDAS_DATA_VERSION,
27
- getMoedaPorCodigo
20
+ lookupMoedaPorCodigo
28
21
  } from "@br-validators/core/moedas";
29
22
  import {
30
23
  NATUREZA_JURIDICA_DATA_VERSION,
31
- getNaturezaJuridicaPorCodigo
24
+ lookupNaturezaJuridicaPorCodigo
32
25
  } from "@br-validators/core/natureza-juridica";
33
- import { NBS_DATA_VERSION, getNbsPorCodigo } from "@br-validators/core/nbs";
26
+ import { NBS_DATA_VERSION, lookupNbsPorCodigo } from "@br-validators/core/nbs";
34
27
  import {
35
28
  PAISES_BACEN_DATA_VERSION,
36
- getPaisPorCodigoBacen
29
+ lookupPaisPorCodigoBacen
37
30
  } from "@br-validators/core/paises-bacen";
38
31
  import {
39
32
  AEROPORTOS_DATA_VERSION,
40
- getAeroportoPorIata,
41
- getAeroportoPorIcao
33
+ lookupAeroportoPorIata,
34
+ lookupAeroportoPorIcao
42
35
  } from "@br-validators/core/aeroportos";
43
- import { PORTOS_DATA_VERSION, getPortoPorCodigo } from "@br-validators/core/portos";
36
+ import { PORTOS_DATA_VERSION, lookupPortoPorCodigo } from "@br-validators/core/portos";
44
37
  import {
45
38
  CNAES_DATA_VERSION,
46
- getCnaePorCodigo
39
+ lookupCnaePorCodigo
47
40
  } from "@br-validators/core/cnaes";
48
41
  import {
49
42
  CFOP_DATA_VERSION,
50
- getCfopPorCodigo
43
+ lookupCfopPorCodigo
51
44
  } from "@br-validators/core/cfop";
52
- import { NCM_DATA_VERSION, getNcmPorCodigo } from "@br-validators/core/ncm";
53
- import { CBO_DATA_VERSION, getCboPorCodigo } from "@br-validators/core/cbo";
45
+ import { NCM_DATA_VERSION, lookupNcmPorCodigo } from "@br-validators/core/ncm";
46
+ import { CBO_DATA_VERSION, lookupCboPorCodigo } from "@br-validators/core/cbo";
47
+ import {
48
+ lookupInvalidFormat,
49
+ lookupInvalidInput
50
+ } from "@br-validators/core/lookup";
54
51
  var REFERENCE_LOOKUP_COMMANDS = [
55
52
  "natureza-juridica",
56
53
  "nbs",
@@ -68,13 +65,16 @@ var REFERENCE_LOOKUP_COMMANDS = [
68
65
  var REFERENCE_SEARCH_COMMANDS = ["cnae", "cfop", "ncm", "cbo"];
69
66
  function lookupAeroporto(input) {
70
67
  const normalized = input.trim().toUpperCase();
68
+ if (normalized.length === 0) {
69
+ return lookupInvalidInput("Airport code is required");
70
+ }
71
71
  if (/^[A-Z0-9]{3}$/.test(normalized)) {
72
- return getAeroportoPorIata(normalized);
72
+ return lookupAeroportoPorIata(normalized);
73
73
  }
74
74
  if (/^[A-Z]{4}$/.test(normalized)) {
75
- return getAeroportoPorIcao(normalized);
75
+ return lookupAeroportoPorIcao(normalized);
76
76
  }
77
- return void 0;
77
+ return lookupInvalidFormat("Airport code must be 3-character IATA or 4-character ICAO");
78
78
  }
79
79
  var REFERENCE_LOOKUP_MODULES = {
80
80
  "natureza-juridica": {
@@ -82,7 +82,7 @@ var REFERENCE_LOOKUP_MODULES = {
82
82
  description: "RFB legal nature codes \u2014 offline lookup",
83
83
  resultKey: "naturezaJuridica",
84
84
  capturadoEm: NATUREZA_JURIDICA_DATA_VERSION.capturadoEm,
85
- lookup: (input) => getNaturezaJuridicaPorCodigo(input),
85
+ lookup: (input) => lookupNaturezaJuridicaPorCodigo(input),
86
86
  formatHuman: (result) => {
87
87
  const row = result;
88
88
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -93,7 +93,7 @@ var REFERENCE_LOOKUP_MODULES = {
93
93
  description: "NFSe NBS service codes \u2014 offline lookup",
94
94
  resultKey: "nbs",
95
95
  capturadoEm: NBS_DATA_VERSION.capturadoEm,
96
- lookup: (input) => getNbsPorCodigo(input),
96
+ lookup: (input) => lookupNbsPorCodigo(input),
97
97
  formatHuman: (result) => {
98
98
  const row = result;
99
99
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -104,7 +104,7 @@ var REFERENCE_LOOKUP_MODULES = {
104
104
  description: "CONFAZ CEST ST codes \u2014 offline lookup",
105
105
  resultKey: "cest",
106
106
  capturadoEm: CEST_DATA_VERSION.capturadoEm,
107
- lookup: (input) => getCestPorCodigo(input),
107
+ lookup: (input) => lookupCestPorCodigo(input),
108
108
  formatHuman: (result) => {
109
109
  const row = result;
110
110
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -115,7 +115,7 @@ var REFERENCE_LOOKUP_MODULES = {
115
115
  description: "IBGE CNAE 2.3 subclasses \u2014 offline lookup",
116
116
  resultKey: "cnae",
117
117
  capturadoEm: CNAES_DATA_VERSION.capturadoEm,
118
- lookup: (input) => getCnaePorCodigo(input),
118
+ lookup: (input) => lookupCnaePorCodigo(input),
119
119
  formatHuman: (result) => {
120
120
  const row = result;
121
121
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -126,7 +126,7 @@ var REFERENCE_LOOKUP_MODULES = {
126
126
  description: "CONFAZ CFOP fiscal operations \u2014 offline lookup",
127
127
  resultKey: "cfop",
128
128
  capturadoEm: CFOP_DATA_VERSION.capturadoEm,
129
- lookup: (input) => getCfopPorCodigo(input),
129
+ lookup: (input) => lookupCfopPorCodigo(input),
130
130
  formatHuman: (result) => {
131
131
  const row = result;
132
132
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -137,7 +137,7 @@ var REFERENCE_LOOKUP_MODULES = {
137
137
  description: "Siscomex NCM Mercosur codes \u2014 offline lookup",
138
138
  resultKey: "ncm",
139
139
  capturadoEm: NCM_DATA_VERSION.capturadoEm,
140
- lookup: (input) => getNcmPorCodigo(input),
140
+ lookup: (input) => lookupNcmPorCodigo(input),
141
141
  formatHuman: (result) => {
142
142
  const row = result;
143
143
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -148,7 +148,7 @@ var REFERENCE_LOOKUP_MODULES = {
148
148
  description: "MTE CBO 2002 occupations \u2014 offline lookup",
149
149
  resultKey: "cbo",
150
150
  capturadoEm: CBO_DATA_VERSION.capturadoEm,
151
- lookup: (input) => getCboPorCodigo(input),
151
+ lookup: (input) => lookupCboPorCodigo(input),
152
152
  formatHuman: (result) => {
153
153
  const row = result;
154
154
  return `${row.codigo} \u2014 ${row.descricao}`;
@@ -159,7 +159,7 @@ var REFERENCE_LOOKUP_MODULES = {
159
159
  description: "ISO 4217 + Bacen PTAX currencies \u2014 offline lookup",
160
160
  resultKey: "moeda",
161
161
  capturadoEm: MOEDAS_DATA_VERSION.capturadoEm,
162
- lookup: (input) => getMoedaPorCodigo(input),
162
+ lookup: (input) => lookupMoedaPorCodigo(input),
163
163
  formatHuman: (result) => {
164
164
  const row = result;
165
165
  const symbol = row.simbolo ?? "\u2014";
@@ -171,7 +171,7 @@ var REFERENCE_LOOKUP_MODULES = {
171
171
  description: "NF-e Bacen country codes \u2014 offline lookup",
172
172
  resultKey: "pais",
173
173
  capturadoEm: PAISES_BACEN_DATA_VERSION.capturadoEm,
174
- lookup: (input) => getPaisPorCodigoBacen(input),
174
+ lookup: (input) => lookupPaisPorCodigoBacen(input),
175
175
  formatHuman: (result) => {
176
176
  const row = result;
177
177
  return `${row.codigo} \u2014 ${row.nome}`;
@@ -182,7 +182,7 @@ var REFERENCE_LOOKUP_MODULES = {
182
182
  description: "ICC Incoterms 2020 \u2014 offline lookup",
183
183
  resultKey: "incoterm",
184
184
  capturadoEm: INCOTERMS_DATA_VERSION.capturadoEm,
185
- lookup: (input) => getIncotermPorCodigo(input),
185
+ lookup: (input) => lookupIncotermPorCodigo(input),
186
186
  formatHuman: (result) => {
187
187
  const row = result;
188
188
  return `${row.codigo} \u2014 ${row.nome} (${row.edicao})`;
@@ -193,7 +193,7 @@ var REFERENCE_LOOKUP_MODULES = {
193
193
  description: "ANTAQ port installations \u2014 offline lookup",
194
194
  resultKey: "porto",
195
195
  capturadoEm: PORTOS_DATA_VERSION.capturadoEm,
196
- lookup: (input) => getPortoPorCodigo(input),
196
+ lookup: (input) => lookupPortoPorCodigo(input),
197
197
  formatHuman: (result) => {
198
198
  const row = result;
199
199
  return `${row.codigo} \u2014 ${row.nome} (${row.uf})`;
@@ -219,15 +219,82 @@ function isReferenceSearchCommand(value) {
219
219
  return REFERENCE_SEARCH_COMMANDS.includes(value);
220
220
  }
221
221
 
222
+ // src/commands/reference-lookup/validate.ts
223
+ import { validateCfop } from "@br-validators/core/cfop";
224
+ import { validateNcm } from "@br-validators/core/ncm";
225
+ var REFERENCE_VALIDATE_COMMANDS = ["ncm", "cfop"];
226
+ var VALIDATORS = {
227
+ ncm: validateNcm,
228
+ cfop: validateCfop
229
+ };
230
+ var CAPTURED_AT = {
231
+ ncm: "ncm",
232
+ cfop: "cfop"
233
+ };
234
+ function emitFailure(result, options, io) {
235
+ if (options.json) {
236
+ io.stdout.push(JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2));
237
+ return;
238
+ }
239
+ io.stderr.push(result.message);
240
+ }
241
+ function isReferenceValidateCommand(command) {
242
+ return REFERENCE_VALIDATE_COMMANDS.includes(command);
243
+ }
244
+ function runReferenceValidateCommand(command, input, options, io = { stdout: [], stderr: [] }) {
245
+ const trimmed = input.trim();
246
+ if (trimmed.length === 0) {
247
+ io.stderr.push(`Missing code. Pass a value to validate for ${command}.`);
248
+ return EXIT.USAGE;
249
+ }
250
+ const result = VALIDATORS[command](trimmed);
251
+ if (!result.ok) {
252
+ emitFailure(result, options, io);
253
+ return EXIT.INVALID;
254
+ }
255
+ if (options.json) {
256
+ const payload = {
257
+ ok: true,
258
+ value: result.value,
259
+ description: result.description,
260
+ ...result.format !== void 0 ? { format: result.format } : {},
261
+ ...options.verbose ? { module: CAPTURED_AT[command] } : {}
262
+ };
263
+ io.stdout.push(JSON.stringify(payload, null, 2));
264
+ return EXIT.OK;
265
+ }
266
+ const lines = [`${result.value} \u2014 ${result.description}`];
267
+ if (result.format !== void 0) {
268
+ lines.push(`format: ${result.format}`);
269
+ }
270
+ io.stdout.push(lines.join("\n"));
271
+ return EXIT.OK;
272
+ }
273
+ function runReferenceValidate(command, value, options, io = { stdout: [], stderr: [] }) {
274
+ if (!isReferenceValidateCommand(command)) {
275
+ io.stderr.push(`Unknown reference validate command: ${command}`);
276
+ return EXIT.USAGE;
277
+ }
278
+ if (!value?.trim()) {
279
+ io.stderr.push(`Missing code. Usage: br-validators ${command} validate <codigo>`);
280
+ return EXIT.USAGE;
281
+ }
282
+ return runReferenceValidateCommand(command, value.trim(), options, io);
283
+ }
284
+
285
+ // src/handlers.ts
286
+ import { createRequire } from "module";
287
+
222
288
  // src/commands/bancos/list.ts
223
- import { BANCOS_DATA_VERSION as BANCOS_DATA_VERSION2, getBancos } from "@br-validators/core/bancos";
289
+ import { BANCOS_DATA_VERSION as BANCOS_DATA_VERSION2, getAllBancos } from "@br-validators/core/bancos";
224
290
 
225
291
  // src/commands/bancos/lookup.ts
226
292
  import {
227
293
  BANCOS_DATA_VERSION,
228
- getBancoPorCodigo,
229
- getBancoPorIspb
294
+ lookupBancoPorCodigo,
295
+ lookupBancoPorIspb
230
296
  } from "@br-validators/core/bancos";
297
+ import { lookupInvalidFormat as lookupInvalidFormat2 } from "@br-validators/core/lookup";
231
298
  function normalizeBancosLookupInput(raw) {
232
299
  const digits = raw.replace(/\D/g, "");
233
300
  if (digits.length === 8) {
@@ -241,33 +308,36 @@ function normalizeBancosLookupInput(raw) {
241
308
  function lookupBanco(raw) {
242
309
  const normalized = normalizeBancosLookupInput(raw);
243
310
  if (!normalized) {
244
- return void 0;
311
+ return lookupInvalidFormat2(
312
+ "Invalid bank code or ISPB. Use 3-digit COMPE (e.g. 001) or 8-digit ISPB."
313
+ );
245
314
  }
246
- return normalized.kind === "ispb" ? getBancoPorIspb(normalized.value) : getBancoPorCodigo(normalized.value);
315
+ return normalized.kind === "ispb" ? lookupBancoPorIspb(normalized.value) : lookupBancoPorCodigo(normalized.value);
247
316
  }
248
317
  function formatBancoHuman(banco) {
249
318
  return `${banco.codigo} \u2014 ${banco.nome} (ISPB ${banco.ispb})`;
250
319
  }
251
320
  function runBancosLookupCommand(input, options, io = { stdout: [], stderr: [] }) {
252
- const normalized = normalizeBancosLookupInput(input);
253
- if (!normalized) {
254
- io.stderr.push("Invalid bank code or ISPB. Use 3-digit COMPE (e.g. 001) or 8-digit ISPB.");
255
- return EXIT.USAGE;
256
- }
257
- const banco = lookupBanco(input);
258
- if (!banco) {
259
- io.stderr.push(`Bank not found: ${input}`);
260
- return EXIT.INVALID;
321
+ const result = lookupBanco(input);
322
+ if (!result.ok) {
323
+ if (options.json) {
324
+ io.stdout.push(
325
+ JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2)
326
+ );
327
+ } else {
328
+ io.stderr.push(result.message);
329
+ }
330
+ return normalizeBancosLookupInput(input) === null ? EXIT.USAGE : EXIT.INVALID;
261
331
  }
262
332
  if (options.json) {
263
- const payload = { ok: true, banco };
333
+ const payload = { ok: true, banco: result.value };
264
334
  if (options.verbose) {
265
335
  payload.capturadoEm = BANCOS_DATA_VERSION.capturadoEm;
266
336
  }
267
337
  io.stdout.push(JSON.stringify(payload, null, 2));
268
338
  return EXIT.OK;
269
339
  }
270
- io.stdout.push(formatBancoHuman(banco));
340
+ io.stdout.push(formatBancoHuman(result.value));
271
341
  if (options.verbose) {
272
342
  io.stdout.push(`capturadoEm: ${BANCOS_DATA_VERSION.capturadoEm}`);
273
343
  }
@@ -283,7 +353,7 @@ function runBancosLookup(value, options, io = { stdout: [], stderr: [] }) {
283
353
 
284
354
  // src/commands/bancos/list.ts
285
355
  function sliceBancos(limit) {
286
- const all = getBancos();
356
+ const all = getAllBancos();
287
357
  if (limit === void 0 || !Number.isFinite(limit) || limit <= 0) {
288
358
  return all;
289
359
  }
@@ -316,6 +386,15 @@ function runBancosList(options, io = { stdout: [], stderr: [] }) {
316
386
  }
317
387
 
318
388
  // src/commands/reference-lookup/lookup.ts
389
+ function emitLookupFailure(result, options, io) {
390
+ if (options.json) {
391
+ io.stdout.push(
392
+ JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2)
393
+ );
394
+ return;
395
+ }
396
+ io.stderr.push(result.message);
397
+ }
319
398
  function runReferenceLookupCommand(command, input, options, io = { stdout: [], stderr: [] }) {
320
399
  const module = REFERENCE_LOOKUP_MODULES[command];
321
400
  const trimmed = input.trim();
@@ -324,20 +403,20 @@ function runReferenceLookupCommand(command, input, options, io = { stdout: [], s
324
403
  return EXIT.USAGE;
325
404
  }
326
405
  const result = module.lookup(trimmed);
327
- if (!result) {
328
- io.stderr.push(`Not found: ${trimmed}`);
406
+ if (!result.ok) {
407
+ emitLookupFailure(result, options, io);
329
408
  return EXIT.INVALID;
330
409
  }
331
410
  if (options.json) {
332
411
  const payload = {
333
412
  ok: true,
334
- [module.resultKey]: result,
413
+ [module.resultKey]: result.value,
335
414
  ...options.verbose ? { capturadoEm: module.capturadoEm } : {}
336
415
  };
337
416
  io.stdout.push(JSON.stringify(payload, null, 2));
338
417
  return EXIT.OK;
339
418
  }
340
- io.stdout.push(module.formatHuman(result));
419
+ io.stdout.push(module.formatHuman(result.value));
341
420
  if (options.verbose) {
342
421
  io.stdout.push(`capturadoEm: ${module.capturadoEm}`);
343
422
  }
@@ -421,11 +500,176 @@ function runReferenceSearch(command, query, options, io = { stdout: [], stderr:
421
500
  return runReferenceSearchCommand(command, query.trim(), options, io);
422
501
  }
423
502
 
503
+ // src/commands/cst/index.ts
504
+ import {
505
+ CST_DATA_VERSION,
506
+ lookupCstCofinsPorCodigo,
507
+ lookupCstIcmsPorCodigo,
508
+ lookupCstIpiPorCodigo,
509
+ lookupCstPisPorCodigo,
510
+ searchCstCofins,
511
+ searchCstIcms,
512
+ searchCstIpi,
513
+ searchCstPis,
514
+ validateCst
515
+ } from "@br-validators/core/cst";
516
+ var CST_TAXES = ["icms", "ipi", "pis", "cofins"];
517
+ function parseCstTax(raw) {
518
+ if (raw === void 0) {
519
+ return null;
520
+ }
521
+ const normalized = raw.trim().toLowerCase();
522
+ if (CST_TAXES.includes(normalized)) {
523
+ return normalized;
524
+ }
525
+ return null;
526
+ }
527
+ function lookupByTax(tax, codigo) {
528
+ switch (tax) {
529
+ case "icms":
530
+ return lookupCstIcmsPorCodigo(codigo);
531
+ case "ipi":
532
+ return lookupCstIpiPorCodigo(codigo);
533
+ case "pis":
534
+ return lookupCstPisPorCodigo(codigo);
535
+ case "cofins":
536
+ return lookupCstCofinsPorCodigo(codigo);
537
+ }
538
+ }
539
+ function searchByTax(tax, query, limit) {
540
+ const options = limit !== void 0 ? { limit } : void 0;
541
+ switch (tax) {
542
+ case "icms":
543
+ return searchCstIcms(query, options);
544
+ case "ipi":
545
+ return searchCstIpi(query, options);
546
+ case "pis":
547
+ return searchCstPis(query, options);
548
+ case "cofins":
549
+ return searchCstCofins(query, options);
550
+ }
551
+ }
552
+ function emitLookupFailure2(result, options, io) {
553
+ if (options.json) {
554
+ io.stdout.push(JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2));
555
+ return;
556
+ }
557
+ io.stderr.push(result.message);
558
+ }
559
+ function emitValidateFailure(result, options, io) {
560
+ if (options.json) {
561
+ io.stdout.push(JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2));
562
+ return;
563
+ }
564
+ io.stderr.push(result.message);
565
+ }
566
+ function runCstLookup(codigo, options, io = { stdout: [], stderr: [] }) {
567
+ const tax = parseCstTax(options.tax);
568
+ if (tax === null) {
569
+ io.stderr.push("Missing or invalid --tax. Expected: icms | ipi | pis | cofins");
570
+ return EXIT.USAGE;
571
+ }
572
+ const trimmed = codigo?.trim() ?? "";
573
+ if (trimmed.length === 0) {
574
+ io.stderr.push("Missing code. Usage: br-validators cst lookup <codigo> --tax icms");
575
+ return EXIT.USAGE;
576
+ }
577
+ const result = lookupByTax(tax, trimmed);
578
+ if (!result.ok) {
579
+ emitLookupFailure2(result, options, io);
580
+ return EXIT.INVALID;
581
+ }
582
+ if (options.json) {
583
+ io.stdout.push(
584
+ JSON.stringify(
585
+ {
586
+ ok: true,
587
+ cst: result.value,
588
+ tax,
589
+ ...options.verbose ? { capturadoEm: CST_DATA_VERSION.capturadoEm } : {}
590
+ },
591
+ null,
592
+ 2
593
+ )
594
+ );
595
+ return EXIT.OK;
596
+ }
597
+ io.stdout.push(`${result.value.codigo} \u2014 ${result.value.descricao}`);
598
+ if (options.verbose) {
599
+ io.stdout.push(`tax: ${tax}`);
600
+ io.stdout.push(`capturadoEm: ${CST_DATA_VERSION.capturadoEm}`);
601
+ }
602
+ return EXIT.OK;
603
+ }
604
+ function runCstSearch(query, options, io = { stdout: [], stderr: [] }) {
605
+ const tax = parseCstTax(options.tax);
606
+ if (tax === null) {
607
+ io.stderr.push("Missing or invalid --tax. Expected: icms | ipi | pis | cofins");
608
+ return EXIT.USAGE;
609
+ }
610
+ const trimmed = query?.trim() ?? "";
611
+ if (trimmed.length === 0) {
612
+ io.stderr.push("Missing query. Usage: br-validators cst search <query> --tax icms");
613
+ return EXIT.USAGE;
614
+ }
615
+ const rows = searchByTax(tax, trimmed, options.limit);
616
+ if (options.json) {
617
+ io.stdout.push(JSON.stringify({ ok: true, tax, results: rows }, null, 2));
618
+ return EXIT.OK;
619
+ }
620
+ if (rows.length === 0) {
621
+ io.stdout.push("No matches.");
622
+ return EXIT.OK;
623
+ }
624
+ for (const row of rows) {
625
+ io.stdout.push(`${row.codigo} \u2014 ${row.descricao}`);
626
+ }
627
+ return EXIT.OK;
628
+ }
629
+ function runCstValidate(codigo, options, io = { stdout: [], stderr: [] }) {
630
+ const tax = parseCstTax(options.tax);
631
+ if (tax === null) {
632
+ io.stderr.push("Missing or invalid --tax. Expected: icms | ipi | pis | cofins");
633
+ return EXIT.USAGE;
634
+ }
635
+ const trimmed = codigo?.trim() ?? "";
636
+ if (trimmed.length === 0) {
637
+ io.stderr.push("Missing code. Usage: br-validators cst validate <codigo> --tax icms");
638
+ return EXIT.USAGE;
639
+ }
640
+ const result = validateCst(trimmed, { tax });
641
+ if (!result.ok) {
642
+ emitValidateFailure(result, options, io);
643
+ return EXIT.INVALID;
644
+ }
645
+ if (options.json) {
646
+ io.stdout.push(
647
+ JSON.stringify(
648
+ {
649
+ ok: true,
650
+ tax,
651
+ value: result.value,
652
+ description: result.description
653
+ },
654
+ null,
655
+ 2
656
+ )
657
+ );
658
+ return EXIT.OK;
659
+ }
660
+ io.stdout.push(`${result.value} \u2014 ${result.description}`);
661
+ if (options.verbose) {
662
+ io.stdout.push(`tax: ${tax}`);
663
+ }
664
+ return EXIT.OK;
665
+ }
666
+
424
667
  // src/commands/ibge/lookup.ts
425
668
  import {
426
- getMunicipioPorCodigo,
669
+ lookupMunicipioPorCodigo,
427
670
  IBGE_DATA_VERSION
428
671
  } from "@br-validators/core/ibge";
672
+ import { lookupInvalidFormat as lookupInvalidFormat3 } from "@br-validators/core/lookup";
429
673
  function normalizeIbgeMunicipioCode(raw) {
430
674
  const digits = raw.replace(/\D/g, "");
431
675
  if (digits.length !== 7) {
@@ -433,24 +677,35 @@ function normalizeIbgeMunicipioCode(raw) {
433
677
  }
434
678
  return Number(digits);
435
679
  }
680
+ function lookupMunicipio(raw) {
681
+ const codigo = normalizeIbgeMunicipioCode(raw);
682
+ if (codigo === null) {
683
+ return lookupInvalidFormat3("Invalid IBGE municipality code. Use 7 digits (e.g. 3550308).");
684
+ }
685
+ return lookupMunicipioPorCodigo(codigo);
686
+ }
436
687
  function formatMunicipioHuman(municipio) {
437
688
  return `${municipio.codigo} \u2014 ${municipio.nome} (${municipio.uf})`;
438
689
  }
439
- function runIbgeLookupCommand(input, options, io = { stdout: [], stderr: [] }) {
440
- const codigo = normalizeIbgeMunicipioCode(input);
441
- if (codigo === null) {
442
- io.stderr.push("Invalid IBGE municipality code. Use 7 digits (e.g. 3550308).");
443
- return EXIT.USAGE;
690
+ function emitLookupFailure3(result, options, io) {
691
+ if (options.json) {
692
+ io.stdout.push(
693
+ JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2)
694
+ );
695
+ return result.code === "INVALID_FORMAT" ? EXIT.USAGE : EXIT.INVALID;
444
696
  }
445
- const municipio = getMunicipioPorCodigo(codigo);
446
- if (!municipio) {
447
- io.stderr.push(`Municipality not found: ${input}`);
448
- return EXIT.INVALID;
697
+ io.stderr.push(result.message);
698
+ return result.code === "INVALID_FORMAT" ? EXIT.USAGE : EXIT.INVALID;
699
+ }
700
+ function runIbgeLookupCommand(input, options, io = { stdout: [], stderr: [] }) {
701
+ const result = lookupMunicipio(input);
702
+ if (!result.ok) {
703
+ return emitLookupFailure3(result, options, io);
449
704
  }
450
705
  if (options.json) {
451
706
  const payload = {
452
707
  ok: true,
453
- municipio
708
+ municipio: result.value
454
709
  };
455
710
  if (options.verbose) {
456
711
  payload.capturadoEm = IBGE_DATA_VERSION.capturadoEm;
@@ -458,7 +713,7 @@ function runIbgeLookupCommand(input, options, io = { stdout: [], stderr: [] }) {
458
713
  io.stdout.push(JSON.stringify(payload, null, 2));
459
714
  return EXIT.OK;
460
715
  }
461
- io.stdout.push(formatMunicipioHuman(municipio));
716
+ io.stdout.push(formatMunicipioHuman(result.value));
462
717
  if (options.verbose) {
463
718
  io.stdout.push(`capturadoEm: ${IBGE_DATA_VERSION.capturadoEm}`);
464
719
  }
@@ -474,8 +729,8 @@ function runIbgeLookup(value, options, io = { stdout: [], stderr: [] }) {
474
729
 
475
730
  // src/commands/ibge/list.ts
476
731
  import {
477
- getEstados,
478
- getMunicipios,
732
+ getAllEstados,
733
+ getAllMunicipios,
479
734
  IBGE_DATA_VERSION as IBGE_DATA_VERSION2
480
735
  } from "@br-validators/core/ibge";
481
736
  function sliceRows(rows, limit) {
@@ -488,7 +743,7 @@ function formatEstadoHuman(estado) {
488
743
  return `${estado.codigo} \u2014 ${estado.sigla} \u2014 ${estado.nome}`;
489
744
  }
490
745
  function runIbgeListEstadosCommand(options, io = { stdout: [], stderr: [] }) {
491
- const estados = sliceRows(getEstados(), options.limit);
746
+ const estados = sliceRows(getAllEstados(), options.limit);
492
747
  if (options.json) {
493
748
  const payload = {
494
749
  ok: true,
@@ -511,7 +766,7 @@ function runIbgeListEstadosCommand(options, io = { stdout: [], stderr: [] }) {
511
766
  }
512
767
  function runIbgeListMunicipiosCommand(options, io = { stdout: [], stderr: [] }) {
513
768
  const uf = options.uf?.trim().toUpperCase();
514
- const municipios = sliceRows(getMunicipios(uf ? { uf } : void 0), options.limit);
769
+ const municipios = sliceRows(getAllMunicipios(uf ? { uf } : void 0), options.limit);
515
770
  if (options.json) {
516
771
  const payload = {
517
772
  ok: true,
@@ -543,7 +798,7 @@ function runIbgeList(target, options, io = { stdout: [], stderr: [] }) {
543
798
  // src/commands/feriados/list.ts
544
799
  import {
545
800
  FERIADOS_DATA_VERSION,
546
- getFeriadosNacionais
801
+ getAllFeriados
547
802
  } from "@br-validators/core/feriados";
548
803
  function resolveYear(year) {
549
804
  if (year !== void 0 && Number.isInteger(year) && year >= 1900 && year <= 2100) {
@@ -556,7 +811,7 @@ function formatFeriadoHuman(feriado) {
556
811
  }
557
812
  function runFeriadosListCommand(options, io = { stdout: [], stderr: [] }) {
558
813
  const year = resolveYear(options.year);
559
- const feriados = getFeriadosNacionais(year);
814
+ const feriados = getAllFeriados(year);
560
815
  if (options.json) {
561
816
  const payload = {
562
817
  ok: true,
@@ -582,13 +837,193 @@ function runFeriadosList(options, io = { stdout: [], stderr: [] }) {
582
837
  return runFeriadosListCommand(options, io);
583
838
  }
584
839
 
840
+ // src/commands/inss/index.ts
841
+ import {
842
+ calcularInssMensal,
843
+ getInssTabelaContribuicao,
844
+ INSS_DATA_VERSION,
845
+ INSS_DEFAULT_ANO
846
+ } from "@br-validators/core/inss";
847
+ function resolveAno(ano) {
848
+ if (ano !== void 0 && Number.isInteger(ano) && ano >= 1900 && ano <= 2100) {
849
+ return ano;
850
+ }
851
+ return INSS_DEFAULT_ANO;
852
+ }
853
+ function formatInssFaixaHuman(faixa) {
854
+ const aliquotaPct = `${String(faixa.aliquota * 100).replace(".", ",")}%`;
855
+ return `Faixa ${String(faixa.faixa)} \u2014 ${faixa.descricao} \u2014 ${aliquotaPct}`;
856
+ }
857
+ function runInssTabelaCommand(options, io = { stdout: [], stderr: [] }) {
858
+ const ano = resolveAno(options.ano);
859
+ const tabela = getInssTabelaContribuicao(ano);
860
+ if (tabela === void 0) {
861
+ io.stderr.push(`INSS contribution table not found for year ${String(ano)}`);
862
+ return EXIT.INVALID;
863
+ }
864
+ if (options.json) {
865
+ const payload = {
866
+ ok: true,
867
+ ano,
868
+ teto: tabela.teto,
869
+ faixas: tabela.faixas
870
+ };
871
+ if (options.verbose) {
872
+ payload.capturadoEm = INSS_DATA_VERSION.capturadoEm;
873
+ }
874
+ io.stdout.push(JSON.stringify(payload, null, 2));
875
+ return EXIT.OK;
876
+ }
877
+ io.stdout.push(`Teto: R$ ${tabela.teto.toFixed(2)}`);
878
+ for (const faixa of tabela.faixas) {
879
+ io.stdout.push(formatInssFaixaHuman(faixa));
880
+ }
881
+ if (options.verbose) {
882
+ io.stdout.push(`capturadoEm: ${INSS_DATA_VERSION.capturadoEm}`);
883
+ }
884
+ return EXIT.OK;
885
+ }
886
+ function runInssCalcCommand(salarioRaw, options, io = { stdout: [], stderr: [] }) {
887
+ const trimmed = salarioRaw.trim().replace(",", ".");
888
+ const salarioContribuicao = Number(trimmed);
889
+ if (!Number.isFinite(salarioContribuicao)) {
890
+ io.stderr.push("Invalid sal\xE1rio de contribui\xE7\xE3o. Pass a numeric value (e.g. 3000).");
891
+ return EXIT.USAGE;
892
+ }
893
+ const ano = resolveAno(options.ano);
894
+ const result = calcularInssMensal(salarioContribuicao, ano);
895
+ if (result === void 0) {
896
+ if (getInssTabelaContribuicao(ano) === void 0) {
897
+ io.stderr.push(`INSS contribution table not found for year ${String(ano)}`);
898
+ return EXIT.INVALID;
899
+ }
900
+ io.stderr.push("Sal\xE1rio de contribui\xE7\xE3o must be a non-negative number");
901
+ return EXIT.INVALID;
902
+ }
903
+ if (options.json) {
904
+ const payload = {
905
+ ok: true,
906
+ ...result,
907
+ ...options.verbose ? { capturadoEm: INSS_DATA_VERSION.capturadoEm } : {}
908
+ };
909
+ io.stdout.push(JSON.stringify(payload, null, 2));
910
+ return EXIT.OK;
911
+ }
912
+ io.stdout.push(
913
+ `INSS ${String(result.ano)} \u2014 sal\xE1rio R$ ${result.salarioContribuicao.toFixed(2)} \u2014 faixa ${String(result.faixa)} \u2014 contribui\xE7\xE3o R$ ${result.contribuicao.toFixed(2)}`
914
+ );
915
+ if (options.verbose) {
916
+ io.stdout.push(`capturadoEm: ${INSS_DATA_VERSION.capturadoEm}`);
917
+ }
918
+ return EXIT.OK;
919
+ }
920
+ function runInssTabela(options, io = { stdout: [], stderr: [] }) {
921
+ return runInssTabelaCommand(options, io);
922
+ }
923
+ function runInssCalc(salario, options, io = { stdout: [], stderr: [] }) {
924
+ if (!salario?.trim()) {
925
+ io.stderr.push("Missing sal\xE1rio de contribui\xE7\xE3o. Usage: br-validators inss calc <salario>");
926
+ return EXIT.USAGE;
927
+ }
928
+ return runInssCalcCommand(salario.trim(), options, io);
929
+ }
930
+
931
+ // src/commands/irpf/index.ts
932
+ import {
933
+ calcularIrpfMensal,
934
+ getIrpfTabelaProgressiva,
935
+ IRPF_DATA_VERSION,
936
+ IRPF_DEFAULT_ANO
937
+ } from "@br-validators/core/irpf";
938
+ function resolveAno2(ano) {
939
+ if (ano !== void 0 && Number.isInteger(ano) && ano >= 1900 && ano <= 2100) {
940
+ return ano;
941
+ }
942
+ return IRPF_DEFAULT_ANO;
943
+ }
944
+ function formatIrpfFaixaHuman(faixa) {
945
+ const aliquotaPct = `${String(faixa.aliquota * 100).replace(".", ",")}%`;
946
+ return `Faixa ${String(faixa.faixa)} \u2014 ${faixa.descricao} \u2014 ${aliquotaPct} \u2014 deduzir R$ ${faixa.parcelaDeduzir.toFixed(2)}`;
947
+ }
948
+ function runIrpfTabelaCommand(options, io = { stdout: [], stderr: [] }) {
949
+ const ano = resolveAno2(options.ano);
950
+ const faixas = getIrpfTabelaProgressiva(ano);
951
+ if (faixas === void 0) {
952
+ io.stderr.push(`IRPF progressive table not found for year ${String(ano)}`);
953
+ return EXIT.INVALID;
954
+ }
955
+ if (options.json) {
956
+ const payload = {
957
+ ok: true,
958
+ ano,
959
+ faixas
960
+ };
961
+ if (options.verbose) {
962
+ payload.capturadoEm = IRPF_DATA_VERSION.capturadoEm;
963
+ }
964
+ io.stdout.push(JSON.stringify(payload, null, 2));
965
+ return EXIT.OK;
966
+ }
967
+ for (const faixa of faixas) {
968
+ io.stdout.push(formatIrpfFaixaHuman(faixa));
969
+ }
970
+ if (options.verbose) {
971
+ io.stdout.push(`capturadoEm: ${IRPF_DATA_VERSION.capturadoEm}`);
972
+ }
973
+ return EXIT.OK;
974
+ }
975
+ function runIrpfCalcCommand(baseRaw, options, io = { stdout: [], stderr: [] }) {
976
+ const trimmed = baseRaw.trim().replace(",", ".");
977
+ const baseCalculo = Number(trimmed);
978
+ if (!Number.isFinite(baseCalculo)) {
979
+ io.stderr.push("Invalid base de c\xE1lculo. Pass a numeric value (e.g. 3000).");
980
+ return EXIT.USAGE;
981
+ }
982
+ const ano = resolveAno2(options.ano);
983
+ const result = calcularIrpfMensal(baseCalculo, ano);
984
+ if (result === void 0) {
985
+ if (getIrpfTabelaProgressiva(ano) === void 0) {
986
+ io.stderr.push(`IRPF progressive table not found for year ${String(ano)}`);
987
+ return EXIT.INVALID;
988
+ }
989
+ io.stderr.push("Base de c\xE1lculo must be a non-negative number");
990
+ return EXIT.INVALID;
991
+ }
992
+ if (options.json) {
993
+ const payload = {
994
+ ok: true,
995
+ ...result,
996
+ ...options.verbose ? { capturadoEm: IRPF_DATA_VERSION.capturadoEm } : {}
997
+ };
998
+ io.stdout.push(JSON.stringify(payload, null, 2));
999
+ return EXIT.OK;
1000
+ }
1001
+ io.stdout.push(
1002
+ `IRPF ${String(result.ano)} \u2014 base R$ ${result.baseCalculo.toFixed(2)} \u2014 faixa ${String(result.faixa)} \u2014 imposto R$ ${result.imposto.toFixed(2)}`
1003
+ );
1004
+ if (options.verbose) {
1005
+ io.stdout.push(`capturadoEm: ${IRPF_DATA_VERSION.capturadoEm}`);
1006
+ }
1007
+ return EXIT.OK;
1008
+ }
1009
+ function runIrpfTabela(options, io = { stdout: [], stderr: [] }) {
1010
+ return runIrpfTabelaCommand(options, io);
1011
+ }
1012
+ function runIrpfCalc(base, options, io = { stdout: [], stderr: [] }) {
1013
+ if (!base?.trim()) {
1014
+ io.stderr.push("Missing base de c\xE1lculo. Usage: br-validators irpf calc <base>");
1015
+ return EXIT.USAGE;
1016
+ }
1017
+ return runIrpfCalcCommand(base.trim(), options, io);
1018
+ }
1019
+
585
1020
  // src/commands/tse-municipios/lookup.ts
586
1021
  import {
587
1022
  getCodigosTsePorMunicipio,
588
1023
  getMunicipioIbgePorCodigoTse,
589
1024
  TSE_MUNICIPIOS_DATA_VERSION
590
1025
  } from "@br-validators/core/tse-municipios";
591
- import { getMunicipioPorCodigo as getMunicipioPorCodigo2 } from "@br-validators/core/ibge";
1026
+ import { getMunicipioPorCodigo } from "@br-validators/core/ibge";
592
1027
  function normalizeTseInput(raw) {
593
1028
  const digits = raw.replace(/\D/g, "");
594
1029
  if (digits.length === 5) {
@@ -619,11 +1054,11 @@ function lookupTseMunicipio(raw) {
619
1054
  }
620
1055
  function formatTseLookupHuman(result) {
621
1056
  if (result.kind === "tse-to-ibge") {
622
- const municipio2 = getMunicipioPorCodigo2(result.ibgeCodigo);
1057
+ const municipio2 = getMunicipioPorCodigo(result.ibgeCodigo);
623
1058
  const name2 = municipio2 ? `${municipio2.nome} (${municipio2.uf})` : String(result.ibgeCodigo);
624
1059
  return `TSE ${result.codigoTse} \u2192 IBGE ${result.ibgeCodigo} \u2014 ${name2}`;
625
1060
  }
626
- const municipio = getMunicipioPorCodigo2(result.ibgeCodigo);
1061
+ const municipio = getMunicipioPorCodigo(result.ibgeCodigo);
627
1062
  const name = municipio ? `${municipio.nome} (${municipio.uf})` : String(result.ibgeCodigo);
628
1063
  return `IBGE ${result.ibgeCodigo} \u2014 ${name} \u2192 TSE ${result.codigosTse.join(", ")}`;
629
1064
  }
@@ -767,6 +1202,228 @@ function runDddLookup(value, options, io = { stdout: [], stderr: [] }) {
767
1202
  return runDddLookupCommand(value.trim(), options, io);
768
1203
  }
769
1204
 
1205
+ // src/commands/nfe-cuf/lookup.ts
1206
+ import {
1207
+ lookupCufPorCodigo,
1208
+ NFE_CUF_DATA_VERSION
1209
+ } from "@br-validators/core/nfe-cuf";
1210
+ function formatNfeCufHuman(row) {
1211
+ return `cUF ${row.codigo} \u2014 ${row.uf} \u2014 ${row.nome} (IBGE UF ${row.codigoIbge})`;
1212
+ }
1213
+ function runNfeCufLookupCommand(input, options, io = { stdout: [], stderr: [] }) {
1214
+ const trimmed = input.trim();
1215
+ if (trimmed.length === 0) {
1216
+ io.stderr.push("Invalid cUF code. Use 2 digits (e.g. 35).");
1217
+ return EXIT.USAGE;
1218
+ }
1219
+ const result = lookupCufPorCodigo(trimmed);
1220
+ if (!result.ok) {
1221
+ if (options.json) {
1222
+ io.stdout.push(JSON.stringify({ ok: false, code: result.code, message: result.message }, null, 2));
1223
+ return EXIT.INVALID;
1224
+ }
1225
+ io.stderr.push(result.message);
1226
+ return EXIT.INVALID;
1227
+ }
1228
+ if (options.json) {
1229
+ const payload = {
1230
+ ok: true,
1231
+ cuf: result.value
1232
+ };
1233
+ if (options.verbose) {
1234
+ payload.capturadoEm = NFE_CUF_DATA_VERSION.capturadoEm;
1235
+ }
1236
+ io.stdout.push(JSON.stringify(payload, null, 2));
1237
+ return EXIT.OK;
1238
+ }
1239
+ io.stdout.push(formatNfeCufHuman(result.value));
1240
+ if (options.verbose) {
1241
+ io.stdout.push(`capturadoEm: ${NFE_CUF_DATA_VERSION.capturadoEm}`);
1242
+ }
1243
+ return EXIT.OK;
1244
+ }
1245
+ function runNfeCufLookup(value, options, io = { stdout: [], stderr: [] }) {
1246
+ if (!value?.trim()) {
1247
+ io.stderr.push("Missing cUF code. Usage: br-validators nfe-cuf lookup <code>");
1248
+ return EXIT.USAGE;
1249
+ }
1250
+ return runNfeCufLookupCommand(value.trim(), options, io);
1251
+ }
1252
+
1253
+ // src/commands/selic/index.ts
1254
+ import {
1255
+ getSelicMeta,
1256
+ getSelicMetaPorData,
1257
+ SELIC_DATA_VERSION
1258
+ } from "@br-validators/core/selic";
1259
+ function formatSelicMetaHuman(meta) {
1260
+ return `SELIC meta ${meta.dataReferencia} \u2014 ${String(meta.valor)}% a.a.`;
1261
+ }
1262
+ function runSelicCommand(options, io = { stdout: [], stderr: [] }) {
1263
+ const meta = options.date === void 0 || options.date.trim().length === 0 ? getSelicMeta() : getSelicMetaPorData(options.date.trim());
1264
+ if (meta === void 0) {
1265
+ io.stderr.push(
1266
+ options.date ? `SELIC meta not found for date ${options.date}` : "SELIC meta series is empty"
1267
+ );
1268
+ return EXIT.INVALID;
1269
+ }
1270
+ if (options.json) {
1271
+ const payload = {
1272
+ ok: true,
1273
+ meta
1274
+ };
1275
+ if (options.verbose) {
1276
+ payload.capturadoEm = SELIC_DATA_VERSION.capturadoEm;
1277
+ }
1278
+ io.stdout.push(JSON.stringify(payload, null, 2));
1279
+ return EXIT.OK;
1280
+ }
1281
+ io.stdout.push(formatSelicMetaHuman(meta));
1282
+ if (options.verbose) {
1283
+ io.stdout.push(`dataReferencia: ${meta.dataReferencia}`);
1284
+ io.stdout.push(`isStale: ${String(meta.isStale)}`);
1285
+ if (meta.warning !== void 0) {
1286
+ io.stdout.push(`warning: ${meta.warning}`);
1287
+ }
1288
+ io.stdout.push(`capturadoEm: ${SELIC_DATA_VERSION.capturadoEm}`);
1289
+ }
1290
+ return EXIT.OK;
1291
+ }
1292
+
1293
+ // src/commands/iss-municipal/index.ts
1294
+ import {
1295
+ getIssMunicipalPorIbge,
1296
+ getIssMunicipalPorUfMunicipio,
1297
+ ISS_MUNICIPAL_DATA_VERSION,
1298
+ ISS_MUNICIPAL_ESTIMATION_WARNING,
1299
+ searchIssMunicipal
1300
+ } from "@br-validators/core/iss-municipal";
1301
+ function formatIssMunicipalHuman(row) {
1302
+ return `${row.nome}/${row.uf} \u2014 ISS ${String(row.aliquotaMin)}%\u2013${String(row.aliquotaMax)}%`;
1303
+ }
1304
+ function emitDisclaimer(options, io) {
1305
+ if (options.json) {
1306
+ return;
1307
+ }
1308
+ io.stderr.push(ISS_MUNICIPAL_ESTIMATION_WARNING);
1309
+ }
1310
+ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] }) {
1311
+ const trimmed = codigo?.trim() ?? "";
1312
+ if (trimmed.length === 0) {
1313
+ io.stderr.push("Missing IBGE code. Usage: br-validators iss-municipal lookup <codigoIbge>");
1314
+ return EXIT.USAGE;
1315
+ }
1316
+ const result = getIssMunicipalPorIbge(trimmed);
1317
+ if (result === void 0) {
1318
+ io.stderr.push(`ISS municipal row not found for IBGE code ${trimmed}`);
1319
+ return EXIT.INVALID;
1320
+ }
1321
+ emitDisclaimer(options, io);
1322
+ if (options.json) {
1323
+ const payload = {
1324
+ ok: true,
1325
+ iss: result
1326
+ };
1327
+ if (options.verbose) {
1328
+ payload.capturadoEm = ISS_MUNICIPAL_DATA_VERSION.capturadoEm;
1329
+ }
1330
+ io.stdout.push(JSON.stringify(payload, null, 2));
1331
+ return EXIT.OK;
1332
+ }
1333
+ io.stdout.push(formatIssMunicipalHuman(result));
1334
+ io.stdout.push(`warning: ${result.warning}`);
1335
+ if (options.verbose) {
1336
+ io.stdout.push(`leiUrl: ${result.leiUrl}`);
1337
+ io.stdout.push(`estimativa: ${String(result.estimativa)}`);
1338
+ io.stdout.push(`capturadoEm: ${ISS_MUNICIPAL_DATA_VERSION.capturadoEm}`);
1339
+ }
1340
+ return EXIT.OK;
1341
+ }
1342
+ function runIssMunicipalSearch(query, options, io = { stdout: [], stderr: [] }) {
1343
+ const trimmed = query?.trim() ?? "";
1344
+ if (trimmed.length === 0) {
1345
+ io.stderr.push("Missing query. Usage: br-validators iss-municipal search <query>");
1346
+ return EXIT.USAGE;
1347
+ }
1348
+ const rows = searchIssMunicipal(trimmed, { limit: options.limit });
1349
+ emitDisclaimer(options, io);
1350
+ if (options.json) {
1351
+ io.stdout.push(JSON.stringify({ ok: true, results: rows }, null, 2));
1352
+ return EXIT.OK;
1353
+ }
1354
+ if (rows.length === 0) {
1355
+ io.stdout.push("No ISS municipal rows matched.");
1356
+ return EXIT.OK;
1357
+ }
1358
+ for (const row of rows) {
1359
+ io.stdout.push(formatIssMunicipalHuman(row));
1360
+ }
1361
+ return EXIT.OK;
1362
+ }
1363
+ function runIssMunicipalResolve(uf, nome, options, io = { stdout: [], stderr: [] }) {
1364
+ const normalizedUf = uf?.trim() ?? "";
1365
+ const normalizedNome = nome?.trim() ?? "";
1366
+ if (normalizedUf.length === 0 || normalizedNome.length === 0) {
1367
+ io.stderr.push("Missing UF or municipality name. Usage: br-validators iss-municipal resolve <uf> <nome>");
1368
+ return EXIT.USAGE;
1369
+ }
1370
+ const result = getIssMunicipalPorUfMunicipio(normalizedUf, normalizedNome);
1371
+ if (result === void 0) {
1372
+ io.stderr.push(`ISS municipal row not found for ${normalizedNome}/${normalizedUf}`);
1373
+ return EXIT.INVALID;
1374
+ }
1375
+ return runIssMunicipalLookup(String(result.codigoIbge), options, io);
1376
+ }
1377
+
1378
+ // src/commands/ptax/lookup.ts
1379
+ import {
1380
+ getPtaxCotacao,
1381
+ PTAX_DATA_VERSION
1382
+ } from "@br-validators/core/ptax";
1383
+ function formatPtaxCotacaoHuman(cotacao) {
1384
+ return `${cotacao.moeda} Fechamento PTAX \u2014 compra ${String(cotacao.cotacaoCompra)} / venda ${String(cotacao.cotacaoVenda)} (${cotacao.dataReferencia})`;
1385
+ }
1386
+ function runPtaxLookupCommand(moeda, data, options, io = { stdout: [], stderr: [] }) {
1387
+ const trimmedMoeda = moeda.trim();
1388
+ if (trimmedMoeda.length === 0) {
1389
+ io.stderr.push("Missing currency code. Pass a 3-letter ISO code (e.g. USD).");
1390
+ return EXIT.USAGE;
1391
+ }
1392
+ const cotacao = data === void 0 || data.trim().length === 0 ? getPtaxCotacao(trimmedMoeda) : getPtaxCotacao(trimmedMoeda, data.trim());
1393
+ if (cotacao === void 0) {
1394
+ io.stderr.push(`PTAX quote not found: ${trimmedMoeda}${data ? ` ${data}` : ""}`);
1395
+ return EXIT.INVALID;
1396
+ }
1397
+ if (options.json) {
1398
+ const payload = {
1399
+ ok: true,
1400
+ cotacao
1401
+ };
1402
+ if (options.verbose) {
1403
+ payload.capturadoEm = PTAX_DATA_VERSION.capturadoEm;
1404
+ }
1405
+ io.stdout.push(JSON.stringify(payload, null, 2));
1406
+ return EXIT.OK;
1407
+ }
1408
+ io.stdout.push(formatPtaxCotacaoHuman(cotacao));
1409
+ if (options.verbose) {
1410
+ io.stdout.push(`dataReferencia: ${cotacao.dataReferencia}`);
1411
+ io.stdout.push(`isStale: ${String(cotacao.isStale)}`);
1412
+ if (cotacao.warning !== void 0) {
1413
+ io.stdout.push(`warning: ${cotacao.warning}`);
1414
+ }
1415
+ io.stdout.push(`capturadoEm: ${PTAX_DATA_VERSION.capturadoEm}`);
1416
+ }
1417
+ return EXIT.OK;
1418
+ }
1419
+ function runPtaxLookup(moeda, data, options, io = { stdout: [], stderr: [] }) {
1420
+ if (!moeda?.trim()) {
1421
+ io.stderr.push("Missing currency code. Usage: ptax lookup <moeda> [data]");
1422
+ return EXIT.USAGE;
1423
+ }
1424
+ return runPtaxLookupCommand(moeda.trim(), data?.trim(), options, io);
1425
+ }
1426
+
770
1427
  // src/commands/brcode.ts
771
1428
  import {
772
1429
  BRCODE_OFFICIAL_SOURCE_URL,
@@ -2204,26 +2861,115 @@ function printDetect(result, options, io = { stdout: [], stderr: [] }) {
2204
2861
  }
2205
2862
  return EXIT.OK;
2206
2863
  }
2207
- io.stderr.push(`type: ${result.type}`);
2208
- io.stderr.push("valid: no");
2209
- io.stderr.push(`code: ${result.code}`);
2210
- io.stderr.push(`message: ${result.message}`);
2211
- return EXIT.INVALID;
2864
+ io.stderr.push(`type: ${result.type}`);
2865
+ io.stderr.push("valid: no");
2866
+ io.stderr.push(`code: ${result.code}`);
2867
+ io.stderr.push(`message: ${result.message}`);
2868
+ return EXIT.INVALID;
2869
+ }
2870
+ function runDetect(value, options, io = { stdout: [], stderr: [] }) {
2871
+ const input = resolveInput20(value, options.file);
2872
+ if (input === null) {
2873
+ io.stderr.push("Missing value. Pass an argument or use --file.");
2874
+ return EXIT.USAGE;
2875
+ }
2876
+ const uf = options.uf?.toUpperCase();
2877
+ const result = detect(input, uf ? { uf } : {});
2878
+ return printDetect(result, options, io);
2879
+ }
2880
+
2881
+ // src/commands/sanitize.ts
2882
+ import { sanitize } from "@br-validators/core";
2883
+ var SANITIZABLE_TYPES = [
2884
+ "cpf",
2885
+ "cnpj",
2886
+ "cep",
2887
+ "placa",
2888
+ "pis-pasep",
2889
+ "telefone",
2890
+ "cnh",
2891
+ "renavam",
2892
+ "titulo-eleitor",
2893
+ "nfe-chave",
2894
+ "boleto",
2895
+ "cartao-credito",
2896
+ "ean",
2897
+ "inscricao-estadual",
2898
+ "inscricao-estadual-produtor-rural"
2899
+ ];
2900
+ function isSanitizableType(type) {
2901
+ return SANITIZABLE_TYPES.includes(type);
2902
+ }
2903
+ function resolveInput21(value, fileContent) {
2904
+ const input = value ?? fileContent?.trim();
2905
+ if (!input) {
2906
+ return null;
2907
+ }
2908
+ return input;
2909
+ }
2910
+ function printSanitize(result, options, io = { stdout: [], stderr: [] }) {
2911
+ if (options.json) {
2912
+ io.stdout.push(JSON.stringify(result, null, 2));
2913
+ return result.ok ? EXIT.OK : EXIT.INVALID;
2914
+ }
2915
+ if (options.quiet) {
2916
+ return result.ok ? EXIT.OK : EXIT.INVALID;
2917
+ }
2918
+ if (result.ok) {
2919
+ io.stdout.push("valid: yes");
2920
+ io.stdout.push(`value: ${result.value}`);
2921
+ io.stdout.push(`fixes: ${result.fixes.join(", ")}`);
2922
+ return EXIT.OK;
2923
+ }
2924
+ io.stderr.push("valid: no");
2925
+ io.stderr.push(`code: ${result.code}`);
2926
+ io.stderr.push(`message: ${result.message}`);
2927
+ return EXIT.INVALID;
2928
+ }
2929
+ function runSanitize(type, value, options, io = { stdout: [], stderr: [] }) {
2930
+ if (!isSanitizableType(type)) {
2931
+ io.stderr.push(`Unsupported sanitize type: ${type}`);
2932
+ return EXIT.USAGE;
2933
+ }
2934
+ const input = resolveInput21(value, options.file);
2935
+ if (input === null) {
2936
+ io.stderr.push("Missing value. Pass an argument or use --file.");
2937
+ return EXIT.USAGE;
2938
+ }
2939
+ const uf = options.uf?.toUpperCase();
2940
+ const result = sanitize(input, type, uf ? { uf } : {});
2941
+ return printSanitize(result, options, io);
2942
+ }
2943
+
2944
+ // src/commands/mask.ts
2945
+ import { isMaskableDocumentType, maskRuntime } from "@br-validators/core";
2946
+ function resolveInput22(value, fileContent) {
2947
+ const input = value ?? fileContent?.trim();
2948
+ if (!input) {
2949
+ return null;
2950
+ }
2951
+ return input;
2212
2952
  }
2213
- function runDetect(value, options, io = { stdout: [], stderr: [] }) {
2214
- const input = resolveInput20(value, options.file);
2953
+ function runMask(type, value, options, io = { stdout: [], stderr: [] }) {
2954
+ if (!isMaskableDocumentType(type)) {
2955
+ io.stderr.push(`Unsupported mask type: ${type}`);
2956
+ return EXIT.USAGE;
2957
+ }
2958
+ const input = resolveInput22(value, options.file);
2215
2959
  if (input === null) {
2216
2960
  io.stderr.push("Missing value. Pass an argument or use --file.");
2217
2961
  return EXIT.USAGE;
2218
2962
  }
2219
2963
  const uf = options.uf?.toUpperCase();
2220
- const result = detect(input, uf ? { uf } : {});
2221
- return printDetect(result, options, io);
2964
+ const result = maskRuntime(type, input, uf ? { uf } : {});
2965
+ return printFormat(result, options, io);
2222
2966
  }
2223
2967
 
2224
- // src/commands/sanitize.ts
2225
- import { sanitize } from "@br-validators/core";
2226
- var SANITIZABLE_TYPES = [
2968
+ // src/commands/compare.ts
2969
+ import { compareRuntime } from "@br-validators/core";
2970
+
2971
+ // src/commands/platform-document-types.ts
2972
+ var PLATFORM_DOCUMENT_TYPES = [
2227
2973
  "cpf",
2228
2974
  "cnpj",
2229
2975
  "cep",
@@ -2233,55 +2979,144 @@ var SANITIZABLE_TYPES = [
2233
2979
  "cnh",
2234
2980
  "renavam",
2235
2981
  "titulo-eleitor",
2982
+ "processo-judicial",
2983
+ "rg",
2236
2984
  "nfe-chave",
2237
2985
  "boleto",
2238
2986
  "cartao-credito",
2239
2987
  "ean",
2240
2988
  "inscricao-estadual",
2241
- "inscricao-estadual-produtor-rural"
2989
+ "inscricao-estadual-produtor-rural",
2990
+ "pix",
2991
+ "brcode"
2242
2992
  ];
2243
- function isSanitizableType(type) {
2244
- return SANITIZABLE_TYPES.includes(type);
2993
+ function isPlatformDocumentType(type) {
2994
+ return PLATFORM_DOCUMENT_TYPES.includes(type);
2245
2995
  }
2246
- function resolveInput21(value, fileContent) {
2247
- const input = value ?? fileContent?.trim();
2248
- if (!input) {
2996
+
2997
+ // src/commands/compare.ts
2998
+ function printCompare(result, options, io = { stdout: [], stderr: [] }) {
2999
+ if (options.json) {
3000
+ io.stdout.push(JSON.stringify(result, null, 2));
3001
+ if ("code" in result) {
3002
+ return EXIT.USAGE;
3003
+ }
3004
+ return result.equal ? EXIT.OK : EXIT.INVALID;
3005
+ }
3006
+ if (options.quiet) {
3007
+ if ("code" in result) {
3008
+ return EXIT.USAGE;
3009
+ }
3010
+ return result.equal ? EXIT.OK : EXIT.INVALID;
3011
+ }
3012
+ if ("code" in result) {
3013
+ io.stderr.push(`code: ${result.code}`);
3014
+ io.stderr.push(`message: ${result.message}`);
3015
+ return EXIT.USAGE;
3016
+ }
3017
+ io.stdout.push(`equal: ${result.equal ? "yes" : "no"}`);
3018
+ return result.equal ? EXIT.OK : EXIT.INVALID;
3019
+ }
3020
+ function runCompare(type, valueA, valueB, options, io = { stdout: [], stderr: [] }) {
3021
+ if (!isPlatformDocumentType(type)) {
3022
+ io.stderr.push(`Unsupported compare type: ${type}`);
3023
+ return EXIT.USAGE;
3024
+ }
3025
+ if (!valueA || !valueB) {
3026
+ io.stderr.push("Missing values. Usage: compare <type> <valueA> <valueB>");
3027
+ return EXIT.USAGE;
3028
+ }
3029
+ const uf = options.uf?.toUpperCase();
3030
+ const platformOptions = uf ? { uf } : {};
3031
+ const result = compareRuntime(valueA, valueB, type, platformOptions);
3032
+ return printCompare(result, options, io);
3033
+ }
3034
+
3035
+ // src/commands/batch.ts
3036
+ import { batch } from "@br-validators/core";
3037
+ function parseBatchLines(raw) {
3038
+ return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
3039
+ }
3040
+ function resolveBatchInputs(options) {
3041
+ if (options.lines === void 0) {
2249
3042
  return null;
2250
3043
  }
2251
- return input;
3044
+ const parsed = parseBatchLines(options.lines);
3045
+ if (options.limit !== void 0 && options.limit > 0) {
3046
+ return parsed.slice(0, options.limit);
3047
+ }
3048
+ return parsed;
2252
3049
  }
2253
- function printSanitize(result, options, io = { stdout: [], stderr: [] }) {
3050
+ function printBatch(result, options, io = { stdout: [], stderr: [] }) {
2254
3051
  if (options.json) {
2255
3052
  io.stdout.push(JSON.stringify(result, null, 2));
2256
- return result.ok ? EXIT.OK : EXIT.INVALID;
3053
+ return result.summary.invalid === 0 ? EXIT.OK : EXIT.INVALID;
2257
3054
  }
2258
3055
  if (options.quiet) {
2259
- return result.ok ? EXIT.OK : EXIT.INVALID;
3056
+ return result.summary.invalid === 0 ? EXIT.OK : EXIT.INVALID;
2260
3057
  }
2261
- if (result.ok) {
2262
- io.stdout.push("valid: yes");
2263
- io.stdout.push(`value: ${result.value}`);
2264
- io.stdout.push(`fixes: ${result.fixes.join(", ")}`);
2265
- return EXIT.OK;
3058
+ io.stdout.push(`total: ${String(result.summary.total)}`);
3059
+ io.stdout.push(`valid: ${String(result.summary.valid)}`);
3060
+ io.stdout.push(`invalid: ${String(result.summary.invalid)}`);
3061
+ for (const entry of result.valid) {
3062
+ io.stdout.push(`ok[${String(entry.index)}]: ${entry.value}`);
2266
3063
  }
2267
- io.stderr.push("valid: no");
2268
- io.stderr.push(`code: ${result.code}`);
2269
- io.stderr.push(`message: ${result.message}`);
2270
- return EXIT.INVALID;
3064
+ for (const entry of result.invalid) {
3065
+ io.stderr.push(`fail[${String(entry.index)}]: ${entry.code} \u2014 ${entry.message}`);
3066
+ }
3067
+ return result.summary.invalid === 0 ? EXIT.OK : EXIT.INVALID;
2271
3068
  }
2272
- function runSanitize(type, value, options, io = { stdout: [], stderr: [] }) {
2273
- if (!isSanitizableType(type)) {
2274
- io.stderr.push(`Unsupported sanitize type: ${type}`);
3069
+ function runBatch(type, options, io = { stdout: [], stderr: [] }) {
3070
+ if (!isPlatformDocumentType(type)) {
3071
+ io.stderr.push(`Unsupported batch type: ${type}`);
2275
3072
  return EXIT.USAGE;
2276
3073
  }
2277
- const input = resolveInput21(value, options.file);
2278
- if (input === null) {
2279
- io.stderr.push("Missing value. Pass an argument or use --file.");
3074
+ const inputs = resolveBatchInputs(options);
3075
+ if (inputs === null) {
3076
+ io.stderr.push("Missing input. Pass --file <path> or pipe one value per line on stdin.");
3077
+ return EXIT.USAGE;
3078
+ }
3079
+ if (inputs.length === 0) {
3080
+ io.stderr.push("No values to validate.");
2280
3081
  return EXIT.USAGE;
2281
3082
  }
2282
3083
  const uf = options.uf?.toUpperCase();
2283
- const result = sanitize(input, type, uf ? { uf } : {});
2284
- return printSanitize(result, options, io);
3084
+ const platformOptions = uf ? { uf } : {};
3085
+ const result = batch(inputs, type, platformOptions);
3086
+ return printBatch(result, options, io);
3087
+ }
3088
+
3089
+ // src/commands/diff.ts
3090
+ import { diff } from "@br-validators/core";
3091
+ function printDiff(result, options, io = { stdout: [], stderr: [] }) {
3092
+ if (options.json) {
3093
+ io.stdout.push(JSON.stringify(result, null, 2));
3094
+ return result.changed ? EXIT.INVALID : EXIT.OK;
3095
+ }
3096
+ if (options.quiet) {
3097
+ return result.changed ? EXIT.INVALID : EXIT.OK;
3098
+ }
3099
+ io.stdout.push(`changed: ${result.changed ? "yes" : "no"}`);
3100
+ for (const field of result.fields) {
3101
+ io.stdout.push(`field: ${field.field}`);
3102
+ io.stdout.push(` a: ${field.a}`);
3103
+ io.stdout.push(` b: ${field.b}`);
3104
+ }
3105
+ return result.changed ? EXIT.INVALID : EXIT.OK;
3106
+ }
3107
+ function runDiff(type, valueA, valueB, options, io = { stdout: [], stderr: [] }) {
3108
+ if (!isPlatformDocumentType(type)) {
3109
+ io.stderr.push(`Unsupported diff type: ${type}`);
3110
+ return EXIT.USAGE;
3111
+ }
3112
+ if (!valueA || !valueB) {
3113
+ io.stderr.push("Missing values. Usage: diff <type> <valueA> <valueB>");
3114
+ return EXIT.USAGE;
3115
+ }
3116
+ const uf = options.uf?.toUpperCase();
3117
+ const platformOptions = uf ? { uf } : {};
3118
+ const result = diff(valueA, valueB, type, platformOptions);
3119
+ return printDiff(result, options, io);
2285
3120
  }
2286
3121
 
2287
3122
  // src/commands/generate.ts
@@ -2313,6 +3148,9 @@ function buildGenerateOptions(options) {
2313
3148
  if (options.masked) {
2314
3149
  core.masked = true;
2315
3150
  }
3151
+ if (options.stripped) {
3152
+ core.stripped = true;
3153
+ }
2316
3154
  if (options.seed !== void 0) {
2317
3155
  core.seed = options.seed;
2318
3156
  }
@@ -2356,10 +3194,14 @@ function listSupportedTypes(io = { stdout: [] }) {
2356
3194
  }
2357
3195
 
2358
3196
  // src/handlers.ts
3197
+ var nodeRequire = createRequire(import.meta.url);
3198
+ function readNodeFileSync(path, encoding) {
3199
+ const fs = nodeRequire("node:fs");
3200
+ return fs.readFileSync(path, encoding);
3201
+ }
2359
3202
  function readInputFile(path, io) {
2360
3203
  try {
2361
- const fsModule = __require("fs");
2362
- return fsModule.readFileSync(path, "utf8");
3204
+ return readNodeFileSync(path, "utf8");
2363
3205
  } catch {
2364
3206
  io.stderr.push(`Cannot read file: ${path}`);
2365
3207
  return null;
@@ -2836,6 +3678,90 @@ function handleSanitizeCli(type, value, opts, io = { stdout: [], stderr: [] }) {
2836
3678
  io
2837
3679
  );
2838
3680
  }
3681
+ function handleMaskCli(type, value, opts, io = { stdout: [], stderr: [] }) {
3682
+ let fileContent;
3683
+ if (opts.file) {
3684
+ const content = readInputFile(opts.file, io);
3685
+ if (content === null) {
3686
+ return EXIT.USAGE;
3687
+ }
3688
+ fileContent = content;
3689
+ }
3690
+ return runMask(
3691
+ type,
3692
+ value,
3693
+ {
3694
+ json: Boolean(opts.json),
3695
+ quiet: Boolean(opts.quiet),
3696
+ uf: opts.uf,
3697
+ file: fileContent
3698
+ },
3699
+ io
3700
+ );
3701
+ }
3702
+ function readStdinSync(io) {
3703
+ try {
3704
+ if (process.stdin.isTTY) {
3705
+ return null;
3706
+ }
3707
+ return readNodeFileSync(0, "utf8");
3708
+ } catch {
3709
+ io.stderr.push("Cannot read stdin.");
3710
+ return null;
3711
+ }
3712
+ }
3713
+ function handleCompareCli(type, valueA, valueB, opts, io = { stdout: [], stderr: [] }) {
3714
+ return runCompare(
3715
+ type,
3716
+ valueA,
3717
+ valueB,
3718
+ {
3719
+ json: Boolean(opts.json),
3720
+ quiet: Boolean(opts.quiet),
3721
+ uf: opts.uf
3722
+ },
3723
+ io
3724
+ );
3725
+ }
3726
+ function handleDiffCli(type, valueA, valueB, opts, io = { stdout: [], stderr: [] }) {
3727
+ return runDiff(
3728
+ type,
3729
+ valueA,
3730
+ valueB,
3731
+ {
3732
+ json: Boolean(opts.json),
3733
+ quiet: Boolean(opts.quiet),
3734
+ uf: opts.uf
3735
+ },
3736
+ io
3737
+ );
3738
+ }
3739
+ function handleBatchCli(type, opts, io = { stdout: [], stderr: [] }) {
3740
+ let lines;
3741
+ if (opts.file) {
3742
+ const content = readInputFile(opts.file, io);
3743
+ if (content === null) {
3744
+ return EXIT.USAGE;
3745
+ }
3746
+ lines = content;
3747
+ } else {
3748
+ const stdin = readStdinSync(io);
3749
+ if (stdin !== null) {
3750
+ lines = stdin;
3751
+ }
3752
+ }
3753
+ return runBatch(
3754
+ type,
3755
+ {
3756
+ json: Boolean(opts.json),
3757
+ quiet: Boolean(opts.quiet),
3758
+ uf: opts.uf,
3759
+ lines,
3760
+ limit: opts.limit
3761
+ },
3762
+ io
3763
+ );
3764
+ }
2839
3765
  function handleGenerateCli(type, opts, io = { stdout: [], stderr: [] }) {
2840
3766
  return runGenerate(
2841
3767
  type,
@@ -2843,6 +3769,7 @@ function handleGenerateCli(type, opts, io = { stdout: [], stderr: [] }) {
2843
3769
  json: Boolean(opts.json),
2844
3770
  quiet: Boolean(opts.quiet),
2845
3771
  masked: Boolean(opts.masked),
3772
+ stripped: Boolean(opts.stripped),
2846
3773
  format: opts.format,
2847
3774
  seed: opts.seed,
2848
3775
  uf: opts.uf,
@@ -2894,6 +3821,39 @@ function handleReferenceSearchCli(command, query, opts, io = { stdout: [], stder
2894
3821
  io
2895
3822
  );
2896
3823
  }
3824
+ function handleReferenceValidateCli(command, value, opts, io = { stdout: [], stderr: [] }) {
3825
+ return runReferenceValidate(
3826
+ command,
3827
+ value,
3828
+ {
3829
+ json: Boolean(opts.json),
3830
+ verbose: Boolean(opts.verbose)
3831
+ },
3832
+ io
3833
+ );
3834
+ }
3835
+ function handleCstLookupCli(value, opts, io = { stdout: [], stderr: [] }) {
3836
+ return runCstLookup(value, {
3837
+ json: Boolean(opts.json),
3838
+ verbose: Boolean(opts.verbose),
3839
+ tax: opts.tax
3840
+ }, io);
3841
+ }
3842
+ function handleCstSearchCli(query, opts, io = { stdout: [], stderr: [] }) {
3843
+ return runCstSearch(query, {
3844
+ json: Boolean(opts.json),
3845
+ verbose: Boolean(opts.verbose),
3846
+ tax: opts.tax,
3847
+ limit: opts.limit
3848
+ }, io);
3849
+ }
3850
+ function handleCstValidateCli(value, opts, io = { stdout: [], stderr: [] }) {
3851
+ return runCstValidate(value, {
3852
+ json: Boolean(opts.json),
3853
+ verbose: Boolean(opts.verbose),
3854
+ tax: opts.tax
3855
+ }, io);
3856
+ }
2897
3857
  function handleIbgeLookupCli(value, opts, io = { stdout: [], stderr: [] }) {
2898
3858
  return runIbgeLookup(value, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
2899
3859
  }
@@ -2912,6 +3872,34 @@ function handleFeriadosListCli(opts, io = { stdout: [], stderr: [] }) {
2912
3872
  year: opts.year
2913
3873
  }, io);
2914
3874
  }
3875
+ function handleInssTabelaCli(opts, io = { stdout: [], stderr: [] }) {
3876
+ return runInssTabela({
3877
+ json: Boolean(opts.json),
3878
+ verbose: Boolean(opts.verbose),
3879
+ ano: opts.year
3880
+ }, io);
3881
+ }
3882
+ function handleInssCalcCli(value, opts, io = { stdout: [], stderr: [] }) {
3883
+ return runInssCalc(value, {
3884
+ json: Boolean(opts.json),
3885
+ verbose: Boolean(opts.verbose),
3886
+ ano: opts.year
3887
+ }, io);
3888
+ }
3889
+ function handleIrpfTabelaCli(opts, io = { stdout: [], stderr: [] }) {
3890
+ return runIrpfTabela({
3891
+ json: Boolean(opts.json),
3892
+ verbose: Boolean(opts.verbose),
3893
+ ano: opts.year
3894
+ }, io);
3895
+ }
3896
+ function handleIrpfCalcCli(value, opts, io = { stdout: [], stderr: [] }) {
3897
+ return runIrpfCalc(value, {
3898
+ json: Boolean(opts.json),
3899
+ verbose: Boolean(opts.verbose),
3900
+ ano: opts.year
3901
+ }, io);
3902
+ }
2915
3903
  function handleTseMunicipiosLookupCli(value, opts, io = { stdout: [], stderr: [] }) {
2916
3904
  return runTseMunicipiosLookup(value, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
2917
3905
  }
@@ -2921,6 +3909,32 @@ function handleCepFaixaCli(value, opts, io = { stdout: [], stderr: [] }) {
2921
3909
  function handleDddLookupCli(value, opts, io = { stdout: [], stderr: [] }) {
2922
3910
  return runDddLookup(value, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
2923
3911
  }
3912
+ function handleNfeCufLookupCli(value, opts, io = { stdout: [], stderr: [] }) {
3913
+ return runNfeCufLookup(value, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
3914
+ }
3915
+ function handleSelicCli(opts, io = { stdout: [], stderr: [] }) {
3916
+ return runSelicCommand({
3917
+ json: Boolean(opts.json),
3918
+ verbose: Boolean(opts.verbose),
3919
+ date: opts.date
3920
+ }, io);
3921
+ }
3922
+ function handleIssMunicipalLookupCli(codigo, opts, io = { stdout: [], stderr: [] }) {
3923
+ return runIssMunicipalLookup(codigo, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
3924
+ }
3925
+ function handleIssMunicipalSearchCli(query, opts, io = { stdout: [], stderr: [] }) {
3926
+ return runIssMunicipalSearch(query, {
3927
+ json: Boolean(opts.json),
3928
+ verbose: Boolean(opts.verbose),
3929
+ limit: opts.limit
3930
+ }, io);
3931
+ }
3932
+ function handleIssMunicipalResolveCli(uf, nome, opts, io = { stdout: [], stderr: [] }) {
3933
+ return runIssMunicipalResolve(uf, nome, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
3934
+ }
3935
+ function handlePtaxLookupCli(moeda, data, opts, io = { stdout: [], stderr: [] }) {
3936
+ return runPtaxLookup(moeda, data, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
3937
+ }
2924
3938
 
2925
3939
  // src/argv-dispatch.ts
2926
3940
  var STANDARD_ACTIONS = ["validate", "format", "strip"];
@@ -2955,6 +3969,10 @@ function parseArgv(tokens) {
2955
3969
  opts.masked = true;
2956
3970
  continue;
2957
3971
  }
3972
+ if (token === "--stripped") {
3973
+ opts.stripped = true;
3974
+ continue;
3975
+ }
2958
3976
  if (token === "-f" || token === "--file") {
2959
3977
  opts.file = tokens[index + 1];
2960
3978
  index += 1;
@@ -2994,11 +4012,26 @@ function parseArgv(tokens) {
2994
4012
  index += 1;
2995
4013
  continue;
2996
4014
  }
4015
+ if (token === "--tax") {
4016
+ opts.tax = tokens[index + 1];
4017
+ index += 1;
4018
+ continue;
4019
+ }
2997
4020
  if (token === "--year") {
2998
4021
  opts.year = Number(tokens[index + 1]);
2999
4022
  index += 1;
3000
4023
  continue;
3001
4024
  }
4025
+ if (token === "--ano") {
4026
+ opts.year = Number(tokens[index + 1]);
4027
+ index += 1;
4028
+ continue;
4029
+ }
4030
+ if (token === "--date") {
4031
+ opts.date = tokens[index + 1];
4032
+ index += 1;
4033
+ continue;
4034
+ }
3002
4035
  if (token.startsWith("-")) {
3003
4036
  continue;
3004
4037
  }
@@ -3021,7 +4054,7 @@ function dispatchArgv(tokens, io) {
3021
4054
  if (tokens.length === 0 || tokens.includes("--help") || tokens.includes("-h")) {
3022
4055
  io.stdout.push("br-validators \u2014 100% open-source Brazilian document validators");
3023
4056
  io.stdout.push("Usage: br-validators <command> ...");
3024
- io.stdout.push("Commands: list \xB7 cpf \xB7 cnpj \xB7 cep \xB7 telefone \xB7 cnh \xB7 renavam \xB7 titulo-eleitor \xB7 processo-judicial \xB7 rg \xB7 nfe-chave \xB7 brcode \xB7 placa \xB7 pis-pasep \xB7 cnis \xB7 pix \xB7 boleto \xB7 cartao \xB7 cartao-credito \xB7 ean \xB7 ie \xB7 bancos \xB7 ibge \xB7 feriados \xB7 tse-municipios \xB7 ddd \xB7 natureza-juridica \xB7 nbs \xB7 cest \xB7 cnae \xB7 cfop \xB7 ncm \xB7 cbo \xB7 moedas \xB7 paises-bacen \xB7 incoterms \xB7 portos \xB7 aeroportos \xB7 detect \xB7 sanitize \xB7 generate");
4057
+ io.stdout.push("Commands: list \xB7 cpf \xB7 cnpj \xB7 cep \xB7 telefone \xB7 cnh \xB7 renavam \xB7 titulo-eleitor \xB7 processo-judicial \xB7 rg \xB7 nfe-chave \xB7 brcode \xB7 placa \xB7 pis-pasep \xB7 cnis \xB7 pix \xB7 boleto \xB7 cartao \xB7 cartao-credito \xB7 ean \xB7 ie \xB7 bancos \xB7 ibge \xB7 feriados \xB7 inss \xB7 irpf \xB7 tse-municipios \xB7 ddd \xB7 nfe-cuf \xB7 selic \xB7 iss-municipal \xB7 ptax \xB7 cst \xB7 natureza-juridica \xB7 nbs \xB7 cest \xB7 cnae \xB7 cfop \xB7 ncm \xB7 cbo \xB7 moedas \xB7 paises-bacen \xB7 incoterms \xB7 portos \xB7 aeroportos \xB7 detect \xB7 sanitize \xB7 mask \xB7 compare \xB7 batch \xB7 diff \xB7 generate");
3025
4058
  return EXIT.OK;
3026
4059
  }
3027
4060
  if (tokens.includes("--version") || tokens.includes("-V")) {
@@ -3199,6 +4232,28 @@ function dispatchArgv(tokens, io) {
3199
4232
  }
3200
4233
  return usage(io, "Expected: feriados list [--year YYYY]");
3201
4234
  }
4235
+ case "inss": {
4236
+ const action = rest[0];
4237
+ if (action === "tabela") {
4238
+ return handleInssTabelaCli(opts, io);
4239
+ }
4240
+ if (action === "calc") {
4241
+ const value = rest.slice(1).join(" ") || void 0;
4242
+ return handleInssCalcCli(value, opts, io);
4243
+ }
4244
+ return usage(io, "Expected: inss tabela [--ano YYYY] | inss calc <salario> [--ano YYYY]");
4245
+ }
4246
+ case "irpf": {
4247
+ const action = rest[0];
4248
+ if (action === "tabela") {
4249
+ return handleIrpfTabelaCli(opts, io);
4250
+ }
4251
+ if (action === "calc") {
4252
+ const value = rest.slice(1).join(" ") || void 0;
4253
+ return handleIrpfCalcCli(value, opts, io);
4254
+ }
4255
+ return usage(io, "Expected: irpf tabela [--ano YYYY] | irpf calc <base> [--ano YYYY]");
4256
+ }
3202
4257
  case "tse-municipios": {
3203
4258
  const action = rest[0];
3204
4259
  if (action === "lookup") {
@@ -3215,10 +4270,90 @@ function dispatchArgv(tokens, io) {
3215
4270
  }
3216
4271
  return usage(io, "Expected: ddd lookup <code>");
3217
4272
  }
4273
+ case "nfe-cuf": {
4274
+ const action = rest[0];
4275
+ if (action === "lookup") {
4276
+ const value = rest.slice(1).join(" ") || void 0;
4277
+ return handleNfeCufLookupCli(value, opts, io);
4278
+ }
4279
+ return usage(io, "Expected: nfe-cuf lookup <code>");
4280
+ }
4281
+ case "selic": {
4282
+ return handleSelicCli(opts, io);
4283
+ }
4284
+ case "iss-municipal": {
4285
+ const action = rest[0];
4286
+ if (action === "lookup") {
4287
+ const value = rest[1];
4288
+ return handleIssMunicipalLookupCli(value, opts, io);
4289
+ }
4290
+ if (action === "resolve") {
4291
+ const uf = rest[1];
4292
+ const nome = rest.slice(2).join(" ") || void 0;
4293
+ return handleIssMunicipalResolveCli(uf, nome, opts, io);
4294
+ }
4295
+ if (action === "search") {
4296
+ const value = rest.slice(1).join(" ") || void 0;
4297
+ return handleIssMunicipalSearchCli(value, opts, io);
4298
+ }
4299
+ return usage(io, "Expected: iss-municipal lookup|resolve|search <args>");
4300
+ }
4301
+ case "ptax": {
4302
+ const action = rest[0];
4303
+ if (action === "lookup") {
4304
+ const moeda = rest[1];
4305
+ const data = rest.slice(2).join(" ") || void 0;
4306
+ return handlePtaxLookupCli(moeda, data, opts, io);
4307
+ }
4308
+ return usage(io, "Expected: ptax lookup <moeda> [data]");
4309
+ }
4310
+ case "cst": {
4311
+ const action = rest[0];
4312
+ if (action === "lookup") {
4313
+ const value = rest.slice(1).join(" ") || void 0;
4314
+ return handleCstLookupCli(value, opts, io);
4315
+ }
4316
+ if (action === "search") {
4317
+ const value = rest.slice(1).join(" ") || void 0;
4318
+ return handleCstSearchCli(value, opts, io);
4319
+ }
4320
+ if (action === "validate") {
4321
+ const value = rest.slice(1).join(" ") || void 0;
4322
+ return handleCstValidateCli(value, opts, io);
4323
+ }
4324
+ return usage(io, "Expected: cst lookup|search|validate <codigo|query> --tax icms|ipi|pis|cofins");
4325
+ }
3218
4326
  case "detect":
3219
4327
  return handleDetectCli(rest.join(" ") || void 0, opts, io);
3220
4328
  case "sanitize":
3221
4329
  return handleSanitizeCli(rest[0] ?? "", rest.slice(1).join(" ") || void 0, opts, io);
4330
+ case "mask":
4331
+ return handleMaskCli(rest[0] ?? "", rest.slice(1).join(" ") || void 0, opts, io);
4332
+ case "compare": {
4333
+ const type = rest[0];
4334
+ const valueA = rest[1];
4335
+ const valueB = rest.slice(2).join(" ") || void 0;
4336
+ if (!type) {
4337
+ return usage(io, "Expected: compare <type> <valueA> <valueB>");
4338
+ }
4339
+ return handleCompareCli(type, valueA, valueB, opts, io);
4340
+ }
4341
+ case "batch": {
4342
+ const type = rest[0];
4343
+ if (!type) {
4344
+ return usage(io, "Expected: batch <type> [--file path]");
4345
+ }
4346
+ return handleBatchCli(type, opts, io);
4347
+ }
4348
+ case "diff": {
4349
+ const type = rest[0];
4350
+ const valueA = rest[1];
4351
+ const valueB = rest.slice(2).join(" ") || void 0;
4352
+ if (!type) {
4353
+ return usage(io, "Expected: diff <type> <valueA> <valueB>");
4354
+ }
4355
+ return handleDiffCli(type, valueA, valueB, opts, io);
4356
+ }
3222
4357
  case "generate":
3223
4358
  return handleGenerateCli(rest[0] ?? "", opts, io);
3224
4359
  default: {
@@ -3232,8 +4367,13 @@ function dispatchArgv(tokens, io) {
3232
4367
  const value = rest.slice(1).join(" ") || void 0;
3233
4368
  return handleReferenceSearchCli(root, value, opts, io);
3234
4369
  }
4370
+ if (action === "validate" && isReferenceValidateCommand(root)) {
4371
+ const value = rest.slice(1).join(" ") || void 0;
4372
+ return handleReferenceValidateCli(root, value, opts, io);
4373
+ }
3235
4374
  const searchHint = isReferenceSearchCommand(root) ? " | search <query>" : "";
3236
- return usage(io, `Expected: ${root} lookup <codigo>${searchHint}`);
4375
+ const validateHint = isReferenceValidateCommand(root) ? " | validate <codigo>" : "";
4376
+ return usage(io, `Expected: ${root} lookup <codigo>${searchHint}${validateHint}`);
3237
4377
  }
3238
4378
  return usage(io, `Unknown command: ${root}`);
3239
4379
  }