Skip to content

Commit

Permalink
✨ Add ortfodb schemas to get list of available json schemas, fix expo…
Browse files Browse the repository at this point in the history
…rter schema $id
  • Loading branch information
ewen-lbh committed Apr 14, 2024
1 parent 00cd565 commit 46a3a02
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 36 deletions.
34 changes: 26 additions & 8 deletions cmd/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,58 @@ package main

import (
"fmt"
"os"
"strings"

"github.com/MakeNowJust/heredoc"
"github.com/invopop/jsonschema"
ortfodb "github.com/ortfo/db"
"github.com/spf13/cobra"
)

var schemasCmd = &cobra.Command{
Use: "schemas <resource>",
Use: "schemas [resource]",
Short: "Output JSON schemas for ortfodb's various resources",
Long: heredoc.Doc(`
Don't pass any resource to get the list of available resources
Output the JSON schema for:
- configuration: the configuration file (.ortfodb.yaml)
- database: the output database file
- tags: the tags repository file (tags.yaml)
- technologies: the technologies repository file (technologies.yaml)
- exporter: the manifest file for an exporter
`),
ValidArgs: []string{"configuration", "database", "tags", "technologies"},
Args: cobra.ExactArgs(1),
ValidArgs: append(ortfodb.AvailableJSONSchemas, "list"),
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println(strings.Join(ortfodb.AvailableJSONSchemas, "\n"))
return
}
switch args[0] {
case "configuration":
fmt.Println(ortfodb.ConfigurationJSONSchema())
printSchema(ortfodb.ConfigurationJSONSchema())
case "database":
fmt.Println(ortfodb.DatabaseJSONSchema())
printSchema(ortfodb.DatabaseJSONSchema())
case "tags":
fmt.Println(ortfodb.TagsRepositoryJSONSchema())
printSchema(ortfodb.TagsRepositoryJSONSchema())
case "technologies":
fmt.Println(ortfodb.TechnologiesRepositoryJSONSchema())
printSchema(ortfodb.TechnologiesRepositoryJSONSchema())
case "exporter":
fmt.Println(ortfodb.ExporterManifestJSONSchema())
printSchema(ortfodb.ExporterManifestJSONSchema())
}
},
}

func init() {
rootCmd.AddCommand(schemasCmd)
}

func printSchema(schema *jsonschema.Schema) {
out, err := schema.MarshalJSON()
if err != nil {
panic(err)
}
os.Stdout.Write(out)
}
35 changes: 17 additions & 18 deletions jsonschema.go
Original file line number Diff line number Diff line change
@@ -1,59 +1,58 @@
package ortfodb

import (
"encoding/json"
"fmt"
"strings"

"github.com/invopop/jsonschema"
)

var AvailableJSONSchemas = []string{"configuration", "database", "tags", "technologies", "exporter"}

var yamlReflector = jsonschema.Reflector{
FieldNameTag: "yaml",
KeyNamer: func(key string) string { return strings.ToLower(key) },
}

func setSchemaId(schema *jsonschema.Schema) {
parts := strings.Split(string(schema.ID), "/")
base := parts[len(parts)-1]
schema.ID = jsonschema.ID(fmt.Sprintf("https://raw.githubusercontent.com/ortfo/db/v%s/schemas/%s.schema.json", Version, base))
func setSchemaId(schema *jsonschema.Schema, name string) {
schema.ID = jsonschema.ID(fmt.Sprintf("https://raw.githubusercontent.com/ortfo/db/v%s/schemas/%s.schema.json", Version, name))
}

func makeJSONSchema(t any, yaml bool) string {
func makeJSONSchema(t any, yaml bool) *jsonschema.Schema {
selectedReflector := jsonschema.Reflector{}
if yaml {
selectedReflector = yamlReflector
}
selectedReflector.AddGoComments("github.com/ortfo/db", "./")
schema := selectedReflector.Reflect(t)
setSchemaId(schema)
out, err := json.MarshalIndent(schema, "", " ")
if err != nil {
panic(err)
}
return string(out)
parts := strings.Split(string(schema.ID), "/")
base := parts[len(parts)-1]
setSchemaId(schema, base)
return schema
}

func ConfigurationJSONSchema() string {
func ConfigurationJSONSchema() *jsonschema.Schema {
return makeJSONSchema(&Configuration{}, true)
}

func DatabaseJSONSchema() string {
func DatabaseJSONSchema() *jsonschema.Schema {
return makeJSONSchema(&Database{}, false)
}

type tags []Tag

func TagsRepositoryJSONSchema() string {
func TagsRepositoryJSONSchema() *jsonschema.Schema {
return makeJSONSchema(&tags{}, true)
}

type technologies []Technology

func TechnologiesRepositoryJSONSchema() string {
func TechnologiesRepositoryJSONSchema() *jsonschema.Schema {
return makeJSONSchema(&technologies{}, true)
}

func ExporterManifestJSONSchema() string {
return makeJSONSchema(&ExporterManifest{}, true)
func ExporterManifestJSONSchema() *jsonschema.Schema {
schema := makeJSONSchema(&ExporterManifest{}, true)
setSchemaId(schema, "exporter")
return schema
}
4 changes: 2 additions & 2 deletions schemas/database.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,11 +262,11 @@
},
"autoplay": {
"type": "boolean",
"description": "Controlled with attribute character \u003e (adds)"
"description": "Controlled with attribute character > (adds)"
},
"muted": {
"type": "boolean",
"description": "Controlled with attribute character \u003e (adds)"
"description": "Controlled with attribute character > (adds)"
},
"playsinline": {
"type": "boolean",
Expand Down
2 changes: 1 addition & 1 deletion schemas/exporter.schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/ortfo/db/v1.1.0/schemas/exporter-manifest.schema.json",
"$id": "https://raw.githubusercontent.com/ortfo/db/v1.1.0/schemas/exporter.schema.json",
"$ref": "#/$defs/ExporterManifest",
"$defs": {
"ExporterCommand": {
Expand Down
17 changes: 12 additions & 5 deletions tools/generate_schemas.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
#!/usr/bin/env python
# Assuming ortfodb is available on PATH
import json
from pathlib import Path
from subprocess import run
from subprocess import run as _run

root = Path(__file__).parent.parent

for thing in ["tags", "technologies", "configuration", "database", "exporter"]:
out = run(["./ortfodb", "schemas", thing], capture_output=True)
schema = out.stdout.decode("utf-8")
(root / "schemas" / f"{thing}.schema.json").write_text(schema)

def run(cmd) -> str:
out = _run(cmd.split(" "), capture_output=True)
return out.stdout.decode("utf-8")


for thing in run("./ortfodb schemas").splitlines():
schema = run(f"./ortfodb schemas {thing.strip()}")
formatted_schema = json.dumps(json.loads(schema), indent=2)
(root / "schemas" / f"{thing}.schema.json").write_text(formatted_schema + "\n")
9 changes: 7 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"regexp"
"strings"

"github.com/invopop/jsonschema"
"github.com/xeipuuv/gojsonschema"
)

Expand Down Expand Up @@ -52,8 +53,12 @@ func writeFile(filename string, content []byte) error {
}

// validateWithJSONSchema checks if the JSON document document conforms to the JSON schema schema.
func validateWithJSONSchema(document string, schema string) (bool, []gojsonschema.ResultError, error) {
schemaLoader := gojsonschema.NewStringLoader(schema)
func validateWithJSONSchema(document string, schema *jsonschema.Schema) (bool, []gojsonschema.ResultError, error) {
schemaJson, err := schema.MarshalJSON()
if err != nil {
panic(err)
}
schemaLoader := gojsonschema.NewStringLoader(string(schemaJson))
documentLoader := gojsonschema.NewStringLoader(document)
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
Expand Down

0 comments on commit 46a3a02

Please sign in to comment.