Asynchronous resources

luastra/resource

Models bounded asynchronous reads and mutations as small explicit state machines. Generation tickets suppress stale results, immutable snapshots drive UI, and application-owned errors preserve retry and field context without leaking provider details.

Create controllers once outside render, begin an operation when the host request starts, and settle only the matching ticket from resolve.

Use one read controller per logical value and one mutation controller per non-concurrent write workflow; compose them in application or feature state rather than subclassing them.

Complete example

local Resource = require("luastra/resource")

local profile = Resource.new {
    isEmpty = function(value: { name: string }): boolean
        return value.name == ""
    end,
}

local ticket = profile.begin(requestId, "load")
if result ~= nil then
    profile.resolve(ticket, result)
else
    profile.reject(ticket, Resource.error("NOT_FOUND", false))
end

local snapshot = profile.snapshot()

Detail pages

Resource.ErrorResource.ReadStatusResource.MutationStatusResource.ReadModeResource.TicketResource.ReadOptionsResource.ReadSnapshotResource.ReadStateResource.OptimisticChangeResource.MutationOptionsResource.MutationStartOptionsResource.MutationSnapshotResource.MutationStateResource.errorResource.newResource.newMutation