Initial MVP implementation of Claudia Docs CLI
- Auth commands: login, logout, status - Document commands: create, list, get, update, delete - Project commands: list, get - Folder commands: list, create - Tag commands: list, create, add - Search command - Reasoning save command - JSON output format with --output text option - Viper-based configuration management - Cobra CLI framework
This commit is contained in:
72
internal/api/search.go
Normal file
72
internal/api/search.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/claudia/docs-cli/pkg/types"
|
||||
)
|
||||
|
||||
// SearchClient handles search API calls
|
||||
type SearchClient struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// NewSearchClient creates a new search client
|
||||
func NewSearchClient(c *Client) *SearchClient {
|
||||
return &SearchClient{client: c}
|
||||
}
|
||||
|
||||
// Search performs a full-text search
|
||||
func (s *SearchClient) Search(query, projectID, tags string) (*types.SearchResult, error) {
|
||||
params := url.Values{}
|
||||
params.Set("q", query)
|
||||
if projectID != "" {
|
||||
params.Set("project_id", projectID)
|
||||
}
|
||||
if tags != "" {
|
||||
params.Set("tags", tags)
|
||||
}
|
||||
|
||||
path := "/search?" + params.Encode()
|
||||
resp, err := s.client.doRequest(http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, handleError(resp, body)
|
||||
}
|
||||
|
||||
var searchResp types.Response
|
||||
if err := decodeJSON(body, &searchResp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mapToSearchResult(searchResp.Data, query), nil
|
||||
}
|
||||
|
||||
func mapToSearchResult(data interface{}, query string) *types.SearchResult {
|
||||
result := &types.SearchResult{Query: query}
|
||||
if m, ok := data.(map[string]interface{}); ok {
|
||||
if v, ok := m["documents"].([]interface{}); ok {
|
||||
for _, item := range v {
|
||||
if doc, ok := item.(map[string]interface{}); ok {
|
||||
result.Documents = append(result.Documents, *mapToDocument(doc))
|
||||
}
|
||||
}
|
||||
}
|
||||
if v, ok := m["total"].(float64); ok {
|
||||
result.Total = int(v)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user