Passed
Pull Request — master (#2607)
by Tolga
04:04
created

pkg/cmd/ast.go   A

Size/Duplication

Total Lines 91
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 51
dl 0
loc 91
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
C cmd.runGenerateAst 0 51 9
A cmd.NewGenerateAstCommand 0 16 2
1
package cmd
2
3
import (
4
	"bytes"
5
	"encoding/json"
6
	"fmt"
7
	"net/url"
8
9
	"github.com/spf13/cobra"
10
	"github.com/spf13/viper"
11
	"google.golang.org/protobuf/encoding/protojson"
12
13
	"github.com/Permify/permify/internal/schema"
14
	"github.com/Permify/permify/pkg/cmd/flags"
15
	"github.com/Permify/permify/pkg/development/file"
16
)
17
18
// NewGenerateASTCommand creates a new cobra.Command to generate the Abstract Syntax Tree (AST) from a given file.
19
// The command expects exactly one argument, which is the URL or path to the file.
20
// It also allows for flags registration for further validation (like coverage flags).
21
func NewGenerateAstCommand() *cobra.Command {
22
	command := &cobra.Command{
23
		Use:   "ast <file>",
24
		Short: "Generates the AST from a specified file and prints it as JSON.",
25
		RunE:  runGenerateAst(),
26
		Args:  cobra.ExactArgs(1),
27
	}
28
29
	f := command.Flags()
30
	f.Bool("pretty", false, "If set to true, produces a human-readable output of the AST.")
31
32
	command.PreRun = func(cmd *cobra.Command, args []string) {
33
		flags.RegisterAstFlags(f)
34
	}
35
36
	return command
37
}
38
39
// runGenerateAST creates a closure that generates the AST and returns its JSON representation.
40
// Depending on the "pretty" flag, the output can be either pretty-printed or raw.
41
func runGenerateAst() func(cmd *cobra.Command, args []string) error {
42
	return func(cmd *cobra.Command, args []string) error {
43
		// Fetch the value of the "pretty" flag.
44
		pretty := viper.GetBool("pretty")
45
46
		// Parse the provided URL.
47
		u, err := url.Parse(args[0])
48
		if err != nil {
49
			return err
50
		}
51
52
		// Initialize a decoder for the provided URL.
53
		decoder, err := file.NewDecoderFromURL(u)
54
		if err != nil {
55
			return err
56
		}
57
58
		// Initialize an empty shape to store the decoded schema.
59
		s := &file.Shape{}
60
61
		// Decode the content from the URL into the shape.
62
		err = decoder.Decode(s)
63
		if err != nil {
64
			return err
65
		}
66
67
		// Convert the string definitions in the shape to a structured schema.
68
		def, err := schema.NewSchemaFromStringDefinitions(true, s.Schema)
69
		if err != nil {
70
			return err
71
		}
72
73
		// Serialize the schema definition into JSON.
74
		jsonData, err := protojson.Marshal(def)
75
		if err != nil {
76
			return err
77
		}
78
79
		// Print the JSON, either prettified or raw based on the "pretty" flag.
80
		if pretty {
81
			var prettyJSON bytes.Buffer
82
			err = json.Indent(&prettyJSON, jsonData, "", "  ")
83
			if err != nil {
84
				return err
85
			}
86
			fmt.Println(prettyJSON.String())
87
		} else {
88
			fmt.Println(string(jsonData))
89
		}
90
91
		return nil
92
	}
93
}
94