this repo has no description
1package knotclient
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "io"
8 "log"
9 "net/http"
10 "net/url"
11 "strconv"
12 "time"
13
14 "tangled.sh/tangled.sh/core/types"
15)
16
17type UnsignedClient struct {
18 Url *url.URL
19 client *http.Client
20}
21
22func NewUnsignedClient(domain string, dev bool) (*UnsignedClient, error) {
23 client := &http.Client{
24 Timeout: 5 * time.Second,
25 }
26
27 scheme := "https"
28 if dev {
29 scheme = "http"
30 }
31 url, err := url.Parse(fmt.Sprintf("%s://%s", scheme, domain))
32 if err != nil {
33 return nil, err
34 }
35
36 unsignedClient := &UnsignedClient{
37 client: client,
38 Url: url,
39 }
40
41 return unsignedClient, nil
42}
43
44func (us *UnsignedClient) newRequest(method, endpoint string, query url.Values, body []byte) (*http.Request, error) {
45 reqUrl := us.Url.JoinPath(endpoint)
46
47 // add query parameters
48 if query != nil {
49 reqUrl.RawQuery = query.Encode()
50 }
51
52 return http.NewRequest(method, reqUrl.String(), bytes.NewReader(body))
53}
54
55func (us *UnsignedClient) Index(ownerDid, repoName, ref string) (*http.Response, error) {
56 const (
57 Method = "GET"
58 )
59
60 endpoint := fmt.Sprintf("/%s/%s/tree/%s", ownerDid, repoName, ref)
61 if ref == "" {
62 endpoint = fmt.Sprintf("/%s/%s", ownerDid, repoName)
63 }
64
65 req, err := us.newRequest(Method, endpoint, nil, nil)
66 if err != nil {
67 return nil, err
68 }
69
70 return us.client.Do(req)
71}
72
73func (us *UnsignedClient) Log(ownerDid, repoName, ref string, page int) (*http.Response, error) {
74 const (
75 Method = "GET"
76 )
77
78 endpoint := fmt.Sprintf("/%s/%s/log/%s", ownerDid, repoName, url.PathEscape(ref))
79
80 query := url.Values{}
81 query.Add("page", strconv.Itoa(page))
82 query.Add("per_page", strconv.Itoa(60))
83
84 req, err := us.newRequest(Method, endpoint, query, nil)
85 if err != nil {
86 return nil, err
87 }
88
89 return us.client.Do(req)
90}
91
92func (us *UnsignedClient) Branches(ownerDid, repoName string) (*http.Response, error) {
93 const (
94 Method = "GET"
95 )
96
97 endpoint := fmt.Sprintf("/%s/%s/branches", ownerDid, repoName)
98
99 req, err := us.newRequest(Method, endpoint, nil, nil)
100 if err != nil {
101 return nil, err
102 }
103
104 return us.client.Do(req)
105}
106
107func (us *UnsignedClient) Tags(ownerDid, repoName string) (*types.RepoTagsResponse, error) {
108 const (
109 Method = "GET"
110 )
111
112 endpoint := fmt.Sprintf("/%s/%s/tags", ownerDid, repoName)
113
114 req, err := us.newRequest(Method, endpoint, nil, nil)
115 if err != nil {
116 return nil, err
117 }
118
119 resp, err := us.client.Do(req)
120 if err != nil {
121 return nil, err
122 }
123
124 body, err := io.ReadAll(resp.Body)
125 if err != nil {
126 return nil, err
127 }
128
129 var result types.RepoTagsResponse
130 err = json.Unmarshal(body, &result)
131 if err != nil {
132 return nil, err
133 }
134
135 return &result, nil
136}
137
138func (us *UnsignedClient) Branch(ownerDid, repoName, branch string) (*http.Response, error) {
139 const (
140 Method = "GET"
141 )
142
143 endpoint := fmt.Sprintf("/%s/%s/branches/%s", ownerDid, repoName, url.PathEscape(branch))
144
145 req, err := us.newRequest(Method, endpoint, nil, nil)
146 if err != nil {
147 return nil, err
148 }
149
150 return us.client.Do(req)
151}
152
153func (us *UnsignedClient) DefaultBranch(ownerDid, repoName string) (*types.RepoDefaultBranchResponse, error) {
154 const (
155 Method = "GET"
156 )
157
158 endpoint := fmt.Sprintf("/%s/%s/branches/default", ownerDid, repoName)
159
160 req, err := us.newRequest(Method, endpoint, nil, nil)
161 if err != nil {
162 return nil, err
163 }
164
165 resp, err := us.client.Do(req)
166 if err != nil {
167 return nil, err
168 }
169 defer resp.Body.Close()
170
171 var defaultBranch types.RepoDefaultBranchResponse
172 if err := json.NewDecoder(resp.Body).Decode(&defaultBranch); err != nil {
173 return nil, err
174 }
175
176 return &defaultBranch, nil
177}
178
179func (us *UnsignedClient) Capabilities() (*types.Capabilities, error) {
180 const (
181 Method = "GET"
182 Endpoint = "/capabilities"
183 )
184
185 req, err := us.newRequest(Method, Endpoint, nil, nil)
186 if err != nil {
187 return nil, err
188 }
189
190 resp, err := us.client.Do(req)
191 if err != nil {
192 return nil, err
193 }
194 defer resp.Body.Close()
195
196 var capabilities types.Capabilities
197 if err := json.NewDecoder(resp.Body).Decode(&capabilities); err != nil {
198 return nil, err
199 }
200
201 return &capabilities, nil
202}
203
204func (us *UnsignedClient) Compare(ownerDid, repoName, rev1, rev2 string) (*types.RepoFormatPatchResponse, error) {
205 const (
206 Method = "GET"
207 )
208
209 endpoint := fmt.Sprintf("/%s/%s/compare/%s/%s", ownerDid, repoName, url.PathEscape(rev1), url.PathEscape(rev2))
210
211 req, err := us.newRequest(Method, endpoint, nil, nil)
212 if err != nil {
213 return nil, fmt.Errorf("Failed to create request.")
214 }
215
216 compareResp, err := us.client.Do(req)
217 if err != nil {
218 return nil, fmt.Errorf("Failed to create request.")
219 }
220 defer compareResp.Body.Close()
221
222 switch compareResp.StatusCode {
223 case 404:
224 case 400:
225 return nil, fmt.Errorf("Branch comparisons not supported on this knot.")
226 }
227
228 respBody, err := io.ReadAll(compareResp.Body)
229 if err != nil {
230 log.Println("failed to compare across branches")
231 return nil, fmt.Errorf("Failed to compare branches.")
232 }
233 defer compareResp.Body.Close()
234
235 var formatPatchResponse types.RepoFormatPatchResponse
236 err = json.Unmarshal(respBody, &formatPatchResponse)
237 if err != nil {
238 log.Println("failed to unmarshal format-patch response", err)
239 return nil, fmt.Errorf("failed to compare branches.")
240 }
241
242 return &formatPatchResponse, nil
243}