Skip to main content

allframe_core/router/
mod.rs

1//! # Protocol-Agnostic Router
2//!
3//! Write handlers once, expose them via REST, GraphQL, and gRPC.
4//!
5//! This is AllFrame's core differentiator - the same handler can serve
6//! multiple protocols without code changes.
7//!
8//! ## Quick Start
9//!
10//! ```rust
11//! use allframe_core::router::{Router, RestAdapter, GraphQLAdapter, GrpcAdapter};
12//!
13//! // Create router and register handlers
14//! let mut router = Router::new();
15//! router.register("get_user", || async {
16//!     r#"{"id": 42, "name": "Alice"}"#.to_string()
17//! });
18//!
19//! // Expose via REST
20//! let mut rest = RestAdapter::new();
21//! rest.route("GET", "/users/:id", "get_user");
22//!
23//! // Expose via GraphQL
24//! let mut graphql = GraphQLAdapter::new();
25//! graphql.query("user", "get_user");
26//!
27//! // Expose via gRPC
28//! let mut grpc = GrpcAdapter::new();
29//! grpc.unary("UserService", "GetUser", "get_user");
30//! ```
31//!
32//! ## Key Types
33//!
34//! - `Router` - Central handler registry
35//! - `RestAdapter` - REST protocol adapter
36//! - `GraphQLAdapter` - GraphQL protocol adapter
37//! - `GrpcAdapter` - gRPC protocol adapter
38//! - `ProtocolAdapter` - Trait for custom protocol adapters
39//!
40//! ## API Documentation
41//!
42//! Generate beautiful API documentation automatically:
43//!
44//! - `scalar_html` - Scalar UI for REST APIs (<50KB)
45//! - `graphiql_html` - GraphiQL playground for GraphQL
46//! - `grpc_explorer_html` - gRPC Explorer for gRPC services
47//! - `OpenApiGenerator` - OpenAPI 3.1 spec generation
48//!
49//! ## Configuration-Driven Protocol Selection
50//!
51//! Use TOML configuration to select protocols without code changes:
52//!
53//! ```toml
54//! [server]
55//! protocols = ["rest", "graphql", "grpc"]
56//!
57//! [server.rest]
58//! port = 8080
59//!
60//! [server.graphql]
61//! port = 8081
62//! ```
63
64use serde::de::DeserializeOwned;
65use serde::Serialize;
66use futures_core::Stream;
67use std::{any::Any, collections::HashMap, future::Future, pin::Pin, sync::Arc};
68
69pub mod adapter;
70pub mod builder;
71#[cfg(feature = "router")]
72pub mod config;
73pub mod contract;
74pub mod docs;
75pub mod graphiql;
76pub mod graphql;
77pub mod grpc;
78pub mod grpc_explorer;
79pub mod handler;
80pub mod metadata;
81pub mod method;
82pub mod openapi;
83pub mod rest;
84pub mod scalar;
85pub mod schema;
86pub mod ts_codegen;
87
88// Production adapters (optional features)
89#[cfg(feature = "router-graphql")]
90pub mod graphql_prod;
91#[cfg(feature = "router-grpc")]
92pub mod grpc_prod;
93
94pub use adapter::ProtocolAdapter;
95pub use builder::RouteBuilder;
96#[cfg(feature = "router")]
97pub use config::{GraphQLConfig, GrpcConfig, RestConfig, RouterConfig, ServerConfig};
98pub use contract::{
99    ContractTestConfig, ContractTestResult, ContractTestResults, ContractTestable, ContractTester,
100};
101pub use docs::DocsConfig;
102pub use graphiql::{graphiql_html, GraphiQLConfig, GraphiQLTheme};
103pub use graphql::{GraphQLAdapter, GraphQLOperation, OperationType};
104// Re-export production adapters when features are enabled
105#[cfg(feature = "router-graphql")]
106pub use graphql_prod::GraphQLProductionAdapter;
107pub use grpc::{GrpcAdapter, GrpcMethod, GrpcMethodType, GrpcRequest, GrpcStatus};
108pub use grpc_explorer::{grpc_explorer_html, GrpcExplorerConfig, GrpcExplorerTheme};
109#[cfg(feature = "router-grpc")]
110pub use grpc_prod::{protobuf, status, streaming, GrpcProductionAdapter, GrpcService};
111pub use handler::{
112    Handler, HandlerFn, HandlerWithArgs, HandlerWithState, HandlerWithStateOnly,
113    IntoHandlerResult, IntoStreamItem, Json, State, StreamError, StreamHandler, StreamReceiver,
114    StreamSender, StreamingHandlerFn, StreamingHandlerWithArgs, StreamingHandlerWithState,
115    StreamingHandlerWithStateOnly, DEFAULT_STREAM_CAPACITY,
116};
117pub use metadata::RouteMetadata;
118pub use method::Method;
119pub use openapi::{OpenApiGenerator, OpenApiServer};
120pub use rest::{RestAdapter, RestRequest, RestResponse, RestRoute};
121pub use scalar::{scalar_html, ScalarConfig, ScalarLayout, ScalarTheme};
122pub use schema::ToJsonSchema;
123pub use ts_codegen::{generate_ts_client, HandlerMeta, TsField, TsType};
124
125/// Drive a `Stream` to completion, forwarding items through a `StreamSender`.
126///
127/// Returns a JSON result: `"null"` on success, or a JSON error string if a
128/// serialization error occurred.
129async fn drive_stream<T, St>(stream: St, tx: &StreamSender) -> String
130where
131    T: IntoStreamItem,
132    St: Stream<Item = T> + Send,
133{
134    tokio::pin!(stream);
135    loop {
136        let next = std::future::poll_fn(|cx| stream.as_mut().poll_next(cx)).await;
137        match next {
138            Some(item) => match tx.send(item).await {
139                Ok(()) => {}
140                Err(StreamError::Closed) => break,
141                Err(StreamError::Serialize(e)) => {
142                    return serde_json::json!({"error": e}).to_string();
143                }
144            },
145            None => break,
146        }
147    }
148    "null".to_string()
149}
150
151/// Router manages handler registration and protocol adapters
152///
153/// The router allows you to register handlers once and expose them via
154/// multiple protocols based on configuration.
155pub struct Router {
156    handlers: HashMap<String, Box<dyn Handler>>,
157    streaming_handlers: HashMap<String, Box<dyn StreamHandler>>,
158    adapters: HashMap<String, Box<dyn ProtocolAdapter>>,
159    routes: Vec<RouteMetadata>,
160    state: Option<Arc<dyn Any + Send + Sync>>,
161    handler_metas: HashMap<String, HandlerMeta>,
162    #[cfg(feature = "router")]
163    #[allow(dead_code)]
164    config: Option<RouterConfig>,
165}
166
167impl Router {
168    /// Create a new router
169    pub fn new() -> Self {
170        Self {
171            handlers: HashMap::new(),
172            streaming_handlers: HashMap::new(),
173            adapters: HashMap::new(),
174            routes: Vec::new(),
175            state: None,
176            handler_metas: HashMap::new(),
177            #[cfg(feature = "router")]
178            config: None,
179        }
180    }
181
182    /// Create a new router with configuration
183    #[cfg(feature = "router")]
184    pub fn with_config(config: RouterConfig) -> Self {
185        let mut router = Self {
186            handlers: HashMap::new(),
187            streaming_handlers: HashMap::new(),
188            adapters: HashMap::new(),
189            routes: Vec::new(),
190            state: None,
191            handler_metas: HashMap::new(),
192            config: Some(config.clone()),
193        };
194
195        // Auto-register adapters based on config
196        if config.has_protocol("rest") {
197            router.add_adapter(Box::new(RestAdapter::new()));
198        }
199        if config.has_protocol("graphql") {
200            router.add_adapter(Box::new(GraphQLAdapter::new()));
201        }
202        if config.has_protocol("grpc") {
203            router.add_adapter(Box::new(GrpcAdapter::new()));
204        }
205
206        router
207    }
208
209    /// Set shared state for dependency injection (builder pattern)
210    pub fn with_state<S: Send + Sync + 'static>(mut self, state: S) -> Self {
211        self.state = Some(Arc::new(state));
212        self
213    }
214
215    /// Register a handler with a name (zero-arg, backward compatible)
216    pub fn register<F, Fut>(&mut self, name: &str, handler: F)
217    where
218        F: Fn() -> Fut + Send + Sync + 'static,
219        Fut: Future<Output = String> + Send + 'static,
220    {
221        self.handlers
222            .insert(name.to_string(), Box::new(HandlerFn::new(handler)));
223    }
224
225    /// Register a handler that receives typed, deserialized args
226    pub fn register_with_args<T, F, Fut>(&mut self, name: &str, handler: F)
227    where
228        T: DeserializeOwned + Send + 'static,
229        F: Fn(T) -> Fut + Send + Sync + 'static,
230        Fut: Future<Output = String> + Send + 'static,
231    {
232        self.handlers
233            .insert(name.to_string(), Box::new(HandlerWithArgs::new(handler)));
234    }
235
236    /// Register a handler that receives injected state and typed args
237    ///
238    /// # Panics
239    ///
240    /// Panics at call-time if `with_state` was not called, or if the state
241    /// type does not match `S`.
242    pub fn register_with_state<S, T, F, Fut>(&mut self, name: &str, handler: F)
243    where
244        S: Send + Sync + 'static,
245        T: DeserializeOwned + Send + 'static,
246        F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync + 'static,
247        Fut: Future<Output = String> + Send + 'static,
248    {
249        let state = self
250            .state
251            .clone()
252            .expect("register_with_state requires with_state to be called first");
253        self.handlers
254            .insert(name.to_string(), Box::new(HandlerWithState::new(handler, state)));
255    }
256
257    /// Register a handler that receives only injected state (no args)
258    ///
259    /// # Panics
260    ///
261    /// Panics at call-time if `with_state` was not called, or if the state
262    /// type does not match `S`.
263    pub fn register_with_state_only<S, F, Fut>(&mut self, name: &str, handler: F)
264    where
265        S: Send + Sync + 'static,
266        F: Fn(State<Arc<S>>) -> Fut + Send + Sync + 'static,
267        Fut: Future<Output = String> + Send + 'static,
268    {
269        let state = self
270            .state
271            .clone()
272            .expect("register_with_state_only requires with_state to be called first");
273        self.handlers
274            .insert(name.to_string(), Box::new(HandlerWithStateOnly::new(handler, state)));
275    }
276
277    // ─── Typed return registration (auto-serialize via Json wrapper) ─────
278
279    /// Register a handler that returns `R: Serialize` (auto-serialized to JSON)
280    pub fn register_typed<R, F, Fut>(&mut self, name: &str, handler: F)
281    where
282        R: Serialize + Send + 'static,
283        F: Fn() -> Fut + Send + Sync + 'static,
284        Fut: Future<Output = R> + Send + 'static,
285    {
286        let wrapped = move || {
287            let fut = handler();
288            async move { Json(fut.await) }
289        };
290        self.handlers
291            .insert(name.to_string(), Box::new(HandlerFn::new(wrapped)));
292    }
293
294    /// Register a handler that accepts typed args and returns `R: Serialize`
295    pub fn register_typed_with_args<T, R, F, Fut>(&mut self, name: &str, handler: F)
296    where
297        T: DeserializeOwned + Send + 'static,
298        R: Serialize + Send + 'static,
299        F: Fn(T) -> Fut + Send + Sync + 'static,
300        Fut: Future<Output = R> + Send + 'static,
301    {
302        let wrapped = move |args: T| {
303            let fut = handler(args);
304            async move { Json(fut.await) }
305        };
306        self.handlers
307            .insert(name.to_string(), Box::new(HandlerWithArgs::new(wrapped)));
308    }
309
310    /// Register a handler that receives state + typed args and returns `R: Serialize`
311    pub fn register_typed_with_state<S, T, R, F, Fut>(&mut self, name: &str, handler: F)
312    where
313        S: Send + Sync + 'static,
314        T: DeserializeOwned + Send + 'static,
315        R: Serialize + Send + 'static,
316        F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync + 'static,
317        Fut: Future<Output = R> + Send + 'static,
318    {
319        let state = self
320            .state
321            .clone()
322            .expect("register_typed_with_state requires with_state to be called first");
323        let wrapped = move |s: State<Arc<S>>, args: T| {
324            let fut = handler(s, args);
325            async move { Json(fut.await) }
326        };
327        self.handlers
328            .insert(name.to_string(), Box::new(HandlerWithState::new(wrapped, state)));
329    }
330
331    /// Register a handler that receives state only and returns `R: Serialize`
332    pub fn register_typed_with_state_only<S, R, F, Fut>(&mut self, name: &str, handler: F)
333    where
334        S: Send + Sync + 'static,
335        R: Serialize + Send + 'static,
336        F: Fn(State<Arc<S>>) -> Fut + Send + Sync + 'static,
337        Fut: Future<Output = R> + Send + 'static,
338    {
339        let state = self
340            .state
341            .clone()
342            .expect("register_typed_with_state_only requires with_state to be called first");
343        let wrapped = move |s: State<Arc<S>>| {
344            let fut = handler(s);
345            async move { Json(fut.await) }
346        };
347        self.handlers
348            .insert(name.to_string(), Box::new(HandlerWithStateOnly::new(wrapped, state)));
349    }
350
351    // ─── Result return registration ─────────────────────────────────────
352
353    /// Register a handler returning `Result<R, E>` (no args)
354    ///
355    /// On `Ok(value)`, `value` is serialized to JSON. On `Err(e)`, the error
356    /// is returned as a string.
357    pub fn register_result<R, E, F, Fut>(&mut self, name: &str, handler: F)
358    where
359        R: Serialize + Send + 'static,
360        E: std::fmt::Display + Send + 'static,
361        F: Fn() -> Fut + Send + Sync + 'static,
362        Fut: Future<Output = Result<R, E>> + Send + 'static,
363    {
364        self.handlers
365            .insert(name.to_string(), Box::new(HandlerFn::new(handler)));
366    }
367
368    /// Register a handler returning `Result<R, E>` with typed args
369    pub fn register_result_with_args<T, R, E, F, Fut>(&mut self, name: &str, handler: F)
370    where
371        T: DeserializeOwned + Send + 'static,
372        R: Serialize + Send + 'static,
373        E: std::fmt::Display + Send + 'static,
374        F: Fn(T) -> Fut + Send + Sync + 'static,
375        Fut: Future<Output = Result<R, E>> + Send + 'static,
376    {
377        self.handlers
378            .insert(name.to_string(), Box::new(HandlerWithArgs::new(handler)));
379    }
380
381    /// Register a handler returning `Result<R, E>` with state + typed args
382    pub fn register_result_with_state<S, T, R, E, F, Fut>(&mut self, name: &str, handler: F)
383    where
384        S: Send + Sync + 'static,
385        T: DeserializeOwned + Send + 'static,
386        R: Serialize + Send + 'static,
387        E: std::fmt::Display + Send + 'static,
388        F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync + 'static,
389        Fut: Future<Output = Result<R, E>> + Send + 'static,
390    {
391        let state = self
392            .state
393            .clone()
394            .expect("register_result_with_state requires with_state to be called first");
395        self.handlers
396            .insert(name.to_string(), Box::new(HandlerWithState::new(handler, state)));
397    }
398
399    /// Register a handler returning `Result<R, E>` with state only
400    pub fn register_result_with_state_only<S, R, E, F, Fut>(&mut self, name: &str, handler: F)
401    where
402        S: Send + Sync + 'static,
403        R: Serialize + Send + 'static,
404        E: std::fmt::Display + Send + 'static,
405        F: Fn(State<Arc<S>>) -> Fut + Send + Sync + 'static,
406        Fut: Future<Output = Result<R, E>> + Send + 'static,
407    {
408        let state = self
409            .state
410            .clone()
411            .expect("register_result_with_state_only requires with_state to be called first");
412        self.handlers
413            .insert(name.to_string(), Box::new(HandlerWithStateOnly::new(handler, state)));
414    }
415
416    /// Get the number of registered handlers (request/response only)
417    pub fn handlers_count(&self) -> usize {
418        self.handlers.len()
419    }
420
421    // ─── Streaming handler registration ─────────────────────────────────
422
423    /// Register a streaming handler (no args, receives StreamSender)
424    pub fn register_streaming<F, Fut, R>(&mut self, name: &str, handler: F)
425    where
426        F: Fn(StreamSender) -> Fut + Send + Sync + 'static,
427        Fut: Future<Output = R> + Send + 'static,
428        R: IntoHandlerResult + 'static,
429    {
430        self.streaming_handlers
431            .insert(name.to_string(), Box::new(StreamingHandlerFn::new(handler)));
432    }
433
434    /// Register a streaming handler with typed args
435    pub fn register_streaming_with_args<T, F, Fut, R>(&mut self, name: &str, handler: F)
436    where
437        T: DeserializeOwned + Send + 'static,
438        F: Fn(T, StreamSender) -> Fut + Send + Sync + 'static,
439        Fut: Future<Output = R> + Send + 'static,
440        R: IntoHandlerResult + 'static,
441    {
442        self.streaming_handlers
443            .insert(name.to_string(), Box::new(StreamingHandlerWithArgs::new(handler)));
444    }
445
446    /// Register a streaming handler with state and typed args
447    pub fn register_streaming_with_state<S, T, F, Fut, R>(&mut self, name: &str, handler: F)
448    where
449        S: Send + Sync + 'static,
450        T: DeserializeOwned + Send + 'static,
451        F: Fn(State<Arc<S>>, T, StreamSender) -> Fut + Send + Sync + 'static,
452        Fut: Future<Output = R> + Send + 'static,
453        R: IntoHandlerResult + 'static,
454    {
455        let state = self
456            .state
457            .clone()
458            .expect("register_streaming_with_state requires with_state to be called first");
459        self.streaming_handlers
460            .insert(name.to_string(), Box::new(StreamingHandlerWithState::new(handler, state)));
461    }
462
463    /// Register a streaming handler with state only (no args)
464    pub fn register_streaming_with_state_only<S, F, Fut, R>(&mut self, name: &str, handler: F)
465    where
466        S: Send + Sync + 'static,
467        F: Fn(State<Arc<S>>, StreamSender) -> Fut + Send + Sync + 'static,
468        Fut: Future<Output = R> + Send + 'static,
469        R: IntoHandlerResult + 'static,
470    {
471        let state = self
472            .state
473            .clone()
474            .expect("register_streaming_with_state_only requires with_state to be called first");
475        self.streaming_handlers
476            .insert(name.to_string(), Box::new(StreamingHandlerWithStateOnly::new(handler, state)));
477    }
478
479    /// Register a handler that returns a `Stream` of items (no args).
480    ///
481    /// The stream is internally bridged to a `StreamSender` channel.
482    /// Items are forwarded through a bounded channel (default capacity 64).
483    /// Register a handler that returns a `Stream` of items (no args).
484    ///
485    /// The stream is internally bridged to a `StreamSender` channel.
486    /// Items are forwarded through a bounded channel (default capacity 64).
487    pub fn register_stream<T, St, F, Fut>(&mut self, name: &str, handler: F)
488    where
489        T: IntoStreamItem + 'static,
490        St: Stream<Item = T> + Send + 'static,
491        F: Fn() -> Fut + Send + Sync + 'static,
492        Fut: Future<Output = St> + Send + 'static,
493    {
494        self.register_streaming(name, move |tx: StreamSender| {
495            let stream_fut = handler();
496            async move {
497                drive_stream(stream_fut.await, &tx).await
498            }
499        });
500    }
501
502    /// Register a handler that takes typed args and returns a `Stream` of items.
503    pub fn register_stream_with_args<T, Item, St, F, Fut>(&mut self, name: &str, handler: F)
504    where
505        T: DeserializeOwned + Send + 'static,
506        Item: IntoStreamItem + 'static,
507        St: Stream<Item = Item> + Send + 'static,
508        F: Fn(T) -> Fut + Send + Sync + 'static,
509        Fut: Future<Output = St> + Send + 'static,
510    {
511        self.register_streaming_with_args::<T, _, _, _>(name, move |args: T, tx: StreamSender| {
512            let stream_fut = handler(args);
513            async move {
514                drive_stream(stream_fut.await, &tx).await
515            }
516        });
517    }
518
519    /// Register a handler that takes state + typed args and returns a `Stream` of items.
520    pub fn register_stream_with_state<S, T, Item, St, F, Fut>(&mut self, name: &str, handler: F)
521    where
522        S: Send + Sync + 'static,
523        T: DeserializeOwned + Send + 'static,
524        Item: IntoStreamItem + 'static,
525        St: Stream<Item = Item> + Send + 'static,
526        F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync + 'static,
527        Fut: Future<Output = St> + Send + 'static,
528    {
529        self.register_streaming_with_state::<S, T, _, _, _>(name, move |state: State<Arc<S>>, args: T, tx: StreamSender| {
530            let stream_fut = handler(state, args);
531            async move {
532                drive_stream(stream_fut.await, &tx).await
533            }
534        });
535    }
536
537    /// Check if a handler is a streaming handler
538    pub fn is_streaming(&self, name: &str) -> bool {
539        self.streaming_handlers.contains_key(name)
540    }
541
542    /// Call a streaming handler by name.
543    ///
544    /// Creates a bounded channel, passes the sender to the handler,
545    /// and returns `(receiver, completion_future)`. The completion future
546    /// resolves with the handler's final result.
547    ///
548    /// Note: the returned future borrows `self`. For use in contexts where
549    /// a `'static` future is needed (e.g., `tokio::spawn`), use
550    /// `spawn_streaming_handler` instead.
551    #[allow(clippy::type_complexity)]
552    pub fn call_streaming_handler(
553        &self,
554        name: &str,
555        args: &str,
556    ) -> Result<
557        (
558            StreamReceiver,
559            Pin<Box<dyn Future<Output = Result<String, String>> + Send + '_>>,
560        ),
561        String,
562    > {
563        let handler = self
564            .streaming_handlers
565            .get(name)
566            .ok_or_else(|| format!("Streaming handler '{}' not found", name))?;
567
568        let (tx, rx) = StreamSender::channel();
569        let fut = handler.call_streaming(args, tx);
570        Ok((rx, fut))
571    }
572
573    /// Spawn a streaming handler as a tokio task.
574    ///
575    /// Like `call_streaming_handler` but returns a `'static` receiver and
576    /// `JoinHandle`, suitable for use with `tokio::spawn`.
577    #[allow(clippy::type_complexity)]
578    pub fn spawn_streaming_handler(
579        self: &Arc<Self>,
580        name: &str,
581        args: &str,
582    ) -> Result<
583        (
584            StreamReceiver,
585            tokio::task::JoinHandle<Result<String, String>>,
586        ),
587        String,
588    > {
589        if !self.streaming_handlers.contains_key(name) {
590            return Err(format!("Streaming handler '{}' not found", name));
591        }
592
593        let router = self.clone();
594        let name = name.to_string();
595        let args = args.to_string();
596
597        let (tx, rx) = StreamSender::channel();
598
599        let handle = tokio::spawn(async move {
600            let handler = router
601                .streaming_handlers
602                .get(&name)
603                .expect("handler verified to exist");
604            handler.call_streaming(&args, tx).await
605        });
606
607        Ok((rx, handle))
608    }
609
610    // ─── TypeScript codegen metadata ────────────────────────────────────
611
612    /// Attach type metadata to a handler for TypeScript client generation
613    ///
614    /// The metadata describes the handler's argument fields and return type,
615    /// which `generate_ts_client()` uses to generate typed async functions.
616    ///
617    /// # Example
618    ///
619    /// ```rust
620    /// use allframe_core::router::{Router, TsField, TsType};
621    ///
622    /// let mut router = Router::new();
623    /// router.register("get_user", || async { r#"{"id":1}"#.to_string() });
624    /// router.describe_handler("get_user", vec![], TsType::Object(vec![
625    ///     TsField::new("id", TsType::Number),
626    ///     TsField::new("name", TsType::String),
627    /// ]));
628    /// ```
629    pub fn describe_handler(
630        &mut self,
631        name: &str,
632        args: Vec<TsField>,
633        returns: TsType,
634    ) {
635        assert!(
636            self.handlers.contains_key(name),
637            "describe_handler: handler '{}' not registered",
638            name
639        );
640        self.handler_metas
641            .insert(name.to_string(), HandlerMeta::new(args, returns));
642    }
643
644    /// Attach type metadata to a streaming handler for TypeScript client generation
645    pub fn describe_streaming_handler(
646        &mut self,
647        name: &str,
648        args: Vec<TsField>,
649        item_type: TsType,
650        final_type: TsType,
651    ) {
652        assert!(
653            self.streaming_handlers.contains_key(name),
654            "describe_streaming_handler: streaming handler '{}' not registered",
655            name
656        );
657        self.handler_metas
658            .insert(name.to_string(), HandlerMeta::streaming(args, item_type, final_type));
659    }
660
661    /// Generate a complete TypeScript client module from all described handlers
662    ///
663    /// Returns a string containing TypeScript code with typed async functions
664    /// for each handler that has metadata attached via `describe_handler()`.
665    ///
666    /// # Example
667    ///
668    /// ```rust
669    /// use allframe_core::router::{Router, TsField, TsType};
670    ///
671    /// let mut router = Router::new();
672    /// router.register("get_user", || async { r#"{"id":1}"#.to_string() });
673    /// router.describe_handler("get_user", vec![
674    ///     TsField::new("id", TsType::Number),
675    /// ], TsType::Object(vec![
676    ///     TsField::new("id", TsType::Number),
677    ///     TsField::new("name", TsType::String),
678    /// ]));
679    ///
680    /// let ts_code = router.generate_ts_client();
681    /// assert!(ts_code.contains("export async function getUser"));
682    /// ```
683    pub fn generate_ts_client(&self) -> String {
684        generate_ts_client(&self.handler_metas)
685    }
686
687    /// Get handler metadata (for inspection/testing)
688    pub fn handler_meta(&self, name: &str) -> Option<&HandlerMeta> {
689        self.handler_metas.get(name)
690    }
691
692    /// Add a protocol adapter
693    pub fn add_adapter(&mut self, adapter: Box<dyn ProtocolAdapter>) {
694        self.adapters.insert(adapter.name().to_string(), adapter);
695    }
696
697    /// Check if an adapter is registered
698    pub fn has_adapter(&self, name: &str) -> bool {
699        self.adapters.contains_key(name)
700    }
701
702    /// Get an adapter by name
703    pub fn get_adapter(&self, name: &str) -> Option<&dyn ProtocolAdapter> {
704        self.adapters.get(name).map(|b| &**b)
705    }
706
707    /// Route a request through the appropriate protocol adapter
708    pub async fn route_request(&self, protocol: &str, request: &str) -> Result<String, String> {
709        let adapter = self
710            .get_adapter(protocol)
711            .ok_or_else(|| format!("Adapter not found: {}", protocol))?;
712
713        adapter.handle(request).await
714    }
715
716    /// Execute a handler by name (zero-arg shorthand)
717    pub async fn execute(&self, name: &str) -> Result<String, String> {
718        self.execute_with_args(name, "{}").await
719    }
720
721    /// Execute a handler by name with JSON args
722    pub async fn execute_with_args(&self, name: &str, args: &str) -> Result<String, String> {
723        match self.handlers.get(name) {
724            Some(handler) => handler.call(args).await,
725            None => Err(format!("Handler '{}' not found", name)),
726        }
727    }
728
729    /// List all registered handler names (both request/response and streaming)
730    ///
731    /// Returns a vector of all handler names that have been registered
732    /// with this router. Used by MCP server for tool discovery.
733    pub fn list_handlers(&self) -> Vec<String> {
734        let mut names: Vec<String> = self.handlers.keys().cloned().collect();
735        names.extend(self.streaming_handlers.keys().cloned());
736        names
737    }
738
739    /// Call a handler by name with request data (JSON args)
740    ///
741    /// Forwards the request string as args to the handler.
742    /// Used by MCP server and Tauri plugin.
743    pub async fn call_handler(&self, name: &str, request: &str) -> Result<String, String> {
744        self.execute_with_args(name, request).await
745    }
746
747    /// Check if handler can be called via REST
748    pub fn can_handle_rest(&self, _name: &str) -> bool {
749        self.has_adapter("rest")
750    }
751
752    /// Check if handler can be called via GraphQL
753    pub fn can_handle_graphql(&self, _name: &str) -> bool {
754        self.has_adapter("graphql")
755    }
756
757    /// Check if handler can be called via gRPC
758    pub fn can_handle_grpc(&self, _name: &str) -> bool {
759        self.has_adapter("grpc")
760    }
761
762    /// Get list of enabled protocols
763    pub fn enabled_protocols(&self) -> Vec<String> {
764        self.adapters.keys().cloned().collect()
765    }
766
767    /// Add a route with metadata
768    ///
769    /// This stores route metadata that can be used to generate
770    /// documentation (OpenAPI, GraphQL schemas, gRPC reflection).
771    pub fn add_route(&mut self, metadata: RouteMetadata) {
772        self.routes.push(metadata);
773    }
774
775    /// Get all registered routes
776    ///
777    /// Returns an immutable reference to all route metadata.
778    /// This is used for documentation generation.
779    pub fn routes(&self) -> &[RouteMetadata] {
780        &self.routes
781    }
782
783    /// Register a GET route
784    ///
785    /// This is a convenience method that registers both a handler and route
786    /// metadata for a GET request. The handler name is automatically
787    /// generated as "GET:{path}".
788    pub fn get<F, Fut>(&mut self, path: &str, handler: F)
789    where
790        F: Fn() -> Fut + Send + Sync + 'static,
791        Fut: Future<Output = String> + Send + 'static,
792    {
793        let handler_name = format!("GET:{}", path);
794        self.register(&handler_name, handler);
795        self.add_route(RouteMetadata::new(path, Method::GET, "rest"));
796    }
797
798    /// Register a POST route
799    ///
800    /// This is a convenience method that registers both a handler and route
801    /// metadata for a POST request. The handler name is automatically
802    /// generated as "POST:{path}".
803    pub fn post<F, Fut>(&mut self, path: &str, handler: F)
804    where
805        F: Fn() -> Fut + Send + Sync + 'static,
806        Fut: Future<Output = String> + Send + 'static,
807    {
808        let handler_name = format!("POST:{}", path);
809        self.register(&handler_name, handler);
810        self.add_route(RouteMetadata::new(path, Method::POST, "rest"));
811    }
812
813    /// Register a PUT route
814    ///
815    /// This is a convenience method that registers both a handler and route
816    /// metadata for a PUT request. The handler name is automatically
817    /// generated as "PUT:{path}".
818    pub fn put<F, Fut>(&mut self, path: &str, handler: F)
819    where
820        F: Fn() -> Fut + Send + Sync + 'static,
821        Fut: Future<Output = String> + Send + 'static,
822    {
823        let handler_name = format!("PUT:{}", path);
824        self.register(&handler_name, handler);
825        self.add_route(RouteMetadata::new(path, Method::PUT, "rest"));
826    }
827
828    /// Register a DELETE route
829    ///
830    /// This is a convenience method that registers both a handler and route
831    /// metadata for a DELETE request. The handler name is automatically
832    /// generated as "DELETE:{path}".
833    pub fn delete<F, Fut>(&mut self, path: &str, handler: F)
834    where
835        F: Fn() -> Fut + Send + Sync + 'static,
836        Fut: Future<Output = String> + Send + 'static,
837    {
838        let handler_name = format!("DELETE:{}", path);
839        self.register(&handler_name, handler);
840        self.add_route(RouteMetadata::new(path, Method::DELETE, "rest"));
841    }
842
843    /// Register a PATCH route
844    ///
845    /// This is a convenience method that registers both a handler and route
846    /// metadata for a PATCH request. The handler name is automatically
847    /// generated as "PATCH:{path}".
848    pub fn patch<F, Fut>(&mut self, path: &str, handler: F)
849    where
850        F: Fn() -> Fut + Send + Sync + 'static,
851        Fut: Future<Output = String> + Send + 'static,
852    {
853        let handler_name = format!("PATCH:{}", path);
854        self.register(&handler_name, handler);
855        self.add_route(RouteMetadata::new(path, Method::PATCH, "rest"));
856    }
857
858    /// Register a HEAD route
859    ///
860    /// This is a convenience method that registers both a handler and route
861    /// metadata for a HEAD request. The handler name is automatically
862    /// generated as "HEAD:{path}".
863    pub fn head<F, Fut>(&mut self, path: &str, handler: F)
864    where
865        F: Fn() -> Fut + Send + Sync + 'static,
866        Fut: Future<Output = String> + Send + 'static,
867    {
868        let handler_name = format!("HEAD:{}", path);
869        self.register(&handler_name, handler);
870        self.add_route(RouteMetadata::new(path, Method::HEAD, "rest"));
871    }
872
873    /// Register an OPTIONS route
874    ///
875    /// This is a convenience method that registers both a handler and route
876    /// metadata for an OPTIONS request. The handler name is automatically
877    /// generated as "OPTIONS:{path}".
878    pub fn options<F, Fut>(&mut self, path: &str, handler: F)
879    where
880        F: Fn() -> Fut + Send + Sync + 'static,
881        Fut: Future<Output = String> + Send + 'static,
882    {
883        let handler_name = format!("OPTIONS:{}", path);
884        self.register(&handler_name, handler);
885        self.add_route(RouteMetadata::new(path, Method::OPTIONS, "rest"));
886    }
887
888    /// Call handler via REST
889    pub async fn call_rest(&self, method: &str, path: &str) -> Result<String, String> {
890        let adapter = self
891            .adapters
892            .get("rest")
893            .ok_or_else(|| "REST adapter not enabled".to_string())?;
894
895        let request = format!("{} {}", method, path);
896        adapter.handle(&request).await
897    }
898
899    /// Call handler via GraphQL
900    pub async fn call_graphql(&self, query: &str) -> Result<String, String> {
901        let adapter = self
902            .adapters
903            .get("graphql")
904            .ok_or_else(|| "GraphQL adapter not enabled".to_string())?;
905
906        adapter.handle(query).await
907    }
908
909    /// Call handler via gRPC
910    pub async fn call_grpc(&self, method: &str, request: &str) -> Result<String, String> {
911        let adapter = self
912            .adapters
913            .get("grpc")
914            .ok_or_else(|| "gRPC adapter not enabled".to_string())?;
915
916        let grpc_request = format!("{}:{}", method, request);
917        adapter.handle(&grpc_request).await
918    }
919
920    /// Generate Scalar documentation HTML with default configuration
921    ///
922    /// This is a convenience method that generates a complete HTML page
923    /// with Scalar UI for interactive API documentation.
924    ///
925    /// # Arguments
926    ///
927    /// * `title` - API title
928    /// * `version` - API version
929    ///
930    /// # Example
931    ///
932    /// ```rust
933    /// use allframe_core::router::Router;
934    ///
935    /// let mut router = Router::new();
936    /// router.get("/users", || async { "Users".to_string() });
937    ///
938    /// let html = router.scalar("My API", "1.0.0");
939    /// // Serve this HTML at /docs endpoint
940    /// ```
941    pub fn scalar(&self, title: &str, version: &str) -> String {
942        let config = scalar::ScalarConfig::default();
943        self.scalar_docs(config, title, version)
944    }
945
946    /// Generate Scalar documentation HTML with custom configuration
947    ///
948    /// This method allows full customization of the Scalar UI appearance
949    /// and behavior.
950    ///
951    /// # Arguments
952    ///
953    /// * `config` - Scalar configuration
954    /// * `title` - API title
955    /// * `version` - API version
956    ///
957    /// # Example
958    ///
959    /// ```rust
960    /// use allframe_core::router::{Router, ScalarConfig, ScalarTheme};
961    ///
962    /// let mut router = Router::new();
963    /// router.get("/users", || async { "Users".to_string() });
964    ///
965    /// let config = ScalarConfig::new()
966    ///     .theme(ScalarTheme::Light)
967    ///     .show_sidebar(false);
968    ///
969    /// let html = router.scalar_docs(config, "My API", "1.0.0");
970    /// ```
971    pub fn scalar_docs(&self, config: scalar::ScalarConfig, title: &str, version: &str) -> String {
972        // Generate OpenAPI spec
973        let spec = OpenApiGenerator::new(title, version).generate(self);
974        let spec_json = serde_json::to_string(&spec).unwrap_or_else(|_| "{}".to_string());
975
976        // Generate Scalar HTML
977        scalar::scalar_html(&config, title, &spec_json)
978    }
979}
980
981impl Default for Router {
982    fn default() -> Self {
983        Self::new()
984    }
985}
986
987#[cfg(test)]
988mod tests {
989    use super::*;
990
991    #[tokio::test]
992    async fn test_router_creation() {
993        let router = Router::new();
994        assert_eq!(router.handlers_count(), 0);
995    }
996
997    #[tokio::test]
998    async fn test_handler_registration() {
999        let mut router = Router::new();
1000        router.register("test", || async { "Hello".to_string() });
1001        assert_eq!(router.handlers_count(), 1);
1002    }
1003
1004    #[tokio::test]
1005    async fn test_handler_execution() {
1006        let mut router = Router::new();
1007        router.register("test", || async { "Hello".to_string() });
1008        let result = router.execute("test").await;
1009        assert_eq!(result, Ok("Hello".to_string()));
1010    }
1011
1012    // New tests for route metadata tracking
1013    #[tokio::test]
1014    async fn test_router_starts_with_no_routes() {
1015        let router = Router::new();
1016        let routes = router.routes();
1017        assert_eq!(routes.len(), 0);
1018    }
1019
1020    #[tokio::test]
1021    async fn test_add_route_metadata() {
1022        let mut router = Router::new();
1023        let metadata = RouteMetadata::new("/users", "GET", "rest");
1024
1025        router.add_route(metadata.clone());
1026
1027        let routes = router.routes();
1028        assert_eq!(routes.len(), 1);
1029        assert_eq!(routes[0].path, "/users");
1030        assert_eq!(routes[0].method, "GET");
1031        assert_eq!(routes[0].protocol, "rest");
1032    }
1033
1034    #[tokio::test]
1035    async fn test_add_multiple_routes() {
1036        let mut router = Router::new();
1037
1038        router.add_route(RouteMetadata::new("/users", "GET", "rest"));
1039        router.add_route(RouteMetadata::new("/users", "POST", "rest"));
1040        router.add_route(RouteMetadata::new("/posts", "GET", "rest"));
1041
1042        let routes = router.routes();
1043        assert_eq!(routes.len(), 3);
1044    }
1045
1046    #[tokio::test]
1047    async fn test_routes_with_different_protocols() {
1048        let mut router = Router::new();
1049
1050        router.add_route(RouteMetadata::new("/users", "GET", "rest"));
1051        router.add_route(RouteMetadata::new("users", "query", "graphql"));
1052        router.add_route(RouteMetadata::new("UserService.GetUser", "unary", "grpc"));
1053
1054        let routes = router.routes();
1055        assert_eq!(routes.len(), 3);
1056
1057        assert_eq!(routes[0].protocol, "rest");
1058        assert_eq!(routes[1].protocol, "graphql");
1059        assert_eq!(routes[2].protocol, "grpc");
1060    }
1061
1062    #[tokio::test]
1063    async fn test_routes_returns_immutable_reference() {
1064        let mut router = Router::new();
1065        router.add_route(RouteMetadata::new("/test", "GET", "rest"));
1066
1067        let routes1 = router.routes();
1068        let routes2 = router.routes();
1069
1070        // Both should have the same data
1071        assert_eq!(routes1.len(), routes2.len());
1072        assert_eq!(routes1[0].path, routes2[0].path);
1073    }
1074
1075    // Tests for type-safe route registration
1076    #[tokio::test]
1077    async fn test_route_get_method() {
1078        let mut router = Router::new();
1079        router.get("/users", || async { "User list".to_string() });
1080
1081        let routes = router.routes();
1082        assert_eq!(routes.len(), 1);
1083        assert_eq!(routes[0].path, "/users");
1084        assert_eq!(routes[0].method, "GET");
1085        assert_eq!(routes[0].protocol, "rest");
1086    }
1087
1088    #[tokio::test]
1089    async fn test_route_post_method() {
1090        let mut router = Router::new();
1091        router.post("/users", || async { "User created".to_string() });
1092
1093        let routes = router.routes();
1094        assert_eq!(routes.len(), 1);
1095        assert_eq!(routes[0].path, "/users");
1096        assert_eq!(routes[0].method, "POST");
1097        assert_eq!(routes[0].protocol, "rest");
1098    }
1099
1100    #[tokio::test]
1101    async fn test_route_put_method() {
1102        let mut router = Router::new();
1103        router.put("/users/1", || async { "User updated".to_string() });
1104
1105        let routes = router.routes();
1106        assert_eq!(routes.len(), 1);
1107        assert_eq!(routes[0].method, "PUT");
1108    }
1109
1110    #[tokio::test]
1111    async fn test_route_delete_method() {
1112        let mut router = Router::new();
1113        router.delete("/users/1", || async { "User deleted".to_string() });
1114
1115        let routes = router.routes();
1116        assert_eq!(routes.len(), 1);
1117        assert_eq!(routes[0].method, "DELETE");
1118    }
1119
1120    #[tokio::test]
1121    async fn test_route_patch_method() {
1122        let mut router = Router::new();
1123        router.patch("/users/1", || async { "User patched".to_string() });
1124
1125        let routes = router.routes();
1126        assert_eq!(routes.len(), 1);
1127        assert_eq!(routes[0].method, "PATCH");
1128    }
1129
1130    #[tokio::test]
1131    async fn test_multiple_routes_different_methods() {
1132        let mut router = Router::new();
1133        router.get("/users", || async { "List".to_string() });
1134        router.post("/users", || async { "Create".to_string() });
1135        router.put("/users/1", || async { "Update".to_string() });
1136        router.delete("/users/1", || async { "Delete".to_string() });
1137
1138        let routes = router.routes();
1139        assert_eq!(routes.len(), 4);
1140
1141        assert_eq!(routes[0].method, "GET");
1142        assert_eq!(routes[1].method, "POST");
1143        assert_eq!(routes[2].method, "PUT");
1144        assert_eq!(routes[3].method, "DELETE");
1145    }
1146
1147    #[tokio::test]
1148    async fn test_route_method_with_path_params() {
1149        let mut router = Router::new();
1150        router.get("/users/{id}", || async { "User details".to_string() });
1151        router.get("/users/{id}/posts/{post_id}", || async {
1152            "Post details".to_string()
1153        });
1154
1155        let routes = router.routes();
1156        assert_eq!(routes.len(), 2);
1157        assert_eq!(routes[0].path, "/users/{id}");
1158        assert_eq!(routes[1].path, "/users/{id}/posts/{post_id}");
1159    }
1160
1161    #[tokio::test]
1162    async fn test_route_registration_and_execution() {
1163        let mut router = Router::new();
1164        router.get("/test", || async { "GET response".to_string() });
1165        router.post("/test", || async { "POST response".to_string() });
1166
1167        // Both route metadata and handler should be registered
1168        assert_eq!(router.routes().len(), 2);
1169        assert_eq!(router.handlers_count(), 2);
1170
1171        // Handlers should be executable
1172        let result1 = router.execute("GET:/test").await;
1173        let result2 = router.execute("POST:/test").await;
1174
1175        assert_eq!(result1, Ok("GET response".to_string()));
1176        assert_eq!(result2, Ok("POST response".to_string()));
1177    }
1178
1179    // Tests for Scalar integration
1180    #[tokio::test]
1181    async fn test_scalar_generates_html() {
1182        let mut router = Router::new();
1183        router.get("/users", || async { "Users".to_string() });
1184
1185        let html = router.scalar("Test API", "1.0.0");
1186
1187        assert!(html.contains("<!DOCTYPE html>"));
1188        assert!(html.contains("<title>Test API - API Documentation</title>"));
1189        assert!(html.contains("@scalar/api-reference"));
1190    }
1191
1192    #[tokio::test]
1193    async fn test_scalar_contains_openapi_spec() {
1194        let mut router = Router::new();
1195        router.get("/users", || async { "Users".to_string() });
1196        router.post("/users", || async { "User created".to_string() });
1197
1198        let html = router.scalar("Test API", "1.0.0");
1199
1200        // Should contain the OpenAPI spec
1201        assert!(html.contains("openapi"));
1202        assert!(html.contains("Test API"));
1203        assert!(html.contains("1.0.0"));
1204    }
1205
1206    #[tokio::test]
1207    async fn test_scalar_docs_with_custom_config() {
1208        let mut router = Router::new();
1209        router.get("/users", || async { "Users".to_string() });
1210
1211        let config = scalar::ScalarConfig::new()
1212            .theme(scalar::ScalarTheme::Light)
1213            .show_sidebar(false);
1214
1215        let html = router.scalar_docs(config, "Custom API", "2.0.0");
1216
1217        assert!(html.contains("Custom API"));
1218        assert!(html.contains(r#""theme":"light""#));
1219        assert!(html.contains(r#""showSidebar":false"#));
1220    }
1221
1222    #[tokio::test]
1223    async fn test_scalar_docs_with_custom_css() {
1224        let mut router = Router::new();
1225        router.get("/test", || async { "Test".to_string() });
1226
1227        let config = scalar::ScalarConfig::new().custom_css("body { font-family: 'Inter'; }");
1228
1229        let html = router.scalar_docs(config, "API", "1.0");
1230
1231        assert!(html.contains("<style>body { font-family: 'Inter'; }</style>"));
1232    }
1233
1234    #[tokio::test]
1235    async fn test_scalar_with_multiple_routes() {
1236        let mut router = Router::new();
1237        router.get("/users", || async { "Users".to_string() });
1238        router.post("/users", || async { "Create".to_string() });
1239        router.get("/users/{id}", || async { "User details".to_string() });
1240        router.delete("/users/{id}", || async { "Delete".to_string() });
1241
1242        let html = router.scalar("API", "1.0.0");
1243
1244        // Should contain all routes in the OpenAPI spec
1245        assert!(html.contains("/users"));
1246    }
1247
1248    // Tests for protocol adapter management
1249    #[tokio::test]
1250    async fn test_get_adapter_returns_adapter() {
1251        let mut router = Router::new();
1252        router.add_adapter(Box::new(RestAdapter::new()));
1253
1254        let adapter = router.get_adapter("rest");
1255        assert!(adapter.is_some());
1256        assert_eq!(adapter.unwrap().name(), "rest");
1257    }
1258
1259    #[tokio::test]
1260    async fn test_get_adapter_returns_none_for_missing() {
1261        let router = Router::new();
1262        let adapter = router.get_adapter("rest");
1263        assert!(adapter.is_none());
1264    }
1265
1266    #[tokio::test]
1267    async fn test_route_request_success() {
1268        let mut router = Router::new();
1269        router.register("test_handler", || async { "Success!".to_string() });
1270
1271        // Register adapter with a route
1272        let mut rest_adapter = RestAdapter::new();
1273        rest_adapter.route("GET", "/test", "test_handler");
1274        router.add_adapter(Box::new(rest_adapter));
1275
1276        let result = router.route_request("rest", "GET /test").await;
1277        assert!(result.is_ok());
1278        let response = result.unwrap();
1279        assert!(response.contains("HTTP 200") || response.contains("test_handler"));
1280    }
1281
1282    #[tokio::test]
1283    async fn test_route_request_unknown_adapter() {
1284        let router = Router::new();
1285        let result = router.route_request("unknown", "test").await;
1286        assert!(result.is_err());
1287        assert!(result.unwrap_err().contains("Adapter not found"));
1288    }
1289
1290    #[tokio::test]
1291    async fn test_enabled_protocols_empty() {
1292        let router = Router::new();
1293        let protocols = router.enabled_protocols();
1294        assert_eq!(protocols.len(), 0);
1295    }
1296
1297    #[tokio::test]
1298    async fn test_enabled_protocols_multiple() {
1299        let mut router = Router::new();
1300        router.add_adapter(Box::new(RestAdapter::new()));
1301        router.add_adapter(Box::new(GraphQLAdapter::new()));
1302        router.add_adapter(Box::new(GrpcAdapter::new()));
1303
1304        let protocols = router.enabled_protocols();
1305        assert_eq!(protocols.len(), 3);
1306        assert!(protocols.contains(&"rest".to_string()));
1307        assert!(protocols.contains(&"graphql".to_string()));
1308        assert!(protocols.contains(&"grpc".to_string()));
1309    }
1310
1311    #[tokio::test]
1312    async fn test_can_handle_rest() {
1313        let mut router = Router::new();
1314        assert!(!router.can_handle_rest("test"));
1315
1316        router.add_adapter(Box::new(RestAdapter::new()));
1317        assert!(router.can_handle_rest("test"));
1318    }
1319
1320    #[tokio::test]
1321    async fn test_can_handle_graphql() {
1322        let mut router = Router::new();
1323        assert!(!router.can_handle_graphql("test"));
1324
1325        router.add_adapter(Box::new(GraphQLAdapter::new()));
1326        assert!(router.can_handle_graphql("test"));
1327    }
1328
1329    #[tokio::test]
1330    async fn test_can_handle_grpc() {
1331        let mut router = Router::new();
1332        assert!(!router.can_handle_grpc("test"));
1333
1334        router.add_adapter(Box::new(GrpcAdapter::new()));
1335        assert!(router.can_handle_grpc("test"));
1336    }
1337
1338    // ===== Integration Tests: Multi-Protocol Routing =====
1339
1340    #[tokio::test]
1341    async fn test_integration_single_handler_rest() {
1342        // Test: Single handler exposed via REST
1343        let mut router = Router::new();
1344        router.register("get_user", || async { "User data".to_string() });
1345
1346        // Configure REST adapter
1347        let mut rest = RestAdapter::new();
1348        rest.route("GET", "/users/:id", "get_user");
1349        router.add_adapter(Box::new(rest));
1350
1351        // Route REST request
1352        let response = router.route_request("rest", "GET /users/42").await;
1353        assert!(response.is_ok());
1354        assert!(response.unwrap().contains("get_user"));
1355    }
1356
1357    #[tokio::test]
1358    async fn test_integration_single_handler_graphql() {
1359        // Test: Single handler exposed via GraphQL
1360        let mut router = Router::new();
1361        router.register("get_user", || async { "User data".to_string() });
1362
1363        // Configure GraphQL adapter
1364        let mut graphql = GraphQLAdapter::new();
1365        graphql.query("user", "get_user");
1366        router.add_adapter(Box::new(graphql));
1367
1368        // Route GraphQL request
1369        let response = router.route_request("graphql", "query { user }").await;
1370        assert!(response.is_ok());
1371        assert!(response.unwrap().contains("get_user"));
1372    }
1373
1374    #[tokio::test]
1375    async fn test_integration_single_handler_grpc() {
1376        // Test: Single handler exposed via gRPC
1377        let mut router = Router::new();
1378        router.register("get_user", || async { "User data".to_string() });
1379
1380        // Configure gRPC adapter
1381        let mut grpc = GrpcAdapter::new();
1382        grpc.unary("UserService", "GetUser", "get_user");
1383        router.add_adapter(Box::new(grpc));
1384
1385        // Route gRPC request
1386        let response = router
1387            .route_request("grpc", "UserService.GetUser:{\"id\":42}")
1388            .await;
1389        assert!(response.is_ok());
1390        assert!(response.unwrap().contains("get_user"));
1391    }
1392
1393    #[tokio::test]
1394    async fn test_integration_single_handler_all_protocols() {
1395        // Test: Single handler exposed via ALL protocols
1396        let mut router = Router::new();
1397        router.register("get_user", || async { "User data".to_string() });
1398
1399        // Configure REST adapter
1400        let mut rest = RestAdapter::new();
1401        rest.route("GET", "/users/:id", "get_user");
1402        router.add_adapter(Box::new(rest));
1403
1404        // Configure GraphQL adapter
1405        let mut graphql = GraphQLAdapter::new();
1406        graphql.query("user", "get_user");
1407        router.add_adapter(Box::new(graphql));
1408
1409        // Configure gRPC adapter
1410        let mut grpc = GrpcAdapter::new();
1411        grpc.unary("UserService", "GetUser", "get_user");
1412        router.add_adapter(Box::new(grpc));
1413
1414        // Test REST
1415        let rest_response = router.route_request("rest", "GET /users/42").await;
1416        assert!(rest_response.is_ok());
1417        assert!(rest_response.unwrap().contains("get_user"));
1418
1419        // Test GraphQL
1420        let graphql_response = router.route_request("graphql", "query { user }").await;
1421        assert!(graphql_response.is_ok());
1422        assert!(graphql_response.unwrap().contains("get_user"));
1423
1424        // Test gRPC
1425        let grpc_response = router
1426            .route_request("grpc", "UserService.GetUser:{\"id\":42}")
1427            .await;
1428        assert!(grpc_response.is_ok());
1429        assert!(grpc_response.unwrap().contains("get_user"));
1430    }
1431
1432    #[tokio::test]
1433    async fn test_integration_multiple_handlers_all_protocols() {
1434        // Test: Multiple handlers, each exposed via all protocols
1435        let mut router = Router::new();
1436        router.register("get_user", || async { "User data".to_string() });
1437        router.register("list_users", || async { "Users list".to_string() });
1438        router.register("create_user", || async { "Created user".to_string() });
1439
1440        // Configure REST adapter
1441        let mut rest = RestAdapter::new();
1442        rest.route("GET", "/users/:id", "get_user");
1443        rest.route("GET", "/users", "list_users");
1444        rest.route("POST", "/users", "create_user");
1445        router.add_adapter(Box::new(rest));
1446
1447        // Configure GraphQL adapter
1448        let mut graphql = GraphQLAdapter::new();
1449        graphql.query("user", "get_user");
1450        graphql.query("users", "list_users");
1451        graphql.mutation("createUser", "create_user");
1452        router.add_adapter(Box::new(graphql));
1453
1454        // Configure gRPC adapter
1455        let mut grpc = GrpcAdapter::new();
1456        grpc.unary("UserService", "GetUser", "get_user");
1457        grpc.unary("UserService", "ListUsers", "list_users");
1458        grpc.unary("UserService", "CreateUser", "create_user");
1459        router.add_adapter(Box::new(grpc));
1460
1461        // Test each handler via each protocol
1462        assert!(router
1463            .route_request("rest", "GET /users/42")
1464            .await
1465            .unwrap()
1466            .contains("get_user"));
1467        assert!(router
1468            .route_request("graphql", "query { user }")
1469            .await
1470            .unwrap()
1471            .contains("get_user"));
1472        assert!(router
1473            .route_request("grpc", "UserService.GetUser:{}")
1474            .await
1475            .unwrap()
1476            .contains("get_user"));
1477    }
1478
1479    #[tokio::test]
1480    async fn test_integration_error_handling_rest_404() {
1481        // Test: REST 404 error
1482        let mut router = Router::new();
1483
1484        let mut rest = RestAdapter::new();
1485        rest.route("GET", "/users/:id", "get_user");
1486        router.add_adapter(Box::new(rest));
1487
1488        let response = router.route_request("rest", "GET /posts/42").await;
1489        assert!(response.is_ok());
1490        assert!(response.unwrap().contains("HTTP 404"));
1491    }
1492
1493    #[tokio::test]
1494    async fn test_integration_error_handling_graphql_not_found() {
1495        // Test: GraphQL operation not found
1496        let mut router = Router::new();
1497
1498        let mut graphql = GraphQLAdapter::new();
1499        graphql.query("user", "get_user");
1500        router.add_adapter(Box::new(graphql));
1501
1502        let response = router.route_request("graphql", "query { post }").await;
1503        assert!(response.is_ok());
1504        assert!(response.unwrap().contains("errors"));
1505    }
1506
1507    #[tokio::test]
1508    async fn test_integration_error_handling_grpc_unimplemented() {
1509        // Test: gRPC method not implemented
1510        let mut router = Router::new();
1511
1512        let mut grpc = GrpcAdapter::new();
1513        grpc.unary("UserService", "GetUser", "get_user");
1514        router.add_adapter(Box::new(grpc));
1515
1516        let response = router.route_request("grpc", "UserService.GetPost:{}").await;
1517        assert!(response.is_ok());
1518        assert!(response.unwrap().contains("grpc-status: 12")); // UNIMPLEMENTED
1519    }
1520
1521    #[tokio::test]
1522    async fn test_integration_unknown_protocol() {
1523        // Test: Unknown protocol error
1524        let router = Router::new();
1525
1526        let response = router.route_request("unknown", "request").await;
1527        assert!(response.is_err());
1528        assert!(response.unwrap_err().contains("Adapter not found"));
1529    }
1530
1531    #[tokio::test]
1532    async fn test_integration_protocol_specific_features_rest_methods() {
1533        // Test: REST-specific HTTP methods
1534        let mut router = Router::new();
1535        router.register("get_users", || async { "Users".to_string() });
1536        router.register("create_user", || async { "Created".to_string() });
1537        router.register("update_user", || async { "Updated".to_string() });
1538        router.register("delete_user", || async { "Deleted".to_string() });
1539
1540        let mut rest = RestAdapter::new();
1541        rest.route("GET", "/users", "get_users");
1542        rest.route("POST", "/users", "create_user");
1543        rest.route("PUT", "/users/:id", "update_user");
1544        rest.route("DELETE", "/users/:id", "delete_user");
1545        router.add_adapter(Box::new(rest));
1546
1547        // Test different HTTP methods
1548        assert!(router
1549            .route_request("rest", "GET /users")
1550            .await
1551            .unwrap()
1552            .contains("get_users"));
1553        assert!(router
1554            .route_request("rest", "POST /users")
1555            .await
1556            .unwrap()
1557            .contains("create_user"));
1558        assert!(router
1559            .route_request("rest", "PUT /users/42")
1560            .await
1561            .unwrap()
1562            .contains("update_user"));
1563        assert!(router
1564            .route_request("rest", "DELETE /users/42")
1565            .await
1566            .unwrap()
1567            .contains("delete_user"));
1568    }
1569
1570    #[tokio::test]
1571    async fn test_integration_protocol_specific_features_graphql_types() {
1572        // Test: GraphQL-specific query vs mutation
1573        let mut router = Router::new();
1574        router.register("get_user", || async { "User".to_string() });
1575        router.register("create_user", || async { "Created".to_string() });
1576
1577        let mut graphql = GraphQLAdapter::new();
1578        graphql.query("user", "get_user");
1579        graphql.mutation("createUser", "create_user");
1580        router.add_adapter(Box::new(graphql));
1581
1582        // Test query
1583        assert!(router
1584            .route_request("graphql", "query { user }")
1585            .await
1586            .unwrap()
1587            .contains("get_user"));
1588
1589        // Test mutation
1590        assert!(router
1591            .route_request("graphql", "mutation { createUser }")
1592            .await
1593            .unwrap()
1594            .contains("create_user"));
1595    }
1596
1597    #[tokio::test]
1598    async fn test_integration_protocol_specific_features_grpc_streaming() {
1599        // Test: gRPC-specific streaming modes
1600        let mut router = Router::new();
1601        router.register("get_user", || async { "User".to_string() });
1602        router.register("list_users", || async { "Users".to_string() });
1603
1604        let mut grpc = GrpcAdapter::new();
1605        grpc.unary("UserService", "GetUser", "get_user");
1606        grpc.server_streaming("UserService", "ListUsers", "list_users");
1607        router.add_adapter(Box::new(grpc));
1608
1609        // Test unary
1610        let unary_response = router
1611            .route_request("grpc", "UserService.GetUser:{}")
1612            .await
1613            .unwrap();
1614        assert!(unary_response.contains("unary"));
1615
1616        // Test server streaming
1617        let streaming_response = router
1618            .route_request("grpc", "UserService.ListUsers:{}")
1619            .await
1620            .unwrap();
1621        assert!(streaming_response.contains("server_streaming"));
1622    }
1623
1624    // ===== Streaming handler registration tests =====
1625
1626    #[tokio::test]
1627    async fn test_register_streaming_handler() {
1628        let mut router = Router::new();
1629        router.register_streaming("stream_data", |tx: StreamSender| async move {
1630            tx.send("item".to_string()).await.ok();
1631            "done".to_string()
1632        });
1633        assert!(router.is_streaming("stream_data"));
1634        assert!(!router.is_streaming("nonexistent"));
1635    }
1636
1637    #[tokio::test]
1638    async fn test_register_streaming_with_args() {
1639        #[derive(serde::Deserialize)]
1640        struct Input {
1641            count: usize,
1642        }
1643
1644        let mut router = Router::new();
1645        router.register_streaming_with_args("stream_items", |args: Input, tx: StreamSender| async move {
1646            for i in 0..args.count {
1647                tx.send(format!("item-{i}")).await.ok();
1648            }
1649            "done".to_string()
1650        });
1651        assert!(router.is_streaming("stream_items"));
1652    }
1653
1654    #[tokio::test]
1655    async fn test_streaming_handler_not_in_regular_handlers() {
1656        let mut router = Router::new();
1657        router.register_streaming("stream", |_tx: StreamSender| async move {
1658            "done".to_string()
1659        });
1660        // Streaming handlers are NOT in the regular handlers map
1661        assert_eq!(router.handlers_count(), 0);
1662    }
1663
1664    #[tokio::test]
1665    async fn test_list_handlers_includes_streaming() {
1666        let mut router = Router::new();
1667        router.register("regular", || async { "ok".to_string() });
1668        router.register_streaming("stream", |_tx: StreamSender| async move {
1669            "ok".to_string()
1670        });
1671
1672        let handlers = router.list_handlers();
1673        assert_eq!(handlers.len(), 2);
1674        assert!(handlers.contains(&"regular".to_string()));
1675        assert!(handlers.contains(&"stream".to_string()));
1676    }
1677
1678    #[tokio::test]
1679    async fn test_call_streaming_handler() {
1680        let mut router = Router::new();
1681        router.register_streaming("stream", |tx: StreamSender| async move {
1682            tx.send("a".to_string()).await.ok();
1683            tx.send("b".to_string()).await.ok();
1684            "final".to_string()
1685        });
1686
1687        let (mut rx, fut) = router.call_streaming_handler("stream", "{}").unwrap();
1688        let result = fut.await;
1689
1690        assert_eq!(result, Ok("final".to_string()));
1691        assert_eq!(rx.recv().await, Some("a".to_string()));
1692        assert_eq!(rx.recv().await, Some("b".to_string()));
1693    }
1694
1695    #[tokio::test]
1696    async fn test_call_streaming_handler_with_args() {
1697        #[derive(serde::Deserialize)]
1698        struct Input {
1699            n: usize,
1700        }
1701
1702        let mut router = Router::new();
1703        router.register_streaming_with_args("count", |args: Input, tx: StreamSender| async move {
1704            for i in 0..args.n {
1705                tx.send(format!("{i}")).await.ok();
1706            }
1707            format!("counted to {}", args.n)
1708        });
1709
1710        let (mut rx, fut) = router.call_streaming_handler("count", r#"{"n":3}"#).unwrap();
1711        let result = fut.await;
1712
1713        assert_eq!(result, Ok("counted to 3".to_string()));
1714        assert_eq!(rx.recv().await, Some("0".to_string()));
1715        assert_eq!(rx.recv().await, Some("1".to_string()));
1716        assert_eq!(rx.recv().await, Some("2".to_string()));
1717    }
1718
1719    #[tokio::test]
1720    async fn test_call_streaming_handler_not_found() {
1721        let router = Router::new();
1722        let result = router.call_streaming_handler("missing", "{}");
1723        assert!(result.is_err());
1724        match result {
1725            Err(e) => assert!(e.contains("not found")),
1726            Ok(_) => panic!("expected error"),
1727        }
1728    }
1729
1730    #[tokio::test]
1731    async fn test_is_streaming_false_for_regular() {
1732        let mut router = Router::new();
1733        router.register("regular", || async { "ok".to_string() });
1734        assert!(!router.is_streaming("regular"));
1735    }
1736
1737    #[tokio::test]
1738    async fn test_mixed_router() {
1739        let mut router = Router::new();
1740        router.register("get_user", || async { "user".to_string() });
1741        router.register_streaming("stream_updates", |tx: StreamSender| async move {
1742            tx.send("update".to_string()).await.ok();
1743            "done".to_string()
1744        });
1745
1746        // Regular handler works
1747        let result = router.execute("get_user").await;
1748        assert_eq!(result, Ok("user".to_string()));
1749
1750        // Streaming handler works
1751        let (mut rx, fut) = router.call_streaming_handler("stream_updates", "{}").unwrap();
1752        let result = fut.await;
1753        assert_eq!(result, Ok("done".to_string()));
1754        assert_eq!(rx.recv().await, Some("update".to_string()));
1755
1756        // Regular handler not found in streaming
1757        assert!(!router.is_streaming("get_user"));
1758        assert!(router.call_streaming_handler("get_user", "{}").is_err());
1759    }
1760
1761    #[tokio::test]
1762    async fn test_register_streaming_with_state() {
1763        struct AppState {
1764            prefix: String,
1765        }
1766
1767        #[derive(serde::Deserialize)]
1768        struct Input {
1769            name: String,
1770        }
1771
1772        let mut router = Router::new().with_state(AppState {
1773            prefix: "Hello".to_string(),
1774        });
1775        router.register_streaming_with_state::<AppState, Input, _, _, _>(
1776            "greet_stream",
1777            |state: State<Arc<AppState>>, args: Input, tx: StreamSender| async move {
1778                tx.send(format!("{} {}", state.prefix, args.name))
1779                    .await
1780                    .ok();
1781                "done".to_string()
1782            },
1783        );
1784
1785        let (mut rx, fut) = router
1786            .call_streaming_handler("greet_stream", r#"{"name":"Alice"}"#)
1787            .unwrap();
1788        let result = fut.await;
1789
1790        assert_eq!(result, Ok("done".to_string()));
1791        assert_eq!(rx.recv().await, Some("Hello Alice".to_string()));
1792    }
1793
1794    #[tokio::test]
1795    async fn test_register_streaming_with_state_only() {
1796        struct AppState {
1797            items: Vec<String>,
1798        }
1799
1800        let mut router = Router::new().with_state(AppState {
1801            items: vec!["x".to_string(), "y".to_string()],
1802        });
1803        router.register_streaming_with_state_only::<AppState, _, _, _>(
1804            "list_stream",
1805            |state: State<Arc<AppState>>, tx: StreamSender| async move {
1806                for item in &state.items {
1807                    tx.send(item.clone()).await.ok();
1808                }
1809                format!("listed {}", state.items.len())
1810            },
1811        );
1812
1813        let (mut rx, fut) = router
1814            .call_streaming_handler("list_stream", "{}")
1815            .unwrap();
1816        let result = fut.await;
1817
1818        assert_eq!(result, Ok("listed 2".to_string()));
1819        assert_eq!(rx.recv().await, Some("x".to_string()));
1820        assert_eq!(rx.recv().await, Some("y".to_string()));
1821    }
1822
1823    // ===== Stream return adapter tests =====
1824
1825    #[tokio::test]
1826    async fn test_register_stream_no_args() {
1827        let mut router = Router::new();
1828        router.register_stream("items", || async {
1829            tokio_stream::iter(vec!["a".to_string(), "b".to_string(), "c".to_string()])
1830        });
1831
1832        assert!(router.is_streaming("items"));
1833
1834        let (mut rx, fut) = router.call_streaming_handler("items", "{}").unwrap();
1835        let _result = fut.await;
1836
1837        assert_eq!(rx.recv().await, Some("a".to_string()));
1838        assert_eq!(rx.recv().await, Some("b".to_string()));
1839        assert_eq!(rx.recv().await, Some("c".to_string()));
1840    }
1841
1842    #[tokio::test]
1843    async fn test_register_stream_with_args() {
1844        #[derive(serde::Deserialize)]
1845        struct Input {
1846            count: usize,
1847        }
1848
1849        let mut router = Router::new();
1850        router.register_stream_with_args("counting", |args: Input| async move {
1851            tokio_stream::iter((0..args.count).map(|i| format!("{i}")))
1852        });
1853
1854        assert!(router.is_streaming("counting"));
1855
1856        let (mut rx, fut) = router
1857            .call_streaming_handler("counting", r#"{"count":3}"#)
1858            .unwrap();
1859        let _result = fut.await;
1860
1861        assert_eq!(rx.recv().await, Some("0".to_string()));
1862        assert_eq!(rx.recv().await, Some("1".to_string()));
1863        assert_eq!(rx.recv().await, Some("2".to_string()));
1864    }
1865
1866    #[tokio::test]
1867    async fn test_register_stream_with_state() {
1868        struct AppState {
1869            items: Vec<String>,
1870        }
1871
1872        let mut router = Router::new().with_state(AppState {
1873            items: vec!["x".to_string(), "y".to_string()],
1874        });
1875        router.register_stream_with_state::<AppState, serde_json::Value, _, _, _, _>(
1876            "state_stream",
1877            |state: State<Arc<AppState>>, _args: serde_json::Value| {
1878                let items = state.items.clone();
1879                async move { tokio_stream::iter(items) }
1880            },
1881        );
1882
1883        assert!(router.is_streaming("state_stream"));
1884    }
1885
1886    #[tokio::test]
1887    async fn test_stream_adapter_shows_in_is_streaming() {
1888        let mut router = Router::new();
1889        router.register_stream("my_stream", || async {
1890            tokio_stream::iter(vec!["done".to_string()])
1891        });
1892
1893        assert!(router.is_streaming("my_stream"));
1894        assert!(!router.is_streaming("nonexistent"));
1895    }
1896}