@br-validators/cli 0.10.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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/index.js +1064 -0
  4. package/package.json +52 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BR Validators contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # @br-validators/cli
2
+
3
+ Terminal CLI for all Brazilian document validators in [@br-validators/core](https://www.npmjs.com/package/@br-validators/core).
4
+
5
+ ---
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g @br-validators/cli
11
+ ```
12
+
13
+ Or run without install:
14
+
15
+ ```bash
16
+ npx @br-validators/cli --help
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Commands
22
+
23
+ ```bash
24
+ br-validators list
25
+ br-validators --version
26
+
27
+ br-validators cnpj validate 12ABC34501DE35 --json --source
28
+ br-validators cpf validate 12345678909
29
+ br-validators cep format 01310100
30
+ br-validators placa validate ABC1D23
31
+ br-validators pis-pasep validate 10027230888
32
+ br-validators pix validate pix@bcb.gov.br
33
+ br-validators boleto validate <linha-ou-barcode>
34
+ br-validators cartao validate 4111111111111111
35
+ br-validators ie validate 110042490114 --uf SP --json
36
+ ```
37
+
38
+ ### Actions (all types)
39
+
40
+ | Action | Description |
41
+ |--------|-------------|
42
+ | `validate` | Check format + check digits |
43
+ | `format` | Apply official mask |
44
+ | `strip` | Normalize to canonical digits/chars |
45
+
46
+ ### Flags
47
+
48
+ | Flag | Description |
49
+ |------|-------------|
50
+ | `--json` | JSON output (`ValidationResult`) |
51
+ | `--quiet` / `-q` | Exit code only (CI) |
52
+ | `--file` / `-f` | Read value from file |
53
+ | `--source` | Print official source URL |
54
+ | `--uf` | Required for IE (27 UFs) |
55
+
56
+ ### CI
57
+
58
+ ```bash
59
+ br-validators cnpj validate "$CNPJ" --quiet || exit 1
60
+ ```
61
+
62
+ ---
63
+
64
+ ## License
65
+
66
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,1064 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+
4
+ // src/program.ts
5
+ import { Command } from "commander";
6
+
7
+ // src/handlers.ts
8
+ import { readFileSync } from "fs";
9
+
10
+ // src/commands/cep.ts
11
+ import {
12
+ CEP_OFFICIAL_SOURCE_URL,
13
+ formatCep,
14
+ stripCep,
15
+ validateCep
16
+ } from "@br-validators/core";
17
+
18
+ // src/constants.ts
19
+ var SUPPORTED_TYPES = ["cnpj", "cpf", "cep", "placa", "pis-pasep", "pix", "boleto", "cartao", "ie"];
20
+ var EXIT = {
21
+ OK: 0,
22
+ INVALID: 1,
23
+ USAGE: 2
24
+ };
25
+
26
+ // src/output.ts
27
+ function printValidation(result, options, io = { stdout: [], stderr: [] }) {
28
+ if (options.json) {
29
+ io.stdout.push(
30
+ JSON.stringify(
31
+ result.ok ? {
32
+ ok: true,
33
+ value: result.value,
34
+ format: result.format,
35
+ ...options.source ? { source: options.source } : {}
36
+ } : { ok: false, code: result.code, message: result.message },
37
+ null,
38
+ 2
39
+ )
40
+ );
41
+ return result.ok ? EXIT.OK : EXIT.INVALID;
42
+ }
43
+ if (options.quiet) {
44
+ return result.ok ? EXIT.OK : EXIT.INVALID;
45
+ }
46
+ if (result.ok) {
47
+ io.stdout.push(`valid: yes (${result.format})`);
48
+ io.stdout.push(`value: ${result.value}`);
49
+ if (options.source) {
50
+ io.stdout.push(`source: ${options.source}`);
51
+ }
52
+ return EXIT.OK;
53
+ }
54
+ io.stderr.push("valid: no");
55
+ io.stderr.push(`code: ${result.code}`);
56
+ io.stderr.push(`message: ${result.message}`);
57
+ return EXIT.INVALID;
58
+ }
59
+ function printFormat(result, options, io = { stdout: [], stderr: [] }) {
60
+ if (options.json) {
61
+ io.stdout.push(JSON.stringify(result, null, 2));
62
+ return result.ok ? EXIT.OK : EXIT.INVALID;
63
+ }
64
+ if (options.quiet) {
65
+ return result.ok ? EXIT.OK : EXIT.INVALID;
66
+ }
67
+ if (result.ok) {
68
+ io.stdout.push(result.formatted);
69
+ return EXIT.OK;
70
+ }
71
+ io.stderr.push(`code: ${result.code}`);
72
+ io.stderr.push(`message: ${result.message}`);
73
+ return EXIT.INVALID;
74
+ }
75
+ function printStrip(value, options, io = { stdout: [] }) {
76
+ if (options.json) {
77
+ io.stdout.push(JSON.stringify({ stripped: value }, null, 2));
78
+ } else {
79
+ io.stdout.push(value);
80
+ }
81
+ return EXIT.OK;
82
+ }
83
+
84
+ // src/commands/cep.ts
85
+ function resolveInput(value, fileContent) {
86
+ const input = value ?? fileContent?.trim();
87
+ if (!input) {
88
+ return null;
89
+ }
90
+ return input;
91
+ }
92
+ function runCepCommand(action, input, options, io = { stdout: [], stderr: [] }) {
93
+ const source = options.source ? CEP_OFFICIAL_SOURCE_URL : void 0;
94
+ switch (action) {
95
+ case "validate":
96
+ return printValidation(validateCep(input), { json: options.json, quiet: options.quiet, source }, io);
97
+ case "format":
98
+ return printFormat(formatCep(input), { json: options.json, quiet: options.quiet }, io);
99
+ case "strip":
100
+ return printStrip(stripCep(input), { json: options.json }, io);
101
+ default: {
102
+ const _exhaustive = action;
103
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
104
+ return EXIT.USAGE;
105
+ }
106
+ }
107
+ }
108
+ function runCep(action, value, options, io = { stdout: [], stderr: [] }) {
109
+ const input = resolveInput(value, options.file);
110
+ if (input === null) {
111
+ io.stderr.push("Missing CEP value. Pass an argument or use --file.");
112
+ return EXIT.USAGE;
113
+ }
114
+ return runCepCommand(action, input, options, io);
115
+ }
116
+
117
+ // src/commands/cnpj.ts
118
+ import {
119
+ CNPJ_OFFICIAL_SOURCE_URL,
120
+ formatCnpj,
121
+ stripCnpj,
122
+ validateCnpj
123
+ } from "@br-validators/core";
124
+ function resolveInput2(value, fileContent) {
125
+ const input = value ?? fileContent?.trim();
126
+ if (!input) {
127
+ return null;
128
+ }
129
+ return input;
130
+ }
131
+ function runCnpjCommand(action, input, options, io = { stdout: [], stderr: [] }) {
132
+ const source = options.source ? CNPJ_OFFICIAL_SOURCE_URL : void 0;
133
+ switch (action) {
134
+ case "validate":
135
+ return printValidation(validateCnpj(input), { json: options.json, quiet: options.quiet, source }, io);
136
+ case "format":
137
+ return printFormat(formatCnpj(input), { json: options.json, quiet: options.quiet }, io);
138
+ case "strip":
139
+ return printStrip(stripCnpj(input), { json: options.json }, io);
140
+ default: {
141
+ const _exhaustive = action;
142
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
143
+ return EXIT.USAGE;
144
+ }
145
+ }
146
+ }
147
+ function runCnpj(action, value, options, io = { stdout: [], stderr: [] }) {
148
+ const input = resolveInput2(value, options.file);
149
+ if (input === null) {
150
+ io.stderr.push("Missing CNPJ value. Pass an argument or use --file.");
151
+ return EXIT.USAGE;
152
+ }
153
+ return runCnpjCommand(action, input, options, io);
154
+ }
155
+
156
+ // src/commands/cpf.ts
157
+ import {
158
+ CPF_OFFICIAL_SOURCE_URL,
159
+ formatCpf,
160
+ stripCpf,
161
+ validateCpf
162
+ } from "@br-validators/core";
163
+ function resolveInput3(value, fileContent) {
164
+ const input = value ?? fileContent?.trim();
165
+ if (!input) {
166
+ return null;
167
+ }
168
+ return input;
169
+ }
170
+ function runCpfCommand(action, input, options, io = { stdout: [], stderr: [] }) {
171
+ const source = options.source ? CPF_OFFICIAL_SOURCE_URL : void 0;
172
+ switch (action) {
173
+ case "validate":
174
+ return printValidation(validateCpf(input), { json: options.json, quiet: options.quiet, source }, io);
175
+ case "format":
176
+ return printFormat(formatCpf(input), { json: options.json, quiet: options.quiet }, io);
177
+ case "strip":
178
+ return printStrip(stripCpf(input), { json: options.json }, io);
179
+ default: {
180
+ const _exhaustive = action;
181
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
182
+ return EXIT.USAGE;
183
+ }
184
+ }
185
+ }
186
+ function runCpf(action, value, options, io = { stdout: [], stderr: [] }) {
187
+ const input = resolveInput3(value, options.file);
188
+ if (input === null) {
189
+ io.stderr.push("Missing CPF value. Pass an argument or use --file.");
190
+ return EXIT.USAGE;
191
+ }
192
+ return runCpfCommand(action, input, options, io);
193
+ }
194
+
195
+ // src/commands/placa.ts
196
+ import {
197
+ PLACA_OFFICIAL_SOURCE_URL,
198
+ convertPlacaToMercosul,
199
+ formatPlaca,
200
+ stripPlaca,
201
+ validatePlaca
202
+ } from "@br-validators/core";
203
+ function resolveInput4(value, fileContent) {
204
+ const input = value ?? fileContent?.trim();
205
+ if (!input) {
206
+ return null;
207
+ }
208
+ return input;
209
+ }
210
+ function runPlacaCommand(action, input, options, io = { stdout: [], stderr: [] }) {
211
+ const source = options.source ? PLACA_OFFICIAL_SOURCE_URL : void 0;
212
+ switch (action) {
213
+ case "validate":
214
+ return printValidation(validatePlaca(input), { json: options.json, quiet: options.quiet, source }, io);
215
+ case "format":
216
+ return printFormat(formatPlaca(input), { json: options.json, quiet: options.quiet }, io);
217
+ case "convert":
218
+ return printFormat(convertPlacaToMercosul(input), { json: options.json, quiet: options.quiet }, io);
219
+ case "strip":
220
+ return printStrip(stripPlaca(input), { json: options.json }, io);
221
+ default: {
222
+ const _exhaustive = action;
223
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
224
+ return EXIT.USAGE;
225
+ }
226
+ }
227
+ }
228
+ function runPlaca(action, value, options, io = { stdout: [], stderr: [] }) {
229
+ const input = resolveInput4(value, options.file);
230
+ if (input === null) {
231
+ io.stderr.push("Missing placa value. Pass an argument or use --file.");
232
+ return EXIT.USAGE;
233
+ }
234
+ return runPlacaCommand(action, input, options, io);
235
+ }
236
+
237
+ // src/commands/pis-pasep.ts
238
+ import {
239
+ PIS_PASEP_OFFICIAL_SOURCE_URL,
240
+ formatPisPasep,
241
+ stripPisPasep,
242
+ validatePisPasep
243
+ } from "@br-validators/core";
244
+ function resolveInput5(value, fileContent) {
245
+ const input = value ?? fileContent?.trim();
246
+ if (!input) {
247
+ return null;
248
+ }
249
+ return input;
250
+ }
251
+ function runPisPasepCommand(action, input, options, io = { stdout: [], stderr: [] }) {
252
+ const source = options.source ? PIS_PASEP_OFFICIAL_SOURCE_URL : void 0;
253
+ switch (action) {
254
+ case "validate":
255
+ return printValidation(validatePisPasep(input), { json: options.json, quiet: options.quiet, source }, io);
256
+ case "format":
257
+ return printFormat(formatPisPasep(input), { json: options.json, quiet: options.quiet }, io);
258
+ case "strip":
259
+ return printStrip(stripPisPasep(input), { json: options.json }, io);
260
+ default: {
261
+ const _exhaustive = action;
262
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
263
+ return EXIT.USAGE;
264
+ }
265
+ }
266
+ }
267
+ function runPisPasep(action, value, options, io = { stdout: [], stderr: [] }) {
268
+ const input = resolveInput5(value, options.file);
269
+ if (input === null) {
270
+ io.stderr.push("Missing PIS/PASEP value. Pass an argument or use --file.");
271
+ return EXIT.USAGE;
272
+ }
273
+ return runPisPasepCommand(action, input, options, io);
274
+ }
275
+
276
+ // src/commands/pix.ts
277
+ import {
278
+ PIX_OFFICIAL_SOURCE_URL,
279
+ detectPixKeyType,
280
+ formatPixKey,
281
+ validatePixKey
282
+ } from "@br-validators/core";
283
+ function resolveInput6(value, fileContent) {
284
+ const input = value ?? fileContent?.trim();
285
+ if (!input) {
286
+ return null;
287
+ }
288
+ return input;
289
+ }
290
+ function printPixValidation(result, options, io = { stdout: [], stderr: [] }) {
291
+ if (options.json) {
292
+ io.stdout.push(
293
+ JSON.stringify(
294
+ result.ok ? {
295
+ ok: true,
296
+ value: result.value,
297
+ keyType: result.keyType,
298
+ format: result.format,
299
+ ...options.source ? { source: options.source } : {}
300
+ } : {
301
+ ok: false,
302
+ code: result.code,
303
+ message: result.message,
304
+ ...result.keyType ? { keyType: result.keyType } : {}
305
+ },
306
+ null,
307
+ 2
308
+ )
309
+ );
310
+ return result.ok ? EXIT.OK : EXIT.INVALID;
311
+ }
312
+ if (options.quiet) {
313
+ return result.ok ? EXIT.OK : EXIT.INVALID;
314
+ }
315
+ if (result.ok) {
316
+ io.stdout.push(`valid: yes (${result.keyType})`);
317
+ io.stdout.push(`value: ${result.value}`);
318
+ io.stdout.push(`format: ${result.format}`);
319
+ if (options.source) {
320
+ io.stdout.push(`source: ${options.source}`);
321
+ }
322
+ return EXIT.OK;
323
+ }
324
+ io.stderr.push("valid: no");
325
+ io.stderr.push(`code: ${result.code}`);
326
+ io.stderr.push(`message: ${result.message}`);
327
+ if (result.keyType) {
328
+ io.stderr.push(`keyType: ${result.keyType}`);
329
+ }
330
+ return EXIT.INVALID;
331
+ }
332
+ function printPixDetect(keyType, options, io = { stdout: [] }) {
333
+ if (options.json) {
334
+ io.stdout.push(JSON.stringify({ keyType }, null, 2));
335
+ } else if (!options.quiet) {
336
+ io.stdout.push(keyType);
337
+ }
338
+ return EXIT.OK;
339
+ }
340
+ function runPixCommand(action, input, options, io = { stdout: [], stderr: [] }) {
341
+ const source = options.source ? PIX_OFFICIAL_SOURCE_URL : void 0;
342
+ const validateOptions = options.type ? { type: options.type } : void 0;
343
+ switch (action) {
344
+ case "validate":
345
+ return printPixValidation(validatePixKey(input, validateOptions), { json: options.json, quiet: options.quiet, source }, io);
346
+ case "format":
347
+ return printFormat(formatPixKey(input, validateOptions), { json: options.json, quiet: options.quiet }, io);
348
+ case "detect":
349
+ return printPixDetect(detectPixKeyType(input), { json: options.json, quiet: options.quiet }, io);
350
+ default: {
351
+ const _exhaustive = action;
352
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
353
+ return EXIT.USAGE;
354
+ }
355
+ }
356
+ }
357
+ function runPix(action, value, options, io = { stdout: [], stderr: [] }) {
358
+ const input = resolveInput6(value, options.file);
359
+ if (input === null) {
360
+ io.stderr.push("Missing PIX key value. Pass an argument or use --file.");
361
+ return EXIT.USAGE;
362
+ }
363
+ return runPixCommand(action, input, options, io);
364
+ }
365
+
366
+ // src/commands/boleto.ts
367
+ import {
368
+ BOLETO_OFFICIAL_SOURCE_URL,
369
+ convertCodigoBarrasToLinhaDigitavel,
370
+ convertLinhaToCodigoBarras,
371
+ detectBoletoInputKind,
372
+ formatBoleto,
373
+ stripCodigoBarras,
374
+ stripLinhaDigitavel,
375
+ validateBoleto
376
+ } from "@br-validators/core";
377
+ function resolveInput7(value, fileContent) {
378
+ const input = value ?? fileContent?.trim();
379
+ if (!input) {
380
+ return null;
381
+ }
382
+ return input;
383
+ }
384
+ function printBoletoValidation(result, options, io = { stdout: [], stderr: [] }) {
385
+ if (options.json) {
386
+ io.stdout.push(
387
+ JSON.stringify(
388
+ result.ok ? {
389
+ ok: true,
390
+ value: result.value,
391
+ inputKind: result.inputKind,
392
+ format: result.format,
393
+ situacao: result.situacao,
394
+ ...options.source ? { source: options.source } : {}
395
+ } : {
396
+ ok: false,
397
+ code: result.code,
398
+ message: result.message,
399
+ ...result.inputKind ? { inputKind: result.inputKind } : {}
400
+ },
401
+ null,
402
+ 2
403
+ )
404
+ );
405
+ return result.ok ? EXIT.OK : EXIT.INVALID;
406
+ }
407
+ if (options.quiet) {
408
+ return result.ok ? EXIT.OK : EXIT.INVALID;
409
+ }
410
+ if (result.ok) {
411
+ io.stdout.push(`valid: yes (${result.inputKind})`);
412
+ io.stdout.push(`value: ${result.value}`);
413
+ io.stdout.push(`format: ${result.format}`);
414
+ io.stdout.push(`situacao: ${result.situacao}`);
415
+ if (options.source) {
416
+ io.stdout.push(`source: ${options.source}`);
417
+ }
418
+ return EXIT.OK;
419
+ }
420
+ io.stderr.push("valid: no");
421
+ io.stderr.push(`code: ${result.code}`);
422
+ io.stderr.push(`message: ${result.message}`);
423
+ if (result.inputKind) {
424
+ io.stderr.push(`inputKind: ${result.inputKind}`);
425
+ }
426
+ return EXIT.INVALID;
427
+ }
428
+ function printBoletoDetect(inputKind, options, io = { stdout: [] }) {
429
+ if (options.json) {
430
+ io.stdout.push(JSON.stringify({ inputKind }, null, 2));
431
+ } else if (!options.quiet) {
432
+ io.stdout.push(inputKind);
433
+ }
434
+ return EXIT.OK;
435
+ }
436
+ function printBoletoConvert(result, options, io = { stdout: [], stderr: [] }) {
437
+ if (options.json) {
438
+ io.stdout.push(
439
+ JSON.stringify(
440
+ result.ok ? { ok: true, value: result.value, inputKind: result.inputKind, format: result.format } : { ok: false, code: result.code, message: result.message, ...result.inputKind ? { inputKind: result.inputKind } : {} },
441
+ null,
442
+ 2
443
+ )
444
+ );
445
+ return result.ok ? EXIT.OK : EXIT.INVALID;
446
+ }
447
+ if (options.quiet) {
448
+ return result.ok ? EXIT.OK : EXIT.INVALID;
449
+ }
450
+ if (result.ok) {
451
+ io.stdout.push(result.value);
452
+ return EXIT.OK;
453
+ }
454
+ io.stderr.push(`code: ${result.code}`);
455
+ io.stderr.push(`message: ${result.message}`);
456
+ return EXIT.INVALID;
457
+ }
458
+ function printBoletoFormat(input, options, io = { stdout: [], stderr: [] }) {
459
+ return printFormat(formatBoleto(input), { json: options.json, quiet: options.quiet }, io);
460
+ }
461
+ function printBoletoStrip(input, options, io = { stdout: [] }) {
462
+ const kind = detectBoletoInputKind(input);
463
+ const stripped = kind === "codigo-barras" ? stripCodigoBarras(input) : stripLinhaDigitavel(input);
464
+ if (options.json) {
465
+ io.stdout.push(JSON.stringify({ stripped, inputKind: kind }, null, 2));
466
+ } else if (!options.quiet) {
467
+ io.stdout.push(stripped);
468
+ }
469
+ return EXIT.OK;
470
+ }
471
+ function runBoletoCommand(action, input, options, direction, io = { stdout: [], stderr: [] }) {
472
+ const source = options.source ? BOLETO_OFFICIAL_SOURCE_URL : void 0;
473
+ const validateOptions = options.kind ? { kind: options.kind } : void 0;
474
+ switch (action) {
475
+ case "validate":
476
+ return printBoletoValidation(validateBoleto(input, validateOptions), { json: options.json, quiet: options.quiet, source }, io);
477
+ case "detect":
478
+ return printBoletoDetect(detectBoletoInputKind(input), { json: options.json, quiet: options.quiet }, io);
479
+ case "convert": {
480
+ if (direction === "linha-to-barras") {
481
+ return printBoletoConvert(convertLinhaToCodigoBarras(input), { json: options.json, quiet: options.quiet }, io);
482
+ }
483
+ if (direction === "barras-to-linha") {
484
+ return printBoletoConvert(convertCodigoBarrasToLinhaDigitavel(input), { json: options.json, quiet: options.quiet }, io);
485
+ }
486
+ io.stderr.push("Missing convert direction. Use linha-to-barras or barras-to-linha.");
487
+ return EXIT.USAGE;
488
+ }
489
+ case "format":
490
+ return printBoletoFormat(input, { json: options.json, quiet: options.quiet }, io);
491
+ case "strip":
492
+ return printBoletoStrip(input, { json: options.json, quiet: options.quiet }, io);
493
+ default: {
494
+ const _exhaustive = action;
495
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
496
+ return EXIT.USAGE;
497
+ }
498
+ }
499
+ }
500
+ function runBoleto(action, value, options, direction, io = { stdout: [], stderr: [] }) {
501
+ const input = resolveInput7(value, options.file);
502
+ if (input === null) {
503
+ io.stderr.push("Missing boleto value. Pass an argument or use --file.");
504
+ return EXIT.USAGE;
505
+ }
506
+ return runBoletoCommand(action, input, options, direction, io);
507
+ }
508
+
509
+ // src/commands/cartao.ts
510
+ import {
511
+ CARTAO_OFFICIAL_SOURCE_URL,
512
+ detectCardBrand,
513
+ formatCartaoCredito,
514
+ stripCartaoCredito,
515
+ validateCartaoCredito
516
+ } from "@br-validators/core";
517
+ function resolveInput8(value, fileContent) {
518
+ const input = value ?? fileContent?.trim();
519
+ if (!input) {
520
+ return null;
521
+ }
522
+ return input;
523
+ }
524
+ function printCartaoValidation(result, options, io = { stdout: [], stderr: [] }) {
525
+ if (options.json) {
526
+ io.stdout.push(
527
+ JSON.stringify(
528
+ result.ok ? {
529
+ ok: true,
530
+ value: result.value,
531
+ brand: result.brand,
532
+ format: result.format,
533
+ ...options.source ? { source: options.source } : {}
534
+ } : {
535
+ ok: false,
536
+ code: result.code,
537
+ message: result.message,
538
+ ...result.brand ? { brand: result.brand } : {}
539
+ },
540
+ null,
541
+ 2
542
+ )
543
+ );
544
+ return result.ok ? EXIT.OK : EXIT.INVALID;
545
+ }
546
+ if (options.quiet) {
547
+ return result.ok ? EXIT.OK : EXIT.INVALID;
548
+ }
549
+ if (result.ok) {
550
+ io.stdout.push(`valid: yes (${result.format})`);
551
+ io.stdout.push(`brand: ${result.brand}`);
552
+ io.stdout.push(`value: ${result.value}`);
553
+ if (options.source) {
554
+ io.stdout.push(`source: ${options.source}`);
555
+ }
556
+ return EXIT.OK;
557
+ }
558
+ io.stderr.push("valid: no");
559
+ io.stderr.push(`code: ${result.code}`);
560
+ io.stderr.push(`message: ${result.message}`);
561
+ if (result.brand) {
562
+ io.stderr.push(`brand: ${result.brand}`);
563
+ }
564
+ return EXIT.INVALID;
565
+ }
566
+ function printCartaoDetect(brand, options, io = { stdout: [] }) {
567
+ if (options.json) {
568
+ io.stdout.push(JSON.stringify({ brand }, null, 2));
569
+ } else if (!options.quiet) {
570
+ io.stdout.push(brand);
571
+ }
572
+ return EXIT.OK;
573
+ }
574
+ function runCartaoCommand(action, input, options, io = { stdout: [], stderr: [] }) {
575
+ const source = options.source ? CARTAO_OFFICIAL_SOURCE_URL : void 0;
576
+ switch (action) {
577
+ case "validate":
578
+ return printCartaoValidation(validateCartaoCredito(input), { json: options.json, quiet: options.quiet, source }, io);
579
+ case "detect":
580
+ return printCartaoDetect(detectCardBrand(stripCartaoCredito(input)), { json: options.json, quiet: options.quiet }, io);
581
+ case "format":
582
+ return printFormat(formatCartaoCredito(input), { json: options.json, quiet: options.quiet }, io);
583
+ case "strip":
584
+ return printStrip(stripCartaoCredito(input), { json: options.json }, io);
585
+ default: {
586
+ const _exhaustive = action;
587
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
588
+ return EXIT.USAGE;
589
+ }
590
+ }
591
+ }
592
+ function runCartao(action, value, options, io = { stdout: [], stderr: [] }) {
593
+ const input = resolveInput8(value, options.file);
594
+ if (input === null) {
595
+ io.stderr.push("Missing credit card PAN value. Pass an argument or use --file.");
596
+ return EXIT.USAGE;
597
+ }
598
+ return runCartaoCommand(action, input, options, io);
599
+ }
600
+
601
+ // src/commands/ie.ts
602
+ import {
603
+ formatInscricaoEstadual,
604
+ getIeOfficialSourceUrl,
605
+ IE_SUPPORTED_UFS,
606
+ stripInscricaoEstadual,
607
+ validateInscricaoEstadual
608
+ } from "@br-validators/core";
609
+ function resolveInput9(value, fileContent) {
610
+ const input = value ?? fileContent?.trim();
611
+ if (!input) {
612
+ return null;
613
+ }
614
+ return input;
615
+ }
616
+ function resolveUf(uf) {
617
+ if (uf === void 0) {
618
+ return null;
619
+ }
620
+ const normalized = uf.toUpperCase();
621
+ if (IE_SUPPORTED_UFS.includes(normalized)) {
622
+ return normalized;
623
+ }
624
+ return null;
625
+ }
626
+ function printIeValidation(result, options, io = { stdout: [], stderr: [] }) {
627
+ if (options.json) {
628
+ io.stdout.push(
629
+ JSON.stringify(
630
+ result.ok ? {
631
+ ok: true,
632
+ value: result.value,
633
+ uf: result.uf,
634
+ format: result.format,
635
+ ...options.source ? { source: options.source } : {}
636
+ } : {
637
+ ok: false,
638
+ code: result.code,
639
+ message: result.message,
640
+ ...result.uf ? { uf: result.uf } : {}
641
+ },
642
+ null,
643
+ 2
644
+ )
645
+ );
646
+ return result.ok ? EXIT.OK : EXIT.INVALID;
647
+ }
648
+ if (options.quiet) {
649
+ return result.ok ? EXIT.OK : EXIT.INVALID;
650
+ }
651
+ if (result.ok) {
652
+ io.stdout.push(`valid: yes (${result.uf})`);
653
+ io.stdout.push(`value: ${result.value}`);
654
+ io.stdout.push(`format: ${result.format}`);
655
+ if (options.source) {
656
+ io.stdout.push(`source: ${options.source}`);
657
+ }
658
+ return EXIT.OK;
659
+ }
660
+ io.stderr.push("valid: no");
661
+ io.stderr.push(`code: ${result.code}`);
662
+ io.stderr.push(`message: ${result.message}`);
663
+ if (result.uf) {
664
+ io.stderr.push(`uf: ${result.uf}`);
665
+ }
666
+ return EXIT.INVALID;
667
+ }
668
+ function runIeCommand(action, input, options, io = { stdout: [], stderr: [] }) {
669
+ const uf = resolveUf(options.uf);
670
+ if (!uf) {
671
+ io.stderr.push(`Missing or invalid --uf. Use one of: ${IE_SUPPORTED_UFS.join(", ")}.`);
672
+ return EXIT.USAGE;
673
+ }
674
+ const source = options.source ? getIeOfficialSourceUrl(uf) : void 0;
675
+ switch (action) {
676
+ case "validate":
677
+ return printIeValidation(validateInscricaoEstadual(input, { uf }), { json: options.json, quiet: options.quiet, source }, io);
678
+ case "format":
679
+ return printFormat(formatInscricaoEstadual(input, { uf }), { json: options.json, quiet: options.quiet }, io);
680
+ case "strip":
681
+ return printStrip(stripInscricaoEstadual(input), { json: options.json }, io);
682
+ default: {
683
+ const _exhaustive = action;
684
+ io.stderr.push(`Unknown action: ${_exhaustive}`);
685
+ return EXIT.USAGE;
686
+ }
687
+ }
688
+ }
689
+ function runIe(action, value, options, io = { stdout: [], stderr: [] }) {
690
+ const input = resolveInput9(value, options.file);
691
+ if (input === null) {
692
+ io.stderr.push("Missing IE value. Pass an argument or use --file.");
693
+ return EXIT.USAGE;
694
+ }
695
+ return runIeCommand(action, input, options, io);
696
+ }
697
+
698
+ // src/commands/list.ts
699
+ function listSupportedTypes(io = { stdout: [] }) {
700
+ for (const type of SUPPORTED_TYPES) {
701
+ io.stdout.push(type);
702
+ }
703
+ return 0;
704
+ }
705
+
706
+ // src/handlers.ts
707
+ function readInputFile(path, io) {
708
+ try {
709
+ return readFileSync(path, "utf8");
710
+ } catch {
711
+ io.stderr.push(`Cannot read file: ${path}`);
712
+ return null;
713
+ }
714
+ }
715
+ function handleListCli(io = { stdout: [], stderr: [] }) {
716
+ return listSupportedTypes(io);
717
+ }
718
+ function handleCnpjCli(action, value, opts, io = { stdout: [], stderr: [] }) {
719
+ let fileContent;
720
+ if (opts.file) {
721
+ const content = readInputFile(opts.file, io);
722
+ if (content === null) {
723
+ return EXIT.USAGE;
724
+ }
725
+ fileContent = content;
726
+ }
727
+ return runCnpj(
728
+ action,
729
+ value,
730
+ {
731
+ json: Boolean(opts.json),
732
+ quiet: Boolean(opts.quiet),
733
+ source: Boolean(opts.source),
734
+ file: fileContent
735
+ },
736
+ io
737
+ );
738
+ }
739
+ function handleCpfCli(action, value, opts, io = { stdout: [], stderr: [] }) {
740
+ let fileContent;
741
+ if (opts.file) {
742
+ const content = readInputFile(opts.file, io);
743
+ if (content === null) {
744
+ return EXIT.USAGE;
745
+ }
746
+ fileContent = content;
747
+ }
748
+ return runCpf(
749
+ action,
750
+ value,
751
+ {
752
+ json: Boolean(opts.json),
753
+ quiet: Boolean(opts.quiet),
754
+ source: Boolean(opts.source),
755
+ file: fileContent
756
+ },
757
+ io
758
+ );
759
+ }
760
+ function handleCepCli(action, value, opts, io = { stdout: [], stderr: [] }) {
761
+ let fileContent;
762
+ if (opts.file) {
763
+ const content = readInputFile(opts.file, io);
764
+ if (content === null) {
765
+ return EXIT.USAGE;
766
+ }
767
+ fileContent = content;
768
+ }
769
+ return runCep(
770
+ action,
771
+ value,
772
+ {
773
+ json: Boolean(opts.json),
774
+ quiet: Boolean(opts.quiet),
775
+ source: Boolean(opts.source),
776
+ file: fileContent
777
+ },
778
+ io
779
+ );
780
+ }
781
+ function handlePlacaCli(action, value, opts, io = { stdout: [], stderr: [] }) {
782
+ let fileContent;
783
+ if (opts.file) {
784
+ const content = readInputFile(opts.file, io);
785
+ if (content === null) {
786
+ return EXIT.USAGE;
787
+ }
788
+ fileContent = content;
789
+ }
790
+ return runPlaca(
791
+ action,
792
+ value,
793
+ {
794
+ json: Boolean(opts.json),
795
+ quiet: Boolean(opts.quiet),
796
+ source: Boolean(opts.source),
797
+ file: fileContent
798
+ },
799
+ io
800
+ );
801
+ }
802
+ function handlePisPasepCli(action, value, opts, io = { stdout: [], stderr: [] }) {
803
+ let fileContent;
804
+ if (opts.file) {
805
+ const content = readInputFile(opts.file, io);
806
+ if (content === null) {
807
+ return EXIT.USAGE;
808
+ }
809
+ fileContent = content;
810
+ }
811
+ return runPisPasep(
812
+ action,
813
+ value,
814
+ {
815
+ json: Boolean(opts.json),
816
+ quiet: Boolean(opts.quiet),
817
+ source: Boolean(opts.source),
818
+ file: fileContent
819
+ },
820
+ io
821
+ );
822
+ }
823
+ function handlePixCli(action, value, opts, io = { stdout: [], stderr: [] }) {
824
+ let fileContent;
825
+ if (opts.file) {
826
+ const content = readInputFile(opts.file, io);
827
+ if (content === null) {
828
+ return EXIT.USAGE;
829
+ }
830
+ fileContent = content;
831
+ }
832
+ return runPix(
833
+ action,
834
+ value,
835
+ {
836
+ json: Boolean(opts.json),
837
+ quiet: Boolean(opts.quiet),
838
+ source: Boolean(opts.source),
839
+ type: opts.type,
840
+ file: fileContent
841
+ },
842
+ io
843
+ );
844
+ }
845
+ function handleBoletoCli(action, value, opts, direction, io = { stdout: [], stderr: [] }) {
846
+ let fileContent;
847
+ if (opts.file) {
848
+ const content = readInputFile(opts.file, io);
849
+ if (content === null) {
850
+ return EXIT.USAGE;
851
+ }
852
+ fileContent = content;
853
+ }
854
+ return runBoleto(
855
+ action,
856
+ value,
857
+ {
858
+ json: Boolean(opts.json),
859
+ quiet: Boolean(opts.quiet),
860
+ source: Boolean(opts.source),
861
+ kind: opts.kind,
862
+ file: fileContent
863
+ },
864
+ direction,
865
+ io
866
+ );
867
+ }
868
+ function handleCartaoCli(action, value, opts, io = { stdout: [], stderr: [] }) {
869
+ let fileContent;
870
+ if (opts.file) {
871
+ const content = readInputFile(opts.file, io);
872
+ if (content === null) {
873
+ return EXIT.USAGE;
874
+ }
875
+ fileContent = content;
876
+ }
877
+ return runCartao(
878
+ action,
879
+ value,
880
+ {
881
+ json: Boolean(opts.json),
882
+ quiet: Boolean(opts.quiet),
883
+ source: Boolean(opts.source),
884
+ file: fileContent
885
+ },
886
+ io
887
+ );
888
+ }
889
+ function handleCartaoCreditoCli(action, value, opts, io = { stdout: [], stderr: [] }) {
890
+ let fileContent;
891
+ if (opts.file) {
892
+ const content = readInputFile(opts.file, io);
893
+ if (content === null) {
894
+ return EXIT.USAGE;
895
+ }
896
+ fileContent = content;
897
+ }
898
+ return runCartao(
899
+ action,
900
+ value,
901
+ {
902
+ json: Boolean(opts.json),
903
+ quiet: Boolean(opts.quiet),
904
+ source: Boolean(opts.source),
905
+ file: fileContent
906
+ },
907
+ io
908
+ );
909
+ }
910
+ function handleIeCli(action, value, opts, io = { stdout: [], stderr: [] }) {
911
+ let fileContent;
912
+ if (opts.file) {
913
+ const content = readInputFile(opts.file, io);
914
+ if (content === null) {
915
+ return EXIT.USAGE;
916
+ }
917
+ fileContent = content;
918
+ }
919
+ return runIe(
920
+ action,
921
+ value,
922
+ {
923
+ json: Boolean(opts.json),
924
+ quiet: Boolean(opts.quiet),
925
+ source: Boolean(opts.source),
926
+ uf: opts.uf,
927
+ file: fileContent
928
+ },
929
+ io
930
+ );
931
+ }
932
+ function writeCliIo(io) {
933
+ for (const line of io.stdout) console.log(line);
934
+ for (const line of io.stderr) console.error(line);
935
+ }
936
+
937
+ // src/program.ts
938
+ function createProgram() {
939
+ const program = new Command();
940
+ program.name("br-validators").description("100% open-source Brazilian document validators").version("0.10.0-alpha.0");
941
+ program.command("list").description("List supported document types").action(() => {
942
+ const io = { stdout: [], stderr: [] };
943
+ process.exitCode = handleListCli(io);
944
+ writeCliIo(io);
945
+ });
946
+ const cnpj = program.command("cnpj").description("CNPJ \u2014 numeric and alphanumeric (RFB Q14)");
947
+ for (const action of ["validate", "format", "strip"]) {
948
+ cnpj.command(action).description(`${action} a CNPJ`).argument("[value]", "CNPJ 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) => {
949
+ const io = { stdout: [], stderr: [] };
950
+ process.exitCode = handleCnpjCli(action, value, opts, io);
951
+ writeCliIo(io);
952
+ });
953
+ }
954
+ const cpf = program.command("cpf").description("CPF \u2014 numeric modulo 11 (RFB)");
955
+ for (const action of ["validate", "format", "strip"]) {
956
+ cpf.command(action).description(`${action} a CPF`).argument("[value]", "CPF 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) => {
957
+ const io = { stdout: [], stderr: [] };
958
+ process.exitCode = handleCpfCli(action, value, opts, io);
959
+ writeCliIo(io);
960
+ });
961
+ }
962
+ const cep = program.command("cep").description("CEP \u2014 8-digit postal code (Correios)");
963
+ for (const action of ["validate", "format", "strip"]) {
964
+ cep.command(action).description(`${action} a CEP`).argument("[value]", "CEP 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) => {
965
+ const io = { stdout: [], stderr: [] };
966
+ process.exitCode = handleCepCli(action, value, opts, io);
967
+ writeCliIo(io);
968
+ });
969
+ }
970
+ const placa = program.command("placa").description("Placa \u2014 legacy + Mercosul (CONTRAN)");
971
+ for (const action of ["validate", "format", "strip", "convert"]) {
972
+ 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) => {
973
+ const io = { stdout: [], stderr: [] };
974
+ process.exitCode = handlePlacaCli(action, value, opts, io);
975
+ writeCliIo(io);
976
+ });
977
+ }
978
+ const pisPasep = program.command("pis-pasep").description("PIS/PASEP \u2014 numeric modulo 11 (Caixa/INSS)");
979
+ for (const action of ["validate", "format", "strip"]) {
980
+ pisPasep.command(action).description(`${action} a PIS/PASEP number`).argument("[value]", "PIS/PASEP 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) => {
981
+ const io = { stdout: [], stderr: [] };
982
+ process.exitCode = handlePisPasepCli(action, value, opts, io);
983
+ writeCliIo(io);
984
+ });
985
+ }
986
+ const pix = program.command("pix").description("PIX key \u2014 CPF, CNPJ, email, phone, EVP (Bacen)");
987
+ pix.command("detect").description("detect PIX key type").argument("[value]", "PIX key value").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((value, opts) => {
988
+ const io = { stdout: [], stderr: [] };
989
+ process.exitCode = handlePixCli("detect", value, opts, io);
990
+ writeCliIo(io);
991
+ });
992
+ pix.command("validate").description("validate a PIX key").argument("[value]", "PIX key value").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL").option("--type <type>", "Force key type: cpf, cnpj, email, phone, evp").option("-f, --file <path>", "Read value from file").action((value, opts) => {
993
+ const io = { stdout: [], stderr: [] };
994
+ process.exitCode = handlePixCli("validate", value, opts, io);
995
+ writeCliIo(io);
996
+ });
997
+ pix.command("format").description("format a PIX key").argument("[value]", "PIX key value").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--type <type>", "Force key type: cpf, cnpj, email, phone, evp").option("-f, --file <path>", "Read value from file").action((value, opts) => {
998
+ const io = { stdout: [], stderr: [] };
999
+ process.exitCode = handlePixCli("format", value, opts, io);
1000
+ writeCliIo(io);
1001
+ });
1002
+ const boleto = program.command("boleto").description("Boleto \u2014 linha digit\xE1vel + c\xF3digo de barras (FEBRABAN)");
1003
+ boleto.command("detect").description("detect boleto input kind").argument("[value]", "Linha digit\xE1vel or c\xF3digo de barras").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1004
+ const io = { stdout: [], stderr: [] };
1005
+ process.exitCode = handleBoletoCli("detect", value, opts, void 0, io);
1006
+ writeCliIo(io);
1007
+ });
1008
+ boleto.command("validate").description("validate a boleto").argument("[value]", "Linha digit\xE1vel or c\xF3digo de barras").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("--source", "Include official source URL").option("--kind <kind>", "Force input kind: linha-digitavel, codigo-barras").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1009
+ const io = { stdout: [], stderr: [] };
1010
+ process.exitCode = handleBoletoCli("validate", value, opts, void 0, io);
1011
+ writeCliIo(io);
1012
+ });
1013
+ const convert = boleto.command("convert").description("convert between linha digit\xE1vel and c\xF3digo de barras");
1014
+ for (const direction of ["linha-to-barras", "barras-to-linha"]) {
1015
+ convert.command(direction).description(`convert boleto ${direction.replace(/-/g, " ")}`).argument("[value]", "Linha digit\xE1vel or c\xF3digo de barras").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1016
+ const io = { stdout: [], stderr: [] };
1017
+ process.exitCode = handleBoletoCli("convert", value, opts, direction, io);
1018
+ writeCliIo(io);
1019
+ });
1020
+ }
1021
+ for (const action of ["format", "strip"]) {
1022
+ boleto.command(action).description(`${action} a boleto linha digit\xE1vel`).argument("[value]", "Linha digit\xE1vel or c\xF3digo de barras").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1023
+ const io = { stdout: [], stderr: [] };
1024
+ process.exitCode = handleBoletoCli(action, value, opts, void 0, io);
1025
+ writeCliIo(io);
1026
+ });
1027
+ }
1028
+ const cartao = program.command("cartao").description("Credit card PAN \u2014 Luhn / ISO/IEC 7812-1");
1029
+ cartao.command("detect").description("detect card brand (best-effort)").argument("[value]", "Credit card PAN (raw or masked)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read value from file").action((value, opts) => {
1030
+ const io = { stdout: [], stderr: [] };
1031
+ process.exitCode = handleCartaoCli("detect", value, opts, io);
1032
+ writeCliIo(io);
1033
+ });
1034
+ for (const action of ["validate", "format", "strip"]) {
1035
+ cartao.command(action).description(`${action} a credit card PAN`).argument("[value]", "Credit card PAN (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) => {
1036
+ const io = { stdout: [], stderr: [] };
1037
+ process.exitCode = handleCartaoCli(action, value, opts, io);
1038
+ writeCliIo(io);
1039
+ });
1040
+ }
1041
+ const cartaoCredito = program.command("cartao-credito").description("Credit card PAN \u2014 Luhn / ISO/IEC 7812-1 (library subpath alias)");
1042
+ for (const action of ["validate", "format", "strip"]) {
1043
+ cartaoCredito.command(action).description(`${action} a credit card PAN`).argument("[value]", "Credit card PAN (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) => {
1044
+ const io = { stdout: [], stderr: [] };
1045
+ process.exitCode = handleCartaoCreditoCli(action, value, opts, io);
1046
+ writeCliIo(io);
1047
+ });
1048
+ }
1049
+ const ie = program.command("ie").description("Inscri\xE7\xE3o Estadual \u2014 SP, MT, DF (SEFAZ/SINTEGRA check digits)");
1050
+ for (const action of ["validate", "format", "strip"]) {
1051
+ ie.command(action).description(`${action} an Inscri\xE7\xE3o Estadual`).argument("[value]", "IE value (raw or masked)").requiredOption("--uf <uf>", "State code (27 UFs, e.g. SP, RJ, MG)").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) => {
1052
+ const io = { stdout: [], stderr: [] };
1053
+ process.exitCode = handleIeCli(action, value, opts, io);
1054
+ writeCliIo(io);
1055
+ });
1056
+ }
1057
+ return program;
1058
+ }
1059
+ function run(argv) {
1060
+ createProgram().parse(argv);
1061
+ }
1062
+
1063
+ // src/index.ts
1064
+ run(process.argv);
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@br-validators/cli",
3
+ "version": "0.10.0-alpha.0",
4
+ "description": "Terminal CLI for Brazilian document validation — CPF, CNPJ, CEP, IE, PIX, boleto, and more",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/AlexandreZanata/doc-raiz.git",
10
+ "directory": "apps/cli"
11
+ },
12
+ "homepage": "https://github.com/AlexandreZanata/doc-raiz#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/AlexandreZanata/doc-raiz/issues"
15
+ },
16
+ "keywords": [
17
+ "brazil",
18
+ "cli",
19
+ "validator",
20
+ "cpf",
21
+ "cnpj"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "bin": {
27
+ "br-validators": "./dist/index.js"
28
+ },
29
+ "dependencies": {
30
+ "commander": "^13.1.0",
31
+ "@br-validators/core": "0.10.0-alpha.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.15.21",
35
+ "@vitest/coverage-v8": "^3.2.4",
36
+ "tsup": "^8.5.0",
37
+ "typescript": "^5.8.3",
38
+ "vitest": "^3.2.4"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "pretypecheck": "pnpm --filter @br-validators/core build",
47
+ "test": "vitest run",
48
+ "test:coverage": "vitest run --coverage",
49
+ "typecheck": "tsc --noEmit",
50
+ "lint": "eslint src tests --max-warnings 0"
51
+ }
52
+ }