A vibe coded tangled fork which supports pijul.
1package cloudflare
2
3import (
4 "context"
5 "fmt"
6 "io"
7 "strings"
8
9 cf "github.com/cloudflare/cloudflare-go/v6"
10 "github.com/cloudflare/cloudflare-go/v6/kv"
11 "github.com/cloudflare/cloudflare-go/v6/shared"
12)
13
14// KVPut writes or overwrites a single Workers KV entry.
15func (cl *Client) KVPut(ctx context.Context, key string, value []byte) error {
16 _, err := cl.kvAPI.KV.Namespaces.Values.Update(ctx, cl.kvNS, key, kv.NamespaceValueUpdateParams{
17 AccountID: cf.F(cl.cfAcct),
18 Value: cf.F[kv.NamespaceValueUpdateParamsValueUnion](shared.UnionString(value)),
19 })
20 if err != nil {
21 return fmt.Errorf("writing KV entry %q: %w", key, err)
22 }
23 return nil
24}
25
26// KVGet reads a single Workers KV entry. Returns nil, nil if the key does not exist.
27func (cl *Client) KVGet(ctx context.Context, key string) ([]byte, error) {
28 res, err := cl.kvAPI.KV.Namespaces.Values.Get(ctx, cl.kvNS, key, kv.NamespaceValueGetParams{
29 AccountID: cf.F(cl.cfAcct),
30 })
31 if err != nil {
32 // The CF SDK returns a 404 when the key doesn't exist. The error type
33 // lives in an internal package so we match on the error string instead.
34 if strings.Contains(err.Error(), "404") && strings.Contains(err.Error(), "key not found") {
35 return nil, nil
36 }
37 return nil, fmt.Errorf("reading KV entry %q: %w", key, err)
38 }
39 defer res.Body.Close()
40 val, err := io.ReadAll(res.Body)
41 if err != nil {
42 return nil, fmt.Errorf("reading KV entry body %q: %w", key, err)
43 }
44 return val, nil
45}
46
47// KVDelete removes a single Workers KV entry.
48// Safe to call even if the entry does not exist.
49func (cl *Client) KVDelete(ctx context.Context, key string) error {
50 _, err := cl.kvAPI.KV.Namespaces.Values.Delete(ctx, cl.kvNS, key, kv.NamespaceValueDeleteParams{
51 AccountID: cf.F(cl.cfAcct),
52 })
53 if err != nil {
54 return fmt.Errorf("deleting KV entry %q: %w", key, err)
55 }
56 return nil
57}
58
59// KVDeleteByPrefix removes every Workers KV entry whose key starts with prefix,
60// handling pagination automatically.
61func (cl *Client) KVDeleteByPrefix(ctx context.Context, prefix string) error {
62 iter := cl.kvAPI.KV.Namespaces.Keys.ListAutoPaging(ctx, cl.kvNS, kv.NamespaceKeyListParams{
63 AccountID: cf.F(cl.cfAcct),
64 Prefix: cf.F(prefix),
65 })
66
67 for iter.Next() {
68 entry := iter.Current()
69 if _, err := cl.kvAPI.KV.Namespaces.Values.Delete(ctx, cl.kvNS, entry.Name, kv.NamespaceValueDeleteParams{
70 AccountID: cf.F(cl.cfAcct),
71 }); err != nil {
72 return fmt.Errorf("deleting KV entry %q: %w", entry.Name, err)
73 }
74 }
75 if err := iter.Err(); err != nil {
76 return fmt.Errorf("listing KV entries with prefix %q: %w", prefix, err)
77 }
78
79 return nil
80}