85 lines
2.4 KiB
Go
85 lines
2.4 KiB
Go
package contracts
|
|
|
|
import (
|
|
"bytes"
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/santhosh-tekuri/jsonschema/v6"
|
|
)
|
|
|
|
// Files contains the shared contract at the project's pinned submodule commit.
|
|
// Runtime code never reads a checkout or resolves schema refs online.
|
|
//
|
|
//go:embed schema/*.json schema/examples
|
|
var Files embed.FS
|
|
|
|
// ReadCurrent reads only shared root schemas and MQ topology.
|
|
// There is no fallback to historical contracts or project-local copies.
|
|
func ReadCurrent(name string) ([]byte, error) {
|
|
if name != path.Base(name) || strings.Contains(name, "\\") {
|
|
return nil, fmt.Errorf("invalid current contract %q", name)
|
|
}
|
|
if name != "mq-topology.json" && !strings.HasSuffix(name, ".schema.json") {
|
|
return nil, fmt.Errorf("invalid current contract %q", name)
|
|
}
|
|
return Files.ReadFile(path.Join("schema", name))
|
|
}
|
|
|
|
type offlineSchemaLoader struct{}
|
|
|
|
func (offlineSchemaLoader) Load(url string) (any, error) {
|
|
return nil, fmt.Errorf("unregistered shared schema reference %q; network loading is disabled", url)
|
|
}
|
|
|
|
// CompileCurrent registers all canonical split schemas before compiling an
|
|
// entrypoint. Unregistered references fail explicitly, without network access.
|
|
func CompileCurrent(name string) (*jsonschema.Schema, error) {
|
|
if _, err := ReadCurrent(name); err != nil {
|
|
return nil, err
|
|
}
|
|
if !strings.HasSuffix(name, ".schema.json") {
|
|
return nil, fmt.Errorf("not a schema: %q", name)
|
|
}
|
|
compiler := jsonschema.NewCompiler()
|
|
compiler.AssertFormat()
|
|
compiler.UseLoader(offlineSchemaLoader{})
|
|
files, err := fs.Glob(Files, "schema/*.schema.json")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var resource string
|
|
for _, file := range files {
|
|
data, err := Files.ReadFile(file)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
doc, err := jsonschema.UnmarshalJSON(bytes.NewReader(data))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("decode shared schema %s: %w", file, err)
|
|
}
|
|
object, ok := doc.(map[string]any)
|
|
if !ok {
|
|
return nil, fmt.Errorf("shared schema %s must be an object", file)
|
|
}
|
|
id, ok := object["$id"].(string)
|
|
if !ok || id == "" {
|
|
return nil, fmt.Errorf("shared schema %s is missing $id", file)
|
|
}
|
|
if err := compiler.AddResource(id, doc); err != nil {
|
|
return nil, fmt.Errorf("register shared schema %s: %w", file, err)
|
|
}
|
|
if path.Base(file) == name {
|
|
resource = id
|
|
}
|
|
}
|
|
schema, err := compiler.Compile(resource)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("compile shared schema %s: %w", name, err)
|
|
}
|
|
return schema, nil
|
|
}
|