refactor to use app package instead of service

refactor app to be composable
This commit is contained in:
Robin Olsen
2026-02-28 23:30:31 +01:00
parent ba4d3df669
commit aabce0b0b2
56 changed files with 385 additions and 279 deletions

View File

@@ -4,14 +4,14 @@ package cli
import (
"context"
issuesCmd "github.com/LazyBachelor/LazyPM/internal/commands/issues"
"github.com/LazyBachelor/LazyPM/internal/app"
issues "github.com/LazyBachelor/LazyPM/internal/commands/issues"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/charmbracelet/fang"
"github.com/spf13/cobra"
)
// Config is an alias for service.Config, used to configure the CLI.
// Config is an alias for app.Config, used to configure the CLI.
type Config = models.Config
type CLI struct {
@@ -26,14 +26,14 @@ func New(rootCmd *cobra.Command) *CLI {
// Run initializes the services and executes the CLI commands.
func (c *CLI) Run(ctx context.Context, config Config) error {
app, cleanup, err := service.NewApp(ctx, config)
app, cleanup, err := app.New(ctx, config)
if err != nil {
return err
}
defer cleanup()
issuesCmd.SetApp(app)
issues.SetApp(app)
if err := fang.Execute(ctx, c.RootCmd,
fang.WithColorSchemeFunc(fang.AnsiColorScheme)); err != nil {
@@ -45,16 +45,16 @@ func (c *CLI) Run(ctx context.Context, config Config) error {
// RunWithArgs initializes the services and executes the CLI commands with the provided arguments.
func (c *CLI) RunWithArgs(ctx context.Context, config Config, args []string) error {
app, cleanup, err := service.NewApp(ctx, config)
app, cleanup, err := app.New(ctx, config)
if err != nil {
return err
}
defer cleanup()
issuesCmd.SetApp(app)
issues.SetApp(app)
if err := issuesCmd.ExecuteArgs(args); err != nil {
if err := issues.ExecuteArgs(args); err != nil {
return err
}

View File

@@ -44,6 +44,6 @@ func executePMCommand(input string) (string, error) {
return "", nil
}
output, err := issuesCmd.ExecuteArgsString(parts)
output, err := issues.ExecuteArgsString(parts)
return output, err
}

View File

@@ -7,9 +7,9 @@ import (
"os"
"strings"
issuesCmd "github.com/LazyBachelor/LazyPM/internal/commands/issues"
"github.com/LazyBachelor/LazyPM/internal/app"
issues "github.com/LazyBachelor/LazyPM/internal/commands/issues"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/internal/style"
"github.com/LazyBachelor/LazyPM/pkg/cli"
"github.com/LazyBachelor/LazyPM/pkg/task"
@@ -54,14 +54,14 @@ func (r *REPL) Run(ctx context.Context, config cli.Config) error {
defer term.Restore(int(os.Stdin.Fd()), oldState)
// Initialize services for beads, config and stats.
app, cleanup, err := service.NewApp(ctx, config)
app, cleanup, err := app.New(ctx, config)
if err != nil {
return fmt.Errorf("failed to initialize services: %w", err)
}
defer cleanup()
// Make sure to set app, to ensure they are available.
issuesCmd.SetApp(app)
issues.SetApp(app)
// Store app reference for updating feedback
r.app = app

View File

@@ -162,7 +162,7 @@ func issueIDSuggestions(partial string, hasCommand bool) []prompt.Suggest {
return nil
}
issues, _ := issuesCmd.GetIssueCompletions(context.Background(), partial)
issues, _ := issues.GetIssueCompletions(context.Background(), partial)
var suggestions []prompt.Suggest
for _, issue := range issues {

View File

@@ -3,8 +3,8 @@ package tui
import (
"context"
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/tui/views"
tea "github.com/charmbracelet/bubbletea"
)
@@ -22,7 +22,7 @@ func New() *Tui {
}
func (t *Tui) Run(ctx context.Context, config Config) error {
app, cleanup, err := service.NewApp(ctx, config)
app, cleanup, err := app.New(ctx, config)
if err != nil {
return err
}

View File

@@ -6,8 +6,8 @@ import (
"io"
"sort"
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/tui/styles"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
@@ -17,7 +17,7 @@ import (
type IssueList struct {
list list.Model
app *service.App
app *app.App
width int
height int
}
@@ -77,7 +77,7 @@ func renderHeaders(cols []TableColumn) string {
return lipgloss.JoinHorizontal(lipgloss.Left, parts...)
}
func NewIssueList(app *service.App, width, height int) IssueList {
func NewIssueList(app *app.App, width, height int) IssueList {
issues, err := app.Issues.SearchIssues(context.Background(), "", models.IssueFilter{})
if err != nil {
return IssueList{}
@@ -111,7 +111,7 @@ func NewIssueList(app *service.App, width, height int) IssueList {
}
}
func NewIssueListFromIssues(app *service.App, issues []*models.Issue, width, height int) IssueList {
func NewIssueListFromIssues(app *app.App, issues []*models.Issue, width, height int) IssueList {
// for making an IssueList from a pre-existing list of issues.
listIssues := make([]list.Item, len(issues))
for i, issue := range issues {

View File

@@ -3,8 +3,8 @@ package dashboard
import (
"context"
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/charmbracelet/bubbles/textarea"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
@@ -21,7 +21,7 @@ type Model struct {
closedIssueList IssueList
helpBar HelpBar
keyMap DashboardKeyMap
app *service.App
app *app.App
width int
height int
focusedWindow int // 0 = main (display issues), 1 = closed issues
@@ -46,14 +46,14 @@ type Model struct {
choosingPriority bool // true while choosing a priority
priorityIssueID string
choosingType bool // true while choosing a type
typeIssueID string
feedbackChan chan models.ValidationFeedback
quitChan chan bool
currentFeedback models.ValidationFeedback
showComplete bool
typeIssueID string
feedbackChan chan models.ValidationFeedback
quitChan chan bool
currentFeedback models.ValidationFeedback
showComplete bool
}
func NewDashboard(app *service.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool) *Model {
func NewDashboard(app *app.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool) *Model {
m := &Model{
header: NewHeader("Project Manager Dashboard"),
keyMap: defaultDashboardKeyMap,

View File

@@ -3,8 +3,8 @@ package dashboard
import (
"context"
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
)
@@ -49,7 +49,7 @@ type issueDeletedMsg struct {
PreviousIndex int
}
func updateIssueTitleCmd(app *service.App, issueID, newTitle string) tea.Cmd {
func updateIssueTitleCmd(app *app.App, issueID, newTitle string) tea.Cmd {
return func() tea.Msg {
updates := map[string]interface{}{"title": newTitle}
err := app.Issues.UpdateIssue(context.Background(), issueID, updates, "tui")
@@ -57,7 +57,7 @@ func updateIssueTitleCmd(app *service.App, issueID, newTitle string) tea.Cmd {
}
}
func updateIssueDescriptionCmd(app *service.App, issueID, newDescription string) tea.Cmd {
func updateIssueDescriptionCmd(app *app.App, issueID, newDescription string) tea.Cmd {
return func() tea.Msg {
updates := map[string]interface{}{"description": newDescription}
err := app.Issues.UpdateIssue(context.Background(), issueID, updates, "tui")
@@ -65,7 +65,7 @@ func updateIssueDescriptionCmd(app *service.App, issueID, newDescription string)
}
}
func updateIssueStatusCmd(app *service.App, issueID, status string) tea.Cmd {
func updateIssueStatusCmd(app *app.App, issueID, status string) tea.Cmd {
return func() tea.Msg {
updates := map[string]interface{}{"status": status}
err := app.Issues.UpdateIssue(context.Background(), issueID, updates, "tui")
@@ -73,7 +73,7 @@ func updateIssueStatusCmd(app *service.App, issueID, status string) tea.Cmd {
}
}
func updateIssuePriorityCmd(app *service.App, issueID string, priority int) tea.Cmd {
func updateIssuePriorityCmd(app *app.App, issueID string, priority int) tea.Cmd {
return func() tea.Msg {
updates := map[string]interface{}{"priority": priority}
err := app.Issues.UpdateIssue(context.Background(), issueID, updates, "tui")
@@ -81,7 +81,7 @@ func updateIssuePriorityCmd(app *service.App, issueID string, priority int) tea.
}
}
func updateIssueTypeCmd(app *service.App, issueID string, issueType models.IssueType) tea.Cmd {
func updateIssueTypeCmd(app *app.App, issueID string, issueType models.IssueType) tea.Cmd {
return func() tea.Msg {
updates := map[string]interface{}{"issue_type": string(issueType)}
err := app.Issues.UpdateIssue(context.Background(), issueID, updates, "tui")
@@ -89,7 +89,7 @@ func updateIssueTypeCmd(app *service.App, issueID string, issueType models.Issue
}
}
func createIssueCmd(app *service.App, title string) tea.Cmd {
func createIssueCmd(app *app.App, title string) tea.Cmd {
return func() tea.Msg {
issue := &models.Issue{
Title: title,
@@ -102,7 +102,7 @@ func createIssueCmd(app *service.App, title string) tea.Cmd {
}
}
func deleteIssueCmd(app *service.App, issueID string, currentIndex int) tea.Cmd {
func deleteIssueCmd(app *app.App, issueID string, currentIndex int) tea.Cmd {
return func() tea.Msg {
err := app.Issues.DeleteIssue(context.Background(), issueID)
return issueDeletedMsg{IssueID: issueID, Err: err, PreviousIndex: currentIndex}

View File

@@ -1,11 +1,11 @@
package views
import (
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/tui/views/dashboard"
)
func NewDashboardView(app *service.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool) *dashboard.Model {
func NewDashboardView(app *app.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool) *dashboard.Model {
return dashboard.NewDashboard(app, feedbackChan, quitChan)
}

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/donseba/go-htmx"
)
@@ -15,7 +15,7 @@ const (
htmxKey contextKey = "htmx"
)
func AppMiddleware(app *service.App) func(http.Handler) http.Handler {
func AppMiddleware(app *app.App) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), appKey, app)
@@ -33,8 +33,8 @@ func HTMXMiddleware(next http.Handler) http.Handler {
})
}
func App(r *http.Request) *service.App {
return r.Context().Value(appKey).(*service.App)
func App(r *http.Request) *app.App {
return r.Context().Value(appKey).(*app.App)
}
func HTMX(r *http.Request) *htmx.Handler {

View File

@@ -5,13 +5,13 @@ import (
"net/http"
"time"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/internal/app"
)
type Server struct {
Address string
Assets embed.FS
App *service.App
App *app.App
}
// NewServer creates and configures a new HTTP server instance.

View File

@@ -9,9 +9,9 @@ import (
"strings"
"time"
"github.com/LazyBachelor/LazyPM/internal/app"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/internal/utils"
"github.com/LazyBachelor/LazyPM/internal/utils/browser"
"github.com/LazyBachelor/LazyPM/pkg/web/handler"
"github.com/LazyBachelor/LazyPM/pkg/web/server"
)
@@ -32,7 +32,7 @@ func New() *Web {
var assets embed.FS
func (w *Web) Run(ctx context.Context, config Config) error {
app, cleanup, err := service.NewApp(ctx, config)
app, cleanup, err := app.New(ctx, config)
if err != nil {
return err
}
@@ -52,7 +52,7 @@ func (w *Web) Run(ctx context.Context, config Config) error {
address = "http://localhost" + address
}
err = utils.OpenBrowser(address)
err = browser.Open(address)
if err != nil {
return fmt.Errorf("failed to open browser: %w", err)
}