@br-validators/cli 1.9.0 → 1.10.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.
- package/README.md +32 -3
- package/dist/index.js +210 -25
- package/dist/run-captured.js +208 -26
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/open-data-brazil/br-validators/blob/main/LICENSE)
|
|
5
5
|
[](https://github.com/open-data-brazil/br-validators/releases)
|
|
6
6
|
|
|
7
|
-
Terminal CLI for all Brazilian document validators in [@br-validators/core](https://www.npmjs.com/package/@br-validators/core) **v1.
|
|
7
|
+
Terminal CLI for all Brazilian document validators in [@br-validators/core](https://www.npmjs.com/package/@br-validators/core) **v1.10.0**.
|
|
8
8
|
|
|
9
9
|
**Repo:** [github.com/open-data-brazil/br-validators](https://github.com/open-data-brazil/br-validators)
|
|
10
10
|
|
|
@@ -78,7 +78,7 @@ br-validators ie validate P-01100424.3/002 --uf SP # SP produtor rural (auto-d
|
|
|
78
78
|
| `sanitize <type> [value]` | ETL fixes + validate; `--uf` for `inscricao-estadual` |
|
|
79
79
|
| `mask <type> [value]` | Unified display mask; `--uf` for IE / RG |
|
|
80
80
|
| `compare <type> <valueA> <valueB>` | Normalized equality; `--uf` for IE / RG / título |
|
|
81
|
-
| `batch <type>` | Bulk validate (stdin or `--file`); `--uf`, `--limit` |
|
|
81
|
+
| `batch <type>` | Bulk validate (stdin or `--file`, or CSV with `--col`); `--delimiter`, `--skip-header`; `--uf`, `--limit` |
|
|
82
82
|
| `diff <type> <valueA> <valueB>` | Field-level diff; `--uf` for IE / RG / título |
|
|
83
83
|
| `generate <type>` | Synthetic test document; `--seed`, `--masked`, `--format` |
|
|
84
84
|
|
|
@@ -91,6 +91,9 @@ br-validators mask cpf 12345678909 --json
|
|
|
91
91
|
br-validators mask inscricao-estadual 110042490114 --uf SP --json
|
|
92
92
|
br-validators compare cpf '123.456.789-09' 12345678909 --json
|
|
93
93
|
br-validators batch cpf --file values.txt --json
|
|
94
|
+
br-validators batch cpf --file payroll.csv --col cpf --json
|
|
95
|
+
br-validators sanitize pix ' PIX@BCB.GOV.BR ' --json
|
|
96
|
+
br-validators csosn lookup 102 --json
|
|
94
97
|
br-validators diff cpf 12345678909 12345678901 --json
|
|
95
98
|
br-validators generate cpf --seed 42 --masked --json
|
|
96
99
|
br-validators generate cnpj --format alphanumeric --seed 7 --json
|
|
@@ -127,6 +130,17 @@ br-validators cbo lookup 212405 --json
|
|
|
127
130
|
br-validators cbo search analista --limit 5
|
|
128
131
|
```
|
|
129
132
|
|
|
133
|
+
### Fiscal reference (33o–34)
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
br-validators iss-municipal lookup 3550308 --json
|
|
137
|
+
br-validators iss-municipal list --uf SP --limit 10 --json
|
|
138
|
+
br-validators iss-municipal search campinas --uf SP --limit 5 --json
|
|
139
|
+
br-validators iss-municipal resolve SP "São Paulo" --verbose
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Partial embed (~500 municipalities). **Estimation / quoting only — not NFSe emission.**
|
|
143
|
+
|
|
130
144
|
### Geography & calendar (27d)
|
|
131
145
|
|
|
132
146
|
```bash
|
|
@@ -145,8 +159,22 @@ br-validators ddd lookup 11 --verbose
|
|
|
145
159
|
br-validators moedas lookup BRL --json
|
|
146
160
|
br-validators paises-bacen lookup 1058 --verbose
|
|
147
161
|
br-validators incoterms lookup FOB --json
|
|
162
|
+
br-validators ptax lookup USD --verbose
|
|
163
|
+
br-validators ptax lookup USD 2026-06-20 --json --verbose
|
|
164
|
+
br-validators ptax historico USD 2026-06-01 2026-06-26 --json --verbose
|
|
148
165
|
```
|
|
149
166
|
|
|
167
|
+
**PTAX:** offline embed — last **90 business days** (`janelaDiasUteis: 90`; not live Bacen). `--verbose` prints `dataReferencia`, `isStale`, and `warning` when stale. `ptax historico` lists all embedded rows in a date range.
|
|
168
|
+
|
|
169
|
+
### Finance (SELIC)
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
br-validators selic --verbose
|
|
173
|
+
br-validators selic --date 2026-06-18 --json --verbose
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`--verbose` includes `dataReferencia`, `isStale`, and dataset `capturadoEm` (same pattern as PTAX).
|
|
177
|
+
|
|
150
178
|
### Logistics (26e)
|
|
151
179
|
|
|
152
180
|
```bash
|
|
@@ -169,9 +197,10 @@ br-validators aeroportos lookup SBGR --json
|
|
|
169
197
|
|------|-------------|
|
|
170
198
|
| `--json` | JSON output |
|
|
171
199
|
| `--quiet` / `-q` | Exit code only (CI) |
|
|
200
|
+
| `--verbose` | PTAX / SELIC: `dataReferencia`, `isStale`, `warning`; other lookups: dataset metadata |
|
|
172
201
|
| `--file` / `-f` | Read value from file |
|
|
173
202
|
| `--source` | Print official source URL (per-type) |
|
|
174
|
-
| `--uf` | Required for IE / detect / sanitize IE;
|
|
203
|
+
| `--uf` | Required for IE / detect / sanitize IE; filter for `ibge list municipios`, `iss-municipal list`, and `iss-municipal search` |
|
|
175
204
|
|
|
176
205
|
### CI
|
|
177
206
|
|
package/dist/index.js
CHANGED
|
@@ -150,6 +150,10 @@ import {
|
|
|
150
150
|
CFOP_DATA_VERSION,
|
|
151
151
|
lookupCfopPorCodigo
|
|
152
152
|
} from "@br-validators/core/cfop";
|
|
153
|
+
import {
|
|
154
|
+
CSOSN_DATA_VERSION,
|
|
155
|
+
lookupCsosnPorCodigo
|
|
156
|
+
} from "@br-validators/core/csosn";
|
|
153
157
|
import { NCM_DATA_VERSION, lookupNcmPorCodigo } from "@br-validators/core/ncm";
|
|
154
158
|
import { CBO_DATA_VERSION, lookupCboPorCodigo } from "@br-validators/core/cbo";
|
|
155
159
|
import {
|
|
@@ -162,6 +166,7 @@ var REFERENCE_LOOKUP_COMMANDS = [
|
|
|
162
166
|
"cest",
|
|
163
167
|
"cnae",
|
|
164
168
|
"cfop",
|
|
169
|
+
"csosn",
|
|
165
170
|
"ncm",
|
|
166
171
|
"cbo",
|
|
167
172
|
"moedas",
|
|
@@ -170,7 +175,7 @@ var REFERENCE_LOOKUP_COMMANDS = [
|
|
|
170
175
|
"portos",
|
|
171
176
|
"aeroportos"
|
|
172
177
|
];
|
|
173
|
-
var REFERENCE_SEARCH_COMMANDS = ["cnae", "cfop", "ncm", "cbo"];
|
|
178
|
+
var REFERENCE_SEARCH_COMMANDS = ["cnae", "cfop", "csosn", "ncm", "cbo"];
|
|
174
179
|
function lookupAeroporto(input) {
|
|
175
180
|
const normalized = input.trim().toUpperCase();
|
|
176
181
|
if (normalized.length === 0) {
|
|
@@ -240,6 +245,17 @@ var REFERENCE_LOOKUP_MODULES = {
|
|
|
240
245
|
return `${row.codigo} \u2014 ${row.descricao}`;
|
|
241
246
|
}
|
|
242
247
|
},
|
|
248
|
+
csosn: {
|
|
249
|
+
command: "csosn",
|
|
250
|
+
description: "CONFAZ CSOSN Simples Nacional \u2014 offline lookup",
|
|
251
|
+
resultKey: "csosn",
|
|
252
|
+
capturadoEm: CSOSN_DATA_VERSION.capturadoEm,
|
|
253
|
+
lookup: (input) => lookupCsosnPorCodigo(input),
|
|
254
|
+
formatHuman: (result) => {
|
|
255
|
+
const row = result;
|
|
256
|
+
return `${row.codigo} \u2014 ${row.descricao}`;
|
|
257
|
+
}
|
|
258
|
+
},
|
|
243
259
|
ncm: {
|
|
244
260
|
command: "ncm",
|
|
245
261
|
description: "Siscomex NCM Mercosur codes \u2014 offline lookup",
|
|
@@ -380,6 +396,7 @@ function runReferenceLookup(command, value, options, io = { stdout: [], stderr:
|
|
|
380
396
|
import { searchCbo } from "@br-validators/core/cbo";
|
|
381
397
|
import { searchCnaes } from "@br-validators/core/cnaes";
|
|
382
398
|
import { searchCfop } from "@br-validators/core/cfop";
|
|
399
|
+
import { searchCsosn } from "@br-validators/core/csosn";
|
|
383
400
|
import { searchNcm } from "@br-validators/core/ncm";
|
|
384
401
|
function runSearch(command, query, limit) {
|
|
385
402
|
switch (command) {
|
|
@@ -387,6 +404,8 @@ function runSearch(command, query, limit) {
|
|
|
387
404
|
return searchCnaes(query, { limit });
|
|
388
405
|
case "cfop":
|
|
389
406
|
return searchCfop(query, { limit });
|
|
407
|
+
case "csosn":
|
|
408
|
+
return searchCsosn(query, { limit });
|
|
390
409
|
case "ncm":
|
|
391
410
|
return searchNcm(query, { limit });
|
|
392
411
|
case "cbo":
|
|
@@ -444,15 +463,18 @@ function runReferenceSearch(command, query, options, io = { stdout: [], stderr:
|
|
|
444
463
|
|
|
445
464
|
// src/commands/reference-lookup/validate.ts
|
|
446
465
|
import { validateCfop } from "@br-validators/core/cfop";
|
|
466
|
+
import { validateCsosn } from "@br-validators/core/csosn";
|
|
447
467
|
import { validateNcm } from "@br-validators/core/ncm";
|
|
448
|
-
var REFERENCE_VALIDATE_COMMANDS = ["ncm", "cfop"];
|
|
468
|
+
var REFERENCE_VALIDATE_COMMANDS = ["ncm", "cfop", "csosn"];
|
|
449
469
|
var VALIDATORS = {
|
|
450
470
|
ncm: validateNcm,
|
|
451
|
-
cfop: validateCfop
|
|
471
|
+
cfop: validateCfop,
|
|
472
|
+
csosn: validateCsosn
|
|
452
473
|
};
|
|
453
474
|
var CAPTURED_AT = {
|
|
454
475
|
ncm: "ncm",
|
|
455
|
-
cfop: "cfop"
|
|
476
|
+
cfop: "cfop",
|
|
477
|
+
csosn: "csosn"
|
|
456
478
|
};
|
|
457
479
|
function emitFailure(result, options, io) {
|
|
458
480
|
if (options.json) {
|
|
@@ -1297,12 +1319,19 @@ function runSelicCommand(options, io = { stdout: [], stderr: [] }) {
|
|
|
1297
1319
|
|
|
1298
1320
|
// src/commands/iss-municipal/index.ts
|
|
1299
1321
|
import {
|
|
1300
|
-
|
|
1322
|
+
getIssMunicipalPorUf,
|
|
1301
1323
|
getIssMunicipalPorUfMunicipio,
|
|
1302
1324
|
ISS_MUNICIPAL_DATA_VERSION,
|
|
1303
1325
|
ISS_MUNICIPAL_ESTIMATION_WARNING,
|
|
1326
|
+
lookupIssMunicipalPorIbge,
|
|
1304
1327
|
searchIssMunicipal
|
|
1305
1328
|
} from "@br-validators/core/iss-municipal";
|
|
1329
|
+
function sliceRows2(rows, limit) {
|
|
1330
|
+
if (limit === void 0 || !Number.isFinite(limit) || limit <= 0) {
|
|
1331
|
+
return rows;
|
|
1332
|
+
}
|
|
1333
|
+
return rows.slice(0, limit);
|
|
1334
|
+
}
|
|
1306
1335
|
function formatIssMunicipalHuman(row) {
|
|
1307
1336
|
return `${row.nome}/${row.uf} \u2014 ISS ${String(row.aliquotaMin)}%\u2013${String(row.aliquotaMax)}%`;
|
|
1308
1337
|
}
|
|
@@ -1318,7 +1347,7 @@ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] })
|
|
|
1318
1347
|
io.stderr.push("Missing IBGE code. Usage: br-validators iss-municipal lookup <codigoIbge>");
|
|
1319
1348
|
return EXIT.USAGE;
|
|
1320
1349
|
}
|
|
1321
|
-
const result =
|
|
1350
|
+
const result = lookupIssMunicipalPorIbge(trimmed);
|
|
1322
1351
|
if (result === void 0) {
|
|
1323
1352
|
io.stderr.push(`ISS municipal row not found for IBGE code ${trimmed}`);
|
|
1324
1353
|
return EXIT.INVALID;
|
|
@@ -1336,6 +1365,7 @@ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] })
|
|
|
1336
1365
|
return EXIT.OK;
|
|
1337
1366
|
}
|
|
1338
1367
|
io.stdout.push(formatIssMunicipalHuman(result));
|
|
1368
|
+
io.stdout.push(`fonte: ${result.fonte}`);
|
|
1339
1369
|
io.stdout.push(`warning: ${result.warning}`);
|
|
1340
1370
|
if (options.verbose) {
|
|
1341
1371
|
io.stdout.push(`leiUrl: ${result.leiUrl}`);
|
|
@@ -1344,13 +1374,49 @@ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] })
|
|
|
1344
1374
|
}
|
|
1345
1375
|
return EXIT.OK;
|
|
1346
1376
|
}
|
|
1377
|
+
function runIssMunicipalList(options, io = { stdout: [], stderr: [] }) {
|
|
1378
|
+
const uf = options.uf?.trim() ?? "";
|
|
1379
|
+
if (uf.length === 0) {
|
|
1380
|
+
io.stderr.push("Missing UF. Usage: br-validators iss-municipal list --uf <UF>");
|
|
1381
|
+
return EXIT.USAGE;
|
|
1382
|
+
}
|
|
1383
|
+
const rows = sliceRows2(getIssMunicipalPorUf(uf), options.limit);
|
|
1384
|
+
emitDisclaimer(options, io);
|
|
1385
|
+
if (options.json) {
|
|
1386
|
+
const payload = {
|
|
1387
|
+
ok: true,
|
|
1388
|
+
uf: uf.toUpperCase(),
|
|
1389
|
+
total: rows.length,
|
|
1390
|
+
results: rows
|
|
1391
|
+
};
|
|
1392
|
+
if (options.verbose) {
|
|
1393
|
+
payload.capturadoEm = ISS_MUNICIPAL_DATA_VERSION.capturadoEm;
|
|
1394
|
+
}
|
|
1395
|
+
io.stdout.push(JSON.stringify(payload, null, 2));
|
|
1396
|
+
return EXIT.OK;
|
|
1397
|
+
}
|
|
1398
|
+
if (rows.length === 0) {
|
|
1399
|
+
io.stdout.push(`No ISS municipal rows embedded for UF ${uf.toUpperCase()}.`);
|
|
1400
|
+
return EXIT.OK;
|
|
1401
|
+
}
|
|
1402
|
+
for (const row of rows) {
|
|
1403
|
+
io.stdout.push(formatIssMunicipalHuman(row));
|
|
1404
|
+
}
|
|
1405
|
+
if (options.verbose) {
|
|
1406
|
+
io.stdout.push(`capturadoEm: ${ISS_MUNICIPAL_DATA_VERSION.capturadoEm}`);
|
|
1407
|
+
}
|
|
1408
|
+
return EXIT.OK;
|
|
1409
|
+
}
|
|
1347
1410
|
function runIssMunicipalSearch(query, options, io = { stdout: [], stderr: [] }) {
|
|
1348
1411
|
const trimmed = query?.trim() ?? "";
|
|
1349
1412
|
if (trimmed.length === 0) {
|
|
1350
1413
|
io.stderr.push("Missing query. Usage: br-validators iss-municipal search <query>");
|
|
1351
1414
|
return EXIT.USAGE;
|
|
1352
1415
|
}
|
|
1353
|
-
const rows = searchIssMunicipal(trimmed, {
|
|
1416
|
+
const rows = searchIssMunicipal(trimmed, {
|
|
1417
|
+
limit: options.limit,
|
|
1418
|
+
...options.uf !== void 0 && options.uf.trim().length > 0 ? { uf: options.uf } : {}
|
|
1419
|
+
});
|
|
1354
1420
|
emitDisclaimer(options, io);
|
|
1355
1421
|
if (options.json) {
|
|
1356
1422
|
io.stdout.push(JSON.stringify({ ok: true, results: rows }, null, 2));
|
|
@@ -1429,6 +1495,73 @@ function runPtaxLookup(moeda, data, options, io = { stdout: [], stderr: [] }) {
|
|
|
1429
1495
|
return runPtaxLookupCommand(moeda.trim(), data?.trim(), options, io);
|
|
1430
1496
|
}
|
|
1431
1497
|
|
|
1498
|
+
// src/commands/ptax/historico.ts
|
|
1499
|
+
import {
|
|
1500
|
+
getPtaxHistorico,
|
|
1501
|
+
PTAX_DATA_VERSION as PTAX_DATA_VERSION2
|
|
1502
|
+
} from "@br-validators/core/ptax";
|
|
1503
|
+
function formatPtaxHistoricoHuman(results) {
|
|
1504
|
+
return results.map(
|
|
1505
|
+
(cotacao) => `${cotacao.dataReferencia} \u2014 compra ${String(cotacao.cotacaoCompra)} / venda ${String(cotacao.cotacaoVenda)}`
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
function runPtaxHistoricoCommand(moeda, desde, ate, options, io = { stdout: [], stderr: [] }) {
|
|
1509
|
+
const trimmedMoeda = moeda.trim();
|
|
1510
|
+
const trimmedDesde = desde.trim();
|
|
1511
|
+
const trimmedAte = ate.trim();
|
|
1512
|
+
if (trimmedMoeda.length === 0) {
|
|
1513
|
+
io.stderr.push("Missing currency code. Pass a 3-letter ISO code (e.g. USD).");
|
|
1514
|
+
return EXIT.USAGE;
|
|
1515
|
+
}
|
|
1516
|
+
if (trimmedDesde.length === 0 || trimmedAte.length === 0) {
|
|
1517
|
+
io.stderr.push("Missing date range. Pass desde and ate as YYYY-MM-DD.");
|
|
1518
|
+
return EXIT.USAGE;
|
|
1519
|
+
}
|
|
1520
|
+
const results = getPtaxHistorico(trimmedMoeda, { desde: trimmedDesde, ate: trimmedAte });
|
|
1521
|
+
if (results.length === 0) {
|
|
1522
|
+
io.stderr.push(
|
|
1523
|
+
`No PTAX quotes in embed for ${trimmedMoeda} between ${trimmedDesde} and ${trimmedAte}`
|
|
1524
|
+
);
|
|
1525
|
+
return EXIT.INVALID;
|
|
1526
|
+
}
|
|
1527
|
+
if (options.json) {
|
|
1528
|
+
const payload = {
|
|
1529
|
+
ok: true,
|
|
1530
|
+
moeda: trimmedMoeda.toUpperCase(),
|
|
1531
|
+
desde: trimmedDesde,
|
|
1532
|
+
ate: trimmedAte,
|
|
1533
|
+
total: results.length,
|
|
1534
|
+
cotacoes: results
|
|
1535
|
+
};
|
|
1536
|
+
if (options.verbose) {
|
|
1537
|
+
payload.capturadoEm = PTAX_DATA_VERSION2.capturadoEm;
|
|
1538
|
+
payload.janelaDiasUteis = PTAX_DATA_VERSION2.janelaDiasUteis;
|
|
1539
|
+
}
|
|
1540
|
+
io.stdout.push(JSON.stringify(payload, null, 2));
|
|
1541
|
+
return EXIT.OK;
|
|
1542
|
+
}
|
|
1543
|
+
io.stdout.push(`${trimmedMoeda.toUpperCase()} PTAX historico (${String(results.length)} rows)`);
|
|
1544
|
+
for (const line of formatPtaxHistoricoHuman(results)) {
|
|
1545
|
+
io.stdout.push(line);
|
|
1546
|
+
}
|
|
1547
|
+
if (options.verbose) {
|
|
1548
|
+
io.stdout.push(`capturadoEm: ${PTAX_DATA_VERSION2.capturadoEm}`);
|
|
1549
|
+
io.stdout.push(`janelaDiasUteis: ${String(PTAX_DATA_VERSION2.janelaDiasUteis)}`);
|
|
1550
|
+
}
|
|
1551
|
+
return EXIT.OK;
|
|
1552
|
+
}
|
|
1553
|
+
function runPtaxHistorico(moeda, desde, ate, options, io = { stdout: [], stderr: [] }) {
|
|
1554
|
+
if (!moeda?.trim()) {
|
|
1555
|
+
io.stderr.push("Missing currency code. Usage: ptax historico <moeda> <desde> <ate>");
|
|
1556
|
+
return EXIT.USAGE;
|
|
1557
|
+
}
|
|
1558
|
+
if (!desde?.trim() || !ate?.trim()) {
|
|
1559
|
+
io.stderr.push("Missing date range. Usage: ptax historico <moeda> <desde> <ate>");
|
|
1560
|
+
return EXIT.USAGE;
|
|
1561
|
+
}
|
|
1562
|
+
return runPtaxHistoricoCommand(moeda.trim(), desde.trim(), ate.trim(), options, io);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1432
1565
|
// src/commands/brcode.ts
|
|
1433
1566
|
import {
|
|
1434
1567
|
BRCODE_OFFICIAL_SOURCE_URL,
|
|
@@ -2900,7 +3033,8 @@ var SANITIZABLE_TYPES = [
|
|
|
2900
3033
|
"cartao-credito",
|
|
2901
3034
|
"ean",
|
|
2902
3035
|
"inscricao-estadual",
|
|
2903
|
-
"inscricao-estadual-produtor-rural"
|
|
3036
|
+
"inscricao-estadual-produtor-rural",
|
|
3037
|
+
"pix"
|
|
2904
3038
|
];
|
|
2905
3039
|
function isSanitizableType(type) {
|
|
2906
3040
|
return SANITIZABLE_TYPES.includes(type);
|
|
@@ -3038,19 +3172,35 @@ function runCompare(type, valueA, valueB, options, io = { stdout: [], stderr: []
|
|
|
3038
3172
|
}
|
|
3039
3173
|
|
|
3040
3174
|
// src/commands/batch.ts
|
|
3041
|
-
import { batch } from "@br-validators/core";
|
|
3175
|
+
import { batch, parseBatchCsv } from "@br-validators/core";
|
|
3042
3176
|
function parseBatchLines(raw) {
|
|
3043
3177
|
return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
3044
3178
|
}
|
|
3045
3179
|
function resolveBatchInputs(options) {
|
|
3046
3180
|
if (options.lines === void 0) {
|
|
3047
|
-
return
|
|
3181
|
+
return { ok: false, reason: "missing_input" };
|
|
3182
|
+
}
|
|
3183
|
+
let parsed;
|
|
3184
|
+
if (options.col !== void 0) {
|
|
3185
|
+
const csv = parseBatchCsv(options.lines, {
|
|
3186
|
+
col: options.col,
|
|
3187
|
+
delimiter: options.delimiter,
|
|
3188
|
+
skipHeader: options.skipHeader
|
|
3189
|
+
});
|
|
3190
|
+
if (!csv.ok) {
|
|
3191
|
+
return { ok: false, reason: "parse_error", message: csv.message };
|
|
3192
|
+
}
|
|
3193
|
+
parsed = csv.values;
|
|
3194
|
+
} else {
|
|
3195
|
+
parsed = parseBatchLines(options.lines);
|
|
3196
|
+
}
|
|
3197
|
+
if (parsed.length === 0) {
|
|
3198
|
+
return { ok: false, reason: "empty" };
|
|
3048
3199
|
}
|
|
3049
|
-
const parsed = parseBatchLines(options.lines);
|
|
3050
3200
|
if (options.limit !== void 0 && options.limit > 0) {
|
|
3051
|
-
return parsed.slice(0, options.limit);
|
|
3201
|
+
return { ok: true, values: parsed.slice(0, options.limit) };
|
|
3052
3202
|
}
|
|
3053
|
-
return parsed;
|
|
3203
|
+
return { ok: true, values: parsed };
|
|
3054
3204
|
}
|
|
3055
3205
|
function printBatch(result, options, io = { stdout: [], stderr: [] }) {
|
|
3056
3206
|
if (options.json) {
|
|
@@ -3076,18 +3226,20 @@ function runBatch(type, options, io = { stdout: [], stderr: [] }) {
|
|
|
3076
3226
|
io.stderr.push(`Unsupported batch type: ${type}`);
|
|
3077
3227
|
return EXIT.USAGE;
|
|
3078
3228
|
}
|
|
3079
|
-
const
|
|
3080
|
-
if (
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3229
|
+
const resolved = resolveBatchInputs(options);
|
|
3230
|
+
if (!resolved.ok) {
|
|
3231
|
+
if (resolved.reason === "missing_input") {
|
|
3232
|
+
io.stderr.push("Missing input. Pass --file <path> or pipe one value per line on stdin.");
|
|
3233
|
+
} else if (resolved.reason === "empty") {
|
|
3234
|
+
io.stderr.push("No values to validate.");
|
|
3235
|
+
} else {
|
|
3236
|
+
io.stderr.push(resolved.message);
|
|
3237
|
+
}
|
|
3086
3238
|
return EXIT.USAGE;
|
|
3087
3239
|
}
|
|
3088
3240
|
const uf = options.uf?.toUpperCase();
|
|
3089
3241
|
const platformOptions = uf ? { uf } : {};
|
|
3090
|
-
const result = batch(
|
|
3242
|
+
const result = batch(resolved.values, type, platformOptions);
|
|
3091
3243
|
return printBatch(result, options, io);
|
|
3092
3244
|
}
|
|
3093
3245
|
|
|
@@ -3762,7 +3914,10 @@ function handleBatchCli(type, opts, io = { stdout: [], stderr: [] }) {
|
|
|
3762
3914
|
quiet: Boolean(opts.quiet),
|
|
3763
3915
|
uf: opts.uf,
|
|
3764
3916
|
lines,
|
|
3765
|
-
limit: opts.limit
|
|
3917
|
+
limit: opts.limit,
|
|
3918
|
+
col: opts.col,
|
|
3919
|
+
delimiter: opts.delimiter,
|
|
3920
|
+
skipHeader: opts.skipHeader
|
|
3766
3921
|
},
|
|
3767
3922
|
io
|
|
3768
3923
|
);
|
|
@@ -3924,6 +4079,14 @@ function handleSelicCli(opts, io = { stdout: [], stderr: [] }) {
|
|
|
3924
4079
|
date: opts.date
|
|
3925
4080
|
}, io);
|
|
3926
4081
|
}
|
|
4082
|
+
function handleIssMunicipalListCli(opts, io = { stdout: [], stderr: [] }) {
|
|
4083
|
+
return runIssMunicipalList({
|
|
4084
|
+
json: Boolean(opts.json),
|
|
4085
|
+
verbose: Boolean(opts.verbose),
|
|
4086
|
+
uf: opts.uf,
|
|
4087
|
+
limit: opts.limit
|
|
4088
|
+
}, io);
|
|
4089
|
+
}
|
|
3927
4090
|
function handleIssMunicipalLookupCli(codigo, opts, io = { stdout: [], stderr: [] }) {
|
|
3928
4091
|
return runIssMunicipalLookup(codigo, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
|
|
3929
4092
|
}
|
|
@@ -3931,7 +4094,8 @@ function handleIssMunicipalSearchCli(query, opts, io = { stdout: [], stderr: []
|
|
|
3931
4094
|
return runIssMunicipalSearch(query, {
|
|
3932
4095
|
json: Boolean(opts.json),
|
|
3933
4096
|
verbose: Boolean(opts.verbose),
|
|
3934
|
-
limit: opts.limit
|
|
4097
|
+
limit: opts.limit,
|
|
4098
|
+
uf: opts.uf
|
|
3935
4099
|
}, io);
|
|
3936
4100
|
}
|
|
3937
4101
|
function handleIssMunicipalResolveCli(uf, nome, opts, io = { stdout: [], stderr: [] }) {
|
|
@@ -3940,6 +4104,15 @@ function handleIssMunicipalResolveCli(uf, nome, opts, io = { stdout: [], stderr:
|
|
|
3940
4104
|
function handlePtaxLookupCli(moeda, data, opts, io = { stdout: [], stderr: [] }) {
|
|
3941
4105
|
return runPtaxLookup(moeda, data, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
|
|
3942
4106
|
}
|
|
4107
|
+
function handlePtaxHistoricoCli(moeda, desde, ate, opts, io = { stdout: [], stderr: [] }) {
|
|
4108
|
+
return runPtaxHistorico(
|
|
4109
|
+
moeda,
|
|
4110
|
+
desde,
|
|
4111
|
+
ate,
|
|
4112
|
+
{ json: Boolean(opts.json), verbose: Boolean(opts.verbose) },
|
|
4113
|
+
io
|
|
4114
|
+
);
|
|
4115
|
+
}
|
|
3943
4116
|
function writeCliIo(io) {
|
|
3944
4117
|
for (const line of io.stdout) console.log(line);
|
|
3945
4118
|
for (const line of io.stderr) console.error(line);
|
|
@@ -4263,6 +4436,11 @@ function createProgram() {
|
|
|
4263
4436
|
writeCliIo(io);
|
|
4264
4437
|
});
|
|
4265
4438
|
const issMunicipal = program.command("iss-municipal").description("Municipal ISS al\xEDquotas \u2014 partial embed (estimation only, not NFSe)");
|
|
4439
|
+
issMunicipal.command("list").description("List embedded municipalities for a UF").requiredOption("--uf <uf>", "UF sigla (2 letters)").option("--json", "JSON output").option("--verbose", "Include dataset capture date in JSON responses").option("--limit <n>", "Maximum rows", (value) => Number(value)).action((opts) => {
|
|
4440
|
+
const io = { stdout: [], stderr: [] };
|
|
4441
|
+
process.exitCode = handleIssMunicipalListCli(opts, io);
|
|
4442
|
+
writeCliIo(io);
|
|
4443
|
+
});
|
|
4266
4444
|
issMunicipal.command("lookup").description("Resolve ISS band by IBGE municipality code").argument("<codigoIbge>", "IBGE municipality code (7 digits)").option("--json", "JSON output").option("--verbose", "Include leiUrl, estimativa flag, and dataset capture date").action((codigoIbge, opts) => {
|
|
4267
4445
|
const io = { stdout: [], stderr: [] };
|
|
4268
4446
|
process.exitCode = handleIssMunicipalLookupCli(codigoIbge, opts, io);
|
|
@@ -4273,7 +4451,7 @@ function createProgram() {
|
|
|
4273
4451
|
process.exitCode = handleIssMunicipalResolveCli(uf, nome, opts, io);
|
|
4274
4452
|
writeCliIo(io);
|
|
4275
4453
|
});
|
|
4276
|
-
issMunicipal.command("search").description("Search embedded municipalities by name, UF, or IBGE code fragment").argument("<query>", "Search query").option("--json", "JSON output").option("--verbose", "Include dataset capture date in JSON responses").option("--limit <n>", "Maximum rows", (value) => Number(value)).action((query, opts) => {
|
|
4454
|
+
issMunicipal.command("search").description("Search embedded municipalities by name, UF, or IBGE code fragment").argument("<query>", "Search query").option("--uf <uf>", "Scope search to a UF").option("--json", "JSON output").option("--verbose", "Include dataset capture date in JSON responses").option("--limit <n>", "Maximum rows", (value) => Number(value)).action((query, opts) => {
|
|
4277
4455
|
const io = { stdout: [], stderr: [] };
|
|
4278
4456
|
process.exitCode = handleIssMunicipalSearchCli(query, opts, io);
|
|
4279
4457
|
writeCliIo(io);
|
|
@@ -4284,6 +4462,13 @@ function createProgram() {
|
|
|
4284
4462
|
process.exitCode = handlePtaxLookupCli(moeda, data, opts, io);
|
|
4285
4463
|
writeCliIo(io);
|
|
4286
4464
|
});
|
|
4465
|
+
ptax.command("historico").description("List embedded Fechamento PTAX rows for a currency and date range").argument("<moeda>", "ISO 4217 currency code (e.g. USD)").argument("<desde>", "Range start \u2014 YYYY-MM-DD or MM-DD-YYYY").argument("<ate>", "Range end \u2014 YYYY-MM-DD or MM-DD-YYYY").option("--json", "JSON output").option("--verbose", "Include capturadoEm and janelaDiasUteis in JSON responses").action(
|
|
4466
|
+
(moeda, desde, ate, opts) => {
|
|
4467
|
+
const io = { stdout: [], stderr: [] };
|
|
4468
|
+
process.exitCode = handlePtaxHistoricoCli(moeda, desde, ate, opts, io);
|
|
4469
|
+
writeCliIo(io);
|
|
4470
|
+
}
|
|
4471
|
+
);
|
|
4287
4472
|
const cst = program.command("cst").description("RFB SPED CST \u2014 offline ICMS, IPI, PIS, COFINS tables");
|
|
4288
4473
|
cst.command("lookup").description("Resolve CST by code and tax").argument("<codigo>", "CST code").requiredOption("--tax <tax>", "Tax table: icms | ipi | pis | cofins").option("--json", "JSON output").option("--verbose", "Include dataset capture date").action((codigo, opts) => {
|
|
4289
4474
|
const io = { stdout: [], stderr: [] };
|
|
@@ -4326,7 +4511,7 @@ function createProgram() {
|
|
|
4326
4511
|
process.exitCode = handleCompareCli(type, valueA, valueB.join(" ") || void 0, opts, io);
|
|
4327
4512
|
writeCliIo(io);
|
|
4328
4513
|
});
|
|
4329
|
-
program.command("batch <type>").description("Bulk validate values from stdin or --file").option("--uf <uf>", "State code (required for inscricao-estadual, rg, titulo-eleitor)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read values from file (one per line)").option("--limit <n>", "Max number of values to process", (v) => Number(v)).action((type, opts) => {
|
|
4514
|
+
program.command("batch <type>").description("Bulk validate values from stdin or --file").option("--uf <uf>", "State code (required for inscricao-estadual, rg, titulo-eleitor)").option("--json", "JSON output").option("-q, --quiet", "Exit code only").option("-f, --file <path>", "Read values from file (one per line, or CSV with --col)").option("--col <name>", "CSV column name or zero-based index (requires --file)").option("--delimiter <char>", "CSV delimiter (default: comma)").option("--skip-header", "Treat first CSV row as header (default: true)", true).option("--no-skip-header", "Parse CSV without header row").option("--limit <n>", "Max number of values to process", (v) => Number(v)).action((type, opts) => {
|
|
4330
4515
|
const io = { stdout: [], stderr: [] };
|
|
4331
4516
|
process.exitCode = handleBatchCli(type, opts, io);
|
|
4332
4517
|
writeCliIo(io);
|
package/dist/run-captured.js
CHANGED
|
@@ -42,6 +42,10 @@ import {
|
|
|
42
42
|
CFOP_DATA_VERSION,
|
|
43
43
|
lookupCfopPorCodigo
|
|
44
44
|
} from "@br-validators/core/cfop";
|
|
45
|
+
import {
|
|
46
|
+
CSOSN_DATA_VERSION,
|
|
47
|
+
lookupCsosnPorCodigo
|
|
48
|
+
} from "@br-validators/core/csosn";
|
|
45
49
|
import { NCM_DATA_VERSION, lookupNcmPorCodigo } from "@br-validators/core/ncm";
|
|
46
50
|
import { CBO_DATA_VERSION, lookupCboPorCodigo } from "@br-validators/core/cbo";
|
|
47
51
|
import {
|
|
@@ -54,6 +58,7 @@ var REFERENCE_LOOKUP_COMMANDS = [
|
|
|
54
58
|
"cest",
|
|
55
59
|
"cnae",
|
|
56
60
|
"cfop",
|
|
61
|
+
"csosn",
|
|
57
62
|
"ncm",
|
|
58
63
|
"cbo",
|
|
59
64
|
"moedas",
|
|
@@ -62,7 +67,7 @@ var REFERENCE_LOOKUP_COMMANDS = [
|
|
|
62
67
|
"portos",
|
|
63
68
|
"aeroportos"
|
|
64
69
|
];
|
|
65
|
-
var REFERENCE_SEARCH_COMMANDS = ["cnae", "cfop", "ncm", "cbo"];
|
|
70
|
+
var REFERENCE_SEARCH_COMMANDS = ["cnae", "cfop", "csosn", "ncm", "cbo"];
|
|
66
71
|
function lookupAeroporto(input) {
|
|
67
72
|
const normalized = input.trim().toUpperCase();
|
|
68
73
|
if (normalized.length === 0) {
|
|
@@ -132,6 +137,17 @@ var REFERENCE_LOOKUP_MODULES = {
|
|
|
132
137
|
return `${row.codigo} \u2014 ${row.descricao}`;
|
|
133
138
|
}
|
|
134
139
|
},
|
|
140
|
+
csosn: {
|
|
141
|
+
command: "csosn",
|
|
142
|
+
description: "CONFAZ CSOSN Simples Nacional \u2014 offline lookup",
|
|
143
|
+
resultKey: "csosn",
|
|
144
|
+
capturadoEm: CSOSN_DATA_VERSION.capturadoEm,
|
|
145
|
+
lookup: (input) => lookupCsosnPorCodigo(input),
|
|
146
|
+
formatHuman: (result) => {
|
|
147
|
+
const row = result;
|
|
148
|
+
return `${row.codigo} \u2014 ${row.descricao}`;
|
|
149
|
+
}
|
|
150
|
+
},
|
|
135
151
|
ncm: {
|
|
136
152
|
command: "ncm",
|
|
137
153
|
description: "Siscomex NCM Mercosur codes \u2014 offline lookup",
|
|
@@ -221,15 +237,18 @@ function isReferenceSearchCommand(value) {
|
|
|
221
237
|
|
|
222
238
|
// src/commands/reference-lookup/validate.ts
|
|
223
239
|
import { validateCfop } from "@br-validators/core/cfop";
|
|
240
|
+
import { validateCsosn } from "@br-validators/core/csosn";
|
|
224
241
|
import { validateNcm } from "@br-validators/core/ncm";
|
|
225
|
-
var REFERENCE_VALIDATE_COMMANDS = ["ncm", "cfop"];
|
|
242
|
+
var REFERENCE_VALIDATE_COMMANDS = ["ncm", "cfop", "csosn"];
|
|
226
243
|
var VALIDATORS = {
|
|
227
244
|
ncm: validateNcm,
|
|
228
|
-
cfop: validateCfop
|
|
245
|
+
cfop: validateCfop,
|
|
246
|
+
csosn: validateCsosn
|
|
229
247
|
};
|
|
230
248
|
var CAPTURED_AT = {
|
|
231
249
|
ncm: "ncm",
|
|
232
|
-
cfop: "cfop"
|
|
250
|
+
cfop: "cfop",
|
|
251
|
+
csosn: "csosn"
|
|
233
252
|
};
|
|
234
253
|
function emitFailure(result, options, io) {
|
|
235
254
|
if (options.json) {
|
|
@@ -438,6 +457,7 @@ function runReferenceLookup(command, value, options, io = { stdout: [], stderr:
|
|
|
438
457
|
import { searchCbo } from "@br-validators/core/cbo";
|
|
439
458
|
import { searchCnaes } from "@br-validators/core/cnaes";
|
|
440
459
|
import { searchCfop } from "@br-validators/core/cfop";
|
|
460
|
+
import { searchCsosn } from "@br-validators/core/csosn";
|
|
441
461
|
import { searchNcm } from "@br-validators/core/ncm";
|
|
442
462
|
function runSearch(command, query, limit) {
|
|
443
463
|
switch (command) {
|
|
@@ -445,6 +465,8 @@ function runSearch(command, query, limit) {
|
|
|
445
465
|
return searchCnaes(query, { limit });
|
|
446
466
|
case "cfop":
|
|
447
467
|
return searchCfop(query, { limit });
|
|
468
|
+
case "csosn":
|
|
469
|
+
return searchCsosn(query, { limit });
|
|
448
470
|
case "ncm":
|
|
449
471
|
return searchNcm(query, { limit });
|
|
450
472
|
case "cbo":
|
|
@@ -1292,12 +1314,19 @@ function runSelicCommand(options, io = { stdout: [], stderr: [] }) {
|
|
|
1292
1314
|
|
|
1293
1315
|
// src/commands/iss-municipal/index.ts
|
|
1294
1316
|
import {
|
|
1295
|
-
|
|
1317
|
+
getIssMunicipalPorUf,
|
|
1296
1318
|
getIssMunicipalPorUfMunicipio,
|
|
1297
1319
|
ISS_MUNICIPAL_DATA_VERSION,
|
|
1298
1320
|
ISS_MUNICIPAL_ESTIMATION_WARNING,
|
|
1321
|
+
lookupIssMunicipalPorIbge,
|
|
1299
1322
|
searchIssMunicipal
|
|
1300
1323
|
} from "@br-validators/core/iss-municipal";
|
|
1324
|
+
function sliceRows2(rows, limit) {
|
|
1325
|
+
if (limit === void 0 || !Number.isFinite(limit) || limit <= 0) {
|
|
1326
|
+
return rows;
|
|
1327
|
+
}
|
|
1328
|
+
return rows.slice(0, limit);
|
|
1329
|
+
}
|
|
1301
1330
|
function formatIssMunicipalHuman(row) {
|
|
1302
1331
|
return `${row.nome}/${row.uf} \u2014 ISS ${String(row.aliquotaMin)}%\u2013${String(row.aliquotaMax)}%`;
|
|
1303
1332
|
}
|
|
@@ -1313,7 +1342,7 @@ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] })
|
|
|
1313
1342
|
io.stderr.push("Missing IBGE code. Usage: br-validators iss-municipal lookup <codigoIbge>");
|
|
1314
1343
|
return EXIT.USAGE;
|
|
1315
1344
|
}
|
|
1316
|
-
const result =
|
|
1345
|
+
const result = lookupIssMunicipalPorIbge(trimmed);
|
|
1317
1346
|
if (result === void 0) {
|
|
1318
1347
|
io.stderr.push(`ISS municipal row not found for IBGE code ${trimmed}`);
|
|
1319
1348
|
return EXIT.INVALID;
|
|
@@ -1331,6 +1360,7 @@ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] })
|
|
|
1331
1360
|
return EXIT.OK;
|
|
1332
1361
|
}
|
|
1333
1362
|
io.stdout.push(formatIssMunicipalHuman(result));
|
|
1363
|
+
io.stdout.push(`fonte: ${result.fonte}`);
|
|
1334
1364
|
io.stdout.push(`warning: ${result.warning}`);
|
|
1335
1365
|
if (options.verbose) {
|
|
1336
1366
|
io.stdout.push(`leiUrl: ${result.leiUrl}`);
|
|
@@ -1339,13 +1369,49 @@ function runIssMunicipalLookup(codigo, options, io = { stdout: [], stderr: [] })
|
|
|
1339
1369
|
}
|
|
1340
1370
|
return EXIT.OK;
|
|
1341
1371
|
}
|
|
1372
|
+
function runIssMunicipalList(options, io = { stdout: [], stderr: [] }) {
|
|
1373
|
+
const uf = options.uf?.trim() ?? "";
|
|
1374
|
+
if (uf.length === 0) {
|
|
1375
|
+
io.stderr.push("Missing UF. Usage: br-validators iss-municipal list --uf <UF>");
|
|
1376
|
+
return EXIT.USAGE;
|
|
1377
|
+
}
|
|
1378
|
+
const rows = sliceRows2(getIssMunicipalPorUf(uf), options.limit);
|
|
1379
|
+
emitDisclaimer(options, io);
|
|
1380
|
+
if (options.json) {
|
|
1381
|
+
const payload = {
|
|
1382
|
+
ok: true,
|
|
1383
|
+
uf: uf.toUpperCase(),
|
|
1384
|
+
total: rows.length,
|
|
1385
|
+
results: rows
|
|
1386
|
+
};
|
|
1387
|
+
if (options.verbose) {
|
|
1388
|
+
payload.capturadoEm = ISS_MUNICIPAL_DATA_VERSION.capturadoEm;
|
|
1389
|
+
}
|
|
1390
|
+
io.stdout.push(JSON.stringify(payload, null, 2));
|
|
1391
|
+
return EXIT.OK;
|
|
1392
|
+
}
|
|
1393
|
+
if (rows.length === 0) {
|
|
1394
|
+
io.stdout.push(`No ISS municipal rows embedded for UF ${uf.toUpperCase()}.`);
|
|
1395
|
+
return EXIT.OK;
|
|
1396
|
+
}
|
|
1397
|
+
for (const row of rows) {
|
|
1398
|
+
io.stdout.push(formatIssMunicipalHuman(row));
|
|
1399
|
+
}
|
|
1400
|
+
if (options.verbose) {
|
|
1401
|
+
io.stdout.push(`capturadoEm: ${ISS_MUNICIPAL_DATA_VERSION.capturadoEm}`);
|
|
1402
|
+
}
|
|
1403
|
+
return EXIT.OK;
|
|
1404
|
+
}
|
|
1342
1405
|
function runIssMunicipalSearch(query, options, io = { stdout: [], stderr: [] }) {
|
|
1343
1406
|
const trimmed = query?.trim() ?? "";
|
|
1344
1407
|
if (trimmed.length === 0) {
|
|
1345
1408
|
io.stderr.push("Missing query. Usage: br-validators iss-municipal search <query>");
|
|
1346
1409
|
return EXIT.USAGE;
|
|
1347
1410
|
}
|
|
1348
|
-
const rows = searchIssMunicipal(trimmed, {
|
|
1411
|
+
const rows = searchIssMunicipal(trimmed, {
|
|
1412
|
+
limit: options.limit,
|
|
1413
|
+
...options.uf !== void 0 && options.uf.trim().length > 0 ? { uf: options.uf } : {}
|
|
1414
|
+
});
|
|
1349
1415
|
emitDisclaimer(options, io);
|
|
1350
1416
|
if (options.json) {
|
|
1351
1417
|
io.stdout.push(JSON.stringify({ ok: true, results: rows }, null, 2));
|
|
@@ -1424,6 +1490,73 @@ function runPtaxLookup(moeda, data, options, io = { stdout: [], stderr: [] }) {
|
|
|
1424
1490
|
return runPtaxLookupCommand(moeda.trim(), data?.trim(), options, io);
|
|
1425
1491
|
}
|
|
1426
1492
|
|
|
1493
|
+
// src/commands/ptax/historico.ts
|
|
1494
|
+
import {
|
|
1495
|
+
getPtaxHistorico,
|
|
1496
|
+
PTAX_DATA_VERSION as PTAX_DATA_VERSION2
|
|
1497
|
+
} from "@br-validators/core/ptax";
|
|
1498
|
+
function formatPtaxHistoricoHuman(results) {
|
|
1499
|
+
return results.map(
|
|
1500
|
+
(cotacao) => `${cotacao.dataReferencia} \u2014 compra ${String(cotacao.cotacaoCompra)} / venda ${String(cotacao.cotacaoVenda)}`
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
function runPtaxHistoricoCommand(moeda, desde, ate, options, io = { stdout: [], stderr: [] }) {
|
|
1504
|
+
const trimmedMoeda = moeda.trim();
|
|
1505
|
+
const trimmedDesde = desde.trim();
|
|
1506
|
+
const trimmedAte = ate.trim();
|
|
1507
|
+
if (trimmedMoeda.length === 0) {
|
|
1508
|
+
io.stderr.push("Missing currency code. Pass a 3-letter ISO code (e.g. USD).");
|
|
1509
|
+
return EXIT.USAGE;
|
|
1510
|
+
}
|
|
1511
|
+
if (trimmedDesde.length === 0 || trimmedAte.length === 0) {
|
|
1512
|
+
io.stderr.push("Missing date range. Pass desde and ate as YYYY-MM-DD.");
|
|
1513
|
+
return EXIT.USAGE;
|
|
1514
|
+
}
|
|
1515
|
+
const results = getPtaxHistorico(trimmedMoeda, { desde: trimmedDesde, ate: trimmedAte });
|
|
1516
|
+
if (results.length === 0) {
|
|
1517
|
+
io.stderr.push(
|
|
1518
|
+
`No PTAX quotes in embed for ${trimmedMoeda} between ${trimmedDesde} and ${trimmedAte}`
|
|
1519
|
+
);
|
|
1520
|
+
return EXIT.INVALID;
|
|
1521
|
+
}
|
|
1522
|
+
if (options.json) {
|
|
1523
|
+
const payload = {
|
|
1524
|
+
ok: true,
|
|
1525
|
+
moeda: trimmedMoeda.toUpperCase(),
|
|
1526
|
+
desde: trimmedDesde,
|
|
1527
|
+
ate: trimmedAte,
|
|
1528
|
+
total: results.length,
|
|
1529
|
+
cotacoes: results
|
|
1530
|
+
};
|
|
1531
|
+
if (options.verbose) {
|
|
1532
|
+
payload.capturadoEm = PTAX_DATA_VERSION2.capturadoEm;
|
|
1533
|
+
payload.janelaDiasUteis = PTAX_DATA_VERSION2.janelaDiasUteis;
|
|
1534
|
+
}
|
|
1535
|
+
io.stdout.push(JSON.stringify(payload, null, 2));
|
|
1536
|
+
return EXIT.OK;
|
|
1537
|
+
}
|
|
1538
|
+
io.stdout.push(`${trimmedMoeda.toUpperCase()} PTAX historico (${String(results.length)} rows)`);
|
|
1539
|
+
for (const line of formatPtaxHistoricoHuman(results)) {
|
|
1540
|
+
io.stdout.push(line);
|
|
1541
|
+
}
|
|
1542
|
+
if (options.verbose) {
|
|
1543
|
+
io.stdout.push(`capturadoEm: ${PTAX_DATA_VERSION2.capturadoEm}`);
|
|
1544
|
+
io.stdout.push(`janelaDiasUteis: ${String(PTAX_DATA_VERSION2.janelaDiasUteis)}`);
|
|
1545
|
+
}
|
|
1546
|
+
return EXIT.OK;
|
|
1547
|
+
}
|
|
1548
|
+
function runPtaxHistorico(moeda, desde, ate, options, io = { stdout: [], stderr: [] }) {
|
|
1549
|
+
if (!moeda?.trim()) {
|
|
1550
|
+
io.stderr.push("Missing currency code. Usage: ptax historico <moeda> <desde> <ate>");
|
|
1551
|
+
return EXIT.USAGE;
|
|
1552
|
+
}
|
|
1553
|
+
if (!desde?.trim() || !ate?.trim()) {
|
|
1554
|
+
io.stderr.push("Missing date range. Usage: ptax historico <moeda> <desde> <ate>");
|
|
1555
|
+
return EXIT.USAGE;
|
|
1556
|
+
}
|
|
1557
|
+
return runPtaxHistoricoCommand(moeda.trim(), desde.trim(), ate.trim(), options, io);
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1427
1560
|
// src/commands/brcode.ts
|
|
1428
1561
|
import {
|
|
1429
1562
|
BRCODE_OFFICIAL_SOURCE_URL,
|
|
@@ -2895,7 +3028,8 @@ var SANITIZABLE_TYPES = [
|
|
|
2895
3028
|
"cartao-credito",
|
|
2896
3029
|
"ean",
|
|
2897
3030
|
"inscricao-estadual",
|
|
2898
|
-
"inscricao-estadual-produtor-rural"
|
|
3031
|
+
"inscricao-estadual-produtor-rural",
|
|
3032
|
+
"pix"
|
|
2899
3033
|
];
|
|
2900
3034
|
function isSanitizableType(type) {
|
|
2901
3035
|
return SANITIZABLE_TYPES.includes(type);
|
|
@@ -3033,19 +3167,35 @@ function runCompare(type, valueA, valueB, options, io = { stdout: [], stderr: []
|
|
|
3033
3167
|
}
|
|
3034
3168
|
|
|
3035
3169
|
// src/commands/batch.ts
|
|
3036
|
-
import { batch } from "@br-validators/core";
|
|
3170
|
+
import { batch, parseBatchCsv } from "@br-validators/core";
|
|
3037
3171
|
function parseBatchLines(raw) {
|
|
3038
3172
|
return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
3039
3173
|
}
|
|
3040
3174
|
function resolveBatchInputs(options) {
|
|
3041
3175
|
if (options.lines === void 0) {
|
|
3042
|
-
return
|
|
3176
|
+
return { ok: false, reason: "missing_input" };
|
|
3177
|
+
}
|
|
3178
|
+
let parsed;
|
|
3179
|
+
if (options.col !== void 0) {
|
|
3180
|
+
const csv = parseBatchCsv(options.lines, {
|
|
3181
|
+
col: options.col,
|
|
3182
|
+
delimiter: options.delimiter,
|
|
3183
|
+
skipHeader: options.skipHeader
|
|
3184
|
+
});
|
|
3185
|
+
if (!csv.ok) {
|
|
3186
|
+
return { ok: false, reason: "parse_error", message: csv.message };
|
|
3187
|
+
}
|
|
3188
|
+
parsed = csv.values;
|
|
3189
|
+
} else {
|
|
3190
|
+
parsed = parseBatchLines(options.lines);
|
|
3191
|
+
}
|
|
3192
|
+
if (parsed.length === 0) {
|
|
3193
|
+
return { ok: false, reason: "empty" };
|
|
3043
3194
|
}
|
|
3044
|
-
const parsed = parseBatchLines(options.lines);
|
|
3045
3195
|
if (options.limit !== void 0 && options.limit > 0) {
|
|
3046
|
-
return parsed.slice(0, options.limit);
|
|
3196
|
+
return { ok: true, values: parsed.slice(0, options.limit) };
|
|
3047
3197
|
}
|
|
3048
|
-
return parsed;
|
|
3198
|
+
return { ok: true, values: parsed };
|
|
3049
3199
|
}
|
|
3050
3200
|
function printBatch(result, options, io = { stdout: [], stderr: [] }) {
|
|
3051
3201
|
if (options.json) {
|
|
@@ -3071,18 +3221,20 @@ function runBatch(type, options, io = { stdout: [], stderr: [] }) {
|
|
|
3071
3221
|
io.stderr.push(`Unsupported batch type: ${type}`);
|
|
3072
3222
|
return EXIT.USAGE;
|
|
3073
3223
|
}
|
|
3074
|
-
const
|
|
3075
|
-
if (
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3224
|
+
const resolved = resolveBatchInputs(options);
|
|
3225
|
+
if (!resolved.ok) {
|
|
3226
|
+
if (resolved.reason === "missing_input") {
|
|
3227
|
+
io.stderr.push("Missing input. Pass --file <path> or pipe one value per line on stdin.");
|
|
3228
|
+
} else if (resolved.reason === "empty") {
|
|
3229
|
+
io.stderr.push("No values to validate.");
|
|
3230
|
+
} else {
|
|
3231
|
+
io.stderr.push(resolved.message);
|
|
3232
|
+
}
|
|
3081
3233
|
return EXIT.USAGE;
|
|
3082
3234
|
}
|
|
3083
3235
|
const uf = options.uf?.toUpperCase();
|
|
3084
3236
|
const platformOptions = uf ? { uf } : {};
|
|
3085
|
-
const result = batch(
|
|
3237
|
+
const result = batch(resolved.values, type, platformOptions);
|
|
3086
3238
|
return printBatch(result, options, io);
|
|
3087
3239
|
}
|
|
3088
3240
|
|
|
@@ -3757,7 +3909,10 @@ function handleBatchCli(type, opts, io = { stdout: [], stderr: [] }) {
|
|
|
3757
3909
|
quiet: Boolean(opts.quiet),
|
|
3758
3910
|
uf: opts.uf,
|
|
3759
3911
|
lines,
|
|
3760
|
-
limit: opts.limit
|
|
3912
|
+
limit: opts.limit,
|
|
3913
|
+
col: opts.col,
|
|
3914
|
+
delimiter: opts.delimiter,
|
|
3915
|
+
skipHeader: opts.skipHeader
|
|
3761
3916
|
},
|
|
3762
3917
|
io
|
|
3763
3918
|
);
|
|
@@ -3919,6 +4074,14 @@ function handleSelicCli(opts, io = { stdout: [], stderr: [] }) {
|
|
|
3919
4074
|
date: opts.date
|
|
3920
4075
|
}, io);
|
|
3921
4076
|
}
|
|
4077
|
+
function handleIssMunicipalListCli(opts, io = { stdout: [], stderr: [] }) {
|
|
4078
|
+
return runIssMunicipalList({
|
|
4079
|
+
json: Boolean(opts.json),
|
|
4080
|
+
verbose: Boolean(opts.verbose),
|
|
4081
|
+
uf: opts.uf,
|
|
4082
|
+
limit: opts.limit
|
|
4083
|
+
}, io);
|
|
4084
|
+
}
|
|
3922
4085
|
function handleIssMunicipalLookupCli(codigo, opts, io = { stdout: [], stderr: [] }) {
|
|
3923
4086
|
return runIssMunicipalLookup(codigo, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
|
|
3924
4087
|
}
|
|
@@ -3926,7 +4089,8 @@ function handleIssMunicipalSearchCli(query, opts, io = { stdout: [], stderr: []
|
|
|
3926
4089
|
return runIssMunicipalSearch(query, {
|
|
3927
4090
|
json: Boolean(opts.json),
|
|
3928
4091
|
verbose: Boolean(opts.verbose),
|
|
3929
|
-
limit: opts.limit
|
|
4092
|
+
limit: opts.limit,
|
|
4093
|
+
uf: opts.uf
|
|
3930
4094
|
}, io);
|
|
3931
4095
|
}
|
|
3932
4096
|
function handleIssMunicipalResolveCli(uf, nome, opts, io = { stdout: [], stderr: [] }) {
|
|
@@ -3935,6 +4099,15 @@ function handleIssMunicipalResolveCli(uf, nome, opts, io = { stdout: [], stderr:
|
|
|
3935
4099
|
function handlePtaxLookupCli(moeda, data, opts, io = { stdout: [], stderr: [] }) {
|
|
3936
4100
|
return runPtaxLookup(moeda, data, { json: Boolean(opts.json), verbose: Boolean(opts.verbose) }, io);
|
|
3937
4101
|
}
|
|
4102
|
+
function handlePtaxHistoricoCli(moeda, desde, ate, opts, io = { stdout: [], stderr: [] }) {
|
|
4103
|
+
return runPtaxHistorico(
|
|
4104
|
+
moeda,
|
|
4105
|
+
desde,
|
|
4106
|
+
ate,
|
|
4107
|
+
{ json: Boolean(opts.json), verbose: Boolean(opts.verbose) },
|
|
4108
|
+
io
|
|
4109
|
+
);
|
|
4110
|
+
}
|
|
3938
4111
|
|
|
3939
4112
|
// src/argv-dispatch.ts
|
|
3940
4113
|
var STANDARD_ACTIONS = ["validate", "format", "strip"];
|
|
@@ -4054,7 +4227,7 @@ function dispatchArgv(tokens, io) {
|
|
|
4054
4227
|
if (tokens.length === 0 || tokens.includes("--help") || tokens.includes("-h")) {
|
|
4055
4228
|
io.stdout.push("br-validators \u2014 100% open-source Brazilian document validators");
|
|
4056
4229
|
io.stdout.push("Usage: br-validators <command> ...");
|
|
4057
|
-
io.stdout.push("Commands: list \xB7 cpf \xB7 cnpj \xB7 cep \xB7 telefone \xB7 cnh \xB7 renavam \xB7 titulo-eleitor \xB7 processo-judicial \xB7 rg \xB7 nfe-chave \xB7 brcode \xB7 placa \xB7 pis-pasep \xB7 cnis \xB7 pix \xB7 boleto \xB7 cartao \xB7 cartao-credito \xB7 ean \xB7 ie \xB7 bancos \xB7 ibge \xB7 feriados \xB7 inss \xB7 irpf \xB7 tse-municipios \xB7 ddd \xB7 nfe-cuf \xB7 selic \xB7 iss-municipal \xB7 ptax \xB7 cst \xB7 natureza-juridica \xB7 nbs \xB7 cest \xB7 cnae \xB7 cfop \xB7 ncm \xB7 cbo \xB7 moedas \xB7 paises-bacen \xB7 incoterms \xB7 portos \xB7 aeroportos \xB7 detect \xB7 sanitize \xB7 mask \xB7 compare \xB7 batch \xB7 diff \xB7 generate");
|
|
4230
|
+
io.stdout.push("Commands: list \xB7 cpf \xB7 cnpj \xB7 cep \xB7 telefone \xB7 cnh \xB7 renavam \xB7 titulo-eleitor \xB7 processo-judicial \xB7 rg \xB7 nfe-chave \xB7 brcode \xB7 placa \xB7 pis-pasep \xB7 cnis \xB7 pix \xB7 boleto \xB7 cartao \xB7 cartao-credito \xB7 ean \xB7 ie \xB7 bancos \xB7 ibge \xB7 feriados \xB7 inss \xB7 irpf \xB7 tse-municipios \xB7 ddd \xB7 nfe-cuf \xB7 selic \xB7 iss-municipal \xB7 ptax \xB7 cst \xB7 csosn \xB7 natureza-juridica \xB7 nbs \xB7 cest \xB7 cnae \xB7 cfop \xB7 ncm \xB7 cbo \xB7 moedas \xB7 paises-bacen \xB7 incoterms \xB7 portos \xB7 aeroportos \xB7 detect \xB7 sanitize \xB7 mask \xB7 compare \xB7 batch \xB7 diff \xB7 generate");
|
|
4058
4231
|
return EXIT.OK;
|
|
4059
4232
|
}
|
|
4060
4233
|
if (tokens.includes("--version") || tokens.includes("-V")) {
|
|
@@ -4287,6 +4460,9 @@ function dispatchArgv(tokens, io) {
|
|
|
4287
4460
|
const value = rest[1];
|
|
4288
4461
|
return handleIssMunicipalLookupCli(value, opts, io);
|
|
4289
4462
|
}
|
|
4463
|
+
if (action === "list") {
|
|
4464
|
+
return handleIssMunicipalListCli(opts, io);
|
|
4465
|
+
}
|
|
4290
4466
|
if (action === "resolve") {
|
|
4291
4467
|
const uf = rest[1];
|
|
4292
4468
|
const nome = rest.slice(2).join(" ") || void 0;
|
|
@@ -4296,7 +4472,7 @@ function dispatchArgv(tokens, io) {
|
|
|
4296
4472
|
const value = rest.slice(1).join(" ") || void 0;
|
|
4297
4473
|
return handleIssMunicipalSearchCli(value, opts, io);
|
|
4298
4474
|
}
|
|
4299
|
-
return usage(io, "Expected: iss-municipal lookup|resolve|search <args>");
|
|
4475
|
+
return usage(io, "Expected: iss-municipal lookup|list|resolve|search <args>");
|
|
4300
4476
|
}
|
|
4301
4477
|
case "ptax": {
|
|
4302
4478
|
const action = rest[0];
|
|
@@ -4305,7 +4481,13 @@ function dispatchArgv(tokens, io) {
|
|
|
4305
4481
|
const data = rest.slice(2).join(" ") || void 0;
|
|
4306
4482
|
return handlePtaxLookupCli(moeda, data, opts, io);
|
|
4307
4483
|
}
|
|
4308
|
-
|
|
4484
|
+
if (action === "historico") {
|
|
4485
|
+
const moeda = rest[1];
|
|
4486
|
+
const desde = rest[2];
|
|
4487
|
+
const ate = rest[3];
|
|
4488
|
+
return handlePtaxHistoricoCli(moeda, desde, ate, opts, io);
|
|
4489
|
+
}
|
|
4490
|
+
return usage(io, "Expected: ptax lookup <moeda> [data] | ptax historico <moeda> <desde> <ate>");
|
|
4309
4491
|
}
|
|
4310
4492
|
case "cst": {
|
|
4311
4493
|
const action = rest[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@br-validators/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "CLI for @br-validators/core — CPF, CNPJ, NF-e, IE, PIX, boleto + detect/sanitize/generate",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"commander": "^13.1.0",
|
|
48
|
-
"@br-validators/core": "1.
|
|
48
|
+
"@br-validators/core": "1.10.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^22.15.21",
|