Files
navidrome/plugins/pdk/rust/nd-pdk-host
Deluan Quintão bd8032b327 fix(plugins): add base64 handling for []byte and remove raw=true (#5121)
* fix(plugins): add base64 handling for []byte and remove raw=true

Go's json.Marshal automatically base64-encodes []byte fields, but Rust's
serde_json serializes Vec<u8> as a JSON array and Python's json.dumps
raises TypeError on bytes. This fixes both directions of plugin
communication by adding proper base64 encoding/decoding in generated
client code.

For Rust templates (client and capability): adds a base64_bytes serde
helper module with #[serde(with = "base64_bytes")] on all Vec<u8> fields,
and adds base64 as a dependency. For Python templates: wraps bytes params
with base64.b64encode() and responses with base64.b64decode().

Also removes the raw=true binary framing protocol from all templates,
the parser, and the Method type. The raw mechanism added complexity that
is no longer needed once []byte works properly over JSON.

* fix(plugins): update production code and tests for base64 migration

Remove raw=true annotation from SubsonicAPI.CallRaw, delete all raw
test fixtures, remove raw-related test cases from parser, generator, and
integration tests, and add new test cases validating base64 handling
for Rust and Python templates.

* fix(plugins): update golden files and regenerate production code

Update golden test fixtures for codec and comprehensive services to
include base64 handling for []byte fields. Regenerate all production
PDK code (Go, Rust, Python) and host wrappers to use standard JSON
with base64-encoded byte fields instead of binary framing protocol.

* refactor: remove base64 helper duplication from rust template

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(plugins): add base64 dependency to capabilities' Cargo.toml

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-02-27 19:00:19 -05:00
..

Navidrome Host Function Wrappers for Rust

This directory contains auto-generated Rust wrappers for Navidrome's host services. These wrappers provide idiomatic Rust 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:

make gen

Usage

Add this crate as a dependency in your plugin's Cargo.toml:

[dependencies]
nd-host = { path = "../../pdk/rust/host" }

Then import the services you need:

use nd_host::{cache, scheduler, library};
use nd_host::library::Library; // Import the typed struct

#[plugin_fn]
pub fn my_callback(input: String) -> FnResult<String> {
    // Use the cache service
    cache::set("my_key", b"my_value", 3600)?;

    // Schedule a recurring task  
    scheduler::schedule_recurring("@every 5m", "payload", "task_id")?;

    // Access library data with typed structs
    let libraries: Vec<Library> = library::get_all_libraries()?;
    for lib in &libraries {
        info!("Library: {} with {} songs", lib.name, lib.total_songs);
    }

    Ok("done".to_string())
}

Typed Structs

Services that work with domain objects provide typed Rust structs instead of serde_json::Value. This enables compile-time type checking and IDE autocompletion.

For example, the library module provides a Library struct:

use nd_host::library::Library;

let libs: Vec<Library> = library::get_all_libraries()?;
println!("First library: {} ({} songs)", libs[0].name, libs[0].total_songs);

All structs derive Debug, Clone, Serialize, and Deserialize for convenient use with logging and serialization.

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

Rust plugins must be compiled to WebAssembly:

cargo build --target wasm32-wasip1 --release

See the webhook-rs example for a complete plugin implementation.