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