From 19514f5b510e81ecd361c06687e614adbf9af107 Mon Sep 17 00:00:00 2001 From: Hinne Stolzenberg Date: Sun, 22 Mar 2026 16:47:26 +0100 Subject: [PATCH 1/2] fix: include folders in confluence page children output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v2 /pages/{id}/children endpoint only returns pages, not folders. This caused --type folder to always return empty results, and the default children list to silently omit folders like WIP, Certs, etc. Fix: - Add GetChildFolders() that uses v1 CQL search (parent = {id} AND type = folder) to fetch child folders - Merge folder results into children output alongside pages - Set Type field to "page" for v2 results (API returns empty string) - Skip folder fetch when --type page is specified (optimization) Before: atl confluence page children 33554434 → 3 results (pages only) After: atl confluence page children 33554434 → 6 results (3 pages + 3 folders) --- internal/api/confluence.go | 29 ++++++++++++++++++++++++ internal/cmd/confluence/page/children.go | 8 +++++++ 2 files changed, 37 insertions(+) diff --git a/internal/api/confluence.go b/internal/api/confluence.go index c2fa87a..2068bc7 100644 --- a/internal/api/confluence.go +++ b/internal/api/confluence.go @@ -702,9 +702,38 @@ func (s *ConfluenceService) GetPageChildren(ctx context.Context, pageID string, return nil, err } + // v2 API returns empty Type for pages — set it explicitly + for _, child := range result.Results { + if child.Type == "" { + child.Type = "page" + } + } + return &result, nil } +// GetChildFolders gets immediate child folders of a page using CQL search. +// The v2 /pages/{id}/children endpoint only returns pages, not folders. +// This uses v1 CQL search with "parent = {id} AND type = folder" as a workaround. +func (s *ConfluenceService) GetChildFolders(ctx context.Context, pageID string) ([]*PageChild, error) { + cql := fmt.Sprintf("parent = %s AND type = folder", pageID) + searchResult, err := s.SearchWithCQL(ctx, cql, 100, "") + if err != nil { + return nil, err + } + + folders := make([]*PageChild, 0, len(searchResult.Results)) + for _, r := range searchResult.Results { + folders = append(folders, &PageChild{ + ID: r.ID, + Title: r.Title, + Status: r.Status, + Type: "folder", + }) + } + return folders, nil +} + // GetPageDescendants gets all descendants of a page (children, grandchildren, etc.). func (s *ConfluenceService) GetPageDescendants(ctx context.Context, pageID string, limit int, cursor string) (*ChildrenResponse, error) { path := fmt.Sprintf("%s/pages/%s/descendants", s.baseURL(), pageID) diff --git a/internal/cmd/confluence/page/children.go b/internal/cmd/confluence/page/children.go index b510190..5522175 100644 --- a/internal/cmd/confluence/page/children.go +++ b/internal/cmd/confluence/page/children.go @@ -118,6 +118,14 @@ func runChildren(opts *ChildrenOptions) error { return fmt.Errorf("failed to get children: %w", err) } children = result.Results + + // Also fetch child folders (v2 API only returns pages, not folders) + if opts.Type == "" || opts.Type == "folder" { + folders, folderErr := confluence.GetChildFolders(ctx, opts.PageID) + if folderErr == nil { + children = append(children, folders...) + } + } } if err != nil { From 90574dd283956bee04a5cbcc37d82ae9851dff5d Mon Sep 17 00:00:00 2001 From: Hinne Stolzenberg Date: Sun, 22 Mar 2026 16:53:39 +0100 Subject: [PATCH 2/2] fix: warn on folder fetch failure, document pagination limit --- internal/api/confluence.go | 1 + internal/cmd/confluence/page/children.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/api/confluence.go b/internal/api/confluence.go index 2068bc7..f4389bc 100644 --- a/internal/api/confluence.go +++ b/internal/api/confluence.go @@ -715,6 +715,7 @@ func (s *ConfluenceService) GetPageChildren(ctx context.Context, pageID string, // GetChildFolders gets immediate child folders of a page using CQL search. // The v2 /pages/{id}/children endpoint only returns pages, not folders. // This uses v1 CQL search with "parent = {id} AND type = folder" as a workaround. +// Limited to 100 results (no pagination) — sufficient for practical use. func (s *ConfluenceService) GetChildFolders(ctx context.Context, pageID string) ([]*PageChild, error) { cql := fmt.Sprintf("parent = %s AND type = folder", pageID) searchResult, err := s.SearchWithCQL(ctx, cql, 100, "") diff --git a/internal/cmd/confluence/page/children.go b/internal/cmd/confluence/page/children.go index 5522175..8b70450 100644 --- a/internal/cmd/confluence/page/children.go +++ b/internal/cmd/confluence/page/children.go @@ -122,7 +122,9 @@ func runChildren(opts *ChildrenOptions) error { // Also fetch child folders (v2 API only returns pages, not folders) if opts.Type == "" || opts.Type == "folder" { folders, folderErr := confluence.GetChildFolders(ctx, opts.PageID) - if folderErr == nil { + if folderErr != nil { + fmt.Fprintf(opts.IO.ErrOut, "Warning: could not fetch child folders: %v\n", folderErr) + } else { children = append(children, folders...) } }