66 lines
1.8 KiB
Go
66 lines
1.8 KiB
Go
package contract
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
"git.ipao.vip/rogee/go-sip/contracts"
|
|
"github.com/santhosh-tekuri/jsonschema/v6"
|
|
)
|
|
|
|
var compiledSchemas sync.Map
|
|
|
|
// ValidateCurrent checks only the current project-local HTTP/MQ contract.
|
|
// An absent schema is an error; it never falls back to historical bundles.
|
|
func ValidateCurrent(surface string, raw []byte) error {
|
|
var name string
|
|
switch surface {
|
|
case "config-read", "task-discovery", "mq":
|
|
name = surface + ".schema.json"
|
|
default:
|
|
return fmt.Errorf("invalid current contract surface %q", surface)
|
|
}
|
|
value, err := jsonschema.UnmarshalJSON(bytes.NewReader(raw))
|
|
if err != nil {
|
|
return fmt.Errorf("decode %s body: %w", surface, err)
|
|
}
|
|
key := "current/" + name
|
|
cached, ok := compiledSchemas.Load(key)
|
|
var schema *jsonschema.Schema
|
|
if ok {
|
|
schema = cached.(*jsonschema.Schema)
|
|
} else {
|
|
data, err := contracts.ReadCurrent(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
doc, err := jsonschema.UnmarshalJSON(bytes.NewReader(data))
|
|
if err != nil {
|
|
return fmt.Errorf("decode current schema %s: %w", name, err)
|
|
}
|
|
compiler := jsonschema.NewCompiler()
|
|
compiler.AssertFormat()
|
|
resource := "https://go-sip.local/contracts/current/" + name
|
|
if err := compiler.AddResource(resource, doc); err != nil {
|
|
return fmt.Errorf("register %s: %w", name, err)
|
|
}
|
|
schema, err = compiler.Compile(resource)
|
|
if err != nil {
|
|
return fmt.Errorf("compile %s: %w", name, err)
|
|
}
|
|
actual, _ := compiledSchemas.LoadOrStore(key, schema)
|
|
schema = actual.(*jsonschema.Schema)
|
|
}
|
|
if err := schema.Validate(value); err != nil {
|
|
var validation *jsonschema.ValidationError
|
|
if errors.As(err, &validation) {
|
|
return fmt.Errorf("%s validation failed at /%s", surface, strings.Join(validation.InstanceLocation, "/"))
|
|
}
|
|
return fmt.Errorf("%s validation failed", surface)
|
|
}
|
|
return nil
|
|
}
|