1- use std:: sync:: OnceLock ;
1+ use std:: sync:: { Arc , OnceLock } ;
22#[ cfg( not( target_arch = "wasm32" ) ) ]
33use std:: { any:: Any , collections:: HashMap , sync:: RwLock } ;
44
5+ use axum_extra:: routing:: TypedPath ;
56use http:: Method ;
6- use leptos:: ServerFnError ;
7+ use leptos:: {
8+ server_fn:: {
9+ client:: browser:: BrowserClient ,
10+ codec:: { Encoding , FromReq , IntoReq , Json } ,
11+ middleware:: Layer ,
12+ request:: { browser:: BrowserRequest , ClientReq } ,
13+ ServerFn ,
14+ } ,
15+ ServerFnError ,
16+ } ;
717use matchit:: Router ;
818use models:: { ApiEndpoint , ApiRequest , AppResponse , ErrorType } ;
919use preprocess:: Preprocessable ;
@@ -16,13 +26,108 @@ use serde::{Serialize, de::DeserializeOwned};
1626type ApiCallRegistryData = OnceLock < RwLock < HashMap < Method , Router < Box < dyn Any + Send + Sync > > > > > ;
1727
1828#[ cfg( not( target_arch = "wasm32" ) ) ]
29+ #[ doc( hidden) ]
1930/// Used internally for registering API calls to the backend. DO NOT USE THIS ON
2031/// YOUR OWN. Use the [`make_request`] fn instead.
2132pub static API_CALL_REGISTRY : ApiCallRegistryData = OnceLock :: new ( ) ;
2233
34+ /// A struct that holds the request to be made to the backend. This is used
35+ /// for the server fn to make the request to the backend.
36+ struct MakeRequest < E >
37+ where
38+ E : ApiEndpoint ,
39+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
40+ E :: RequestBody : Serialize + DeserializeOwned ,
41+ E :: ResponseBody : Serialize + DeserializeOwned ,
42+ {
43+ request : ApiRequest < E > ,
44+ }
45+
46+ impl < E > ServerFn for MakeRequest < E >
47+ where
48+ E : ApiEndpoint ,
49+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
50+ E :: RequestBody : Serialize + DeserializeOwned ,
51+ E :: ResponseBody : Serialize + DeserializeOwned ,
52+ {
53+ type Client = BrowserClient ;
54+ type Error = ErrorType ;
55+ type InputEncoding = if E :: METHOD == Method :: GET {
56+ GetJson
57+ } else {
58+ Json
59+ } ;
60+ type Output = AppResponse < E > ;
61+ type OutputEncoding = Json ;
62+ #[ cfg( not( target_arch = "wasm32" ) ) ]
63+ type ServerRequest = http:: Request < axum:: body:: Body > ;
64+ #[ cfg( target_arch = "wasm32" ) ]
65+ type ServerRequest = leptos:: server_fn:: request:: BrowserMockReq ;
66+ #[ cfg( not( target_arch = "wasm32" ) ) ]
67+ type ServerResponse = http:: Response < axum:: body:: Body > ;
68+ #[ cfg( target_arch = "wasm32" ) ]
69+ type ServerResponse = leptos:: server_fn:: response:: BrowserMockRes ;
70+
71+ const PATH : & ' static str = <E :: RequestPath as TypedPath >:: PATH ;
72+
73+ async fn run_body ( self ) -> Result < Self :: Output , ServerFnError < Self :: Error > > {
74+ todo ! ( )
75+ }
76+
77+ fn middlewares ( ) -> Vec < Arc < dyn Layer < Self :: ServerRequest , Self :: ServerResponse > > > {
78+ vec ! [ ]
79+ }
80+ }
81+
82+ impl < E > IntoReq < Json , BrowserRequest , ErrorType > for MakeRequest < E >
83+ where
84+ E : ApiEndpoint ,
85+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
86+ E :: RequestBody : Serialize + DeserializeOwned ,
87+ E :: ResponseBody : Serialize + DeserializeOwned ,
88+ {
89+ fn into_req (
90+ self ,
91+ path : & str ,
92+ accepts : & str ,
93+ ) -> Result < BrowserRequest , ServerFnError < ErrorType > > {
94+ let request = if E :: METHOD == Method :: GET {
95+ BrowserRequest :: try_new_get ( path, Json :: CONTENT_TYPE , accepts, query)
96+ } else {
97+ BrowserRequest :: try_new_post ( path, content_type, accepts, body)
98+ }
99+ }
100+ }
101+
102+ #[ cfg( not( target_arch = "wasm32" ) ) ]
103+ impl < E > FromReq < Json , http:: Request < axum:: body:: Body > , ErrorType > for MakeRequest < E >
104+ where
105+ E : ApiEndpoint ,
106+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
107+ E :: RequestBody : Serialize + DeserializeOwned ,
108+ E :: ResponseBody : Serialize + DeserializeOwned ,
109+ {
110+ async fn from_req (
111+ req : http:: Request < axum:: body:: Body > ,
112+ ) -> Result < Self , ServerFnError < ErrorType > > {
113+ todo ! ( )
114+ }
115+ }
116+
23117#[ cfg( target_arch = "wasm32" ) ]
24- /// The client used to make requests to the backend
25- static REQWEST_CLIENT : OnceLock < reqwest:: Client > = OnceLock :: new ( ) ;
118+ impl < E > FromReq < Json , leptos:: server_fn:: request:: BrowserMockReq , ErrorType > for MakeRequest < E >
119+ where
120+ E : ApiEndpoint ,
121+ <E :: RequestBody as Preprocessable >:: Processed : Send ,
122+ E :: RequestBody : Serialize + DeserializeOwned ,
123+ E :: ResponseBody : Serialize + DeserializeOwned ,
124+ {
125+ async fn from_req (
126+ req : leptos:: server_fn:: request:: BrowserMockReq ,
127+ ) -> Result < Self , ServerFnError < ErrorType > > {
128+ unreachable ! ( )
129+ }
130+ }
26131
27132/// Makes an API call to the backend. If you want to make an API request, just
28133/// call this function with the request and you'll get a response. All the
0 commit comments