refactor services to use Interface and change name to app
This commit is contained in:
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/LazyBachelor/LazyPM/pkg/cli/commands"
|
||||
)
|
||||
|
||||
// CLIConfig is an alias for service.Config, used to configure the CLI.
|
||||
type CLIConfig = service.Config
|
||||
// Config is an alias for service.Config, used to configure the CLI.
|
||||
type Config = service.Config
|
||||
|
||||
type CLI struct{}
|
||||
|
||||
@@ -18,15 +18,15 @@ func NewCli() *CLI {
|
||||
}
|
||||
|
||||
// Run initializes the services and executes the CLI commands.
|
||||
func (c *CLI) Run(ctx context.Context, config CLIConfig) error {
|
||||
svc, cleanup, err := service.NewServices(ctx, config)
|
||||
func (c *CLI) Run(ctx context.Context, config Config) error {
|
||||
app, cleanup, err := service.NewServices(ctx, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer cleanup()
|
||||
|
||||
commands.SetServices(svc)
|
||||
commands.SetApp(app)
|
||||
|
||||
if err := commands.Execute(); err != nil {
|
||||
return err
|
||||
@@ -36,15 +36,15 @@ func (c *CLI) Run(ctx context.Context, config CLIConfig) error {
|
||||
}
|
||||
|
||||
// RunWithArgs initializes the services and executes the CLI commands with the provided arguments.
|
||||
func (c *CLI) RunWithArgs(ctx context.Context, config CLIConfig, args []string) error {
|
||||
svc, cleanup, err := service.NewServices(ctx, config)
|
||||
func (c *CLI) RunWithArgs(ctx context.Context, config Config, args []string) error {
|
||||
app, cleanup, err := service.NewServices(ctx, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer cleanup()
|
||||
|
||||
commands.SetServices(svc)
|
||||
commands.SetApp(app)
|
||||
|
||||
if err := commands.ExecuteArgs(args); err != nil {
|
||||
return err
|
||||
|
||||
@@ -30,8 +30,10 @@ func runCloseCmd(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("issue ID cannot be empty")
|
||||
}
|
||||
|
||||
app := AppFromContext(cmd.Context())
|
||||
|
||||
// Fetch the issue to ensure it exists before closing.
|
||||
issue, err := svc.Beads.GetIssue(cmd.Context(), closeID)
|
||||
issue, err := app.Issues.GetIssue(cmd.Context(), closeID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching issue: %w", err)
|
||||
}
|
||||
@@ -47,7 +49,7 @@ func runCloseCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Close the issue.
|
||||
err = svc.Beads.CloseIssue(cmd.Context(), closeID, issue.CloseReason, "", "")
|
||||
err = app.Issues.CloseIssue(cmd.Context(), closeID, issue.CloseReason, "", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error closing issue: %w", err)
|
||||
}
|
||||
|
||||
@@ -34,11 +34,12 @@ func completeIssues(cmd *cobra.Command, args []string, toComplete string) ([]str
|
||||
|
||||
// GetIssueCompletions fetches issues matching the toComplete string for shell completion.
|
||||
func GetIssueCompletions(ctx context.Context, toComplete string) ([]models.Issue, cobra.ShellCompDirective) {
|
||||
if svc == nil {
|
||||
app := AppFromContext(ctx)
|
||||
if app == nil {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
issues, err := svc.Beads.AllIssues(ctx)
|
||||
issues, err := app.Issues.AllIssues(ctx)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ func runCreateCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Create the issue using the service layer.
|
||||
err := svc.Beads.CreateIssue(cmd.Context(), issue, "test_actor")
|
||||
app := AppFromContext(cmd.Context())
|
||||
err := app.Issues.CreateIssue(cmd.Context(), issue, "test_actor")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating issue: %w", err)
|
||||
}
|
||||
|
||||
@@ -46,8 +46,10 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("issue ID cannot be empty")
|
||||
}
|
||||
|
||||
app := AppFromContext(cmd.Context())
|
||||
|
||||
// Fetch the issue to ensure it exists before deletion.
|
||||
issue, err := svc.Beads.GetIssue(cmd.Context(), deleteID)
|
||||
issue, err := app.Issues.GetIssue(cmd.Context(), deleteID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching issue: %w", err)
|
||||
}
|
||||
@@ -70,7 +72,7 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Delete the issue.
|
||||
err = svc.Beads.DeleteIssue(cmd.Context(), deleteID)
|
||||
err = app.Issues.DeleteIssue(cmd.Context(), deleteID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting issue: %w", err)
|
||||
}
|
||||
@@ -83,9 +85,10 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
|
||||
// runDeleteInteractive runs the interactive mode for deleting issues,
|
||||
// allowing users to select multiple issues for deletion.
|
||||
func runDeleteInteractive(ctx context.Context) error {
|
||||
app := AppFromContext(ctx)
|
||||
options := []huh.Option[string]{}
|
||||
|
||||
issues, err := svc.Beads.SearchIssues(ctx, "", models.IssueFilter{})
|
||||
issues, err := app.Issues.SearchIssues(ctx, "", models.IssueFilter{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching issues: %w", err)
|
||||
}
|
||||
@@ -110,7 +113,7 @@ func runDeleteInteractive(ctx context.Context) error {
|
||||
}
|
||||
|
||||
for _, id := range deleteIDs {
|
||||
err := svc.Beads.DeleteIssue(ctx, id)
|
||||
err := app.Issues.DeleteIssue(ctx, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting issue with ID %s: %w", id, err)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ func runGetIssuesCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Fetch issues based on the search query and filters.
|
||||
issuesPtr, err := svc.Beads.SearchIssues(cmd.Context(), queryArg, filter)
|
||||
app := AppFromContext(cmd.Context())
|
||||
issuesPtr, err := app.Issues.SearchIssues(cmd.Context(), queryArg, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ func runGetCmd(cmd *cobra.Command, args []string) error {
|
||||
issueID := args[0]
|
||||
|
||||
// Fetch the issue details using the service layer.
|
||||
issuePtr, err := svc.Beads.GetIssue(cmd.Context(), issueID)
|
||||
app := AppFromContext(cmd.Context())
|
||||
issuePtr, err := app.Issues.GetIssue(cmd.Context(), issueID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,9 +10,12 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// svc is a global variable that holds beads, config and stats services.
|
||||
// Must be called before executing any commands to ensure services are available.
|
||||
var svc *service.Services
|
||||
type contextKey string
|
||||
|
||||
const appKey contextKey = "app"
|
||||
|
||||
// app is a package-level variable used during command setup
|
||||
var app *service.App
|
||||
|
||||
// Flags struct to hold command-line flag values for issues.
|
||||
type Flags struct {
|
||||
@@ -30,13 +33,28 @@ type Flags struct {
|
||||
var rootCmd = &cobra.Command{
|
||||
Short: "Project Management CLI",
|
||||
Long: `Project Management CLI for managing issues and tasks.`,
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
// Inject app into context for all commands
|
||||
if app != nil {
|
||||
cmd.SetContext(context.WithValue(cmd.Context(), appKey, app))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// SetServices sets the global services variable for use in command execution.
|
||||
// SetApp sets the app variable for use in command execution.
|
||||
// Must be called before executing any commands to ensure services are available.
|
||||
func SetServices(services *service.Services) {
|
||||
svc = services
|
||||
rootCmd.Use = svc.Config.RootCmd
|
||||
func SetApp(application *service.App) {
|
||||
app = application
|
||||
rootCmd.Use = app.Config.RootCmd
|
||||
}
|
||||
|
||||
// AppFromContext retrieves the App from the command context
|
||||
func AppFromContext(ctx context.Context) *service.App {
|
||||
if a, ok := ctx.Value(appKey).(*service.App); ok {
|
||||
return a
|
||||
}
|
||||
// Fallback to package-level app (for testing or edge cases)
|
||||
return app
|
||||
}
|
||||
|
||||
// Execute executes the root command using the fang library.
|
||||
|
||||
@@ -23,7 +23,9 @@ var updateCmd = &cobra.Command{
|
||||
func runUpdateCmd(cmd *cobra.Command, args []string) error {
|
||||
issueID := args[0]
|
||||
|
||||
issue, err := svc.Beads.GetIssue(cmd.Context(), issueID)
|
||||
app := AppFromContext(cmd.Context())
|
||||
|
||||
issue, err := app.Issues.GetIssue(cmd.Context(), issueID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting issue: %w", err)
|
||||
}
|
||||
@@ -37,12 +39,12 @@ func runUpdateCmd(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("error getting update values: %w", err)
|
||||
}
|
||||
|
||||
err = svc.Beads.UpdateIssue(cmd.Context(), issueID, updates, "test_actor")
|
||||
err = app.Issues.UpdateIssue(cmd.Context(), issueID, updates, "test_actor")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error updating issue: %w", err)
|
||||
}
|
||||
|
||||
updatedIssue, err := svc.Beads.GetIssue(cmd.Context(), issueID)
|
||||
updatedIssue, err := app.Issues.GetIssue(cmd.Context(), issueID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting updated issue: %w", err)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func NewRepl() *REPL {
|
||||
}
|
||||
|
||||
// Run starts the interactive Read-Eval-Print Loop for the PM CLI.
|
||||
func (r *REPL) Run(ctx context.Context, config cli.CLIConfig) error {
|
||||
func (r *REPL) Run(ctx context.Context, config cli.Config) error {
|
||||
// Set terminal to raw mode to capture input properly in the REPL.
|
||||
// This allows us to handle input character by character and provide a better user experience.
|
||||
// We also ensure that the terminal state is restored when the REPL exits, even if an error occurs.
|
||||
@@ -48,14 +48,14 @@ func (r *REPL) Run(ctx context.Context, config cli.CLIConfig) error {
|
||||
defer term.Restore(int(os.Stdin.Fd()), oldState)
|
||||
|
||||
// Initialize services for beads, config and stats.
|
||||
svc, cleanup, err := service.NewServices(ctx, config)
|
||||
app, cleanup, err := service.NewServices(ctx, config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize services: %w", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
// Make sure to set services, to ensure they are available.
|
||||
commands.SetServices(svc)
|
||||
// Make sure to set app, to ensure they are available.
|
||||
commands.SetApp(app)
|
||||
|
||||
// Set the REPL instance so status command can access it
|
||||
commands.SetRepl(r)
|
||||
|
||||
Reference in New Issue
Block a user