#[server] docs

This commit is contained in:
Greg Johnston 2022-11-26 09:02:36 -05:00
parent 1a0168bf28
commit fdd07aafb7
3 changed files with 57 additions and 7 deletions

View file

@ -26,14 +26,16 @@ lazy_static = "1.4"
[dev-dependencies]
log = "0.4"
typed-builder = "0.10"
leptos = { path = "../leptos", version = "0.0" }
leptos = { path = "../leptos", version = "0.0", default-features = false }
leptos_router = { path = "../router", version = "0.0 " }
serde = { version = "1", features = ["derive"] }
[features]
default = ["ssr"]
csr = ["leptos_dom/csr", "leptos_reactive/csr"]
hydrate = ["leptos_dom/hydrate", "leptos_reactive/hydrate"]
ssr = ["leptos_dom/ssr", "leptos_reactive/ssr"]
stable = ["leptos_dom/stable", "leptos_reactive/stable"]
csr = ["leptos_dom/csr", "leptos_reactive/csr", "leptos/csr"]
hydrate = ["leptos_dom/hydrate", "leptos_reactive/hydrate", "leptos/hydrate"]
ssr = ["leptos_dom/ssr", "leptos_reactive/ssr", "leptos/ssr"]
stable = ["leptos_dom/stable", "leptos_reactive/stable", "leptos/stable"]
[package.metadata.cargo-all-features]
denylist = ["stable"]

View file

@ -352,6 +352,54 @@ pub fn component(_args: proc_macro::TokenStream, s: TokenStream) -> TokenStream
}
}
/// Declares that a function is a [server function](leptos::leptos_server). This means that
/// its body will only run on the server, i.e., when the `ssr` feature is enabled.
///
/// If you call a server function from the client (i.e., when the `csr` or `hydrate` features
/// are enabled), it will instead make a network request to the server.
///
/// You can specify one, two, or three arguments to the server function:
/// 1. **Required**: A type name that will be used to identify and register the server function
/// (e.g., `MyServerFn`).
/// 2. *Optional*: A URL prefix at which the function will be mounted when its registered
/// (e.g., `"/api"`). Defaults to `"/"`.
/// 3. *Optional*: either `"Cbor"` (specifying that it should use the binary `cbor` format for
/// serialization) or `"Url"` (specifying that it should be use a URL-encoded form-data string).
/// Defaults to `"Url"`. If you want to use this server function to power an
/// [ActionForm](leptos_router::ActionForm) the encoding must be `"Url"`.
///
/// The server function itself can take any number of arguments, each of which should be serializable
/// and deserializable with `serde`. Optionally, its first argument can be a Leptos [Scope](leptos::Scope),
/// which will be injected *on the server side.* This can be used to inject the raw HTTP request or other
/// server-side context into the server function.
///
/// ```
/// # use leptos::*; use serde::{Serialize, Deserialize};
/// # #[derive(Serialize, Deserialize)]
/// # pub struct Post { }
/// #[server(ReadPosts, "/api")]
/// pub async fn read_posts(how_many: u8, query: String) -> Result<Vec<Post>, ServerFnError> {
/// // do some work on the server to access the database
/// todo!()
/// }
/// ```
///
/// Note the following:
/// - **Server functions must be `async`.** Even if the work being done inside the function body
/// can run synchronously on the server, from the clients perspective it involves an asynchronous
/// function call.
/// - **Server functions must return `Result<T, ServerFnError>`.** Even if the work being done
/// inside the function body cant fail, the processes of serialization/deserialization and the
/// network call are fallible.
/// - **Return types must be [Serializable](leptos_reactive::Serializable).**
/// This should be fairly obvious: we have to serialize arguments to send them to the server, and we
/// need to deserialize the result to return it to the client.
/// - **Arguments must be implement [serde::Serialize].** They are serialized as an `application/x-www-form-urlencoded`
/// form data using [`serde_urlencoded`](https://docs.rs/serde_urlencoded/latest/serde_urlencoded/) or as `application/cbor`
/// using [`cbor`](https://docs.rs/cbor/latest/cbor/).
/// - **The [Scope](leptos_reactive::Scope) comes from the server.** Optionally, the first argument of a server function
/// can be a Leptos [Scope](leptos_reactive::Scope). This scope can be used to inject dependencies like the HTTP request
/// or response or other server-only dependencies, but it does *not* have access to reactive state that exists in the client.
#[proc_macro_attribute]
pub fn server(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
match server_macro_impl(args, s.into()) {

View file

@ -145,14 +145,14 @@ pub fn server_macro_impl(args: proc_macro::TokenStream, s: TokenStream2) -> Resu
#encoding
}
#[cfg(feature = "ssr")]
#[cfg(any(feature = "ssr", doc))]
fn call_fn(self, cx: ::leptos::Scope) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Output, ::leptos::ServerFnError>>>> {
let #struct_name { #(#field_names),* } = self;
#cx_assign_statement;
Box::pin(async move { #fn_name( #cx_fn_arg #(#field_names_2),*).await })
}
#[cfg(not(feature = "ssr"))]
#[cfg(any(not(feature = "ssr"), doc))]
fn call_fn_client(self, cx: ::leptos::Scope) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Output, ::leptos::ServerFnError>>>> {
let #struct_name { #(#field_names_3),* } = self;
Box::pin(async move { #fn_name( #cx_fn_arg #(#field_names_4),*).await })