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