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/stream v1.4.0
|
||||||
github.com/djherbis/times v1.6.0
|
github.com/djherbis/times v1.6.0
|
||||||
github.com/dustin/go-humanize v1.0.1
|
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/extism/go-sdk v1.7.1
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
github.com/go-chi/chi/v5 v5.2.3
|
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/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 h1:UwSIFv5g5lIvbGgtf3tVwC7Ky9rmMFBp0RMs+6f6YqE=
|
||||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a/go.mod h1:C8DzXehI4zAbrdlbtOByKX6pfivJTBiV9Jjqv56Yd9Q=
|
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 h1:lWJos6uY+tRFdlIHR+SJjwFDApY7OypS/2nMhiVQ9Sw=
|
||||||
github.com/extism/go-sdk v1.7.1/go.mod h1:IT+Xdg5AZM9hVtpFUA+uZCJMge/hbvshl8bwzLtFyKA=
|
github.com/extism/go-sdk v1.7.1/go.mod h1:IT+Xdg5AZM9hVtpFUA+uZCJMge/hbvshl8bwzLtFyKA=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
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
|
### 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:
|
**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`:
|
Add to your `go.mod`:
|
||||||
|
|
||||||
```
|
```
|
||||||
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 => ../../pdk/go/host
|
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).
|
**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
|
```bash
|
||||||
go run ./plugins/cmd/ndpgen \
|
go run ./plugins/cmd/ndpgen \
|
||||||
-input ./plugins/host \
|
-input ./plugins/host \
|
||||||
-output ./plugins/pdk/go/host
|
-output ./plugins/pdk
|
||||||
```
|
```
|
||||||
|
|
||||||
## Annotations
|
## Annotations
|
||||||
@ -92,7 +92,7 @@ type SubsonicAPIService interface {
|
|||||||
|
|
||||||
### Go Client Library (Go/TinyGo WASM)
|
### 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:
|
The generator creates:
|
||||||
- `nd_host_<servicename>.go` - Client wrapper code (WASM build)
|
- `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())
|
Expect(filepath.Join(goHostDir, "nd_host_test.go")).To(BeAnExistingFile())
|
||||||
// Stub file also generated
|
// Stub file also generated
|
||||||
Expect(filepath.Join(goHostDir, "nd_host_test_stub.go")).To(BeAnExistingFile())
|
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, "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")
|
pluginDir := filepath.Join(outputDir, "plugin")
|
||||||
Expect(os.MkdirAll(pluginDir, 0750)).To(Succeed())
|
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
|
// Create go.mod for the plugin that imports the generated library
|
||||||
goMod := fmt.Sprintf(`module testplugin
|
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
|
replace github.com/navidrome/navidrome/plugins/pdk/go => %s
|
||||||
`, goHostDir)
|
`, goDir)
|
||||||
Expect(os.WriteFile(filepath.Join(pluginDir, "go.mod"), []byte(goMod), 0600)).To(Succeed())
|
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
|
// 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
|
// Tidy dependencies for the generated go library
|
||||||
goTidyLibCmd := exec.Command("go", "mod", "tidy")
|
goTidyLibCmd := exec.Command("go", "mod", "tidy")
|
||||||
goTidyLibCmd.Dir = goHostDir
|
goTidyLibCmd.Dir = goDir
|
||||||
goTidyLibOutput, err := goTidyLibCmd.CombinedOutput()
|
goTidyLibOutput, err := goTidyLibCmd.CombinedOutput()
|
||||||
Expect(err).ToNot(HaveOccurred(), "go mod tidy (library) failed: %s", goTidyLibOutput)
|
Expect(err).ToNot(HaveOccurred(), "go mod tidy (library) failed: %s", goTidyLibOutput)
|
||||||
|
|
||||||
|
|||||||
@ -573,11 +573,13 @@ var _ = Describe("Generator", func() {
|
|||||||
|
|
||||||
codeStr := string(code)
|
codeStr := string(code)
|
||||||
|
|
||||||
// Check for module declaration (using new PDK path)
|
// Check for module declaration (consolidated PDK path at pdk/go level)
|
||||||
Expect(codeStr).To(ContainSubstring("module github.com/navidrome/navidrome/plugins/pdk/go/host"))
|
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
|
// Check for Go version
|
||||||
Expect(codeStr).To(ContainSubstring("go 1.24"))
|
Expect(codeStr).To(ContainSubstring("go 1.25"))
|
||||||
|
|
||||||
// Check for extism-go-pdk dependency
|
// Check for extism-go-pdk dependency
|
||||||
Expect(codeStr).To(ContainSubstring("github.com/extism/go-pdk"))
|
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
|
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.
|
// 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 {
|
func generateGoModFile(outputDir string, dryRun, verbose bool) error {
|
||||||
code, err := internal.GenerateGoMod()
|
code, err := internal.GenerateGoMod()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("generating go.mod: %w", err)
|
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 {
|
if dryRun {
|
||||||
fmt.Printf("=== %s ===\n%s\n", modFile, code)
|
fmt.Printf("=== %s ===\n%s\n", modFile, code)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create output directory if needed
|
// Create parent directory if needed
|
||||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
if err := os.MkdirAll(parentDir, 0755); err != nil {
|
||||||
return fmt.Errorf("creating output directory: %w", err)
|
return fmt.Errorf("creating output directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,10 +4,7 @@ go 1.25
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
||||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0-00010101000000-000000000000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome => ../../..
|
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
|
||||||
|
|||||||
@ -4,10 +4,7 @@ go 1.25
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
||||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0-00010101000000-000000000000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome => ../../..
|
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@ module minimal-plugin
|
|||||||
|
|
||||||
go 1.25
|
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
|
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 (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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.
|
// indicating they should not be edited manually.
|
||||||
//
|
//
|
||||||
//go:generate go run ../cmd/ndpgen -input=. -output=../pdk -go -python -rust
|
//go:generate go run ../cmd/ndpgen -input=. -output=../pdk -go -python -rust
|
||||||
|
//go:generate go mod tidy -C ../pdk/go
|
||||||
package host
|
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=
|
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
|
module test-artwork
|
||||||
|
|
||||||
go 1.24
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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 (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
module test-kvstore
|
||||||
|
|
||||||
go 1.24
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
module test-library
|
||||||
|
|
||||||
go 1.24
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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 (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
go 1.25
|
||||||
|
|
||||||
require (
|
require github.com/navidrome/navidrome/plugins/pdk/go v0.0.0
|
||||||
github.com/navidrome/navidrome v0.0.0
|
|
||||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
require github.com/extism/go-pdk v1.1.3 // indirect
|
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
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
|
||||||
|
|||||||
4
plugins/testdata/test-scrobbler/go.mod
vendored
4
plugins/testdata/test-scrobbler/go.mod
vendored
@ -4,7 +4,7 @@ go 1.25
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
module test-subsonicapi-plugin
|
||||||
|
|
||||||
go 1.24
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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 (
|
require (
|
||||||
github.com/extism/go-pdk v1.1.3
|
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
|
||||||
github.com/navidrome/navidrome/plugins/pdk/go/host v0.0.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome => ../../..
|
replace github.com/navidrome/navidrome/plugins/pdk/go => ../../pdk/go
|
||||||
|
|
||||||
replace github.com/navidrome/navidrome/plugins/pdk/go/host => ../../pdk/go/host
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user