br-utilities 0.0.0 → 1.0.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.
data/README.pt.md ADDED
@@ -0,0 +1,1296 @@
1
+ ![br-utilities para Ruby](https://br-utils.vercel.app/img/cover_br-utils.jpg)
2
+
3
+ > 🚀 **Suporte total ao [novo formato alfanumérico de CNPJ](https://github.com/user-attachments/files/23937961/calculodvcnpjalfanaumerico.pdf).**
4
+
5
+ > 🌎 [Access documentation in English](./README.md)
6
+
7
+ Kit em Ruby para as principais operações com dados brasileiros: CPF (Cadastro de Pessoa Física) e CNPJ (Cadastro Nacional da Pessoa Jurídica). Envolve [`cpf-utilities`](https://rubygems.org/gems/cpf-utilities) e [`cnpj-utilities`](https://rubygems.org/gems/cnpj-utilities) em uma única classe fachada (`BrUtils`).
8
+
9
+ ## Suporte a Ruby
10
+
11
+ | ![Ruby 3.1](https://img.shields.io/badge/Ruby-3.1-CC342D?logo=ruby&logoColor=white) | ![Ruby 3.2](https://img.shields.io/badge/Ruby-3.2-CC342D?logo=ruby&logoColor=white) | ![Ruby 3.3](https://img.shields.io/badge/Ruby-3.3-CC342D?logo=ruby&logoColor=white) | ![Ruby 3.4](https://img.shields.io/badge/Ruby-3.4-CC342D?logo=ruby&logoColor=white) | ![Ruby 4.0](https://img.shields.io/badge/Ruby-4.0-CC342D?logo=ruby&logoColor=white) |
12
+ | --- | --- | --- | --- | --- |
13
+ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ |
14
+
15
+ Requer Ruby **≥ 3.1** (veja `required_ruby_version` no gemspec).
16
+
17
+ ## Recursos
18
+
19
+ - ✅ **API unificada de alto nível**: Helpers de classe `BrUtils.cpf` / `.cnpj` encaminham para `BrUtils::DEFAULT.cpf` / `.cnpj`; cada domínio oferece `format`, `generate` e `is_valid`
20
+ - ✅ **Domínios empacotados**: [`cpf-utilities`](https://rubygems.org/gems/cpf-utilities) e [`cnpj-utilities`](https://rubygems.org/gems/cnpj-utilities) instalados juntos
21
+ - ✅ **CNPJ alfanumérico**: Suporte completo ao novo formato alfanumérico de CNPJ (a partir de 2026)
22
+ - ✅ **Instância reutilizável**: Classe `BrUtils` com configurações padrão opcionais de CPF e CNPJ (mapeamentos aninhados, kwargs planos de componentes ou instâncias prontas de utils)
23
+ - ✅ **Acesso em dois níveis**: Prefira atalhos de classes principais na raiz da fachada (`BrUtils::CpfFormatter`, `BrUtils::CnpjValidator`, …); Options, helpers e erros ficam nos módulos aninhados (`BrUtils::CpfFmt`, `BrUtils::CnpjUtils`, …). Os irmãos na raiz (`CpfUtils`, `CnpjUtils`, `CpfFmt`, …) continuam funcionando
24
+ - ✅ **Sobrescritas por chamada**: Configure padrões na fachada / utils de domínio; sobrescreva opções em uma única chamada de `format` / `generate` / `is_valid`
25
+ - ✅ **Tratamento de erros**: Erros de domínio propagam inalterados dos pacotes incluídos; esta gem define `BrUtils::TypeMismatchError` e `BrUtils::InvalidArgumentCombinationError` para uso indevido da API
26
+
27
+ ## Instalação
28
+
29
+ Instale a gem diretamente:
30
+
31
+ ```bash
32
+ gem install br-utilities
33
+ ```
34
+
35
+ Ou adicione ao seu `Gemfile` e execute `bundle install`:
36
+
37
+ ```ruby
38
+ gem 'br-utilities'
39
+ ```
40
+
41
+ Isso instala **`br-utilities`** junto com [`cpf-utilities`](https://rubygems.org/gems/cpf-utilities) e [`cnpj-utilities`](https://rubygems.org/gems/cnpj-utilities) (que por sua vez trazem os pacotes componentes de CPF e CNPJ). Você **não** precisa de `gem install` / linhas `gem` separados para os pacotes de domínio ao usar **`br-utilities`**.
42
+
43
+ ## Require
44
+
45
+ ```ruby
46
+ require 'br-utilities'
47
+ ```
48
+
49
+ ## Início rápido
50
+
51
+ Prefira os helpers de classe do agregador (`BrUtils.cpf` / `BrUtils.cnpj`) para chamadas pontuais — eles encaminham para `BrUtils::DEFAULT`:
52
+
53
+ ```ruby
54
+ require 'br-utilities'
55
+
56
+ cpf = '12345678909'
57
+ cnpj = '03603568000195'
58
+
59
+ # CPF (pessoa física)
60
+ BrUtils.cpf.format(cpf) # => "123.456.789-09"
61
+ BrUtils.cpf.generate(format: true) # => ex.: "478.442.410-55"
62
+ BrUtils.cpf.is_valid('123.456.789-09') # => true
63
+
64
+ # CNPJ (pessoa jurídica)
65
+ BrUtils.cnpj.format(cnpj) # => "03.603.568/0001-95"
66
+ BrUtils.cnpj.generate(format: true) # => ex.: "AB.123.CDE/0001-55"
67
+ BrUtils.cnpj.is_valid('98765432000198') # => true
68
+ ```
69
+
70
+ **Com agregadores de domínio:**
71
+
72
+ ```ruby
73
+ require 'br-utilities'
74
+
75
+ cpf = '12345678909'
76
+ cnpj = '03603568000195'
77
+
78
+ CpfUtils.format(cpf) # => "123.456.789-09"
79
+ CnpjUtils.format(cnpj) # => "03.603.568/0001-95"
80
+ CpfUtils.is_valid(cpf) # => true
81
+ CnpjUtils.is_valid(cnpj) # => true
82
+ ```
83
+
84
+ **Com helpers funcionais** (módulos irmãos na raiz, carregados por esta gem):
85
+
86
+ ```ruby
87
+ require 'br-utilities'
88
+
89
+ cpf = '12345678909'
90
+ cnpj = '03603568000195'
91
+
92
+ CpfFmt.cpf_fmt(cpf) # => "123.456.789-09"
93
+ CpfVal.cpf_val(cpf) # => true
94
+ CnpjFmt.cnpj_fmt(cnpj) # => "03.603.568/0001-95"
95
+ CnpjVal.cnpj_val(cnpj) # => true
96
+ ```
97
+
98
+ ## Utilização
99
+
100
+ Você pode trabalhar destas formas equivalentes:
101
+
102
+ 1. **`BrUtils.cpf` / `.cnpj`** — helpers de classe para chamadas rápidas (encaminham para `DEFAULT`).
103
+ 2. **`BrUtils::DEFAULT`** — singleton compartilhado mutável (o mesmo objeto usado pelos helpers de classe; em todo o processo / não isolado por thread).
104
+ 3. **`BrUtils.new`** — instância configurável com padrões compartilhados entre os domínios CPF e CNPJ.
105
+ 4. **Agregadores de domínio** — `CpfUtils` / `CnpjUtils` (ou `BrUtils::CpfUtils` / `BrUtils::CnpjUtils`) diretamente.
106
+ 5. **Classes principais sob `BrUtils`** — `BrUtils::CpfFormatter`, `BrUtils::CnpjGenerator` e atalhos relacionados.
107
+ 6. **Módulos aninhados do pacote** — Options, helpers, erros e tipos via `BrUtils::CpfFmt` / `CpfGen` / `CpfVal` / `CnpjFmt` / `CnpjGen` / `CnpjVal` / `CpfUtils` / `CnpjUtils`.
108
+ 7. **Módulos irmãos na raiz** (ainda suportados) — `CpfFmt`, `CnpjUtils` e demais inalterados.
109
+
110
+ Todas as abordagens expõem as mesmas opções e comportamento dentro de cada domínio. Para tabelas de opções exaustivas e detalhes específicos de cada componente, consulte o README de cada [pacote incluído](#pacotes-incluídos).
111
+
112
+ ### Helpers de classe (`BrUtils.cpf` / `.cnpj`)
113
+
114
+ Esses métodos de classe retornam as mesmas instâncias de utils de domínio que `BrUtils::DEFAULT`. Prefira-os para chamadas pontuais:
115
+
116
+ ```ruby
117
+ BrUtils.cpf.format('12345678909')
118
+ BrUtils.cpf.generate(format: true)
119
+ BrUtils.cpf.is_valid('12345678909')
120
+
121
+ BrUtils.cnpj.format('03603568000195')
122
+ BrUtils.cnpj.generate(type: 'numeric')
123
+ BrUtils.cnpj.is_valid('98765432000198')
124
+ ```
125
+
126
+ ### `BrUtils::DEFAULT` (instância padrão)
127
+
128
+ `BrUtils::DEFAULT` é o singleton pré-construído e **mutável** por trás dos helpers de classe (paridade com a exportação padrão do JS / `br_utils` do Python). Sua configuração é **em todo o processo e compartilhada entre threads**: mutá-lo (ex.: `DEFAULT.cpf = …`) afeta chamadas subsequentes de `BrUtils.cpf` / `.cnpj` para todos os callers no processo. Prefira `BrUtils.new` ou opções por chamada para trabalho concorrente ou isolado; instâncias customizadas permanecem independentes de `DEFAULT`:
129
+
130
+ ```ruby
131
+ BrUtils::DEFAULT.cpf = CpfUtils.new(formatter: { dash_key: '|' })
132
+ BrUtils.cpf.format('12345678909') # => "123.456.789|09"
133
+
134
+ custom = BrUtils.new
135
+ custom.cpf.format('12345678909') # => "123.456.789-09" (não afetado)
136
+ ```
137
+
138
+ ### `BrUtils` (classe)
139
+
140
+ Para utils de CPF ou CNPJ padrão customizados, crie sua própria instância:
141
+
142
+ ```ruby
143
+ require 'br-utilities'
144
+
145
+ utils = BrUtils.new(
146
+ cpf: {
147
+ formatter: { hidden: true, hidden_key: '#' },
148
+ generator: { format: true }
149
+ },
150
+ cnpj: {
151
+ formatter: { hidden: true },
152
+ generator: { type: 'numeric', format: true },
153
+ validator: { type: 'numeric' }
154
+ }
155
+ )
156
+
157
+ utils.cpf.format('12345678909') # => "123.###.###-##"
158
+ utils.cpf.generate # => ex.: "005.265.352-88"
159
+ utils.cnpj.format('03603568000195') # => "03.603.***/****-**"
160
+ utils.cnpj.generate # => ex.: "73.008.535/0005-06"
161
+
162
+ # Acessar ou substituir instâncias internas de domínio
163
+ utils.cpf # => CpfUtils
164
+ utils.cnpj # => CnpjUtils
165
+ ```
166
+
167
+ - **`BrUtils.new(settings = nil, **keywords)`**: Configurações opcionais. Passe um `Hash` de settings com chaves `:cpf` e/ou `:cnpj`, **ou** as mesmas chaves (mais kwargs planos de componentes) como argumentos nomeados — não ambos (passar ambos lança `BrUtils::InvalidArgumentCombinationError`).
168
+ - **`:cpf` / `:cnpj`**: Uma instância pronta de `CpfUtils` / `CnpjUtils` **ou** um `Hash` de configuração repassado ao construtor do utils correspondente. Dentro desse `Hash`, cada chave de recurso (`:formatter`, `:generator` e `:validator` para CNPJ) aceita um objeto de opções ou um mapeamento de valores de opção.
169
+ - **`:cpf_formatter`**, **`:cpf_generator`**, **`:cnpj_formatter`**, **`:cnpj_generator`**, **`:cnpj_validator`**: Argumentos planos de conveniência quando apenas componentes individuais precisam de customização. São ignorados quando o argumento `:cpf` ou `:cnpj` correspondente é fornecido.
170
+ - **`#cpf`**, **`#cnpj`**: Acessores (getters e setters) das instâncias de utils de domínio. Os setters aceitam uma instância de utils, um `Hash` de configuração ou `nil` para voltar aos padrões (substitui a instância inteira; não faz merge).
171
+
172
+ Opções planas no construtor (alternativa aos mapeamentos aninhados `:cpf` / `:cnpj`):
173
+
174
+ ```ruby
175
+ require 'br-utilities'
176
+
177
+ utils = BrUtils.new(
178
+ cpf_formatter: CpfFmt::CpfFormatterOptions.new(hidden: true, hidden_key: '#'),
179
+ cpf_generator: CpfGen::CpfGeneratorOptions.new(format: true),
180
+ cnpj_formatter: CnpjFmt::CnpjFormatterOptions.new(hidden: true, hidden_key: '#'),
181
+ cnpj_generator: CnpjGen::CnpjGeneratorOptions.new(format: true, type: 'numeric'),
182
+ cnpj_validator: CnpjVal::CnpjValidatorOptions.new(type: 'numeric')
183
+ )
184
+ ```
185
+
186
+ Passar um `Hash` de settings posicional junto com qualquer palavra-chave lança:
187
+
188
+ ```ruby
189
+ BrUtils.new({ cpf: {} }, cnpj: CnpjUtils.new)
190
+ # lança BrUtils::InvalidArgumentCombinationError
191
+ ```
192
+
193
+ ### Padrões da instância e sobrescritas por chamada
194
+
195
+ ```ruby
196
+ require 'br-utilities'
197
+
198
+ utils = BrUtils.new(
199
+ cpf: {
200
+ formatter: { hidden: true, hidden_key: '#' },
201
+ generator: { format: true }
202
+ },
203
+ cnpj: {
204
+ formatter: { hidden: true, hidden_key: '#' },
205
+ generator: { format: true },
206
+ validator: { type: 'numeric' }
207
+ }
208
+ )
209
+
210
+ cpf = '12345678909'
211
+ cnpj = '03603568000195'
212
+
213
+ utils.cpf.format(cpf) # => "123.###.###-##"
214
+ utils.cpf.format(cpf, hidden: false) # só nesta chamada: sem máscara
215
+ utils.cpf.generate(format: false) # só nesta chamada: saída compacta
216
+
217
+ utils.cnpj.format(cnpj) # => "03.603.###/####-##"
218
+ utils.cnpj.format(cnpj, hidden: false) # só nesta chamada: sem máscara
219
+ utils.cnpj.is_valid('1QB5UKALPYFP59') # => false (validador da instância é só numérico)
220
+ utils.cnpj.is_valid( # => true nesta chamada
221
+ '1QB5UKALPYFP59',
222
+ type: 'alphanumeric'
223
+ )
224
+ ```
225
+
226
+ Passar uma instância de `CnpjFmt::CnpjFormatterOptions`, `CnpjGen::CnpjGeneratorOptions` ou `CnpjVal::CnpjValidatorOptions` ao construtor de `BrUtils` armazena esse objeto por referência — mutá-lo depois afeta chamadas subsequentes sem sobrescrita por chamada.
227
+
228
+ Para alterar uma única opção aninhada sem substituir o utils de domínio inteiro, mute via os acessores de domínio (ex.: `utils.cpf.formatter.options.hidden = true`).
229
+
230
+ ### Operações de CPF
231
+
232
+ Os métodos de CPF são acessados via `BrUtils.cpf`, `utils.cpf`, `CpfUtils` ou os helpers `CpfFmt` / `CpfGen` / `CpfVal`. O CPF usa a API de [`cpf-utilities`](../cpf-utilities/README.pt.md).
233
+
234
+ #### Formatação (`#format` / `CpfFmt.cpf_fmt`)
235
+
236
+ | Opção | Tipo | Padrão | Descrição |
237
+ |--------|------|---------|-------------|
238
+ | `hidden` | `Boolean` | `false` | Se `true`, mascara dígitos entre `hidden_start` e `hidden_end` com `hidden_key` |
239
+ | `hidden_key` | `String` | `'*'` | Caractere(s) usados para substituir dígitos mascarados |
240
+ | `hidden_start` | `Integer` | `3` | Índice inicial (0–10, inclusivo) do intervalo a ocultar |
241
+ | `hidden_end` | `Integer` | `10` | Índice final (0–10, inclusivo) do intervalo a ocultar |
242
+ | `dot_key` | `String` | `'.'` | Delimitador de ponto (ex.: em `123.456.789`) |
243
+ | `dash_key` | `String` | `'-'` | Delimitador de hífen (ex.: antes dos dígitos verificadores `…-09`) |
244
+ | `escape` | `Boolean` | `false` | Se `true`, escapa caracteres especiais HTML no resultado |
245
+ | `encode` | `Boolean` | `false` | Se `true`, codifica o resultado para URL (similar ao `encodeURIComponent` do JavaScript) |
246
+ | `on_fail` | `Proc` / invocável | retorna `''` | Callback quando o tamanho da entrada sanitizada ≠ 11; o retorno é usado como resultado |
247
+
248
+ O **`on_fail`** padrão retorna uma string vazia. Comprimento inválido **não** lança exceção em `#format`.
249
+
250
+ ```ruby
251
+ require 'br-utilities'
252
+
253
+ cpf = '12345678909'
254
+
255
+ BrUtils.cpf.format(cpf) # => "123.456.789-09"
256
+ BrUtils.cpf.format(cpf, hidden: true, hidden_key: '#') # => "123.###.###-##"
257
+ BrUtils.cpf.format(cpf, dot_key: '', dash_key: '_') # => "123456789_09"
258
+
259
+ CpfFmt.cpf_fmt(cpf, hidden: true) # => "123.***.***-**"
260
+ ```
261
+
262
+ #### Geração (`#generate` / `CpfGen.cpf_gen`)
263
+
264
+ | Opção | Tipo | Padrão | Descrição |
265
+ |--------|------|---------|-------------|
266
+ | `format` | `Boolean` | `false` | Se `true`, retorna o CPF gerado no formato padrão (`000.000.000-00`) |
267
+ | `prefix` | `String` | `''` | String parcial inicial (0–9 dígitos). Não dígitos são removidos; caracteres faltantes são gerados e os dígitos verificadores calculados. Prefixos com mais de 9 dígitos são truncados silenciosamente. |
268
+
269
+ Regras de prefixo: a base (primeiros 9 dígitos) não pode ser toda zeros; 9 dígitos repetidos (ex.: `999999999`) não são permitidos.
270
+
271
+ ```ruby
272
+ require 'br-utilities'
273
+
274
+ BrUtils.cpf.generate # => ex.: "11508890048"
275
+ BrUtils.cpf.generate(format: true) # => ex.: "661.134.831-00"
276
+ BrUtils.cpf.generate(prefix: '123456789') # => "12345678909"
277
+ CpfGen.cpf_gen(prefix: '123456789', format: true) # => "123.456.789-09"
278
+ ```
279
+
280
+ #### Validação (`#is_valid` / `CpfVal.cpf_val`)
281
+
282
+ Aceita CPF formatado ou não (ou um `Array` de strings). Retorna **`true`** ou **`false`** sem lançar exceção para CPF inválido. Não há opções de validador.
283
+
284
+ ```ruby
285
+ require 'br-utilities'
286
+
287
+ BrUtils.cpf.is_valid('12345678909') # => true
288
+ BrUtils.cpf.is_valid('123.456.789-09') # => true
289
+ BrUtils.cpf.is_valid('12345678900') # => false
290
+ CpfVal.cpf_val('12345678909') # => true
291
+ ```
292
+
293
+ ### Operações de CNPJ
294
+
295
+ Os métodos de CNPJ são acessados via `BrUtils.cnpj`, `utils.cnpj`, `CnpjUtils` ou os helpers `CnpjFmt` / `CnpjGen` / `CnpjVal`. O CNPJ usa a API de [`cnpj-utilities`](../cnpj-utilities/README.pt.md).
296
+
297
+ #### Formatação (`#format` / `CnpjFmt.cnpj_fmt`)
298
+
299
+ | Opção | Tipo | Padrão | Descrição |
300
+ |--------|------|---------|-------------|
301
+ | `hidden` | `Boolean` | `false` | Se `true`, mascara caracteres entre `hidden_start` e `hidden_end` com `hidden_key` |
302
+ | `hidden_key` | `String` | `'*'` | Caractere(s) usados para substituir caracteres mascarados |
303
+ | `hidden_start` | `Integer` | `5` | Índice inicial (0–13, inclusivo) do intervalo a ocultar |
304
+ | `hidden_end` | `Integer` | `13` | Índice final (0–13, inclusivo) do intervalo a ocultar |
305
+ | `dot_key` | `String` | `'.'` | Delimitador de ponto (ex.: em `12.345.678`) |
306
+ | `slash_key` | `String` | `'/'` | Delimitador de barra (ex.: antes da filial `…/0001-90`) |
307
+ | `dash_key` | `String` | `'-'` | Delimitador de hífen (ex.: antes dos dígitos verificadores `…-90`) |
308
+ | `escape` | `Boolean` | `false` | Se `true`, escapa caracteres especiais HTML no resultado |
309
+ | `encode` | `Boolean` | `false` | Se `true`, codifica o resultado para URL (similar ao `encodeURIComponent` do JavaScript) |
310
+ | `on_fail` | `Proc` / invocável | retorna `''` | Callback quando o tamanho da entrada sanitizada ≠ 14; o retorno é usado como resultado |
311
+
312
+ O **`on_fail`** padrão retorna uma string vazia. Tipos de entrada incorretos lançam **`CnpjFmt::TypeMismatchError`**.
313
+
314
+ ```ruby
315
+ require 'br-utilities'
316
+
317
+ cnpj = '03603568000195'
318
+
319
+ BrUtils.cnpj.format(cnpj) # => "03.603.568/0001-95"
320
+ BrUtils.cnpj.format('12ABC34500DE99') # => "12.ABC.345/00DE-99"
321
+ BrUtils.cnpj.format( # => "03.603.###/####-##"
322
+ cnpj,
323
+ hidden: true,
324
+ hidden_key: '#'
325
+ )
326
+ BrUtils.cnpj.format( # => "03603568|0001_95"
327
+ cnpj,
328
+ dot_key: '',
329
+ slash_key: '|',
330
+ dash_key: '_'
331
+ )
332
+
333
+ CnpjFmt.cnpj_fmt(cnpj) # => "03.603.568/0001-95"
334
+ ```
335
+
336
+ #### Geração (`#generate` / `CnpjGen.cnpj_gen`)
337
+
338
+ | Opção | Tipo | Padrão | Descrição |
339
+ |--------|------|---------|-------------|
340
+ | `format` | `Boolean` | `false` | Se `true`, retorna o CNPJ gerado no formato padrão (`00.000.000/0000-00`) |
341
+ | `prefix` | `String` | `''` | String parcial inicial (0–12 caracteres alfanuméricos). Caracteres faltantes são gerados e os dígitos verificadores calculados. |
342
+ | `type` | `String` | `'alphanumeric'` | Conjunto de caracteres para a parte gerada aleatoriamente: `'numeric'`, `'alphabetic'` ou `'alphanumeric'`. **Os dígitos verificadores são sempre numéricos.** |
343
+
344
+ Regras de prefixo: o ID base (primeiros 8 caracteres) e o ID da filial (caracteres 9–12) não podem ser todos zeros; 12 dígitos repetidos (ex.: `111111111111`) também não são permitidos.
345
+
346
+ ```ruby
347
+ require 'br-utilities'
348
+
349
+ BrUtils.cnpj.generate # => ex.: "1GJTR3J3XSSA96"
350
+ BrUtils.cnpj.generate(format: true) # => ex.: "V1.J0V.8WE/DVZ7-50"
351
+ BrUtils.cnpj.generate( # => ex.: "12345678855883"
352
+ prefix: '12345678',
353
+ type: 'numeric'
354
+ )
355
+ CnpjGen.cnpj_gen(type: 'numeric') # => ex.: "65453043000178"
356
+ ```
357
+
358
+ #### Validação (`#is_valid` / `CnpjVal.cnpj_val`)
359
+
360
+ | Opção | Tipo | Padrão | Descrição |
361
+ |--------|------|---------|-------------|
362
+ | `case_sensitive` | `Boolean` | `true` | Se `false`, letras minúsculas são aceitas para CNPJ alfanumérico (a entrada é convertida para maiúsculas antes da validação). |
363
+ | `type` | `String` | `'alphanumeric'` | `'numeric'`: apenas dígitos (0–9); `'alphanumeric'`: dígitos e letras (0–9, A–Z). |
364
+
365
+ ```ruby
366
+ require 'br-utilities'
367
+
368
+ BrUtils.cnpj.is_valid('98765432000198') # => true
369
+ BrUtils.cnpj.is_valid('98765432000199') # => false
370
+ BrUtils.cnpj.is_valid('1QB5UKALPYFP59') # => true
371
+ BrUtils.cnpj.is_valid('1QB5UKALpyfp59') # => false
372
+ BrUtils.cnpj.is_valid( # => true
373
+ '1QB5UKALpyfp59',
374
+ case_sensitive: false
375
+ )
376
+ BrUtils.cnpj.is_valid( # => false
377
+ '1QB5UKALPYFP59',
378
+ type: 'numeric'
379
+ )
380
+
381
+ CnpjVal.cnpj_val('98765432000198') # => true
382
+ CnpjVal.cnpj_val('1QB5UKALpyfp59', case_sensitive: false) # => true
383
+ CnpjVal.cnpj_val('1QB5UKALPYFP59', type: 'numeric') # => false
384
+ ```
385
+
386
+ CNPJ inválido retorna **`false`** sem lançar exceção. Tipos de entrada incorretos lançam **`CnpjVal::TypeMismatchError`**.
387
+
388
+ ### Agregadores de domínio (isolados)
389
+
390
+ Use `CpfUtils` ou `CnpjUtils` diretamente quando precisar de apenas um domínio:
391
+
392
+ ```ruby
393
+ require 'br-utilities'
394
+
395
+ cpf_utils = CpfUtils.new(
396
+ formatter: { hidden: true },
397
+ generator: { format: true }
398
+ )
399
+
400
+ cnpj_utils = CnpjUtils.new(
401
+ formatter: { hidden: true },
402
+ generator: { format: true },
403
+ validator: { type: 'numeric' }
404
+ )
405
+
406
+ cpf_utils.format('12345678909') # => "123.***.***-**"
407
+ cnpj_utils.format('03603568000195') # => "03.603.***/****-**"
408
+ ```
409
+
410
+ ### Acessando componentes
411
+
412
+ Cada agregador de domínio expõe seu formatador, gerador e validador internos:
413
+
414
+ ```ruby
415
+ require 'br-utilities'
416
+
417
+ utils = BrUtils.new
418
+
419
+ utils.cpf.formatter.format('12345678909', hidden: true) # => "123.***.***-**"
420
+ utils.cpf.generator.generate(format: true) # => ex.: "545.507.690-68"
421
+ utils.cpf.validator.is_valid('12345678909') # => true
422
+
423
+ utils.cnpj.formatter.format('12ABC34500DE99') # => "12.ABC.345/00DE-99"
424
+ utils.cnpj.generator.generate(format: true) # => ex.: "8O.BE5.2KL/UI0Y-06"
425
+ utils.cnpj.validator.is_valid('03603568000195') # => true
426
+ ```
427
+
428
+ ### Usando classes componentes e módulos aninhados
429
+
430
+ Caminhos preferidos após `require 'br-utilities'`:
431
+
432
+ ```ruby
433
+ require 'br-utilities'
434
+
435
+ # Classes principais na raiz da fachada
436
+ formatter = BrUtils::CpfFormatter.new(hidden: true)
437
+ generator = BrUtils::CnpjGenerator.new(type: 'numeric')
438
+ validator = BrUtils::CnpjValidator.new
439
+
440
+ formatter.format('12345678909') # => "123.***.***-**"
441
+
442
+ # Options, helpers e erros nos módulos aninhados do pacote
443
+ options = BrUtils::CpfFmt::CpfFormatterOptions.new(dash_key: '|')
444
+ BrUtils::CpfFmt.cpf_fmt('12345678909') # => "123.456.789-09"
445
+
446
+ begin
447
+ BrUtils::CnpjFmt.cnpj_fmt(12_345)
448
+ rescue BrUtils::CnpjFmt::TypeMismatchError
449
+ # tipo de entrada incorreto
450
+ end
451
+ ```
452
+
453
+ Os irmãos na raiz continuam suportados (os mesmos objetos dos nests):
454
+
455
+ ```ruby
456
+ CpfFmt.cpf_fmt('12345678909', dash_key: '|') # => "123.456.789|09"
457
+ CpfGen.cpf_gen(format: true) # => ex.: "478.442.410-55"
458
+ CpfVal.cpf_val('12345678909') # => true
459
+ CnpjFmt.cnpj_fmt('01ABC234000X56', slash_key: '|') # => "01.ABC.234|000X-56"
460
+ CnpjGen.cnpj_gen(type: 'numeric') # => ex.: "65453043000178"
461
+ CnpjVal.cnpj_val('9JN7MGLJZXIO50') # => true
462
+ ```
463
+
464
+ Consulte [`cpf-utilities`](../cpf-utilities/README.pt.md) e [`cnpj-utilities`](../cnpj-utilities/README.pt.md) para detalhes completos de opções e erros.
465
+
466
+ ### Misturando estilos
467
+
468
+ Use `BrUtils` onde uma configuração compartilhada ajuda, e componentes ou helpers isolados em outros pontos — são as mesmas classes subjacentes:
469
+
470
+ ```ruby
471
+ require 'br-utilities'
472
+
473
+ utils = BrUtils.new(cnpj: { validator: { type: 'numeric' } })
474
+
475
+ # Via fachada
476
+ utils.cpf.format('12345678909') # => "123.456.789-09"
477
+
478
+ # Via componente retornado pela fachada
479
+ utils.cnpj.formatter.format('12ABC34500DE99') # => "12.ABC.345/00DE-99"
480
+
481
+ # Via instância de componente separada
482
+ BrUtils::CnpjFormatter.new.format('03603568000195') # => "03.603.568/0001-95"
483
+
484
+ # Via helpers funcionais
485
+ CpfFmt.cpf_fmt('12345678909') # => "123.456.789-09"
486
+ CnpjVal.cnpj_val('98.765.432/0001-98') # => true
487
+ ```
488
+
489
+ ## API
490
+
491
+ ### Exportações
492
+
493
+ Após `require 'br-utilities'`:
494
+
495
+ - **`BrUtils`**: Classe fachada para criar uma instância com configurações opcionais dos utils de CPF e CNPJ.
496
+ - **`BrUtils.cpf` / `.cnpj`**: Helpers de classe que encaminham para os acessores de domínio de `BrUtils::DEFAULT`.
497
+ - **`BrUtils::DEFAULT`**: Instância pré-construída e mutável de `BrUtils` (o mesmo objeto usado pelos helpers de classe). Em todo o processo / compartilhada entre threads — prefira `BrUtils.new` ou opções por chamada sob concorrência.
498
+ - **`BrUtils::VERSION`**: String da versão da gem.
499
+ - **Atalhos de classes principais**: `BrUtils::CpfFormatter`, `BrUtils::CpfFormatterOptions`, `BrUtils::CpfGenerator`, `BrUtils::CpfGeneratorOptions`, `BrUtils::CpfValidator`, `BrUtils::CnpjFormatter`, `BrUtils::CnpjFormatterOptions`, `BrUtils::CnpjGenerator`, `BrUtils::CnpjGeneratorOptions`, `BrUtils::CnpjValidator`, `BrUtils::CnpjValidatorOptions` (os mesmos objetos das classes irmãs). Atalhos de marcadores de erro: `BrUtils::CpfFormatterError`, `BrUtils::CpfGeneratorError`, `BrUtils::CpfValidatorError`, `BrUtils::CnpjFormatterError`, `BrUtils::CnpjGeneratorError`, `BrUtils::CnpjValidatorError`.
500
+ - **Módulos aninhados do pacote**: `BrUtils::CpfUtils`, `BrUtils::CnpjUtils`, `BrUtils::CpfFmt`, `BrUtils::CpfGen`, `BrUtils::CpfVal`, `BrUtils::CnpjFmt`, `BrUtils::CnpjGen`, `BrUtils::CnpjVal` — superfície completa dos irmãos (Options, helpers, erros, tipos).
501
+ - **Módulos irmãos na raiz** (ainda suportados): `CpfUtils`, `CnpjUtils`, `CpfFmt`, `CpfGen`, `CpfVal`, `CnpjFmt`, `CnpjGen`, `CnpjVal` — os mesmos objetos dos nests.
502
+
503
+ ### Erros e exceções
504
+
505
+ `BrUtils` define apenas erros de uso indevido da API para as regras de argumentos desta gem. Erros de domínio são lançados pelos pacotes incluídos e propagam inalterados.
506
+
507
+ #### Definidos por `br-utilities`
508
+
509
+ Os erros definidos por esta gem são **apenas uso indevido da API** (tipo errado ou combinação inválida de argumentos). Todo erro customizado inclui o módulo marcador `BrUtils::Error`. Esta gem **não** define `BrUtils::DomainError` nem folhas de domínio — falhas de domínio vêm apenas dos [pacotes incluídos](#propagados-dos-pacotes-incluídos) e mantêm os namespaces desses pacotes (`CpfFmt::…`, `CnpjGen::…`, …).
510
+
511
+ `rescue BrUtils::Error` captura **apenas** erros que esta gem lança. **Não** captura erros de componentes que propagam inalterados.
512
+
513
+ ##### Resumo
514
+
515
+ | Classe | Herda de | Categoria | Condição de disparo |
516
+ |-------|---------------|----------|-------------------|
517
+ | `BrUtils::InvalidArgumentCombinationError` | `BrUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include BrUtils::Error`) | Uso indevido da API | `Hash` de settings não-`nil` passado junto com qualquer argumento nomeado não-`nil` |
518
+ | `BrUtils::TypeMismatchError` | `BrUtils::TypeMismatchError < TypeError < StandardError` (+ `include BrUtils::Error`) | Uso indevido da API | Argumento `settings` não-`nil` em `BrUtils.new` não é um `Hash` |
519
+
520
+ ##### `BrUtils::Error` (módulo marcador)
521
+
522
+ - **Herança:** módulo marcador misturado em todo erro customizado que esta gem lança via `include` (não é uma classe).
523
+ - **Categoria:** N/A (apenas alvo de rescue) — não é um modo de falha por si só.
524
+ - **Quando é lançado:** Nunca lançado diretamente; incluído por todo erro customizado que esta gem lança.
525
+ - **Exemplo:** N/A
526
+ - **Como resgatar:**
527
+
528
+ ```ruby
529
+ rescue BrUtils::Error
530
+ # TypeMismatchError, InvalidArgumentCombinationError apenas desta gem
531
+ # (não CpfFmt::*, CnpjGen::* ou outros erros dos pacotes incluídos)
532
+ ```
533
+
534
+ ##### `BrUtils::TypeMismatchError`
535
+
536
+ - **Herança:** `BrUtils::TypeMismatchError < TypeError < StandardError` (inclui `BrUtils::Error`)
537
+ - **Categoria:** Uso indevido da API — o caller passou um valor do tipo errado.
538
+ - **Quando é lançado:** Quando `BrUtils.new` recebe um argumento `settings` não-`nil` que não é um `Hash`.
539
+ - **Exemplo:**
540
+
541
+ ```ruby
542
+ BrUtils.new('not-a-hash') # lança BrUtils::TypeMismatchError
543
+ BrUtils.new(false) # lança BrUtils::TypeMismatchError (false é não-nil)
544
+ ```
545
+
546
+ - **Como resgatar:**
547
+
548
+ ```ruby
549
+ rescue BrUtils::TypeMismatchError
550
+ # violação de contrato de tipo desta gem
551
+
552
+ rescue TypeError
553
+ # erros nativos de tipo, incluindo TypeMismatchError desta gem
554
+ ```
555
+
556
+ ##### `BrUtils::InvalidArgumentCombinationError`
557
+
558
+ - **Herança:** `BrUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `BrUtils::Error`)
559
+ - **Categoria:** Uso indevido da API — o caller misturou padrões de argumentos mutuamente exclusivos.
560
+ - **Quando é lançado:** Quando `BrUtils.new` recebe um `Hash` de settings não-`nil` e qualquer argumento nomeado não-`nil` (`cpf:`, `cnpj:`, `cpf_formatter:`, …) ao mesmo tempo.
561
+ - **Exemplo:**
562
+
563
+ ```ruby
564
+ BrUtils.new({ cpf: { formatter: { hidden: true } } }, cnpj: { formatter: { hidden: true } })
565
+ # lança BrUtils::InvalidArgumentCombinationError
566
+ ```
567
+
568
+ - **Como resgatar:**
569
+
570
+ ```ruby
571
+ rescue BrUtils::InvalidArgumentCombinationError
572
+ # combinação inválida de assinatura desta gem
573
+
574
+ rescue ArgumentError
575
+ # erros nativos de argumento, incluindo InvalidArgumentCombinationError desta gem
576
+ ```
577
+
578
+ ##### Granularidade de rescue
579
+
580
+ Cada nível é mostrado como seu próprio exemplo isolado (não os una em uma única escada de `rescue` — um handler nativo amplo tornaria cláusulas mais estreitas inalcançáveis).
581
+
582
+ ```ruby
583
+ require 'br-utilities'
584
+
585
+ # 1) Classe nativa única — captura erros de uso indevido desse tipo,
586
+ # incluindo os não-biblioteca já tratados em outro ponto do código do consumidor.
587
+ begin
588
+ BrUtils.new('not-a-hash')
589
+ rescue TypeError
590
+ # BrUtils::TypeMismatchError e qualquer outro TypeError (biblioteca ou não)
591
+ end
592
+
593
+ begin
594
+ BrUtils.new({ cpf: {} }, cnpj: CnpjUtils.new)
595
+ rescue ArgumentError
596
+ # BrUtils::InvalidArgumentCombinationError e qualquer outro ArgumentError (biblioteca ou não)
597
+ end
598
+ ```
599
+
600
+ ```ruby
601
+ require 'br-utilities'
602
+
603
+ # 2) DomainError dos pacotes — esta gem não define DomainError; falhas de domínio
604
+ # vêm dos pacotes incluídos e mantêm esses namespaces (ex.: CpfFmt, CnpjFmt).
605
+ begin
606
+ BrUtils.new.cpf.format('12345678909', hidden_start: -1)
607
+ rescue CpfFmt::DomainError
608
+ # CpfFmt::OutOfRangeError, CpfFmt::ValidationError e outras subclasses de DomainError
609
+ end
610
+
611
+ begin
612
+ BrUtils.new.cnpj.format('91415732000793', hidden_start: -1)
613
+ rescue CnpjFmt::DomainError
614
+ # CnpjFmt::OutOfRangeError, CnpjFmt::ValidationError e outras subclasses de DomainError
615
+ end
616
+ ```
617
+
618
+ ```ruby
619
+ require 'br-utilities'
620
+
621
+ # 3) BrUtils::Error — captura tudo que esta gem lança, independentemente da ancestralidade nativa.
622
+ # Não captura CpfFmt::*, CnpjGen::* ou outros erros dos pacotes incluídos.
623
+ begin
624
+ BrUtils.new('not-a-hash')
625
+ rescue BrUtils::Error
626
+ # todo erro customizado que inclui BrUtils::Error
627
+ end
628
+ ```
629
+
630
+ ```ruby
631
+ require 'br-utilities'
632
+
633
+ # 4) Classe folha específica — captura apenas aquele modo de falha exato.
634
+ begin
635
+ BrUtils.new('not-a-hash')
636
+ rescue BrUtils::TypeMismatchError
637
+ # apenas BrUtils::TypeMismatchError
638
+ end
639
+ ```
640
+
641
+ #### Propagados dos pacotes incluídos
642
+
643
+ Os erros dos componentes mantêm os namespaces dos pacotes e se propagam inalterados pela fachada (e pelas APIs aninhadas / irmãs na raiz). Cada pacote também expõe um módulo marcador `*::Error` para rescue em toda a biblioteca. **Dados** inválidos de CPF/CNPJ em `#is_valid` retornam `false` (sem raise de domínio). Falha de comprimento na formatação **não** é lançada por `#format` — é entregue a **`on_fail`** como `CpfFmt::InvalidLengthError` ou `CnpjFmt::InvalidLengthError` (`on_fail` padrão retorna `''`).
644
+
645
+ `CpfUtils::*` / `CnpjUtils::*` de uso indevido também se propagam quando agregadores aninhados são construídos ou chamados via `BrUtils`. Para tabelas de opções e casos extremos, veja [`cpf-utilities`](../cpf-utilities/README.pt.md) e [`cnpj-utilities`](../cnpj-utilities/README.pt.md).
646
+
647
+ ##### Resumo
648
+
649
+ | Classe | Herda de | Categoria | Condição de disparo |
650
+ |-------|---------------|----------|-------------------|
651
+ | `CnpjFmt::InvalidArgumentCombinationError` | `CnpjFmt::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CnpjFmt::Error`) | Uso indevido da API | Instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` em `CnpjFormatter` / `cnpj_fmt` |
652
+ | `CnpjFmt::TypeMismatchError` | `CnpjFmt::TypeMismatchError < TypeError < StandardError` (+ `include CnpjFmt::Error`) | Uso indevido da API | Entrada de CNPJ ou opção do formatador tem o tipo errado (ou o retorno de `on_fail` não é `String`) |
653
+ | `CnpjGen::InvalidArgumentCombinationError` | `CnpjGen::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CnpjGen::Error`) | Uso indevido da API | Instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` em `CnpjGenerator` / `cnpj_gen` |
654
+ | `CnpjGen::TypeMismatchError` | `CnpjGen::TypeMismatchError < TypeError < StandardError` (+ `include CnpjGen::Error`) | Uso indevido da API | Opção do gerador (`format` / `prefix` / `type`) tem o tipo errado |
655
+ | `CnpjUtils::InvalidArgumentCombinationError` | `CnpjUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CnpjUtils::Error`) | Uso indevido da API | Construtor/`#format`/`#generate`/`#is_valid`/helpers de classe: `Hash`/instância de settings/options não-`nil` com qualquer argumento nomeado não-`nil` |
656
+ | `CnpjUtils::TypeMismatchError` | `CnpjUtils::TypeMismatchError < TypeError < StandardError` (+ `include CnpjUtils::Error`) | Uso indevido da API | Argumento `settings` não-`nil` de `CnpjUtils.new` não é um `Hash` |
657
+ | `CnpjVal::InvalidArgumentCombinationError` | `CnpjVal::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CnpjVal::Error`) | Uso indevido da API | Instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` em `CnpjValidator` / `cnpj_val` |
658
+ | `CnpjVal::TypeMismatchError` | `CnpjVal::TypeMismatchError < TypeError < StandardError` (+ `include CnpjVal::Error`) | Uso indevido da API | Entrada de CNPJ ou opção do validador tem o tipo errado |
659
+ | `CpfFmt::InvalidArgumentCombinationError` | `CpfFmt::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CpfFmt::Error`) | Uso indevido da API | Instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` em `CpfFormatter` / `cpf_fmt` |
660
+ | `CpfFmt::TypeMismatchError` | `CpfFmt::TypeMismatchError < TypeError < StandardError` (+ `include CpfFmt::Error`) | Uso indevido da API | Entrada de CPF ou opção do formatador tem o tipo errado (ou o retorno de `on_fail` não é `String`) |
661
+ | `CpfGen::InvalidArgumentCombinationError` | `CpfGen::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CpfGen::Error`) | Uso indevido da API | Instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` em `CpfGenerator` / `cpf_gen` |
662
+ | `CpfGen::TypeMismatchError` | `CpfGen::TypeMismatchError < TypeError < StandardError` (+ `include CpfGen::Error`) | Uso indevido da API | Opção do gerador (`format` / `prefix`) tem o tipo errado |
663
+ | `CpfUtils::InvalidArgumentCombinationError` | `CpfUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CpfUtils::Error`) | Uso indevido da API | Construtor: `Hash` de settings não-`nil` com qualquer argumento nomeado não-`nil`; ou `#format`/`#generate`/helpers de classe: `Hash`/instância `*Options` de options não-`nil` com qualquer argumento nomeado não-`nil` |
664
+ | `CpfUtils::TypeMismatchError` | `CpfUtils::TypeMismatchError < TypeError < StandardError` (+ `include CpfUtils::Error`) | Uso indevido da API | Argumento `settings` não-`nil` de `CpfUtils.new` não é um `Hash` |
665
+ | `CpfVal::TypeMismatchError` | `CpfVal::TypeMismatchError < TypeError < StandardError` (+ `include CpfVal::Error`) | Uso indevido da API | Entrada de CPF não é `String` nem `Array` de strings |
666
+ | `CnpjFmt::InvalidLengthError` | `CnpjFmt::InvalidLengthError < CnpjFmt::DomainError < RangeError < StandardError` (+ `include CnpjFmt::Error`) | Erro de domínio | Comprimento sanitizado ≠ 14 — **passado a `on_fail`**, não lançado por `#format` |
667
+ | `CnpjFmt::OutOfRangeError` | `CnpjFmt::OutOfRangeError < CnpjFmt::DomainError < RangeError < StandardError` (+ `include CnpjFmt::Error`) | Erro de domínio | `hidden_start` / `hidden_end` fora de `0`–`13` |
668
+ | `CnpjFmt::ValidationError` | `CnpjFmt::ValidationError < CnpjFmt::DomainError < RangeError < StandardError` (+ `include CnpjFmt::Error`) | Erro de domínio | `hidden_key` / `dot_key` / `slash_key` / `dash_key` contém caractere proibido |
669
+ | `CnpjGen::ValidationError` | `CnpjGen::ValidationError < CnpjGen::DomainError < RangeError < StandardError` (+ `include CnpjGen::Error`) | Erro de domínio | `prefix` inelegível, ou `type` fora de `'alphabetic'` / `'alphanumeric'` / `'numeric'` |
670
+ | `CnpjVal::ValidationError` | `CnpjVal::ValidationError < CnpjVal::DomainError < RangeError < StandardError` (+ `include CnpjVal::Error`) | Erro de domínio | `type` do validador não é `'alphanumeric'` nem `'numeric'` |
671
+ | `CpfFmt::InvalidLengthError` | `CpfFmt::InvalidLengthError < CpfFmt::DomainError < RangeError < StandardError` (+ `include CpfFmt::Error`) | Erro de domínio | Comprimento sanitizado ≠ 11 — **passado a `on_fail`**, não lançado por `#format` |
672
+ | `CpfFmt::OutOfRangeError` | `CpfFmt::OutOfRangeError < CpfFmt::DomainError < RangeError < StandardError` (+ `include CpfFmt::Error`) | Erro de domínio | `hidden_start` / `hidden_end` fora de `0`–`10` |
673
+ | `CpfFmt::ValidationError` | `CpfFmt::ValidationError < CpfFmt::DomainError < RangeError < StandardError` (+ `include CpfFmt::Error`) | Erro de domínio | `hidden_key` / `dot_key` / `dash_key` contém caractere proibido |
674
+ | `CpfGen::ValidationError` | `CpfGen::ValidationError < CpfGen::DomainError < RangeError < StandardError` (+ `include CpfGen::Error`) | Erro de domínio | `prefix` inelegível (base zerada ou 9 dígitos repetidos) |
675
+
676
+ ##### `CpfFmt::DomainError`
677
+
678
+ - **Herança:** `CpfFmt::DomainError < RangeError < StandardError` (inclui `CpfFmt::Error`)
679
+ - **Categoria:** Erro de domínio — ancestral das folhas de domínio do formatador.
680
+ - **Quando é lançado:** Não é lançado diretamente; alvo de rescue para `OutOfRangeError`, `ValidationError` e `InvalidLengthError` relançado.
681
+ - **Exemplo:** Prefira resgatar uma folha, ou `CpfFmt::DomainError` para todas as falhas de domínio do formatador de CPF.
682
+ - **Como resgatar:**
683
+
684
+ ```ruby
685
+ rescue CpfFmt::DomainError
686
+ # OutOfRangeError, ValidationError, InvalidLengthError (se relançado a partir de on_fail)
687
+ ```
688
+
689
+ ##### `CpfFmt::TypeMismatchError`
690
+
691
+ - **Herança:** `CpfFmt::TypeMismatchError < TypeError < StandardError` (inclui `CpfFmt::Error`)
692
+ - **Categoria:** Uso indevido da API — tipo errado para entrada de CPF ou opção do formatador.
693
+ - **Quando é lançado:** Lançado quando `#format` / `cpf_fmt` recebe entrada que não é `String` / `Array<String>`, uma opção tem o tipo errado, ou `on_fail` não retorna `String`.
694
+ - **Exemplo:**
695
+
696
+ ```ruby
697
+ BrUtils.new.cpf.format(12_345) # lança CpfFmt::TypeMismatchError
698
+ ```
699
+
700
+ - **Como resgatar:**
701
+
702
+ ```ruby
703
+ rescue CpfFmt::TypeMismatchError
704
+ # violação de contrato de tipo do formatador
705
+
706
+ rescue TypeError
707
+ # erros nativos de tipo, incluindo CpfFmt::TypeMismatchError
708
+ ```
709
+
710
+ ##### `CpfFmt::InvalidArgumentCombinationError`
711
+
712
+ - **Herança:** `CpfFmt::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CpfFmt::Error`)
713
+ - **Categoria:** Uso indevido da API — `options` e argumentos nomeados misturados na API do formatador.
714
+ - **Quando é lançado:** Lançado por `CpfFmt::CpfFormatter` / `CpfFmt.cpf_fmt` quando uma instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` são passados juntos. (O agregador de CPF lança `CpfUtils::InvalidArgumentCombinationError` para o mesmo padrão em `CpfUtils#format`.)
715
+ - **Exemplo:**
716
+
717
+ ```ruby
718
+ CpfFmt::CpfFormatter.new({ dash_key: '_' }, hidden: true)
719
+ # lança CpfFmt::InvalidArgumentCombinationError
720
+ ```
721
+
722
+ - **Como resgatar:**
723
+
724
+ ```ruby
725
+ rescue CpfFmt::InvalidArgumentCombinationError
726
+ # combinação inválida de assinatura do formatador
727
+
728
+ rescue ArgumentError
729
+ # erros nativos de argumento, incluindo este
730
+ ```
731
+
732
+ ##### `CpfFmt::InvalidLengthError` (entregue via callback)
733
+
734
+ - **Herança:** `CpfFmt::InvalidLengthError < CpfFmt::DomainError < RangeError < StandardError` (inclui `CpfFmt::Error`)
735
+ - **Categoria:** Erro de domínio — o comprimento sanitizado do CPF não é exatamente 11.
736
+ - **Quando é lançado:** **Não é lançado** por `#format` / `cpf_fmt`; construído e passado como segundo argumento a `on_fail`.
737
+ - **Exemplo:**
738
+
739
+ ```ruby
740
+ custom_fail = ->(value, error) {
741
+ error # => #<CpfFmt::InvalidLengthError ...>
742
+ "Invalid CPF: #{value}"
743
+ }
744
+
745
+ BrUtils.new.cpf.format('123', on_fail: custom_fail) # => "Invalid CPF: 123"
746
+ BrUtils.new.cpf.format('123') # => "" (on_fail padrão)
747
+ ```
748
+
749
+ - **Como resgatar:** Trate dentro de `on_fail` (típico), ou faça rescue se relançar:
750
+
751
+ ```ruby
752
+ rescue CpfFmt::InvalidLengthError
753
+ # esta violação exata de comprimento
754
+
755
+ rescue CpfFmt::DomainError
756
+ # falhas de domínio com raiz em RangeError de cpf-fmt
757
+ ```
758
+
759
+ ##### `CpfFmt::OutOfRangeError`
760
+
761
+ - **Herança:** `CpfFmt::OutOfRangeError < CpfFmt::DomainError < RangeError < StandardError` (inclui `CpfFmt::Error`)
762
+ - **Categoria:** Erro de domínio — `hidden_start` / `hidden_end` fora de `0`–`10`.
763
+ - **Quando é lançado:** Lançado ao construir ou aplicar opções do formatador com índice de ocultação fora do intervalo.
764
+ - **Exemplo:**
765
+
766
+ ```ruby
767
+ BrUtils.new.cpf.format('12345678909', hidden_start: -1) # lança CpfFmt::OutOfRangeError
768
+ ```
769
+
770
+ - **Como resgatar:**
771
+
772
+ ```ruby
773
+ rescue CpfFmt::OutOfRangeError
774
+ # esta violação exata de intervalo
775
+
776
+ rescue CpfFmt::DomainError
777
+ # falhas de domínio com raiz em RangeError de cpf-fmt
778
+ ```
779
+
780
+ ##### `CpfFmt::ValidationError`
781
+
782
+ - **Herança:** `CpfFmt::ValidationError < CpfFmt::DomainError < RangeError < StandardError` (inclui `CpfFmt::Error`)
783
+ - **Categoria:** Erro de domínio — uma opção de chave contém um caractere proibido.
784
+ - **Quando é lançado:** Lançado quando `hidden_key`, `dot_key` ou `dash_key` contém um caractere proibido.
785
+ - **Exemplo:**
786
+
787
+ ```ruby
788
+ BrUtils.new(cpf: { formatter: { dot_key: 'å' } }) # lança CpfFmt::ValidationError
789
+ ```
790
+
791
+ - **Como resgatar:**
792
+
793
+ ```ruby
794
+ rescue CpfFmt::ValidationError
795
+ # esta falha exata de validação de domínio
796
+
797
+ rescue CpfFmt::DomainError
798
+ # falhas de domínio com raiz em RangeError de cpf-fmt
799
+ ```
800
+
801
+ ##### `CpfGen::DomainError`
802
+
803
+ - **Herança:** `CpfGen::DomainError < RangeError < StandardError` (inclui `CpfGen::Error`)
804
+ - **Categoria:** Erro de domínio — ancestral das folhas de domínio do gerador.
805
+ - **Quando é lançado:** Não é lançado diretamente; alvo de rescue para `CpfGen::ValidationError`.
806
+ - **Exemplo:** Prefira `rescue CpfGen::ValidationError` ou `CpfGen::DomainError`.
807
+ - **Como resgatar:**
808
+
809
+ ```ruby
810
+ rescue CpfGen::DomainError
811
+ # ValidationError e outras subclasses de DomainError de cpf-gen
812
+ ```
813
+
814
+ ##### `CpfGen::TypeMismatchError`
815
+
816
+ - **Herança:** `CpfGen::TypeMismatchError < TypeError < StandardError` (inclui `CpfGen::Error`)
817
+ - **Categoria:** Uso indevido da API — tipo errado para uma opção do gerador.
818
+ - **Quando é lançado:** Lançado quando `format` ou `prefix` tem o tipo de runtime errado.
819
+ - **Exemplo:**
820
+
821
+ ```ruby
822
+ BrUtils.new.cpf.generate(prefix: 123) # lança CpfGen::TypeMismatchError
823
+ ```
824
+
825
+ - **Como resgatar:**
826
+
827
+ ```ruby
828
+ rescue CpfGen::TypeMismatchError
829
+ # violação de contrato de tipo do gerador
830
+
831
+ rescue TypeError
832
+ # erros nativos de tipo, incluindo CpfGen::TypeMismatchError
833
+ ```
834
+
835
+ ##### `CpfGen::InvalidArgumentCombinationError`
836
+
837
+ - **Herança:** `CpfGen::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CpfGen::Error`)
838
+ - **Categoria:** Uso indevido da API — `options` e argumentos nomeados misturados na API do gerador.
839
+ - **Quando é lançado:** Lançado por `CpfGen::CpfGenerator` / `CpfGen.cpf_gen` quando uma instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` são passados juntos. (O agregador de CPF lança `CpfUtils::InvalidArgumentCombinationError` para o mesmo padrão em `CpfUtils#generate`.)
840
+ - **Exemplo:**
841
+
842
+ ```ruby
843
+ CpfGen::CpfGenerator.new({ format: true }, prefix: '123')
844
+ # lança CpfGen::InvalidArgumentCombinationError
845
+ ```
846
+
847
+ - **Como resgatar:**
848
+
849
+ ```ruby
850
+ rescue CpfGen::InvalidArgumentCombinationError
851
+ # combinação inválida de assinatura do gerador
852
+
853
+ rescue ArgumentError
854
+ # erros nativos de argumento, incluindo este
855
+ ```
856
+
857
+ ##### `CpfGen::ValidationError`
858
+
859
+ - **Herança:** `CpfGen::ValidationError < CpfGen::DomainError < RangeError < StandardError` (inclui `CpfGen::Error`)
860
+ - **Categoria:** Erro de domínio — `prefix` inelegível.
861
+ - **Quando é lançado:** Lançado quando `prefix` é uma base zerada (`'000000000'`) ou 9 dígitos repetidos (ex.: `'999999999'`).
862
+ - **Exemplo:**
863
+
864
+ ```ruby
865
+ BrUtils.new.cpf.generate(prefix: '000000000') # lança CpfGen::ValidationError
866
+ ```
867
+
868
+ - **Como resgatar:**
869
+
870
+ ```ruby
871
+ rescue CpfGen::ValidationError
872
+ # esta falha exata de validação de domínio
873
+
874
+ rescue CpfGen::DomainError
875
+ # falhas de domínio com raiz em RangeError de cpf-gen
876
+ ```
877
+
878
+ ##### `CpfVal::TypeMismatchError`
879
+
880
+ - **Herança:** `CpfVal::TypeMismatchError < TypeError < StandardError` (inclui `CpfVal::Error`)
881
+ - **Categoria:** Uso indevido da API — tipo errado para entrada de CPF.
882
+ - **Quando é lançado:** Lançado quando `#is_valid` / `cpf_val` recebe um valor que não é `String` nem `Array` de strings (incluindo elemento de array que não é string). **Dados** de CPF inválidos retornam `false` e não lançam.
883
+ - **Exemplo:**
884
+
885
+ ```ruby
886
+ BrUtils.new.cpf.is_valid(12_345_678_909) # lança CpfVal::TypeMismatchError
887
+ BrUtils.new.cpf.is_valid('12345678900') # => false (dados inválidos, sem raise)
888
+ ```
889
+
890
+ - **Como resgatar:**
891
+
892
+ ```ruby
893
+ rescue CpfVal::TypeMismatchError
894
+ # violação de contrato de tipo do validador
895
+
896
+ rescue TypeError
897
+ # erros nativos de tipo, incluindo CpfVal::TypeMismatchError
898
+ ```
899
+
900
+ ##### `CnpjFmt::DomainError`
901
+
902
+ - **Herança:** `CnpjFmt::DomainError < RangeError < StandardError` (inclui `CnpjFmt::Error`)
903
+ - **Categoria:** Erro de domínio — ancestral das folhas de domínio do formatador.
904
+ - **Quando é lançado:** Não é lançado diretamente; alvo de rescue para `OutOfRangeError`, `ValidationError` e `InvalidLengthError` relançado.
905
+ - **Exemplo:** Prefira resgatar uma folha, ou `CnpjFmt::DomainError` para todas as falhas de domínio do formatador de CNPJ.
906
+ - **Como resgatar:**
907
+
908
+ ```ruby
909
+ rescue CnpjFmt::DomainError
910
+ # OutOfRangeError, ValidationError, InvalidLengthError (se relançado a partir de on_fail)
911
+ ```
912
+
913
+ ##### `CnpjFmt::TypeMismatchError`
914
+
915
+ - **Herança:** `CnpjFmt::TypeMismatchError < TypeError < StandardError` (inclui `CnpjFmt::Error`)
916
+ - **Categoria:** Uso indevido da API — tipo errado para entrada de CNPJ ou opção do formatador.
917
+ - **Quando é lançado:** Lançado quando `#format` / `cnpj_fmt` recebe entrada que não é `String` / `Array<String>`, uma opção tem o tipo errado, ou `on_fail` não retorna `String`.
918
+ - **Exemplo:**
919
+
920
+ ```ruby
921
+ BrUtils.new.cnpj.format(12_345) # lança CnpjFmt::TypeMismatchError
922
+ ```
923
+
924
+ - **Como resgatar:**
925
+
926
+ ```ruby
927
+ rescue CnpjFmt::TypeMismatchError
928
+ # violação de contrato de tipo do formatador
929
+
930
+ rescue TypeError
931
+ # erros nativos de tipo, incluindo CnpjFmt::TypeMismatchError
932
+ ```
933
+
934
+ ##### `CnpjFmt::InvalidArgumentCombinationError`
935
+
936
+ - **Herança:** `CnpjFmt::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CnpjFmt::Error`)
937
+ - **Categoria:** Uso indevido da API — `options` e argumentos nomeados misturados na API do formatador.
938
+ - **Quando é lançado:** Lançado por `CnpjFmt::CnpjFormatter` / `CnpjFmt.cnpj_fmt` quando uma instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` são passados juntos. (O agregador de CNPJ lança `CnpjUtils::InvalidArgumentCombinationError` para o mesmo padrão em `CnpjUtils#format`.)
939
+ - **Exemplo:**
940
+
941
+ ```ruby
942
+ CnpjFmt::CnpjFormatter.new({ slash_key: '|' }, hidden: true)
943
+ # lança CnpjFmt::InvalidArgumentCombinationError
944
+ ```
945
+
946
+ - **Como resgatar:**
947
+
948
+ ```ruby
949
+ rescue CnpjFmt::InvalidArgumentCombinationError
950
+ # combinação inválida de assinatura do formatador
951
+
952
+ rescue ArgumentError
953
+ # erros nativos de argumento, incluindo este
954
+ ```
955
+
956
+ ##### `CnpjFmt::InvalidLengthError` (entregue via callback)
957
+
958
+ - **Herança:** `CnpjFmt::InvalidLengthError < CnpjFmt::DomainError < RangeError < StandardError` (inclui `CnpjFmt::Error`)
959
+ - **Categoria:** Erro de domínio — o comprimento sanitizado do CNPJ não é exatamente 14.
960
+ - **Quando é lançado:** **Não é lançado** por `#format` / `cnpj_fmt`; construído e passado como segundo argumento a `on_fail`.
961
+ - **Exemplo:**
962
+
963
+ ```ruby
964
+ custom_fail = ->(value, error) {
965
+ error # => #<CnpjFmt::InvalidLengthError ...>
966
+ "Invalid CNPJ: #{value}"
967
+ }
968
+
969
+ BrUtils.new.cnpj.format('123', on_fail: custom_fail) # => "Invalid CNPJ: 123"
970
+ BrUtils.new.cnpj.format('123') # => "" (on_fail padrão)
971
+ ```
972
+
973
+ - **Como resgatar:** Trate dentro de `on_fail` (típico), ou faça rescue se relançar:
974
+
975
+ ```ruby
976
+ rescue CnpjFmt::InvalidLengthError
977
+ # esta violação exata de comprimento
978
+
979
+ rescue CnpjFmt::DomainError
980
+ # falhas de domínio com raiz em RangeError de cnpj-fmt
981
+ ```
982
+
983
+ ##### `CnpjFmt::OutOfRangeError`
984
+
985
+ - **Herança:** `CnpjFmt::OutOfRangeError < CnpjFmt::DomainError < RangeError < StandardError` (inclui `CnpjFmt::Error`)
986
+ - **Categoria:** Erro de domínio — `hidden_start` / `hidden_end` fora de `0`–`13`.
987
+ - **Quando é lançado:** Lançado ao construir ou aplicar opções do formatador com índice de ocultação fora do intervalo.
988
+ - **Exemplo:**
989
+
990
+ ```ruby
991
+ BrUtils.new.cnpj.format('91415732000793', hidden_start: -1) # lança CnpjFmt::OutOfRangeError
992
+ ```
993
+
994
+ - **Como resgatar:**
995
+
996
+ ```ruby
997
+ rescue CnpjFmt::OutOfRangeError
998
+ # esta violação exata de intervalo
999
+
1000
+ rescue CnpjFmt::DomainError
1001
+ # falhas de domínio com raiz em RangeError de cnpj-fmt
1002
+ ```
1003
+
1004
+ ##### `CnpjFmt::ValidationError`
1005
+
1006
+ - **Herança:** `CnpjFmt::ValidationError < CnpjFmt::DomainError < RangeError < StandardError` (inclui `CnpjFmt::Error`)
1007
+ - **Categoria:** Erro de domínio — uma opção de chave contém um caractere proibido.
1008
+ - **Quando é lançado:** Lançado quando `hidden_key`, `dot_key`, `slash_key` ou `dash_key` contém um caractere proibido.
1009
+ - **Exemplo:**
1010
+
1011
+ ```ruby
1012
+ BrUtils.new(cnpj: { formatter: { slash_key: 'å' } }) # lança CnpjFmt::ValidationError
1013
+ ```
1014
+
1015
+ - **Como resgatar:**
1016
+
1017
+ ```ruby
1018
+ rescue CnpjFmt::ValidationError
1019
+ # esta falha exata de validação de domínio
1020
+
1021
+ rescue CnpjFmt::DomainError
1022
+ # falhas de domínio com raiz em RangeError de cnpj-fmt
1023
+ ```
1024
+
1025
+ ##### `CnpjGen::DomainError`
1026
+
1027
+ - **Herança:** `CnpjGen::DomainError < RangeError < StandardError` (inclui `CnpjGen::Error`)
1028
+ - **Categoria:** Erro de domínio — ancestral das folhas de domínio do gerador.
1029
+ - **Quando é lançado:** Não é lançado diretamente; alvo de rescue para `CnpjGen::ValidationError`.
1030
+ - **Exemplo:** Prefira `rescue CnpjGen::ValidationError` ou `CnpjGen::DomainError`.
1031
+ - **Como resgatar:**
1032
+
1033
+ ```ruby
1034
+ rescue CnpjGen::DomainError
1035
+ # ValidationError e outras subclasses de DomainError de cnpj-gen
1036
+ ```
1037
+
1038
+ ##### `CnpjGen::TypeMismatchError`
1039
+
1040
+ - **Herança:** `CnpjGen::TypeMismatchError < TypeError < StandardError` (inclui `CnpjGen::Error`)
1041
+ - **Categoria:** Uso indevido da API — tipo errado para uma opção do gerador.
1042
+ - **Quando é lançado:** Lançado quando `format`, `prefix` ou `type` tem o tipo de runtime errado.
1043
+ - **Exemplo:**
1044
+
1045
+ ```ruby
1046
+ BrUtils.new.cnpj.generate(prefix: 123) # lança CnpjGen::TypeMismatchError
1047
+ ```
1048
+
1049
+ - **Como resgatar:**
1050
+
1051
+ ```ruby
1052
+ rescue CnpjGen::TypeMismatchError
1053
+ # violação de contrato de tipo do gerador
1054
+
1055
+ rescue TypeError
1056
+ # erros nativos de tipo, incluindo CnpjGen::TypeMismatchError
1057
+ ```
1058
+
1059
+ ##### `CnpjGen::InvalidArgumentCombinationError`
1060
+
1061
+ - **Herança:** `CnpjGen::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CnpjGen::Error`)
1062
+ - **Categoria:** Uso indevido da API — `options` e argumentos nomeados misturados na API do gerador.
1063
+ - **Quando é lançado:** Lançado por `CnpjGen::CnpjGenerator` / `CnpjGen.cnpj_gen` quando uma instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` são passados juntos. (O agregador de CNPJ lança `CnpjUtils::InvalidArgumentCombinationError` para o mesmo padrão em `CnpjUtils#generate`.)
1064
+ - **Exemplo:**
1065
+
1066
+ ```ruby
1067
+ CnpjGen::CnpjGenerator.new({ format: true }, prefix: '123')
1068
+ # lança CnpjGen::InvalidArgumentCombinationError
1069
+ ```
1070
+
1071
+ - **Como resgatar:**
1072
+
1073
+ ```ruby
1074
+ rescue CnpjGen::InvalidArgumentCombinationError
1075
+ # combinação inválida de assinatura do gerador
1076
+
1077
+ rescue ArgumentError
1078
+ # erros nativos de argumento, incluindo este
1079
+ ```
1080
+
1081
+ ##### `CnpjGen::ValidationError`
1082
+
1083
+ - **Herança:** `CnpjGen::ValidationError < CnpjGen::DomainError < RangeError < StandardError` (inclui `CnpjGen::Error`)
1084
+ - **Categoria:** Erro de domínio — `prefix` inelegível ou `type` não permitido.
1085
+ - **Quando é lançado:** Lançado quando `prefix` é base/filial zerada ou 12 dígitos repetidos, ou quando `type` não é `'alphabetic'`, `'alphanumeric'` ou `'numeric'`.
1086
+ - **Exemplo:**
1087
+
1088
+ ```ruby
1089
+ BrUtils.new.cnpj.generate(type: 'boolean') # lança CnpjGen::ValidationError
1090
+ ```
1091
+
1092
+ - **Como resgatar:**
1093
+
1094
+ ```ruby
1095
+ rescue CnpjGen::ValidationError
1096
+ # esta falha exata de validação de domínio
1097
+
1098
+ rescue CnpjGen::DomainError
1099
+ # falhas de domínio com raiz em RangeError de cnpj-gen
1100
+ ```
1101
+
1102
+ ##### `CnpjVal::DomainError`
1103
+
1104
+ - **Herança:** `CnpjVal::DomainError < RangeError < StandardError` (inclui `CnpjVal::Error`)
1105
+ - **Categoria:** Erro de domínio — ancestral das folhas de domínio do validador.
1106
+ - **Quando é lançado:** Não é lançado diretamente; alvo de rescue para `CnpjVal::ValidationError`.
1107
+ - **Exemplo:** Prefira `rescue CnpjVal::ValidationError` ou `CnpjVal::DomainError`.
1108
+ - **Como resgatar:**
1109
+
1110
+ ```ruby
1111
+ rescue CnpjVal::DomainError
1112
+ # ValidationError e outras subclasses de DomainError de cnpj-val
1113
+ ```
1114
+
1115
+ ##### `CnpjVal::TypeMismatchError`
1116
+
1117
+ - **Herança:** `CnpjVal::TypeMismatchError < TypeError < StandardError` (inclui `CnpjVal::Error`)
1118
+ - **Categoria:** Uso indevido da API — tipo errado para entrada de CNPJ ou opção do validador.
1119
+ - **Quando é lançado:** Lançado quando `#is_valid` / `cnpj_val` recebe um valor que não é `String` nem `Array` de strings, ou uma opção do validador tem o tipo errado. **Dados** de CNPJ inválidos retornam `false` e não lançam.
1120
+ - **Exemplo:**
1121
+
1122
+ ```ruby
1123
+ BrUtils.new.cnpj.is_valid(12_345_678_000_198) # lança CnpjVal::TypeMismatchError
1124
+ BrUtils.new.cnpj.is_valid('00000000000000') # => false (dados inválidos, sem raise)
1125
+ ```
1126
+
1127
+ - **Como resgatar:**
1128
+
1129
+ ```ruby
1130
+ rescue CnpjVal::TypeMismatchError
1131
+ # violação de contrato de tipo do validador
1132
+
1133
+ rescue TypeError
1134
+ # erros nativos de tipo, incluindo CnpjVal::TypeMismatchError
1135
+ ```
1136
+
1137
+ ##### `CnpjVal::InvalidArgumentCombinationError`
1138
+
1139
+ - **Herança:** `CnpjVal::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CnpjVal::Error`)
1140
+ - **Categoria:** Uso indevido da API — `options` e argumentos nomeados misturados na API do validador.
1141
+ - **Quando é lançado:** Lançado por `CnpjVal::CnpjValidator` / `CnpjVal.cnpj_val` quando uma instância/`Hash` de `options` e qualquer argumento nomeado não-`nil` são passados juntos. (O agregador de CNPJ lança `CnpjUtils::InvalidArgumentCombinationError` para o mesmo padrão em `CnpjUtils#is_valid`.)
1142
+ - **Exemplo:**
1143
+
1144
+ ```ruby
1145
+ CnpjVal.cnpj_val('98765432000198', { type: 'numeric' }, case_sensitive: false)
1146
+ # lança CnpjVal::InvalidArgumentCombinationError
1147
+ ```
1148
+
1149
+ - **Como resgatar:**
1150
+
1151
+ ```ruby
1152
+ rescue CnpjVal::InvalidArgumentCombinationError
1153
+ # combinação inválida de assinatura do validador
1154
+
1155
+ rescue ArgumentError
1156
+ # erros nativos de argumento, incluindo este
1157
+ ```
1158
+
1159
+ ##### `CnpjVal::ValidationError`
1160
+
1161
+ - **Herança:** `CnpjVal::ValidationError < CnpjVal::DomainError < RangeError < StandardError` (inclui `CnpjVal::Error`)
1162
+ - **Categoria:** Erro de domínio — `type` do validador não permitido.
1163
+ - **Quando é lançado:** Lançado quando `type` não é `'alphanumeric'` nem `'numeric'`.
1164
+ - **Exemplo:**
1165
+
1166
+ ```ruby
1167
+ BrUtils.new.cnpj.is_valid('91415732000793', type: 'boolean') # lança CnpjVal::ValidationError
1168
+ ```
1169
+
1170
+ - **Como resgatar:**
1171
+
1172
+ ```ruby
1173
+ rescue CnpjVal::ValidationError
1174
+ # esta falha exata de validação de domínio
1175
+
1176
+ rescue CnpjVal::DomainError
1177
+ # falhas de domínio com raiz em RangeError de cnpj-val
1178
+ ```
1179
+
1180
+ ##### `CpfUtils::TypeMismatchError`
1181
+
1182
+ - **Herança:** `CpfUtils::TypeMismatchError < TypeError < StandardError` (inclui `CpfUtils::Error`)
1183
+ - **Categoria:** Uso indevido da API — o caller passou um valor do tipo errado.
1184
+ - **Quando é lançado:** Quando `CpfUtils.new` recebe um argumento `settings` não-`nil` que não é um `Hash`.
1185
+ - **Exemplo:**
1186
+
1187
+ ```ruby
1188
+ CpfUtils.new('not-a-hash') # lança CpfUtils::TypeMismatchError
1189
+ CpfUtils.new(false) # lança CpfUtils::TypeMismatchError (false é não-nil)
1190
+ ```
1191
+
1192
+ - **Como resgatar:**
1193
+
1194
+ ```ruby
1195
+ rescue CpfUtils::TypeMismatchError
1196
+ # violação de contrato de tipo do agregador de CPF (não BrUtils::Error)
1197
+
1198
+ rescue TypeError
1199
+ # erros nativos de tipo, incluindo CpfUtils::TypeMismatchError
1200
+ ```
1201
+
1202
+ ##### `CpfUtils::InvalidArgumentCombinationError`
1203
+
1204
+ - **Herança:** `CpfUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CpfUtils::Error`)
1205
+ - **Categoria:** Uso indevido da API — o caller misturou padrões de argumentos mutuamente exclusivos.
1206
+ - **Quando é lançado:** Quando `CpfUtils.new` recebe um `Hash` de settings não-`nil` e qualquer argumento nomeado não-`nil`, ou quando `#format` / `#generate` misturam um `Hash`/`*Options` de options não-`nil` com qualquer argumento nomeado não-`nil`. `#is_valid` não tem caminho de options e não lança este erro.
1207
+ - **Exemplo:**
1208
+
1209
+ ```ruby
1210
+ BrUtils.new.cpf.format({ hidden: true }, dash_key: '|')
1211
+ # lança CpfUtils::InvalidArgumentCombinationError
1212
+ ```
1213
+
1214
+ - **Como resgatar:**
1215
+
1216
+ ```ruby
1217
+ rescue CpfUtils::InvalidArgumentCombinationError
1218
+ # combinação inválida de assinatura do agregador de CPF (não BrUtils::Error)
1219
+
1220
+ rescue ArgumentError
1221
+ # erros nativos de argumento, incluindo CpfUtils::InvalidArgumentCombinationError
1222
+ ```
1223
+
1224
+ ##### `CnpjUtils::TypeMismatchError`
1225
+
1226
+ - **Herança:** `CnpjUtils::TypeMismatchError < TypeError < StandardError` (inclui `CnpjUtils::Error`)
1227
+ - **Categoria:** Uso indevido da API — o caller passou um valor do tipo errado.
1228
+ - **Quando é lançado:** Quando `CnpjUtils.new` recebe um argumento `settings` não-`nil` que não é um `Hash`.
1229
+ - **Exemplo:**
1230
+
1231
+ ```ruby
1232
+ CnpjUtils.new('not-a-hash') # lança CnpjUtils::TypeMismatchError
1233
+ CnpjUtils.new(false) # lança CnpjUtils::TypeMismatchError (false é não-nil)
1234
+ ```
1235
+
1236
+ - **Como resgatar:**
1237
+
1238
+ ```ruby
1239
+ rescue CnpjUtils::TypeMismatchError
1240
+ # violação de contrato de tipo do agregador de CNPJ (não BrUtils::Error)
1241
+
1242
+ rescue TypeError
1243
+ # erros nativos de tipo, incluindo CnpjUtils::TypeMismatchError
1244
+ ```
1245
+
1246
+ ##### `CnpjUtils::InvalidArgumentCombinationError`
1247
+
1248
+ - **Herança:** `CnpjUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (inclui `CnpjUtils::Error`)
1249
+ - **Categoria:** Uso indevido da API — o caller misturou padrões de argumentos mutuamente exclusivos.
1250
+ - **Quando é lançado:** Quando `CnpjUtils.new`, `#format`, `#generate`, `#is_valid` ou os helpers de classe recebem um `Hash`/instância de settings/options não-`nil` e qualquer argumento nomeado não-`nil` ao mesmo tempo.
1251
+ - **Exemplo:**
1252
+
1253
+ ```ruby
1254
+ BrUtils.new.cnpj.format({ hidden: true }, slash_key: '|')
1255
+ # lança CnpjUtils::InvalidArgumentCombinationError
1256
+ ```
1257
+
1258
+ - **Como resgatar:**
1259
+
1260
+ ```ruby
1261
+ rescue CnpjUtils::InvalidArgumentCombinationError
1262
+ # combinação inválida de assinatura do agregador de CNPJ (não BrUtils::Error)
1263
+
1264
+ rescue ArgumentError
1265
+ # erros nativos de argumento, incluindo CnpjUtils::InvalidArgumentCombinationError
1266
+ ```
1267
+
1268
+ ### Pacotes incluídos
1269
+
1270
+ | Pacote | Principais recursos | README |
1271
+ |---------|----------------|--------|
1272
+ | [`cpf-utilities`](https://rubygems.org/gems/cpf-utilities) | `CpfUtils`, `CpfFormatter`, `CpfGenerator`, `CpfValidator`, `CpfFmt.cpf_fmt`, `CpfGen.cpf_gen`, `CpfVal.cpf_val` | [docs](../cpf-utilities/README.pt.md) |
1273
+ | [`cnpj-utilities`](https://rubygems.org/gems/cnpj-utilities) | `CnpjUtils`, `CnpjFormatter`, `CnpjGenerator`, `CnpjValidator`, `CnpjFmt.cnpj_fmt`, `CnpjGen.cnpj_gen`, `CnpjVal.cnpj_val` | [docs](../cnpj-utilities/README.pt.md) |
1274
+
1275
+ Todos os acima são puxados como dependências de **`br-utilities`**. Demos interativas: [CPF](https://cpf-utils.vercel.app/) e [CNPJ](https://cnpj-utils.vercel.app/).
1276
+
1277
+ ## Contribuição e suporte
1278
+
1279
+ Contribuições são bem-vindas! Consulte as [Diretrizes de contribuição](https://github.com/LacusSolutions/br-utils-ruby/blob/main/CONTRIBUTING.md). Se o projeto for útil para você, considere:
1280
+
1281
+ - ⭐ Dar uma estrela no repositório
1282
+ - 🤝 Contribuir com código
1283
+ - 💡 [Sugerir novas funcionalidades](https://github.com/LacusSolutions/br-utils-ruby/issues)
1284
+ - 🐛 [Reportar bugs](https://github.com/LacusSolutions/br-utils-ruby/issues)
1285
+
1286
+ ## Licença
1287
+
1288
+ Este projeto está sob a licença MIT — veja o arquivo [LICENSE](https://github.com/LacusSolutions/br-utils-ruby/blob/main/LICENSE).
1289
+
1290
+ ## Changelog
1291
+
1292
+ Veja o [CHANGELOG](./CHANGELOG.md) para alterações e histórico de versões.
1293
+
1294
+ ---
1295
+
1296
+ Feito com ❤️ por [Lacus Solutions](https://github.com/LacusSolutions)