89 lines
4.1 KiB
Markdown
89 lines
4.1 KiB
Markdown
# 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.
|