Skip to content

Commit cdc4894

Browse files
authored
Merge pull request #160 from basecamp/adopt-search-service
Repurpose fizzy search to call the dedicated FTS endpoint
2 parents 6976c76 + 89386c9 commit cdc4894

7 files changed

Lines changed: 80 additions & 225 deletions

File tree

SURFACE.txt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,24 +2353,17 @@ FLAG fizzy reaction rm --styled type=bool
23532353
FLAG fizzy reaction rm --token type=string
23542354
FLAG fizzy reaction rm --verbose type=bool
23552355
FLAG fizzy search --agent type=bool
2356-
FLAG fizzy search --all type=bool
23572356
FLAG fizzy search --api-url type=string
2358-
FLAG fizzy search --assignee type=string
2359-
FLAG fizzy search --board type=string
23602357
FLAG fizzy search --count type=bool
23612358
FLAG fizzy search --help type=bool
23622359
FLAG fizzy search --ids-only type=bool
2363-
FLAG fizzy search --indexed-by type=string
23642360
FLAG fizzy search --jq type=string
23652361
FLAG fizzy search --json type=bool
23662362
FLAG fizzy search --limit type=int
23672363
FLAG fizzy search --markdown type=bool
2368-
FLAG fizzy search --page type=int
23692364
FLAG fizzy search --profile type=string
23702365
FLAG fizzy search --quiet type=bool
2371-
FLAG fizzy search --sort type=string
23722366
FLAG fizzy search --styled type=bool
2373-
FLAG fizzy search --tag type=string
23742367
FLAG fizzy search --token type=string
23752368
FLAG fizzy search --verbose type=bool
23762369
FLAG fizzy setup --agent type=bool

e2e/cli_tests/search_and_auth_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@ import (
88

99
func TestSearch(t *testing.T) {
1010
h := newHarness(t)
11+
// Single-token query
1112
assertOK(t, h.Run("search", "test"))
12-
assertOK(t, h.Run("search", "test", "--board", fixture.BoardID))
13-
assertOK(t, h.Run("search", "test", "--all"))
13+
// Multi-arg joined into a single q string
14+
assertOK(t, h.Run("search", "login", "error"))
15+
}
16+
17+
func TestCardListWithSearch(t *testing.T) {
18+
// Filter use cases that used to live on `fizzy search` now belong here.
19+
h := newHarness(t)
20+
assertOK(t, h.Run("card", "list", "--search", "test", "--board", fixture.BoardID))
21+
assertOK(t, h.Run("card", "list", "--search", "test", "--all"))
1422
}
1523

1624
func TestAuthInvalidToken(t *testing.T) {

internal/commands/help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ var commandExamples = map[string]string{
405405
"fizzy config show": "$ fizzy config show\n$ fizzy config show --verbose",
406406
"fizzy config explain": "$ fizzy config explain\n$ fizzy config explain --profile acme",
407407
"fizzy doctor": "$ fizzy doctor\n$ fizzy doctor --profile acme\n$ fizzy doctor --all-profiles",
408-
"fizzy search": "$ fizzy search \"billing bug\"\n$ fizzy search \"billing bug\" --board <id>",
408+
"fizzy search": "$ fizzy search \"billing bug\"\n$ fizzy search <card-id>",
409409
"fizzy notification": "$ fizzy notification tray\n$ fizzy notification list",
410410
"fizzy notification tray": "$ fizzy notification tray",
411411
"fizzy user": "$ fizzy user list\n$ fizzy user show <id>",

internal/commands/search.go

Lines changed: 16 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,118 +2,49 @@ package commands
22

33
import (
44
"fmt"
5-
"strconv"
65
"strings"
76

87
"github.com/spf13/cobra"
98
)
109

11-
// Search flags
12-
var searchBoard string
13-
var searchTag string
14-
var searchAssignee string
15-
var searchIndexedBy string
16-
var searchSort string
17-
var searchPage int
18-
var searchAll bool
19-
2010
var searchCmd = &cobra.Command{
21-
Use: "search QUERY",
11+
Use: "search QUERY...",
2212
Short: "Search cards",
23-
Long: "Searches cards by text. Multiple words are treated as separate terms (AND).",
24-
Args: cobra.MinimumNArgs(1),
13+
Long: `Searches cards using the dedicated full-text search endpoint.
14+
15+
The query is sent as a single string. If the query exactly matches a card ID,
16+
that card is returned directly.
17+
18+
To filter cards by structured criteria (board, tag, assignee, status, etc.),
19+
use 'fizzy card list' with --search and the relevant filter flags.`,
20+
Args: cobra.MinimumNArgs(1),
2521
RunE: func(cmd *cobra.Command, args []string) error {
2622
if err := requireAuthAndAccount(); err != nil {
2723
return err
2824
}
29-
if err := checkLimitAll(searchAll); err != nil {
30-
return err
31-
}
3225

3326
query := strings.Join(args, " ")
3427

3528
ac := getSDK()
36-
path := "/cards.json"
37-
38-
var params []string
39-
40-
// Add search terms
41-
for term := range strings.FieldsSeq(query) {
42-
params = append(params, "terms[]="+term)
29+
raw, _, err := ac.Search().Search(cmd.Context(), &query)
30+
if err != nil {
31+
return convertSDKError(err)
4332
}
4433

45-
// Add optional filters (search is cross-board by default;
46-
// only scope to a board when explicitly requested via --board)
47-
if searchBoard != "" {
48-
params = append(params, "board_ids[]="+searchBoard)
49-
}
50-
if searchTag != "" {
51-
params = append(params, "tag_ids[]="+searchTag)
52-
}
53-
if searchAssignee != "" {
54-
params = append(params, "assignee_ids[]="+searchAssignee)
55-
}
56-
if searchIndexedBy != "" {
57-
params = append(params, "indexed_by="+searchIndexedBy)
58-
}
59-
if searchSort != "" {
60-
params = append(params, "sorted_by="+searchSort)
61-
}
62-
if searchPage > 0 {
63-
params = append(params, "page="+strconv.Itoa(searchPage))
64-
}
65-
66-
if len(params) > 0 {
67-
path += "?" + strings.Join(params, "&")
68-
}
69-
70-
var items any
71-
var linkNext string
72-
73-
if searchAll {
74-
pages, err := ac.GetAll(cmd.Context(), path)
75-
if err != nil {
76-
return convertSDKError(err)
77-
}
78-
items = jsonAnySlice(pages)
79-
} else {
80-
data, resp, err := ac.Cards().List(cmd.Context(), path)
81-
if err != nil {
82-
return convertSDKError(err)
83-
}
84-
items = normalizeAny(data)
85-
linkNext = parseSDKLinkNext(resp)
86-
}
87-
88-
// Build summary
34+
items := normalizeAny(raw)
8935
count := dataCount(items)
90-
summary := fmt.Sprintf("%d results for \"%s\"", count, query)
91-
if searchAll {
92-
summary = fmt.Sprintf("%d results for \"%s\" (all)", count, query)
93-
} else if searchPage > 0 {
94-
summary = fmt.Sprintf("%d results for \"%s\" (page %d)", count, query, searchPage)
95-
}
36+
summary := fmt.Sprintf("%d results for %q", count, query)
9637

97-
// Build breadcrumbs
9838
breadcrumbs := []Breadcrumb{
9939
breadcrumb("show", "fizzy card show <number>", "View card details"),
100-
breadcrumb("narrow", fmt.Sprintf("fizzy search \"%s\" --board <id>", query), "Filter by board"),
40+
breadcrumb("filter", fmt.Sprintf("fizzy card list --search %q --board <id>", query), "Filter cards by criteria"),
10141
}
10242

103-
hasNext := linkNext != ""
104-
printListPaginated(items, searchColumns, hasNext, linkNext, searchAll, summary, breadcrumbs)
43+
printList(items, searchColumns, summary, breadcrumbs)
10544
return nil
10645
},
10746
}
10847

10948
func init() {
11049
rootCmd.AddCommand(searchCmd)
111-
112-
searchCmd.Flags().StringVar(&searchBoard, "board", "", "Filter by board ID")
113-
searchCmd.Flags().StringVar(&searchTag, "tag", "", "Filter by tag ID")
114-
searchCmd.Flags().StringVar(&searchAssignee, "assignee", "", "Filter by assignee ID")
115-
searchCmd.Flags().StringVar(&searchIndexedBy, "indexed-by", "", "Filter by status (all, closed, maybe, not_now, golden)")
116-
searchCmd.Flags().StringVar(&searchSort, "sort", "", "Sort order: newest, oldest, or latest (default)")
117-
searchCmd.Flags().IntVar(&searchPage, "page", 0, "Page number")
118-
searchCmd.Flags().BoolVar(&searchAll, "all", false, "Fetch all pages")
11950
}

0 commit comments

Comments
 (0)