This is a quick reference for modkit's core types. For full documentation, see pkg.go.dev.
| Package | Import | Purpose |
|---|---|---|
module |
github.com/go-modkit/modkit/modkit/module |
Module metadata types |
config |
github.com/go-modkit/modkit/modkit/config |
Typed config loading helpers |
kernel |
github.com/go-modkit/modkit/modkit/kernel |
Graph builder, bootstrap |
http |
github.com/go-modkit/modkit/modkit/http |
HTTP adapter |
logging |
github.com/go-modkit/modkit/modkit/logging |
Logging interface |
testkit |
github.com/go-modkit/modkit/modkit/testkit |
Testing harness and overrides |
| Package | Stability (v0.x) | Upgrade Impact Notes |
|---|---|---|
module |
Medium | Core metadata types are expected to stay recognizable, but fields/validation behavior may evolve before v1.0.0. |
config |
Medium | Typed config helpers are stable in intent; option surfaces may expand. |
kernel |
Medium | Bootstrap and graph semantics are central; error typing and option behavior may tighten over time. |
http |
Medium | Router/registration APIs are stable in direction; middleware defaults may change in minor releases. |
logging |
High | Thin contract; changes are expected to be low churn. |
testkit |
Medium | Test ergonomics can evolve; prefer documented helpers over internal assumptions. |
For release-phase guarantees and deprecation expectations, see Stability and Compatibility Policy.
type Module interface {
Definition() ModuleDef
}Every module must implement this interface. Modules must be passed as pointers.
type ModuleDef struct {
Name string
Imports []Module
Providers []ProviderDef
Controllers []ControllerDef
Exports []Token
}| Field | Description |
|---|---|
Name |
Unique identifier for the module |
Imports |
Modules this module depends on |
Providers |
Services/values created by this module |
Controllers |
HTTP controllers created by this module |
Exports |
Tokens visible to modules that import this one |
type ProviderDef struct {
Token Token
Build func(Resolver) (any, error)
}| Field | Description |
|---|---|
Token |
Unique identifier for the provider |
Build |
Factory function called on first Get() |
type ControllerDef struct {
Name string
Build func(Resolver) (any, error)
}| Field | Description |
|---|---|
Name |
Unique identifier within the module |
Build |
Factory function that creates the controller |
type Token stringString identifier for providers. Convention: module.component (e.g., users.service).
type Resolver interface {
Get(token Token) (any, error)
}Used in Build functions to retrieve dependencies.
func Get[T any](r Resolver, token Token) (T, error)Type-safe wrapper around Resolver.Get. Returns an error if resolution fails or if the type doesn't match T.
func (a *App) Get(token Token) (any, error)Resolves a token from the root module scope. Note that module.Get[T] can be used with an App instance because App implements the Resolver interface.
func (a *App) Resolver() ResolverReturns a root-scoped resolver that enforces module visibility.
func BootstrapWithOptions(root module.Module, opts ...BootstrapOption) (*App, error)Bootstraps with explicit options. Use WithProviderOverrides to replace provider implementations, typically for testing.
type ProviderOverride struct {
Token module.Token
Build func(module.Resolver) (any, error)
Cleanup func(context.Context) error // Optional; called when harness is closed
}
func WithProviderOverrides(overrides ...ProviderOverride) BootstrapOption| Type | When |
|---|---|
RootModuleNilError |
Bootstrap(nil) |
DuplicateModuleNameError |
Two modules have the same name |
ModuleCycleError |
Circular module imports |
DuplicateProviderTokenError |
Same token registered twice |
ProviderNotFoundError |
Get() with unknown token |
TokenNotVisibleError |
Token not exported to requester |
ProviderCycleError |
Provider depends on itself |
ProviderBuildError |
Provider's Build function failed |
ControllerBuildError |
Controller's Build function failed |
DuplicateOverrideTokenError |
Override list contains duplicate token |
OverrideTokenNotFoundError |
Override targets missing provider token |
OverrideTokenNotVisibleFromRootError |
Override token not visible from root |
BootstrapOptionConflictError |
Multiple options mutate same token |
func NewRouter() *chi.MuxCreates a new chi router with baseline middleware (request ID, recoverer).
func RegisterRoutes(router Router, controllers map[string]any) errorRegisters all controllers that implement RouteRegistrar.
func AsRouter(mux *chi.Mux) RouterWraps a chi router to implement the Router interface.
type Router interface {
Handle(method, pattern string, handler http.Handler)
Group(pattern string, fn func(Router))
Use(middleware ...func(http.Handler) http.Handler)
}type RouteRegistrar interface {
RegisterRoutes(router Router)
}Controllers must implement this interface.
func Serve(addr string, handler http.Handler) errorStarts an HTTP server with graceful shutdown on SIGINT/SIGTERM.
func New(tb testkit.TB, root module.Module, opts ...testkit.Option) *testkit.Harness
func NewE(tb testkit.TB, root module.Module, opts ...testkit.Option) (*testkit.Harness, error)Bootstraps a test harness. New fails the test on bootstrap error. NewE returns the error.
func (h *Harness) App() *kernel.App
func (h *Harness) Close() error
func (h *Harness) CloseContext(ctx context.Context) errorClose runs provider cleanup hooks first and then app closers.
func WithOverrides(overrides ...Override) Option
func OverrideValue(token module.Token, value any) Override
func OverrideBuild(token module.Token, build func(module.Resolver) (any, error)) Override
func WithoutAutoClose() OptionApplies token-level provider overrides while preserving graph and visibility semantics.
func Get[T any](tb testkit.TB, h *testkit.Harness, token module.Token) T
func GetE[T any](h *testkit.Harness, token module.Token) (T, error)
func Controller[T any](tb testkit.TB, h *testkit.Harness, moduleName, controllerName string) T
func ControllerE[T any](h *testkit.Harness, moduleName, controllerName string) (T, error)Typed wrappers for provider and controller retrieval in tests.
| Type | When |
|---|---|
ControllerNotFoundError |
Controller key was not found in harness app |
TypeAssertionError |
Typed helper could not assert expected type |
HarnessCloseError |
Hook close and/or app close returned errors |
type Logger interface {
Debug(msg string, args ...any)
Info(msg string, args ...any)
Warn(msg string, args ...any)
Error(msg string, args ...any)
With(args ...any) Logger
}Generic logging interface. Use logging.NewSlogLogger(slog.Default()) for slog integration.
func NewSlogLogger(logger *slog.Logger) LoggerWraps a *slog.Logger to implement the Logger interface.
func NewNopLogger() LoggerReturns a no-op logger (useful for testing).
type UsersModule struct {
db *DatabaseModule
}
func NewUsersModule(db *DatabaseModule) *UsersModule {
return &UsersModule{db: db}
}
func (m *UsersModule) Definition() module.ModuleDef {
return module.ModuleDef{
Name: "users",
Imports: []module.Module{m.db},
Providers: []module.ProviderDef{{
Token: "users.service",
Build: func(r module.Resolver) (any, error) {
db, err := module.Get[*sql.DB](r, "db.connection")
if err != nil {
return nil, err
}
return NewUsersService(db), nil
},
}},
Controllers: []module.ControllerDef{{
Name: "UsersController",
Build: func(r module.Resolver) (any, error) {
svc, err := module.Get[UsersService](r, "users.service")
if err != nil {
return nil, err
}
return NewUsersController(svc), nil
},
}},
Exports: []module.Token{"users.service"},
}
}func main() {
app, err := kernel.Bootstrap(&AppModule{})
if err != nil {
log.Fatal(err)
}
router := mkhttp.NewRouter()
if err := mkhttp.RegisterRoutes(mkhttp.AsRouter(router), app.Controllers); err != nil {
log.Fatal(err)
}
log.Println("Listening on :8080")
if err := mkhttp.Serve(":8080", router); err != nil {
log.Fatal(err)
}
}