From 96c7cceefcb62e723417d720c40dadfde74d4df4 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Mon, 29 Dec 2025 14:04:20 -0800 Subject: [PATCH] refactor: Extract IssueDetails to shared type (bd-6dnt) Consolidated 5 duplicate IssueDetails struct definitions into a single types.IssueDetails in internal/types/types.go: - Removed 4 inline definitions from cmd/bd/show.go - Removed 1 inline definition from internal/rpc/server_issues_epics.go The shared type embeds types.Issue by value and includes: Labels, Dependencies, Dependents, Comments, and Parent fields. This improves maintainability and reduces risk of inconsistency. --- cmd/bd/show.go | 39 +++-------------------------- internal/rpc/server_issues_epics.go | 12 ++------- internal/types/types.go | 11 ++++++++ 3 files changed, 17 insertions(+), 45 deletions(-) diff --git a/cmd/bd/show.go b/cmd/bd/show.go index 9f789469..665a3f24 100644 --- a/cmd/bd/show.go +++ b/cmd/bd/show.go @@ -105,15 +105,7 @@ var showCmd = &cobra.Command{ } if jsonOutput { // Get labels and deps for JSON output - type IssueDetails struct { - *types.Issue - Labels []string `json:"labels,omitempty"` - Dependencies []*types.IssueWithDependencyMetadata `json:"dependencies,omitempty"` - Dependents []*types.IssueWithDependencyMetadata `json:"dependents,omitempty"` - Comments []*types.Comment `json:"comments,omitempty"` - Parent *string `json:"parent,omitempty"` - } - details := &IssueDetails{Issue: issue} + details := &types.IssueDetails{Issue: *issue} details.Labels, _ = issueStore.GetLabels(ctx, issue.ID) if sqliteStore, ok := issueStore.(*sqlite.SQLiteStorage); ok { details.Dependencies, _ = sqliteStore.GetDependenciesWithMetadata(ctx, issue.ID) @@ -155,15 +147,7 @@ var showCmd = &cobra.Command{ } if jsonOutput { - type IssueDetails struct { - types.Issue - Labels []string `json:"labels,omitempty"` - Dependencies []*types.IssueWithDependencyMetadata `json:"dependencies,omitempty"` - Dependents []*types.IssueWithDependencyMetadata `json:"dependents,omitempty"` - Comments []*types.Comment `json:"comments,omitempty"` - Parent *string `json:"parent,omitempty"` - } - var details IssueDetails + var details types.IssueDetails if err := json.Unmarshal(resp.Data, &details); err == nil { // Compute parent from dependencies for _, dep := range details.Dependencies { @@ -182,14 +166,7 @@ var showCmd = &cobra.Command{ } // Parse response first to check shortMode before output - type IssueDetails struct { - types.Issue - Labels []string `json:"labels,omitempty"` - Dependencies []*types.IssueWithDependencyMetadata `json:"dependencies,omitempty"` - Dependents []*types.IssueWithDependencyMetadata `json:"dependents,omitempty"` - Comments []*types.Comment `json:"comments,omitempty"` - } - var details IssueDetails + var details types.IssueDetails if err := json.Unmarshal(resp.Data, &details); err != nil { fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err) os.Exit(1) @@ -380,15 +357,7 @@ var showCmd = &cobra.Command{ if jsonOutput { // Include labels, dependencies (with metadata), dependents (with metadata), and comments in JSON output - type IssueDetails struct { - *types.Issue - Labels []string `json:"labels,omitempty"` - Dependencies []*types.IssueWithDependencyMetadata `json:"dependencies,omitempty"` - Dependents []*types.IssueWithDependencyMetadata `json:"dependents,omitempty"` - Comments []*types.Comment `json:"comments,omitempty"` - Parent *string `json:"parent,omitempty"` - } - details := &IssueDetails{Issue: issue} + details := &types.IssueDetails{Issue: *issue} details.Labels, _ = issueStore.GetLabels(ctx, issue.ID) // Get dependencies with metadata (dependency_type field) diff --git a/internal/rpc/server_issues_epics.go b/internal/rpc/server_issues_epics.go index f5a4ee71..ec4514b9 100644 --- a/internal/rpc/server_issues_epics.go +++ b/internal/rpc/server_issues_epics.go @@ -1305,16 +1305,8 @@ func (s *Server) handleShow(req *Request) Response { comments, _ := store.GetIssueComments(ctx, issue.ID) // Create detailed response with related data - type IssueDetails struct { - *types.Issue - Labels []string `json:"labels,omitempty"` - Dependencies []*types.IssueWithDependencyMetadata `json:"dependencies,omitempty"` - Dependents []*types.IssueWithDependencyMetadata `json:"dependents,omitempty"` - Comments []*types.Comment `json:"comments,omitempty"` - } - - details := &IssueDetails{ - Issue: issue, + details := &types.IssueDetails{ + Issue: *issue, Labels: labels, Dependencies: deps, Dependents: dependents, diff --git a/internal/types/types.go b/internal/types/types.go index f3672451..d7710b6d 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -483,6 +483,17 @@ type IssueWithCounts struct { DependentCount int `json:"dependent_count"` } +// IssueDetails extends Issue with labels, dependencies, dependents, and comments. +// Used for JSON serialization in bd show and RPC responses. +type IssueDetails struct { + Issue + Labels []string `json:"labels,omitempty"` + Dependencies []*IssueWithDependencyMetadata `json:"dependencies,omitempty"` + Dependents []*IssueWithDependencyMetadata `json:"dependents,omitempty"` + Comments []*Comment `json:"comments,omitempty"` + Parent *string `json:"parent,omitempty"` +} + // DependencyType categorizes the relationship type DependencyType string