fizzy-cli 0.1.0 → 0.2.1
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.
- package/.env +1 -0
- package/.github/workflows/release.yml +29 -0
- package/.github/workflows/tests.yml +24 -0
- package/AGENTS.md +33 -0
- package/CHANGELOG.md +69 -0
- package/Makefile +20 -9
- package/README.md +88 -1
- package/bin/fizzy +0 -0
- package/cmd/account.go +14 -0
- package/cmd/account_list.go +44 -0
- package/cmd/account_list_test.go +118 -0
- package/cmd/board.go +38 -12
- package/cmd/board_create.go +60 -0
- package/cmd/board_create_test.go +158 -0
- package/cmd/board_list.go +18 -32
- package/cmd/board_list_test.go +115 -0
- package/cmd/board_test.go +92 -0
- package/cmd/card.go +24 -0
- package/cmd/card_close.go +46 -0
- package/cmd/card_close_test.go +92 -0
- package/cmd/card_create.go +73 -0
- package/cmd/card_create_test.go +206 -0
- package/cmd/card_delete.go +46 -0
- package/cmd/card_delete_test.go +92 -0
- package/cmd/card_list.go +53 -0
- package/cmd/card_list_test.go +148 -0
- package/cmd/card_reopen.go +46 -0
- package/cmd/card_reopen_test.go +92 -0
- package/cmd/card_show.go +46 -0
- package/cmd/card_show_test.go +92 -0
- package/cmd/card_update.go +74 -0
- package/cmd/card_update_test.go +147 -0
- package/cmd/column.go +14 -0
- package/cmd/column_create.go +80 -0
- package/cmd/column_create_test.go +196 -0
- package/cmd/column_list.go +44 -0
- package/cmd/column_list_test.go +138 -0
- package/cmd/login.go +61 -4
- package/cmd/login_test.go +98 -0
- package/cmd/root.go +15 -4
- package/cmd/use.go +85 -0
- package/cmd/use_test.go +186 -0
- package/docs/API.md +1168 -0
- package/go.mod +23 -2
- package/go.sum +43 -0
- package/internal/api/client.go +463 -0
- package/internal/app/app.go +49 -0
- package/internal/colors/colors.go +32 -0
- package/internal/config/config.go +69 -0
- package/internal/testutil/client.go +26 -0
- package/internal/ui/account_list.go +14 -0
- package/internal/ui/account_selector.go +63 -0
- package/internal/ui/board_list.go +14 -0
- package/internal/ui/card_list.go +14 -0
- package/internal/ui/card_show.go +23 -0
- package/internal/ui/column_list.go +28 -0
- package/internal/ui/format.go +14 -0
- package/main.go +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +5 -1
package/.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
FIZZY_ACCESS_TOKEN=S7FiVcT1K3WgwXc7uzBdQRim
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Go
|
|
18
|
+
uses: actions/setup-go@v4
|
|
19
|
+
with:
|
|
20
|
+
go-version: "1.25"
|
|
21
|
+
|
|
22
|
+
- name: Build binaries
|
|
23
|
+
run: make build-all
|
|
24
|
+
|
|
25
|
+
- name: Upload Release Assets
|
|
26
|
+
env:
|
|
27
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
28
|
+
run: |
|
|
29
|
+
gh release upload ${{ github.event.release.tag_name }} bin/fizzy-* --clobber
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-go@v4
|
|
17
|
+
with:
|
|
18
|
+
go-version: "1.25"
|
|
19
|
+
|
|
20
|
+
- name: Install gotestsum
|
|
21
|
+
run: go install gotest.tools/gotestsum@latest
|
|
22
|
+
|
|
23
|
+
- name: Run tests
|
|
24
|
+
run: make test
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## About
|
|
4
|
+
|
|
5
|
+
fizzy-cli is a CLI application built in Go that provides an interface to the
|
|
6
|
+
[Fizzy](https://fizzy.do) API. Fizzy is a kanban-style project management SaaS.
|
|
7
|
+
|
|
8
|
+
## Dev instructions
|
|
9
|
+
|
|
10
|
+
All the commands for development are available through Makefile, just read that
|
|
11
|
+
file whenever you need to run something because chances are that you will find
|
|
12
|
+
you answer there.
|
|
13
|
+
|
|
14
|
+
You can find the Fizzy API specification at @docs/API.md
|
|
15
|
+
|
|
16
|
+
## Testing
|
|
17
|
+
|
|
18
|
+
Automated testing is done via `make test`.
|
|
19
|
+
|
|
20
|
+
For manual testing/debugging, you should run `make install` first to install the
|
|
21
|
+
binary and then run the `fizzy` command normally.
|
|
22
|
+
|
|
23
|
+
## Code quality, standards and style
|
|
24
|
+
|
|
25
|
+
This project is being built in Go because it's supposed to have a strong focus
|
|
26
|
+
on performance. Always prefer performant code and solutions and low memory
|
|
27
|
+
footprint.
|
|
28
|
+
|
|
29
|
+
Don't write obvious code comments. Only use code comments when the code itself
|
|
30
|
+
requires some clarification to be understood.
|
|
31
|
+
|
|
32
|
+
When in doubt, always check similar files or features and reuse the patterns and
|
|
33
|
+
style applied.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.1] - 2025-12-20
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- NPM package publishing script
|
|
8
|
+
|
|
9
|
+
## [0.2.0] - 2025-12-20
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
#### Card Management
|
|
14
|
+
|
|
15
|
+
- `fizzy card update <card_number>` - Update card properties (title, description, status, tags)
|
|
16
|
+
- `fizzy card delete <card_number>` - Delete a card permanently
|
|
17
|
+
- `fizzy card close <card_number>` - Close an existing card (already existed, now documented)
|
|
18
|
+
- `fizzy card reopen <card_number>` - Reopen a closed card (already existed, now documented)
|
|
19
|
+
|
|
20
|
+
#### Account Management
|
|
21
|
+
|
|
22
|
+
- `fizzy account list` - List all accounts you have access to
|
|
23
|
+
|
|
24
|
+
#### Improvements
|
|
25
|
+
|
|
26
|
+
- `fizzy board` without arguments now displays the currently selected board
|
|
27
|
+
- Added `--version` flag to display CLI version
|
|
28
|
+
- Fixed HTTP client leak in API requests
|
|
29
|
+
- Updated API specification to latest version
|
|
30
|
+
|
|
31
|
+
## [0.1.0] - 2025-12-16
|
|
32
|
+
|
|
33
|
+
### Initial Release
|
|
34
|
+
|
|
35
|
+
The first stable release of Fizzy CLI with core functionality for managing
|
|
36
|
+
boards, cards, and columns.
|
|
37
|
+
|
|
38
|
+
### Features
|
|
39
|
+
|
|
40
|
+
#### Authentication
|
|
41
|
+
|
|
42
|
+
- `fizzy login` - Authenticate with Fizzy API using access tokens
|
|
43
|
+
|
|
44
|
+
#### Board Management
|
|
45
|
+
|
|
46
|
+
- `fizzy board list` - List all boards
|
|
47
|
+
- `fizzy board create` - Create a new board
|
|
48
|
+
|
|
49
|
+
#### Card Management
|
|
50
|
+
|
|
51
|
+
- `fizzy card list` - List all cards in the selected board
|
|
52
|
+
- `fizzy card create` - Create a new card
|
|
53
|
+
- `fizzy card show <card_id>` - Display details for a specific card
|
|
54
|
+
|
|
55
|
+
#### Column Management
|
|
56
|
+
|
|
57
|
+
- `fizzy column list` - List all columns in the selected board
|
|
58
|
+
- `fizzy column create` - Create a new column
|
|
59
|
+
|
|
60
|
+
#### Configuration
|
|
61
|
+
|
|
62
|
+
- `fizzy use --board <name>` - Set the active board for subsequent commands
|
|
63
|
+
- `fizzy use --account <slug>` - Set the active account for subsequent commands
|
|
64
|
+
|
|
65
|
+
### Distribution
|
|
66
|
+
|
|
67
|
+
- Multi-platform support (macOS, Linux, Windows)
|
|
68
|
+
- Multi-architecture binaries (x64, arm64)
|
|
69
|
+
- Distributed via NPM with automatic binary download on install
|
package/Makefile
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
.PHONY: help dev-tools run build build-all clean test
|
|
1
|
+
.PHONY: help dev-tools run build build-all clean test install sync-api-spec
|
|
2
|
+
|
|
3
|
+
VERSION := $(shell grep '"version"' package.json | sed 's/.*"version": "\([^"]*\)".*/\1/')
|
|
4
|
+
LDFLAGS := -ldflags="-X 'github.com/rogeriopvl/fizzy/cmd.Version=$(VERSION)'"
|
|
2
5
|
|
|
3
6
|
help:
|
|
4
7
|
@echo 'Usage: make [target]'
|
|
@@ -8,25 +11,33 @@ help:
|
|
|
8
11
|
|
|
9
12
|
dev-tools:
|
|
10
13
|
@echo "Installing development tools..."
|
|
11
|
-
go install
|
|
14
|
+
go install gotest.tools/gotestsum@latest
|
|
12
15
|
|
|
13
16
|
run:
|
|
14
17
|
go run .
|
|
15
18
|
|
|
19
|
+
install:
|
|
20
|
+
go install $(LDFLAGS) .
|
|
21
|
+
|
|
16
22
|
build:
|
|
17
|
-
go build -o bin/fizzy .
|
|
23
|
+
go build $(LDFLAGS) -o bin/fizzy .
|
|
18
24
|
|
|
19
25
|
build-all: clean
|
|
20
26
|
mkdir -p bin
|
|
21
|
-
GOOS=darwin GOARCH=amd64 go build -o bin/fizzy-darwin-amd64 .
|
|
22
|
-
GOOS=darwin GOARCH=arm64 go build -o bin/fizzy-darwin-arm64 .
|
|
23
|
-
GOOS=linux GOARCH=amd64 go build -o bin/fizzy-linux-amd64 .
|
|
24
|
-
GOOS=linux GOARCH=arm64 go build -o bin/fizzy-linux-arm64 .
|
|
25
|
-
GOOS=windows GOARCH=amd64 go build -o bin/fizzy-windows-amd64.exe .
|
|
27
|
+
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o bin/fizzy-darwin-amd64 .
|
|
28
|
+
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o bin/fizzy-darwin-arm64 .
|
|
29
|
+
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o bin/fizzy-linux-amd64 .
|
|
30
|
+
GOOS=linux GOARCH=arm64 go build $(LDFLAGS) -o bin/fizzy-linux-arm64 .
|
|
31
|
+
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o bin/fizzy-windows-amd64.exe .
|
|
26
32
|
@echo "Binaries built successfully in bin/"
|
|
27
33
|
|
|
28
34
|
clean:
|
|
29
35
|
rm -rf bin/
|
|
30
36
|
|
|
31
37
|
test:
|
|
32
|
-
|
|
38
|
+
gotestsum -- -v ./...
|
|
39
|
+
|
|
40
|
+
sync-api-spec:
|
|
41
|
+
@mkdir -p docs
|
|
42
|
+
@curl -s https://raw.githubusercontent.com/basecamp/fizzy/main/docs/API.md -o docs/API.md
|
|
43
|
+
@echo "API spec synced to docs/API.md"
|
package/README.md
CHANGED
|
@@ -1,7 +1,94 @@
|
|
|
1
1
|
# Fizzy CLI
|
|
2
2
|
|
|
3
|
+
[](https://github.com/rogeriopvl/fizzy-cli/actions/workflows/tests.yml)
|
|
4
|
+
[](https://github.com/rogeriopvl/fizzy-cli/commits)
|
|
5
|
+
[](https://github.com/rogeriopvl/fizzy-cli/commits)
|
|
6
|
+
|
|
3
7
|
This is a command-line interface for https://fizzy.do
|
|
4
8
|
|
|
5
9
|
## Install
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
You have multiple options to install:
|
|
12
|
+
|
|
13
|
+
### Homebrew (Mac/Linux)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
brew tap rogeriopvl/tap
|
|
17
|
+
|
|
18
|
+
brew install fizzy-cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### NPM (Mac/Linux/Windows)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm i -g fizzy-cli
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or...
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx -y fizzy-cli@latest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
Before you start using `fizzy-cli`, you need to authenticate it with your Fizzy
|
|
36
|
+
account:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
fizzy login
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The first time you run this command it will print out the instructions for you
|
|
43
|
+
to follow. These instructions will guide you through creating an access token on
|
|
44
|
+
the Fizzy web app.
|
|
45
|
+
|
|
46
|
+
After you get the token, setup your shell to export the `FIZZY_ACCESS_TOKEN`
|
|
47
|
+
environment variable. Edit your `~/.bashrc` or `~/.zshrc` and add the following
|
|
48
|
+
line:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
export FIZZY_ACCESS_TOKEN=your_access_token
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Reload the shell, and run the `fizzy login` command again to confirm that you're
|
|
55
|
+
authenticated. If you have only one Fizzy account, `fizzy-cli` will select it
|
|
56
|
+
automatically. Otherwise you will be able to select which one you want to use.
|
|
57
|
+
|
|
58
|
+
### Board selection
|
|
59
|
+
|
|
60
|
+
You can choose which board you want to pre-select for all your commands with:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
fizzy use --board <board_name>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
To get the board name just type:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
fizzy board list
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `use` command also supports selecting a different account:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
fizzy use --account <account_slug>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Development
|
|
79
|
+
|
|
80
|
+
### Tests
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
make test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Run
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
make install
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
fizzy --help
|
|
94
|
+
```
|
package/bin/fizzy
CHANGED
|
Binary file
|
package/cmd/account.go
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package cmd
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
|
|
7
|
+
"github.com/rogeriopvl/fizzy/internal/app"
|
|
8
|
+
"github.com/rogeriopvl/fizzy/internal/ui"
|
|
9
|
+
"github.com/spf13/cobra"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
var accountListCmd = &cobra.Command{
|
|
13
|
+
Use: "list",
|
|
14
|
+
Short: "List all accounts",
|
|
15
|
+
Long: `Retrieve and display all accounts from Fizzy`,
|
|
16
|
+
Run: func(cmd *cobra.Command, args []string) {
|
|
17
|
+
if err := handleListAccounts(cmd); err != nil {
|
|
18
|
+
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
func handleListAccounts(cmd *cobra.Command) error {
|
|
24
|
+
a := app.FromContext(cmd.Context())
|
|
25
|
+
if a == nil || a.Client == nil {
|
|
26
|
+
return fmt.Errorf("API client not available")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
identity, err := a.Client.GetMyIdentity(context.Background())
|
|
30
|
+
if err != nil {
|
|
31
|
+
return fmt.Errorf("fetching accounts: %w", err)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if len(identity.Accounts) == 0 {
|
|
35
|
+
fmt.Println("No accounts found")
|
|
36
|
+
return nil
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return ui.DisplayAccounts(identity.Accounts)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func init() {
|
|
43
|
+
accountCmd.AddCommand(accountListCmd)
|
|
44
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
package cmd
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"encoding/json"
|
|
6
|
+
"net/http"
|
|
7
|
+
"net/http/httptest"
|
|
8
|
+
"testing"
|
|
9
|
+
|
|
10
|
+
"github.com/rogeriopvl/fizzy/internal/api"
|
|
11
|
+
"github.com/rogeriopvl/fizzy/internal/app"
|
|
12
|
+
"github.com/rogeriopvl/fizzy/internal/testutil"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
func TestAccountListCommand(t *testing.T) {
|
|
16
|
+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
17
|
+
if r.URL.Path != "/my/identity" {
|
|
18
|
+
t.Errorf("expected /my/identity, got %s", r.URL.Path)
|
|
19
|
+
}
|
|
20
|
+
if r.Method != http.MethodGet {
|
|
21
|
+
t.Errorf("expected GET, got %s", r.Method)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
auth := r.Header.Get("Authorization")
|
|
25
|
+
if auth == "" {
|
|
26
|
+
t.Error("missing Authorization header")
|
|
27
|
+
}
|
|
28
|
+
if auth != "Bearer test-token" {
|
|
29
|
+
t.Errorf("expected Bearer test-token, got %s", auth)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
w.Header().Set("Content-Type", "application/json")
|
|
33
|
+
response := api.GetMyIdentityResponse{
|
|
34
|
+
Accounts: []api.Account{
|
|
35
|
+
{
|
|
36
|
+
ID: "account-123",
|
|
37
|
+
Name: "Personal",
|
|
38
|
+
Slug: "personal",
|
|
39
|
+
CreatedAt: "2025-01-01T00:00:00Z",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
ID: "account-456",
|
|
43
|
+
Name: "Work",
|
|
44
|
+
Slug: "work",
|
|
45
|
+
CreatedAt: "2025-01-02T00:00:00Z",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
json.NewEncoder(w).Encode(response)
|
|
50
|
+
}))
|
|
51
|
+
defer server.Close()
|
|
52
|
+
|
|
53
|
+
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
54
|
+
testApp := &app.App{Client: client}
|
|
55
|
+
|
|
56
|
+
cmd := accountListCmd
|
|
57
|
+
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
58
|
+
|
|
59
|
+
if err := handleListAccounts(cmd); err != nil {
|
|
60
|
+
t.Fatalf("handleListAccounts failed: %v", err)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func TestAccountListCommandNoAccounts(t *testing.T) {
|
|
65
|
+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
66
|
+
w.Header().Set("Content-Type", "application/json")
|
|
67
|
+
response := api.GetMyIdentityResponse{Accounts: []api.Account{}}
|
|
68
|
+
json.NewEncoder(w).Encode(response)
|
|
69
|
+
}))
|
|
70
|
+
defer server.Close()
|
|
71
|
+
|
|
72
|
+
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
73
|
+
testApp := &app.App{Client: client}
|
|
74
|
+
|
|
75
|
+
cmd := accountListCmd
|
|
76
|
+
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
77
|
+
|
|
78
|
+
if err := handleListAccounts(cmd); err != nil {
|
|
79
|
+
t.Fatalf("handleListAccounts failed: %v", err)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func TestAccountListCommandAPIError(t *testing.T) {
|
|
84
|
+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
85
|
+
w.WriteHeader(http.StatusInternalServerError)
|
|
86
|
+
w.Write([]byte("Internal Server Error"))
|
|
87
|
+
}))
|
|
88
|
+
defer server.Close()
|
|
89
|
+
|
|
90
|
+
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
91
|
+
testApp := &app.App{Client: client}
|
|
92
|
+
|
|
93
|
+
cmd := accountListCmd
|
|
94
|
+
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
95
|
+
|
|
96
|
+
err := handleListAccounts(cmd)
|
|
97
|
+
if err == nil {
|
|
98
|
+
t.Errorf("expected error for API failure")
|
|
99
|
+
}
|
|
100
|
+
if err.Error() != "fetching accounts: unexpected status code 500: Internal Server Error" {
|
|
101
|
+
t.Errorf("expected API error, got %v", err)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
func TestAccountListCommandNoClient(t *testing.T) {
|
|
106
|
+
testApp := &app.App{}
|
|
107
|
+
|
|
108
|
+
cmd := accountListCmd
|
|
109
|
+
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
110
|
+
|
|
111
|
+
err := handleListAccounts(cmd)
|
|
112
|
+
if err == nil {
|
|
113
|
+
t.Errorf("expected error when client not available")
|
|
114
|
+
}
|
|
115
|
+
if err.Error() != "API client not available" {
|
|
116
|
+
t.Errorf("expected 'client not available' error, got %v", err)
|
|
117
|
+
}
|
|
118
|
+
}
|
package/cmd/board.go
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
|
+
// Package cmd
|
|
1
2
|
package cmd
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
import (
|
|
5
|
+
"context"
|
|
6
|
+
"fmt"
|
|
7
|
+
|
|
8
|
+
"github.com/rogeriopvl/fizzy/internal/app"
|
|
9
|
+
"github.com/rogeriopvl/fizzy/internal/ui"
|
|
10
|
+
"github.com/spf13/cobra"
|
|
11
|
+
)
|
|
4
12
|
|
|
5
13
|
var boardCmd = &cobra.Command{
|
|
6
14
|
Use: "board",
|
|
7
|
-
Short: "
|
|
8
|
-
Long: `
|
|
15
|
+
Short: "Show the currently selected board",
|
|
16
|
+
Long: `Display the name and ID of the currently selected board.
|
|
17
|
+
|
|
18
|
+
Use subcommands to list, create, or manage boards:
|
|
19
|
+
fizzy board list List all boards
|
|
20
|
+
fizzy board create Create a new board`,
|
|
21
|
+
Run: func(cmd *cobra.Command, args []string) {
|
|
22
|
+
if err := handleShowBoard(cmd); err != nil {
|
|
23
|
+
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
24
|
+
}
|
|
25
|
+
},
|
|
9
26
|
}
|
|
10
27
|
|
|
11
|
-
func
|
|
12
|
-
|
|
28
|
+
func handleShowBoard(cmd *cobra.Command) error {
|
|
29
|
+
a := app.FromContext(cmd.Context())
|
|
30
|
+
if a == nil || a.Client == nil {
|
|
31
|
+
return fmt.Errorf("API client not available")
|
|
32
|
+
}
|
|
13
33
|
|
|
14
|
-
|
|
34
|
+
if a.Config.SelectedBoard == "" {
|
|
35
|
+
return fmt.Errorf("no board selected")
|
|
36
|
+
}
|
|
15
37
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
38
|
+
board, err := a.Client.GetBoard(context.Background(), a.Config.SelectedBoard)
|
|
39
|
+
if err != nil {
|
|
40
|
+
return fmt.Errorf("fetching board: %w", err)
|
|
41
|
+
}
|
|
19
42
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
43
|
+
fmt.Printf("%s (%s)\n", board.Name, ui.DisplayID(board.ID))
|
|
44
|
+
return nil
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func init() {
|
|
48
|
+
rootCmd.AddCommand(boardCmd)
|
|
23
49
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package cmd
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
|
|
7
|
+
"github.com/rogeriopvl/fizzy/internal/api"
|
|
8
|
+
"github.com/rogeriopvl/fizzy/internal/app"
|
|
9
|
+
"github.com/spf13/cobra"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
var (
|
|
13
|
+
boardName string
|
|
14
|
+
boardAllAccess bool
|
|
15
|
+
boardAutoPostponePeriod int
|
|
16
|
+
boardPublicDescription string
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
var boardCreateCmd = &cobra.Command{
|
|
20
|
+
Use: "create",
|
|
21
|
+
Short: "Create a new board",
|
|
22
|
+
Long: `Create a new board in Fizzy`,
|
|
23
|
+
Run: func(cmd *cobra.Command, args []string) {
|
|
24
|
+
if err := handleCreateBoard(cmd); err != nil {
|
|
25
|
+
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func handleCreateBoard(cmd *cobra.Command) error {
|
|
31
|
+
a := app.FromContext(cmd.Context())
|
|
32
|
+
if a == nil || a.Client == nil {
|
|
33
|
+
return fmt.Errorf("API client not available")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
payload := api.CreateBoardPayload{
|
|
37
|
+
Name: boardName,
|
|
38
|
+
AllAccess: boardAllAccess,
|
|
39
|
+
AutoPostponePeriod: boardAutoPostponePeriod,
|
|
40
|
+
PublicDescription: boardPublicDescription,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_, err := a.Client.PostBoards(context.Background(), payload)
|
|
44
|
+
if err != nil {
|
|
45
|
+
return fmt.Errorf("creating board: %w", err)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fmt.Printf("✓ Board '%s' created successfully\n", boardName)
|
|
49
|
+
return nil
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func init() {
|
|
53
|
+
boardCreateCmd.Flags().StringVarP(&boardName, "name", "n", "", "Board name (required)")
|
|
54
|
+
boardCreateCmd.MarkFlagRequired("name")
|
|
55
|
+
boardCreateCmd.Flags().BoolVar(&boardAllAccess, "all-access", false, "Allow all access to the board")
|
|
56
|
+
boardCreateCmd.Flags().IntVar(&boardAutoPostponePeriod, "auto-postpone-period", 0, "Auto postpone period in days")
|
|
57
|
+
boardCreateCmd.Flags().StringVar(&boardPublicDescription, "description", "", "Public description of the board")
|
|
58
|
+
|
|
59
|
+
boardCmd.AddCommand(boardCreateCmd)
|
|
60
|
+
}
|