vaultik/internal/cli/app.go
sneak 26db096913 Move StartTime initialization to application startup hook
- Remove StartTime initialization from globals.New()
- Add setupGlobals function in app.go to set StartTime during fx OnStart
- Simplify globals package to be just a key/value store
- Remove fx dependencies from globals test
2025-07-20 12:05:24 +02:00

69 lines
1.6 KiB
Go

package cli
import (
"context"
"fmt"
"time"
"git.eeqj.de/sneak/vaultik/internal/config"
"git.eeqj.de/sneak/vaultik/internal/database"
"git.eeqj.de/sneak/vaultik/internal/globals"
"go.uber.org/fx"
)
// AppOptions contains common options for creating the fx application
type AppOptions struct {
ConfigPath string
Modules []fx.Option
Invokes []fx.Option
}
// setupGlobals sets up the globals with application startup time
func setupGlobals(lc fx.Lifecycle, g *globals.Globals) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
g.StartTime = time.Now()
return nil
},
})
}
// NewApp creates a new fx application with common modules
func NewApp(opts AppOptions) *fx.App {
baseModules := []fx.Option{
fx.Supply(config.ConfigPath(opts.ConfigPath)),
fx.Provide(globals.New),
config.Module,
database.Module,
fx.Invoke(setupGlobals),
fx.NopLogger,
}
allOptions := append(baseModules, opts.Modules...)
allOptions = append(allOptions, opts.Invokes...)
return fx.New(allOptions...)
}
// RunApp starts and stops the fx application within the given context
func RunApp(ctx context.Context, app *fx.App) error {
if err := app.Start(ctx); err != nil {
return fmt.Errorf("failed to start app: %w", err)
}
defer func() {
if err := app.Stop(ctx); err != nil {
fmt.Printf("error stopping app: %v\n", err)
}
}()
// Wait for context cancellation
<-ctx.Done()
return nil
}
// RunWithApp is a helper that creates and runs an fx app with the given options
func RunWithApp(ctx context.Context, opts AppOptions) error {
app := NewApp(opts)
return RunApp(ctx, app)
}