summaryrefslogtreecommitdiffstats
path: root/cepis.lua
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-26 12:42:08 -0300
committerMurilo Ijanc <[email protected]>2026-07-26 12:42:08 -0300
commit7fd555fcaf4304cb0dff3e8f5661565c3618299e (patch)
tree61199793c3046d73b97e9822895ede2a33034d41 /cepis.lua
downloadlua-7fd555fcaf4304cb0dff3e8f5661565c3618299e.tar.gz
Initial importv0.1.0
Diffstat (limited to 'cepis.lua')
-rw-r--r--cepis.lua157
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