catalogue's working set starts empty and a host gives it the seats it read (UseSeats over SeatsFromDefinitions); the node-engine's verbs and events take the seat's name from the caller. Tests take their seats from seatlisttest. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
73 lines
1.9 KiB
Go
73 lines
1.9 KiB
Go
package seatdef
|
|
|
|
import "strings"
|
|
|
|
// 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.
|
|
func ResolveRefs(schema map[string]any, defs map[string]map[string]any) map[string]any {
|
|
if schema == nil {
|
|
return nil
|
|
}
|
|
m, _ := StringLists(resolveValue(schema, defs, 0)).(map[string]any)
|
|
return m
|
|
}
|
|
|
|
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[strings.TrimPrefix(r, "#/defs/")]; 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
|
|
}
|