Files
esp32-lua-api/AGENTS.md
T
evan 772618ef89 feat(json): JSON for apps through vendored lua-cjson
lua-cjson decodes straight onto the Lua stack, so a response costs its
text plus the table it becomes rather than a document in between, and it
brings the encode half that a C tokenizer would have left to write here.

It is a module rather than a global: a global namespace is a contract a
firmware implements, and nothing about this needs a provider. Registering
into package.preload also puts it ahead of the SD-card searcher, so an
implementation cannot be shadowed, and an app that never requires it
never pays for the module.

Depth is capped at 32 through the module's own knobs rather than by
patching the vendored source. Decoding recurses on the C stack and
upstream defaults to 1000, which assumes a server rather than a FreeRTOS
task.
2026-08-05 16:41:51 -04:00

26 lines
2.1 KiB
Markdown

# ESP32 Lua API Guidelines
This is a clean contract for repositories under the same owner's control. Choose the best shared
API without preserving old names, signatures, or behavior; consumers migrate to the contract.
Every firmware implements all declarations under `lua/api/core/`. Optional hardware contracts
live under `lua/api/features/`, as one file or one directory per feature; `sys.hasFeature(name)`
guarantees the complete matching contract. Every namespace belongs to exactly one feature or to
core, so a feature is a provider pointer rather than a claim to validate: a panel is the `screen`
feature (`screen` and `tree`, including the saved rotation and theme), registered only when the
firmware supplies a `GuiProvider`, and calibration is `touch.setCalibration()`.
A global namespace is a provider contract a firmware implements; anything this library provides
itself is a module instead, so `require` and globals divide by who supplies the code. Those live in
`native/src/bindings/lib/` and register into `package.preload`, which puts them ahead of the SD-card
searcher so nothing shadows an implementation. Pure-Lua modules stay in `lua/lib/`, where shadowing
is allowed because a module there is self-contained: it belongs in `lua/lib/` only if replacing it
can break nothing but itself.
Lua-language sources stay under `lua/`; C/C++ and the vendored interpreter stay under `native/`.
Apps are fully trusted; keep permissions and sandboxing out of scope.
Firmware commits dirty display content and owns panel refresh policy. Binding annotations under
`native/src/bindings/` generate matching `lua/api/` files; regenerate instead of editing files
marked generated. Callbacks are fields on the table an app returns, so a `@lua-app` block generates
a class an app composes (`---@class PaintApp : App, TouchHandlers`) rather than global functions. Each `@lua-module`/`@lua-augment` directive sits immediately above the
`luaL_Reg` table it describes, which is how one source declares several namespaces. This repository owns portable `lua/lib/` modules; shared UI owns theme application and persistence. Use `ble` for BLE/GATT
and reserve `bt` for a future Classic Bluetooth contract.