Rust WASM Nodes
Rust is the most complete Flow-Like WASM SDK and the recommended starting
point. The checked-in template targets the WASM Component Model with
wasm32-wasip2.
Start from the template
Section titled “Start from the template”Copy templates/wasm-node-rust into your own project, then run:
mise run setupmise run testmise run buildThe build task installs the wasm32-wasip2 target, compiles a release component,
and copies the result to node.wasm. The underlying Cargo artifact is:
target/wasm32-wasip2/release/flow_like_wasm_node_template.wasmIf you do not use mise:
rustup target add wasm32-wasip2cargo build --release --target wasm32-wasip2The template configures the library as cdylib. Its checked-in dependency
currently includes a relative path to libs/wasm-sdk/wasm-sdk-rust alongside
version 0.4.0, so copying the directory alone still requires changing that
dependency. Use the published crate after confirming that the required version
is available, or keep the SDK at the path expected by the manifest. The SDK
release procedure below includes the check for a standalone template.
Define a node
Section titled “Define a node”Rust packages use #[register_node], WasmNode, and a single
wasm_main!() invocation:
use flow_like_wasm_sdk::*;
#[register_node]#[derive(Default)]pub struct UppercaseNode;
impl WasmNode for UppercaseNode { fn get_node(&self) -> NodeDefinition { let mut node = NodeDefinition::new( "uppercase", "Uppercase", "Converts text to uppercase", "Custom/Text", );
node.add_input_pin( "exec", "Exec", "Trigger execution", VariableType::Execution, ); node.add_input_pin( "text", "Text", "Text to transform", VariableType::String, ) .set_default_value(json!("")); node.add_output_pin( "exec_out", "Done", "Continue execution", VariableType::Execution, ); node.add_output_pin( "result", "Result", "Uppercase text", VariableType::String, );
node }
fn run(&self, mut ctx: Context) -> ExecutionResult { let text = ctx.get_string("text").unwrap_or_default(); ctx.set_output("result", text.to_uppercase()); ctx.activate_exec("exec_out"); ctx.success() }}
wasm_main!();Add more registered structs for a multi-node package. wasm_main!() generates
the Component Model exports and automatically exposes every registered node
through get_nodes.
Context API
Section titled “Context API”Common input helpers:
ctx.get_string("name"); // Option<String>ctx.get_i64("name"); // Option<i64>ctx.get_f64("name"); // Option<f64>ctx.get_bool("name"); // Option<bool>ctx.get_input("name"); // Option<&serde_json::Value>ctx.get_input_as::<T>("name"); // Option<T>ctx.require_input_as::<T>("name");Common output and control helpers:
ctx.set_output("result", value);ctx.set_output_json("result", &value);ctx.activate_exec("exec_out");ctx.success();ctx.fail("What went wrong");Logging and streaming are also available through the context:
ctx.info("Starting work");ctx.stream_text("Partial result");ctx.stream_progress(0.5, "Halfway");Typed struct pins
Section titled “Typed struct pins”Derive JsonSchema for a serializable Rust type, then attach the schema to a
struct pin:
#[derive(Default, serde::Serialize, serde::Deserialize, JsonSchema)]struct Request { query: String, limit: u32,}
node.add_input_pin( "request", "Request", "Search request", VariableType::Struct,).set_schema::<Request>().set_enforce_schema(true);Read it with ctx.get_input_as::<Request>("request").
Permissions
Section titled “Permissions”Declare each capability on the node that uses it:
node.add_permission(NodePermission::NetworkHttp);node.add_permission(NodePermission::StorageRead);node.add_permission(NodePermission::StorageWrite);Permissions are part of the exported node definition and drive the execution
sandbox. Package memory and timeout tiers, the host allowlist, and OAuth scopes
remain in flow-like.toml; see the
manifest reference.
Do not author capability flags in the manifest. The registry derives the
store’s capability listing from node.add_permission(...).
Test locally
Section titled “Test locally”The template’s tests run on the native host target so node logic can be tested without loading WASM:
mise run testFrom the repository root, run the template definition lint and runtime integration suite:
mise run test:wasm:rust:lintmise run test:wasm:rust:e2ePublish
Section titled “Publish”- Run
mise run build. - Open Flow-Like Desktop.
- In Packages › Mine, add the project with Add folder if it is not listed yet.
- Select Publish… on the package card. The wizard reads
flow-like.tomland the builtnode.wasmfrom the folder. - Review the extracted nodes and submit the package.
There is no checked-in flow-like publish CLI and no supported
~/.flow-like/nodes copy-install workflow.
Release the Rust SDK
Section titled “Release the Rust SDK”SDK maintainers publish flow-like-wasm-sdk to crates.io before changing the
template to use a new registry version. Run these commands from the Flow-Like
repository root with its pinned Rust toolchain. The SDK does not depend on
Wasmtime, so the runtime’s Rust minimum is a separate requirement.
The examples below use the current SDK version, 0.4.0. Read the SDK manifest
before a later release and substitute its version in registry checks and the
template dependency. The macros crate remains at 0.3.7; publish it separately
only when its own version changes.
Verify the package
Section titled “Verify the package”Install the component target, then test with and without the optional Rig agent library:
rustup target add wasm32-wasip2cargo test --manifest-path libs/wasm-sdk/wasm-sdk-rust/Cargo.toml --locked --target host-tuplecargo test --manifest-path libs/wasm-sdk/wasm-sdk-rust/Cargo.toml --locked --all-features --target host-tuplecargo package --manifest-path libs/wasm-sdk/wasm-sdk-rust/Cargo.toml --locked --allow-dirty --listmise run publish:wasm:rust:dry-runReview the SDK changelog
and package listing. The archive must include src/resources.rs and
wit/flow-like-node.wit. Cargo includes the WIT symlink’s content in the
archive, so consumers do not need a separate WIT checkout.
The dry-run task builds the packaged source for the native host and
wasm32-wasip2, with all SDK features and locked dependencies, without
uploading. It uses --allow-dirty to validate changes before commit. Commit
the release files before using the publication task, which rejects dirty
package contents.
Publish and confirm the version
Section titled “Publish and confirm the version”Use a crates.io account allowed to publish flow-like-wasm-sdk. If Cargo is
not authenticated, run this in your own terminal and enter the token at its
prompt:
cargo login --registry crates-iomise run publish:wasm:rustThe SDK task uploads only the SDK. A published version cannot be overwritten.
If Cargo reports an index timeout after upload, check the registry version
before trying another upload. Update the SDK index in libs/wasm-sdk/README.md
once the version is available. Use mise run publish:wasm:rust:macros only for
a changed macros crate.
To publish reviewed but uncommitted package changes deliberately, Cargo accepts the explicit override:
cargo publish --manifest-path libs/wasm-sdk/wasm-sdk-rust/Cargo.toml --locked --all-features --registry crates-io --allow-dirtyVerify the standalone template
Section titled “Verify the standalone template”After confirming publication, replace the dependency and its local path
comments in templates/wasm-node-rust/Cargo.toml with:
flow-like-wasm-sdk = { version = "0.4.0", features = ["rig"] }Keep rig enabled because the template includes agent examples. Remove any
template instructions requiring a sibling SDK checkout and replace
repository-relative SDK links with public links. Regenerate its lockfile and
test the published dependency:
cargo update --manifest-path templates/wasm-node-rust/Cargo.toml -p flow-like-wasm-sdk --precise 0.4.0cargo test --manifest-path templates/wasm-node-rust/Cargo.toml --locked --target host-tuplecargo build --manifest-path templates/wasm-node-rust/Cargo.toml --locked --release --target wasm32-wasip2The SDK’s template lockfile entry must have a registry source and checksum. Copy the template outside this repository, repeat its tests and component build, and confirm that it needs no sibling SDK directory. Commit the template manifest, lockfile, and documentation changes together.