lemonsqueezy.*Client.do   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 15
nop 4
dl 0
loc 24
rs 8.6666
c 0
b 0
f 0
1
package lemonsqueezy
2
3
import (
4
	"bytes"
5
	"context"
6
	"encoding/json"
7
	"io"
8
	"net/http"
9
)
10
11
type service struct {
12
	client *Client
13
}
14
15
// Client is the lemonsqueezy API client.
16
// Do not instantiate this client with Client{}. Use the New method instead.
17
type Client struct {
18
	httpClient    *http.Client
19
	common        service
20
	baseURL       string
21
	apiKey        string
22
	signingSecret string
23
24
	Webhooks             *WebhooksService
25
	Subscriptions        *SubscriptionsService
26
	Users                *UsersService
27
	Stores               *StoresService
28
	Customers            *CustomersService
29
	Products             *ProductsService
30
	Variants             *VariantsService
31
	Files                *FilesService
32
	Orders               *OrdersService
33
	OrderItems           *OrderItemsService
34
	SubscriptionInvoices *SubscriptionInvoicesService
35
	SubscriptionItems    *SubscriptionItemsService
36
	DiscountRedemptions  *DiscountRedemptionsService
37
	Discounts            *DiscountsService
38
	Checkouts            *CheckoutsService
39
	LicenseKeys          *LicenseKeysService
40
	LicenseKeyInstances  *LicenseKeyInstancesService
41
	Licenses             *LicensesService
42
	Prices               *PricesService
43
}
44
45
// New creates and returns a new Client from a slice of Option.
46
func New(options ...Option) *Client {
47
	config := defaultClientConfig()
48
49
	for _, option := range options {
50
		option.apply(config)
51
	}
52
53
	client := &Client{
54
		httpClient:    config.httpClient,
55
		apiKey:        config.apiKey,
56
		signingSecret: config.signingSecret,
57
		baseURL:       config.baseURL,
58
	}
59
60
	client.common.client = client
61
	client.Subscriptions = (*SubscriptionsService)(&client.common)
62
	client.Webhooks = (*WebhooksService)(&client.common)
63
	client.Users = (*UsersService)(&client.common)
64
	client.Stores = (*StoresService)(&client.common)
65
	client.Customers = (*CustomersService)(&client.common)
66
	client.Products = (*ProductsService)(&client.common)
67
	client.Variants = (*VariantsService)(&client.common)
68
	client.Files = (*FilesService)(&client.common)
69
	client.Orders = (*OrdersService)(&client.common)
70
	client.OrderItems = (*OrderItemsService)(&client.common)
71
	client.SubscriptionInvoices = (*SubscriptionInvoicesService)(&client.common)
72
	client.SubscriptionItems = (*SubscriptionItemsService)(&client.common)
73
	client.DiscountRedemptions = (*DiscountRedemptionsService)(&client.common)
74
	client.Discounts = (*DiscountsService)(&client.common)
75
	client.Checkouts = (*CheckoutsService)(&client.common)
76
	client.LicenseKeys = (*LicenseKeysService)(&client.common)
77
	client.LicenseKeyInstances = (*LicenseKeyInstancesService)(&client.common)
78
	client.Licenses = (*LicensesService)(&client.common)
79
	client.Prices = (*PricesService)(&client.common)
80
81
	return client
82
}
83
84
// newRequest creates an API request. A relative URL can be provided in uri,
85
// in which case it is resolved relative to the BaseURL of the Client.
86
// URI's should always be specified without a preceding slash.
87
func (client *Client) newRequest(ctx context.Context, method, uri string, body ...any) (*http.Request, error) {
88
	var buffer io.ReadWriter
89
	if len(body) > 0 {
90
		buffer = &bytes.Buffer{}
91
		enc := json.NewEncoder(buffer)
92
		enc.SetEscapeHTML(false)
93
		err := enc.Encode(body[0])
94
		if err != nil {
95
			return nil, err
96
		}
97
	}
98
99
	req, err := http.NewRequestWithContext(ctx, method, client.baseURL+uri, buffer)
100
	if err != nil {
101
		return nil, err
102
	}
103
104
	req.Header.Set("Authorization", "Bearer "+client.apiKey)
105
	req.Header.Set("Content-Type", "application/vnd.api+json")
106
	req.Header.Set("Accept", "application/vnd.api+json")
107
108
	return req, nil
109
}
110
111
// do carries out an HTTP request and returns a Response
112
func (client *Client) do(ctx context.Context, method, uri string, body ...any) (*Response, error) {
113
	request, err := client.newRequest(ctx, method, uri, body...)
114
	if err != nil {
115
		return nil, err
116
	}
117
118
	httpResponse, err := client.httpClient.Do(request)
119
	if err != nil {
120
		return nil, err
121
	}
122
123
	defer func() { _ = httpResponse.Body.Close() }()
124
125
	resp, err := client.newResponse(httpResponse)
126
	if err != nil {
127
		return resp, err
128
	}
129
130
	_, err = io.Copy(io.Discard, httpResponse.Body)
131
	if err != nil {
132
		return resp, err
133
	}
134
135
	return resp, nil
136
}
137
138
// newResponse converts an *http.Response to *Response
139
func (client *Client) newResponse(httpResponse *http.Response) (*Response, error) {
140
	resp := new(Response)
141
	resp.HTTPResponse = httpResponse
142
143
	buf, err := io.ReadAll(resp.HTTPResponse.Body)
144
	if err != nil {
145
		return nil, err
146
	}
147
	resp.Body = &buf
148
149
	return resp, resp.Error()
150
}
151