Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ but the few rules below hold everywhere:
they call.
- `src/_internals/` holds the helpers shared between utilities (check-digit arithmetic, `mod10`/
`mod11`, TLV parsing for Pix, sanitizers). `src/_internals/constants/` holds the datasets
(banks, municipalities, CNAE, CBO, CFOP, NCM, NBS, the LC 116/2003 service list, legal natures,
the IBS/CBS tables), generated by the `scripts/` from their official sources and refreshed by the
`Update datasets` workflow through a pull request, never edited by hand.
(banks, municipalities, CNAE, CBO, CEST, CFOP, NCM, NBS, the LC 116/2003 service list, legal
natures, the IBS/CBS tables), generated by the `scripts/` from their official sources and
refreshed by the `Update datasets` workflow through a pull request, never edited by hand.
- Utilities are synchronous, stateless and side-effect free: input in, value out, no globals, no
environment access, no dynamic code. The two exceptions are `getAddressInfoByCep` and
`getCepInfoByAddress`, the only utilities that do I/O: they query public CEP APIs (BrasilAPI,
Expand Down
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, getCnae, getCbo, getCfop, getClassTrib, isValidNcm, getBanks, getNbs, isValidNbs, getServiceItem, isValidServiceItem): each one embeds a large official table.",
"Use the subpaths to lazy-load the dataset-backed utils (getMunicipalities, getMunicipalityByCode, getCnae, getCbo, getCest, isValidCest, getCfop, getClassTrib, isValidNcm, getBanks, getNbs, isValidNbs, getServiceItem, isValidServiceItem): 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
1 change: 1 addition & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ A few utils embed an official dataset and weigh far more than everything else co
| `getCities` | 5571 IBGE municipality names | 154.2 KB | 49.8 KB |
| `isValidNcm` | NCM (Nomenclatura Comum do Mercosul) codes | 114.2 KB | 24.6 KB |
| `isValidCbo` · `getCbo` | CBO 2002 occupation titles | 119.1 KB | 30.6 KB |
| `isValidCest` · `getCest` | CEST descriptions and segments (Convênio ICMS 142/18) | 117.8 KB | 26.8 - 26.9 KB |
| `isValidCnae` · `getCnae` | CNAE-Subclasses 2.3 | 93.9 KB | 21.2 KB |
| `isValidNbs` · `getNbs` | NBS 2.0 (Nomenclatura Brasileira de Serviços) descriptions | 81.8 KB | 13.8 KB |
| `isValidCfop` · `getCfop` | CFOP operation descriptions | 68.9 KB | 6.9 KB |
Expand Down
1 change: 1 addition & 0 deletions docs/pt-br/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Alguns utilitários embutem uma base de dados oficial e pesam muito mais que tod
| `getCities` | nomes dos 5571 municípios do IBGE | 154,2 KB | 49,8 KB |
| `isValidNcm` | códigos NCM (Nomenclatura Comum do Mercosul) | 114,2 KB | 24,6 KB |
| `isValidCbo` · `getCbo` | títulos das ocupações da CBO 2002 | 119,1 KB | 30,6 KB |
| `isValidCest` · `getCest` | descrições e segmentos do CEST (Convênio ICMS 142/18) | 117,8 KB | 26,8 - 26,9 KB |
| `isValidCnae` · `getCnae` | CNAE-Subclasses 2.3 | 93,9 KB | 21,2 KB |
| `isValidNbs` · `getNbs` | descrições da NBS 2.0 (Nomenclatura Brasileira de Serviços) | 81,8 KB | 13,8 KB |
| `isValidCfop` · `getCfop` | descrições das operações do CFOP | 68,9 KB | 6,9 KB |
Expand Down
71 changes: 71 additions & 0 deletions docs/pt-br/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -3001,6 +3001,77 @@ getCfop('abc5102'); // null (não é uma forma documentada)

Fonte: [Anexo II consolidado do Convênio SINIEF s/nº 1970](https://www.confaz.fazenda.gov.br/legislacao/ajustes/sinief/cfop_cvsn_1-6.24), última alteração pelo [Ajuste SINIEF 39/25](https://www.confaz.fazenda.gov.br/legislacao/ajustes/2025/AJ039_25).

### isValidCest

Valida um CEST (Código Especificador da Substituição Tributária) contra os anexos do Convênio ICMS 142/18, no texto consolidado vigente.

- Só os itens em vigor contam: um item que os anexos marcam como revogado é rejeitado.
- A verificação é só do código: ela não diz se o código combina com um dado NCM, nem se um estado aplica o regime de substituição tributária a ele.
- Um CEST tem 7 dígitos: os dois primeiros são o segmento, do terceiro ao quinto o item do segmento e os dois últimos a especificação do item (cláusula sexta, IV).
- Aceita uma string com os 7 dígitos ou com a forma `NN.NNN.NN` que os anexos imprimem, com um único separador entre os grupos e espaços opcionais nas extremidades, ou um inteiro seguro não negativo. Qualquer outra string é rejeitada em vez de ter os dígitos pinçados.
- O zero à esquerda dos segmentos 01 a 09 faz parte do código, então um valor escrito apenas com dígitos é completado com zeros à esquerda até 7, como string ou como número: `100100`, `'100100'` e `'0100100'` são o mesmo código. Um valor mascarado é lido como foi escrito.

```javascript
import { isValidCest } from '@brazilian-utils/brazilian-utils';

isValidCest('01.001.00'); // true
isValidCest('0100100'); // true
isValidCest(100100); // true (completado para 7 dígitos, ou seja, '0100100')
isValidCest('03.001.00'); // false (um item revogado)
isValidCest('0000000'); // false
isValidCest('abc0100100'); // false (não é uma forma documentada)
isValidCest(-100100); // false (não é um inteiro seguro não negativo)
```

### formatCest

Formata um CEST (Código Especificador da Substituição Tributária) na forma `NN.NNN.NN` que os anexos do Convênio ICMS 142/18 imprimem. Só a estrutura muda; use `isValidCest` para conferir um código com os anexos.

- **Opções** (`FormatCestOptions`): `pad` (padrão `false`) completa antes o valor com zeros à esquerda até os 7 dígitos de um código completo.
- Mesmas regras de `formatNcm`: sem `pad` a máscara é aplicada até onde o valor vai, que é o que um campo sendo digitado precisa, os caracteres fora dela são descartados e um número é lido como a string dos seus dígitos, ou seja, só é completado com `pad: true`.

```javascript
import { formatCest } from '@brazilian-utils/brazilian-utils';

formatCest('0100100'); // 01.001.00
formatCest(2899900); // 28.999.00
formatCest('01001'); // 01.001 (máscara aplicada até onde o valor vai)
formatCest(100100, { pad: true }); // 01.001.00 (completado até 7 dígitos antes)
formatCest('abc0100100'); // 01.001.00 (só os dígitos são lidos)
```

### parseCest

Remove a formatação do CEST (Código Especificador da Substituição Tributária), mantém apenas os dígitos e limita o resultado aos 7 dígitos de um código completo.

- Mesmas regras de `parseCbo`: nada é completado com zeros à esquerda aqui, então o zero à esquerda dos segmentos 01 a 09 precisa estar escrito. Use `isValidCest` ou `getCest`, que completam um código numérico sem máscara, para consultar um código.

```javascript
import { parseCest } from '@brazilian-utils/brazilian-utils';

parseCest('01.001.00'); // '0100100'
parseCest('28.999'); // '28999' (um código parcial é mantido como foi escrito)
```

### getCest

Consulta um CEST (Código Especificador da Substituição Tributária) e retorna a descrição do bem ou mercadoria e o nome do seu segmento, como os Anexos I a XXVI do Convênio ICMS 142/18 os redigem. O resultado é um registro `Cest`: `{ code, description, segment }`.

- Mesmas regras de `isValidCest`. Retorna `null` para um código desconhecido, revogado ou malformado.
- Os códigos NCM/SH que os anexos associam a cada CEST não fazem parte do resultado.

```javascript
import { getCest } from '@brazilian-utils/brazilian-utils';

getCest('05.001.00'); // { code: '0500100', description: 'Cimento', segment: 'Cimentos' }
getCest(500100); // { code: '0500100', description: 'Cimento', segment: 'Cimentos' }
getCest('03.001.00'); // null (um item revogado)
getCest('0000000'); // null
getCest('abc0500100'); // null (não é uma forma documentada)
```

Fonte: [Convênio ICMS 142/18 consolidado](https://www.confaz.fazenda.gov.br/legislacao/convenios/2018/CV142_18), alterado por último pelo Convênio ICMS 180/24.

### isValidCst

Valida um código de CST (Código de Situação Tributária) para um tributo. Informe o tributo em `options.tax`:
Expand Down
71 changes: 71 additions & 0 deletions docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -3001,6 +3001,77 @@ getCfop('abc5102'); // null (not a documented form)

Source: [consolidated Anexo II of Convênio SINIEF s/nº 1970](https://www.confaz.fazenda.gov.br/legislacao/ajustes/sinief/cfop_cvsn_1-6.24), last amended by [Ajuste SINIEF 39/25](https://www.confaz.fazenda.gov.br/legislacao/ajustes/2025/AJ039_25).

### isValidCest

Check if a CEST (Código Especificador da Substituição Tributária) is listed in the annexes of Convênio ICMS 142/18, the consolidated text in force.

- Only the items in force count: an item the annexes mark as revoked is rejected.
- The check is about the code alone: it does not tell whether the code suits a given NCM, nor whether a state applies the substituição tributária regime to it.
- A CEST has 7 digits: the first two are the segment, the third to the fifth the item of the segment and the last two the specification of the item (cláusula sexta, IV).
- Accepts a string with the 7 digits or with the `NN.NNN.NN` form the annexes print, with a single separator between the groups and optional surrounding whitespace, or a non-negative safe integer. Any other string is rejected instead of having its digits picked out.
- The leading zero of segments 01 to 09 is part of the code, so a value written as bare digits is left padded with zeros to 7, as a string or as a number: `100100`, `'100100'` and `'0100100'` are the same code. A masked value is read as written.

```javascript
import { isValidCest } from '@brazilian-utils/brazilian-utils';

isValidCest('01.001.00'); // true
isValidCest('0100100'); // true
isValidCest(100100); // true (padded to 7 digits, so this is '0100100')
isValidCest('03.001.00'); // false (a revoked item)
isValidCest('0000000'); // false
isValidCest('abc0100100'); // false (not a documented form)
isValidCest(-100100); // false (not a non-negative safe integer)
```

### formatCest

Format a CEST (Código Especificador da Substituição Tributária) in the `NN.NNN.NN` form the annexes of Convênio ICMS 142/18 print. Only the structure changes; use `isValidCest` to check a code against the annexes.

- **Options** (`FormatCestOptions`): `pad` (default `false`) first left pads the value with zeros to the 7 digits of a complete code.
- Same rules as `formatNcm`: without `pad` the mask is applied as far as the value goes, which is what an input being typed into needs, characters outside it are dropped, and a number is read as the string of its digits, so it is only padded under `pad: true`.

```javascript
import { formatCest } from '@brazilian-utils/brazilian-utils';

formatCest('0100100'); // 01.001.00
formatCest(2899900); // 28.999.00
formatCest('01001'); // 01.001 (masked as far as it goes)
formatCest(100100, { pad: true }); // 01.001.00 (padded to 7 digits first)
formatCest('abc0100100'); // 01.001.00 (only the digits are read)
```

### parseCest

Remove CEST (Código Especificador da Substituição Tributária) formatting, keep only digits, and cap the result to the 7 digits of a complete code.

- Same rules as `parseCbo`: nothing is left padded here, so the leading zero of segments 01 to 09 has to be written out. Use `isValidCest` or `getCest`, which do pad a bare numeric code, to look a code up.

```javascript
import { parseCest } from '@brazilian-utils/brazilian-utils';

parseCest('01.001.00'); // '0100100'
parseCest('28.999'); // '28999' (a partial code is kept as written)
```

### getCest

Look a CEST (Código Especificador da Substituição Tributária) up and get the description of the goods and the name of its segment, as Anexos I to XXVI of Convênio ICMS 142/18 word them. The result is a `Cest` record: `{ code, description, segment }`.

- Same rules as `isValidCest`. Returns `null` for an unknown, revoked or malformed code.
- The NCM/SH codes the annexes pair each CEST with are not part of the entry.

```javascript
import { getCest } from '@brazilian-utils/brazilian-utils';

getCest('05.001.00'); // { code: '0500100', description: 'Cimento', segment: 'Cimentos' }
getCest(500100); // { code: '0500100', description: 'Cimento', segment: 'Cimentos' }
getCest('03.001.00'); // null (a revoked item)
getCest('0000000'); // null
getCest('abc0500100'); // null (not a documented form)
```

Source: [consolidated Convênio ICMS 142/18](https://www.confaz.fazenda.gov.br/legislacao/convenios/2018/CV142_18), last amended by Convênio ICMS 180/24.

### isValidCst

Check if a CST (Código de Situação Tributária) code is valid for a given tax. Pass the tax through `options.tax`:
Expand Down
4 changes: 4 additions & 0 deletions jsr.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"./format-cei": "./src/format-cei/format-cei.ts",
"./format-cep": "./src/format-cep/format-cep.ts",
"./format-certidao": "./src/format-certidao/format-certidao.ts",
"./format-cest": "./src/format-cest/format-cest.ts",
"./format-cnae": "./src/format-cnae/format-cnae.ts",
"./format-cnh": "./src/format-cnh/format-cnh.ts",
"./format-cno": "./src/format-cno/format-cno.ts",
Expand Down Expand Up @@ -60,6 +61,7 @@
"./get-cbo": "./src/get-cbo/get-cbo.ts",
"./get-cep-info-by-address": "./src/get-cep-info-by-address/get-cep-info-by-address.ts",
"./get-certidao-info": "./src/get-certidao-info/get-certidao-info.ts",
"./get-cest": "./src/get-cest/get-cest.ts",
"./get-cfop": "./src/get-cfop/get-cfop.ts",
"./get-cities": "./src/get-cities/get-cities.ts",
"./get-class-trib": "./src/get-class-trib/get-class-trib.ts",
Expand Down Expand Up @@ -101,6 +103,7 @@
"./is-valid-cei": "./src/is-valid-cei/is-valid-cei.ts",
"./is-valid-cep": "./src/is-valid-cep/is-valid-cep.ts",
"./is-valid-certidao": "./src/is-valid-certidao/is-valid-certidao.ts",
"./is-valid-cest": "./src/is-valid-cest/is-valid-cest.ts",
"./is-valid-cfop": "./src/is-valid-cfop/is-valid-cfop.ts",
"./is-valid-class-trib": "./src/is-valid-class-trib/is-valid-class-trib.ts",
"./is-valid-cnae": "./src/is-valid-cnae/is-valid-cnae.ts",
Expand Down Expand Up @@ -146,6 +149,7 @@
"./parse-cei": "./src/parse-cei/parse-cei.ts",
"./parse-cep": "./src/parse-cep/parse-cep.ts",
"./parse-certidao": "./src/parse-certidao/parse-certidao.ts",
"./parse-cest": "./src/parse-cest/parse-cest.ts",
"./parse-cfop": "./src/parse-cfop/parse-cfop.ts",
"./parse-cnae": "./src/parse-cnae/parse-cnae.ts",
"./parse-cnh": "./src/parse-cnh/parse-cnh.ts",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"brazilian",
"cbo",
"cep",
"cest",
"cfop",
"cnae",
"cnh",
Expand Down
24 changes: 24 additions & 0 deletions reports/api/brazilian-utils.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ export type CertidaoInfo = {
// @public
export type CertidaoType = "birth" | "marriage" | "religious-marriage" | "death" | "stillbirth" | "banns" | "other" | "emancipation" | "interdiction";

// @public
export type Cest = {
code: string;
description: string;
segment: string;
};

// @public
export type Cfop = {
code: string;
Expand Down Expand Up @@ -214,6 +221,14 @@ export type FormatCertidaoOptions = {
pad?: boolean;
};

// @public
export const formatCest: (value: string | number, options?: FormatCestOptions) => string;

// @public
export type FormatCestOptions = {
pad?: boolean;
};

// @public
export const formatCnae: (value: string | number, options?: FormatCnaeOptions) => string;

Expand Down Expand Up @@ -532,6 +547,9 @@ export class GetCepInfoByAddressValidationError extends GetCepInfoByAddressError
// @public
export const getCertidaoInfo: (value: string) => CertidaoInfo | null;

// @public
export const getCest: (value: string | number) => Cest | null;

// @public
export const getCfop: (value: string | number) => Cfop | null;

Expand Down Expand Up @@ -774,6 +792,9 @@ export type IsValidCertidaoOptions = {
accept?: CertidaoType[];
};

// @public
export const isValidCest: (value: string | number) => boolean;

// @public
export const isValidCfop: (value: string | number) => boolean;

Expand Down Expand Up @@ -1048,6 +1069,9 @@ export const parseCep: (value: string | number) => string;
// @public
export const parseCertidao: (value: string | number) => string;

// @public
export const parseCest: (value: string | number) => string;

// @public
export const parseCfop: (value: string | number) => string;

Expand Down
Loading
Loading