diff --git a/rpc-toolkit-macro-internals/src/command/build.rs b/rpc-toolkit-macro-internals/src/command/build.rs index 75bbed0..444d8f3 100644 --- a/rpc-toolkit-macro-internals/src/command/build.rs +++ b/rpc-toolkit-macro-internals/src/command/build.rs @@ -264,7 +264,7 @@ fn rpc_handler( _ => unreachable!(), }); match opt { - Options::Leaf(opt) if matches!(opt.exec_ctx, ExecutionContext::LocalOnly(_)) => quote! { + Options::Leaf(opt) if matches!(opt.exec_ctx, ExecutionContext::CliOnly(_)) => quote! { #param_struct_def pub async fn rpc_handler#fn_generics( @@ -347,7 +347,7 @@ fn rpc_handler( } }; match self_impl { - Some(self_impl) if !matches!(common.exec_ctx, ExecutionContext::LocalOnly(_)) => { + Some(self_impl) if !matches!(common.exec_ctx, ExecutionContext::CliOnly(_)) => { let self_impl_fn = &self_impl.path; let self_impl = if self_impl.is_async { quote_spanned! { self_impl_fn.span() => @@ -552,7 +552,7 @@ fn cli_handler( quote! { rpc_toolkit_prelude::default_display } }; match opt { - Options::Leaf(opt) if matches!(opt.exec_ctx, ExecutionContext::RemoteOnly(_)) => quote! { + Options::Leaf(opt) if matches!(opt.exec_ctx, ExecutionContext::RpcOnly(_)) => quote! { pub fn cli_handler#generics( _ctx: #ctx_ty, _rt: Option, @@ -566,7 +566,7 @@ fn cli_handler( }) } }, - Options::Leaf(opt) if matches!(opt.exec_ctx, ExecutionContext::LocalOnly(_)) => { + Options::Leaf(opt) if matches!(opt.exec_ctx, ExecutionContext::CliOnly(_)) => { let invocation = if opt.is_async { quote! { rt_ref.block_on(#fn_path(#(#param),*))? @@ -687,7 +687,7 @@ fn cli_handler( } }); let self_impl = match (self_impl, &common.exec_ctx) { - (Some(self_impl), ExecutionContext::LocalOnly(_)) => { + (Some(self_impl), ExecutionContext::CliOnly(_)) => { let self_impl_fn = &self_impl.path; let create_rt = if common.is_async { None diff --git a/rpc-toolkit-macro-internals/src/command/mod.rs b/rpc-toolkit-macro-internals/src/command/mod.rs index 6fab29e..73c7666 100644 --- a/rpc-toolkit-macro-internals/src/command/mod.rs +++ b/rpc-toolkit-macro-internals/src/command/mod.rs @@ -5,8 +5,9 @@ mod parse; pub enum ExecutionContext { Standard, - LocalOnly(Path), - RemoteOnly(Path), + CliOnly(Path), + RpcOnly(Path), + Local(Path), } impl Default for ExecutionContext { fn default() -> Self { diff --git a/rpc-toolkit-macro-internals/src/command/parse.rs b/rpc-toolkit-macro-internals/src/command/parse.rs index a376931..4da703c 100644 --- a/rpc-toolkit-macro-internals/src/command/parse.rs +++ b/rpc-toolkit-macro-internals/src/command/parse.rs @@ -126,18 +126,92 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result { "`display` cannot be assigned to", )); } + NestedMeta::Meta(Meta::Path(p)) if p.is_ident("cli_only") => { + match &opt.common().exec_ctx { + ExecutionContext::Standard => { + opt.common().exec_ctx = ExecutionContext::CliOnly(p) + } + ExecutionContext::CliOnly(_) => { + return Err(Error::new(p.span(), "duplicate argument: `cli_only`")) + } + ExecutionContext::RpcOnly(_) => { + return Err(Error::new( + p.span(), + "`cli_only` and `rpc_only` are mutually exclusive", + )) + } + ExecutionContext::Local(_) => { + return Err(Error::new( + p.span(), + "`cli_only` and `local` are mutually exclusive", + )) + } + } + } + NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("cli_only") => { + return Err(Error::new( + list.path.span(), + "`cli_only` does not take any arguments", + )); + } + NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("cli_only") => { + return Err(Error::new( + nv.path.span(), + "`cli_only` cannot be assigned to", + )); + } + NestedMeta::Meta(Meta::Path(p)) if p.is_ident("rpc_only") => { + match &opt.common().exec_ctx { + ExecutionContext::Standard => { + opt.common().exec_ctx = ExecutionContext::RpcOnly(p) + } + ExecutionContext::RpcOnly(_) => { + return Err(Error::new(p.span(), "duplicate argument: `rpc_only`")) + } + ExecutionContext::CliOnly(_) => { + return Err(Error::new( + p.span(), + "`rpc_only` and `cli_only` are mutually exclusive", + )) + } + ExecutionContext::Local(_) => { + return Err(Error::new( + p.span(), + "`rpc_only` and `local` are mutually exclusive", + )) + } + } + } + NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("rpc_only") => { + return Err(Error::new( + list.path.span(), + "`rpc_only` does not take any arguments", + )); + } + NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("rpc_only") => { + return Err(Error::new( + nv.path.span(), + "`rpc_only` cannot be assigned to", + )); + } NestedMeta::Meta(Meta::Path(p)) if p.is_ident("local") => { match &opt.common().exec_ctx { ExecutionContext::Standard => { - opt.common().exec_ctx = ExecutionContext::LocalOnly(p) + opt.common().exec_ctx = ExecutionContext::Local(p) } - ExecutionContext::LocalOnly(_) => { + ExecutionContext::Local(_) => { return Err(Error::new(p.span(), "duplicate argument: `local`")) } - ExecutionContext::RemoteOnly(_) => { + ExecutionContext::RpcOnly(_) => { return Err(Error::new( p.span(), - "`local` and `remote` are mutually exclusive", + "`local` and `rpc_only` are mutually exclusive", + )) + } + ExecutionContext::CliOnly(_) => { + return Err(Error::new( + p.span(), + "`local` and `cli_only` are mutually exclusive", )) } } @@ -151,31 +225,6 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result { NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("local") => { return Err(Error::new(nv.path.span(), "`local` cannot be assigned to")); } - NestedMeta::Meta(Meta::Path(p)) if p.is_ident("remote") => { - match &opt.common().exec_ctx { - ExecutionContext::Standard => { - opt.common().exec_ctx = ExecutionContext::RemoteOnly(p) - } - ExecutionContext::LocalOnly(_) => { - return Err(Error::new(p.span(), "duplicate argument: `remote`")) - } - ExecutionContext::RemoteOnly(_) => { - return Err(Error::new( - p.span(), - "`local` and `remote` are mutually exclusive", - )) - } - } - } - NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("remote") => { - return Err(Error::new( - list.path.span(), - "`remote` does not take any arguments", - )); - } - NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("remote") => { - return Err(Error::new(nv.path.span(), "`remote` cannot be assigned to")); - } NestedMeta::Meta(Meta::Path(p)) if p.is_ident("blocking") => { if opt.common().blocking.is_some() { return Err(Error::new(p.span(), "duplicate argument `blocking`")); @@ -249,16 +298,16 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result { )); } match &opt.common.exec_ctx { - ExecutionContext::LocalOnly(local) => { + ExecutionContext::CliOnly(cli_only) => { return Err(Error::new( - local.span(), - "cannot define `local` for a command without an implementation", + cli_only.span(), + "cannot define `cli_only` for a command without an implementation", )) } - ExecutionContext::RemoteOnly(remote) => { + ExecutionContext::RpcOnly(rpc_only) => { return Err(Error::new( - remote.span(), - "cannot define `remote` for a command without an implementation", + rpc_only.span(), + "cannot define `rpc_only` for a command without an implementation", )) } _ => (), diff --git a/rpc-toolkit/src/lib.rs b/rpc-toolkit/src/lib.rs index a1e3c92..488e00b 100644 --- a/rpc-toolkit/src/lib.rs +++ b/rpc-toolkit/src/lib.rs @@ -1,14 +1,7 @@ -pub use crate::context::{Context, SeedableContext}; -pub use clap; -pub use hyper; -pub use serde; -pub use serde_json; -pub use tokio; -pub use yajrc; - /// `#[command(...)]` -/// - `#[command(local)]` -> executed by CLI instead of RPC server (leaf commands only) -/// - `#[command(remote)]` -> no CLI bindings (leaf commands only) +/// - `#[command(cli_only)]` -> executed by CLI instead of RPC server (leaf commands only) +/// - `#[command(rpc_only)]` -> no CLI bindings (leaf commands only) +/// - `#[command(local)]` -> executed wherever it was invoked. (By RPC when hit from RPC server, by cli when invoked from CLI) /// - `#[command(blocking)]` -> run with [spawn_blocking](tokio::task::spawn_blocking) if in an async context /// - `#[command(about = "About text")]` -> Set about text for the command /// - `#[command(rename = "new_name")]` -> Set the name of the command to `new_name` in the RPC and CLI @@ -27,7 +20,6 @@ pub use yajrc; /// /// See also: [arg](rpc_toolkit_macro::arg), [context](rpc_toolkit_macro::context) pub use rpc_toolkit_macro::command; - /// `rpc_server!(command, seed, status_fn)` /// - returns: [Server](hyper::Server) /// - `command`: path to an rpc command (with the `#[command]` attribute) @@ -35,7 +27,6 @@ pub use rpc_toolkit_macro::command; /// - `status_fn` (optional): a function that takes a JSON RPC error code (`i32`) and returns a [StatusCode](hyper::StatusCode) /// - default: `|_| StatusCode::OK` pub use rpc_toolkit_macro::rpc_server; - /// `run_cli!(command, app_mutator, make_seed, exit_fn)` /// - this function does not return /// - `command`: path to an rpc command (with the `#[command]` attribute) @@ -48,6 +39,9 @@ pub use rpc_toolkit_macro::rpc_server; /// - `exit_fn` (optional): a function that takes a JSON RPC error code (`i32`) and returns an Exit code (`i32`) /// - default: `|code| code` pub use rpc_toolkit_macro::run_cli; +pub use {clap, hyper, reqwest, serde, serde_json, tokio, url, yajrc}; + +pub use crate::context::{Context, SeedableContext}; pub mod command_helpers; mod context; diff --git a/rpc-toolkit/src/test.rs b/rpc-toolkit/src/test.rs index 62abcb1..0b4ca10 100644 --- a/rpc-toolkit/src/test.rs +++ b/rpc-toolkit/src/test.rs @@ -115,7 +115,6 @@ async fn test() { .arg("test::cli_test") .arg("--exact") .arg("--nocapture") - .arg("--ignored") .arg("--") .arg("-b") .arg("test") @@ -132,8 +131,7 @@ async fn test() { .unwrap(); let out = cmd.wait_with_output().await.unwrap(); assert!(out.status.success()); - assert!(std::str::from_utf8(&out.stdout) - .unwrap() + assert!(dbg!(std::str::from_utf8(&out.stdout).unwrap()) .contains("\nNone, test, false, \"TEST\", \"HAHA\"\n")); handle.abort(); }