# backpack Per-instance application container that holds the configuration, a typed service registry, the event bus and the set of activated plugins. `import "git.golem15.com/golem15/summercms/modules/backpack"` ## Overview `backpack` plays the role of the Laravel service container that WinterCMS plugins reach through `App::make` and singleton bindings, without any process-global state: every `backpack.App` is independent, so tests and multiple instances in one process do not interfere. The generated `main` of an application loads configuration with [compass](../compass/README.md), creates the container with `backpack.New`, and hands it to [party](../party/README.md), which passes it to every plugin's Register and Boot. `backpack` deliberately does not import `party`, which keeps the dependency graph acyclic. ## Features - `backpack.New` wires a container around a loaded `*compass.Config`: `backpack.App.Config`, a fresh service registry in `backpack.App.Services` and a new [festival](../festival/README.md) bus in `backpack.App.Events`. - Typed services keyed by the type argument: `backpack.App.Publish` stores a value under its type T and `backpack.App.Lookup` returns it. Publishing the same T twice or publishing nil is an error, so two plugins cannot silently replace each other's service. Framework modules share their infrastructure this way (for example the database handles published by [lagoon](../lagoon/README.md), or the translator from [phrasebook](../phrasebook/README.md)). - Plugin presence checks: `backpack.App.SetPlugins` records the complete activated set before any plugin boots, and `backpack.App.HasPlugin` answers whether an optional integration partner is part of this build (the equivalent of WinterCMS's `PluginManager::exists`). - `backpack.Registry` can be used on its own through `backpack.NewRegistry`; it is safe for concurrent use. - Nil-safe methods: calls on a nil container or registry return an error or a zero value instead of panicking. ## Usage ```go package blog import ( "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" ) // Feed is a service the blog plugin offers to other plugins. type Feed interface { Latest(n int) []string } type staticFeed struct{} func (staticFeed) Latest(n int) []string { return []string{"hello-world"} } func setup() error { cfg, err := compass.Load("config") if err != nil { return err } app := backpack.New(cfg) app.SetPlugins([]string{"acme.blog", "acme.search"}) // Provider side, usually in the plugin's Register step. var feed Feed = staticFeed{} if err := app.Publish(feed); err != nil { // published under Feed, not staticFeed return err } // Consumer side, usually in another plugin's Boot step. if app.HasPlugin("acme.blog") { if found, ok := app.Lookup[Feed](); ok { _ = found.Latest(5) } } return nil } ``` Publish under an interface type when consumers should not depend on the concrete implementation; the lookup must use exactly the same type argument. ## API reference | Identifier | Description | |------------|-------------| | `backpack.App` | The application container: configuration, service registry, event bus and the activated plugin set. | | `backpack.New` | Creates a `backpack.App` around a loaded configuration, with an empty registry and a new event bus. | | `backpack.App.Publish` / `backpack.App.Lookup` | Store and retrieve an app-scoped service by type. | | `backpack.App.SetPlugins` / `backpack.App.HasPlugin` | Record the activated plugin IDs and check whether one is present. | | `backpack.Registry` | Concurrency-safe typed service catalog behind `backpack.App.Services`. | | `backpack.NewRegistry` | Returns an empty registry. | | `backpack.Registry.Publish` / `backpack.Registry.Lookup` | Registry-level publish and lookup behind the `backpack.App` methods. | ## Dependencies - SummerCMS modules: [compass](../compass/README.md), [festival](../festival/README.md). - Third-party: none. - Standard library: `fmt`, `reflect`, `sync`. ## Testing ```sh go test ./modules/backpack/... ``` The tests build containers in memory and need no external services.