diff --git a/yerpc-derive/src/openrpc.rs b/yerpc-derive/src/openrpc.rs index 689e741..45e0743 100644 --- a/yerpc-derive/src/openrpc.rs +++ b/yerpc-derive/src/openrpc.rs @@ -96,7 +96,7 @@ fn generate_method(method: &RemoteProcedure, definitions: Ident) -> TokenStream } /// A macro generating an OpenRPC Document. -fn generate_doc(info: &RpcInfo) -> TokenStream { +pub(crate) fn generate_doc(info: &RpcInfo) -> TokenStream { let definitions_ident = Ident::new("definitions", Span::call_site()); let methods = &info .methods diff --git a/yerpc-derive/src/rpc.rs b/yerpc-derive/src/rpc.rs index ee8636b..5b6e6b5 100644 --- a/yerpc-derive/src/rpc.rs +++ b/yerpc-derive/src/rpc.rs @@ -2,6 +2,9 @@ use crate::{util::is_result_ty, Inputs, RpcInfo}; use proc_macro2::TokenStream; use quote::quote; +#[cfg(feature = "openrpc")] +use crate::openrpc::generate_doc; + pub(crate) fn generate_rpc_impl(info: &RpcInfo) -> TokenStream { let mut request_arms = vec![]; let mut notification_arms = vec![]; @@ -66,12 +69,29 @@ pub(crate) fn generate_rpc_impl(info: &RpcInfo) -> TokenStream { let struc = &info.self_ty; let crat = quote! { ::yerpc }; + + #[cfg(feature = "openrpc")] + let openrpc_doc = generate_doc(info); + + #[cfg(not(feature = "openrpc"))] + let openrpc_specification_method = quote! {}; + + #[cfg(feature = "openrpc")] + let openrpc_specification_method = quote! { + fn openrpc_specification() -> Result { + let doc = #openrpc_doc; + let json = ::serde_json::to_string_pretty(&doc)?; + Ok(json.to_string()) + } + }; let (impl_generics, _ty_generics, where_clause) = &info.generics.split_for_impl(); quote! { #[automatically_derived] #[::yerpc::async_trait] impl #impl_generics #crat::RpcServer for #struc #where_clause { + #openrpc_specification_method + async fn handle_request( &self, method: String, diff --git a/yerpc/src/lib.rs b/yerpc/src/lib.rs index 93741a1..585d201 100644 --- a/yerpc/src/lib.rs +++ b/yerpc/src/lib.rs @@ -22,6 +22,12 @@ pub use integrations::*; #[async_trait] pub trait RpcServer: Sync + Send + 'static { + /// Returns OpenRPC specification as a string. + #[cfg(feature = "openrpc")] + fn openrpc_specification() -> Result { + Ok(String::new()) + } + async fn handle_notification(&self, _method: String, _params: serde_json::Value) -> Result<()> { Ok(()) }