From 3ddffc14d7cd1ba3c956ef7f42219ebab24ee0dc Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Wed, 24 Jun 2026 14:46:01 +0200 Subject: [PATCH] controllogic: add Graph.StateVars declarations (persisted via store JSON) Co-Authored-By: Claude Sonnet 4.6 --- internal/controllogic/model.go | 4 ++++ internal/controllogic/store_test.go | 33 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 internal/controllogic/store_test.go diff --git a/internal/controllogic/model.go b/internal/controllogic/model.go index 8136f5c..8113d9c 100644 --- a/internal/controllogic/model.go +++ b/internal/controllogic/model.go @@ -72,6 +72,10 @@ type Graph struct { Nodes []Node `json:"nodes"` Wires []Wire `json:"wires"` Groups []NodeGroup `json:"groups,omitempty"` + // StateVars declares graph-local variables (scalar or array). Live values are + // instantiated in memory per generation from these declarations; only the + // declarations persist. Mirrors the panel-logic statevars feature. + StateVars []StateVar `json:"statevars,omitempty"` } func (n Node) param(key string) string { diff --git a/internal/controllogic/store_test.go b/internal/controllogic/store_test.go new file mode 100644 index 0000000..cdfb1bc --- /dev/null +++ b/internal/controllogic/store_test.go @@ -0,0 +1,33 @@ +package controllogic + +import "testing" + +func TestStoreRoundTripStateVars(t *testing.T) { + dir := t.TempDir() + st, err := NewStore(dir) // NewStore takes the storage DIRECTORY + if err != nil { + t.Fatal(err) + } + g := Graph{ + ID: "g1", + Name: "with-vars", + StateVars: []StateVar{ + {Name: "count", Type: "number", Initial: "0"}, + {Name: "buf", Type: "array", Initial: "[1,2]", Elem: "number", Sizing: "capped", Capacity: 5}, + }, + } + if err := st.Save(g); err != nil { // Save returns only error + t.Fatal(err) + } + st2, err := NewStore(dir) + if err != nil { + t.Fatal(err) + } + got, err := st2.Get("g1") // Get returns (Graph, error); ErrNotFound if absent + if err != nil { + t.Fatal(err) + } + if len(got.StateVars) != 2 || got.StateVars[1].Name != "buf" || got.StateVars[1].Capacity != 5 { + t.Fatalf("statevars not round-tripped: %#v", got.StateVars) + } +}