mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-31 07:30:32 +00:00
refactor(plugins): consolidate PDK module path and update Go version to 1.25
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
034e8af90b
commit
c19ce124d5
1
go.mod
1
go.mod
@ -21,7 +21,6 @@ require (
|
||||
github.com/djherbis/stream v1.4.0
|
||||
github.com/djherbis/times v1.6.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/extism/go-sdk v1.7.1
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/go-chi/chi/v5 v5.2.3
|
||||
|
||||
2
go.sum
2
go.sum
@ -57,8 +57,6 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a h1:UwSIFv5g5lIvbGgtf3tVwC7Ky9rmMFBp0RMs+6f6YqE=
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a/go.mod h1:C8DzXehI4zAbrdlbtOByKX6pfivJTBiV9Jjqv56Yd9Q=
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
github.com/extism/go-sdk v1.7.1 h1:lWJos6uY+tRFdlIHR+SJjwFDApY7OypS/2nMhiVQ9Sw=
|
||||
github.com/extism/go-sdk v1.7.1/go.mod h1:IT+Xdg5AZM9hVtpFUA+uZCJMge/hbvshl8bwzLtFyKA=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
|
||||
@ -792,7 +792,7 @@ See [capabilities/README.md](capabilities/README.md) for available schemas and s
|
||||
|
||||
### Using Host Service SDKs
|
||||
|
||||
Generated SDKs for calling host services are in `plugins/pdk/go/host/`, `plugins/pdk/python/` and `plugins/pdk/rust`.
|
||||
Generated SDKs for calling host services are in `plugins/pdk/go/`, `plugins/pdk/python/` and `plugins/pdk/rust`.
|
||||
|
||||
**For Go plugins:** Import the SDK as a Go module:
|
||||
|
||||
@ -803,11 +803,11 @@ import ndhost "github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
Add to your `go.mod`:
|
||||
|
||||
```
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
```
|
||||
|
||||
See [pdk/go/host/README.md](pdk/go/host/README.md) for detailed documentation.
|
||||
See [pdk/go/README.md](pdk/go/README.md) for detailed documentation.
|
||||
|
||||
**For Python plugins:** Copy functions from `nd_host_*.py` into your `__init__.py` (see comments in those files for extism-py limitations).
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ ndpgen -input <dir> -output <dir> [-package <name>] [-v] [-dry-run] [-host-only]
|
||||
```bash
|
||||
go run ./plugins/cmd/ndpgen \
|
||||
-input ./plugins/host \
|
||||
-output ./plugins/pdk/go/host
|
||||
-output ./plugins/pdk
|
||||
```
|
||||
|
||||
## Annotations
|
||||
@ -92,7 +92,7 @@ type SubsonicAPIService interface {
|
||||
|
||||
### Go Client Library (Go/TinyGo WASM)
|
||||
|
||||
Generated files are named `nd_host_<servicename>.go` (lowercase) and placed directly in the output directory. The output directory becomes a complete Go module (`github.com/navidrome/navidrome/plugins/pdk/go/host`) with package name `ndpdk`, intended for import by Navidrome plugins built with TinyGo.
|
||||
Generated files are named `nd_host_<servicename>.go` (lowercase) and placed in `$output/go/host/`. The `$output/go/` directory becomes a complete Go module (`github.com/navidrome/navidrome/plugins/pdk/go`) with package name `host`, intended for import by Navidrome plugins built with TinyGo.
|
||||
|
||||
The generator creates:
|
||||
- `nd_host_<servicename>.go` - Client wrapper code (WASM build)
|
||||
|
||||
@ -166,9 +166,11 @@ type ServiceB interface {
|
||||
Expect(filepath.Join(goHostDir, "nd_host_test.go")).To(BeAnExistingFile())
|
||||
// Stub file also generated
|
||||
Expect(filepath.Join(goHostDir, "nd_host_test_stub.go")).To(BeAnExistingFile())
|
||||
// doc.go and go.mod also generated
|
||||
// doc.go in host dir
|
||||
Expect(filepath.Join(goHostDir, "doc.go")).To(BeAnExistingFile())
|
||||
Expect(filepath.Join(goHostDir, "go.mod")).To(BeAnExistingFile())
|
||||
// go.mod at parent $output/go/ for consolidated module
|
||||
goDir := filepath.Join(outputDir, "go")
|
||||
Expect(filepath.Join(goDir, "go.mod")).To(BeAnExistingFile())
|
||||
})
|
||||
})
|
||||
|
||||
@ -332,15 +334,18 @@ type ServiceB interface {
|
||||
pluginDir := filepath.Join(outputDir, "plugin")
|
||||
Expect(os.MkdirAll(pluginDir, 0750)).To(Succeed())
|
||||
|
||||
// go.mod is at parent $output/go/ for consolidated module
|
||||
goDir := filepath.Join(outputDir, "go")
|
||||
|
||||
// Create go.mod for the plugin that imports the generated library
|
||||
goMod := fmt.Sprintf(`module testplugin
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => %s
|
||||
`, goHostDir)
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => %s
|
||||
`, goDir)
|
||||
Expect(os.WriteFile(filepath.Join(pluginDir, "go.mod"), []byte(goMod), 0600)).To(Succeed())
|
||||
|
||||
// Add a simple main function that imports and uses the ndpdk package
|
||||
@ -357,7 +362,7 @@ var _ = ndpdk.ComprehensiveNoParams
|
||||
|
||||
// Tidy dependencies for the generated go library
|
||||
goTidyLibCmd := exec.Command("go", "mod", "tidy")
|
||||
goTidyLibCmd.Dir = goHostDir
|
||||
goTidyLibCmd.Dir = goDir
|
||||
goTidyLibOutput, err := goTidyLibCmd.CombinedOutput()
|
||||
Expect(err).ToNot(HaveOccurred(), "go mod tidy (library) failed: %s", goTidyLibOutput)
|
||||
|
||||
|
||||
@ -573,11 +573,13 @@ var _ = Describe("Generator", func() {
|
||||
|
||||
codeStr := string(code)
|
||||
|
||||
// Check for module declaration (using new PDK path)
|
||||
Expect(codeStr).To(ContainSubstring("module github.com/navidrome/navidrome/plugins/pdk/go/host"))
|
||||
// Check for module declaration (consolidated PDK path at pdk/go level)
|
||||
Expect(codeStr).To(ContainSubstring("module github.com/navidrome/navidrome/plugins/pdk/go"))
|
||||
// Ensure it's not the old host-specific path
|
||||
Expect(codeStr).NotTo(ContainSubstring("module github.com/navidrome/navidrome/plugins/pdk/go/host"))
|
||||
|
||||
// Check for Go version
|
||||
Expect(codeStr).To(ContainSubstring("go 1.24"))
|
||||
Expect(codeStr).To(ContainSubstring("go 1.25"))
|
||||
|
||||
// Check for extism-go-pdk dependency
|
||||
Expect(codeStr).To(ContainSubstring("github.com/extism/go-pdk"))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
module github.com/navidrome/navidrome/plugins/pdk/go/host
|
||||
module github.com/navidrome/navidrome/plugins/pdk/go
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3
|
||||
|
||||
@ -601,21 +601,25 @@ func generateGoDocFile(services []internal.Service, outputDir, pkgName string, d
|
||||
}
|
||||
|
||||
// generateGoModFile generates the go.mod file for the Go library.
|
||||
// The go.mod is placed at the parent directory ($output/go/) to create a unified
|
||||
// module that includes both host wrappers and capabilities.
|
||||
func generateGoModFile(outputDir string, dryRun, verbose bool) error {
|
||||
code, err := internal.GenerateGoMod()
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating go.mod: %w", err)
|
||||
}
|
||||
|
||||
modFile := filepath.Join(outputDir, "go.mod")
|
||||
// Output to parent directory ($output/go/) instead of host directory
|
||||
parentDir := filepath.Dir(outputDir)
|
||||
modFile := filepath.Join(parentDir, "go.mod")
|
||||
|
||||
if dryRun {
|
||||
fmt.Printf("=== %s ===\n%s\n", modFile, code)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create output directory if needed
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
// Create parent directory if needed
|
||||
if err := os.MkdirAll(parentDir, 0755); err != nil {
|
||||
return fmt.Errorf("creating output directory: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@ -4,10 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome v0.0.0-00010101000000-000000000000
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0-00010101000000-000000000000
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -4,10 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome v0.0.0-00010101000000-000000000000
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0-00010101000000-000000000000
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -2,8 +2,8 @@ module minimal-plugin
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/navidrome/navidrome v0.0.0-00010101000000-000000000000
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3 // indirect
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -4,7 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome v0.0.0-00010101000000-000000000000
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -38,4 +38,5 @@
|
||||
// indicating they should not be edited manually.
|
||||
//
|
||||
//go:generate go run ../cmd/ndpgen -input=. -output=../pdk -go -python -rust
|
||||
//go:generate go mod tidy -C ../pdk/go
|
||||
package host
|
||||
|
||||
251
plugins/pdk/go/README.md
Normal file
251
plugins/pdk/go/README.md
Normal file
@ -0,0 +1,251 @@
|
||||
# Navidrome Plugin Development Kit for Go
|
||||
|
||||
This directory contains the auto-generated Go PDK (Plugin Development Kit) for building Navidrome plugins.
|
||||
The PDK provides both **host function wrappers** for interacting with Navidrome and
|
||||
**capability interfaces** for implementing plugin functionality.
|
||||
|
||||
## ⚠️ Auto-Generated Code
|
||||
|
||||
**Do not edit files in this directory manually.** They are generated by the `ndpgen` tool.
|
||||
|
||||
To regenerate:
|
||||
|
||||
```bash
|
||||
make gen
|
||||
```
|
||||
|
||||
## Module Structure
|
||||
|
||||
This is a consolidated Go module that includes:
|
||||
|
||||
- `host/` - Host function wrappers for calling Navidrome services from plugins
|
||||
- `lifecycle/` - Plugin lifecycle hooks (initialization)
|
||||
- `metadata/` - Metadata agent capability for artist/album info
|
||||
- `scheduler/` - Scheduler callback capability for scheduled tasks
|
||||
- `scrobbler/` - Scrobbler capability for play tracking
|
||||
- `websocket/` - WebSocket callback capability for real-time messages
|
||||
|
||||
## Usage
|
||||
|
||||
Add this module as a dependency in your plugin's `go.mod`:
|
||||
|
||||
```go
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
```
|
||||
|
||||
Then import the packages you need:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/lifecycle"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/scheduler"
|
||||
)
|
||||
|
||||
func init() {
|
||||
lifecycle.Register(&myPlugin{})
|
||||
scheduler.Register(&myPlugin{})
|
||||
}
|
||||
|
||||
type myPlugin struct{}
|
||||
|
||||
func (p *myPlugin) OnInit() error {
|
||||
// Initialize your plugin
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *myPlugin) OnSchedulerCallback(req scheduler.SchedulerCallbackRequest) error {
|
||||
// Handle scheduled task
|
||||
return host.WebSocketBroadcast("task-complete", req.ScheduleID)
|
||||
}
|
||||
|
||||
func main() {}
|
||||
```
|
||||
|
||||
## Host Services
|
||||
|
||||
The `host` package provides wrappers for calling Navidrome's host services:
|
||||
|
||||
| Service | Description |
|
||||
|---------------|----------------------------------------------------|
|
||||
| `Artwork` | Access album and artist artwork |
|
||||
| `Cache` | Temporary key-value storage with TTL |
|
||||
| `KVStore` | Persistent key-value storage |
|
||||
| `Library` | Access the music library (albums, artists, tracks) |
|
||||
| `Scheduler` | Schedule one-time and recurring tasks |
|
||||
| `SubsonicAPI` | Make Subsonic API calls |
|
||||
| `WebSocket` | Send real-time messages to clients |
|
||||
|
||||
### Example: Using Host Services
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
)
|
||||
|
||||
func myPluginFunction() error {
|
||||
// Use the cache service
|
||||
_, err := host.CacheSetString("my_key", "my_value", 3600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Schedule a recurring task
|
||||
_, err = host.SchedulerScheduleRecurring("@every 5m", "payload", "task_id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Access library data with typed structs
|
||||
resp, err := host.LibraryGetAllLibraries()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, lib := range resp.Result {
|
||||
// Library: %s with %d songs", lib.Name, lib.TotalSongs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Capabilities
|
||||
|
||||
Capabilities define what functionality your plugin implements. Register your implementations
|
||||
in the `init()` function.
|
||||
|
||||
### Lifecycle
|
||||
|
||||
Provides plugin initialization hooks.
|
||||
|
||||
```go
|
||||
import "github.com/navidrome/navidrome/plugins/pdk/go/lifecycle"
|
||||
|
||||
func init() {
|
||||
lifecycle.Register(&myPlugin{})
|
||||
}
|
||||
|
||||
type myPlugin struct{}
|
||||
|
||||
func (p *myPlugin) OnInit() error {
|
||||
// Called once when plugin is loaded
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
### MetadataAgent
|
||||
|
||||
Provides artist and album metadata from external sources.
|
||||
|
||||
```go
|
||||
import "github.com/navidrome/navidrome/plugins/pdk/go/metadata"
|
||||
|
||||
func init() {
|
||||
metadata.Register(&myAgent{})
|
||||
}
|
||||
|
||||
type myAgent struct{}
|
||||
|
||||
func (a *myAgent) GetArtistBiography(req metadata.ArtistRequest) (*metadata.ArtistBiographyResponse, error) {
|
||||
return &metadata.ArtistBiographyResponse{
|
||||
Biography: "Artist biography text...",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *myAgent) GetArtistImages(req metadata.ArtistRequest) (*metadata.ArtistImagesResponse, error) {
|
||||
return &metadata.ArtistImagesResponse{
|
||||
Images: []metadata.ImageInfo{
|
||||
{URL: "https://example.com/image.jpg", Size: 1000},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Scheduler
|
||||
|
||||
Handles callbacks from scheduled tasks.
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/navidrome/navidrome/plugins/pdk/go/scheduler"
|
||||
)
|
||||
|
||||
func init() {
|
||||
scheduler.Register(&myScheduler{})
|
||||
}
|
||||
|
||||
type myScheduler struct{}
|
||||
|
||||
func (s *myScheduler) OnSchedulerCallback(req scheduler.SchedulerCallbackRequest) error {
|
||||
// Handle the scheduled task
|
||||
if req.Payload == "update-data" {
|
||||
// Do work...
|
||||
return host.WebSocketBroadcast("data-updated", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
### Scrobbler
|
||||
|
||||
Tracks play activity.
|
||||
|
||||
```go
|
||||
import "github.com/navidrome/navidrome/plugins/pdk/go/scrobbler"
|
||||
|
||||
func init() {
|
||||
scrobbler.Register(&myScrobbler{})
|
||||
}
|
||||
|
||||
type myScrobbler struct{}
|
||||
|
||||
func (s *myScrobbler) Scrobble(req scrobbler.ScrobbleRequest) error {
|
||||
// Track the play
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *myScrobbler) NowPlaying(req scrobbler.NowPlayingRequest) error {
|
||||
// Update now playing status
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
### WebSocket
|
||||
|
||||
Handles incoming WebSocket messages.
|
||||
|
||||
```go
|
||||
import "github.com/navidrome/navidrome/plugins/pdk/go/websocket"
|
||||
|
||||
func init() {
|
||||
websocket.Register(&myHandler{})
|
||||
}
|
||||
|
||||
type myHandler struct{}
|
||||
|
||||
func (h *myHandler) OnWebSocketMessage(req websocket.WebSocketMessageRequest) error {
|
||||
// Handle incoming message
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Building Plugins
|
||||
|
||||
Go plugins must be compiled to WebAssembly using TinyGo:
|
||||
|
||||
```bash
|
||||
tinygo build -o plugin.wasm -target=wasip1 -buildmode=c-shared .
|
||||
```
|
||||
|
||||
Or use the provided Makefile targets in plugin examples:
|
||||
|
||||
```bash
|
||||
make plugin.wasm
|
||||
```
|
||||
5
plugins/pdk/go/go.mod
Normal file
5
plugins/pdk/go/go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/navidrome/navidrome/plugins/pdk/go
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3
|
||||
@ -1 +1,2 @@
|
||||
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
|
||||
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
|
||||
@ -1,98 +0,0 @@
|
||||
# Navidrome Host Function Wrappers for Go
|
||||
|
||||
This directory contains auto-generated Go wrappers for Navidrome's host services.
|
||||
These wrappers provide idiomatic Go APIs for interacting with Navidrome from WASM plugins.
|
||||
|
||||
## ⚠️ Auto-Generated Code
|
||||
|
||||
**Do not edit these files manually.** They are generated by the `ndpgen` tool.
|
||||
|
||||
To regenerate:
|
||||
|
||||
```bash
|
||||
make gen
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Add this module as a dependency in your plugin's `go.mod`:
|
||||
|
||||
```go
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
```
|
||||
|
||||
Then import the package in your plugin code:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
host "github.com/navidrome/navidrome/plugins/pdk/go/host"
|
||||
"github.com/extism/go-pdk"
|
||||
)
|
||||
|
||||
func myPluginFunction() error {
|
||||
// Use the cache service
|
||||
_, err := host.CacheSetString("my_key", "my_value", 3600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Schedule a recurring task
|
||||
_, err = host.SchedulerScheduleRecurring("@every 5m", "payload", "task_id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Access library data with typed structs
|
||||
resp, err := host.LibraryGetAllLibraries()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, lib := range resp.Result {
|
||||
pdk.Log(pdk.LogInfo, fmt.Sprintf("Library: %s with %d songs", lib.Name, lib.TotalSongs))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Typed Structs
|
||||
|
||||
Services that work with domain objects provide typed Go structs instead of
|
||||
`map[string]interface{}`. This enables compile-time type checking and IDE
|
||||
autocompletion.
|
||||
|
||||
For example, the library service provides a `Library` struct:
|
||||
|
||||
```go
|
||||
resp, err := host.LibraryGetAllLibraries()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, lib := range resp.Result {
|
||||
fmt.Printf("Library: %s (%d songs)\n", lib.Name, lib.TotalSongs)
|
||||
}
|
||||
```
|
||||
|
||||
## Available Services
|
||||
|
||||
| Module | Description |
|
||||
|---------------|----------------------------------------------------|
|
||||
| `Artwork` | Access album and artist artwork |
|
||||
| `Cache` | Temporary key-value storage with TTL |
|
||||
| `KVStore` | Persistent key-value storage |
|
||||
| `Library` | Access the music library (albums, artists, tracks) |
|
||||
| `Scheduler` | Schedule one-time and recurring tasks |
|
||||
| `SubsonicAPI` | Make Subsonic API calls |
|
||||
| `WebSocket` | Send real-time messages to clients |
|
||||
|
||||
## Building Plugins
|
||||
|
||||
Go plugins must be compiled to WebAssembly using TinyGo:
|
||||
|
||||
```bash
|
||||
tinygo build -o plugin.wasm -target=wasip1 -buildmode=c-shared .
|
||||
```
|
||||
@ -1,5 +0,0 @@
|
||||
module github.com/navidrome/navidrome/plugins/pdk/go/host
|
||||
|
||||
go 1.24
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3
|
||||
6
plugins/testdata/test-artwork/go.mod
vendored
6
plugins/testdata/test-artwork/go.mod
vendored
@ -1,10 +1,10 @@
|
||||
module test-artwork
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
4
plugins/testdata/test-cache-plugin/go.mod
vendored
4
plugins/testdata/test-cache-plugin/go.mod
vendored
@ -4,7 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
6
plugins/testdata/test-kvstore/go.mod
vendored
6
plugins/testdata/test-kvstore/go.mod
vendored
@ -1,10 +1,10 @@
|
||||
module test-kvstore
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
6
plugins/testdata/test-library/go.mod
vendored
6
plugins/testdata/test-library/go.mod
vendored
@ -1,10 +1,10 @@
|
||||
module test-library
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
4
plugins/testdata/test-metadata-agent/go.mod
vendored
4
plugins/testdata/test-metadata-agent/go.mod
vendored
@ -4,7 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
9
plugins/testdata/test-scheduler/go.mod
vendored
9
plugins/testdata/test-scheduler/go.mod
vendored
@ -2,13 +2,8 @@ module test-scheduler
|
||||
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/navidrome/navidrome v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
)
|
||||
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
|
||||
require github.com/extism/go-pdk v1.1.3 // indirect
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
4
plugins/testdata/test-scrobbler/go.mod
vendored
4
plugins/testdata/test-scrobbler/go.mod
vendored
@ -4,7 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
module test-subsonicapi-plugin
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
7
plugins/testdata/test-websocket/go.mod
vendored
7
plugins/testdata/test-websocket/go.mod
vendored
@ -4,10 +4,7 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/navidrome/navidrome v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||
)
|
||||
|
||||
replace github.com/navidrome/navidrome => ../../..
|
||||
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
||||
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user