node-app-sdk-rust 5.22.1

Rust SDK for building Node-App native plugins (cdylib) — Lightning-powered marketplace nodes
Documentation

node-app-sdk-rust

Status: 1.0.0-experimental — API surface is frozen pending validation by at least two first-party packages. Breaking changes between 1.0.0-experimental.* releases are possible. Pin to an exact version in production.

Rust SDK for building Node-App native plugins as shared libraries (.so / .dylib / .dll). Node-Apps run inside the Node Lightning-powered marketplace daemon and communicate with the host through a stable C ABI.

What it gives you

  • A NodeApp trait — implement it on your plugin type to get HTTP, event, and capability handling.
  • The declare_node_app! macro — generates all FFI boilerplate (vtable, panic guards, JSON serialization) from your trait impl.
  • Helpers for talking to the host: log_info!, invoke_capability, publish_event, get_config, get_storage, set_storage.
  • Distributed-trace propagation across capability invocations (thread-local span context).
  • Hard limits matching the host: MAX_CAPABILITY_RESPONSE_SIZE (16 MiB), MAX_EVENT_NAME_LEN (256 B), MAX_EVENT_DATA_LEN (64 KiB).

Quick start

Add to your Cargo.toml:

[package]
name = "my-node-app"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]      # required: host loads via libloading

[dependencies]
node-app-sdk-rust = "1.0.0-experimental"
serde_json = "1.0"

src/lib.rs:

use node_app_sdk_rust::*;

#[derive(Default)]
pub struct MyApp;

impl NodeApp for MyApp {
    fn metadata() -> NodeAppInfo {
        NodeAppInfo {
            name: "my-app".into(),
            version: "0.1.0".into(),
            author: "Me".into(),
            description: "Hello-world Node-App".into(),
            capabilities: vec!["http_handler".into()],
        }
    }

    fn handle_request(&self, _req: AppRequest) -> Result<AppResponse, NodeAppError> {
        Ok(AppResponse {
            status: 200,
            headers: Default::default(),
            body: serde_json::json!({ "hello": "world" }),
        })
    }
}

declare_node_app!(MyApp);

Build:

cargo build --release
# Output: target/release/libmy_node_app.so (Linux), .dylib (macOS), .dll (Windows)

Drop the resulting shared library into the host's app directory alongside a manifest.json. The host discovers it on startup or via app.discover.

Calling host capabilities

use node_app_sdk_rust::{invoke_capability, CapabilityRequest};

let response = invoke_capability(&CapabilityRequest {
    id: uuid::Uuid::new_v4().to_string(),
    capability: "core.storage.get".into(),
    payload: serde_json::json!({ "key": "user_pref" }),
    caller_node_id: None,
    trace_id: None,
    span_id: None,
    parent_span_id: None,
    trace_depth: None,
})?;

Trace context (trace_id / span_id / trace_depth) is propagated automatically when invoking from inside handle_capability — you don't need to thread it manually.

Publishing events

use node_app_sdk_rust::publish_event;

publish_event(
    "my-app.something_happened",
    &serde_json::json!({ "user_id": 42 }),
)?;

Event names must be namespaced with your app name (my-app.*); the host rejects un-namespaced events.

ABI stability

This SDK targets Node Host API v1. The C ABI is defined by node-app-api (re-exported here) and the canonical C header lives at core/host-abi-v1/include/node-host-api-v1.h in the host repo. Apps declare their API version in NodeAppMetadata.api_version; the host refuses to load apps with mismatched versions.

License

Licensed under either of

  • Apache License, Version 2.0
  • MIT License

at your option.