Skip to main content

typed_openrpc/
openrpc.rs

1use serde_json::{json, Value};
2
3use crate::{registry::Registry, rpc_method::MethodDoc};
4
5/// Metadata describing the OpenRPC document.
6#[derive(Clone, Debug)]
7pub struct OpenRpcInfo {
8    pub title: String,
9    pub version: String,
10    pub description: Option<String>,
11}
12
13impl Default for OpenRpcInfo {
14    fn default() -> Self {
15        Self {
16            title: "Generated API".to_string(),
17            version: "1.0.0".to_string(),
18            description: None,
19        }
20    }
21}
22
23impl OpenRpcInfo {
24    fn to_value(&self) -> Value {
25        let mut info = json!({
26            "title": self.title,
27            "version": self.version,
28        });
29
30        if let Some(description) = &self.description {
31            info["description"] = json!(description);
32        }
33
34        info
35    }
36}
37
38impl Registry {
39    /// Convert all registered methods into an OpenRPC JSON document.
40    pub fn generate_openrpc_doc(&self) -> Value {
41        generate_openrpc_doc_with_info(self, &OpenRpcInfo::default())
42    }
43
44    pub fn generate_openrpc_doc_with_info(&self, info: &OpenRpcInfo) -> Value {
45        generate_openrpc_doc_with_info(self, info)
46    }
47}
48
49/// Convert all registered methods into an OpenRPC JSON document, using custom metadata.
50fn generate_openrpc_doc_with_info(registry: &Registry, info: &OpenRpcInfo) -> Value {
51    let methods = registry
52        .methods()
53        .iter()
54        .map(method_to_value)
55        .collect::<Vec<_>>();
56
57    json!({
58        "openrpc": "1.2.6",
59        "info": info.to_value(),
60        "methods": methods,
61    })
62}
63
64fn method_to_value(method: &MethodDoc) -> Value {
65    json!({
66        "name": method.name.clone(),
67        "summary": method.summary.clone(),
68        "deprecated": method.deprecation.clone(),
69        "tags": method.tags.clone(),
70        "params": [{
71            "name": "params",
72            "schema": method.params_schema.clone(),
73            "required": true,
74        }],
75        "result": {
76            "name": "result",
77            "schema": method.result_schema.clone(),
78        }
79    })
80}