The template's files at a77fd30, without its history or LICENSE, after script/rename simplexcalc. Model: opus-5-5
73 lines
2.2 KiB
Go
73 lines
2.2 KiB
Go
// Package app wires the object graph. It is the one place that knows
|
|
// which concrete types satisfy the application's dependencies, so every
|
|
// other package can be constructed in a test with substitutes.
|
|
package app
|
|
|
|
import (
|
|
"log/slog"
|
|
|
|
"go.uber.org/fx"
|
|
"go.uber.org/fx/fxevent"
|
|
"sneak.berlin/go/simplexcalc/internal/config"
|
|
"sneak.berlin/go/simplexcalc/internal/database"
|
|
"sneak.berlin/go/simplexcalc/internal/globals"
|
|
"sneak.berlin/go/simplexcalc/internal/handlers"
|
|
"sneak.berlin/go/simplexcalc/internal/logger"
|
|
"sneak.berlin/go/simplexcalc/internal/middleware"
|
|
"sneak.berlin/go/simplexcalc/internal/render"
|
|
"sneak.berlin/go/simplexcalc/internal/server"
|
|
"sneak.berlin/go/simplexcalc/internal/telemetry"
|
|
)
|
|
|
|
// Module is every provider the service needs. Constructor order is
|
|
// irrelevant to fx; the order here is the order a reader wants: build
|
|
// metadata, logging, configuration, storage, then the HTTP layer.
|
|
//
|
|
//nolint:gochecknoglobals // an fx module is a declaration, not mutable state.
|
|
var Module = fx.Options(
|
|
fx.Provide(
|
|
globals.New,
|
|
logger.New,
|
|
config.New,
|
|
database.New,
|
|
telemetry.NewSentry,
|
|
telemetry.NewMetrics,
|
|
render.New,
|
|
middleware.New,
|
|
handlers.New,
|
|
server.New,
|
|
),
|
|
|
|
// fx's own lifecycle events go through the application logger, so
|
|
// the process emits one stream in one format. Without this, fx
|
|
// prints its own plain-text output to stderr and a log pipeline
|
|
// gets two formats from one process.
|
|
fx.WithLogger(func(l *logger.Logger) fxevent.Logger {
|
|
return &fxevent.SlogLogger{Logger: l.Get()}
|
|
}),
|
|
)
|
|
|
|
// Invoke forces the graph to be built. fx constructs lazily: without a
|
|
// request for the Server, a perfectly valid App would start, construct
|
|
// nothing, and serve nothing.
|
|
//
|
|
//nolint:gochecknoglobals // as above.
|
|
var Invoke = fx.Invoke(func(_ *server.Server, log *logger.Logger, cfg *config.Config) {
|
|
if cfg.Debug {
|
|
log.EnableDebugLogging()
|
|
}
|
|
|
|
log.Identify()
|
|
})
|
|
|
|
// New builds the fx application for `serve`.
|
|
func New(opts ...fx.Option) *fx.App {
|
|
return fx.New(append([]fx.Option{Module, Invoke}, opts...)...)
|
|
}
|
|
|
|
// DiscardLogger is a logger that writes nothing, for tests that build
|
|
// the graph and do not want its startup output.
|
|
func DiscardLogger() *slog.Logger {
|
|
return slog.New(slog.DiscardHandler)
|
|
}
|