6. Replace src/main.luau
generated Luau client · trusted JavaScript handler · about 25 minutesinput → RequestId → resolve → decode → state
The application stores each request ID and changes visible state only after the matching completion is decoded.
When to use it
Replace the entry module after generation. This is the complete asynchronous client lifecycle rather than a synchronous function return.
Focused example
--!strict
local ServerFunctions = require("app/server-functions")
local UI = require("luastra/ui")
local App = require("luastra/app")
local Root = {}
local name = "Ada"
local status = "Ready"
local pending: {[number]: boolean} = {}
local function busy(): boolean
return next(pending) ~= nil
end
function Root.render(): UI.Node
return UI.Screen {
id = "server-recipe",
width = "content",
padding = "responsive",
UI.Card {
id = "greeting/card",
gap = "md",
padding = "lg",
surface = "elevated",
UI.Text { id = "greeting/title", text = "Server greeting", variant = "title" },
UI.Field {
id = "greeting/name-field",
gap = "xs",
role = "group",
label = "Name field",
UI.Text { id = "greeting/name-label", text = "Name" },
UI.TextInput {
id = "greeting/name",
label = "Name",
value = name,
onInput = "greeting.name",
autoComplete = "name",
enterKeyHint = "done",
required = true,
},
},
UI.Button {
id = "greeting/send",
text = if busy() then "Waiting..." else "Ask the server",
onTap = "greeting.send",
disabled = busy(),
},
UI.Text { id = "greeting/status", text = status, role = "status" },
},
}
end
function Root.handle(action: string, target: string, value: string)
if action == "greeting.name" and target == "greeting/name" then
name = value
status = "Ready"
elseif action == "greeting.send" and target == "greeting/send" and not busy() then
local requestId = ServerFunctions.greet({ name = name }, { deadlineMs = 2000, retry = true })
pending[requestId] = true
status = "Waiting for the server..."
end
end
function Root.resolve(
requestId: number,
success: boolean,
payload: string,
errorCode: string,
errorMessage: string
)
if pending[requestId] ~= true then return end
pending[requestId] = nil
if not success then
status = errorCode .. ": " .. errorMessage
return
end
local result = ServerFunctions.decodeGreet(payload)
if result == nil then
status = "INTERNAL: Invalid greeting response"
return
end
status = result.message
end
function Root.snapshot()
return { name = name, status = status, busy = busy() }
end
return App.compose {
render = function(_outputs) return Root.render() end,
handle = Root.handle,
resolve = Root.resolve,
snapshot = Root.snapshot,
}