# typed-openrpc
`typed-openrpc` is a Rust workspace that helps you describe JSON-RPC 2.0 methods with strong typing and produce OpenRPC-compliant specifications automatically. The workspace contains:
- **typed-openrpc** – the core library with the `RpcMethod` trait, registries, and OpenRPC JSON generation.
- **typed-openrpc-macros** – a procedural macro crate that lets you declare methods with `#[rpc_method(...)]` annotations.
## Features
- Derive JSON Schemas for params/results using `schemars`.
- Collect method metadata in a registry and emit OpenRPC documents at runtime.
- Optional `inventory` integration for auto-discovery of annotated methods.
- Proc-macro attribute that wires everything together with minimal boilerplate, inferring method names automatically.
### Cargo Features
- `proc-macro` – exposes the `#[rpc_method]` attribute. Enabled through the `full` feature or directly.
- `inventory` – collects registered methods via the `inventory` crate. Combine with `proc-macro` for auto discovery.
- `full` – convenience feature that enables both `proc-macro` and `inventory`.
## Quick Start
```rust
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use typed_openrpc::{generate_openrpc_doc, Registry, RpcMethod};
#[derive(Serialize, Deserialize, JsonSchema)]
struct AddParams {
a: i64,
b: i64,
}
#[derive(Serialize, Deserialize, JsonSchema)]
struct AddResult {
sum: i64,
}
struct AddMethod;
impl RpcMethod for AddMethod {
const NAME: &'static str = "add";
const SUMMARY: &'static str = "Add two numbers";
type Params = AddParams;
type Result = AddResult;
}
fn main() {
let mut registry = Registry::new();
registry.register_method::<AddMethod>();
let doc = generate_openrpc_doc(®istry);
println!("{}", serde_json::to_string_pretty(&doc).unwrap());
}
```
With the `proc-macro` feature enabled you can replace the manual impl with:
```rust
#[typed_openrpc::rpc_method(summary = "Add two numbers")]
fn add(params: AddParams) -> AddResult {
AddResult { sum: params.a + params.b }
}
```
If you omit the `name`, the macro uses the function name (`add` here). The `summary` argument is optional as well and defaults to an empty string. You can still override the name or other metadata explicitly when needed.
## Development
- Formatting: `cargo fmt`
- Linting: `cargo clippy --all-targets -- -D warnings`
- Tests: `cargo test`
### Generating OpenRPC During Build
Enable the `inventory` feature and use a `build.rs` script to emit the OpenRPC document at compile time:
```rust
// Cargo.toml
[dependencies]
typed-openrpc = { version = "0.1", features = ["full"] }
[build-dependencies]
typed-openrpc = { version = "0.1", features = ["inventory"] }
// build.rs
fn main() {
println!("cargo:rerun-if-changed=src");
let mut registry = typed_openrpc::Registry::new();
registry.collect();
let doc = typed_openrpc::generate_openrpc_doc(®istry);
std::fs::write(
"openrpc.json",
serde_json::to_string_pretty(&doc).expect("failed to serialize OpenRPC doc"),
)
.expect("failed to write openrpc.json");
}
```
Every build refreshes `openrpc.json`, keeping the spec aligned with your registered methods.
## License
Licensed under the [MIT License](LICENSE).