Passed
Push — main ( b6acc3...d081c0 )
by Acho
01:28
created

lemonsqueezy.*Client.do   B

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
	DiscountRedemptions  *DiscountRedemptionsService
36
	Discounts            *DiscountsService
37
	Checkouts            *CheckoutsService
38
	LicenseKeys          *LicenseKeysService
39
	LicenseKeyInstances  *LicenseKeyInstancesService
40
}
41
42
// New creates and returns a new Client from a slice of Option.
43
func New(options ...Option) *Client {
44
	config := defaultClientConfig()
45
46
	for _, option := range options {
47
		option.apply(config)
48
	}
49
50
	client := &Client{
51
		httpClient:    config.httpClient,
52
		apiKey:        config.apiKey,
53
		signingSecret: config.signingSecret,
54
		baseURL:       config.baseURL,
55
	}
56
57
	client.common.client = client
58
	client.Subscriptions = (*SubscriptionsService)(&client.common)
59
	client.Webhooks = (*WebhooksService)(&client.common)
60
	client.Users = (*UsersService)(&client.common)
61
	client.Stores = (*StoresService)(&client.common)
62
	client.Customers = (*CustomersService)(&client.common)
63
	client.Products = (*ProductsService)(&client.common)
64
	client.Variants = (*VariantsService)(&client.common)
65
	client.Files = (*FilesService)(&client.common)
66
	client.Orders = (*OrdersService)(&client.common)
67
	client.OrderItems = (*OrderItemsService)(&client.common)
68
	client.SubscriptionInvoices = (*SubscriptionInvoicesService)(&client.common)
69
	client.DiscountRedemptions = (*DiscountRedemptionsService)(&client.common)
70
	client.Discounts = (*DiscountsService)(&client.common)
71
	client.Checkouts = (*CheckoutsService)(&client.common)
72
	client.LicenseKeys = (*LicenseKeysService)(&client.common)
73
	client.LicenseKeyInstances = (*LicenseKeyInstancesService)(&client.common)
74
75
	return client
76
}
77
78
// newRequest creates an API request. A relative URL can be provided in uri,
79
// in which case it is resolved relative to the BaseURL of the Client.
80
// URI's should always be specified without a preceding slash.
81
func (client *Client) newRequest(ctx context.Context, method, uri string, body ...any) (*http.Request, error) {
82
	var buffer io.ReadWriter
83
	if len(body) > 0 {
84
		buffer = &bytes.Buffer{}
85
		enc := json.NewEncoder(buffer)
86
		enc.SetEscapeHTML(false)
87
		err := enc.Encode(body[0])
88
		if err != nil {
89
			return nil, err
90
		}
91
	}
92
93
	req, err := http.NewRequestWithContext(ctx, method, client.baseURL+uri, buffer)
94
	if err != nil {
95
		return nil, err
96
	}
97
98
	req.Header.Set("Authorization", "Bearer "+client.apiKey)
99
	req.Header.Set("Content-Type", "application/vnd.api+json")
100
	req.Header.Set("Accept", "application/vnd.api+json")
101
102
	return req, nil
103
}
104
105
// do carries out an HTTP request and returns a Response
106
func (client *Client) do(ctx context.Context, method, uri string, body ...any) (*Response, error) {
107
	request, err := client.newRequest(ctx, method, uri, body...)
108
	if err != nil {
109
		return nil, err
110
	}
111
112
	httpResponse, err := client.httpClient.Do(request)
113
	if err != nil {
114
		return nil, err
115
	}
116
117
	defer func() { _ = httpResponse.Body.Close() }()
118
119
	resp, err := client.newResponse(httpResponse)
120
	if err != nil {
121
		return resp, err
122
	}
123
124
	_, err = io.Copy(io.Discard, httpResponse.Body)
125
	if err != nil {
126
		return resp, err
127
	}
128
129
	return resp, nil
130
}
131
132
// newResponse converts an *http.Response to *Response
133
func (client *Client) newResponse(httpResponse *http.Response) (*Response, error) {
134
	resp := new(Response)
135
	resp.HTTPResponse = httpResponse
136
137
	buf, err := io.ReadAll(resp.HTTPResponse.Body)
138
	if err != nil {
139
		return nil, err
140
	}
141
	resp.Body = &buf
142
143
	return resp, resp.Error()
144
}
145