diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-26 12:42:08 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-26 12:42:08 -0300 |
| commit | 7fd555fcaf4304cb0dff3e8f5661565c3618299e (patch) | |
| tree | 61199793c3046d73b97e9822895ede2a33034d41 /cepis.lua | |
| download | lua-7fd555fcaf4304cb0dff3e8f5661565c3618299e.tar.gz | |
Initial importv0.1.0
Diffstat (limited to 'cepis.lua')
| -rw-r--r-- | cepis.lua | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/cepis.lua b/cepis.lua new file mode 100644 index 0000000..e120af1 --- /dev/null +++ b/cepis.lua @@ -0,0 +1,157 @@ +--- Lua client for the public CEP API at [cep.is](https://cep.is). +-- +-- Quick use — for a script, the module-level functions are enough: +-- +-- local cepis = require("cepis") +-- +-- local address, err = cepis.lookup("01001-000") +-- print(address.localidade, address.uf) --> São Paulo SP +-- +-- In an application — build a client once and reuse it: +-- +-- local client = cepis.new({ timeout = 5, total_timeout = 15 }) +-- local address, err = client:lookup("01001000") +-- +-- Pointing at a local instance (the API repo brings one up with `just up`): +-- +-- local client = cepis.new({ base_url = "http://localhost:8080" }) +-- +-- Expected failures are returned, never thrown, and every error carries a +-- `kind` so the caller branches on one string instead of matching messages: +-- +-- local address, err = cepis.lookup(cep_from_form) +-- if not address then +-- if err.kind == cepis.NOT_FOUND then +-- -- the CEP does not exist: ask the user for another +-- elseif err:is_retriable() then +-- -- network, server, rate limit: reschedule +-- end +-- end +-- +-- `error()` is reserved for programmer mistakes — a bad option table, a wrong +-- argument type. Those are bugs to fix, not conditions to handle. +-- +-- Note on field names: the API surface is English, but the **data fields keep +-- the API's own Portuguese names** (`logradouro`, `bairro`, `localidade`). +-- What you read in the JSON is what you index on the table. +-- +-- The module-level functions share one default client, built on first use. +-- It applies process-wide, including to any other library that also requires +-- this module. Anyone needing different settings should build their own. +-- +-- @module cepis + +local client = require("cepis.client") +local errors = require("cepis.errors") +local models = require("cepis.models") + +local M = {} + +--- Library version. +M._VERSION = client.VERSION + +--- Where the API lives unless `base_url` says otherwise: `https://cep.is`. +M.DEFAULT_URL = client.DEFAULT_URL + +--- How many CEPs the batch endpoint accepts in one request: `500`. +M.MAX_BATCH = client.MAX_BATCH + +--- The `Client` class. `cepis.new` is the shorthand for `Client.new`. +M.Client = client.Client + +--- The `Address` metatable, for `getmetatable(x) == cepis.Address`. +M.Address = models.Address + +--- The `Geo` metatable. +M.Geo = models.Geo + +--- The `Health` metatable. +M.Health = models.Health + +--- Error kind: the CEP is not 8 digits. No request was made. +M.INVALID_CEP = errors.INVALID_CEP + +--- Error kind: well-formed, but absent from the DNE database. +M.NOT_FOUND = errors.NOT_FOUND + +--- Error kind: 429 on every attempt. `err.retry_after` may hold seconds. +M.RATE_LIMITED = errors.RATE_LIMITED + +--- Error kind: 5xx on every attempt. `err.status` holds the last one seen. +M.SERVER_ERROR = errors.SERVER_ERROR + +--- Error kind: the request never completed — DNS, connection, timeout, TLS. +M.NETWORK_ERROR = errors.NETWORK_ERROR + +--- Error kind: a success status with a body that cannot be parsed. +M.INVALID_RESPONSE = errors.INVALID_RESPONSE + +--- Every error kind, keyed by itself. +M.kinds = errors.kinds + +--- Whether a value is one of this library's errors. +-- @param value anything +-- @treturn boolean +M.is_error = errors.is + +--- Build a client. See `cepis.client.Client.new` for every option. +-- @tparam[opt] table opts +-- @treturn Client +M.new = client.Client.new + +--- Return the CEP's 8 digits, accepting the mask. +-- @tparam string value +-- @treturn[1] string +-- @treturn[2] nil +-- @treturn[2] table the error +M.normalize_cep = client.normalize_cep + +local default + +--- The shared client behind the module-level functions. +-- +-- Built on first use with every default. Do not mutate it: it applies +-- process-wide. +-- @treturn Client +function M.default() + if not default then + default = client.Client.new() + end + return default +end + +--- Look up a CEP using the default configuration. +-- +-- Shorthand for `cepis.default():lookup(cep)`. +-- @tparam string cep masked or unmasked +-- @treturn[1] Address +-- @treturn[2] nil +-- @treturn[2] table the error +function M.lookup(cep) + return M.default():lookup(cep) +end + +--- Look up many CEPs in one batch, using the default configuration. +-- +-- Shorthand for `cepis.default():lookup_many(ceps)` — read that one, in +-- particular why a missing CEP is `false` and not `nil`, and the warning that +-- batches carry no coordinate. +-- @tparam table ceps list of strings +-- @treturn[1] table list of `Address|false` +-- @treturn[2] nil +-- @treturn[2] table the error +function M.lookup_many(ceps) + return M.default():lookup_many(ceps) +end + +--- Query the API's health using the default configuration. +-- +-- Shorthand for `cepis.default():health()`. +-- @treturn[1] Health +-- @treturn[2] nil +-- @treturn[2] table the error +function M.health() + return M.default():health() +end + +return M |