all repos — postern

@ 50dc541db37adabbbb220f4abf62aba899c48f5d

Modern mail management

clone
git clone https:///postern.git

internal/cli/kv.go (view raw)

  1package cli
  2
  3import (
  4	"context"
  5	"database/sql"
  6	"errors"
  7	"fmt"
  8	"text/tabwriter"
  9
 10	"postern/internal/model"
 11
 12	"github.com/spf13/cobra"
 13)
 14
 15// KVList returns all stored key-value pairs.
 16func (c *Command) KVList(ctx context.Context) (map[string]any, error) {
 17	pairs, err := c.db.KVList(ctx)
 18	if err != nil {
 19		return nil, err
 20	}
 21	for key, value := range pairs {
 22		pairs[key] = normalizeKVValue(value)
 23	}
 24	return pairs, nil
 25}
 26
 27// KVGet returns the value stored under key.
 28func (c *Command) KVGet(ctx context.Context, key string) (any, error) {
 29	val, err := c.db.KVGet(ctx, key)
 30	if err != nil {
 31		if errors.Is(err, sql.ErrNoRows) {
 32			return nil, fmt.Errorf("%w: key %q", model.ErrNotFound, key)
 33		}
 34		return nil, err
 35	}
 36	return normalizeKVValue(val), nil
 37}
 38
 39// KVPop removes the value stored under key and returns it.
 40func (c *Command) KVPop(ctx context.Context, key string) (any, error) {
 41	val, err := c.db.KVPop(ctx, key)
 42	if err != nil {
 43		if errors.Is(err, sql.ErrNoRows) {
 44			return nil, fmt.Errorf("%w: key %q", model.ErrNotFound, key)
 45		}
 46		return nil, err
 47	}
 48	return normalizeKVValue(val), nil
 49}
 50
 51// normalizeKVValue converts []byte values to string so they are not
 52// base64-encoded when serialized to JSON and print cleanly.
 53func normalizeKVValue(v any) any {
 54	if b, ok := v.([]byte); ok {
 55		return string(b)
 56	}
 57	return v
 58}
 59
 60// kvFormat renders a stored value for display, converting []byte to string.
 61func kvFormat(v any) string {
 62	if b, ok := v.([]byte); ok {
 63		return string(b)
 64	}
 65	return fmt.Sprint(v)
 66}
 67
 68func (c *Command) kvList(cmd *cobra.Command, _ []string) error {
 69	cmd.SilenceUsage = true
 70	ctx := cmd.Context()
 71
 72	pairs, err := c.clientKVList(ctx)
 73	if err != nil {
 74		_, _ = fmt.Fprintln(cmd.OutOrStdout(), "Error listing keys")
 75		return err
 76	}
 77
 78	if len(pairs) == 0 {
 79		_, _ = fmt.Fprintln(cmd.OutOrStdout(), "No keys found")
 80		return nil
 81	}
 82
 83	w := tabwriter.NewWriter(cmd.OutOrStdout(), 1, 1, 1, ' ', 0)
 84	_, _ = fmt.Fprintln(w, "Key\tValue")
 85	for key, value := range pairs {
 86		_, _ = fmt.Fprintf(w, "%s\t%s\n", key, kvFormat(value))
 87	}
 88	_ = w.Flush()
 89
 90	return nil
 91}
 92
 93func (c *Command) kvGet(cmd *cobra.Command, args []string) error {
 94	cmd.SilenceUsage = true
 95	ctx := cmd.Context()
 96	key := args[0]
 97
 98	val, err := c.clientKVGet(ctx, key)
 99	if err != nil {
100		return err
101	}
102
103	_, _ = fmt.Fprintln(cmd.OutOrStdout(), kvFormat(val))
104	return nil
105}
106
107func (c *Command) kvPop(cmd *cobra.Command, args []string) error {
108	cmd.SilenceUsage = true
109	ctx := cmd.Context()
110	key := args[0]
111
112	val, err := c.clientKVPop(ctx, key)
113	if err != nil {
114		return err
115	}
116
117	_, _ = fmt.Fprintln(cmd.OutOrStdout(), kvFormat(val))
118	return nil
119}