@br-validators/cli 0.10.0-alpha.1 → 0.12.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +846 -72
  2. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -6,22 +6,103 @@ import { Command } from "commander";
6
6
  // src/handlers.ts
7
7
  import { readFileSync } from "fs";
8
8
 
9
- // src/commands/cep.ts
9
+ // src/commands/brcode.ts
10
10
  import {
11
- CEP_OFFICIAL_SOURCE_URL,
12
- formatCep,
13
- stripCep,
14
- validateCep
11
+ BRCODE_OFFICIAL_SOURCE_URL,
12
+ parseBrCode,
13
+ validateBrCode
15
14
  } from "@br-validators/core";
16
15
 
17
16
  // src/constants.ts
18
- var SUPPORTED_TYPES = ["cnpj", "cpf", "cep", "placa", "pis-pasep", "pix", "boleto", "cartao", "ie"];
17
+ var SUPPORTED_TYPES = ["cnpj", "cpf", "cep", "telefone", "cnh", "renavam", "titulo-eleitor", "nfe-chave", "brcode", "placa", "pis-pasep", "pix", "boleto", "cartao", "ie"];
19
18
  var EXIT = {
20
19
  OK: 0,
21
20
  INVALID: 1,
22
21
  USAGE: 2
23
22
  };
24
23
 
24
+ // src/commands/brcode.ts
25
+ function resolveInput(value, fileContent) {
26
+ const input = value ?? fileContent?.trim();
27
+ if (!input) {
28
+ return null;
29
+ }
30
+ return input;
31
+ }
32
+ function printBrCodeResult(result, options, io = { stdout: [], stderr: [] }) {
33
+ if (options.json) {
34
+ io.stdout.push(
35
+ JSON.stringify(
36
+ result.ok ? {
37
+ ok: true,
38
+ value: result.value,
39
+ format: result.format,
40
+ merchantName: result.merchantName,
41
+ merchantCity: result.merchantCity,
42
+ ...result.amount ? { amount: result.amount } : {},
43
+ ...result.txid ? { txid: result.txid } : {},
44
+ ...result.pixKey ? { pixKey: result.pixKey, pixKeyType: result.pixKeyType } : {},
45
+ ...result.pixInitiationUrl ? { pixInitiationUrl: result.pixInitiationUrl } : {},
46
+ ...options.source ? { source: options.source } : {}
47
+ } : { ok: false, code: result.code, message: result.message },
48
+ null,
49
+ 2
50
+ )
51
+ );
52
+ return result.ok ? EXIT.OK : EXIT.INVALID;
53
+ }
54
+ if (options.quiet) {
55
+ return result.ok ? EXIT.OK : EXIT.INVALID;
56
+ }
57
+ if (result.ok) {
58
+ io.stdout.push("valid: yes");
59
+ io.stdout.push(`merchantName: ${result.merchantName}`);
60
+ io.stdout.push(`merchantCity: ${result.merchantCity}`);
61
+ if (result.amount) {
62
+ io.stdout.push(`amount: ${result.amount}`);
63
+ }
64
+ if (result.txid) {
65
+ io.stdout.push(`txid: ${result.txid}`);
66
+ }
67
+ if (result.pixKey) {
68
+ io.stdout.push(`pixKey: ${result.pixKey}`);
69
+ io.stdout.push(`pixKeyType: ${result.pixKeyType}`);
70
+ }
71
+ if (result.pixInitiationUrl) {
72
+ io.stdout.push(`pixInitiationUrl: ${result.pixInitiationUrl}`);
73
+ }
74
+ if (options.source) {
75
+ io.stdout.push(`source: ${options.source}`);
76
+ }
77
+ return EXIT.OK;
78
+ }
79
+ io.stderr.push("valid: no");
80
+ io.stderr.push(`code: ${result.code}`);
81
+ io.stderr.push(`message: ${result.message}`);
82
+ return EXIT.INVALID;
83
+ }
84
+ function runBrCodeCommand(action, input, options, io = { stdout: [], stderr: [] }) {
85
+ const source = options.source ? BRCODE_OFFICIAL_SOURCE_URL : void 0;
86
+ const result = action === "validate" ? validateBrCode(input) : parseBrCode(input);
87
+ return printBrCodeResult(result, { json: options.json, quiet: options.quiet, source }, io);
88
+ }
89
+ function runBrCode(action, value, options, io = { stdout: [], stderr: [] }) {
90
+ const input = resolveInput(value, options.file);
91
+ if (input === null) {
92
+ io.stderr.push("Missing BR Code payload. Pass an argument or use --file.");
93
+ return EXIT.USAGE;
94
+ }
95
+ return runBrCodeCommand(action, input, options, io);
96
+ }
97
+
98
+ // src/commands/cep.ts
99
+ import {
100
+ CEP_OFFICIAL_SOURCE_URL,
101
+ formatCep,
102
+ stripCep,
103
+ validateCep
104
+ } from "@br-validators/core";
105
+
25
106
  // src/output.ts
26
107
  function printValidation(result, options, io = { stdout: [], stderr: [] }) {
27
108
  if (options.json) {
@@ -55,6 +136,46 @@ function printValidation(result, options, io = { stdout: [], stderr: [] }) {
55
136
  io.stderr.push(`message: ${result.message}`);
56
137
  return EXIT.INVALID;
57
138
  }
139
+ function printNfeChaveValidation(result, options, io = { stdout: [], stderr: [] }) {
140
+ if (options.json) {
141
+ io.stdout.push(
142
+ JSON.stringify(
143
+ result.ok ? {
144
+ ok: true,
145
+ value: result.value,
146
+ format: result.format,
147
+ parsed: result.parsed,
148
+ ...result.uf ? { uf: result.uf } : {},
149
+ ...options.source ? { source: options.source } : {}
150
+ } : { ok: false, code: result.code, message: result.message },
151
+ null,
152
+ 2
153
+ )
154
+ );
155
+ return result.ok ? EXIT.OK : EXIT.INVALID;
156
+ }
157
+ if (options.quiet) {
158
+ return result.ok ? EXIT.OK : EXIT.INVALID;
159
+ }
160
+ if (result.ok) {
161
+ io.stdout.push(`valid: yes (${result.format})`);
162
+ io.stdout.push(`value: ${result.value}`);
163
+ io.stdout.push(`cUF: ${result.parsed.cUF}`);
164
+ io.stdout.push(`cnpj: ${result.parsed.cnpj}`);
165
+ io.stdout.push(`mod: ${result.parsed.mod}`);
166
+ if (result.uf) {
167
+ io.stdout.push(`uf: ${result.uf}`);
168
+ }
169
+ if (options.source) {
170
+ io.stdout.push(`source: ${options.source}`);
171
+ }
172
+ return EXIT.OK;
173
+ }
174
+ io.stderr.push("valid: no");
175
+ io.stderr.push(`code: ${result.code}`);
176
+ io.stderr.push(`message: ${result.message}`);
177
+ return EXIT.INVALID;
178
+ }
58
179
  function printFormat(result, options, io = { stdout: [], stderr: [] }) {
59
180
  if (options.json) {
60
181
  io.stdout.push(JSON.stringify(result, null, 2));
@@ -81,7 +202,7 @@ function printStrip(value, options, io = { stdout: [] }) {
81
202
  }
82
203
 
83
204
  // src/commands/cep.ts
84
- function resolveInput(value, fileContent) {
205
+ function resolveInput2(value, fileContent) {
85
206
  const input = value ?? fileContent?.trim();
86
207
  if (!input) {
87
208
  return null;
@@ -105,7 +226,7 @@ function runCepCommand(action, input, options, io = { stdout: [], stderr: [] })
105
226
  }
106
227
  }
107
228
  function runCep(action, value, options, io = { stdout: [], stderr: [] }) {
108
- const input = resolveInput(value, options.file);
229
+ const input = resolveInput2(value, options.file);
109
230
  if (input === null) {
110
231
  io.stderr.push("Missing CEP value. Pass an argument or use --file.");
111
232
  return EXIT.USAGE;
@@ -113,6 +234,238 @@ function runCep(action, value, options, io = { stdout: [], stderr: [] }) {
113
234
  return runCepCommand(action, input, options, io);
114
235
  }
115
236
 
237
+ // src/commands/telefone.ts
238
+ import {
239
+ TELEFONE_OFFICIAL_SOURCE_URL,
240
+ formatTelefone,
241
+ stripTelefone,
242
+ validateTelefone
243
+ } from "@br-validators/core";
244
+ function resolveInput3(value, fileContent) {
245
+ const input = value ?? fileContent?.trim();
246
+ if (!input) {
247
+ return null;
248
+ }
249
+ return input;
250
+ }
251
+ function printTelefoneValidation(result, options, io = { stdout: [], stderr: [] }) {
252
+ if (options.json) {
253
+ io.stdout.push(
254
+ JSON.stringify(
255
+ result.ok ? {
256
+ ok: true,
257
+ value: result.value,
258
+ tipo: result.tipo,
259
+ format: result.format,
260
+ ...options.source ? { source: options.source } : {}
261
+ } : { ok: false, code: result.code, message: result.message },
262
+ null,
263
+ 2
264
+ )
265
+ );
266
+ return result.ok ? EXIT.OK : EXIT.INVALID;
267
+ }
268
+ if (options.quiet) {
269
+ return result.ok ? EXIT.OK : EXIT.INVALID;
270
+ }
271
+ if (result.ok) {
272
+ io.stdout.push(`valid: yes (${result.tipo})`);
273
+ io.stdout.push(`value: ${result.value}`);
274
+ io.stdout.push(`format: ${result.format}`);
275
+ if (options.source) {
276
+ io.stdout.push(`source: ${options.source}`);
277
+ }
278
+ return EXIT.OK;
279
+ }
280
+ io.stderr.push("valid: no");
281
+ io.stderr.push(`code: ${result.code}`);
282
+ io.stderr.push(`message: ${result.message}`);
283
+ return EXIT.INVALID;
284
+ }
285
+ function runTelefoneCommand(action, input, options, io = { stdout: [], stderr: [] }) {
286
+ const source = options.source ? TELEFONE_OFFICIAL_SOURCE_URL : void 0;
287
+ switch (action) {
288
+ case "validate":
289
+ return printTelefoneValidation(validateTelefone(input), { json: options.json, quiet: options.quiet, source }, io);
290
+ case "format":
291
+ return printFormat(formatTelefone(input), { json: options.json, quiet: options.quiet }, io);
292
+ case "strip":
293
+ return printStrip(stripTelefone(input), { json: options.json }, io);
294
+ default: {
295
+ const _exhaustive = action;
296
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
297
+ return EXIT.USAGE;
298
+ }
299
+ }
300
+ }
301
+ function runTelefone(action, value, options, io = { stdout: [], stderr: [] }) {
302
+ const input = resolveInput3(value, options.file);
303
+ if (input === null) {
304
+ io.stderr.push("Missing telephone value. Pass an argument or use --file.");
305
+ return EXIT.USAGE;
306
+ }
307
+ return runTelefoneCommand(action, input, options, io);
308
+ }
309
+
310
+ // src/commands/cnh.ts
311
+ import {
312
+ CNH_OFFICIAL_SOURCE_URL,
313
+ formatCnh,
314
+ stripCnh,
315
+ validateCnh
316
+ } from "@br-validators/core";
317
+ function resolveInput4(value, fileContent) {
318
+ const input = value ?? fileContent?.trim();
319
+ if (!input) {
320
+ return null;
321
+ }
322
+ return input;
323
+ }
324
+ function runCnhCommand(action, input, options, io = { stdout: [], stderr: [] }) {
325
+ const source = options.source ? CNH_OFFICIAL_SOURCE_URL : void 0;
326
+ switch (action) {
327
+ case "validate":
328
+ return printValidation(validateCnh(input), { json: options.json, quiet: options.quiet, source }, io);
329
+ case "format":
330
+ return printFormat(formatCnh(input), { json: options.json, quiet: options.quiet }, io);
331
+ case "strip":
332
+ return printStrip(stripCnh(input), { json: options.json }, io);
333
+ default: {
334
+ const _exhaustive = action;
335
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
336
+ return EXIT.USAGE;
337
+ }
338
+ }
339
+ }
340
+ function runCnh(action, value, options, io = { stdout: [], stderr: [] }) {
341
+ const input = resolveInput4(value, options.file);
342
+ if (input === null) {
343
+ io.stderr.push("Missing CNH value. Pass an argument or use --file.");
344
+ return EXIT.USAGE;
345
+ }
346
+ return runCnhCommand(action, input, options, io);
347
+ }
348
+
349
+ // src/commands/renavam.ts
350
+ import {
351
+ RENAVAM_OFFICIAL_SOURCE_URL,
352
+ formatRenavam,
353
+ stripRenavam,
354
+ validateRenavam
355
+ } from "@br-validators/core";
356
+ function resolveInput5(value, fileContent) {
357
+ const input = value ?? fileContent?.trim();
358
+ if (!input) {
359
+ return null;
360
+ }
361
+ return input;
362
+ }
363
+ function runRenavamCommand(action, input, options, io = { stdout: [], stderr: [] }) {
364
+ const source = options.source ? RENAVAM_OFFICIAL_SOURCE_URL : void 0;
365
+ switch (action) {
366
+ case "validate":
367
+ return printValidation(validateRenavam(input), { json: options.json, quiet: options.quiet, source }, io);
368
+ case "format":
369
+ return printFormat(formatRenavam(input), { json: options.json, quiet: options.quiet }, io);
370
+ case "strip":
371
+ return printStrip(stripRenavam(input), { json: options.json }, io);
372
+ default: {
373
+ const _exhaustive = action;
374
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
375
+ return EXIT.USAGE;
376
+ }
377
+ }
378
+ }
379
+ function runRenavam(action, value, options, io = { stdout: [], stderr: [] }) {
380
+ const input = resolveInput5(value, options.file);
381
+ if (input === null) {
382
+ io.stderr.push("Missing RENAVAM value. Pass an argument or use --file.");
383
+ return EXIT.USAGE;
384
+ }
385
+ return runRenavamCommand(action, input, options, io);
386
+ }
387
+
388
+ // src/commands/titulo-eleitor.ts
389
+ import {
390
+ TITULO_ELEITOR_OFFICIAL_SOURCE_URL,
391
+ formatTituloEleitor,
392
+ stripTituloEleitor,
393
+ validateTituloEleitor
394
+ } from "@br-validators/core";
395
+ function resolveInput6(value, fileContent) {
396
+ const input = value ?? fileContent?.trim();
397
+ if (!input) {
398
+ return null;
399
+ }
400
+ return input;
401
+ }
402
+ function runTituloEleitorCommand(action, input, options, io = { stdout: [], stderr: [] }) {
403
+ const source = options.source ? TITULO_ELEITOR_OFFICIAL_SOURCE_URL : void 0;
404
+ switch (action) {
405
+ case "validate":
406
+ return printValidation(validateTituloEleitor(input), { json: options.json, quiet: options.quiet, source }, io);
407
+ case "format":
408
+ return printFormat(formatTituloEleitor(input), { json: options.json, quiet: options.quiet }, io);
409
+ case "strip":
410
+ return printStrip(stripTituloEleitor(input), { json: options.json }, io);
411
+ default: {
412
+ const _exhaustive = action;
413
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
414
+ return EXIT.USAGE;
415
+ }
416
+ }
417
+ }
418
+ function runTituloEleitor(action, value, options, io = { stdout: [], stderr: [] }) {
419
+ const input = resolveInput6(value, options.file);
420
+ if (input === null) {
421
+ io.stderr.push("Missing T\xEDtulo de Eleitor value. Pass an argument or use --file.");
422
+ return EXIT.USAGE;
423
+ }
424
+ return runTituloEleitorCommand(action, input, options, io);
425
+ }
426
+
427
+ // src/commands/nfe-chave.ts
428
+ import {
429
+ NFE_CHAVE_OFFICIAL_SOURCE_URL,
430
+ formatNfeChave,
431
+ parseNfeChave,
432
+ stripNfeChave,
433
+ validateNfeChave
434
+ } from "@br-validators/core";
435
+ function resolveInput7(value, fileContent) {
436
+ const input = value ?? fileContent?.trim();
437
+ if (!input) {
438
+ return null;
439
+ }
440
+ return input;
441
+ }
442
+ function runNfeChaveCommand(action, input, options, io = { stdout: [], stderr: [] }) {
443
+ const source = options.source ? NFE_CHAVE_OFFICIAL_SOURCE_URL : void 0;
444
+ switch (action) {
445
+ case "validate":
446
+ return printValidation(validateNfeChave(input), { json: options.json, quiet: options.quiet, source }, io);
447
+ case "parse":
448
+ return printNfeChaveValidation(parseNfeChave(input), { json: options.json, quiet: options.quiet, source }, io);
449
+ case "format":
450
+ return printFormat(formatNfeChave(input), { json: options.json, quiet: options.quiet }, io);
451
+ case "strip":
452
+ return printStrip(stripNfeChave(input), { json: options.json }, io);
453
+ default: {
454
+ const _exhaustive = action;
455
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
456
+ return EXIT.USAGE;
457
+ }
458
+ }
459
+ }
460
+ function runNfeChave(action, value, options, io = { stdout: [], stderr: [] }) {
461
+ const input = resolveInput7(value, options.file);
462
+ if (input === null) {
463
+ io.stderr.push("Missing NF-e chave de acesso value. Pass an argument or use --file.");
464
+ return EXIT.USAGE;
465
+ }
466
+ return runNfeChaveCommand(action, input, options, io);
467
+ }
468
+
116
469
  // src/commands/cnpj.ts
117
470
  import {
118
471
  CNPJ_OFFICIAL_SOURCE_URL,
@@ -120,7 +473,7 @@ import {
120
473
  stripCnpj,
121
474
  validateCnpj
122
475
  } from "@br-validators/core";
123
- function resolveInput2(value, fileContent) {
476
+ function resolveInput8(value, fileContent) {
124
477
  const input = value ?? fileContent?.trim();
125
478
  if (!input) {
126
479
  return null;
@@ -144,7 +497,7 @@ function runCnpjCommand(action, input, options, io = { stdout: [], stderr: [] })
144
497
  }
145
498
  }
146
499
  function runCnpj(action, value, options, io = { stdout: [], stderr: [] }) {
147
- const input = resolveInput2(value, options.file);
500
+ const input = resolveInput8(value, options.file);
148
501
  if (input === null) {
149
502
  io.stderr.push("Missing CNPJ value. Pass an argument or use --file.");
150
503
  return EXIT.USAGE;
@@ -159,7 +512,7 @@ import {
159
512
  stripCpf,
160
513
  validateCpf
161
514
  } from "@br-validators/core";
162
- function resolveInput3(value, fileContent) {
515
+ function resolveInput9(value, fileContent) {
163
516
  const input = value ?? fileContent?.trim();
164
517
  if (!input) {
165
518
  return null;
@@ -183,7 +536,7 @@ function runCpfCommand(action, input, options, io = { stdout: [], stderr: [] })
183
536
  }
184
537
  }
185
538
  function runCpf(action, value, options, io = { stdout: [], stderr: [] }) {
186
- const input = resolveInput3(value, options.file);
539
+ const input = resolveInput9(value, options.file);
187
540
  if (input === null) {
188
541
  io.stderr.push("Missing CPF value. Pass an argument or use --file.");
189
542
  return EXIT.USAGE;
@@ -199,7 +552,7 @@ import {
199
552
  stripPlaca,
200
553
  validatePlaca
201
554
  } from "@br-validators/core";
202
- function resolveInput4(value, fileContent) {
555
+ function resolveInput10(value, fileContent) {
203
556
  const input = value ?? fileContent?.trim();
204
557
  if (!input) {
205
558
  return null;
@@ -225,7 +578,7 @@ function runPlacaCommand(action, input, options, io = { stdout: [], stderr: [] }
225
578
  }
226
579
  }
227
580
  function runPlaca(action, value, options, io = { stdout: [], stderr: [] }) {
228
- const input = resolveInput4(value, options.file);
581
+ const input = resolveInput10(value, options.file);
229
582
  if (input === null) {
230
583
  io.stderr.push("Missing placa value. Pass an argument or use --file.");
231
584
  return EXIT.USAGE;
@@ -240,7 +593,7 @@ import {
240
593
  stripPisPasep,
241
594
  validatePisPasep
242
595
  } from "@br-validators/core";
243
- function resolveInput5(value, fileContent) {
596
+ function resolveInput11(value, fileContent) {
244
597
  const input = value ?? fileContent?.trim();
245
598
  if (!input) {
246
599
  return null;
@@ -264,7 +617,7 @@ function runPisPasepCommand(action, input, options, io = { stdout: [], stderr: [
264
617
  }
265
618
  }
266
619
  function runPisPasep(action, value, options, io = { stdout: [], stderr: [] }) {
267
- const input = resolveInput5(value, options.file);
620
+ const input = resolveInput11(value, options.file);
268
621
  if (input === null) {
269
622
  io.stderr.push("Missing PIS/PASEP value. Pass an argument or use --file.");
270
623
  return EXIT.USAGE;
@@ -279,7 +632,7 @@ import {
279
632
  formatPixKey,
280
633
  validatePixKey
281
634
  } from "@br-validators/core";
282
- function resolveInput6(value, fileContent) {
635
+ function resolveInput12(value, fileContent) {
283
636
  const input = value ?? fileContent?.trim();
284
637
  if (!input) {
285
638
  return null;
@@ -354,7 +707,7 @@ function runPixCommand(action, input, options, io = { stdout: [], stderr: [] })
354
707
  }
355
708
  }
356
709
  function runPix(action, value, options, io = { stdout: [], stderr: [] }) {
357
- const input = resolveInput6(value, options.file);
710
+ const input = resolveInput12(value, options.file);
358
711
  if (input === null) {
359
712
  io.stderr.push("Missing PIX key value. Pass an argument or use --file.");
360
713
  return EXIT.USAGE;
@@ -373,7 +726,7 @@ import {
373
726
  stripLinhaDigitavel,
374
727
  validateBoleto
375
728
  } from "@br-validators/core";
376
- function resolveInput7(value, fileContent) {
729
+ function resolveInput13(value, fileContent) {
377
730
  const input = value ?? fileContent?.trim();
378
731
  if (!input) {
379
732
  return null;
@@ -497,7 +850,7 @@ function runBoletoCommand(action, input, options, direction, io = { stdout: [],
497
850
  }
498
851
  }
499
852
  function runBoleto(action, value, options, direction, io = { stdout: [], stderr: [] }) {
500
- const input = resolveInput7(value, options.file);
853
+ const input = resolveInput13(value, options.file);
501
854
  if (input === null) {
502
855
  io.stderr.push("Missing boleto value. Pass an argument or use --file.");
503
856
  return EXIT.USAGE;
@@ -513,7 +866,7 @@ import {
513
866
  stripCartaoCredito,
514
867
  validateCartaoCredito
515
868
  } from "@br-validators/core";
516
- function resolveInput8(value, fileContent) {
869
+ function resolveInput14(value, fileContent) {
517
870
  const input = value ?? fileContent?.trim();
518
871
  if (!input) {
519
872
  return null;
@@ -589,7 +942,7 @@ function runCartaoCommand(action, input, options, io = { stdout: [], stderr: []
589
942
  }
590
943
  }
591
944
  function runCartao(action, value, options, io = { stdout: [], stderr: [] }) {
592
- const input = resolveInput8(value, options.file);
945
+ const input = resolveInput14(value, options.file);
593
946
  if (input === null) {
594
947
  io.stderr.push("Missing credit card PAN value. Pass an argument or use --file.");
595
948
  return EXIT.USAGE;
@@ -599,13 +952,18 @@ function runCartao(action, value, options, io = { stdout: [], stderr: [] }) {
599
952
 
600
953
  // src/commands/ie.ts
601
954
  import {
955
+ formatIeProdutorRural,
602
956
  formatInscricaoEstadual,
603
957
  getIeOfficialSourceUrl,
958
+ getIeProdutorRuralOfficialSourceUrl,
604
959
  IE_SUPPORTED_UFS,
960
+ isSpRuralIeInput,
961
+ stripIeSpRural,
605
962
  stripInscricaoEstadual,
963
+ validateIeProdutorRural,
606
964
  validateInscricaoEstadual
607
965
  } from "@br-validators/core";
608
- function resolveInput9(value, fileContent) {
966
+ function resolveInput15(value, fileContent) {
609
967
  const input = value ?? fileContent?.trim();
610
968
  if (!input) {
611
969
  return null;
@@ -622,76 +980,249 @@ function resolveUf(uf) {
622
980
  }
623
981
  return null;
624
982
  }
625
- function printIeValidation(result, options, io = { stdout: [], stderr: [] }) {
983
+ function isSpRuralRoute(uf, input) {
984
+ return uf === "SP" && isSpRuralIeInput(input);
985
+ }
986
+ function printIeValidation(result, options, io = { stdout: [], stderr: [] }) {
987
+ if (options.json) {
988
+ io.stdout.push(
989
+ JSON.stringify(
990
+ result.ok ? {
991
+ ok: true,
992
+ value: result.value,
993
+ uf: result.uf,
994
+ format: result.format,
995
+ ...options.rural ? { produtorRural: true } : {},
996
+ ...options.source ? { source: options.source } : {}
997
+ } : {
998
+ ok: false,
999
+ code: result.code,
1000
+ message: result.message,
1001
+ ...result.uf ? { uf: result.uf } : {}
1002
+ },
1003
+ null,
1004
+ 2
1005
+ )
1006
+ );
1007
+ return result.ok ? EXIT.OK : EXIT.INVALID;
1008
+ }
1009
+ if (options.quiet) {
1010
+ return result.ok ? EXIT.OK : EXIT.INVALID;
1011
+ }
1012
+ if (result.ok) {
1013
+ io.stdout.push(`valid: yes (${result.uf})`);
1014
+ if (options.rural) {
1015
+ io.stdout.push("kind: produtor-rural");
1016
+ }
1017
+ io.stdout.push(`value: ${result.value}`);
1018
+ io.stdout.push(`format: ${result.format}`);
1019
+ if (options.source) {
1020
+ io.stdout.push(`source: ${options.source}`);
1021
+ }
1022
+ return EXIT.OK;
1023
+ }
1024
+ io.stderr.push("valid: no");
1025
+ io.stderr.push(`code: ${result.code}`);
1026
+ io.stderr.push(`message: ${result.message}`);
1027
+ if (result.uf) {
1028
+ io.stderr.push(`uf: ${result.uf}`);
1029
+ }
1030
+ return EXIT.INVALID;
1031
+ }
1032
+ function runIeCommand(action, input, options, io = { stdout: [], stderr: [] }) {
1033
+ const uf = resolveUf(options.uf);
1034
+ if (!uf) {
1035
+ io.stderr.push(`Missing or invalid --uf. Use one of: ${IE_SUPPORTED_UFS.join(", ")}.`);
1036
+ return EXIT.USAGE;
1037
+ }
1038
+ const rural = isSpRuralRoute(uf, input);
1039
+ const source = options.source ? rural ? getIeProdutorRuralOfficialSourceUrl() : getIeOfficialSourceUrl(uf) : void 0;
1040
+ switch (action) {
1041
+ case "validate":
1042
+ return printIeValidation(
1043
+ rural ? validateIeProdutorRural(uf, input) : validateInscricaoEstadual(input, { uf }),
1044
+ { json: options.json, quiet: options.quiet, source, rural },
1045
+ io
1046
+ );
1047
+ case "format":
1048
+ return printFormat(
1049
+ rural ? formatIeProdutorRural(input) : formatInscricaoEstadual(input, { uf }),
1050
+ { json: options.json, quiet: options.quiet },
1051
+ io
1052
+ );
1053
+ case "strip":
1054
+ return printStrip(rural ? stripIeSpRural(input) : stripInscricaoEstadual(input), { json: options.json }, io);
1055
+ default: {
1056
+ const _exhaustive = action;
1057
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
1058
+ return EXIT.USAGE;
1059
+ }
1060
+ }
1061
+ }
1062
+ function runIe(action, value, options, io = { stdout: [], stderr: [] }) {
1063
+ const input = resolveInput15(value, options.file);
1064
+ if (input === null) {
1065
+ io.stderr.push("Missing IE value. Pass an argument or use --file.");
1066
+ return EXIT.USAGE;
1067
+ }
1068
+ return runIeCommand(action, input, options, io);
1069
+ }
1070
+
1071
+ // src/commands/detect.ts
1072
+ import { detect } from "@br-validators/core";
1073
+ function resolveInput16(value, fileContent) {
1074
+ const input = value ?? fileContent?.trim();
1075
+ if (!input) {
1076
+ return null;
1077
+ }
1078
+ return input;
1079
+ }
1080
+ function printDetect(result, options, io = { stdout: [], stderr: [] }) {
1081
+ if (options.json) {
1082
+ io.stdout.push(JSON.stringify(result, null, 2));
1083
+ return result.ok ? EXIT.OK : EXIT.INVALID;
1084
+ }
1085
+ if (options.quiet) {
1086
+ return result.ok ? EXIT.OK : EXIT.INVALID;
1087
+ }
1088
+ if (result.ok) {
1089
+ io.stdout.push(`type: ${result.type}`);
1090
+ io.stdout.push("valid: yes");
1091
+ io.stdout.push(`value: ${result.value}`);
1092
+ if (result.format) {
1093
+ io.stdout.push(`format: ${result.format}`);
1094
+ }
1095
+ if (result.meta) {
1096
+ io.stdout.push(`meta: ${JSON.stringify(result.meta)}`);
1097
+ }
1098
+ return EXIT.OK;
1099
+ }
1100
+ io.stderr.push(`type: ${result.type}`);
1101
+ io.stderr.push("valid: no");
1102
+ io.stderr.push(`code: ${result.code}`);
1103
+ io.stderr.push(`message: ${result.message}`);
1104
+ return EXIT.INVALID;
1105
+ }
1106
+ function runDetect(value, options, io = { stdout: [], stderr: [] }) {
1107
+ const input = resolveInput16(value, options.file);
1108
+ if (input === null) {
1109
+ io.stderr.push("Missing value. Pass an argument or use --file.");
1110
+ return EXIT.USAGE;
1111
+ }
1112
+ const uf = options.uf?.toUpperCase();
1113
+ const result = detect(input, uf ? { uf } : {});
1114
+ return printDetect(result, options, io);
1115
+ }
1116
+
1117
+ // src/commands/sanitize.ts
1118
+ import { sanitize } from "@br-validators/core";
1119
+ var SANITIZABLE_TYPES = [
1120
+ "cpf",
1121
+ "cnpj",
1122
+ "cep",
1123
+ "placa",
1124
+ "pis-pasep",
1125
+ "telefone",
1126
+ "cnh",
1127
+ "renavam",
1128
+ "titulo-eleitor",
1129
+ "nfe-chave",
1130
+ "boleto",
1131
+ "cartao-credito",
1132
+ "inscricao-estadual",
1133
+ "inscricao-estadual-produtor-rural"
1134
+ ];
1135
+ function isSanitizableType(type) {
1136
+ return SANITIZABLE_TYPES.includes(type);
1137
+ }
1138
+ function resolveInput17(value, fileContent) {
1139
+ const input = value ?? fileContent?.trim();
1140
+ if (!input) {
1141
+ return null;
1142
+ }
1143
+ return input;
1144
+ }
1145
+ function printSanitize(result, options, io = { stdout: [], stderr: [] }) {
626
1146
  if (options.json) {
627
- io.stdout.push(
628
- JSON.stringify(
629
- result.ok ? {
630
- ok: true,
631
- value: result.value,
632
- uf: result.uf,
633
- format: result.format,
634
- ...options.source ? { source: options.source } : {}
635
- } : {
636
- ok: false,
637
- code: result.code,
638
- message: result.message,
639
- ...result.uf ? { uf: result.uf } : {}
640
- },
641
- null,
642
- 2
643
- )
644
- );
1147
+ io.stdout.push(JSON.stringify(result, null, 2));
645
1148
  return result.ok ? EXIT.OK : EXIT.INVALID;
646
1149
  }
647
1150
  if (options.quiet) {
648
1151
  return result.ok ? EXIT.OK : EXIT.INVALID;
649
1152
  }
650
1153
  if (result.ok) {
651
- io.stdout.push(`valid: yes (${result.uf})`);
1154
+ io.stdout.push("valid: yes");
652
1155
  io.stdout.push(`value: ${result.value}`);
653
- io.stdout.push(`format: ${result.format}`);
654
- if (options.source) {
655
- io.stdout.push(`source: ${options.source}`);
656
- }
1156
+ io.stdout.push(`fixes: ${result.fixes.join(", ")}`);
657
1157
  return EXIT.OK;
658
1158
  }
659
1159
  io.stderr.push("valid: no");
660
1160
  io.stderr.push(`code: ${result.code}`);
661
1161
  io.stderr.push(`message: ${result.message}`);
662
- if (result.uf) {
663
- io.stderr.push(`uf: ${result.uf}`);
664
- }
665
1162
  return EXIT.INVALID;
666
1163
  }
667
- function runIeCommand(action, input, options, io = { stdout: [], stderr: [] }) {
668
- const uf = resolveUf(options.uf);
669
- if (!uf) {
670
- io.stderr.push(`Missing or invalid --uf. Use one of: ${IE_SUPPORTED_UFS.join(", ")}.`);
1164
+ function runSanitize(type, value, options, io = { stdout: [], stderr: [] }) {
1165
+ if (!isSanitizableType(type)) {
1166
+ io.stderr.push(`Unsupported sanitize type: ${type}`);
671
1167
  return EXIT.USAGE;
672
1168
  }
673
- const source = options.source ? getIeOfficialSourceUrl(uf) : void 0;
674
- switch (action) {
675
- case "validate":
676
- return printIeValidation(validateInscricaoEstadual(input, { uf }), { json: options.json, quiet: options.quiet, source }, io);
677
- case "format":
678
- return printFormat(formatInscricaoEstadual(input, { uf }), { json: options.json, quiet: options.quiet }, io);
679
- case "strip":
680
- return printStrip(stripInscricaoEstadual(input), { json: options.json }, io);
681
- default: {
682
- const _exhaustive = action;
683
- io.stderr.push(`Unknown action: ${_exhaustive}`);
684
- return EXIT.USAGE;
685
- }
1169
+ const input = resolveInput17(value, options.file);
1170
+ if (input === null) {
1171
+ io.stderr.push("Missing value. Pass an argument or use --file.");
1172
+ return EXIT.USAGE;
686
1173
  }
1174
+ const uf = options.uf?.toUpperCase();
1175
+ const result = sanitize(input, type, uf ? { uf } : {});
1176
+ return printSanitize(result, options, io);
687
1177
  }
688
- function runIe(action, value, options, io = { stdout: [], stderr: [] }) {
689
- const input = resolveInput9(value, options.file);
690
- if (input === null) {
691
- io.stderr.push("Missing IE value. Pass an argument or use --file.");
1178
+
1179
+ // src/commands/generate.ts
1180
+ import { generate } from "@br-validators/core";
1181
+ var GENERATABLE_TYPES = [
1182
+ "cpf",
1183
+ "cnpj",
1184
+ "cep",
1185
+ "placa",
1186
+ "pis-pasep",
1187
+ "renavam",
1188
+ "cnh",
1189
+ "telefone",
1190
+ "cartao-credito"
1191
+ ];
1192
+ function isGeneratableType(type) {
1193
+ return GENERATABLE_TYPES.includes(type);
1194
+ }
1195
+ function buildGenerateOptions(options) {
1196
+ const core = {};
1197
+ if (options.masked) {
1198
+ core.masked = true;
1199
+ }
1200
+ if (options.seed !== void 0) {
1201
+ core.seed = options.seed;
1202
+ }
1203
+ if (options.format) {
1204
+ core.format = options.format;
1205
+ }
1206
+ return core;
1207
+ }
1208
+ function printGenerate(value, options, io = { stdout: [], stderr: [] }) {
1209
+ if (options.json) {
1210
+ io.stdout.push(JSON.stringify({ ok: true, value }, null, 2));
1211
+ return EXIT.OK;
1212
+ }
1213
+ if (options.quiet) {
1214
+ return EXIT.OK;
1215
+ }
1216
+ io.stdout.push(value);
1217
+ return EXIT.OK;
1218
+ }
1219
+ function runGenerate(type, options, io = { stdout: [], stderr: [] }) {
1220
+ if (!isGeneratableType(type)) {
1221
+ io.stderr.push(`Unsupported generate type: ${type}`);
692
1222
  return EXIT.USAGE;
693
1223
  }
694
- return runIeCommand(action, input, options, io);
1224
+ const value = generate(type, buildGenerateOptions(options));
1225
+ return printGenerate(value, options, io);
695
1226
  }
696
1227
 
697
1228
  // src/commands/list.ts
@@ -777,6 +1308,48 @@ function handleCepCli(action, value, opts, io = { stdout: [], stderr: [] }) {
777
1308
  io
778
1309
  );
779
1310
  }
1311
+ function handleTelefoneCli(action, value, opts, io = { stdout: [], stderr: [] }) {
1312
+ let fileContent;
1313
+ if (opts.file) {
1314
+ const content = readInputFile(opts.file, io);
1315
+ if (content === null) {
1316
+ return EXIT.USAGE;
1317
+ }
1318
+ fileContent = content;
1319
+ }
1320
+ return runTelefone(
1321
+ action,
1322
+ value,
1323
+ {
1324
+ json: Boolean(opts.json),
1325
+ quiet: Boolean(opts.quiet),
1326
+ source: Boolean(opts.source),
1327
+ file: fileContent
1328
+ },
1329
+ io
1330
+ );
1331
+ }
1332
+ function handleCnhCli(action, value, opts, io = { stdout: [], stderr: [] }) {
1333
+ let fileContent;
1334
+ if (opts.file) {
1335
+ const content = readInputFile(opts.file, io);
1336
+ if (content === null) {
1337
+ return EXIT.USAGE;
1338
+ }
1339
+ fileContent = content;
1340
+ }
1341
+ return runCnh(
1342
+ action,
1343
+ value,
1344
+ {
1345
+ json: Boolean(opts.json),
1346
+ quiet: Boolean(opts.quiet),
1347
+ source: Boolean(opts.source),
1348
+ file: fileContent
1349
+ },
1350
+ io
1351
+ );
1352
+ }
780
1353
  function handlePlacaCli(action, value, opts, io = { stdout: [], stderr: [] }) {
781
1354
  let fileContent;
782
1355
  if (opts.file) {
@@ -906,6 +1479,90 @@ function handleCartaoCreditoCli(action, value, opts, io = { stdout: [], stderr:
906
1479
  io
907
1480
  );
908
1481
  }
1482
+ function handleRenavamCli(action, value, opts, io = { stdout: [], stderr: [] }) {
1483
+ let fileContent;
1484
+ if (opts.file) {
1485
+ const content = readInputFile(opts.file, io);
1486
+ if (content === null) {
1487
+ return EXIT.USAGE;
1488
+ }
1489
+ fileContent = content;
1490
+ }
1491
+ return runRenavam(
1492
+ action,
1493
+ value,
1494
+ {
1495
+ json: Boolean(opts.json),
1496
+ quiet: Boolean(opts.quiet),
1497
+ source: Boolean(opts.source),
1498
+ file: fileContent
1499
+ },
1500
+ io
1501
+ );
1502
+ }
1503
+ function handleTituloEleitorCli(action, value, opts, io = { stdout: [], stderr: [] }) {
1504
+ let fileContent;
1505
+ if (opts.file) {
1506
+ const content = readInputFile(opts.file, io);
1507
+ if (content === null) {
1508
+ return EXIT.USAGE;
1509
+ }
1510
+ fileContent = content;
1511
+ }
1512
+ return runTituloEleitor(
1513
+ action,
1514
+ value,
1515
+ {
1516
+ json: Boolean(opts.json),
1517
+ quiet: Boolean(opts.quiet),
1518
+ source: Boolean(opts.source),
1519
+ file: fileContent
1520
+ },
1521
+ io
1522
+ );
1523
+ }
1524
+ function handleNfeChaveCli(action, value, opts, io = { stdout: [], stderr: [] }) {
1525
+ let fileContent;
1526
+ if (opts.file) {
1527
+ const content = readInputFile(opts.file, io);
1528
+ if (content === null) {
1529
+ return EXIT.USAGE;
1530
+ }
1531
+ fileContent = content;
1532
+ }
1533
+ return runNfeChave(
1534
+ action,
1535
+ value,
1536
+ {
1537
+ json: Boolean(opts.json),
1538
+ quiet: Boolean(opts.quiet),
1539
+ source: Boolean(opts.source),
1540
+ file: fileContent
1541
+ },
1542
+ io
1543
+ );
1544
+ }
1545
+ function handleBrCodeCli(action, value, opts, io = { stdout: [], stderr: [] }) {
1546
+ let fileContent;
1547
+ if (opts.file) {
1548
+ const content = readInputFile(opts.file, io);
1549
+ if (content === null) {
1550
+ return EXIT.USAGE;
1551
+ }
1552
+ fileContent = content;
1553
+ }
1554
+ return runBrCode(
1555
+ action,
1556
+ value,
1557
+ {
1558
+ json: Boolean(opts.json),
1559
+ quiet: Boolean(opts.quiet),
1560
+ source: Boolean(opts.source),
1561
+ file: fileContent
1562
+ },
1563
+ io
1564
+ );
1565
+ }
909
1566
  function handleIeCli(action, value, opts, io = { stdout: [], stderr: [] }) {
910
1567
  let fileContent;
911
1568
  if (opts.file) {
@@ -928,6 +1585,60 @@ function handleIeCli(action, value, opts, io = { stdout: [], stderr: [] }) {
928
1585
  io
929
1586
  );
930
1587
  }
1588
+ function handleDetectCli(value, opts, io = { stdout: [], stderr: [] }) {
1589
+ let fileContent;
1590
+ if (opts.file) {
1591
+ const content = readInputFile(opts.file, io);
1592
+ if (content === null) {
1593
+ return EXIT.USAGE;
1594
+ }
1595
+ fileContent = content;
1596
+ }
1597
+ return runDetect(
1598
+ value,
1599
+ {
1600
+ json: Boolean(opts.json),
1601
+ quiet: Boolean(opts.quiet),
1602
+ uf: opts.uf,
1603
+ file: fileContent
1604
+ },
1605
+ io
1606
+ );
1607
+ }
1608
+ function handleSanitizeCli(type, value, opts, io = { stdout: [], stderr: [] }) {
1609
+ let fileContent;
1610
+ if (opts.file) {
1611
+ const content = readInputFile(opts.file, io);
1612
+ if (content === null) {
1613
+ return EXIT.USAGE;
1614
+ }
1615
+ fileContent = content;
1616
+ }
1617
+ return runSanitize(
1618
+ type,
1619
+ value,
1620
+ {
1621
+ json: Boolean(opts.json),
1622
+ quiet: Boolean(opts.quiet),
1623
+ uf: opts.uf,
1624
+ file: fileContent
1625
+ },
1626
+ io
1627
+ );
1628
+ }
1629
+ function handleGenerateCli(type, opts, io = { stdout: [], stderr: [] }) {
1630
+ return runGenerate(
1631
+ type,
1632
+ {
1633
+ json: Boolean(opts.json),
1634
+ quiet: Boolean(opts.quiet),
1635
+ masked: Boolean(opts.masked),
1636
+ format: opts.format,
1637
+ seed: opts.seed
1638
+ },
1639
+ io
1640
+ );
1641
+ }
931
1642
  function writeCliIo(io) {
932
1643
  for (const line of io.stdout) console.log(line);
933
1644
  for (const line of io.stderr) console.error(line);
@@ -966,6 +1677,54 @@ function createProgram() {
966
1677
  writeCliIo(io);
967
1678
  });
968
1679
  }
1680
+ const telefone = program.command("telefone").description("Telefone \u2014 Brazilian fixo/celular (Anatel DDD)");
1681
+ for (const action of ["validate", "format", "strip"]) {
1682
+ telefone.command(action).description(`${action} a Brazilian telephone number`).argument("[value]", "Telephone value (raw or masked)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL (validate only)").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1683
+ const io = { stdout: [], stderr: [] };
1684
+ process.exitCode = handleTelefoneCli(action, value, opts, io);
1685
+ writeCliIo(io);
1686
+ });
1687
+ }
1688
+ const cnh = program.command("cnh").description("CNH \u2014 Registro Nacional, 11 contiguous digits (CONTRAN / SENATRAN)");
1689
+ for (const action of ["validate", "format", "strip"]) {
1690
+ cnh.command(action).description(`${action} a CNH`).argument("[value]", "CNH value (11 digits or decorated input)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL (validate only)").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1691
+ const io = { stdout: [], stderr: [] };
1692
+ process.exitCode = handleCnhCli(action, value, opts, io);
1693
+ writeCliIo(io);
1694
+ });
1695
+ }
1696
+ const renavam = program.command("renavam").description("RENAVAM \u2014 11-digit vehicle registry code (DENATRAN / SENATRAN)");
1697
+ for (const action of ["validate", "format", "strip"]) {
1698
+ renavam.command(action).description(`${action} a RENAVAM`).argument("[value]", "RENAVAM value (11 digits or optional dash before DV)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL (validate only)").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1699
+ const io = { stdout: [], stderr: [] };
1700
+ process.exitCode = handleRenavamCli(action, value, opts, io);
1701
+ writeCliIo(io);
1702
+ });
1703
+ }
1704
+ const tituloEleitor = program.command("titulo-eleitor").description("T\xEDtulo de Eleitor \u2014 12-digit voter registration (TSE / Wikipedia PT algorithm)");
1705
+ for (const action of ["validate", "format", "strip"]) {
1706
+ tituloEleitor.command(action).description(`${action} a T\xEDtulo de Eleitor`).argument("[value]", "T\xEDtulo de Eleitor value (12 or 13 digits, spaces allowed)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL (validate only)").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1707
+ const io = { stdout: [], stderr: [] };
1708
+ process.exitCode = handleTituloEleitorCli(action, value, opts, io);
1709
+ writeCliIo(io);
1710
+ });
1711
+ }
1712
+ const nfeChave = program.command("nfe-chave").description("NF-e / NFC-e chave de acesso \u2014 44 digits (SEFAZ MOC \xA72.2.6)");
1713
+ for (const action of ["validate", "parse", "format", "strip"]) {
1714
+ nfeChave.command(action).description(`${action} an NF-e chave de acesso`).argument("[value]", "Chave de acesso (44 digits, spaces allowed)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL (validate/parse only)").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1715
+ const io = { stdout: [], stderr: [] };
1716
+ process.exitCode = handleNfeChaveCli(action, value, opts, io);
1717
+ writeCliIo(io);
1718
+ });
1719
+ }
1720
+ const brcode = program.command("brcode").description("BR Code \u2014 PIX QR payload (Bacen EMV TLV)");
1721
+ for (const action of ["parse", "validate"]) {
1722
+ brcode.command(action).description(`${action} a BR Code payload`).argument("[value]", "BR Code payload (Pix Copia e Cola)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1723
+ const io = { stdout: [], stderr: [] };
1724
+ process.exitCode = handleBrCodeCli(action, value, opts, io);
1725
+ writeCliIo(io);
1726
+ });
1727
+ }
969
1728
  const placa = program.command("placa").description("Placa \u2014 legacy + Mercosul (CONTRAN)");
970
1729
  for (const action of ["validate", "format", "strip", "convert"]) {
971
1730
  placa.command(action).description(`${action} a license plate`).argument("[value]", "Placa value (raw or masked)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL (validate only)").option("-f, --file <path>", "Read value from file").action((value, opts) => {
@@ -1053,6 +1812,21 @@ function createProgram() {
1053
1812
  writeCliIo(io);
1054
1813
  });
1055
1814
  }
1815
+ program.command("detect").description("Detect document type from raw input").argument("[value]", "Raw value to classify").option("--uf <uf>", "State code for Inscri\xE7\xE3o Estadual detection").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1816
+ const io = { stdout: [], stderr: [] };
1817
+ process.exitCode = handleDetectCli(value, opts, io);
1818
+ writeCliIo(io);
1819
+ });
1820
+ program.command("sanitize <type> [value]").description("Sanitize messy input then validate").option("--uf <uf>", "State code (required for inscricao-estadual)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((type, value, opts) => {
1821
+ const io = { stdout: [], stderr: [] };
1822
+ process.exitCode = handleSanitizeCli(type, value, opts, io);
1823
+ writeCliIo(io);
1824
+ });
1825
+ program.command("generate <type>").description("Generate synthetic valid test document").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--masked", "Return masked/formatted output").option("--format <format>", "Format variant (numeric, alphanumeric, legacy, mercosul, celular, fixo)").option("--seed <number>", "Deterministic PRNG seed", (v) => Number(v)).action((type, opts) => {
1826
+ const io = { stdout: [], stderr: [] };
1827
+ process.exitCode = handleGenerateCli(type, opts, io);
1828
+ writeCliIo(io);
1829
+ });
1056
1830
  return program;
1057
1831
  }
1058
1832
  function run(argv) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@br-validators/cli",
3
- "version": "0.10.0-alpha.1",
3
+ "version": "0.12.0-alpha.0",
4
4
  "description": "Terminal CLI for Brazilian document validation — CPF, CNPJ, CEP, IE, PIX, boleto, and more",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "commander": "^13.1.0",
32
- "@br-validators/core": "0.10.0-alpha.0"
32
+ "@br-validators/core": "0.12.0-alpha.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^22.15.21",
@@ -44,6 +44,8 @@
44
44
  ],
45
45
  "scripts": {
46
46
  "build": "tsup",
47
+ "pretest": "pnpm run build",
48
+ "pretest:coverage": "pnpm run build",
47
49
  "pretypecheck": "pnpm --filter @br-validators/core build",
48
50
  "test": "vitest run",
49
51
  "test:coverage": "vitest run --coverage",