mirror of
https://github.com/foomo/squadron.git
synced 2025-10-16 12:35:42 +00:00
125 lines
3.0 KiB
Go
125 lines
3.0 KiB
Go
package jsonschema
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// JSONSchema represents the structure of a JSON schema
|
|
type JSONSchema struct {
|
|
baseSchema map[string]any
|
|
}
|
|
|
|
// New takes a URL to the base JSON schema and returns a JSONSchema instance
|
|
func New() *JSONSchema {
|
|
return &JSONSchema{}
|
|
}
|
|
|
|
func (js *JSONSchema) LoadBaseSchema(ctx context.Context, url string) error {
|
|
baseSchema, err := LoadMap(ctx, url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
js.baseSchema = baseSchema
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetSquadronUnitSchema overrides the base schema at the given path with another JSON schema from a URL
|
|
func (js *JSONSchema) SetSquadronUnitSchema(ctx context.Context, squadron, unit, url string) error {
|
|
var ref string
|
|
if strings.HasPrefix(url, "http") {
|
|
ref = strings.TrimPrefix(url, "https:")
|
|
ref = strings.TrimPrefix(ref, "http:")
|
|
ref = strings.TrimPrefix(ref, "//")
|
|
} else {
|
|
ref = path.Clean(url)
|
|
ref = strings.TrimPrefix(ref, "..")
|
|
ref = strings.TrimPrefix(ref, ".")
|
|
ref = strings.TrimPrefix(ref, "/")
|
|
}
|
|
|
|
ref = strings.TrimSuffix(ref, "/")
|
|
ref = strings.ReplaceAll(ref, "/", "-")
|
|
ref = strings.ToLower(ref)
|
|
|
|
// retrieve definitions
|
|
defsMap := js.ensure(js.baseSchema, "$defs", map[string]any{})
|
|
|
|
// add definition
|
|
if _, ok := defsMap[ref]; !ok {
|
|
valuesMap, err := LoadMap(ctx, url)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to load map: "+url)
|
|
}
|
|
|
|
delete(valuesMap, "$schema")
|
|
js.ensure(defsMap, ref, valuesMap)
|
|
}
|
|
|
|
// extend Config
|
|
configMap := js.ensure(defsMap, "Config", map[string]any{})
|
|
configPropertiesMap := js.ensure(configMap, "properties", map[string]any{})
|
|
squadronsMap := js.ensure(configPropertiesMap, "squadron", map[string]any{})
|
|
squadronsPropertiesMap := js.ensure(squadronsMap, "properties", map[string]any{})
|
|
squadronMap := js.ensure(squadronsPropertiesMap, squadron, map[string]any{
|
|
"additionalProperties": map[string]any{
|
|
"$ref": "#/$defs/Unit",
|
|
},
|
|
"type": "object",
|
|
})
|
|
squadronPropertiesMap := js.ensure(squadronMap, "properties", map[string]any{})
|
|
_ = js.ensure(squadronPropertiesMap, unit, map[string]any{
|
|
"anyOf": []map[string]any{
|
|
{
|
|
"$ref": "#/$defs/Unit",
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"values": map[string]any{
|
|
"$ref": "#/$defs/" + ref,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// String outputs the resulting JSON schema as string
|
|
func (js *JSONSchema) String() (string, error) {
|
|
output, err := json.Marshal(js.baseSchema)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(output), nil
|
|
}
|
|
|
|
// PrettyString outputs the resulting JSON schema as a formatted string
|
|
func (js *JSONSchema) PrettyString() (string, error) {
|
|
output, err := json.MarshalIndent(js.baseSchema, "", " ")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(output), nil
|
|
}
|
|
|
|
func (js *JSONSchema) ensure(source map[string]any, name string, initial map[string]any) map[string]any {
|
|
ret, ok := source[name].(map[string]any)
|
|
if !ok {
|
|
ret = initial
|
|
source[name] = ret
|
|
}
|
|
|
|
return ret
|
|
}
|