gui/docs/framework/plugins.md
Snider 032c426ac3 feat: initial Wails v3 desktop framework
GUI packages, examples, and documentation for building
desktop applications with Go and web technologies.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 08:44:23 +00:00

172 lines
3.8 KiB
Markdown

# Plugin System
The Plugin system (`pkg/plugin`) allows you to extend Core applications with HTTP-based plugins that register routes under `/api/{namespace}/{name}/`.
## Features
- Namespace-based organization
- HTTP handler registration
- Lifecycle hooks (OnRegister, OnUnregister)
- Wails service integration
## Plugin Interface
All plugins implement the `Plugin` interface:
```go
type Plugin interface {
// Name returns the unique identifier for this plugin
Name() string
// Namespace returns the plugin's namespace (e.g., "core", "mining")
Namespace() string
// ServeHTTP handles HTTP requests routed to this plugin
http.Handler
// OnRegister is called when the plugin is registered
OnRegister(ctx context.Context) error
// OnUnregister is called when the plugin is being removed
OnUnregister(ctx context.Context) error
}
```
## Using BasePlugin
For simple plugins, embed `BasePlugin`:
```go
import "github.com/Snider/Core/pkg/plugin"
func NewMyPlugin() *plugin.BasePlugin {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello from plugin!"))
})
return plugin.NewBasePlugin("myapp", "greeting", handler).
WithDescription("A simple greeting plugin").
WithVersion("1.0.0")
}
```
## Custom Plugin Implementation
For more control, implement the full interface:
```go
type DataPlugin struct {
db *sql.DB
}
func (p *DataPlugin) Name() string { return "data" }
func (p *DataPlugin) Namespace() string { return "myapp" }
func (p *DataPlugin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/users":
p.handleUsers(w, r)
case "/items":
p.handleItems(w, r)
default:
http.NotFound(w, r)
}
}
func (p *DataPlugin) OnRegister(ctx context.Context) error {
// Initialize database connection
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
return err
}
p.db = db
return nil
}
func (p *DataPlugin) OnUnregister(ctx context.Context) error {
if p.db != nil {
return p.db.Close()
}
return nil
}
```
## Plugin Info
Access plugin metadata:
```go
info := myPlugin.Info()
fmt.Println(info.Name) // "greeting"
fmt.Println(info.Namespace) // "myapp"
fmt.Println(info.Description) // "A simple greeting plugin"
fmt.Println(info.Version) // "1.0.0"
```
## Wails Integration
Register plugins as Wails services:
```go
app := application.New(application.Options{
Services: []application.Service{
application.NewServiceWithOptions(
myPlugin,
plugin.ServiceOptionsForPlugin(myPlugin),
),
},
})
```
## URL Routing
Plugins receive requests at:
```
/api/{namespace}/{name}/{path}
```
Examples:
- `/api/myapp/greeting/` → GreetingPlugin
- `/api/myapp/data/users` → DataPlugin (path: "/users")
- `/api/core/system/health` → SystemPlugin (path: "/health")
## Built-in Plugins
### System Plugin
Located at `pkg/plugin/builtin/system`:
```go
// Provides system information endpoints
/api/core/system/info - Application info
/api/core/system/health - Health check
```
## Plugin Router
The Router manages plugin registration:
```go
import "github.com/Snider/Core/pkg/plugin"
router := plugin.NewRouter()
// Register plugins
router.Register(ctx, myPlugin)
router.Register(ctx, dataPlugin)
// Get all registered plugins
plugins := router.List()
// Unregister a plugin
router.Unregister(ctx, "myapp", "greeting")
```
## Best Practices
1. **Use namespaces** to group related plugins
2. **Implement OnRegister** for initialization that can fail
3. **Implement OnUnregister** to clean up resources
4. **Return meaningful errors** from lifecycle hooks
5. **Use standard HTTP patterns** in ServeHTTP