cnpj-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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37e50d704bb23dc45064d080f4bf79d4c852540390f53e22bedd715e54382bb6
4
- data.tar.gz: e3279a8f68a41fe377287f558794b8f59a4674bb8d3962301c808c24481b1782
3
+ metadata.gz: dbde0213b7ccc92a1336f5a65850b30ce1f3c2c39cb26a1e038d30914f5ce2cb
4
+ data.tar.gz: 3efe21df6bdc6d9d5ac27ed38e42fa3eeca7d809c3f13c2c7a34abbc042f3077
5
5
  SHA512:
6
- metadata.gz: e7dfca6dfc87ad3aad139e80498241cf72a698f4e287959eb4facd3c2fc3add4010a0b766ed3e99327a6820596e3bbe9137283dcbe5473eef2244a09a58d1c10
7
- data.tar.gz: 74953b1739a13ce1a37a0c91596c283a1644e1f31081f4033b1fe1a9149815723b6f86ed5ab12811643c5cebd66faced479a2d9bfd79c78ffaca0fcf506f5561
6
+ metadata.gz: ed402960200f5c7f5c763c7cb1e5680cc2a08fe956a5cb5787a96b0fef159a90c5e7af39c716e5414926592c83bf4f2761eab31586f31866c41b4cd86c1f2a63
7
+ data.tar.gz: 459f193ed8572275e00bbabf8a37f0ce93553a75ec5f8efd2b63ff52a8ee5061b637e169e655a88b7198953989a07de428d4e664bf5ec21562815b0c23240916
data/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # cnpj-utilities
2
+
3
+ ## 1.0.0
4
+
5
+ ### 🚀 Stable Version Released!
6
+
7
+ Unified toolkit to deal with CNPJ (Brazilian legal entity ID): formatting, generation, and validation. Main features:
8
+
9
+ - **Unified façade**: `CnpjUtils` delegates `#format`, `#generate`, and `#is_valid` to `cnpj-fmt`, `cnpj-gen`, and `cnpj-val`.
10
+ - **Alphanumeric CNPJ**: full support for the [14-character alphanumeric CNPJ](https://www.gov.br/receitafederal/pt-br/assuntos/noticias/2023/julho/cnpj-alfa-numerico); generate with `type` `"numeric"`, `"alphabetic"`, or `"alphanumeric"`.
11
+ - **Quick helpers**: `CnpjUtils.format` / `.generate` / `.is_valid` alias mutable `CnpjUtils::DEFAULT` (process-wide; prefer `CnpjUtils.new` / per-call options under concurrency).
12
+ - **Two-tier re-exports**: `CnpjUtils::CnpjFormatter` / `CnpjGenerator` / `CnpjValidator` at the façade root; full sibling surface under `CnpjUtils::CnpjFmt` / `CnpjGen` / `CnpjVal`.
13
+ - **Configurable components**: constructor and setters accept component instances, `*Options`, `Hash`, or `nil`; accessors expose `formatter`, `generator`, and `validator`.
14
+ - **Per-call overrides**: `#format`, `#generate`, and `#is_valid` accept an options `Hash`/instance or keyword overrides (not both).
15
+ - **Root siblings**: after `require 'cnpj-utilities'`, `CnpjFmt`, `CnpjGen`, and `CnpjVal` remain loadable (same objects as the nests).
16
+ - **Structured errors**: `CnpjUtils::TypeMismatchError` / `InvalidArgumentCombinationError` (+ `CnpjUtils::Error` marker); only `nil` means omitted for settings/options (e.g. `false` raises).
17
+
18
+ For detailed usage and API reference, see the [README](./README.md).
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Julio L. Muller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,467 @@
1
+ ![cnpj-utilities for Ruby](https://br-utils.vercel.app/img/cover_cnpj-utils.jpg)
2
+
3
+ [![Gem Version](https://img.shields.io/gem/v/cnpj-utilities)](https://rubygems.org/gems/cnpj-utilities)
4
+ [![Gem Downloads](https://img.shields.io/gem/dt/cnpj-utilities)](https://rubygems.org/gems/cnpj-utilities)
5
+ [![Ruby Version](https://img.shields.io/gem/rv/cnpj-utilities)](https://www.ruby-lang.org/)
6
+ [![Test Status](https://img.shields.io/github/actions/workflow/status/LacusSolutions/br-utils-ruby/ci.yml?label=ci/cd)](https://github.com/LacusSolutions/br-utils-ruby/actions)
7
+ [![Last Update Date](https://img.shields.io/github/last-commit/LacusSolutions/br-utils-ruby)](https://github.com/LacusSolutions/br-utils-ruby)
8
+ [![Project License](https://img.shields.io/github/license/LacusSolutions/br-utils-ruby)](https://github.com/LacusSolutions/br-utils-ruby/blob/main/LICENSE)
9
+
10
+ > 🚀 **Full support for the [new alphanumeric CNPJ format](https://github.com/user-attachments/files/23937961/calculodvcnpjalfanaumerico.pdf).**
11
+
12
+ > 🌎 [Acessar documentação em português](./README.pt.md)
13
+
14
+ A Ruby toolkit to format, generate, and validate CNPJ (Brazilian Business Tax ID). It wraps [`cnpj-fmt`](https://rubygems.org/gems/cnpj-fmt), [`cnpj-gen`](https://rubygems.org/gems/cnpj-gen), and [`cnpj-val`](https://rubygems.org/gems/cnpj-val) in a single façade class (`CnpjUtils`).
15
+
16
+ ## Ruby Support
17
+
18
+ | ![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) |
19
+ | --- | --- | --- | --- | --- |
20
+ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ |
21
+
22
+ Requires Ruby **≥ 3.1** (see `required_ruby_version` in the gemspec).
23
+
24
+ ## Features
25
+
26
+ - ✅ **Unified API**: Class helpers `CnpjUtils.format` / `.generate` / `.is_valid`
27
+ - ✅ **Two-tier access**: Prefer `CnpjUtils::CnpjFormatter` / `CnpjGenerator` / `CnpjValidator` for the main classes; Options, helpers, and errors live under `CnpjUtils::CnpjFmt` / `CnpjGen` / `CnpjVal` (root siblings `CnpjFmt` / `CnpjGen` / `CnpjVal` still work)
28
+ - ✅ **Alphanumeric CNPJ**: Format, generate, and validate 14-character numeric or alphanumeric CNPJ
29
+ - ✅ **Reusable instance**: `CnpjUtils` class with optional default settings (formatter, generator, validator options or instances)
30
+ - ✅ **Flexible input**: `#format` and `#is_valid` accept a `String` or an `Array` of strings (elements concatenated in order)
31
+ - ✅ **Per-call overrides**: Instance defaults plus a per-call options `Hash`/`*Options` instance **or** keyword overrides (not both)
32
+ - ✅ **Error handling**: Component errors propagate unchanged; this gem defines `CnpjUtils::TypeMismatchError` and `CnpjUtils::InvalidArgumentCombinationError` for API misuse
33
+
34
+ ## Installation
35
+
36
+ Install the gem directly:
37
+
38
+ ```bash
39
+ gem install cnpj-utilities
40
+ ```
41
+
42
+ Or add it to your `Gemfile` and run `bundle install`:
43
+
44
+ ```ruby
45
+ gem 'cnpj-utilities'
46
+ ```
47
+
48
+ This installs **`cnpj-utilities`** together with [`cnpj-fmt`](https://rubygems.org/gems/cnpj-fmt), [`cnpj-gen`](https://rubygems.org/gems/cnpj-gen), and [`cnpj-val`](https://rubygems.org/gems/cnpj-val). You do **not** need separate `gem install` / `gem` lines for the component packages when using **`cnpj-utilities`**.
49
+
50
+ ## Require
51
+
52
+ ```ruby
53
+ require 'cnpj-utilities'
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ Basic usage with class helpers (aliases of `CnpjUtils::DEFAULT`):
59
+
60
+ ```ruby
61
+ require 'cnpj-utilities'
62
+
63
+ cnpj = '03603568000195'
64
+
65
+ CnpjUtils.format(cnpj) # => "03.603.568/0001-95"
66
+ CnpjUtils.format(cnpj, hidden: true) # => "03.603.***/****-**"
67
+ CnpjUtils.format( # => "03603568|0001_95"
68
+ cnpj,
69
+ dot_key: '',
70
+ slash_key: '|',
71
+ dash_key: '_'
72
+ )
73
+
74
+ CnpjUtils.generate # => e.g. "AB123CDE000155" (14-char alphanumeric)
75
+ CnpjUtils.generate(format: true) # => e.g. "AB.123.CDE/0001-55"
76
+ CnpjUtils.generate(prefix: '45623767') # => e.g. "45623767000296"
77
+ CnpjUtils.generate(type: 'numeric') # => e.g. "65453043000178" (digits only)
78
+
79
+ CnpjUtils.is_valid('98765432000198') # => true
80
+ CnpjUtils.is_valid('98.765.432/0001-98') # => true
81
+ CnpjUtils.is_valid('1QB5UKALPYFP59') # => true (alphanumeric)
82
+ CnpjUtils.is_valid('98765432000199') # => false
83
+ ```
84
+
85
+ ## Usage
86
+
87
+ You can work in these equivalent ways:
88
+
89
+ 1. **`CnpjUtils.format` / `.generate` / `.is_valid`** — class helpers for quick one-off calls (forward to `DEFAULT`).
90
+ 2. **`CnpjUtils::DEFAULT`** — mutable shared singleton (same object the class helpers use; process-wide / not thread-isolated).
91
+ 3. **`CnpjUtils.new`** — configurable instance with shared defaults across format, generate, and validate.
92
+ 4. **Main classes under `CnpjUtils`** — `CnpjUtils::CnpjFormatter`, `CnpjUtils::CnpjGenerator`, `CnpjUtils::CnpjValidator`.
93
+ 5. **Nested package modules** — Options, helpers, errors, and types via `CnpjUtils::CnpjFmt` / `CnpjGen` / `CnpjVal` (e.g. `CnpjUtils::CnpjFmt::CnpjFormatterOptions`, `CnpjUtils::CnpjFmt.cnpj_fmt`).
94
+ 6. **Root sibling modules** (still supported) — `CnpjFmt`, `CnpjGen`, `CnpjVal` unchanged.
95
+
96
+ All approaches expose the same options and behavior. For exhaustive option tables and component-specific details, see the README of each [bundled package](#bundled-packages).
97
+
98
+ ### Formatter options
99
+
100
+ When calling `#format(cnpj_input, options = nil, **keywords)`, all options are optional:
101
+
102
+ | Option | Type | Default | Description |
103
+ |--------|------|---------|-------------|
104
+ | `hidden` | `Boolean` | `false` | When `true`, mask characters in `hidden_start`–`hidden_end` with `hidden_key` |
105
+ | `hidden_key` | `String` | `'*'` | Character(s) used to replace masked characters |
106
+ | `hidden_start` | `Integer` | `5` | Start index (0–13, inclusive) of the range to hide |
107
+ | `hidden_end` | `Integer` | `13` | End index (0–13, inclusive) of the range to hide |
108
+ | `dot_key` | `String` | `'.'` | Dot delimiter (e.g. in `12.345.678`) |
109
+ | `slash_key` | `String` | `'/'` | Slash delimiter (e.g. before branch `…/0001-90`) |
110
+ | `dash_key` | `String` | `'-'` | Dash delimiter (e.g. before check digits `…-90`) |
111
+ | `escape` | `Boolean` | `false` | When `true`, escape HTML special characters in the result |
112
+ | `encode` | `Boolean` | `false` | When `true`, URL-encode the result (similar to JavaScript `encodeURIComponent`) |
113
+ | `on_fail` | `Proc` / callable | returns `''` | Callback when sanitized input length ≠ 14; return value is used as result |
114
+
115
+ ### Generator options
116
+
117
+ When calling `#generate(options = nil, **keywords)`, all options are optional:
118
+
119
+ | Option | Type | Default | Description |
120
+ |--------|------|---------|-------------|
121
+ | `format` | `Boolean` | `false` | When `true`, return the generated CNPJ in standard format (`00.000.000/0000-00`) |
122
+ | `prefix` | `String` | `''` | Partial start string (0–12 alphanumeric chars). Missing characters are generated and check digits computed. |
123
+ | `type` | `String` | `'alphanumeric'` | Character set for the randomly generated part: `'numeric'`, `'alphabetic'`, or `'alphanumeric'`. **Check digits are always numeric.** |
124
+
125
+ Prefix rules: base ID (first 8 chars) and branch ID (chars 9–12) cannot be all zeros; 12 repeated digits (e.g. `111111111111`) are also not allowed.
126
+
127
+ ### Validator options
128
+
129
+ When calling `#is_valid(cnpj_input, options = nil, **keywords)`, all options are optional:
130
+
131
+ | Option | Type | Default | Description |
132
+ |--------|------|---------|-------------|
133
+ | `case_sensitive` | `Boolean` | `true` | When `false`, lowercase letters are accepted for alphanumeric CNPJ (input is uppercased before validation). |
134
+ | `type` | `String` | `'alphanumeric'` | `'numeric'`: only digits (0–9); `'alphanumeric'`: digits and letters (0–9, A–Z). |
135
+
136
+ ### Class helpers (`CnpjUtils.format` / `.generate` / `.is_valid`)
137
+
138
+ These class methods are aliases of the same methods on `CnpjUtils::DEFAULT`. Prefer them for one-off calls:
139
+
140
+ ```ruby
141
+ CnpjUtils.format('03603568000195')
142
+ CnpjUtils.generate(type: 'numeric')
143
+ CnpjUtils.is_valid('98765432000198')
144
+ ```
145
+
146
+ ### `CnpjUtils::DEFAULT` (default instance)
147
+
148
+ `CnpjUtils::DEFAULT` is the pre-built, **mutable** singleton behind the class helpers (parity with the JS default export / Python `cnpj_utils`). Its configuration is **process-wide and shared across threads**: mutating it (e.g. `DEFAULT.formatter = …`) affects subsequent `CnpjUtils.format` / `.generate` / `.is_valid` calls for every caller in the process. Prefer `CnpjUtils.new` or per-call options for concurrent or isolated work; custom instances stay independent of `DEFAULT`:
149
+
150
+ ```ruby
151
+ CnpjUtils::DEFAULT.formatter = { slash_key: '|' }
152
+ CnpjUtils.format('01ABC234000X56') # => "01.ABC.234|000X-56"
153
+
154
+ custom = CnpjUtils.new
155
+ custom.format('01ABC234000X56') # => "01.ABC.234/000X-56" (unaffected)
156
+ ```
157
+
158
+ Instance methods on `DEFAULT` (and any `CnpjUtils` instance):
159
+
160
+ - **`#format(cnpj_input, options = nil, **keywords)`**: Formats a CNPJ string or array of strings. Delegates to the internal formatter. Input must be 14 alphanumeric characters (after sanitization); otherwise `on_fail` is used.
161
+ - **`#generate(options = nil, **keywords)`**: Generates a valid CNPJ. Delegates to the internal generator.
162
+ - **`#is_valid(cnpj_input, options = nil, **keywords)`**: Returns `true` if the CNPJ is valid. Delegates to the internal validator.
163
+
164
+ ### `CnpjUtils` (class)
165
+
166
+ For custom default formatter, generator, or validator, create your own instance:
167
+
168
+ ```ruby
169
+ require 'cnpj-utilities'
170
+
171
+ utils = CnpjUtils.new(
172
+ formatter: { hidden: true, hidden_key: '#' },
173
+ generator: { type: 'numeric', format: true },
174
+ validator: { type: 'numeric', case_sensitive: false }
175
+ )
176
+
177
+ utils.format('RK0CMT3W000100') # => "RK.0CM.###/####-##"
178
+ utils.generate # => e.g. "73.008.535/0005-06"
179
+ utils.is_valid('98.765.432/0001-98') # => true
180
+
181
+ # Access or replace internal instances
182
+ utils.formatter # => CnpjFmt::CnpjFormatter
183
+ utils.generator # => CnpjGen::CnpjGenerator
184
+ utils.validator # => CnpjVal::CnpjValidator
185
+ ```
186
+
187
+ - **`CnpjUtils.new(settings = nil, **keywords)`**: Optional settings. Pass either a settings `Hash` with `:formatter`, `:generator`, and/or `:validator` keys, **or** the same keys as keyword arguments — not both (passing both raises `CnpjUtils::InvalidArgumentCombinationError`). Each value may be a component instance, a `*Options` instance (stored by reference — mutating it later affects subsequent calls with no per-call override), a plain options `Hash`, or omitted/`nil` for defaults.
188
+ - **`#format(cnpj_input, options = nil, **keywords)`**: Same as the default instance; per-call options override the formatter’s defaults for that call only. Pass either an options `Hash`/`CnpjFmt::CnpjFormatterOptions` **or** keyword overrides — not both.
189
+ - **`#generate(options = nil, **keywords)`**: Same as the default instance; per-call options override the generator’s defaults. Pass either an options `Hash`/`CnpjGen::CnpjGeneratorOptions` **or** keyword overrides — not both.
190
+ - **`#is_valid(cnpj_input, options = nil, **keywords)`**: Same as the default instance; per-call options override the validator’s defaults. Pass either an options `Hash`/`CnpjVal::CnpjValidatorOptions` **or** keyword overrides — not both.
191
+ - **`#formatter`**, **`#generator`**, **`#validator`**: Accessors (getters and setters) for the internal components. Setters accept the same shapes as the constructor. To change a single option without replacing the instance, mutate the component’s options (e.g. `utils.formatter.options.hidden = true`).
192
+
193
+ Instance defaults and per-call overrides:
194
+
195
+ ```ruby
196
+ require 'cnpj-utilities'
197
+
198
+ utils = CnpjUtils.new(
199
+ formatter: { hidden: true, hidden_key: '#' },
200
+ generator: { format: true },
201
+ validator: { type: 'numeric' }
202
+ )
203
+
204
+ cnpj = '03603568000195'
205
+
206
+ utils.format(cnpj) # masked (instance formatter defaults)
207
+ utils.format(cnpj, hidden: false) # this call only: unmasked
208
+ utils.generate(format: false) # this call only: compact output
209
+ utils.is_valid('1QB5UKALPYFP59') # => false (instance validator is numeric-only)
210
+ utils.is_valid( # => true for this call
211
+ '1QB5UKALPYFP59',
212
+ type: 'alphanumeric'
213
+ )
214
+ ```
215
+
216
+ Options can also be passed as a `Hash` (or options instance) on each method — without keyword overrides:
217
+
218
+ ```ruby
219
+ utils.format(cnpj, { slash_key: '|' })
220
+ utils.generate({ prefix: '12345', type: 'numeric' })
221
+ utils.is_valid('1QB5UKALPYFP59', { case_sensitive: false })
222
+ ```
223
+
224
+ ### Using component classes and nested modules
225
+
226
+ Preferred paths after `require 'cnpj-utilities'`:
227
+
228
+ ```ruby
229
+ require 'cnpj-utilities'
230
+
231
+ # Main classes at the façade root
232
+ formatter = CnpjUtils::CnpjFormatter.new(hidden: true)
233
+ generator = CnpjUtils::CnpjGenerator.new(type: 'numeric')
234
+ validator = CnpjUtils::CnpjValidator.new
235
+
236
+ formatter.format('AB123XYZ000123') # => "AB.123.***/****-**"
237
+
238
+ # Options, helpers, and errors under nested package modules
239
+ options = CnpjUtils::CnpjFmt::CnpjFormatterOptions.new(slash_key: '|')
240
+ CnpjUtils::CnpjFmt.cnpj_fmt('03603568000195') # => "03.603.568/0001-95"
241
+
242
+ begin
243
+ CnpjUtils::CnpjFmt.cnpj_fmt(12_345)
244
+ rescue CnpjUtils::CnpjFmt::TypeMismatchError
245
+ # wrong input type
246
+ end
247
+ ```
248
+
249
+ Root siblings remain supported (same objects as the nests):
250
+
251
+ ```ruby
252
+ CnpjFmt.cnpj_fmt('01ABC234000X56', slash_key: '|') # => "01.ABC.234|000X-56"
253
+ CnpjGen.cnpj_gen(type: 'numeric') # => e.g. "65453043000178"
254
+ CnpjVal.cnpj_val('9JN7MGLJZXIO50') # => true
255
+ CnpjFmt::CnpjFormatter.new(hidden: true)
256
+ ```
257
+
258
+ See [`cnpj-fmt`](../cnpj-fmt/README.md), [`cnpj-gen`](../cnpj-gen/README.md), and [`cnpj-val`](../cnpj-val/README.md) for full option and error details.
259
+
260
+ ## API
261
+
262
+ ### Exports
263
+
264
+ After `require 'cnpj-utilities'`:
265
+
266
+ - **`CnpjUtils`**: Façade class to create a utils instance with optional default formatter, generator, and validator settings.
267
+ - **`CnpjUtils.format` / `.generate` / `.is_valid`**: Class helpers that forward to `CnpjUtils::DEFAULT`.
268
+ - **`CnpjUtils::DEFAULT`**: Mutable pre-built `CnpjUtils` instance (same object the class helpers use). Process-wide / shared across threads — prefer `CnpjUtils.new` or per-call options under concurrency.
269
+ - **`CnpjUtils::VERSION`**: Gem version string.
270
+ - **Main-class shortcuts**: `CnpjUtils::CnpjFormatter`, `CnpjUtils::CnpjGenerator`, `CnpjUtils::CnpjValidator` (same objects as the sibling classes).
271
+ - **Nested package modules**: `CnpjUtils::CnpjFmt`, `CnpjUtils::CnpjGen`, `CnpjUtils::CnpjVal` — full sibling surface (Options, helpers, errors, types). Options/helpers/errors are **not** aliased at the `CnpjUtils` root.
272
+ - **Root sibling modules** (still supported): `CnpjFmt`, `CnpjGen`, `CnpjVal` — same objects as the nests.
273
+
274
+ ### Errors & Exceptions
275
+
276
+ `CnpjUtils` defines only API-misuse errors for this gem’s argument rules. Component errors are raised by the bundled packages and propagate unchanged.
277
+
278
+ #### Defined by `cnpj-utilities`
279
+
280
+ Errors defined by this gem are **API misuse** only (wrong type or invalid argument combination). Every custom error includes the `CnpjUtils::Error` marker module. This gem defines **no** `CnpjUtils::DomainError` and no domain leaves — domain failures come only from the [bundled packages](#propagated-from-bundled-packages) and keep those packages’ namespaces (`CnpjFmt::…`, `CnpjGen::…`, `CnpjVal::…`).
281
+
282
+ `rescue CnpjUtils::Error` catches **only** errors this gem raises. It does **not** catch component errors that propagate unchanged.
283
+
284
+ ##### Summary
285
+
286
+ | Class | Inherits from | Category | Trigger condition |
287
+ |-------|---------------|----------|-------------------|
288
+ | `CnpjUtils::InvalidArgumentCombinationError` | `CnpjUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (+ `include CnpjUtils::Error`) | API misuse | Non-`nil` settings/options `Hash` (or options instance) passed together with any non-`nil` keyword argument |
289
+ | `CnpjUtils::TypeMismatchError` | `CnpjUtils::TypeMismatchError < TypeError < StandardError` (+ `include CnpjUtils::Error`) | API misuse | Non-`nil` `settings` argument to `CnpjUtils.new` is not a `Hash` |
290
+
291
+ ##### `CnpjUtils::Error` (marker module)
292
+
293
+ - **Inheritance:** module marker mixed into every custom error this gem raises via `include` (not a class).
294
+ - **Category:** N/A (rescue target only) — not a failure mode by itself.
295
+ - **When it is raised:** Never raised directly; included by every custom error this gem raises.
296
+ - **Example:** N/A
297
+ - **How to rescue it:**
298
+
299
+ ```ruby
300
+ rescue CnpjUtils::Error
301
+ # TypeMismatchError, InvalidArgumentCombinationError from this gem only
302
+ # (not CnpjFmt::*, CnpjGen::*, or CnpjVal::* errors)
303
+ ```
304
+
305
+ ##### `CnpjUtils::TypeMismatchError`
306
+
307
+ - **Inheritance:** `CnpjUtils::TypeMismatchError < TypeError < StandardError` (includes `CnpjUtils::Error`)
308
+ - **Category:** API misuse — the caller passed a value of the wrong type.
309
+ - **When it is raised:** Raised when `CnpjUtils.new` receives a non-`nil` `settings` argument that is not a `Hash`.
310
+ - **Example:**
311
+
312
+ ```ruby
313
+ CnpjUtils.new('not-a-hash') # raises CnpjUtils::TypeMismatchError
314
+ CnpjUtils.new(false) # raises CnpjUtils::TypeMismatchError (false is non-nil)
315
+ ```
316
+
317
+ - **How to rescue it:**
318
+
319
+ ```ruby
320
+ rescue CnpjUtils::TypeMismatchError
321
+ # this gem's type-contract violation
322
+
323
+ rescue TypeError
324
+ # native type errors, including this gem's TypeMismatchError
325
+ ```
326
+
327
+ ##### `CnpjUtils::InvalidArgumentCombinationError`
328
+
329
+ - **Inheritance:** `CnpjUtils::InvalidArgumentCombinationError < ArgumentError < StandardError` (includes `CnpjUtils::Error`)
330
+ - **Category:** API misuse — the caller mixed mutually exclusive argument patterns.
331
+ - **When it is raised:** Raised when `CnpjUtils.new`, `#format`, `#generate`, `#is_valid`, or the class helpers receive both a non-`nil` settings/options `Hash` (or options instance) and any non-`nil` keyword argument at the same time.
332
+ - **Example:**
333
+
334
+ ```ruby
335
+ CnpjUtils.new({ formatter: { hidden: true } }, generator: { format: true })
336
+ # raises CnpjUtils::InvalidArgumentCombinationError
337
+
338
+ CnpjUtils.format('03603568000195', { hidden: true }, slash_key: '|')
339
+ # raises CnpjUtils::InvalidArgumentCombinationError
340
+ ```
341
+
342
+ - **How to rescue it:**
343
+
344
+ ```ruby
345
+ rescue CnpjUtils::InvalidArgumentCombinationError
346
+ # this gem's invalid signature combination
347
+
348
+ rescue ArgumentError
349
+ # native argument errors, including this gem's InvalidArgumentCombinationError
350
+ ```
351
+
352
+ ##### Rescue granularity
353
+
354
+ Each level is shown as its own standalone example (do not merge them into one `rescue` ladder — a broad native handler would make narrower clauses unreachable).
355
+
356
+ ```ruby
357
+ require 'cnpj-utilities'
358
+
359
+ # 1) Single native class — catches misuse errors of that kind,
360
+ # including non-library ones already handled elsewhere in the consumer's code.
361
+ begin
362
+ CnpjUtils.new('not-a-hash')
363
+ rescue TypeError
364
+ # CnpjUtils::TypeMismatchError and any other TypeError (library or not)
365
+ end
366
+
367
+ begin
368
+ CnpjUtils.new({ formatter: { hidden: true } }, generator: { format: true })
369
+ rescue ArgumentError
370
+ # CnpjUtils::InvalidArgumentCombinationError and any other ArgumentError (library or not)
371
+ end
372
+ ```
373
+
374
+ ```ruby
375
+ require 'cnpj-utilities'
376
+
377
+ # 2) CnpjUtils::DomainError — not applicable: this gem defines no DomainError
378
+ # (and no domain leaves). Domain failures come from bundled packages only.
379
+ # begin
380
+ # CnpjUtils.new.format(12_345)
381
+ # rescue CnpjUtils::DomainError # NameError — constant is not defined
382
+ # end
383
+ ```
384
+
385
+ ```ruby
386
+ require 'cnpj-utilities'
387
+
388
+ # 3) CnpjUtils::Error — catches everything this gem raises, regardless of native ancestry.
389
+ # Does not catch CnpjFmt::*, CnpjGen::*, or CnpjVal::* errors.
390
+ begin
391
+ CnpjUtils.new('not-a-hash')
392
+ rescue CnpjUtils::Error
393
+ # every custom error that includes CnpjUtils::Error
394
+ end
395
+ ```
396
+
397
+ ```ruby
398
+ require 'cnpj-utilities'
399
+
400
+ # 4) Specific leaf class — catches only that exact failure mode.
401
+ begin
402
+ CnpjUtils.new('not-a-hash')
403
+ rescue CnpjUtils::TypeMismatchError
404
+ # only CnpjUtils::TypeMismatchError
405
+ end
406
+ ```
407
+
408
+ #### Propagated from bundled packages
409
+
410
+ - **Formatting** (`CnpjFmt`): `CnpjFmt::TypeMismatchError`, `CnpjFmt::OutOfRangeError`, `CnpjFmt::ValidationError`, `CnpjFmt::InvalidLengthError` (passed to `on_fail`, not raised by `#format`), and related classes.
411
+ - **Generation** (`CnpjGen`): `CnpjGen::TypeMismatchError`, `CnpjGen::ValidationError`, and related classes.
412
+ - **Validation** (`CnpjVal`): `CnpjVal::TypeMismatchError`, `CnpjVal::ValidationError`, and related classes.
413
+
414
+ Invalid option types are typically **`TypeError`** subclasses (`*::TypeMismatchError`); invalid option values are domain errors under each package’s `DomainError` hierarchy. Validation failure returns `false`; formatting length failure is handled by **`on_fail`** (default returns an empty string).
415
+
416
+ ```ruby
417
+ require 'cnpj-utilities'
418
+
419
+ begin
420
+ CnpjUtils.new.format(12_345)
421
+ rescue CnpjFmt::TypeMismatchError => e
422
+ puts e.message
423
+ end
424
+
425
+ begin
426
+ CnpjUtils.new.is_valid(12_345_678_000_198)
427
+ rescue CnpjVal::TypeMismatchError => e
428
+ puts e.message
429
+ end
430
+
431
+ # Custom on_fail for invalid length
432
+ custom_fail = ->(value, _exception) { "Invalid CNPJ: #{value}" }
433
+
434
+ CnpjFmt.cnpj_fmt('123', on_fail: custom_fail) # => "Invalid CNPJ: 123"
435
+ CnpjFmt.cnpj_fmt('123') # => "" (default on_fail)
436
+ ```
437
+
438
+ ### Bundled packages
439
+
440
+ | Package | Main resources | README |
441
+ |---------|----------------|--------|
442
+ | [`cnpj-fmt`](https://rubygems.org/gems/cnpj-fmt) | `CnpjFmt::CnpjFormatter`, `CnpjFmt::CnpjFormatterOptions`, `CnpjFmt.cnpj_fmt` | [docs](../cnpj-fmt/README.md) |
443
+ | [`cnpj-gen`](https://rubygems.org/gems/cnpj-gen) | `CnpjGen::CnpjGenerator`, `CnpjGen::CnpjGeneratorOptions`, `CnpjGen.cnpj_gen` | [docs](../cnpj-gen/README.md) |
444
+ | [`cnpj-val`](https://rubygems.org/gems/cnpj-val) | `CnpjVal::CnpjValidator`, `CnpjVal::CnpjValidatorOptions`, `CnpjVal.cnpj_val` | [docs](../cnpj-val/README.md) |
445
+
446
+ All of the above are pulled in as dependencies of **`cnpj-utilities`**. For exhaustive option tables, exception lists, and edge-case behavior, see each package README.
447
+
448
+ ## Contribution & Support
449
+
450
+ We welcome contributions! Please see our [Contributing Guidelines](https://github.com/LacusSolutions/br-utils-ruby/blob/main/CONTRIBUTING.md) for details. If you find this project helpful, please consider:
451
+
452
+ - ⭐ Starring the repository
453
+ - 🤝 Contributing to the codebase
454
+ - 💡 [Suggesting new features](https://github.com/LacusSolutions/br-utils-ruby/issues)
455
+ - 🐛 [Reporting bugs](https://github.com/LacusSolutions/br-utils-ruby/issues)
456
+
457
+ ## License
458
+
459
+ This project is licensed under the MIT License — see the [LICENSE](https://github.com/LacusSolutions/br-utils-ruby/blob/main/LICENSE) file for details.
460
+
461
+ ## Changelog
462
+
463
+ See [CHANGELOG](./CHANGELOG.md) for a list of changes and version history.
464
+
465
+ ---
466
+
467
+ Made with ❤️ by [Lacus Solutions](https://github.com/LacusSolutions)