diff --git a/internal/api/client.go b/internal/api/client.go index 5dbb6b0..0ec49f3 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -11,6 +11,8 @@ import ( "time" ) +const defaultListPageSize = 250 + // Client is the n8n API client type Client struct { baseURL string @@ -170,8 +172,8 @@ func (c *Client) request(method, path string, body interface{}) ([]byte, error) return respBody, nil } -// ListWorkflows returns all workflows -func (c *Client) ListWorkflows(opts ListWorkflowsOptions) (*ListResult[Workflow], error) { +// listWorkflowsPage fetches a single page of workflows. +func (c *Client) listWorkflowsPage(opts ListWorkflowsOptions) (*ListResult[Workflow], error) { params := url.Values{} if opts.Limit > 0 { params.Set("limit", strconv.Itoa(opts.Limit)) @@ -213,6 +215,39 @@ func (c *Client) ListWorkflows(opts ListWorkflowsOptions) (*ListResult[Workflow] return &resp, nil } +// ListWorkflows returns all workflows, auto-paginating through all pages. +// If opts.Cursor is set, only that single page is returned (manual pagination). +func (c *Client) ListWorkflows(opts ListWorkflowsOptions) (*ListResult[Workflow], error) { + // Manual pagination: caller provided a cursor, return single page + if opts.Cursor != "" { + return c.listWorkflowsPage(opts) + } + + pageSize := opts.Limit + if pageSize <= 0 { + pageSize = defaultListPageSize + } + + var all []Workflow + pageOpts := opts + pageOpts.Limit = pageSize + + for { + page, err := c.listWorkflowsPage(pageOpts) + if err != nil { + return nil, err + } + all = append(all, page.Data...) + + if page.NextCursor == "" || len(page.Data) == 0 { + break + } + pageOpts.Cursor = page.NextCursor + } + + return &ListResult[Workflow]{Data: all}, nil +} + // GetWorkflow returns a workflow by ID func (c *Client) GetWorkflow(id string) (*Workflow, error) { respBody, err := c.request(http.MethodGet, "/workflows/"+url.PathEscape(id), nil) diff --git a/internal/cmd/workflow/workflow.go b/internal/cmd/workflow/workflow.go index b776d5e..66461bc 100644 --- a/internal/cmd/workflow/workflow.go +++ b/internal/cmd/workflow/workflow.go @@ -108,10 +108,6 @@ func newListCmd() *cobra.Command { fmt.Printf("%-18s %-6s %s\n", wf.ID, activeStr, wf.Name) } - if result.NextCursor != "" { - fmt.Printf("\nMore results available. Use --cursor %s to continue.\n", result.NextCursor) - } - return nil }, } @@ -119,8 +115,8 @@ func newListCmd() *cobra.Command { cmd.Flags().BoolVar(&active, "active", false, "Show only active workflows") cmd.Flags().BoolVar(&inactive, "inactive", false, "Show only inactive workflows") cmd.Flags().StringSliceVar(&tags, "tag", nil, "Filter by tag (can be repeated)") - cmd.Flags().IntVar(&limit, "limit", 100, "Maximum number of workflows to return") - cmd.Flags().StringVar(&cursor, "cursor", "", "Pagination cursor for next page") + cmd.Flags().IntVar(&limit, "limit", 0, "Page size per API request (0 = default)") + cmd.Flags().StringVar(&cursor, "cursor", "", "Pagination cursor (fetches single page only)") cmd.Flags().StringVar(&projectID, "project", "", "Filter by project ID") cmd.Flags().StringVar(&name, "name", "", "Filter by workflow name")