LuaRocks y el ecosistema de paquetes de Lua en 2026

Una de las críticas habituales a Lua es que su biblioteca estándar es intencionadamente pequeña. No hay módulo de HTTP, ni de JSON, ni de expresiones regulares PCRE, ni de filesystem completo. Esa filosofía de mínima superficie es una decisión de diseño consciente: el intérprete se mantiene pequeño y es la comunidad quien aporta los módulos adicionales a través de LuaRocks.

¿Qué es LuaRocks?

LuaRocks es el gestor de paquetes de Lua. Un paquete en LuaRocks se llama rock y consiste en código Lua puro, extensiones C compiladas, o una combinación de ambos. El registro público está en luarocks.org y cuenta con miles de paquetes disponibles. LuaRocks descarga las fuentes, las compila si hace falta y las instala en el directorio correcto para que require las encuentre.

Instalación y uso básico

# Instalar LuaRocks (Ubuntu/Debian)
sudo apt install luarocks

# Instalar un paquete globalmente
luarocks install luasocket

# Instalar una versión concreta
luarocks install lua-cjson 2.1.0

# Instalar solo para el usuario actual (sin sudo)
luarocks install --local penlight

# Listar paquetes instalados
luarocks list

# Buscar un paquete en el registro
luarocks search http

# Ver información de un paquete
luarocks show busted

# Eliminar un paquete
luarocks remove luasocket

Paquetes imprescindibles en 2026

luasocket: networking básico

La biblioteca de red más usada en Lua. Proporciona TCP, UDP, HTTP simple y DNS:

local http = require("socket.http")
local ltn12 = require("ltn12")

-- GET sencillo
local body, code, headers = http.request("http://ejemplo.com/api/datos")
print("HTTP " .. code)
print(body)

-- GET con sink para respuestas grandes
local resultado = {}
http.request({
    url = "http://api.ejemplo.com/datos",
    sink = ltn12.sink.table(resultado),
    headers = {["Accept"] = "application/json"}
})
print(table.concat(resultado))

lua-cjson: JSON rápido

Módulo C para codificar y decodificar JSON. Mucho más rápido que implementaciones Lua puras:

local cjson = require("cjson")

-- Decodificar
local datos = cjson.decode('{"nombre":"Ana","edad":30,"activo":true}')
print(datos.nombre)   -- Ana
print(datos.edad)     -- 30

-- Codificar
local obj = {
    usuarios = {"Ana", "Bruno", "Carla"},
    total = 3,
    pagina = 1
}
print(cjson.encode(obj))
-- {"usuarios":["Ana","Bruno","Carla"],"total":3,"pagina":1}

-- null de JSON se mapea a cjson.null (no a nil)
local con_null = cjson.decode('{"campo":null}')
if con_null.campo == cjson.null then
    print("El campo es null en JSON")
end

penlight: utilidades de propósito general

Penlight es la biblioteca de «puertas de batería incluidas» de Lua. Cubre colecciones, strings, ficheros, templates y más:

local pl = require("pl.import_into")()

-- Manipulación de paths
local path = pl.path
print(path.join("/usr", "local", "bin"))   -- /usr/local/bin
print(path.basename("/usr/local/bin/lua")) -- lua
print(path.exists("/etc/hosts"))           -- true o false

-- Strings
local stringx = pl.stringx
print(stringx.strip("  hola mundo  "))    -- "hola mundo"
print(stringx.startswith("hola", "ho"))   -- true
local partes = stringx.split("a,b,c", ",")
-- {"a", "b", "c"}

-- Colecciones funcionales
local tablex = pl.tablex
local nums = {1, 2, 3, 4, 5, 6}
local pares = tablex.filter(nums, function(x) return x % 2 == 0 end)
-- {2, 4, 6}
local cuadrados = tablex.map(function(x) return x * x end, nums)
-- {1, 4, 9, 16, 25, 36}

busted: testing

El framework de testing más usado en Lua. Usa una sintaxis BDD similar a Mocha o RSpec:

-- fichero: spec/calculadora_spec.lua
local calc = require("calculadora")

describe("Calculadora", function()
    it("suma dos números", function()
        assert.are.equal(5, calc.suma(2, 3))
    end)

    it("devuelve error al dividir por cero", function()
        assert.has_error(function()
            calc.dividir(10, 0)
        end, "división por cero")
    end)

    describe("operaciones en cadena", function()
        it("permite encadenar sumas", function()
            local resultado = calc.nuevo():suma(1):suma(2):suma(3):valor()
            assert.are.equal(6, resultado)
        end)
    end)
end)
# Ejecutar todos los tests
busted

# Solo un fichero
busted spec/calculadora_spec.lua

# Con cobertura (requiere luacov)
busted --coverage

luafilesystem (lfs): acceso al sistema de ficheros

local lfs = require("lfs")

-- Listar un directorio
for entrada in lfs.dir("/tmp") do
    if entrada ~= "." and entrada ~= ".." then
        local info = lfs.attributes("/tmp/" .. entrada)
        print(entrada, info.mode, info.size)
    end
end

-- Crear directorio y cambiar permisos
lfs.mkdir("/tmp/mi_directorio")

-- Atributos de un fichero
local attr = lfs.attributes("/etc/hosts")
print("Tamaño: " .. attr.size .. " bytes")
print("Modificado: " .. os.date("%Y-%m-%d", attr.modification))

Crear un rockspec propio

Para distribuir tu propio módulo Lua, creas un fichero .rockspec que describe el paquete:

-- mi-modulo-1.0-1.rockspec
package = "mi-modulo"
version = "1.0-1"
source = {
    url = "https://github.com/usuario/mi-modulo/archive/v1.0.tar.gz",
    md5 = "abc123..."
}
description = {
    summary = "Un módulo Lua de ejemplo",
    homepage = "https://github.com/usuario/mi-modulo",
    license = "MIT"
}
dependencies = {
    "lua >= 5.1",
    "lua-cjson >= 2.0"
}
build = {
    type = "builtin",
    modules = {
        ["mi-modulo"] = "src/mi-modulo.lua",
        ["mi-modulo.util"] = "src/util.lua"
    }
}
# Instalar localmente desde el rockspec
luarocks make mi-modulo-1.0-1.rockspec

# Subir al registro (requiere cuenta en luarocks.org)
luarocks upload mi-modulo-1.0-1.rockspec --api-key=TU_CLAVE

LuaRocks resuelve el problema más importante que tenía Lua como lenguaje práctico: la ausencia de un repositorio centralizado de código reutilizable. Combinado con las capacidades de metatables para OOP y el ecosistema de LuaJIT para rendimiento, convierte a Lua en una plataforma viable para proyectos de tamaño mediano sin necesidad de reinventar la rueda en cada proyecto.

Imagen: Pexels / Pixabay

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP