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
83 lines
2.2 KiB
Go
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
|
|
}
|