Caelum-Lua is your go-to framework for structured, safe, and strongly-typed Lua scripting β without giving up the simplicity and speed of Lua.
Originally crafted to embed Lua into custom engines with reflection and automatic UI inspectors, Caelum has grown into a complete toolset for the Lua Language
β
Safer code β catch type errors early
β
Structured design β Classes, Structs, Enums, Arrays, Maps
β
Modern features β Switch-case, try-catch, custom errors
β
Embed-friendly β Designed for engine integrations & live validation
Caelum adds what Lua is missing β without changing what makes Lua great.
- π§± OOP System β
class,struct,inheritancewith type-safe fields and methods. - π·οΈ Enums β Clean enum handling with index/next helpers.
- π Strong Type System β Type checking with metatables and proxies.
- π§© Advanced Data Types β
Array,Map, all fully type-checked. - π Metadata Support β Title, description, range, and custom metadata.
- πΎ Serialization & Deserialization β Easily convert objects to pure lua tables and restore them.
- β Validators & Events β Automatic on-change triggers and custom validators.
βοΈ Language Features βswitch,try-catch-finally, and structured error handling.
- The framework can be easily installed with luarocks with the command
$ luarocks install caelum
β οΈ Note: The LuaRocks version may lag behind GitHub. For the latest updates, clone directly from GitHub.
- Simply copy the Caelum.lua file into your projectβs
src/folder.
Other examples for every feature of the framework can be found in the examples/ folder
local c = require "Caelum"
MyClass = c.class "MyClass" {
val = c.int(50),
__init = function(self, init_values)
if type(init_values) == "number" then
self.val = init_values
end
end
}
local instance = MyClass:new(20)
print(instance.val) -- Output: 20
local c = require "Caelum"
MyEnum = c.enum( "MyEnum", { "ONE", "TWO", "THREE", "FOUR" }, {
default = "ONE"
})
MyClass = c.class "MyClass" {
val = c.field(MyEnum, "TWO"),
}
local instance = MyClass:new()
print(instance.val) -- Output: TWO
print(MyEnum.get_index(instance.val)) -- Output: 2
print(MyEnum.get_next(instance.val)) -- Output: THREE
instance.val = "FIVE"local c = require "Caelum"
MyClass = c.class "MyClass" {
arr = c.array(c.Int, {0,1,2,3,4})
}
local instance = MyClass:new()
print("Array len at start: " .. instance.arr.length) -- Output: Array len at start: 5
instance.arr:push(5)
print("Array len after push: " .. instance.arr.length) -- Output: Array len after push: 6
instance.arr:forEach(function(element, index)
print("[" .. index .. "] = " .. element) -- Output: [1] = 0 [2] = 1 ...
end)
instance.arr:pop()
print("Array len at end: " .. instance.arr.length) -- Output: Array len at end: 5local TestError = c.class("TestError", c.Error){
errCode = c.int(0),
__init = function(self, init_values)
if init_values then
self.msg = init_values[1] or self.msg
self.errCode = init_values[2] or self.errCode
end
end,
what = function(self) -- This is an overriden function from the Error base class
return string.format("ERROR: %s", self.msg)
end,
code = function(self)
return self.errCode
end
}
try(function()
local var = 5
if var ~= 10 then
throw(TestError:new({"Testing Error System", 3}))
end
end)
:catch(TestError, function(err)
print("TestError: " .. err:what() .. " with error code: " .. err:code())
end)
:catch(function(err)
print("General catch:" .. err:what())
end)
:finally(function()
print("This should be called at the end!")
end)
local c = require "Caelum"
MyClass = c.class "MyClass" {
val = c.int(50),
__init = function(self, init_values)
if type(init_values) == "number" then
self.val = init_values
end
end
}
local instance = MyClass:new(20)
local serialized_table = c.serialize(instance)
local reconstructed_instance = c.deserialize(serialized_table)
Caelum is built to be open and extensible.
π’ Found a bug? π£ Have an idea? π Want to contribute?
π Issues and pull requests are welcome! Letβs make Lua structured together.
Link to the luarocks module page here
Caelum is released under the MIT License.