From 401a2851c643c5051c75310704cfdc94d6b0a072 Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 14:16:18 +0200 Subject: Compose global state activation --- lua/clever_f/composition_root.lua | 130 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 lua/clever_f/composition_root.lua (limited to 'lua/clever_f') diff --git a/lua/clever_f/composition_root.lua b/lua/clever_f/composition_root.lua new file mode 100644 index 0000000..e04c177 --- /dev/null +++ b/lua/clever_f/composition_root.lua @@ -0,0 +1,130 @@ +local action_facade = require("clever_f.action_facade") +local capabilities = require("clever_f.capabilities") +local feedback_service = require("clever_f.feedback_service") +local policy = require("clever_f.policy") +local sequence_coordinator = require("clever_f.sequence_coordinator") +local sequence_state = require("clever_f.sequence_state") +local state_transitions = require("clever_f.state_transitions") + +local M = {} +local CompositionRoot = {} +CompositionRoot.__index = CompositionRoot +M.CompositionRoot = CompositionRoot + +local root_records = setmetatable({}, { __mode = "k" }) + +local function fail(message, level) + error(message, (level or 1) + 1) +end + +local function normalize_options(options) + if type(options) ~= "table" then + fail("CompositionRoot options must be a table", 3) + end + if options.host == nil then + return { host = options } + end + return options +end + +function CompositionRoot.new(options) + if CompositionRoot.is(options) then + return options + end + options = normalize_options(options) + local host = capabilities.assert_implements(options.host) + local state = sequence_state.new() + local transitions = options.transitions + or options.state_transitions + or state_transitions.new(state) + local policy_service = options.policy + or options.policy_service + or policy.new(host) + local feedback = options.feedback + or options.feedback_service + or feedback_service.new({ + host = host, + state = state, + transitions = transitions, + policy = policy_service, + }) + local coordinator = options.coordinator + or options.sequence_coordinator + or sequence_coordinator.new({ + host = host, + state = state, + transitions = transitions, + policy = policy_service, + feedback = feedback, + }) + local facade = options.facade + or options.action_facade + or action_facade.new({ coordinator = coordinator }) + + local root = setmetatable({}, CompositionRoot) + root_records[root] = { + host = host, + state = state, + transitions = transitions, + policy = policy_service, + feedback = feedback, + coordinator = coordinator, + facade = facade, + activation = nil, + } + return root +end + +function CompositionRoot.is(value) + return type(value) == "table" and root_records[value] ~= nil +end + +function CompositionRoot:activate() + local record = root_records[self] + if record.activation == nil then + record.activation = { + state = record.state, + } + end + return record.activation +end + +function CompositionRoot:host() + return root_records[self].host +end + +function CompositionRoot:state() + return root_records[self].state +end + +function CompositionRoot:transitions() + return root_records[self].transitions +end + +function CompositionRoot:policy() + return root_records[self].policy +end + +function CompositionRoot:feedback() + return root_records[self].feedback +end + +function CompositionRoot:coordinator() + return root_records[self].coordinator +end + +function CompositionRoot:facade() + return root_records[self].facade +end + +function M.new(options) + return CompositionRoot.new(options) +end + +setmetatable(M, { + __call = function(_, options) + return CompositionRoot.new(options) + end, +}) + +return M -- cgit v1.2.3