Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
e076931
test(business-days): compare calendar days in the month-walk properties
hyanmandian Sep 29, 2026
e936f51
fix(capitalize): keep more prepositions and S.A in the right case, sc…
hyanmandian Sep 29, 2026
74484c1
fix(to-standard-schema): report a throwing validator as an issue
hyanmandian Sep 29, 2026
7fbabbf
fix(convert-number-to-words): export NumberToWordsGender from the sub…
hyanmandian Sep 29, 2026
9c14768
docs(words): describe the e, de and zero reais rules of the words fun…
hyanmandian Sep 29, 2026
6380311
docs(schema): validate an object in the Hono route and name the vee-v…
hyanmandian Sep 29, 2026
808a359
docs(address-form): fix the guide links and clear aria-busy on an inc…
hyanmandian Sep 29, 2026
829700d
docs(state-city): build the guide on getMunicipalities and fix the A,…
hyanmandian Sep 29, 2026
2eb0d06
fix(get-holidays): start the AM 8 December ponto facultativo in 1999 …
hyanmandian Sep 29, 2026
06f3ab4
docs(holidays): list the holidays of 2024 in full and state what isHo…
hyanmandian Sep 29, 2026
13535f1
docs(nfse-key): say the key accepts the mask between its fields
hyanmandian Sep 29, 2026
2702a11
fix(nfe-key): strip the XML Id prefix and reject wrong types in forma…
hyanmandian Sep 29, 2026
6fce860
fix(license-plate): reject characters outside the mask, in isValidReg…
hyanmandian Sep 29, 2026
b46084c
fix(vin): test for ASCII letters before upper casing in isValidVin an…
hyanmandian Sep 29, 2026
557bc7e
refactor(certidao): re-export the option types from the subpath entries
hyanmandian Sep 29, 2026
425fd98
docs(nfe-key): note the cNF rule for older keys and the unchecked iss…
hyanmandian Sep 29, 2026
843f35d
refactor(keys): remove prose comments from the keys and vehicles modules
hyanmandian Sep 29, 2026
3fa9fe1
docs(keys): move the norm notes above @param in the processo and lice…
hyanmandian Sep 29, 2026
345450e
fix(license-plate): draw the fifth letter of a generated Mercosul pla…
hyanmandian Sep 29, 2026
0519227
refactor(processo-juridico): name the generateProcessoJuridico parame…
hyanmandian Sep 29, 2026
1f41e60
docs(gtin): cite the version of NT 2021.003 the linked PDF serves
hyanmandian Sep 29, 2026
fc110aa
docs(keys): document the VIN separators, the progressive plate mask a…
hyanmandian Sep 29, 2026
e5f6f12
fix(phone): reject letters and other junk in phone validators
hyanmandian Sep 29, 2026
625dd25
fix(phone): strip an explicit +55 or 0055 at any length
hyanmandian Sep 29, 2026
2f12922
fix(phone): drop an explicit country code in every formatPhone mask
hyanmandian Sep 29, 2026
660f5f7
fix(phone): accept a country code in isValidServicePhone
hyanmandian Sep 29, 2026
aafdabd
fix(email): cap the address length and accept a punycode final label
hyanmandian Sep 29, 2026
721a34c
refactor(phone): keep module level tables literal and JSDoc in tag order
hyanmandian Sep 29, 2026
24083b7
fix(phone): generate landlines that stay valid after March 2027
hyanmandian Sep 29, 2026
60b1492
refactor(payments): lazy caches, no prose comments, PixKeyType re-export
hyanmandian Sep 29, 2026
f909834
fix(pix): require the CRC as the last object and reject repeated IDs
hyanmandian Sep 29, 2026
cfc7cbc
docs(boleto): cite Bradesco for the fator de vencimento base date
hyanmandian Sep 29, 2026
07a5780
fix(boleto): ignore an invalid referenceDate in getBoletoInfo
hyanmandian Sep 29, 2026
e1a9b4d
fix(boleto): reject letters and stray characters in isValidBoleto
hyanmandian Sep 29, 2026
7334fba
fix(boleto): accept the 44 digit cobranca bancaria barcode
hyanmandian Sep 29, 2026
64b0d18
docs(payments): state the limits of the bank and currency checks
hyanmandian Sep 29, 2026
1caadc8
refactor(internals): allocate the retry code set and code tables lazily
hyanmandian Sep 29, 2026
df8b01d
fix(get-address-info-by-cep): abort the providers that lost the race
hyanmandian Sep 29, 2026
17f121f
fix(get-address-info-by-cep): reject an address that contradicts the CEP
hyanmandian Sep 29, 2026
9ff2296
fix(get-cep-info-by-address): validate the city and street before the…
hyanmandian Sep 29, 2026
54bb018
fix(generate-cep): draw the CEP inside the ranges the states own
hyanmandian Sep 29, 2026
ea03a17
docs(get-timezone-by-state): cite the legal source and warn about mul…
hyanmandian Sep 29, 2026
0fc3060
test(cep): add the missing properties blocks and cover slashes in isV…
hyanmandian Sep 29, 2026
630fe51
docs(cep): fix the CEP, state and capital notes in the docs and JSDoc
hyanmandian Sep 29, 2026
8ce1cc1
refactor(cep): drop the prose comments from the source files
hyanmandian Sep 29, 2026
960d9bb
fix(format): return an empty string when the value has no digits, eve…
hyanmandian Sep 29, 2026
b9a1ff4
docs(documents): align the docs and examples of the document utilitie…
hyanmandian Sep 29, 2026
3deac83
docs(documents): cite the reachable e-Financeira manual and tidy the …
hyanmandian Sep 29, 2026
a55aedd
refactor(documents): move prose comments into JSDoc and share the doc…
hyanmandian Sep 29, 2026
a39dc8c
fix(datasets): emit the committed mask regexes from the generator tem…
hyanmandian Sep 29, 2026
58b39aa
docs(classifications): state the mask-run rule for the masked codes a…
hyanmandian Sep 29, 2026
473ce8e
refactor(legal-nature): move buildLegalNature to _internals and tidy …
hyanmandian Sep 29, 2026
f27b8a4
fix(legal-nature): accept numbers and read the documented mask only
hyanmandian Sep 29, 2026
f2f1aff
fix(cst): accept the bare 2 digit Tabela B codes for tax icms
hyanmandian Sep 29, 2026
840604f
fix(classifications): read null options as none in isValidCst and isV…
hyanmandian Sep 29, 2026
7b6e898
docs(ibs-cbs): cite the 23/06/2026 publication and the final SVRS add…
hyanmandian Sep 29, 2026
c26888c
feat(cbo): add formatCbo
hyanmandian Sep 29, 2026
ae2a308
feat(cfop): add formatCfop
hyanmandian Sep 29, 2026
6fe8ca1
feat(nbs): add parseNbs
hyanmandian Sep 29, 2026
dc85223
feat(nbs): add the pad option to formatNbs
hyanmandian Sep 29, 2026
ee75fa0
fix(types): re-export option types from the cnpj and license plate su…
hyanmandian Sep 29, 2026
871607b
docs(format): state the empty value rule under pad in every formatter
hyanmandian Sep 29, 2026
ebdecb0
docs(license-plate): name IsValidLicensePlateOptions in the isValidLi…
hyanmandian Sep 29, 2026
1316022
refactor(comments): fold the last prose comments into JSDoc and drop …
hyanmandian Sep 29, 2026
d06354d
docs(types): keep the JSDoc of exported type keys to one line
hyanmandian Sep 29, 2026
e5b5e1c
refactor(internals): split normalizeStateCode out of read-state-code
hyanmandian Sep 29, 2026
c585777
docs(context7): list every dataset-backed subpath in the lazy-load rule
hyanmandian Sep 29, 2026
2899a97
test(boleto): keep the reference date of the barcode property within …
hyanmandian Sep 29, 2026
0df8ce1
perf(get-address-info-by-cep): check the answered state against the C…
hyanmandian Sep 29, 2026
d4a6207
fix(pix-key): reject a phone key that repeats the country code
hyanmandian Sep 29, 2026
b32ce6c
fix(get-address-info-by-cep): read a provider CEP without its leading…
hyanmandian Sep 29, 2026
5061f0a
docs(get-timezone-by-state): cite the decree that sets the zones inst…
hyanmandian Sep 29, 2026
91963e5
docs(get-boleto-info): state the exact window where an old factor fli…
hyanmandian Sep 29, 2026
f193887
docs: fix dead citations and small wording slips in the docs
hyanmandian Sep 29, 2026
9a35612
docs(boleto): state that a 44 digit barcode starting with 8 is always…
hyanmandian Sep 29, 2026
425bc30
docs: correct the CEP ranges wording, the legal nature successors and…
hyanmandian Sep 29, 2026
e9157f2
test(mutation): kill the surviving mutants of the CEP and phone code,…
hyanmandian Sep 29, 2026
a3e5511
fix(is-valid-phone): apply the character check to the string form of …
hyanmandian Sep 29, 2026
99f3c20
fix(read-municipality-area-code): read the index by own key only
hyanmandian Sep 29, 2026
0ad6d4e
test(mutation): drop a dead format check and the directives of the fo…
hyanmandian Sep 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion context7.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"rules": [
"The package has zero runtime dependencies and ships as ESM plus a UMD build; nothing else needs to be installed to use it.",
"Import from the root: import { isValidCpf } from '@brazilian-utils/brazilian-utils'. Every util is also a kebab-case subpath, e.g. '@brazilian-utils/brazilian-utils/is-valid-cpf'.",
"Use the subpaths to lazy-load the dataset-backed utils (getMunicipalities, getMunicipalityByCode, getCodeByMunicipalityName, getMunicipalitiesByAreaCode, getAreaCodeByMunicipalityCode, getCnae, getCbo, getCest, getCfop, getCid10, isValidCid10, getIsbnInfo, formatIsbn, getClassTrib, isValidNcm, getBanks, getNbs, getServiceItem): each one embeds a large official table.",
"Use the subpaths to lazy-load the dataset-backed utils (getMunicipalities, getMunicipalityByCode, getCodeByMunicipalityName, getMunicipalitiesByAreaCode, getAreaCodeByMunicipalityCode, getCnae, getCbo, getCest, getCfop, getCid10, isValidCid10, getIsbnInfo, formatIsbn, getClassTrib, isValidNcm, getBanks, getBankByCode, getBankByIspb, getNbs, getServiceItem, and the deprecated getMunicipality and getCities): each one embeds a large official table.",
"Never import the same util from both the root and its subpath in one app: a bundler treats them as two unrelated modules and bundles the dataset twice.",
"Public functions never throw on bad input (null, undefined, wrong type): isValid* return false, format* and parse* return '', single-item getters return null, list getters return [].",
"The only utils that reject are the async getAddressInfoByCep (GetAddressInfoByCepError: NotFound, Validation, Service) and getCepInfoByAddress (GetCepInfoByAddressError: NotFound, Validation).",
Expand Down
8 changes: 4 additions & 4 deletions docs/guides/address-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ keywords: ["CEP lookup", "address by CEP", "autofill address", "getAddressInfoBy

Type a CEP and the rest of the address fills itself. Pick the framework: each example runs the code below it, which you can copy as is.

`getAddressInfoByCep` asks the CEP providers and returns the street, neighborhood, city and state, or throws when no one has that CEP. It is asked only once `isValidCep` says the CEP is complete, so a request is not made on every keystroke, and what comes back stays editable: a lookup fills a form, it does not own it. The [document field guide](document-field.md) has the mask that keeps the caret where it belongs.
`getAddressInfoByCep` asks the CEP providers and returns the street, neighborhood, city and state, or throws when no one has that CEP. It is asked only once `isValidCep` says the CEP is complete, so a request is not made on every keystroke, and what comes back stays editable: a lookup fills a form, it does not own it. The [document field guide](guides/document-field.md) has the mask that keeps the caret where it belongs.


<div class="example" data-name="React" data-demo="/snippets/live/?dir=address-form/react&example=address-form.tsx">

A hook takes the CEP and gives back what is known about it; the form draws that. The CEP field is the one the [document field guide](document-field.md) builds:
A hook takes the CEP and gives back what is known about it; the form draws that. The CEP field is the one the [document field guide](guides/document-field.md) builds:

<div class="file" data-file="address-form.tsx">

Expand All @@ -29,7 +29,7 @@ A hook takes the CEP and gives back what is known about it; the form draws that.

<div class="example" data-name="Angular" data-demo="/snippets/live/?dir=address-form/angular&example=address-form.ts">

A `resource` takes the CEP and gives back what is known about it, reloading when it changes. The CEP field is the one the [document field guide](document-field.md) builds:
A `resource` takes the CEP and gives back what is known about it, reloading when it changes. The CEP field is the one the [document field guide](guides/document-field.md) builds:

<div class="file" data-file="address-form.ts">

Expand All @@ -47,7 +47,7 @@ A `resource` takes the CEP and gives back what is known about it, reloading when

<div class="example" data-name="Vue" data-demo="/snippets/live/?dir=address-form/vue&example=address-form.vue">

A composable takes the CEP and gives back what is known about it; the form draws that. The CEP field is the one the [document field guide](document-field.md) builds:
A composable takes the CEP and gives back what is known about it; the form draws that. The CEP field is the one the [document field guide](guides/document-field.md) builds:

<div class="file" data-file="address-form.vue">

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Each of these builds the document on its own first, so it can be reused wherever

<div class="example" data-name="Standard Schema">

No schema library at all: `toStandardSchema` gives the validator the interface every form library speaks.
No schema library at all: `toStandardSchema` gives the validator the interface every form library speaks. VeeValidate takes it as `rules` from version 5 on, and Hono validates an object, so its route wraps the validator for the JSON body.

<div class="variant" data-variant="CPF">

Expand Down
4 changes: 2 additions & 2 deletions docs/guides/state-city.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
title: "State and city"
description: "Pick a state and the cities of that state load on demand, with Brazilian Utils in React, Angular, Vue and plain JavaScript."
keywords: ["state and city select", "IBGE cities", "getCities", "lazy import", "code splitting", "municipalities of a state"]
keywords: ["state and city select", "IBGE municipalities", "getMunicipalities", "lazy import", "code splitting", "municipalities of a state"]
---

Pick a state and its cities fill the second select. Pick the framework: each example runs the code below it, which you can copy as is.

The point of this one is when each table is loaded, and the answer is: when someone opens the select that shows it. Not with the page, and not when a state is picked either — a form where the city is filled in by something else, or left alone, never fetches 154 KB of cities. The states are 27 rows, 2.5 KB; the cities are 5,571 of them, 154 KB. Each util is its own subpath, so `await import("@brazilian-utils/brazilian-utils/get-cities")` fetches that table and nothing else. A bundler makes it a chunk of its own; the browser fetches it once and keeps it, so only the first opening waits.
The point of this one is when each table is loaded, and the answer is: when someone opens the select that shows it. Not with the page, and not when a state is picked either. A form where the city is filled in by something else, or left alone, never fetches 148 KB of municipalities. The states are 27 rows, 2.5 KB; the municipalities are 5,571 of them, 148 KB. Each util is its own subpath, so `await import("@brazilian-utils/brazilian-utils/get-municipalities")` fetches that table and nothing else. Each option takes the IBGE `code` of the municipality as its value and the `name` as its label, since names repeat across states (there are two "Pau D'Arco"). A bundler makes it a chunk of its own; the browser fetches it once and keeps it, so only the first opening waits.


<div class="example" data-name="React" data-demo="/snippets/live/?dir=state-city/react&example=state-city.tsx">
Expand Down
2 changes: 1 addition & 1 deletion docs/pt-br/guides/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ O `narrow` recebe ele, e diz o que o valor tem que ser quando recusa:

<div class="example" data-name="Standard Schema">

Sem biblioteca de schema nenhuma: o `toStandardSchema` dá ao validador a interface que toda biblioteca de formulário fala.
Sem biblioteca de schema nenhuma: o `toStandardSchema` dá ao validador a interface que toda biblioteca de formulário fala. O VeeValidate aceita esse schema em `rules` a partir da versão 5, e o Hono valida um objeto, então a rota embrulha o validador para o corpo JSON.

<div class="variant" data-variant="CPF">

Expand Down
6 changes: 3 additions & 3 deletions docs/pt-br/guides/state-city.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
title: "Estado e cidade"
description: "Escolha um estado e as cidades dele carregam sob demanda, com Brazilian Utils em React, Angular, Vue e JavaScript puro."
keywords: ["select de estado e cidade", "cidades do IBGE", "getCities", "import lazy", "code splitting", "municípios de um estado"]
keywords: ["select de estado e cidade", "municípios do IBGE", "getMunicipalities", "import lazy", "code splitting", "municípios de um estado"]
---

Escolha um estado e as cidades dele preenchem o segundo select. Escolha o framework: cada exemplo roda o código logo abaixo dele, que pode ser copiado do jeito que está.

O ponto aqui é quando cada tabela é carregada, e a resposta é: quando alguém abre o select que a mostra. Nem com a página, nem ao escolher um estado — num formulário em que a cidade vem preenchida de outro lugar, ou é deixada em branco, os 154 KB de cidades nunca são buscados. Os estados são 27 linhas, 2,5 KB; as cidades são 5.571, 154 KB. Cada utilitário é um subpath, então `await import("@brazilian-utils/brazilian-utils/get-cities")` busca essa tabela e nada mais. O bundler transforma isso num chunk separado, e o browser busca uma vez e guarda, então só a primeira abertura espera.
O ponto aqui é quando cada tabela é carregada, e a resposta é: quando alguém abre o select que a mostra. Nem com a página, nem ao escolher um estado. Num formulário em que a cidade vem preenchida de outro lugar, ou é deixada em branco, os 148 KB de municípios nunca são buscados. Os estados são 27 linhas, 2,5 KB; os municípios são 5.571, 148 KB. Cada utilitário é um subpath, então `await import("@brazilian-utils/brazilian-utils/get-municipalities")` busca essa tabela e nada mais. Cada opção usa o `code` IBGE do município como valor e o `name` como rótulo, já que os nomes se repetem entre estados (existem dois "Pau D'Arco"). O bundler transforma isso num chunk separado, e o browser busca uma vez e guarda, então só a primeira abertura espera.


<div class="example" data-name="React" data-demo="/snippets/live/?dir=state-city/react&example=state-city.tsx">
Expand Down Expand Up @@ -93,4 +93,4 @@ Sem build: salve como um arquivo `.html` e abra. Cada subpath é um módulo pró

</div>

A [introdução](pt-br/getting-started.md#bundle-size) lista todos os utilitários que embutem uma tabela e valem um subpath próprio.
A [introdução](pt-br/getting-started.md#tamanho-do-bundle) lista todos os utilitários que embutem uma tabela e valem um subpath próprio.
Loading
Loading