package app import ( "fmt" "log/slog" ) // Module represents a sub-system of the application, with its setup and // teardown functions and dependencies. type Module struct { logger *slog.Logger name string setup setupFn teardown teardownFn depends []string loaded bool // loaded indicates if the module has been set up } // ModuleOpts contains user-exposed options when defining a module. type ModuleOpts struct { // Setup is the setup function for the module. Setup setupFn // Teardown is the teardown function for the module. Teardown teardownFn // Depends is a list of modules that this module depends on. Each entry must // be the exact name of a module registered in the lifecycle. Depends []string } // NewModule creates a new Module instance with the given name and options. func NewModule(name string, opts ModuleOpts) *Module { return &Module{ name: name, setup: opts.Setup, teardown: opts.Teardown, depends: opts.Depends, } } // Logger returns the logger for the module. func (s *Module) Logger() *slog.Logger { if s.logger == nil { panic(fmt.Sprintf("module %s used before logger was initialized", s.name)) } return s.logger } // Name returns the name of the module. func (s *Module) Name() string { return s.name } // Loaded returns whether the module has been set up. func (s *Module) Loaded() bool { return s.loaded }