summaryrefslogtreecommitdiffstats
path: root/lib/src/errors.dart
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:25:04 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:53:07 -0300
commit82d92ed4291663bae94014b4363064dbb26c6a51 (patch)
tree69d91a59c955f1e6ec6fc0007324b5d73b3f0d01 /lib/src/errors.dart
parent8e719fc715eb7ae9aa1c842e633f15b5c6cd3688 (diff)
downloaddart-82d92ed4291663bae94014b4363064dbb26c6a51.tar.gz
Name the municipality behind a CEP that does not existHEADv0.2.0main
A CEP that fails a lookup is rarely a random number: it is usually someone who knows the city and guessed the digits, and the classic guess is the -000 that 957 municipalities never received. The API now attaches a faixa block to the 404 naming the municipality that band belongs to, so the caller can answer "no, but you were looking at Areal/RJ" instead of just "no". It stays an error. Faixa hangs off CepNotFoundException, never off Address, and cepIni/cepFim are the extremes that actually exist in the municipality rather than the range the Correios publish — echoing back the published start would return the very CEP that just failed. The interval is sparse, which is what ceps is for; it is not a list of alternatives. Parsing is deliberately forgiving: a missing, empty or malformed block is null. Losing a clean not-found to a parse error over the hint attached to it would be a bad trade.
Diffstat (limited to 'lib/src/errors.dart')
-rw-r--r--lib/src/errors.dart34
1 files changed, 32 insertions, 2 deletions
diff --git a/lib/src/errors.dart b/lib/src/errors.dart
index 24b35c4..be32b25 100644
--- a/lib/src/errors.dart
+++ b/lib/src/errors.dart
@@ -18,6 +18,8 @@
/// all, when the CEP is malformed before it ever leaves the machine.
library;
+import 'models.dart';
+
/// Base of every error this library throws. Catch this to handle any failure.
///
/// Sealed: the subtypes below are the complete set, so a `switch` on one is
@@ -59,12 +61,40 @@ final class InvalidCepException extends CepisException
}
/// The CEP is well-formed but does not exist in the DNE database.
+///
+/// [faixa] may name the municipality the CEP would have belonged to. It does
+/// not soften the error: this is still a 404, and there is still no address.
final class CepNotFoundException extends CepisException {
- /// Creates the error for [message], recording the normalised [cep].
- const CepNotFoundException(super.message, {this.cep});
+ /// Creates the error for [message], recording the normalised [cep] and the
+ /// [faixa] the API named, when it named one.
+ const CepNotFoundException(super.message, {this.cep, this.faixa});
/// The CEP that was looked up, normalised to 8 digits.
final String? cep;
+
+ /// The municipality that owns the numeric band this CEP fell in, or `null`.
+ ///
+ /// `null` when the CEP falls in a band no municipality owns — the API
+ /// **omits** the block there rather than sending null — and also whenever the
+ /// block cannot be read. See [Faixa], and read [Faixa.cepIni]/[Faixa.cepFim]
+ /// as the extremes that exist, not as a range of valid CEPs.
+ final Faixa? faixa;
+
+ /// Mentions the municipality when the API named one.
+ ///
+ /// The count comes along deliberately: `118 CEPs` across nearly five
+ /// thousand numbers is what stops the two bounds from reading like a range
+ /// where anything in between would work.
+ @override
+ String toString() {
+ final band = faixa;
+ if (band == null) {
+ return super.toString();
+ }
+ return '$runtimeType: $message — that band belongs to '
+ '${band.localidade}/${band.uf}, which has ${band.ceps} CEPs scattered '
+ 'between ${band.cepIni} and ${band.cepFim}';
+ }
}
/// The request never completed: DNS, refused connection, timeout, TLS.