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
11 changes: 8 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,14 @@ 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, 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.
(banks, municipalities, CNAE, CBO, CEST, CFOP, NCM, NBS, CID-10, 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. Every
generator runs in the same job, so one of them failing opens no pull request at all: when
`scripts/cid10.ts` reports a SHA-256 other than the reviewed `CID10_ZIP_SHA256` (DATASUS serves
that archive over plain HTTP, so the digest is what makes the download safe), review the new
archive, put its digest in the generator and regenerate, otherwise the other datasets stay
frozen.
- 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, getCest, isValidCest, 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, getCid10, 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
2 changes: 2 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ A few utils embed an official dataset and weigh far more than everything else co

| Util | Dataset | Minified | Gzipped |
| --- | --- | --- | --- |
| `getCid10` | CID-10 V2008 categories and subcategories, with the DATASUS descriptions | 1030.4 KB | 146.9 KB |
| `getMunicipalities` · `getMunicipalityByCode` · `getMunicipality` | 5571 IBGE municipalities, with names and codes | 154.9 - 156.5 KB | 50.3 - 50.4 KB |
| `getCities` | 5571 IBGE municipality names | 154.2 KB | 49.8 KB |
| `isValidNcm` | NCM (Nomenclatura Comum do Mercosul) codes | 114.2 KB | 24.6 KB |
Expand All @@ -79,6 +80,7 @@ A few utils embed an official dataset and weigh far more than everything else co
| `getClassTrib` | cClassTrib (IBS/CBS) names and descriptions | 50.8 KB | 9.6 KB |
| `getBanks` · `getBankByCode` · `getBankByIspb` | Banco Central STR participants (COMPE + ISPB) | 38.3 - 38.6 KB | 9.5 - 9.7 KB |
| `isValidServiceItem` · `getServiceItem` | Service list of the Lei Complementar 116/2003 | 27.2 KB | 8.9 KB |
| `isValidCid10` | CID-10 V2008 category and subcategory codes, without the descriptions | 27.0 KB | 7.4 KB |

The root of the package is a single ESM module, so a bundler cannot split one of these datasets out of it: importing a heavy util from the root puts its whole dataset in your main bundle, and a dynamic `import()` of the root does not help. To lazy-load one, import it from its own subpath:

Expand Down
2 changes: 2 additions & 0 deletions docs/pt-br/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Alguns utilitários embutem uma base de dados oficial e pesam muito mais que tod

| Utilitário | Base de dados | Minificado | Gzip |
| --- | --- | --- | --- |
| `getCid10` | categorias e subcategorias da CID-10 V2008, com as descrições do DATASUS | 1030,4 KB | 146,9 KB |
| `getMunicipalities` · `getMunicipalityByCode` · `getMunicipality` | 5571 municípios do IBGE, com nomes e códigos | 154,9 - 156,5 KB | 50,3 - 50,4 KB |
| `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 |
Expand All @@ -79,6 +80,7 @@ Alguns utilitários embutem uma base de dados oficial e pesam muito mais que tod
| `getClassTrib` | nomes e descrições do cClassTrib (IBS/CBS) | 50,8 KB | 9,6 KB |
| `getBanks` · `getBankByCode` · `getBankByIspb` | participantes do STR do Banco Central (COMPE + ISPB) | 38,3 - 38,6 KB | 9,5 - 9,7 KB |
| `isValidServiceItem` · `getServiceItem` | lista de serviços da Lei Complementar 116/2003 | 27,2 KB | 8,9 KB |
| `isValidCid10` | códigos das categorias e subcategorias da CID-10 V2008, sem as descrições | 27,0 KB | 7,4 KB |

A raiz do pacote é um único módulo ESM, então o bundler não consegue separar uma dessas bases de dados dele: importar um utilitário pesado da raiz coloca a base inteira no seu bundle principal, e um `import()` dinâmico da raiz não ajuda. Para carregar sob demanda, importe do subpath próprio:

Expand Down
72 changes: 72 additions & 0 deletions docs/pt-br/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -3275,6 +3275,78 @@ getGtinInfo('7890000000018'); // null (dígito verificador errado)

Fonte: [GS1 General Specifications](https://ref.gs1.org/standards/genspecs/), [calculadora de dígito verificador da GS1](https://www.gs1.org/services/how-calculate-check-digit-manually), [Nota Técnica 2021.003 da SEFAZ](https://www.nfe.fazenda.gov.br/portal/exibirArquivo.aspx?conteudo=SrQT9ys8ODo%3D) e [Tabela Prefixo GS1](https://www.nfe.fazenda.gov.br/portal/exibirArquivo.aspx?conteudo=Oc+fygAxwmc%3D) do Portal da NF-e.

## CID-10

### isValidCid10

Valida um código CID-10 contra as tabelas que o DATASUS publica, a edição brasileira da CID-10 (Classificação Estatística Internacional de Doenças e Problemas Relacionados à Saúde, 10ª revisão), o código que atestados médicos e sistemas de saúde carregam.

- Os dois níveis da classificação são válidos: as categorias de 3 caracteres (`A00`) e as subcategorias de 4 caracteres, escritas com o ponto (`A00.0`) ou sem ele (`A000`).
- Maiúsculas, minúsculas e espaços em volta são ignorados. Qualquer outra coisa (outro separador, um quinto caractere, um sufixo de cruz ou asterisco, um valor que não é string) é rejeitada.
- As tabelas da V2008 são a única fonte: um código que não está nelas, como `U07.1` (COVID-19), não é encontrado.
- Só uma tabela de códigos é lida (cerca de 27 KB minificada), não as descrições que `getCid10` carrega.

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

isValidCid10('A00.0'); // true
isValidCid10('a000'); // true
isValidCid10('A00'); // true (uma categoria)
isValidCid10('I10'); // true (uma categoria que não é subdividida)
isValidCid10('A00.5'); // false (A00 não tem a subcategoria 5)
isValidCid10('I10.0'); // false (I10 não tem subcategorias)
isValidCid10('A00-0'); // false (não é uma forma documentada)
```

### formatCid10

Formata um código CID-10 do jeito que ele é impresso: em maiúsculas, com um ponto entre a categoria de 3 caracteres e o quarto caractere da subcategoria. Só a estrutura muda; use `isValidCid10` para conferir um código com as tabelas.

- A máscara é aplicada até onde o valor vai, então uma categoria fica como está e o ponto só aparece com o quarto caractere.
- Caracteres fora da máscara são descartados e o valor é limitado a 4 caracteres.

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

formatCid10('A000'); // A00.0
formatCid10('f322'); // F32.2
formatCid10('A00'); // A00 (uma categoria não tem ponto)
formatCid10('A00.0'); // A00.0
```

### parseCid10

Remove a formatação de um código CID-10, mantém apenas letras e dígitos, em maiúsculas, e limita o resultado aos 4 caracteres de uma subcategoria, a forma que as tabelas do DATASUS guardam.

- Um valor mais curto passa até onde ele vai.

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

parseCid10('A00.0'); // 'A000'
parseCid10('f32.2'); // 'F322'
parseCid10('A00'); // 'A00'
```

### getCid10

Busca um código CID-10 e retorna a sua descrição oficial em português. O resultado é um registro `Cid10`: `{ code, description }`.

- Mesmas regras de entrada de `isValidCid10`. O `code` vem em maiúsculas e sem o ponto. Retorna `null` quando o código é desconhecido ou o valor não está em uma forma documentada.
- Este é o utilitário mais pesado do pacote: ele embute as 2045 categorias e 12188 subcategorias com suas descrições, cerca de 1 MB minificado (147 KB com gzip). Carregue-o sob demanda pelo seu subpath, como mostrado em [Tamanho do bundle](pt-br/getting-started.md#tamanho-do-bundle), e use `isValidCid10` quando a descrição não for necessária.

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

getCid10('A00.0'); // { code: 'A000', description: 'Cólera devida a Vibrio cholerae 01, biótipo cholerae' }
getCid10('a000'); // { code: 'A000', description: 'Cólera devida a Vibrio cholerae 01, biótipo cholerae' }
getCid10('A00'); // { code: 'A00', description: 'Cólera' }
getCid10('A00.5'); // null
getCid10('A00-0'); // null (não é uma forma documentada)
```

Fonte: [tabelas da CID-10 V2008 que o DATASUS publica em CSV](http://www2.datasus.gov.br/cid10/V2008/descrcsv.htm).

## Texto

### capitalize
Expand Down
72 changes: 72 additions & 0 deletions docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -3275,6 +3275,78 @@ getGtinInfo('7890000000018'); // null (wrong check digit)

Source: [GS1 General Specifications](https://ref.gs1.org/standards/genspecs/), [GS1 check digit calculator](https://www.gs1.org/services/how-calculate-check-digit-manually), [SEFAZ Nota Técnica 2021.003](https://www.nfe.fazenda.gov.br/portal/exibirArquivo.aspx?conteudo=SrQT9ys8ODo%3D) and the [Tabela Prefixo GS1](https://www.nfe.fazenda.gov.br/portal/exibirArquivo.aspx?conteudo=Oc+fygAxwmc%3D) of the Portal da NF-e.

## CID-10

### isValidCid10

Check if a CID-10 code exists in the tables DATASUS publishes, the Brazilian Portuguese edition of the ICD-10 (Classificação Estatística Internacional de Doenças e Problemas Relacionados à Saúde, 10th revision), the code medical certificates and health systems carry.

- Both levels of the classification are valid: the 3 character categories (`A00`) and the 4 character subcategories, written with the dot (`A00.0`) or without it (`A000`).
- Letter case and surrounding whitespace are ignored. Anything else (another separator, a fifth character, a dagger or asterisk suffix, a value that is not a string) is rejected.
- The V2008 tables are the only source: a code that is not in them, such as `U07.1` (COVID-19), is not found.
- Only a table of codes is read (about 27 KB minified), not the descriptions `getCid10` carries.

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

isValidCid10('A00.0'); // true
isValidCid10('a000'); // true
isValidCid10('A00'); // true (a category)
isValidCid10('I10'); // true (a category that is not subdivided)
isValidCid10('A00.5'); // false (A00 has no subcategory 5)
isValidCid10('I10.0'); // false (I10 has no subcategories)
isValidCid10('A00-0'); // false (not a documented form)
```

### formatCid10

Format a CID-10 code the way it is printed: upper case, with a dot between the 3 character category and the fourth character of the subcategory. Only the structure changes; use `isValidCid10` to check a code against the tables.

- The mask is applied as far as the value goes, so a category stays as it is and the dot only shows up with the fourth character.
- Characters outside the mask are dropped and the value is capped at 4 characters.

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

formatCid10('A000'); // A00.0
formatCid10('f322'); // F32.2
formatCid10('A00'); // A00 (a category has no dot)
formatCid10('A00.0'); // A00.0
```

### parseCid10

Remove CID-10 formatting, keep only letters and digits, upper case them and cap the result to the 4 characters of a subcategory, the form the DATASUS tables store.

- A shorter value passes through as far as it goes.

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

parseCid10('A00.0'); // 'A000'
parseCid10('f32.2'); // 'F322'
parseCid10('A00'); // 'A00'
```

### getCid10

Look a CID-10 code up and get its official Brazilian Portuguese description. The result is a `Cid10` record: `{ code, description }`.

- Same input rules as `isValidCid10`. `code` is upper case and has no dot. Returns `null` when the code is unknown or the value is not in a documented form.
- This is the heaviest util of the package: it embeds the 2045 categories and 12188 subcategories with their descriptions, about 1 MB minified (147 KB gzipped). Load it lazily through its subpath, as shown in [Bundle size](getting-started.md#bundle-size), and use `isValidCid10` when the description is not needed.

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

getCid10('A00.0'); // { code: 'A000', description: 'Cólera devida a Vibrio cholerae 01, biótipo cholerae' }
getCid10('a000'); // { code: 'A000', description: 'Cólera devida a Vibrio cholerae 01, biótipo cholerae' }
getCid10('A00'); // { code: 'A00', description: 'Cólera' }
getCid10('A00.5'); // null
getCid10('A00-0'); // null (not a documented form)
```

Source: [CID-10 V2008 tables DATASUS publishes as CSV](http://www2.datasus.gov.br/cid10/V2008/descrcsv.htm).

## Text

### capitalize
Expand Down
4 changes: 4 additions & 0 deletions jsr.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"./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-cid10": "./src/format-cid10/format-cid10.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 @@ -63,6 +64,7 @@
"./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-cid10": "./src/get-cid10/get-cid10.ts",
"./get-cities": "./src/get-cities/get-cities.ts",
"./get-class-trib": "./src/get-class-trib/get-class-trib.ts",
"./get-cnae": "./src/get-cnae/get-cnae.ts",
Expand Down Expand Up @@ -105,6 +107,7 @@
"./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-cid10": "./src/is-valid-cid10/is-valid-cid10.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",
"./is-valid-cnh": "./src/is-valid-cnh/is-valid-cnh.ts",
Expand Down Expand Up @@ -151,6 +154,7 @@
"./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-cid10": "./src/parse-cid10/parse-cid10.ts",
"./parse-cnae": "./src/parse-cnae/parse-cnae.ts",
"./parse-cnh": "./src/parse-cnh/parse-cnh.ts",
"./parse-cno": "./src/parse-cno/parse-cno.ts",
Expand Down
18 changes: 18 additions & 0 deletions reports/api/brazilian-utils.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ export type Cfop = {
description: string;
};

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

// @public
export type ClassTrib = {
code: string;
Expand Down Expand Up @@ -229,6 +235,9 @@ export type FormatCestOptions = {
pad?: boolean;
};

// @public
export const formatCid10: (value: string) => string;

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

Expand Down Expand Up @@ -553,6 +562,9 @@ export const getCest: (value: string | number) => Cest | null;
// @public
export const getCfop: (value: string | number) => Cfop | null;

// @public
export const getCid10: (value: string) => Cid10 | null;

// @public @deprecated
export const getCities: (state?: StateCode) => string[];

Expand Down Expand Up @@ -798,6 +810,9 @@ export const isValidCest: (value: string | number) => boolean;
// @public
export const isValidCfop: (value: string | number) => boolean;

// @public
export const isValidCid10: (value: string) => boolean;

// @public
export const isValidClassTrib: (value: string | number, options?: IsValidClassTribOptions) => boolean;

Expand Down Expand Up @@ -1075,6 +1090,9 @@ export const parseCest: (value: string | number) => string;
// @public
export const parseCfop: (value: string | number) => string;

// @public
export const parseCid10: (value: string) => string;

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

Expand Down
Loading
Loading