@br-validators/cli
Advanced tools
+583
-21
@@ -17,3 +17,3 @@ #!/usr/bin/env node | ||
| // src/constants.ts | ||
| var SUPPORTED_TYPES = ["cnpj", "cpf", "cep", "telefone", "brcode", "placa", "pis-pasep", "pix", "boleto", "cartao", "ie"]; | ||
| var SUPPORTED_TYPES = ["cnpj", "cpf", "cep", "telefone", "cnh", "renavam", "titulo-eleitor", "nfe-chave", "brcode", "placa", "pis-pasep", "pix", "boleto", "cartao", "ie"]; | ||
| var EXIT = { | ||
@@ -140,2 +140,42 @@ OK: 0, | ||
| } | ||
| function printNfeChaveValidation(result, options, io = { stdout: [], stderr: [] }) { | ||
| if (options.json) { | ||
| io.stdout.push( | ||
| JSON.stringify( | ||
| result.ok ? { | ||
| ok: true, | ||
| value: result.value, | ||
| format: result.format, | ||
| parsed: result.parsed, | ||
| ...result.uf ? { uf: result.uf } : {}, | ||
| ...options.source ? { source: options.source } : {} | ||
| } : { ok: false, code: result.code, message: result.message }, | ||
| null, | ||
| 2 | ||
| ) | ||
| ); | ||
| return result.ok ? EXIT.OK : EXIT.INVALID; | ||
| } | ||
| if (options.quiet) { | ||
| return result.ok ? EXIT.OK : EXIT.INVALID; | ||
| } | ||
| if (result.ok) { | ||
| io.stdout.push(`valid: yes (${result.format})`); | ||
| io.stdout.push(`value: ${result.value}`); | ||
| io.stdout.push(`cUF: ${result.parsed.cUF}`); | ||
| io.stdout.push(`cnpj: ${result.parsed.cnpj}`); | ||
| io.stdout.push(`mod: ${result.parsed.mod}`); | ||
| if (result.uf) { | ||
| io.stdout.push(`uf: ${result.uf}`); | ||
| } | ||
| if (options.source) { | ||
| io.stdout.push(`source: ${options.source}`); | ||
| } | ||
| return EXIT.OK; | ||
| } | ||
| io.stderr.push("valid: no"); | ||
| io.stderr.push(`code: ${result.code}`); | ||
| io.stderr.push(`message: ${result.message}`); | ||
| return EXIT.INVALID; | ||
| } | ||
| function printFormat(result, options, io = { stdout: [], stderr: [] }) { | ||
@@ -272,2 +312,161 @@ if (options.json) { | ||
| // src/commands/cnh.ts | ||
| import { | ||
| CNH_OFFICIAL_SOURCE_URL, | ||
| formatCnh, | ||
| stripCnh, | ||
| validateCnh | ||
| } from "@br-validators/core"; | ||
| function resolveInput4(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
| if (!input) { | ||
| return null; | ||
| } | ||
| return input; | ||
| } | ||
| function runCnhCommand(action, input, options, io = { stdout: [], stderr: [] }) { | ||
| const source = options.source ? CNH_OFFICIAL_SOURCE_URL : void 0; | ||
| switch (action) { | ||
| case "validate": | ||
| return printValidation(validateCnh(input), { json: options.json, quiet: options.quiet, source }, io); | ||
| case "format": | ||
| return printFormat(formatCnh(input), { json: options.json, quiet: options.quiet }, io); | ||
| case "strip": | ||
| return printStrip(stripCnh(input), { json: options.json }, io); | ||
| default: { | ||
| const _exhaustive = action; | ||
| io.stderr.push(`Unknown action: ${_exhaustive}`); | ||
| return EXIT.USAGE; | ||
| } | ||
| } | ||
| } | ||
| function runCnh(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput4(value, options.file); | ||
| if (input === null) { | ||
| io.stderr.push("Missing CNH value. Pass an argument or use --file."); | ||
| return EXIT.USAGE; | ||
| } | ||
| return runCnhCommand(action, input, options, io); | ||
| } | ||
| // src/commands/renavam.ts | ||
| import { | ||
| RENAVAM_OFFICIAL_SOURCE_URL, | ||
| formatRenavam, | ||
| stripRenavam, | ||
| validateRenavam | ||
| } from "@br-validators/core"; | ||
| function resolveInput5(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
| if (!input) { | ||
| return null; | ||
| } | ||
| return input; | ||
| } | ||
| function runRenavamCommand(action, input, options, io = { stdout: [], stderr: [] }) { | ||
| const source = options.source ? RENAVAM_OFFICIAL_SOURCE_URL : void 0; | ||
| switch (action) { | ||
| case "validate": | ||
| return printValidation(validateRenavam(input), { json: options.json, quiet: options.quiet, source }, io); | ||
| case "format": | ||
| return printFormat(formatRenavam(input), { json: options.json, quiet: options.quiet }, io); | ||
| case "strip": | ||
| return printStrip(stripRenavam(input), { json: options.json }, io); | ||
| default: { | ||
| const _exhaustive = action; | ||
| io.stderr.push(`Unknown action: ${_exhaustive}`); | ||
| return EXIT.USAGE; | ||
| } | ||
| } | ||
| } | ||
| function runRenavam(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput5(value, options.file); | ||
| if (input === null) { | ||
| io.stderr.push("Missing RENAVAM value. Pass an argument or use --file."); | ||
| return EXIT.USAGE; | ||
| } | ||
| return runRenavamCommand(action, input, options, io); | ||
| } | ||
| // src/commands/titulo-eleitor.ts | ||
| import { | ||
| TITULO_ELEITOR_OFFICIAL_SOURCE_URL, | ||
| formatTituloEleitor, | ||
| stripTituloEleitor, | ||
| validateTituloEleitor | ||
| } from "@br-validators/core"; | ||
| function resolveInput6(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
| if (!input) { | ||
| return null; | ||
| } | ||
| return input; | ||
| } | ||
| function runTituloEleitorCommand(action, input, options, io = { stdout: [], stderr: [] }) { | ||
| const source = options.source ? TITULO_ELEITOR_OFFICIAL_SOURCE_URL : void 0; | ||
| switch (action) { | ||
| case "validate": | ||
| return printValidation(validateTituloEleitor(input), { json: options.json, quiet: options.quiet, source }, io); | ||
| case "format": | ||
| return printFormat(formatTituloEleitor(input), { json: options.json, quiet: options.quiet }, io); | ||
| case "strip": | ||
| return printStrip(stripTituloEleitor(input), { json: options.json }, io); | ||
| default: { | ||
| const _exhaustive = action; | ||
| io.stderr.push(`Unknown action: ${_exhaustive}`); | ||
| return EXIT.USAGE; | ||
| } | ||
| } | ||
| } | ||
| function runTituloEleitor(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput6(value, options.file); | ||
| if (input === null) { | ||
| io.stderr.push("Missing T\xEDtulo de Eleitor value. Pass an argument or use --file."); | ||
| return EXIT.USAGE; | ||
| } | ||
| return runTituloEleitorCommand(action, input, options, io); | ||
| } | ||
| // src/commands/nfe-chave.ts | ||
| import { | ||
| NFE_CHAVE_OFFICIAL_SOURCE_URL, | ||
| formatNfeChave, | ||
| parseNfeChave, | ||
| stripNfeChave, | ||
| validateNfeChave | ||
| } from "@br-validators/core"; | ||
| function resolveInput7(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
| if (!input) { | ||
| return null; | ||
| } | ||
| return input; | ||
| } | ||
| function runNfeChaveCommand(action, input, options, io = { stdout: [], stderr: [] }) { | ||
| const source = options.source ? NFE_CHAVE_OFFICIAL_SOURCE_URL : void 0; | ||
| switch (action) { | ||
| case "validate": | ||
| return printValidation(validateNfeChave(input), { json: options.json, quiet: options.quiet, source }, io); | ||
| case "parse": | ||
| return printNfeChaveValidation(parseNfeChave(input), { json: options.json, quiet: options.quiet, source }, io); | ||
| case "format": | ||
| return printFormat(formatNfeChave(input), { json: options.json, quiet: options.quiet }, io); | ||
| case "strip": | ||
| return printStrip(stripNfeChave(input), { json: options.json }, io); | ||
| default: { | ||
| const _exhaustive = action; | ||
| io.stderr.push(`Unknown action: ${_exhaustive}`); | ||
| return EXIT.USAGE; | ||
| } | ||
| } | ||
| } | ||
| function runNfeChave(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput7(value, options.file); | ||
| if (input === null) { | ||
| io.stderr.push("Missing NF-e chave de acesso value. Pass an argument or use --file."); | ||
| return EXIT.USAGE; | ||
| } | ||
| return runNfeChaveCommand(action, input, options, io); | ||
| } | ||
| // src/commands/cnpj.ts | ||
@@ -280,3 +479,3 @@ import { | ||
| } from "@br-validators/core"; | ||
| function resolveInput4(value, fileContent) { | ||
| function resolveInput8(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -305,3 +504,3 @@ if (!input) { | ||
| function runCnpj(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput4(value, options.file); | ||
| const input = resolveInput8(value, options.file); | ||
| if (input === null) { | ||
@@ -321,3 +520,3 @@ io.stderr.push("Missing CNPJ value. Pass an argument or use --file."); | ||
| } from "@br-validators/core"; | ||
| function resolveInput5(value, fileContent) { | ||
| function resolveInput9(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -346,3 +545,3 @@ if (!input) { | ||
| function runCpf(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput5(value, options.file); | ||
| const input = resolveInput9(value, options.file); | ||
| if (input === null) { | ||
@@ -363,3 +562,3 @@ io.stderr.push("Missing CPF value. Pass an argument or use --file."); | ||
| } from "@br-validators/core"; | ||
| function resolveInput6(value, fileContent) { | ||
| function resolveInput10(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -390,3 +589,3 @@ if (!input) { | ||
| function runPlaca(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput6(value, options.file); | ||
| const input = resolveInput10(value, options.file); | ||
| if (input === null) { | ||
@@ -406,3 +605,3 @@ io.stderr.push("Missing placa value. Pass an argument or use --file."); | ||
| } from "@br-validators/core"; | ||
| function resolveInput7(value, fileContent) { | ||
| function resolveInput11(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -431,3 +630,3 @@ if (!input) { | ||
| function runPisPasep(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput7(value, options.file); | ||
| const input = resolveInput11(value, options.file); | ||
| if (input === null) { | ||
@@ -447,3 +646,3 @@ io.stderr.push("Missing PIS/PASEP value. Pass an argument or use --file."); | ||
| } from "@br-validators/core"; | ||
| function resolveInput8(value, fileContent) { | ||
| function resolveInput12(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -523,3 +722,3 @@ if (!input) { | ||
| function runPix(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput8(value, options.file); | ||
| const input = resolveInput12(value, options.file); | ||
| if (input === null) { | ||
@@ -543,3 +742,3 @@ io.stderr.push("Missing PIX key value. Pass an argument or use --file."); | ||
| } from "@br-validators/core"; | ||
| function resolveInput9(value, fileContent) { | ||
| function resolveInput13(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -668,3 +867,3 @@ if (!input) { | ||
| function runBoleto(action, value, options, direction, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput9(value, options.file); | ||
| const input = resolveInput13(value, options.file); | ||
| if (input === null) { | ||
@@ -685,3 +884,3 @@ io.stderr.push("Missing boleto value. Pass an argument or use --file."); | ||
| } from "@br-validators/core"; | ||
| function resolveInput10(value, fileContent) { | ||
| function resolveInput14(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -762,3 +961,3 @@ if (!input) { | ||
| function runCartao(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput10(value, options.file); | ||
| const input = resolveInput14(value, options.file); | ||
| if (input === null) { | ||
@@ -773,9 +972,14 @@ io.stderr.push("Missing credit card PAN value. Pass an argument or use --file."); | ||
| import { | ||
| formatIeProdutorRural, | ||
| formatInscricaoEstadual, | ||
| getIeOfficialSourceUrl, | ||
| getIeProdutorRuralOfficialSourceUrl, | ||
| IE_SUPPORTED_UFS, | ||
| isSpRuralIeInput, | ||
| stripIeSpRural, | ||
| stripInscricaoEstadual, | ||
| validateIeProdutorRural, | ||
| validateInscricaoEstadual | ||
| } from "@br-validators/core"; | ||
| function resolveInput11(value, fileContent) { | ||
| function resolveInput15(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
@@ -797,2 +1001,5 @@ if (!input) { | ||
| } | ||
| function isSpRuralRoute(uf, input) { | ||
| return uf === "SP" && isSpRuralIeInput(input); | ||
| } | ||
| function printIeValidation(result, options, io = { stdout: [], stderr: [] }) { | ||
@@ -807,2 +1014,3 @@ if (options.json) { | ||
| format: result.format, | ||
| ...options.rural ? { produtorRural: true } : {}, | ||
| ...options.source ? { source: options.source } : {} | ||
@@ -826,2 +1034,5 @@ } : { | ||
| io.stdout.push(`valid: yes (${result.uf})`); | ||
| if (options.rural) { | ||
| io.stdout.push("kind: produtor-rural"); | ||
| } | ||
| io.stdout.push(`value: ${result.value}`); | ||
@@ -848,10 +1059,19 @@ io.stdout.push(`format: ${result.format}`); | ||
| } | ||
| const source = options.source ? getIeOfficialSourceUrl(uf) : void 0; | ||
| const rural = isSpRuralRoute(uf, input); | ||
| const source = options.source ? rural ? getIeProdutorRuralOfficialSourceUrl() : getIeOfficialSourceUrl(uf) : void 0; | ||
| switch (action) { | ||
| case "validate": | ||
| return printIeValidation(validateInscricaoEstadual(input, { uf }), { json: options.json, quiet: options.quiet, source }, io); | ||
| return printIeValidation( | ||
| rural ? validateIeProdutorRural(uf, input) : validateInscricaoEstadual(input, { uf }), | ||
| { json: options.json, quiet: options.quiet, source, rural }, | ||
| io | ||
| ); | ||
| case "format": | ||
| return printFormat(formatInscricaoEstadual(input, { uf }), { json: options.json, quiet: options.quiet }, io); | ||
| return printFormat( | ||
| rural ? formatIeProdutorRural(input) : formatInscricaoEstadual(input, { uf }), | ||
| { json: options.json, quiet: options.quiet }, | ||
| io | ||
| ); | ||
| case "strip": | ||
| return printStrip(stripInscricaoEstadual(input), { json: options.json }, io); | ||
| return printStrip(rural ? stripIeSpRural(input) : stripInscricaoEstadual(input), { json: options.json }, io); | ||
| default: { | ||
@@ -865,3 +1085,3 @@ const _exhaustive = action; | ||
| function runIe(action, value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput11(value, options.file); | ||
| const input = resolveInput15(value, options.file); | ||
| if (input === null) { | ||
@@ -874,2 +1094,159 @@ io.stderr.push("Missing IE value. Pass an argument or use --file."); | ||
| // src/commands/detect.ts | ||
| import { detect } from "@br-validators/core"; | ||
| function resolveInput16(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
| if (!input) { | ||
| return null; | ||
| } | ||
| return input; | ||
| } | ||
| function printDetect(result, options, io = { stdout: [], stderr: [] }) { | ||
| if (options.json) { | ||
| io.stdout.push(JSON.stringify(result, null, 2)); | ||
| return result.ok ? EXIT.OK : EXIT.INVALID; | ||
| } | ||
| if (options.quiet) { | ||
| return result.ok ? EXIT.OK : EXIT.INVALID; | ||
| } | ||
| if (result.ok) { | ||
| io.stdout.push(`type: ${result.type}`); | ||
| io.stdout.push("valid: yes"); | ||
| io.stdout.push(`value: ${result.value}`); | ||
| if (result.format) { | ||
| io.stdout.push(`format: ${result.format}`); | ||
| } | ||
| if (result.meta) { | ||
| io.stdout.push(`meta: ${JSON.stringify(result.meta)}`); | ||
| } | ||
| return EXIT.OK; | ||
| } | ||
| io.stderr.push(`type: ${result.type}`); | ||
| io.stderr.push("valid: no"); | ||
| io.stderr.push(`code: ${result.code}`); | ||
| io.stderr.push(`message: ${result.message}`); | ||
| return EXIT.INVALID; | ||
| } | ||
| function runDetect(value, options, io = { stdout: [], stderr: [] }) { | ||
| const input = resolveInput16(value, options.file); | ||
| if (input === null) { | ||
| io.stderr.push("Missing value. Pass an argument or use --file."); | ||
| return EXIT.USAGE; | ||
| } | ||
| const uf = options.uf?.toUpperCase(); | ||
| const result = detect(input, uf ? { uf } : {}); | ||
| return printDetect(result, options, io); | ||
| } | ||
| // src/commands/sanitize.ts | ||
| import { sanitize } from "@br-validators/core"; | ||
| var SANITIZABLE_TYPES = [ | ||
| "cpf", | ||
| "cnpj", | ||
| "cep", | ||
| "placa", | ||
| "pis-pasep", | ||
| "telefone", | ||
| "cnh", | ||
| "renavam", | ||
| "titulo-eleitor", | ||
| "nfe-chave", | ||
| "boleto", | ||
| "cartao-credito", | ||
| "inscricao-estadual", | ||
| "inscricao-estadual-produtor-rural" | ||
| ]; | ||
| function isSanitizableType(type) { | ||
| return SANITIZABLE_TYPES.includes(type); | ||
| } | ||
| function resolveInput17(value, fileContent) { | ||
| const input = value ?? fileContent?.trim(); | ||
| if (!input) { | ||
| return null; | ||
| } | ||
| return input; | ||
| } | ||
| function printSanitize(result, options, io = { stdout: [], stderr: [] }) { | ||
| if (options.json) { | ||
| io.stdout.push(JSON.stringify(result, null, 2)); | ||
| return result.ok ? EXIT.OK : EXIT.INVALID; | ||
| } | ||
| if (options.quiet) { | ||
| return result.ok ? EXIT.OK : EXIT.INVALID; | ||
| } | ||
| if (result.ok) { | ||
| io.stdout.push("valid: yes"); | ||
| io.stdout.push(`value: ${result.value}`); | ||
| io.stdout.push(`fixes: ${result.fixes.join(", ")}`); | ||
| return EXIT.OK; | ||
| } | ||
| io.stderr.push("valid: no"); | ||
| io.stderr.push(`code: ${result.code}`); | ||
| io.stderr.push(`message: ${result.message}`); | ||
| return EXIT.INVALID; | ||
| } | ||
| function runSanitize(type, value, options, io = { stdout: [], stderr: [] }) { | ||
| if (!isSanitizableType(type)) { | ||
| io.stderr.push(`Unsupported sanitize type: ${type}`); | ||
| return EXIT.USAGE; | ||
| } | ||
| const input = resolveInput17(value, options.file); | ||
| if (input === null) { | ||
| io.stderr.push("Missing value. Pass an argument or use --file."); | ||
| return EXIT.USAGE; | ||
| } | ||
| const uf = options.uf?.toUpperCase(); | ||
| const result = sanitize(input, type, uf ? { uf } : {}); | ||
| return printSanitize(result, options, io); | ||
| } | ||
| // src/commands/generate.ts | ||
| import { generate } from "@br-validators/core"; | ||
| var GENERATABLE_TYPES = [ | ||
| "cpf", | ||
| "cnpj", | ||
| "cep", | ||
| "placa", | ||
| "pis-pasep", | ||
| "renavam", | ||
| "cnh", | ||
| "telefone", | ||
| "cartao-credito" | ||
| ]; | ||
| function isGeneratableType(type) { | ||
| return GENERATABLE_TYPES.includes(type); | ||
| } | ||
| function buildGenerateOptions(options) { | ||
| const core = {}; | ||
| if (options.masked) { | ||
| core.masked = true; | ||
| } | ||
| if (options.seed !== void 0) { | ||
| core.seed = options.seed; | ||
| } | ||
| if (options.format) { | ||
| core.format = options.format; | ||
| } | ||
| return core; | ||
| } | ||
| function printGenerate(value, options, io = { stdout: [], stderr: [] }) { | ||
| if (options.json) { | ||
| io.stdout.push(JSON.stringify({ ok: true, value }, null, 2)); | ||
| return EXIT.OK; | ||
| } | ||
| if (options.quiet) { | ||
| return EXIT.OK; | ||
| } | ||
| io.stdout.push(value); | ||
| return EXIT.OK; | ||
| } | ||
| function runGenerate(type, options, io = { stdout: [], stderr: [] }) { | ||
| if (!isGeneratableType(type)) { | ||
| io.stderr.push(`Unsupported generate type: ${type}`); | ||
| return EXIT.USAGE; | ||
| } | ||
| const value = generate(type, buildGenerateOptions(options)); | ||
| return printGenerate(value, options, io); | ||
| } | ||
| // src/commands/list.ts | ||
@@ -979,2 +1356,23 @@ function listSupportedTypes(io = { stdout: [] }) { | ||
| } | ||
| function handleCnhCli(action, value, opts, io = { stdout: [], stderr: [] }) { | ||
| let fileContent; | ||
| if (opts.file) { | ||
| const content = readInputFile(opts.file, io); | ||
| if (content === null) { | ||
| return EXIT.USAGE; | ||
| } | ||
| fileContent = content; | ||
| } | ||
| return runCnh( | ||
| action, | ||
| value, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| source: Boolean(opts.source), | ||
| file: fileContent | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function handlePlacaCli(action, value, opts, io = { stdout: [], stderr: [] }) { | ||
@@ -1109,2 +1507,65 @@ let fileContent; | ||
| } | ||
| function handleRenavamCli(action, value, opts, io = { stdout: [], stderr: [] }) { | ||
| let fileContent; | ||
| if (opts.file) { | ||
| const content = readInputFile(opts.file, io); | ||
| if (content === null) { | ||
| return EXIT.USAGE; | ||
| } | ||
| fileContent = content; | ||
| } | ||
| return runRenavam( | ||
| action, | ||
| value, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| source: Boolean(opts.source), | ||
| file: fileContent | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function handleTituloEleitorCli(action, value, opts, io = { stdout: [], stderr: [] }) { | ||
| let fileContent; | ||
| if (opts.file) { | ||
| const content = readInputFile(opts.file, io); | ||
| if (content === null) { | ||
| return EXIT.USAGE; | ||
| } | ||
| fileContent = content; | ||
| } | ||
| return runTituloEleitor( | ||
| action, | ||
| value, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| source: Boolean(opts.source), | ||
| file: fileContent | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function handleNfeChaveCli(action, value, opts, io = { stdout: [], stderr: [] }) { | ||
| let fileContent; | ||
| if (opts.file) { | ||
| const content = readInputFile(opts.file, io); | ||
| if (content === null) { | ||
| return EXIT.USAGE; | ||
| } | ||
| fileContent = content; | ||
| } | ||
| return runNfeChave( | ||
| action, | ||
| value, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| source: Boolean(opts.source), | ||
| file: fileContent | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function handleBrCodeCli(action, value, opts, io = { stdout: [], stderr: [] }) { | ||
@@ -1153,2 +1614,56 @@ let fileContent; | ||
| } | ||
| function handleDetectCli(value, opts, io = { stdout: [], stderr: [] }) { | ||
| let fileContent; | ||
| if (opts.file) { | ||
| const content = readInputFile(opts.file, io); | ||
| if (content === null) { | ||
| return EXIT.USAGE; | ||
| } | ||
| fileContent = content; | ||
| } | ||
| return runDetect( | ||
| value, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| uf: opts.uf, | ||
| file: fileContent | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function handleSanitizeCli(type, value, opts, io = { stdout: [], stderr: [] }) { | ||
| let fileContent; | ||
| if (opts.file) { | ||
| const content = readInputFile(opts.file, io); | ||
| if (content === null) { | ||
| return EXIT.USAGE; | ||
| } | ||
| fileContent = content; | ||
| } | ||
| return runSanitize( | ||
| type, | ||
| value, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| uf: opts.uf, | ||
| file: fileContent | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function handleGenerateCli(type, opts, io = { stdout: [], stderr: [] }) { | ||
| return runGenerate( | ||
| type, | ||
| { | ||
| json: Boolean(opts.json), | ||
| quiet: Boolean(opts.quiet), | ||
| masked: Boolean(opts.masked), | ||
| format: opts.format, | ||
| seed: opts.seed | ||
| }, | ||
| io | ||
| ); | ||
| } | ||
| function writeCliIo(io) { | ||
@@ -1200,2 +1715,34 @@ for (const line of io.stdout) console.log(line); | ||
| } | ||
| const cnh = program.command("cnh").description("CNH \u2014 Registro Nacional, 11 contiguous digits (CONTRAN / SENATRAN)"); | ||
| for (const action of ["validate", "format", "strip"]) { | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleCnhCli(action, value, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| } | ||
| const renavam = program.command("renavam").description("RENAVAM \u2014 11-digit vehicle registry code (DENATRAN / SENATRAN)"); | ||
| for (const action of ["validate", "format", "strip"]) { | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleRenavamCli(action, value, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| } | ||
| const tituloEleitor = program.command("titulo-eleitor").description("T\xEDtulo de Eleitor \u2014 12-digit voter registration (TSE / Wikipedia PT algorithm)"); | ||
| for (const action of ["validate", "format", "strip"]) { | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleTituloEleitorCli(action, value, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| } | ||
| const nfeChave = program.command("nfe-chave").description("NF-e / NFC-e chave de acesso \u2014 44 digits (SEFAZ MOC \xA72.2.6)"); | ||
| for (const action of ["validate", "parse", "format", "strip"]) { | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleNfeChaveCli(action, value, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| } | ||
| const brcode = program.command("brcode").description("BR Code \u2014 PIX QR payload (Bacen EMV TLV)"); | ||
@@ -1296,2 +1843,17 @@ for (const action of ["parse", "validate"]) { | ||
| } | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleDetectCli(value, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleSanitizeCli(type, value, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| 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) => { | ||
| const io = { stdout: [], stderr: [] }; | ||
| process.exitCode = handleGenerateCli(type, opts, io); | ||
| writeCliIo(io); | ||
| }); | ||
| return program; | ||
@@ -1298,0 +1860,0 @@ } |
+2
-2
| { | ||
| "name": "@br-validators/cli", | ||
| "version": "0.11.0-alpha.0", | ||
| "version": "0.12.0-alpha.0", | ||
| "description": "Terminal CLI for Brazilian document validation — CPF, CNPJ, CEP, IE, PIX, boleto, and more", | ||
@@ -32,3 +32,3 @@ "license": "MIT", | ||
| "commander": "^13.1.0", | ||
| "@br-validators/core": "0.11.0-alpha.0" | ||
| "@br-validators/core": "0.12.0-alpha.0" | ||
| }, | ||
@@ -35,0 +35,0 @@ "devDependencies": { |
66716
38.9%1831
44.29%+ Added
- Removed