feat: publish immutable workflow definitions with typed SDK
This commit is contained in:
75
weave/definition/data.go
Normal file
75
weave/definition/data.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package definition
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"git.yuntuo.hk/k2safe/orbit/internal/jsonvalue"
|
||||
)
|
||||
|
||||
// ValidateData 在实例输入、任务成功结果、信号和块输出边界复用同一类型契约。
|
||||
// 使用精确JSON数值文本;大小、重复字段、Unicode和嵌套限制先于类型检查。
|
||||
func ValidateData(schema Type, raw json.RawMessage) error {
|
||||
if err := checkType(schema, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(raw) == 0 || len(raw) > 256<<10 {
|
||||
return invalid("data", "JSON value required, maximum 256 KiB")
|
||||
}
|
||||
if _, err := jsonvalue.Canonical(raw); err != nil {
|
||||
return invalid("data", "invalid JSON, duplicate fields or unsupported value limits")
|
||||
}
|
||||
var value any
|
||||
d := json.NewDecoder(bytes.NewReader(raw))
|
||||
d.UseNumber()
|
||||
if err := d.Decode(&value); err != nil {
|
||||
return invalid("data", "invalid JSON value")
|
||||
}
|
||||
return matchData(schema, value)
|
||||
}
|
||||
func matchData(schema Type, value any) error {
|
||||
valid := false
|
||||
switch schema.Kind {
|
||||
case "JSON":
|
||||
return nil
|
||||
case "NULL":
|
||||
valid = value == nil
|
||||
case "STRING":
|
||||
v, ok := value.(string)
|
||||
valid = ok && (len(schema.Enum) == 0 || contains(schema.Enum, v))
|
||||
case "NUMBER":
|
||||
_, valid = value.(json.Number)
|
||||
case "BOOLEAN":
|
||||
_, valid = value.(bool)
|
||||
case "OBJECT":
|
||||
v, ok := value.(map[string]any)
|
||||
if !ok || len(v) != len(schema.Fields) {
|
||||
return invalid("data", "object fields do not match declared type")
|
||||
}
|
||||
for key, t := range schema.Fields {
|
||||
child, ok := v[key]
|
||||
if !ok {
|
||||
return invalid("data", "required object field missing")
|
||||
}
|
||||
if err := matchData(t, child); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case "ARRAY":
|
||||
v, ok := value.([]any)
|
||||
if !ok || len(v) > 4096 {
|
||||
return invalid("data", "array required, maximum 4096 elements")
|
||||
}
|
||||
for _, child := range v {
|
||||
if err := matchData(*schema.Items, child); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !valid {
|
||||
return invalid("data", "value does not match declared type")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user