diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-26 14:40:05 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-26 14:40:05 -0300 |
| commit | 0bc578d6d334c7f1ccaf329cd61bb8bce76b7f59 (patch) | |
| tree | 86f73108f0432fd8330edcaab8b8ae7018322dee /lib/Cepis.pm | |
| download | perl-0.1.0.tar.gz | |
Initial importv0.1.0
Diffstat (limited to 'lib/Cepis.pm')
| -rw-r--r-- | lib/Cepis.pm | 184 |
1 files changed, 184 insertions, 0 deletions
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<https://cep.is>: 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<No non-core dependencies.> L<HTTP::Tiny>, L<JSON::PP> and L<Encode> all ship +with Perl, and the CSV reader is part of this distribution. Reaching +C<https://cep.is> does need L<IO::Socket::SSL> and L<Net::SSLeay>, which do not +ship with Perl — see L</"HTTPS support">. + +For a script, the module-level functions are enough. In an application, build a +L<Cepis::Client> 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<just up>): + + my $client = Cepis::Client->new( base_url => 'http://localhost:8080' ); + +=head2 Errors + +Every failure is thrown as an object under L<Cepis::Error>, 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<data fields keep the API's own Portuguese +names> — C<logradouro>, C<bairro>, C<localidade>. What you read in the JSON is +what you read on the object. See L<Cepis::Address>. + +=head2 HTTPS support + +L<HTTP::Tiny> speaks HTTPS only when L<IO::Socket::SSL> 1.968 or later and +L<Net::SSLeay> 1.49 or later are installed, and neither ships with Perl. Without +them, any call against the default C<https://cep.is> throws +L<Cepis::Error::Network> straight away with a message naming both modules. +C<Cepis::Client::tls_available()> reports the same thing without making a +request. See L<Cepis::Client/"HTTPS support">. + +=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<Cepis::Client>. + +Nothing is exported by default. C<lookup>, C<lookup_many>, C<health> and +C<normalize_cep> 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<Cepis::Address>. Shorthand for C<< Cepis::default_client->lookup($cep) >>; see +L<Cepis::Client/lookup> 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<undef> for the misses. Shorthand +for L<Cepis::Client/lookup_many> — 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<Cepis::Health>. Shorthand for L<Cepis::Client/health>. + +=head2 normalize_cep + + my $number = Cepis::normalize_cep('01001-000'); # "01001000" + +Strips the mask and validates that 8 digits remain, throwing +L<Cepis::Error::InvalidCEP> otherwise. Makes no request. See +L<Cepis::Client/normalize_cep>. + +=head2 default_client + + my $client = Cepis::default_client(); + +The L<Cepis::Client> behind the functions above, built on first use. + +=head1 SEE ALSO + +L<Cepis::Client>, L<Cepis::Address>, L<Cepis::Geo>, L<Cepis::Health>, +L<Cepis::Error> + +The API itself is documented at L<https://cep.is>. + +=head1 AUTHOR + +Murilo Ijanc E<lt>[email protected]<gt> + +=head1 LICENCE + +ISC. Copyright (c) 2026 Murilo Ijanc E<lt>[email protected]<gt>. + +=cut |