// am-gen generates states files and Grafana dashboards.
package main import ( _ ) const EnvGrafanaToken = "GRAFANA_TOKEN" func init() { // read .env _ = godotenv.Load() } func main() { := context.Background() := &cobra.Command{ Use: "am-gen", Long: strings.Trim(dedent.Dedent(` am-gen generates state files for asyncmachine-go state machines. Example: $ am-gen states-file --states State1,State2:multi \ --inherit basic,connected \ --groups Group1,Group2 \ --name MyMach Example: $ am-gen grafana --IDs MyMach1,MyMach2 \ --sync grafana-host.com `), "\n"), Run: func( *cobra.Command, []string) { := cli.ParseRootParams(, ) // print the version := cli.GetVersion() if .Version { fmt.Println() os.Exit(0) } }, } // states-file := &cobra.Command{ Use: "states-file --name MyMach --states State1,State2:multi", Run: genStatesFile(), } cli.AddStatesFlags() .AddCommand() // grafana := &cobra.Command{ Use: "grafana --name MyDash --ids my-mach-1,my-mach-2 --source my-service", Run: genGrafana(), } cli.AddGrafanaFlags() .AddCommand() := .Execute() if != nil { fmt.Println() os.Exit(1) } } func genGrafana( context.Context) func( *cobra.Command, []string) { return func( *cobra.Command, []string) { := cli.ParseGrafanaParams(, ) .Token = os.Getenv(EnvGrafanaToken) , := generator.GenDashboard() if != nil { fmt.Println() os.Exit(1) } if .GrafanaUrl != "" { := generator.SyncDashboard(, , ) if != nil { fmt.Println() os.Exit(1) } } else { fmt.Println(.MarshalIndentJSON()) } } } func genStatesFile( context.Context) func( *cobra.Command, []string, ) { return func( *cobra.Command, []string) { := cli.ParseSFParams(, ) := fmt.Sprintf("ss_%s.go", camelToSnake(.Name)) if !fileExists() || .Force { // generate , := generator.NewSchemaGenerator(, ) if != nil { panic() } // save ss_ := []byte(.Output()) = os.WriteFile(, , 0666) if != nil { panic() } fmt.Printf("Generated %s\n", ) // save utils = []byte(generator.GenUtilsFile()) = os.WriteFile("states_utils.go", , 0666) if != nil { panic() } fmt.Println("Generated states_utils.go") } else { fmt.Printf("Error: file %s already exists, delete it or use --force\n", ) os.Exit(1) } } } func camelToSnake( string) string { := regexp.MustCompile("([a-z0-9])([A-Z])") := .ReplaceAllString(, "${1}_${2}") return strings.ToLower() } func fileExists( string) bool { , := os.Stat() if errors.Is(, os.ErrNotExist) { return false } return !.IsDir() }