A vibe coded tangled fork which supports pijul.
1package cloudflare
2
3import (
4 "fmt"
5
6 cf "github.com/cloudflare/cloudflare-go/v6"
7 "github.com/cloudflare/cloudflare-go/v6/option"
8
9 "github.com/aws/aws-sdk-go-v2/aws"
10 "github.com/aws/aws-sdk-go-v2/credentials"
11 "github.com/aws/aws-sdk-go-v2/service/s3"
12
13 "tangled.org/core/appview/config"
14)
15
16// Client holds all cloudflare service clients used by the appview.
17type Client struct {
18 api *cf.Client // scoped to DNS / zone operations
19 kvAPI *cf.Client // scoped to Workers KV (separate token)
20 s3 *s3.Client
21 zone string
22 kvNS string
23 bucket string
24 cfAcct string
25}
26
27func New(c *config.Config) (*Client, error) {
28 api := cf.NewClient(option.WithAPIToken(c.Cloudflare.ApiToken))
29
30 kvAPI := cf.NewClient(option.WithAPIToken(c.Cloudflare.KV.ApiToken))
31
32 // R2 endpoint is S3-compatible, keyed by account id.
33 r2Endpoint := fmt.Sprintf("https://%s.r2.cloudflarestorage.com", c.Cloudflare.AccountId)
34
35 s3Client := s3.New(s3.Options{
36 BaseEndpoint: aws.String(r2Endpoint),
37 Region: "auto",
38 Credentials: credentials.NewStaticCredentialsProvider(
39 c.Cloudflare.R2.AccessKeyID,
40 c.Cloudflare.R2.SecretAccessKey,
41 "",
42 ),
43 UsePathStyle: true,
44 })
45
46 return &Client{
47 api: api,
48 kvAPI: kvAPI,
49 s3: s3Client,
50 zone: c.Cloudflare.ZoneId,
51 kvNS: c.Cloudflare.KV.NamespaceId,
52 bucket: c.Cloudflare.R2.Bucket,
53 cfAcct: c.Cloudflare.AccountId,
54 }, nil
55}
56
57// Enabled returns true when the client has enough config to perform site
58// operations. Callers should check this before attempting any CF operations
59// so the appview degrades gracefully in dev environments without credentials.
60func (cl *Client) Enabled() bool {
61 return cl != nil &&
62 cl.cfAcct != "" &&
63 cl.kvNS != "" &&
64 cl.bucket != ""
65}