mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-26 02:11:56 +00:00
local -> cli_only;remote -> rpc_only;both -> local
This commit is contained in:
@@ -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<rpc_toolkit_prelude::Runtime>,
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -126,18 +126,92 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
|
||||
"`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<Options> {
|
||||
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<Options> {
|
||||
));
|
||||
}
|
||||
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",
|
||||
))
|
||||
}
|
||||
_ => (),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user