From 0bc578d6d334c7f1ccaf329cd61bb8bce76b7f59 Mon Sep 17 00:00:00 2001 From: Murilo Ijanc Date: Sun, 26 Jul 2026 14:40:05 -0300 Subject: Initial import --- lib/Cepis.pm | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 lib/Cepis.pm (limited to 'lib/Cepis.pm') diff --git a/lib/Cepis.pm b/lib/Cepis.pm new file mode 100644 index 0000000..224d80d --- /dev/null +++ b/lib/Cepis.pm @@ -0,0 +1,184 @@ +package Cepis; + +use strict; +use warnings; + +use Exporter 5.57 qw(import); + +use Cepis::Address; +use Cepis::Client; +use Cepis::Error; +use Cepis::Geo; +use Cepis::Health; + +our $VERSION = '0.1.0'; + +our @EXPORT_OK = qw(lookup lookup_many health normalize_cep); + +my $DEFAULT_CLIENT; + +sub default_client { + $DEFAULT_CLIENT = Cepis::Client->new unless defined $DEFAULT_CLIENT; + return $DEFAULT_CLIENT; +} + +sub lookup { + return default_client()->lookup(@_); +} + +sub lookup_many { + return default_client()->lookup_many(@_); +} + +sub health { + return default_client()->health; +} + +sub normalize_cep { + return Cepis::Client::normalize_cep(@_); +} + +1; + +__END__ + +=encoding UTF-8 + +=head1 NAME + +Cepis - Perl client for the public CEP API at cep.is + +=head1 SYNOPSIS + + use Cepis; + + my $address = Cepis::lookup('01001-000'); + print $address->localidade, ' ', $address->uf, "\n"; # São Paulo SP + + my $result = Cepis::lookup_many( [ '01001000', '99999999' ] ); + print defined $result->[1] ? 'found' : 'not found', "\n"; + + my $health = Cepis::health(); + print $health->dne, "\n"; + +=head1 DESCRIPTION + +Looks Brazilian postal codes up against L: official Correios +data (DNE), refreshed every two weeks. Single lookups carry coordinates when the +database has them; batches resolve up to 500 CEPs in one request. + +B L, L and L all ship +with Perl, and the CSV reader is part of this distribution. Reaching +C does need L and L, which do not +ship with Perl — see L. + +For a script, the module-level functions are enough. In an application, build a +L once and reuse it: + + my $client = Cepis::Client->new( timeout => 5.0, total_timeout => 15.0 ); + my $address = $client->lookup('01001000'); + +Pointing at a local instance (the API repo brings one up with C): + + my $client = Cepis::Client->new( base_url => 'http://localhost:8080' ); + +=head2 Errors + +Every failure is thrown as an object under L, so one test catches +the lot, and the split below it is by whether retrying helps: + + my $address = eval { Cepis::lookup($cep_from_form) }; + if ( !$address ) { + my $err = $@; + if ( ref $err && $err->isa('Cepis::Error::CEPNotFound') ) { + # the CEP does not exist: ask the user for another + } + elsif ( ref $err && $err->isa('Cepis::Error') ) { + # network, server, rate limit: retry later + } + else { + die $err; + } + } + +=head2 Field names + +The API surface is English, but the B — C, C, C. What you read in the JSON is +what you read on the object. See L. + +=head2 HTTPS support + +L speaks HTTPS only when L 1.968 or later and +L 1.49 or later are installed, and neither ships with Perl. Without +them, any call against the default C throws +L straight away with a message naming both modules. +C reports the same thing without making a +request. See L. + +=head1 FUNCTIONS + +The module-level functions all go through one shared default client, built on +first use. It applies process-wide, including to third-party libraries that also +use this module, so do not reconfigure it — anyone needing different settings +should build their own L. + +Nothing is exported by default. C, C, C and +C are available on request: + + use Cepis qw(lookup lookup_many); + +=head2 lookup + + my $address = Cepis::lookup('01001-000'); + +Looks up a CEP using the default configuration and returns a +L. Shorthand for C<< Cepis::default_client->lookup($cep) >>; see +L for the errors it throws. + +=head2 lookup_many + + my $result = Cepis::lookup_many( \@ceps ); + +Looks many CEPs up in one batch, using the default configuration, and returns an +arrayref of the same length and order with C for the misses. Shorthand +for L — read that one, especially the warning that +batches carry no coordinate. + +=head2 health + + my $health = Cepis::health(); + +Queries the API's health using the default configuration and returns a +L. Shorthand for L. + +=head2 normalize_cep + + my $number = Cepis::normalize_cep('01001-000'); # "01001000" + +Strips the mask and validates that 8 digits remain, throwing +L otherwise. Makes no request. See +L. + +=head2 default_client + + my $client = Cepis::default_client(); + +The L behind the functions above, built on first use. + +=head1 SEE ALSO + +L, L, L, L, +L + +The API itself is documented at L. + +=head1 AUTHOR + +Murilo Ijanc Emurilo@ijanc.orgE + +=head1 LICENCE + +ISC. Copyright (c) 2026 Murilo Ijanc Emurilo@ijanc.orgE. + +=cut -- cgit v1.3