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.
This commit is contained in:
Steve Yegge
2025-12-29 14:04:20 -08:00
parent 2c57d41275
commit 96c7cceefc
3 changed files with 17 additions and 45 deletions

View File

@@ -105,15 +105,7 @@ var showCmd = &cobra.Command{
} }
if jsonOutput { if jsonOutput {
// Get labels and deps for JSON output // Get labels and deps for JSON output
type IssueDetails struct { details := &types.IssueDetails{Issue: *issue}
*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.Labels, _ = issueStore.GetLabels(ctx, issue.ID) details.Labels, _ = issueStore.GetLabels(ctx, issue.ID)
if sqliteStore, ok := issueStore.(*sqlite.SQLiteStorage); ok { if sqliteStore, ok := issueStore.(*sqlite.SQLiteStorage); ok {
details.Dependencies, _ = sqliteStore.GetDependenciesWithMetadata(ctx, issue.ID) details.Dependencies, _ = sqliteStore.GetDependenciesWithMetadata(ctx, issue.ID)
@@ -155,15 +147,7 @@ var showCmd = &cobra.Command{
} }
if jsonOutput { if jsonOutput {
type IssueDetails struct { var details types.IssueDetails
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
if err := json.Unmarshal(resp.Data, &details); err == nil { if err := json.Unmarshal(resp.Data, &details); err == nil {
// Compute parent from dependencies // Compute parent from dependencies
for _, dep := range details.Dependencies { for _, dep := range details.Dependencies {
@@ -182,14 +166,7 @@ var showCmd = &cobra.Command{
} }
// Parse response first to check shortMode before output // Parse response first to check shortMode before output
type IssueDetails struct { var details types.IssueDetails
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
if err := json.Unmarshal(resp.Data, &details); err != nil { if err := json.Unmarshal(resp.Data, &details); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err) fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
os.Exit(1) os.Exit(1)
@@ -380,15 +357,7 @@ var showCmd = &cobra.Command{
if jsonOutput { if jsonOutput {
// Include labels, dependencies (with metadata), dependents (with metadata), and comments in JSON output // Include labels, dependencies (with metadata), dependents (with metadata), and comments in JSON output
type IssueDetails struct { details := &types.IssueDetails{Issue: *issue}
*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.Labels, _ = issueStore.GetLabels(ctx, issue.ID) details.Labels, _ = issueStore.GetLabels(ctx, issue.ID)
// Get dependencies with metadata (dependency_type field) // Get dependencies with metadata (dependency_type field)

View File

@@ -1305,16 +1305,8 @@ func (s *Server) handleShow(req *Request) Response {
comments, _ := store.GetIssueComments(ctx, issue.ID) comments, _ := store.GetIssueComments(ctx, issue.ID)
// Create detailed response with related data // Create detailed response with related data
type IssueDetails struct { details := &types.IssueDetails{
*types.Issue Issue: *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,
Labels: labels, Labels: labels,
Dependencies: deps, Dependencies: deps,
Dependents: dependents, Dependents: dependents,

View File

@@ -483,6 +483,17 @@ type IssueWithCounts struct {
DependentCount int `json:"dependent_count"` 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 // DependencyType categorizes the relationship
type DependencyType string type DependencyType string