fizzy-cli 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/package.json +2 -1
  2. package/.env +0 -1
  3. package/.github/workflows/release.yml +0 -29
  4. package/.github/workflows/tests.yml +0 -24
  5. package/AGENTS.md +0 -33
  6. package/CHANGELOG.md +0 -194
  7. package/Makefile +0 -43
  8. package/bin/fizzy +0 -0
  9. package/cmd/account.go +0 -14
  10. package/cmd/account_list.go +0 -44
  11. package/cmd/account_list_test.go +0 -118
  12. package/cmd/board.go +0 -49
  13. package/cmd/board_create.go +0 -59
  14. package/cmd/board_create_test.go +0 -141
  15. package/cmd/board_delete.go +0 -40
  16. package/cmd/board_delete_test.go +0 -121
  17. package/cmd/board_list.go +0 -44
  18. package/cmd/board_list_test.go +0 -115
  19. package/cmd/board_show.go +0 -40
  20. package/cmd/board_show_test.go +0 -113
  21. package/cmd/board_test.go +0 -92
  22. package/cmd/board_update.go +0 -72
  23. package/cmd/board_update_test.go +0 -233
  24. package/cmd/card.go +0 -24
  25. package/cmd/card_assign.go +0 -55
  26. package/cmd/card_assign_test.go +0 -130
  27. package/cmd/card_close.go +0 -46
  28. package/cmd/card_close_test.go +0 -92
  29. package/cmd/card_create.go +0 -72
  30. package/cmd/card_create_test.go +0 -186
  31. package/cmd/card_delete.go +0 -46
  32. package/cmd/card_delete_test.go +0 -92
  33. package/cmd/card_golden.go +0 -46
  34. package/cmd/card_golden_test.go +0 -92
  35. package/cmd/card_list.go +0 -114
  36. package/cmd/card_list_test.go +0 -373
  37. package/cmd/card_not_now.go +0 -46
  38. package/cmd/card_not_now_test.go +0 -92
  39. package/cmd/card_reaction.go +0 -13
  40. package/cmd/card_reaction_create.go +0 -46
  41. package/cmd/card_reaction_create_test.go +0 -148
  42. package/cmd/card_reaction_delete.go +0 -46
  43. package/cmd/card_reaction_delete_test.go +0 -112
  44. package/cmd/card_reaction_list.go +0 -51
  45. package/cmd/card_reaction_list_test.go +0 -127
  46. package/cmd/card_reopen.go +0 -46
  47. package/cmd/card_reopen_test.go +0 -92
  48. package/cmd/card_show.go +0 -46
  49. package/cmd/card_show_test.go +0 -92
  50. package/cmd/card_tag.go +0 -51
  51. package/cmd/card_tag_test.go +0 -112
  52. package/cmd/card_triage.go +0 -46
  53. package/cmd/card_ungolden.go +0 -46
  54. package/cmd/card_ungolden_test.go +0 -92
  55. package/cmd/card_untriage.go +0 -46
  56. package/cmd/card_untriage_test.go +0 -92
  57. package/cmd/card_unwatch.go +0 -46
  58. package/cmd/card_unwatch_test.go +0 -92
  59. package/cmd/card_update.go +0 -82
  60. package/cmd/card_update_test.go +0 -149
  61. package/cmd/card_watch.go +0 -46
  62. package/cmd/card_watch_test.go +0 -92
  63. package/cmd/column.go +0 -14
  64. package/cmd/column_create.go +0 -79
  65. package/cmd/column_create_test.go +0 -178
  66. package/cmd/column_delete.go +0 -40
  67. package/cmd/column_delete_test.go +0 -121
  68. package/cmd/column_list.go +0 -44
  69. package/cmd/column_list_test.go +0 -138
  70. package/cmd/column_show.go +0 -40
  71. package/cmd/column_show_test.go +0 -111
  72. package/cmd/column_update.go +0 -67
  73. package/cmd/column_update_test.go +0 -198
  74. package/cmd/comment.go +0 -14
  75. package/cmd/comment_create.go +0 -51
  76. package/cmd/comment_create_test.go +0 -129
  77. package/cmd/comment_delete.go +0 -46
  78. package/cmd/comment_delete_test.go +0 -92
  79. package/cmd/comment_list.go +0 -51
  80. package/cmd/comment_list_test.go +0 -132
  81. package/cmd/comment_show.go +0 -46
  82. package/cmd/comment_show_test.go +0 -104
  83. package/cmd/comment_update.go +0 -51
  84. package/cmd/comment_update_test.go +0 -130
  85. package/cmd/login.go +0 -81
  86. package/cmd/login_test.go +0 -98
  87. package/cmd/notification.go +0 -14
  88. package/cmd/notification_list.go +0 -69
  89. package/cmd/notification_list_test.go +0 -288
  90. package/cmd/notification_read.go +0 -51
  91. package/cmd/notification_read_all.go +0 -38
  92. package/cmd/notification_read_all_test.go +0 -75
  93. package/cmd/notification_read_test.go +0 -138
  94. package/cmd/notification_unread.go +0 -44
  95. package/cmd/notification_unread_test.go +0 -99
  96. package/cmd/reaction.go +0 -13
  97. package/cmd/reaction_create.go +0 -46
  98. package/cmd/reaction_create_test.go +0 -113
  99. package/cmd/reaction_delete.go +0 -46
  100. package/cmd/reaction_delete_test.go +0 -92
  101. package/cmd/reaction_list.go +0 -51
  102. package/cmd/reaction_list_test.go +0 -125
  103. package/cmd/root.go +0 -38
  104. package/cmd/step.go +0 -14
  105. package/cmd/step_create.go +0 -53
  106. package/cmd/step_create_test.go +0 -171
  107. package/cmd/step_delete.go +0 -46
  108. package/cmd/step_delete_test.go +0 -92
  109. package/cmd/step_update.go +0 -66
  110. package/cmd/step_update_test.go +0 -190
  111. package/cmd/tag.go +0 -15
  112. package/cmd/tag_list.go +0 -47
  113. package/cmd/tag_list_test.go +0 -109
  114. package/cmd/use.go +0 -85
  115. package/cmd/use_test.go +0 -186
  116. package/cmd/user.go +0 -22
  117. package/cmd/user_deactivate.go +0 -40
  118. package/cmd/user_deactivate_test.go +0 -121
  119. package/cmd/user_list.go +0 -44
  120. package/cmd/user_list_test.go +0 -126
  121. package/cmd/user_show.go +0 -40
  122. package/cmd/user_show_test.go +0 -110
  123. package/cmd/user_update.go +0 -71
  124. package/cmd/user_update_test.go +0 -177
  125. package/go.mod +0 -31
  126. package/go.sum +0 -53
  127. package/internal/api/boards.go +0 -93
  128. package/internal/api/cards.go +0 -322
  129. package/internal/api/client.go +0 -99
  130. package/internal/api/columns.go +0 -113
  131. package/internal/api/comments.go +0 -108
  132. package/internal/api/identity.go +0 -24
  133. package/internal/api/notifications.go +0 -89
  134. package/internal/api/reactions.go +0 -130
  135. package/internal/api/steps.go +0 -101
  136. package/internal/api/tags.go +0 -24
  137. package/internal/api/types.go +0 -195
  138. package/internal/api/users.go +0 -75
  139. package/internal/app/app.go +0 -49
  140. package/internal/colors/colors.go +0 -32
  141. package/internal/config/config.go +0 -70
  142. package/internal/testutil/client.go +0 -26
  143. package/internal/ui/account_list.go +0 -14
  144. package/internal/ui/account_selector.go +0 -63
  145. package/internal/ui/board_list.go +0 -14
  146. package/internal/ui/board_show.go +0 -17
  147. package/internal/ui/card_list.go +0 -14
  148. package/internal/ui/card_show.go +0 -23
  149. package/internal/ui/column_list.go +0 -28
  150. package/internal/ui/column_show.go +0 -16
  151. package/internal/ui/comment_list.go +0 -25
  152. package/internal/ui/format.go +0 -27
  153. package/internal/ui/notification_list.go +0 -27
  154. package/internal/ui/reaction_list.go +0 -14
  155. package/internal/ui/user_list.go +0 -19
  156. package/internal/ui/user_show.go +0 -23
@@ -1,93 +0,0 @@
1
- package api
2
-
3
- import (
4
- "context"
5
- "fmt"
6
- "net/http"
7
- )
8
-
9
- func (c *Client) GetBoards(ctx context.Context) ([]Board, error) {
10
- endpointURL := c.AccountBaseURL + "/boards"
11
-
12
- req, err := c.newRequest(ctx, http.MethodGet, endpointURL, nil)
13
- if err != nil {
14
- return nil, fmt.Errorf("failed to create request: %w", err)
15
- }
16
-
17
- var response []Board
18
- _, err = c.decodeResponse(req, &response)
19
- if err != nil {
20
- return nil, err
21
- }
22
-
23
- return response, nil
24
- }
25
-
26
- func (c *Client) GetBoard(ctx context.Context, boardID string) (*Board, error) {
27
- endpointURL := c.AccountBaseURL + "/boards/" + boardID
28
-
29
- req, err := c.newRequest(ctx, http.MethodGet, endpointURL, nil)
30
- if err != nil {
31
- return nil, fmt.Errorf("failed to create request: %w", err)
32
- }
33
-
34
- var response Board
35
- _, err = c.decodeResponse(req, &response)
36
- if err != nil {
37
- return nil, err
38
- }
39
-
40
- return &response, nil
41
- }
42
-
43
- func (c *Client) PostBoards(ctx context.Context, payload CreateBoardPayload) (bool, error) {
44
- endpointURL := c.AccountBaseURL + "/boards"
45
-
46
- body := map[string]CreateBoardPayload{"board": payload}
47
-
48
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, body)
49
- if err != nil {
50
- return false, fmt.Errorf("failed to create board request: %w", err)
51
- }
52
-
53
- _, err = c.decodeResponse(req, nil, http.StatusCreated)
54
- if err != nil {
55
- return false, err
56
- }
57
-
58
- return true, nil
59
- }
60
-
61
- func (c *Client) PutBoard(ctx context.Context, boardID string, payload UpdateBoardPayload) error {
62
- endpointURL := c.AccountBaseURL + "/boards/" + boardID
63
-
64
- body := map[string]UpdateBoardPayload{"board": payload}
65
-
66
- req, err := c.newRequest(ctx, http.MethodPut, endpointURL, body)
67
- if err != nil {
68
- return fmt.Errorf("failed to create update board request: %w", err)
69
- }
70
-
71
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
72
- if err != nil {
73
- return err
74
- }
75
-
76
- return nil
77
- }
78
-
79
- func (c *Client) DeleteBoard(ctx context.Context, boardID string) error {
80
- endpointURL := c.AccountBaseURL + "/boards/" + boardID
81
-
82
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
83
- if err != nil {
84
- return fmt.Errorf("failed to create delete board request: %w", err)
85
- }
86
-
87
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
88
- if err != nil {
89
- return err
90
- }
91
-
92
- return nil
93
- }
@@ -1,322 +0,0 @@
1
- package api
2
-
3
- import (
4
- "context"
5
- "fmt"
6
- "net/http"
7
- )
8
-
9
- func (c *Client) GetCards(ctx context.Context, filters CardFilters) ([]Card, error) {
10
- endpointURL := c.AccountBaseURL + "/cards"
11
-
12
- req, err := c.newRequest(ctx, http.MethodGet, endpointURL, nil)
13
- if err != nil {
14
- return nil, fmt.Errorf("failed to create get cards request: %w", err)
15
- }
16
-
17
- q := req.URL.Query()
18
-
19
- for _, boardID := range filters.BoardIDs {
20
- q.Add("board_ids[]", boardID)
21
- }
22
- for _, tagID := range filters.TagIDs {
23
- q.Add("tag_ids[]", tagID)
24
- }
25
- for _, assigneeID := range filters.AssigneeIDs {
26
- q.Add("assignee_ids[]", assigneeID)
27
- }
28
- for _, creatorID := range filters.CreatorIDs {
29
- q.Add("creator_ids[]", creatorID)
30
- }
31
- for _, closerID := range filters.CloserIDs {
32
- q.Add("closer_ids[]", closerID)
33
- }
34
- for _, cardID := range filters.CardIDs {
35
- q.Add("card_ids[]", cardID)
36
- }
37
- for _, term := range filters.Terms {
38
- q.Add("terms[]", term)
39
- }
40
-
41
- if filters.IndexedBy != "" {
42
- q.Set("indexed_by", filters.IndexedBy)
43
- }
44
- if filters.SortedBy != "" {
45
- q.Set("sorted_by", filters.SortedBy)
46
- }
47
- if filters.AssignmentStatus != "" {
48
- q.Set("assignment_status", filters.AssignmentStatus)
49
- }
50
- if filters.CreationStatus != "" {
51
- q.Set("creation", filters.CreationStatus)
52
- }
53
- if filters.ClosureStatus != "" {
54
- q.Set("closure", filters.ClosureStatus)
55
- }
56
-
57
- req.URL.RawQuery = q.Encode()
58
-
59
- var response []Card
60
- _, err = c.decodeResponse(req, &response)
61
- if err != nil {
62
- return nil, err
63
- }
64
-
65
- return response, nil
66
- }
67
-
68
- func (c *Client) GetCard(ctx context.Context, cardNumber int) (*Card, error) {
69
- endpointURL := fmt.Sprintf("%s/cards/%d", c.AccountBaseURL, cardNumber)
70
-
71
- req, err := c.newRequest(ctx, http.MethodGet, endpointURL, nil)
72
- if err != nil {
73
- return nil, fmt.Errorf("failed to create get card by id request: %w", err)
74
- }
75
-
76
- var response Card
77
- _, err = c.decodeResponse(req, &response)
78
- if err != nil {
79
- return nil, err
80
- }
81
-
82
- return &response, nil
83
- }
84
-
85
- func (c *Client) PostCards(ctx context.Context, payload CreateCardPayload) (bool, error) {
86
- if c.BoardBaseURL == "" {
87
- return false, fmt.Errorf("please select a board first with 'fizzy use --board <board_name>'")
88
- }
89
-
90
- endpointURL := c.BoardBaseURL + "/cards"
91
-
92
- body := map[string]CreateCardPayload{"card": payload}
93
-
94
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, body)
95
- if err != nil {
96
- return false, fmt.Errorf("failed to create card request: %w", err)
97
- }
98
-
99
- _, err = c.decodeResponse(req, nil, http.StatusCreated)
100
- if err != nil {
101
- return false, err
102
- }
103
-
104
- return true, nil
105
- }
106
-
107
- func (c *Client) PutCard(ctx context.Context, cardNumber int, payload UpdateCardPayload) (*Card, error) {
108
- endpointURL := fmt.Sprintf("%s/cards/%d", c.AccountBaseURL, cardNumber)
109
-
110
- body := map[string]UpdateCardPayload{"card": payload}
111
-
112
- req, err := c.newRequest(ctx, http.MethodPut, endpointURL, body)
113
- if err != nil {
114
- return nil, fmt.Errorf("failed to create update card request: %w", err)
115
- }
116
-
117
- var response Card
118
- _, err = c.decodeResponse(req, &response, http.StatusOK)
119
- if err != nil {
120
- return nil, err
121
- }
122
-
123
- return &response, nil
124
- }
125
-
126
- func (c *Client) DeleteCard(ctx context.Context, cardNumber int) (bool, error) {
127
- endpointURL := fmt.Sprintf("%s/cards/%d", c.AccountBaseURL, cardNumber)
128
-
129
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
130
- if err != nil {
131
- return false, fmt.Errorf("failed to create delete card request: %w", err)
132
- }
133
-
134
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
135
- if err != nil {
136
- return false, err
137
- }
138
-
139
- return true, nil
140
- }
141
-
142
- func (c *Client) PostCardsClosure(ctx context.Context, cardNumber int) (bool, error) {
143
- endpointURL := fmt.Sprintf("%s/cards/%d/closure", c.AccountBaseURL, cardNumber)
144
-
145
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, nil)
146
- if err != nil {
147
- return false, fmt.Errorf("failed to create closure card request: %w", err)
148
- }
149
-
150
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
151
- if err != nil {
152
- return false, err
153
- }
154
-
155
- return true, nil
156
- }
157
-
158
- func (c *Client) PostCardNotNow(ctx context.Context, cardNumber int) (bool, error) {
159
- endpointURL := fmt.Sprintf("%s/cards/%d/not_now", c.AccountBaseURL, cardNumber)
160
-
161
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, nil)
162
- if err != nil {
163
- return false, fmt.Errorf("failed to create post not now request: %w", err)
164
- }
165
-
166
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
167
- if err != nil {
168
- return false, err
169
- }
170
-
171
- return true, nil
172
- }
173
-
174
- func (c *Client) PostCardTriage(ctx context.Context, cardNumber int, columnID string) (bool, error) {
175
- endpointURL := fmt.Sprintf("%s/cards/%d/triage", c.AccountBaseURL, cardNumber)
176
-
177
- body := map[string]any{"column_id": columnID}
178
-
179
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, body)
180
- if err != nil {
181
- return false, fmt.Errorf("failed to create post triage request: %w", err)
182
- }
183
-
184
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
185
- if err != nil {
186
- return false, err
187
- }
188
-
189
- return true, nil
190
- }
191
-
192
- func (c *Client) DeleteCardTriage(ctx context.Context, cardNumber int) (bool, error) {
193
- endpointURL := fmt.Sprintf("%s/cards/%d/triage", c.AccountBaseURL, cardNumber)
194
-
195
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
196
- if err != nil {
197
- return false, fmt.Errorf("failed to create delete triage request: %w", err)
198
- }
199
-
200
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
201
- if err != nil {
202
- return false, err
203
- }
204
-
205
- return true, nil
206
- }
207
-
208
- func (c *Client) PostCardWatch(ctx context.Context, cardNumber int) (bool, error) {
209
- endpointURL := fmt.Sprintf("%s/cards/%d/watch", c.AccountBaseURL, cardNumber)
210
-
211
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, nil)
212
- if err != nil {
213
- return false, fmt.Errorf("failed to create post watch request: %w", err)
214
- }
215
-
216
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
217
- if err != nil {
218
- return false, err
219
- }
220
-
221
- return true, nil
222
- }
223
-
224
- func (c *Client) DeleteCardWatch(ctx context.Context, cardNumber int) (bool, error) {
225
- endpointURL := fmt.Sprintf("%s/cards/%d/watch", c.AccountBaseURL, cardNumber)
226
-
227
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
228
- if err != nil {
229
- return false, fmt.Errorf("failed to create delete watch request: %w", err)
230
- }
231
-
232
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
233
- if err != nil {
234
- return false, err
235
- }
236
-
237
- return true, nil
238
- }
239
-
240
- func (c *Client) PostCardGoldenness(ctx context.Context, cardNumber int) (bool, error) {
241
- endpointURL := fmt.Sprintf("%s/cards/%d/goldness", c.AccountBaseURL, cardNumber)
242
-
243
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, nil)
244
- if err != nil {
245
- return false, fmt.Errorf("failed to create post goldness request: %w", err)
246
- }
247
-
248
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
249
- if err != nil {
250
- return false, err
251
- }
252
-
253
- return true, nil
254
- }
255
-
256
- func (c *Client) DeleteCardGoldenness(ctx context.Context, cardNumber int) (bool, error) {
257
- endpointURL := fmt.Sprintf("%s/cards/%d/goldness", c.AccountBaseURL, cardNumber)
258
-
259
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
260
- if err != nil {
261
- return false, fmt.Errorf("failed to create delete goldness request: %w", err)
262
- }
263
-
264
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
265
- if err != nil {
266
- return false, err
267
- }
268
-
269
- return true, nil
270
- }
271
-
272
- func (c *Client) DeleteCardsClosure(ctx context.Context, cardNumber int) (bool, error) {
273
- endpointURL := fmt.Sprintf("%s/cards/%d/closure", c.AccountBaseURL, cardNumber)
274
-
275
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
276
- if err != nil {
277
- return false, fmt.Errorf("failed to create delete closure card request: %w", err)
278
- }
279
-
280
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
281
- if err != nil {
282
- return false, err
283
- }
284
-
285
- return true, nil
286
- }
287
-
288
- func (c *Client) PostCardAssignments(ctx context.Context, cardNumber int, userID string) (bool, error) {
289
- endpointURL := fmt.Sprintf("%s/cards/%d/assignments", c.AccountBaseURL, cardNumber)
290
-
291
- body := map[string]string{"assignee_id": userID}
292
-
293
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, body)
294
- if err != nil {
295
- return false, fmt.Errorf("failed to create assignment request: %w", err)
296
- }
297
-
298
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
299
- if err != nil {
300
- return false, err
301
- }
302
-
303
- return true, nil
304
- }
305
-
306
- func (c *Client) PostCardTagging(ctx context.Context, cardNumber int, tagTitle string) (bool, error) {
307
- endpointURL := fmt.Sprintf("%s/cards/%d/taggings", c.AccountBaseURL, cardNumber)
308
-
309
- body := map[string]string{"tag_title": tagTitle}
310
-
311
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, body)
312
- if err != nil {
313
- return false, fmt.Errorf("failed to create tagging request: %w", err)
314
- }
315
-
316
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
317
- if err != nil {
318
- return false, err
319
- }
320
-
321
- return true, nil
322
- }
@@ -1,99 +0,0 @@
1
- // Package api provides the Fizzy API client
2
- package api
3
-
4
- import (
5
- "bytes"
6
- "context"
7
- "encoding/json"
8
- "fmt"
9
- "io"
10
- "net/http"
11
- "os"
12
- "time"
13
- )
14
-
15
- type Client struct {
16
- BaseURL string
17
- AccountBaseURL string
18
- BoardBaseURL string
19
- AccessToken string
20
- HTTPClient *http.Client
21
- }
22
-
23
- func NewClient(accountSlug string, boardID string) (*Client, error) {
24
- baseURL := "https://app.fizzy.do"
25
- accountBaseURL := baseURL + accountSlug
26
-
27
- var boardBaseURL string
28
- if boardID != "" {
29
- boardBaseURL = accountBaseURL + "/boards" + "/" + boardID
30
- }
31
-
32
- token, isSet := os.LookupEnv("FIZZY_ACCESS_TOKEN")
33
- if !isSet || token == "" {
34
- return nil, fmt.Errorf("FIZZY_ACCESS_TOKEN environment variable is not set")
35
- }
36
-
37
- return &Client{
38
- BaseURL: baseURL,
39
- AccountBaseURL: accountBaseURL,
40
- BoardBaseURL: boardBaseURL,
41
- AccessToken: token,
42
- HTTPClient: &http.Client{Timeout: 30 * time.Second},
43
- }, nil
44
- }
45
-
46
- // newRequest makes an HTTP request with the required headers setup
47
- func (c *Client) newRequest(ctx context.Context, method, url string, body any) (*http.Request, error) {
48
- var bodyReader io.Reader
49
- if body != nil {
50
- data, err := json.Marshal(body)
51
- if err != nil {
52
- return nil, fmt.Errorf("failed to marshal request body: %w", err)
53
- }
54
- bodyReader = bytes.NewReader(data)
55
- }
56
-
57
- req, err := http.NewRequestWithContext(ctx, method, url, bodyReader)
58
- if err != nil {
59
- return nil, err
60
- }
61
-
62
- req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.AccessToken))
63
- req.Header.Set("Accept", "application/json")
64
- req.Header.Set("Content-Type", "application/json")
65
-
66
- return req, nil
67
- }
68
-
69
- // decodeResponse executes a request and decodes the JSON response into v
70
- // If expectedStatus is 0, it defaults to http.StatusOK
71
- // If v is nil, the response body is not decoded
72
- func (c *Client) decodeResponse(req *http.Request, v any, expectedStatus ...int) (int, error) {
73
- expectedCode := http.StatusOK
74
- if len(expectedStatus) > 0 {
75
- expectedCode = expectedStatus[0]
76
- }
77
-
78
- res, err := c.HTTPClient.Do(req)
79
- if err != nil {
80
- return 0, fmt.Errorf("failed to make request: %w", err)
81
- }
82
- defer res.Body.Close()
83
-
84
- if res.StatusCode != expectedCode {
85
- body, err := io.ReadAll(res.Body)
86
- if err != nil {
87
- return 0, fmt.Errorf("unexpected status code %d (failed to read error response: %w)", res.StatusCode, err)
88
- }
89
- return 0, fmt.Errorf("unexpected status code %d: %s", res.StatusCode, string(body))
90
- }
91
-
92
- if v != nil {
93
- if err := json.NewDecoder(res.Body).Decode(v); err != nil {
94
- return 0, fmt.Errorf("failed to decode response: %w", err)
95
- }
96
- }
97
-
98
- return res.StatusCode, nil
99
- }
@@ -1,113 +0,0 @@
1
- package api
2
-
3
- import (
4
- "context"
5
- "fmt"
6
- "net/http"
7
- )
8
-
9
- func (c *Client) GetColumns(ctx context.Context) ([]Column, error) {
10
- if c.BoardBaseURL == "" {
11
- return nil, fmt.Errorf("please select a board first with 'fizzy use --board <board_name>'")
12
- }
13
-
14
- endpointURL := c.BoardBaseURL + "/columns"
15
-
16
- req, err := c.newRequest(ctx, http.MethodGet, endpointURL, nil)
17
- if err != nil {
18
- return nil, fmt.Errorf("failed to create get columns request: %w", err)
19
- }
20
-
21
- var response []Column
22
- _, err = c.decodeResponse(req, &response)
23
- if err != nil {
24
- return nil, err
25
- }
26
-
27
- return response, nil
28
- }
29
-
30
- func (c *Client) GetColumn(ctx context.Context, columnID string) (*Column, error) {
31
- if c.BoardBaseURL == "" {
32
- return nil, fmt.Errorf("please select a board first with 'fizzy use --board <board_name>'")
33
- }
34
-
35
- endpointURL := c.BoardBaseURL + "/columns/" + columnID
36
-
37
- req, err := c.newRequest(ctx, http.MethodGet, endpointURL, nil)
38
- if err != nil {
39
- return nil, fmt.Errorf("failed to create request: %w", err)
40
- }
41
-
42
- var response Column
43
- _, err = c.decodeResponse(req, &response)
44
- if err != nil {
45
- return nil, err
46
- }
47
-
48
- return &response, nil
49
- }
50
-
51
- func (c *Client) PostColumns(ctx context.Context, payload CreateColumnPayload) (bool, error) {
52
- if c.BoardBaseURL == "" {
53
- return false, fmt.Errorf("please select a board first with 'fizzy use --board <board_name>'")
54
- }
55
-
56
- endpointURL := c.BoardBaseURL + "/columns"
57
-
58
- body := map[string]CreateColumnPayload{"column": payload}
59
-
60
- req, err := c.newRequest(ctx, http.MethodPost, endpointURL, body)
61
- if err != nil {
62
- return false, fmt.Errorf("failed to create column request: %w", err)
63
- }
64
-
65
- _, err = c.decodeResponse(req, nil, http.StatusCreated)
66
- if err != nil {
67
- return false, err
68
- }
69
-
70
- return true, nil
71
- }
72
-
73
- func (c *Client) PutColumn(ctx context.Context, columnID string, payload UpdateColumnPayload) error {
74
- if c.BoardBaseURL == "" {
75
- return fmt.Errorf("please select a board first with 'fizzy use --board <board_name>'")
76
- }
77
-
78
- endpointURL := c.BoardBaseURL + "/columns/" + columnID
79
-
80
- body := map[string]UpdateColumnPayload{"column": payload}
81
-
82
- req, err := c.newRequest(ctx, http.MethodPut, endpointURL, body)
83
- if err != nil {
84
- return fmt.Errorf("failed to create update column request: %w", err)
85
- }
86
-
87
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
88
- if err != nil {
89
- return err
90
- }
91
-
92
- return nil
93
- }
94
-
95
- func (c *Client) DeleteColumn(ctx context.Context, columnID string) error {
96
- if c.BoardBaseURL == "" {
97
- return fmt.Errorf("please select a board first with 'fizzy use --board <board_name>'")
98
- }
99
-
100
- endpointURL := c.BoardBaseURL + "/columns/" + columnID
101
-
102
- req, err := c.newRequest(ctx, http.MethodDelete, endpointURL, nil)
103
- if err != nil {
104
- return fmt.Errorf("failed to create delete column request: %w", err)
105
- }
106
-
107
- _, err = c.decodeResponse(req, nil, http.StatusNoContent)
108
- if err != nil {
109
- return err
110
- }
111
-
112
- return nil
113
- }