Changes to support axum 0.8 (#3820)
* changes to support axum 0.8 * fixing ci/cd failures. I would like advice on the change to cli/server * putting back in something I took out because I am retarded * update server function revision * remove playwright test results * clippy --------- Co-authored-by: Evan Almloff <evanalmloff@gmail.com> Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
14 files changed
+297
-315
No files matched your search
Generated
+222
-161
File diff suppressed because it is too large.
Load diff
+4
-3
@@ -208,7 +208,7 @@ tauri-utils = { version = "=2.1.1" }
|
|||||||
tauri-bundler = { version = "=2.2.3" }
|
tauri-bundler = { version = "=2.2.3" }
|
||||||
lru = "0.12.2"
|
lru = "0.12.2"
|
||||||
async-trait = "0.1.77"
|
async-trait = "0.1.77"
|
||||||
axum = { version = "0.7.0", default-features = false }
|
axum = "0.8.1"
|
||||||
axum-server = { version = "0.7.1", default-features = false }
|
axum-server = { version = "0.7.1", default-features = false }
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
http = "1.0.0"
|
http = "1.0.0"
|
||||||
@@ -222,8 +222,9 @@ serde = "1.0.61"
|
|||||||
syn = "2.0"
|
syn = "2.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
axum_session = "0.12.1"
|
axum_session = "0.16.0"
|
||||||
axum_session_auth = "0.12.1"
|
axum_session_auth = "0.16.0"
|
||||||
|
axum_session_sqlx = "0.5.0"
|
||||||
axum-extra = "0.9.2"
|
axum-extra = "0.9.2"
|
||||||
reqwest = "0.12.5"
|
reqwest = "0.12.5"
|
||||||
owo-colors = "4.0.0"
|
owo-colors = "4.0.0"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ axum = { workspace = true, optional = true }
|
|||||||
tokio = { workspace = true, features = ["full"], optional = true }
|
tokio = { workspace = true, features = ["full"], optional = true }
|
||||||
tower-http = { workspace = true, features = ["auth"], optional = true }
|
tower-http = { workspace = true, features = ["auth"], optional = true }
|
||||||
async-trait = { version = "0.1.71", optional = true }
|
async-trait = { version = "0.1.71", optional = true }
|
||||||
sqlx = { version = "0.7.0", features = [
|
sqlx = { version = "0.8.2", features = [
|
||||||
"macros",
|
"macros",
|
||||||
"migrate",
|
"migrate",
|
||||||
"postgres",
|
"postgres",
|
||||||
@@ -34,12 +34,15 @@ anyhow = { workspace = true }
|
|||||||
|
|
||||||
[dependencies.axum_session]
|
[dependencies.axum_session]
|
||||||
workspace = true
|
workspace = true
|
||||||
features = ["sqlite-rustls"]
|
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.axum_session_auth]
|
[dependencies.axum_session_auth]
|
||||||
workspace = true
|
workspace = true
|
||||||
features = ["sqlite-rustls"]
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.axum_session_sqlx]
|
||||||
|
workspace = true
|
||||||
|
features = ["sqlite"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -54,6 +57,7 @@ server = [
|
|||||||
"sqlx",
|
"sqlx",
|
||||||
"axum_session",
|
"axum_session",
|
||||||
"axum_session_auth",
|
"axum_session_auth",
|
||||||
|
"axum_session_sqlx",
|
||||||
"http",
|
"http",
|
||||||
"tower",
|
"tower",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use axum_session::{SessionConfig, SessionLayer, SessionSqlitePool, SessionStore};
|
use axum_session::{SessionConfig, SessionLayer, SessionStore};
|
||||||
use axum_session_auth::*;
|
use axum_session_auth::*;
|
||||||
|
use axum_session_sqlx::SessionSqlitePool;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use dioxus_fullstack::prelude::*;
|
use dioxus_fullstack::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -192,12 +193,8 @@ pub async fn connect_to_database() -> SqlitePool {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Session = axum_session_auth::AuthSession<
|
pub type Session =
|
||||||
crate::auth::User,
|
axum_session_auth::AuthSession<crate::auth::User, i64, SessionSqlitePool, sqlx::SqlitePool>;
|
||||||
i64,
|
|
||||||
axum_session_auth::SessionSqlitePool,
|
|
||||||
sqlx::SqlitePool,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub async fn get_session() -> Result<Session, ServerFnError> {
|
pub async fn get_session() -> Result<Session, ServerFnError> {
|
||||||
extract::<Session, _>()
|
extract::<Session, _>()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fn main() {
|
|||||||
use axum_session::SessionConfig;
|
use axum_session::SessionConfig;
|
||||||
use axum_session::SessionStore;
|
use axum_session::SessionStore;
|
||||||
use axum_session_auth::AuthConfig;
|
use axum_session_auth::AuthConfig;
|
||||||
use axum_session_auth::SessionSqlitePool;
|
use axum_session_sqlx::SessionSqlitePool;
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
@@ -49,7 +49,7 @@ fn main() {
|
|||||||
axum_session_auth::AuthSessionLayer::<
|
axum_session_auth::AuthSessionLayer::<
|
||||||
crate::auth::User,
|
crate::auth::User,
|
||||||
i64,
|
i64,
|
||||||
axum_session_auth::SessionSqlitePool,
|
SessionSqlitePool,
|
||||||
sqlx::SqlitePool,
|
sqlx::SqlitePool,
|
||||||
>::new(Some(pool))
|
>::new(Some(pool))
|
||||||
.with_config(auth_config),
|
.with_config(auth_config),
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ pub(crate) fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result<Ro
|
|||||||
|
|
||||||
// api/*path
|
// api/*path
|
||||||
router = router.route(
|
router = router.route(
|
||||||
&format!("/{}/*path", trimmed_path.trim_end_matches('/')),
|
&format!("/{}/{{*path}}", trimmed_path.trim_end_matches('/')),
|
||||||
method_router.clone(),
|
method_router.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ mod test {
|
|||||||
async fn setup_servers(mut config: WebProxyConfig) -> String {
|
async fn setup_servers(mut config: WebProxyConfig) -> String {
|
||||||
let backend_router =
|
let backend_router =
|
||||||
Router::new().route(
|
Router::new().route(
|
||||||
"/*path",
|
"/{*path}",
|
||||||
any(|request: axum::extract::Request| async move {
|
any(|request: axum::extract::Request| async move {
|
||||||
format!("backend: {}", request.uri())
|
format!("backend: {}", request.uri())
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -211,8 +211,8 @@ impl WebServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.send_shutdown().await;
|
self.send_shutdown().await;
|
||||||
for socket in self.hot_reload_sockets.drain(..) {
|
for mut socket in self.hot_reload_sockets.drain(..) {
|
||||||
_ = socket.close().await;
|
_ = socket.send(Message::Close(None)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +302,11 @@ impl WebServer {
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < self.hot_reload_sockets.len() {
|
while i < self.hot_reload_sockets.len() {
|
||||||
let socket = &mut self.hot_reload_sockets[i];
|
let socket = &mut self.hot_reload_sockets[i];
|
||||||
if socket.send(Message::Text(msg.clone())).await.is_err() {
|
if socket
|
||||||
|
.send(Message::Text(msg.clone().into()))
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
self.hot_reload_sockets.remove(i);
|
self.hot_reload_sockets.remove(i);
|
||||||
} else {
|
} else {
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -343,7 +347,7 @@ impl WebServer {
|
|||||||
async fn send_devserver_message(&mut self, msg: DevserverMsg) {
|
async fn send_devserver_message(&mut self, msg: DevserverMsg) {
|
||||||
for socket in self.hot_reload_sockets.iter_mut() {
|
for socket in self.hot_reload_sockets.iter_mut() {
|
||||||
_ = socket
|
_ = socket
|
||||||
.send(Message::Text(serde_json::to_string(&msg).unwrap()))
|
.send(Message::Text(serde_json::to_string(&msg).unwrap().into()))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +397,11 @@ async fn devserver_mainloop(
|
|||||||
|
|
||||||
// If we're not using rustls, just use regular axum
|
// If we're not using rustls, just use regular axum
|
||||||
if https_cfg.enabled != Some(true) {
|
if https_cfg.enabled != Some(true) {
|
||||||
axum::serve(listener.try_into().unwrap(), router.into_make_service()).await?;
|
axum::serve(
|
||||||
|
tokio::net::TcpListener::from_std(listener).unwrap(),
|
||||||
|
router.into_make_service(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +442,7 @@ fn build_devserver_router(
|
|||||||
// For fullstack, liveview, and server, forward all requests to the inner server
|
// For fullstack, liveview, and server, forward all requests to the inner server
|
||||||
let address = fullstack_address.unwrap();
|
let address = fullstack_address.unwrap();
|
||||||
tracing::debug!("Proxying requests to fullstack server at {address}");
|
tracing::debug!("Proxying requests to fullstack server at {address}");
|
||||||
router = router.nest_service("/",super::proxy::proxy_to(
|
router = router.fallback_service(super::proxy::proxy_to(
|
||||||
format!("http://{address}").parse().unwrap(),
|
format!("http://{address}").parse().unwrap(),
|
||||||
true,
|
true,
|
||||||
|error| {
|
|error| {
|
||||||
@@ -461,8 +469,11 @@ fn build_devserver_router(
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.trim_matches('/')
|
.trim_matches('/')
|
||||||
);
|
);
|
||||||
|
if base_path == "/" {
|
||||||
router = router.nest_service(&base_path, build_serve_dir(args, krate));
|
router = router.fallback_service(build_serve_dir(args, krate));
|
||||||
|
} else {
|
||||||
|
router = router.nest_service(&base_path, build_serve_dir(args, krate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup middleware to intercept html requests if the build status is "Building"
|
// Setup middleware to intercept html requests if the build status is "Building"
|
||||||
@@ -755,6 +766,6 @@ impl SharedStatus {
|
|||||||
|
|
||||||
async fn send_to(&self, socket: &mut WebSocket) -> Result<(), axum::Error> {
|
async fn send_to(&self, socket: &mut WebSocket) -> Result<(), axum::Error> {
|
||||||
let msg = serde_json::to_string(&self.get()).unwrap();
|
let msg = serde_json::to_string(&self.get()).unwrap();
|
||||||
socket.send(Message::Text(msg)).await
|
socket.send(Message::Text(msg.into())).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ resolver = "2"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# server functions
|
# server functions
|
||||||
server_fn = { version = "0.7.3", features = ["json", "url", "browser"], default-features = false }
|
server_fn = { version = "0.8.0-rc1", features = ["browser"], default-features = false }
|
||||||
dioxus_server_macro = { workspace = true }
|
dioxus_server_macro = { workspace = true }
|
||||||
|
|
||||||
# axum
|
# axum
|
||||||
|
|||||||
@@ -160,8 +160,6 @@ async fn handle_server_fns_inner(
|
|||||||
additional_context: ContextProviders,
|
additional_context: ContextProviders,
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
use server_fn::middleware::Service;
|
|
||||||
|
|
||||||
let path_string = path.to_string();
|
let path_string = path.to_string();
|
||||||
|
|
||||||
let (parts, body) = req.into_parts();
|
let (parts, body) = req.into_parts();
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ fn transform_rx(message: Result<Message, axum::Error>) -> Result<Vec<u8>, LiveVi
|
|||||||
message
|
message
|
||||||
.map_err(|_| LiveViewError::SendingFailed)?
|
.map_err(|_| LiveViewError::SendingFailed)?
|
||||||
.into_text()
|
.into_text()
|
||||||
.map(|s| s.into_bytes())
|
.map(|s| s.as_str().into())
|
||||||
.map_err(|_| LiveViewError::SendingFailed)
|
.map_err(|_| LiveViewError::SendingFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn transform_tx(message: Vec<u8>) -> Result<Message, axum::Error> {
|
async fn transform_tx(message: Vec<u8>) -> Result<Message, axum::Error> {
|
||||||
Ok(Message::Binary(message))
|
Ok(Message::Binary(message.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveviewRouter for Router {
|
impl LiveviewRouter for Router {
|
||||||
|
|||||||
+19
-15
@@ -9,22 +9,23 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.42.1"
|
"@playwright/test": "^1.51.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@playwright/test": {
|
"node_modules/@playwright/test": {
|
||||||
"version": "1.42.1",
|
"version": "1.51.0",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.0.tgz",
|
||||||
"integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==",
|
"integrity": "sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.42.1"
|
"playwright": "1.51.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@@ -42,33 +44,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright": {
|
"node_modules/playwright": {
|
||||||
"version": "1.42.1",
|
"version": "1.51.0",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.0.tgz",
|
||||||
"integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==",
|
"integrity": "sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.1"
|
"playwright-core": "1.51.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "2.3.2"
|
"fsevents": "2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright-core": {
|
"node_modules/playwright-core": {
|
||||||
"version": "1.42.1",
|
"version": "1.51.0",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.0.tgz",
|
||||||
"integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==",
|
"integrity": "sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,6 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.42.1"
|
"@playwright/test": "^1.51.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ description = "Server function macros for Dioxus"
|
|||||||
proc-macro2 = "^1.0.63"
|
proc-macro2 = "^1.0.63"
|
||||||
quote = "^1.0.26"
|
quote = "^1.0.26"
|
||||||
syn = { workspace = true, features = ["full"] }
|
syn = { workspace = true, features = ["full"] }
|
||||||
server_fn_macro = { version = "0.7.3" }
|
server_fn_macro = "0.8.0-rc1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dioxus = { workspace = true, features = ["fullstack"] }
|
dioxus = { workspace = true, features = ["fullstack"] }
|
||||||
|
|||||||
@@ -6,12 +6,8 @@
|
|||||||
//! See the [server_fn_macro] crate for more information.
|
//! See the [server_fn_macro] crate for more information.
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use server_fn_macro::ServerFnCall;
|
||||||
use server_fn_macro::server_macro_impl;
|
use syn::{__private::ToTokens, parse_quote};
|
||||||
use syn::{
|
|
||||||
__private::ToTokens,
|
|
||||||
parse::{Parse, ParseStream},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Declares that a function is a [server function](https://docs.rs/server_fn/).
|
/// Declares that a function is a [server function](https://docs.rs/server_fn/).
|
||||||
/// This means that its body will only run on the server, i.e., when the `ssr`
|
/// This means that its body will only run on the server, i.e., when the `ssr`
|
||||||
@@ -146,107 +142,17 @@ use syn::{
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn server(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
pub fn server(args: proc_macro::TokenStream, body: TokenStream) -> TokenStream {
|
||||||
// If there is no input codec, use json as the default
|
// If there is no input codec, use json as the default
|
||||||
let args = default_json_codec(args);
|
let parsed = match ServerFnCall::parse("/api", args.into(), body.into()) {
|
||||||
|
Ok(parsed) => parsed,
|
||||||
match server_macro_impl(
|
Err(e) => return e.to_compile_error().into(),
|
||||||
args.into(),
|
|
||||||
s.into(),
|
|
||||||
Some(syn::parse_quote!(server_fn)),
|
|
||||||
"/api",
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
) {
|
|
||||||
Err(e) => e.to_compile_error().into(),
|
|
||||||
Ok(s) => s.to_token_stream().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_json_codec(args: TokenStream) -> TokenStream {
|
|
||||||
// Try to parse the args
|
|
||||||
if let Err(err) = syn::parse::<ServerFnArgsMetadata>(args.clone()) {
|
|
||||||
return err.to_compile_error().into();
|
|
||||||
}
|
|
||||||
let Ok(args_metadata) = syn::parse::<ServerFnArgsMetadata>(args.clone()) else {
|
|
||||||
// If we fail to parse the args, forward them directly to the macro for diagnostics
|
|
||||||
return args;
|
|
||||||
};
|
};
|
||||||
let mut new_tokens = args;
|
|
||||||
|
|
||||||
// Make sure the args always end with a comma
|
parsed
|
||||||
if args_metadata.requires_trailing_comma {
|
.default_input_encoding(Some(parse_quote!(server_fn::codec::Json)))
|
||||||
let default_comma: TokenStream = quote! {,}.into();
|
.default_output_encoding(Some(parse_quote!(server_fn::codec::Json)))
|
||||||
new_tokens.extend(default_comma);
|
.default_server_fn_path(Some(parse_quote!(server_fn)))
|
||||||
}
|
.to_token_stream()
|
||||||
|
.into()
|
||||||
// If the user didn't override the input codec, default to Json
|
|
||||||
if !args_metadata.manual_input {
|
|
||||||
let default_input: TokenStream = quote! {
|
|
||||||
input = server_fn::codec::Json,
|
|
||||||
}
|
|
||||||
.into();
|
|
||||||
new_tokens.extend(default_input);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user didn't override the output codec, default to Json
|
|
||||||
if !args_metadata.manual_output {
|
|
||||||
let default_output: TokenStream = quote! {
|
|
||||||
output = server_fn::codec::Json,
|
|
||||||
}
|
|
||||||
.into();
|
|
||||||
new_tokens.extend(default_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
new_tokens
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ServerFnArgsMetadata {
|
|
||||||
manual_input: bool,
|
|
||||||
manual_output: bool,
|
|
||||||
requires_trailing_comma: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for ServerFnArgsMetadata {
|
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
|
||||||
let mut manual_input = false;
|
|
||||||
let mut manual_output = false;
|
|
||||||
let mut requires_trailing_comma = false;
|
|
||||||
let mut take_comma = |input: &ParseStream| {
|
|
||||||
let comma: Option<syn::Token![,]> = input.parse().ok();
|
|
||||||
requires_trailing_comma = comma.is_none();
|
|
||||||
};
|
|
||||||
|
|
||||||
while !input.is_empty() {
|
|
||||||
// Ignore legacy ident and string args
|
|
||||||
if input.peek(syn::Ident) && !input.peek2(syn::Token![=]) {
|
|
||||||
input.parse::<syn::Ident>()?;
|
|
||||||
take_comma(&input);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if input.peek(syn::LitStr) && !input.peek2(syn::Token![=]) {
|
|
||||||
input.parse::<syn::LitStr>()?;
|
|
||||||
take_comma(&input);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ident: syn::Ident = input.parse()?;
|
|
||||||
let _: syn::Token![=] = input.parse()?;
|
|
||||||
let _: syn::Expr = input.parse()?;
|
|
||||||
|
|
||||||
if ident == "input" {
|
|
||||||
manual_input = true;
|
|
||||||
} else if ident == "output" {
|
|
||||||
manual_output = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
take_comma(&input);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
manual_input,
|
|
||||||
manual_output,
|
|
||||||
requires_trailing_comma,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user