package api import ( "fmt" "io" "net/http" "time" "github.com/claudia/docs-cli/pkg/types" ) // FoldersClient handles folder API calls type FoldersClient struct { client *Client } // NewFoldersClient creates a new folders client func NewFoldersClient(c *Client) *FoldersClient { return &FoldersClient{client: c} } // List lists folders in a project func (f *FoldersClient) List(projectID, parentID string) ([]types.Folder, error) { path := "/projects/" + projectID + "/folders" if parentID != "" { path += "?parent_id=" + parentID } resp, err := f.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 folderResp types.Response if err := decodeJSON(body, &folderResp); err != nil { return nil, err } return sliceToFolders(folderResp.Data), nil } // Create creates a new folder func (f *FoldersClient) Create(projectID string, req types.CreateFolderRequest) (*types.Folder, error) { resp, err := f.client.doRequest(http.MethodPost, "/projects/"+projectID+"/folders", req) 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.StatusCreated && resp.StatusCode != http.StatusOK { return nil, handleError(resp, body) } var folderResp types.Response if err := decodeJSON(body, &folderResp); err != nil { return nil, err } folder, ok := folderResp.Data.(map[string]interface{}) if !ok { return nil, fmt.Errorf("unexpected response format") } return mapToFolder(folder), nil } // Get gets a folder by ID func (f *FoldersClient) Get(id string) (*types.Folder, error) { resp, err := f.client.doRequest(http.MethodGet, "/folders/"+id, 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 folderResp types.Response if err := decodeJSON(body, &folderResp); err != nil { return nil, err } folder, ok := folderResp.Data.(map[string]interface{}) if !ok { return nil, fmt.Errorf("unexpected response format") } return mapToFolder(folder), nil } func mapToFolder(m map[string]interface{}) *types.Folder { folder := &types.Folder{} if v, ok := m["id"].(string); ok { folder.ID = v } if v, ok := m["name"].(string); ok { folder.Name = v } if v, ok := m["project_id"].(string); ok { folder.ProjectID = v } if v, ok := m["parent_id"].(string); ok { folder.ParentID = v } if v, ok := m["created_at"].(string); ok { folder.CreatedAt, _ = time.Parse(time.RFC3339, v) } if v, ok := m["updated_at"].(string); ok { folder.UpdatedAt, _ = time.Parse(time.RFC3339, v) } return folder } func sliceToFolders(data interface{}) []types.Folder { var folders []types.Folder if arr, ok := data.([]interface{}); ok { for _, item := range arr { if m, ok := item.(map[string]interface{}); ok { folders = append(folders, *mapToFolder(m)) } } } return folders }