Files
goplt/internal/di/providers.go
0x1d 4724a2efb5 feat: implement Epic 0 - Project Setup & Foundation
Implemented all 5 stories from Epic 0:

Story 0.1: Project Initialization
- Initialize Go module with path git.dcentral.systems/toolz/goplt
- Create complete directory structure (cmd/, internal/, pkg/, modules/, config/, etc.)
- Add comprehensive .gitignore for Go projects
- Create README.md with project overview and setup instructions

Story 0.2: Configuration Management System
- Define ConfigProvider interface in pkg/config
- Implement Viper-based configuration in internal/config
- Create configuration loader with environment support
- Add default, development, and production YAML config files

Story 0.3: Structured Logging System
- Define Logger interface in pkg/logger
- Implement Zap-based logger in internal/logger
- Add request ID middleware for Gin
- Create global logger export with convenience functions
- Support context-aware logging with request/user ID extraction

Story 0.4: CI/CD Pipeline
- Create GitHub Actions workflow for CI (test, lint, build, fmt)
- Add comprehensive Makefile with development commands
- Configure golangci-lint with reasonable defaults

Story 0.5: Dependency Injection and Bootstrap
- Create FX-based DI container in internal/di
- Implement provider functions for Config and Logger
- Create application entry point in cmd/platform/main.go
- Add lifecycle management with graceful shutdown

All acceptance criteria met:
- go build ./cmd/platform succeeds
- go test ./... runs successfully
- go mod verify passes
- Config loads from config/default.yaml
- Logger can be injected and used
- Application starts and shuts down gracefully
2025-11-05 12:21:15 +01:00

84 lines
1.9 KiB
Go

package di
import (
"context"
"fmt"
"os"
"go.uber.org/fx"
configimpl "git.dcentral.systems/toolz/goplt/internal/config"
loggerimpl "git.dcentral.systems/toolz/goplt/internal/logger"
"git.dcentral.systems/toolz/goplt/pkg/config"
"git.dcentral.systems/toolz/goplt/pkg/logger"
)
// ProvideConfig creates an FX option that provides ConfigProvider.
func ProvideConfig() fx.Option {
return fx.Provide(func() (config.ConfigProvider, error) {
// Determine environment from environment variable or default to "development"
env := os.Getenv("ENVIRONMENT")
if env == "" {
env = "development"
}
cfg, err := configimpl.LoadConfig(env)
if err != nil {
return nil, fmt.Errorf("failed to load config: %w", err)
}
return cfg, nil
})
}
// ProvideLogger creates an FX option that provides Logger.
func ProvideLogger() fx.Option {
return fx.Provide(func(cfg config.ConfigProvider) (logger.Logger, error) {
level := cfg.GetString("logging.level")
if level == "" {
level = "info"
}
format := cfg.GetString("logging.format")
if format == "" {
format = "json"
}
log, err := loggerimpl.NewZapLogger(level, format)
if err != nil {
return nil, fmt.Errorf("failed to create logger: %w", err)
}
// Set as global logger
logger.SetGlobalLogger(log)
return log, nil
})
}
// CoreModule returns an FX option that provides all core services.
// This includes configuration and logging.
func CoreModule() fx.Option {
return fx.Options(
ProvideConfig(),
ProvideLogger(),
)
}
// RegisterLifecycleHooks registers lifecycle hooks for logging.
func RegisterLifecycleHooks(lc fx.Lifecycle, l logger.Logger) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
l.Info("Application starting",
logger.String("component", "bootstrap"),
)
return nil
},
OnStop: func(ctx context.Context) error {
l.Info("Application shutting down",
logger.String("component", "bootstrap"),
)
return nil
},
})
}