package cmd import ( "context" "fmt" "io" "log/slog" "os" "slices" "strings" "git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces" "git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces/params" "git.bissendorf.co/bissendorf/unifood/m/v2/core/output" "git.bissendorf.co/bissendorf/unifood/m/v2/core/services/jlog" "github.com/spf13/cobra" ) type VerbItem struct { Name interfaces.Verb Aliases []string Description string RunFn func(ctx context.Context, config AppConfig, handler interfaces.ResourceHandler, params params.Container) error } var verbs = []VerbItem{ { Name: interfaces.VerbGet, Description: "Retrieve resource information", RunFn: func(ctx context.Context, config AppConfig, handler interfaces.ResourceHandler, params params.Container) error { h, ok := handler.(interfaces.GetHandler) if !ok { return fmt.Errorf("resource does not support GET") } // Get item item, err := h.Get(ctx, params) if err != nil { return fmt.Errorf("retrieving item failed: %w", err) } formatterName := strings.ToLower(config.OutputMode) formatter, exists := output.Formatters[formatterName] if !exists { return fmt.Errorf("could not find output formatter '%s'", formatterName) } // Format and output formatted, err := formatter.Format(item) if err != nil { return fmt.Errorf("failed to format output: %w", err) } _, err = io.Copy(os.Stdout, formatted) if err != nil { return fmt.Errorf("failed to write output: %w", err) } return nil }, }, } func getVerbs(ctx context.Context, config AppConfig) (commands []*cobra.Command) { logger := jlog.FromContext(ctx) for _, v := range verbs { verbCommand := &cobra.Command{ Use: strings.ToLower(string(v.Name)), Aliases: v.Aliases, Short: v.Description, } // Add all resources that can handle this verb for _, r := range availableResources { if !slices.Contains(r.Verbs, v.Name) { continue } var params params.Container resourceCommand := &cobra.Command{ Use: r.Name, Aliases: r.Aliases, Short: r.Description, Run: func(cmd *cobra.Command, args []string) { logger := jlog.New(slog.LevelInfo) ctx := jlog.ContextWith(context.Background(), logger) err := v.RunFn(ctx, config, r.Handler, params) if err != nil { logger.ErrorContext(ctx, fmt.Sprintf("%s %s failed", strings.ToUpper(string(v.Name)), r.Name), "error", err.Error()) os.Exit(1) } }, } // Register parameters for _, param := range r.Handler.GetParametersForVerb(v.Name) { resourceCommand.Flags().StringVarP( params.Register(param.Name, param.ParseFunc), param.Name, param.ShortHand, param.DefaultFunc(), param.Description, ) } verbCommand.AddCommand(resourceCommand) logger.Debug(fmt.Sprintf("Registered %s %s", strings.ToUpper(string(v.Name)), r.Name)) } commands = append(commands, verbCommand) } return }