diff --git a/cmd/obp/cmd/root.go b/cmd/obp/cmd/root.go index 549ab1e..770e98e 100644 --- a/cmd/obp/cmd/root.go +++ b/cmd/obp/cmd/root.go @@ -16,9 +16,10 @@ var cfgFile string // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ - Use: "obp", - Short: "obp is a toolkit for managing your vault in headless contexts", - Long: `a suite of tools for managing your obsidian vault`, + TraverseChildren: true, + Use: "obp", + Short: "obp is a toolkit for managing your vault in headless contexts", + Long: `a suite of tools for managing your obsidian vault`, PreRunE: func(cmd *cobra.Command, args []string) error { // here is where I validate arguments, open and parse config files, etc return nil diff --git a/cmd/obp/cmd/validate.go b/cmd/obp/cmd/validate.go index 31e426d..e2cf52f 100644 --- a/cmd/obp/cmd/validate.go +++ b/cmd/obp/cmd/validate.go @@ -4,26 +4,81 @@ Copyright © 2023 NAME HERE package cmd import ( + "bytes" + "fmt" + "io" + "log" + "os" + "strings" + + "github.com/santhosh-tekuri/jsonschema/v5" "github.com/spf13/cobra" + "gopkg.in/yaml.v3" ) // rootCmd represents the base command when called without any subcommands var validateCmd = &cobra.Command{ Use: "validate", Short: "loads a note and ensures its frontmatter follows the provided protobuf schema", - Long: `parses frontmatter in a markdown note and attempts to write the struct out using the provided protobuf schema. - -If the write succeeds, the data satisfies the schema. + Long: `Validate YAML frontmatter with jsonschema `, // Uncomment the following line if your bare application // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + PreRunE: func(cmd *cobra.Command, args []string) error { + schemaFilename := cmd.Flag("schema").Value.String() + if len(schemaFilename) == 0 { + return fmt.Errorf("Please profide a schema filename") + } + target := cmd.Flag("target").Value.String() + if len(target) == 0 { + return fmt.Errorf("Please profide a target filename") + } + return nil + }, + Run: func(cmd *cobra.Command, args []string) { + var m interface{} + var schemaBytes bytes.Buffer + + schemaFilename := cmd.Flag("schema").Value.String() + schemaFile, err := os.Open(schemaFilename) + if err != nil { + log.Fatalf("could not open schema file: %s\n", err) + } + io.Copy(&schemaBytes, schemaFile) + + // err := yaml.Unmarshal([]byte(yamlText), &m) + targetFilename := cmd.Flag("target").Value.String() + target, err := os.Open(targetFilename) + if err != nil { + log.Fatalf("could not open target file: %s\n", err) + } + dec := yaml.NewDecoder(target) + err = dec.Decode(&m) + if err != nil { + log.Fatalf("error decoding YAML: %s\n", err) + } + + compiler := jsonschema.NewCompiler() + if err := compiler.AddResource(schemaFilename, strings.NewReader(schemaBytes.String())); err != nil { + log.Fatalf("error adding resource to jsonschema compiler: %s\n", err) + } + + schema, err := compiler.Compile("schema.json") + if err != nil { + log.Fatalf("error compiling schema: %s\n", err) + } + if err := schema.Validate(m); err != nil { + log.Fatalf("error validating: %s\n", err) + } + fmt.Println("validation successfull") + }, } func init() { // Cobra also supports local flags, which will only run // when this action is called directly. // rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - validateCmd.Flags().StringP("schema", "s", "schema.proto", "path to protobuf file") + validateCmd.Flags().StringP("schema", "s", "base.schema", "path to protobuf file") + validateCmd.Flags().StringP("target", "t", "", "list of filenames to validate") rootCmd.AddCommand(validateCmd) }