Files
mesh-sdk/go/seatdef/refs.go
T
jschoubben e29c452aa3 RR-2, RR-3: the reader reads a verb's and a manifest's needs-approval and a definition's bodies
A verb's needs-approval is a boolean, a manifest's a list of tools, seat verbs and events; bodies are named schemas the
grants part makes no seat event or stream from, and a reference #/bodies/<name> resolves beside #/defs/<name>. All 40
definitions of mesh-contracts' feat/47-G-build (5f7610f) read.

Builds: design 47 G §409, §439, §448; design 46 M7 §1, §2, §23

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 10:49:32 +01:00

83 lines
2.2 KiB
Go

package seatdef
// ResolveRefs is a schema (its all-string lists as []string, StringLists) with every `{"$ref": "#/defs/<name>"}` replaced by the definition's named type, as the seat
// list's readers need it (a verb's input and answer are one schema each, not a schema and its types). A reference to a
// name the definition does not define stays as it is; nesting deeper than 32 levels stops there.
//
// A reference `#/bodies/<name>` resolves against the definition's bodies, given after defs (design 47 G §439).
func ResolveRefs(schema map[string]any, defs map[string]map[string]any, bodies ...map[string]map[string]any) map[string]any {
if schema == nil {
return nil
}
all := make(map[string]map[string]any, len(defs))
for n, d := range defs {
all["#/defs/"+n] = d
}
for _, b := range bodies {
for n, d := range b {
all["#/bodies/"+n] = d
}
}
m, _ := StringLists(resolveValue(schema, all, 0)).(map[string]any)
return m
}
// resolveValue resolves against refs, each reference as written (`#/defs/<name>`, `#/bodies/<name>`).
func resolveValue(v any, defs map[string]map[string]any, depth int) any {
if depth > 32 {
return v
}
switch x := v.(type) {
case map[string]any:
if r, ok := x["$ref"].(string); ok {
if d, ok := defs[r]; ok {
return resolveValue(d, defs, depth+1)
}
}
out := make(map[string]any, len(x))
for k, e := range x {
out[k] = resolveValue(e, defs, depth+1)
}
return out
case []any:
out := make([]any, len(x))
for i, e := range x {
out[i] = resolveValue(e, defs, depth+1)
}
return out
}
return v
}
// StringLists is a schema with every list whose items are all strings (`required`, `enum`) as a []string, the form the
// compiled seat list wrote them in; a JSON decoder reads them as []any.
func StringLists(v any) any {
switch x := v.(type) {
case map[string]any:
out := make(map[string]any, len(x))
for k, e := range x {
out[k] = StringLists(e)
}
return out
case []any:
strs := make([]string, 0, len(x))
for _, e := range x {
s, ok := e.(string)
if !ok {
strs = nil
break
}
strs = append(strs, s)
}
if strs != nil && len(x) > 0 {
return strs
}
out := make([]any, len(x))
for i, e := range x {
out[i] = StringLists(e)
}
return out
}
return v
}