mirror of
https://github.com/jwetzell/showbridge-go.git
synced 2026-04-26 21:05:30 +00:00
move schema to an internal package
This commit is contained in:
10
api.go
10
api.go
@@ -10,8 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/jwetzell/showbridge-go/internal/config"
|
"github.com/jwetzell/showbridge-go/internal/config"
|
||||||
"github.com/jwetzell/showbridge-go/internal/module"
|
"github.com/jwetzell/showbridge-go/internal/module"
|
||||||
"github.com/jwetzell/showbridge-go/internal/processor"
|
|
||||||
"github.com/jwetzell/showbridge-go/internal/route"
|
"github.com/jwetzell/showbridge-go/internal/route"
|
||||||
|
"github.com/jwetzell/showbridge-go/internal/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Router) startAPIServer(config config.ApiConfig) {
|
func (r *Router) startAPIServer(config config.ApiConfig) {
|
||||||
@@ -135,7 +135,7 @@ func (r *Router) handleConfigHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
func handleConfigSchema(w http.ResponseWriter, req *http.Request) {
|
func handleConfigSchema(w http.ResponseWriter, req *http.Request) {
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
schemaJSON, err := json.Marshal(config.ConfigSchema)
|
schemaJSON, err := json.Marshal(schema.ConfigSchema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -157,7 +157,7 @@ func handleConfigSchema(w http.ResponseWriter, req *http.Request) {
|
|||||||
func handleRoutesSchema(w http.ResponseWriter, req *http.Request) {
|
func handleRoutesSchema(w http.ResponseWriter, req *http.Request) {
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
schemaJSON, err := json.Marshal(config.RoutesConfigSchema)
|
schemaJSON, err := json.Marshal(schema.RoutesConfigSchema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -179,7 +179,7 @@ func handleRoutesSchema(w http.ResponseWriter, req *http.Request) {
|
|||||||
func handleModulesSchema(w http.ResponseWriter, req *http.Request) {
|
func handleModulesSchema(w http.ResponseWriter, req *http.Request) {
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
schemaJSON, err := json.Marshal(module.GetModulesSchema())
|
schemaJSON, err := json.Marshal(schema.GetModulesSchema())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -201,7 +201,7 @@ func handleModulesSchema(w http.ResponseWriter, req *http.Request) {
|
|||||||
func handleProcessorsSchema(w http.ResponseWriter, req *http.Request) {
|
func handleProcessorsSchema(w http.ResponseWriter, req *http.Request) {
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
schemaJSON, err := json.Marshal(processor.GetProcessorsSchema())
|
schemaJSON, err := json.Marshal(schema.GetProcessorsSchema())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,28 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/google/jsonschema-go/jsonschema"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ApiConfig struct {
|
type ApiConfig struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var ApiConfigSchema = jsonschema.Schema{
|
|
||||||
Type: "object",
|
|
||||||
Properties: map[string]*jsonschema.Schema{
|
|
||||||
"enabled": {
|
|
||||||
Type: "boolean",
|
|
||||||
Description: "Whether the API server is enabled",
|
|
||||||
Default: json.RawMessage(`false`),
|
|
||||||
},
|
|
||||||
"port": {
|
|
||||||
Type: "integer",
|
|
||||||
Description: "Port for the API server to listen on",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Required: []string{"port"},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,28 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/google/jsonschema-go/jsonschema"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Api ApiConfig `json:"api"`
|
Api ApiConfig `json:"api"`
|
||||||
Modules []ModuleConfig `json:"modules"`
|
Modules []ModuleConfig `json:"modules"`
|
||||||
Routes []RouteConfig `json:"routes"`
|
Routes []RouteConfig `json:"routes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var ConfigSchema = jsonschema.Schema{
|
|
||||||
Schema: "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
ID: "https://showbridge.io/config.schema.json",
|
|
||||||
Title: "Config",
|
|
||||||
Description: "showbridge configuration",
|
|
||||||
Type: "object",
|
|
||||||
Properties: map[string]*jsonschema.Schema{
|
|
||||||
"api": &ApiConfigSchema,
|
|
||||||
"modules": {
|
|
||||||
Ref: "https://showbridge.io/modules.schema.json",
|
|
||||||
},
|
|
||||||
"routes": {
|
|
||||||
Ref: "https://showbridge.io/routes.schema.json",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,29 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/google/jsonschema-go/jsonschema"
|
|
||||||
|
|
||||||
type RouteConfig struct {
|
type RouteConfig struct {
|
||||||
Input string `json:"input"`
|
Input string `json:"input"`
|
||||||
Processors []ProcessorConfig `json:"processors"`
|
Processors []ProcessorConfig `json:"processors"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var RoutesConfigSchema = jsonschema.Schema{
|
|
||||||
Schema: "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
ID: "https://showbridge.io/routes.schema.json",
|
|
||||||
Title: "Routes",
|
|
||||||
Description: "route configurations",
|
|
||||||
Type: "array",
|
|
||||||
Items: &jsonschema.Schema{
|
|
||||||
Type: "object",
|
|
||||||
Properties: map[string]*jsonschema.Schema{
|
|
||||||
"input": {
|
|
||||||
Type: "string",
|
|
||||||
MinLength: jsonschema.Ptr(1),
|
|
||||||
},
|
|
||||||
"processors": {
|
|
||||||
Ref: "https://showbridge.io/processors.schema.json",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Required: []string{"input"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -50,49 +50,3 @@ var (
|
|||||||
func CreateLogger(config config.ModuleConfig) *slog.Logger {
|
func CreateLogger(config config.ModuleConfig) *slog.Logger {
|
||||||
return slog.Default().With("component", "module", "id", config.Id, "type", config.Type)
|
return slog.Default().With("component", "module", "id", config.Id, "type", config.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetModulesSchema() *jsonschema.Schema {
|
|
||||||
moduleRegistryMu.RLock()
|
|
||||||
defer moduleRegistryMu.RUnlock()
|
|
||||||
|
|
||||||
schema := &jsonschema.Schema{
|
|
||||||
Schema: "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
ID: "https://showbridge.io/modules.schema.json",
|
|
||||||
Title: "Modules",
|
|
||||||
Description: "module configurations",
|
|
||||||
Type: "array",
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleDefinitionSchemas := []*jsonschema.Schema{}
|
|
||||||
for _, mod := range ModuleRegistry {
|
|
||||||
moduleSchema := &jsonschema.Schema{
|
|
||||||
Type: "object",
|
|
||||||
Properties: map[string]*jsonschema.Schema{
|
|
||||||
"id": {
|
|
||||||
Type: "string",
|
|
||||||
MinLength: jsonschema.Ptr(1),
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
Const: jsonschema.Ptr[any](mod.Type),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Required: []string{"id", "type"},
|
|
||||||
AdditionalProperties: nil,
|
|
||||||
}
|
|
||||||
if mod.Title != "" {
|
|
||||||
moduleSchema.Title = mod.Title
|
|
||||||
}
|
|
||||||
if mod.Description != "" {
|
|
||||||
moduleSchema.Description = mod.Description
|
|
||||||
}
|
|
||||||
if mod.ParamsSchema != nil {
|
|
||||||
moduleSchema.Properties["params"] = mod.ParamsSchema
|
|
||||||
moduleSchema.Required = append(moduleSchema.Required, "params")
|
|
||||||
}
|
|
||||||
moduleDefinitionSchemas = append(moduleDefinitionSchemas, moduleSchema)
|
|
||||||
}
|
|
||||||
schema.Items = &jsonschema.Schema{
|
|
||||||
OneOf: moduleDefinitionSchemas,
|
|
||||||
}
|
|
||||||
return schema
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -45,45 +45,3 @@ var (
|
|||||||
processorRegistryMu sync.RWMutex
|
processorRegistryMu sync.RWMutex
|
||||||
ProcessorRegistry = make(map[string]ProcessorRegistration)
|
ProcessorRegistry = make(map[string]ProcessorRegistration)
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetProcessorsSchema() *jsonschema.Schema {
|
|
||||||
processorRegistryMu.RLock()
|
|
||||||
defer processorRegistryMu.RUnlock()
|
|
||||||
|
|
||||||
schema := &jsonschema.Schema{
|
|
||||||
Schema: "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
ID: "https://showbridge.io/processors.schema.json",
|
|
||||||
Title: "Processors",
|
|
||||||
Description: "processor configurations",
|
|
||||||
Type: "array",
|
|
||||||
}
|
|
||||||
|
|
||||||
processorDefinitionSchemas := []*jsonschema.Schema{}
|
|
||||||
for _, proc := range ProcessorRegistry {
|
|
||||||
processorSchema := &jsonschema.Schema{
|
|
||||||
Type: "object",
|
|
||||||
Properties: map[string]*jsonschema.Schema{
|
|
||||||
"type": {
|
|
||||||
Const: jsonschema.Ptr[any](proc.Type),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Required: []string{"type"},
|
|
||||||
AdditionalProperties: nil,
|
|
||||||
}
|
|
||||||
if proc.Title != "" {
|
|
||||||
processorSchema.Title = proc.Title
|
|
||||||
}
|
|
||||||
if proc.Description != "" {
|
|
||||||
processorSchema.Description = proc.Description
|
|
||||||
}
|
|
||||||
if proc.ParamsSchema != nil {
|
|
||||||
processorSchema.Properties["params"] = proc.ParamsSchema
|
|
||||||
processorSchema.Required = append(processorSchema.Required, "params")
|
|
||||||
}
|
|
||||||
processorDefinitionSchemas = append(processorDefinitionSchemas, processorSchema)
|
|
||||||
}
|
|
||||||
schema.Items = &jsonschema.Schema{
|
|
||||||
OneOf: processorDefinitionSchemas,
|
|
||||||
}
|
|
||||||
return schema
|
|
||||||
}
|
|
||||||
|
|||||||
26
internal/schema/api.go
Normal file
26
internal/schema/api.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/google/jsonschema-go/jsonschema"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ApiConfigSchema = jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"enabled": {
|
||||||
|
Type: "boolean",
|
||||||
|
Description: "Whether the API server is enabled",
|
||||||
|
Default: json.RawMessage(`false`),
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
Type: "integer",
|
||||||
|
Description: "Port for the API server to listen on",
|
||||||
|
Minimum: jsonschema.Ptr[float64](1024),
|
||||||
|
Maximum: jsonschema.Ptr[float64](65535),
|
||||||
|
Default: json.RawMessage(`8080`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"port"},
|
||||||
|
}
|
||||||
45
internal/schema/config.go
Normal file
45
internal/schema/config.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/google/jsonschema-go/jsonschema"
|
||||||
|
"github.com/jwetzell/showbridge-go/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ConfigSchema = jsonschema.Schema{
|
||||||
|
Schema: "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
ID: "https://showbridge.io/config.schema.json",
|
||||||
|
Title: "Config",
|
||||||
|
Description: "showbridge configuration",
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"api": &ApiConfigSchema,
|
||||||
|
"modules": {
|
||||||
|
Ref: "https://showbridge.io/modules.schema.json",
|
||||||
|
},
|
||||||
|
"routes": {
|
||||||
|
Ref: "https://showbridge.io/routes.schema.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateConfig(config config.Config) error {
|
||||||
|
resolvedSchema, err := GetResolvedConfigSchema()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonBytes, err := json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonMap := make(map[string]any)
|
||||||
|
err = json.Unmarshal(jsonBytes, &jsonMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvedSchema.Validate(jsonMap)
|
||||||
|
}
|
||||||
50
internal/schema/modules.go
Normal file
50
internal/schema/modules.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/jsonschema-go/jsonschema"
|
||||||
|
"github.com/jwetzell/showbridge-go/internal/module"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetModulesSchema() *jsonschema.Schema {
|
||||||
|
|
||||||
|
schema := &jsonschema.Schema{
|
||||||
|
Schema: "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
ID: "https://showbridge.io/modules.schema.json",
|
||||||
|
Title: "Modules",
|
||||||
|
Description: "module configurations",
|
||||||
|
Type: "array",
|
||||||
|
}
|
||||||
|
|
||||||
|
moduleDefinitionSchemas := []*jsonschema.Schema{}
|
||||||
|
for _, mod := range module.ModuleRegistry {
|
||||||
|
moduleSchema := &jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"id": {
|
||||||
|
Type: "string",
|
||||||
|
MinLength: jsonschema.Ptr(1),
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
Const: jsonschema.Ptr[any](mod.Type),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"id", "type"},
|
||||||
|
AdditionalProperties: nil,
|
||||||
|
}
|
||||||
|
if mod.Title != "" {
|
||||||
|
moduleSchema.Title = mod.Title
|
||||||
|
}
|
||||||
|
if mod.Description != "" {
|
||||||
|
moduleSchema.Description = mod.Description
|
||||||
|
}
|
||||||
|
if mod.ParamsSchema != nil {
|
||||||
|
moduleSchema.Properties["params"] = mod.ParamsSchema
|
||||||
|
moduleSchema.Required = append(moduleSchema.Required, "params")
|
||||||
|
}
|
||||||
|
moduleDefinitionSchemas = append(moduleDefinitionSchemas, moduleSchema)
|
||||||
|
}
|
||||||
|
schema.Items = &jsonschema.Schema{
|
||||||
|
OneOf: moduleDefinitionSchemas,
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
46
internal/schema/processors.go
Normal file
46
internal/schema/processors.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/jsonschema-go/jsonschema"
|
||||||
|
"github.com/jwetzell/showbridge-go/internal/processor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProcessorsSchema() *jsonschema.Schema {
|
||||||
|
|
||||||
|
schema := &jsonschema.Schema{
|
||||||
|
Schema: "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
ID: "https://showbridge.io/processors.schema.json",
|
||||||
|
Title: "Processors",
|
||||||
|
Description: "processor configurations",
|
||||||
|
Type: "array",
|
||||||
|
}
|
||||||
|
|
||||||
|
processorDefinitionSchemas := []*jsonschema.Schema{}
|
||||||
|
for _, proc := range processor.ProcessorRegistry {
|
||||||
|
processorSchema := &jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"type": {
|
||||||
|
Const: jsonschema.Ptr[any](proc.Type),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"type"},
|
||||||
|
AdditionalProperties: nil,
|
||||||
|
}
|
||||||
|
if proc.Title != "" {
|
||||||
|
processorSchema.Title = proc.Title
|
||||||
|
}
|
||||||
|
if proc.Description != "" {
|
||||||
|
processorSchema.Description = proc.Description
|
||||||
|
}
|
||||||
|
if proc.ParamsSchema != nil {
|
||||||
|
processorSchema.Properties["params"] = proc.ParamsSchema
|
||||||
|
processorSchema.Required = append(processorSchema.Required, "params")
|
||||||
|
}
|
||||||
|
processorDefinitionSchemas = append(processorDefinitionSchemas, processorSchema)
|
||||||
|
}
|
||||||
|
schema.Items = &jsonschema.Schema{
|
||||||
|
OneOf: processorDefinitionSchemas,
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
24
internal/schema/routes.go
Normal file
24
internal/schema/routes.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import "github.com/google/jsonschema-go/jsonschema"
|
||||||
|
|
||||||
|
var RoutesConfigSchema = jsonschema.Schema{
|
||||||
|
Schema: "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
ID: "https://showbridge.io/routes.schema.json",
|
||||||
|
Title: "Routes",
|
||||||
|
Description: "route configurations",
|
||||||
|
Type: "array",
|
||||||
|
Items: &jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"input": {
|
||||||
|
Type: "string",
|
||||||
|
MinLength: jsonschema.Ptr(1),
|
||||||
|
},
|
||||||
|
"processors": {
|
||||||
|
Ref: "https://showbridge.io/processors.schema.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"input"},
|
||||||
|
},
|
||||||
|
}
|
||||||
27
internal/schema/schema.go
Normal file
27
internal/schema/schema.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/google/jsonschema-go/jsonschema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetResolvedConfigSchema() (*jsonschema.Resolved, error) {
|
||||||
|
configSchema := ConfigSchema
|
||||||
|
|
||||||
|
return configSchema.Resolve(&jsonschema.ResolveOptions{
|
||||||
|
Loader: func(uri *url.URL) (*jsonschema.Schema, error) {
|
||||||
|
switch uri.String() {
|
||||||
|
case "https://showbridge.io/modules.schema.json":
|
||||||
|
return GetModulesSchema(), nil
|
||||||
|
case "https://showbridge.io/processors.schema.json":
|
||||||
|
return GetProcessorsSchema(), nil
|
||||||
|
case "https://showbridge.io/routes.schema.json":
|
||||||
|
return &RoutesConfigSchema, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown schema reference: %s", uri.String())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user