package cli import ( "context" "database/sql" "errors" "fmt" "text/tabwriter" "postern/internal/model" "github.com/spf13/cobra" ) // KVList returns all stored key-value pairs. func (c *Command) KVList(ctx context.Context) (map[string]any, error) { pairs, err := c.db.KVList(ctx) if err != nil { return nil, err } for key, value := range pairs { pairs[key] = normalizeKVValue(value) } return pairs, nil } // KVGet returns the value stored under key. func (c *Command) KVGet(ctx context.Context, key string) (any, error) { val, err := c.db.KVGet(ctx, key) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, fmt.Errorf("%w: key %q", model.ErrNotFound, key) } return nil, err } return normalizeKVValue(val), nil } // KVPop removes the value stored under key and returns it. func (c *Command) KVPop(ctx context.Context, key string) (any, error) { val, err := c.db.KVPop(ctx, key) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, fmt.Errorf("%w: key %q", model.ErrNotFound, key) } return nil, err } return normalizeKVValue(val), nil } // normalizeKVValue converts []byte values to string so they are not // base64-encoded when serialized to JSON and print cleanly. func normalizeKVValue(v any) any { if b, ok := v.([]byte); ok { return string(b) } return v } // kvFormat renders a stored value for display, converting []byte to string. func kvFormat(v any) string { if b, ok := v.([]byte); ok { return string(b) } return fmt.Sprint(v) } func (c *Command) kvList(cmd *cobra.Command, _ []string) error { cmd.SilenceUsage = true ctx := cmd.Context() pairs, err := c.clientKVList(ctx) if err != nil { _, _ = fmt.Fprintln(cmd.OutOrStdout(), "Error listing keys") return err } if len(pairs) == 0 { _, _ = fmt.Fprintln(cmd.OutOrStdout(), "No keys found") return nil } w := tabwriter.NewWriter(cmd.OutOrStdout(), 1, 1, 1, ' ', 0) _, _ = fmt.Fprintln(w, "Key\tValue") for key, value := range pairs { _, _ = fmt.Fprintf(w, "%s\t%s\n", key, kvFormat(value)) } _ = w.Flush() return nil } func (c *Command) kvGet(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true ctx := cmd.Context() key := args[0] val, err := c.clientKVGet(ctx, key) if err != nil { return err } _, _ = fmt.Fprintln(cmd.OutOrStdout(), kvFormat(val)) return nil } func (c *Command) kvPop(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true ctx := cmd.Context() key := args[0] val, err := c.clientKVPop(ctx, key) if err != nil { return err } _, _ = fmt.Fprintln(cmd.OutOrStdout(), kvFormat(val)) return nil }