nestrs_core/
route_registry.rs1use std::sync::{OnceLock, RwLock};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct OpenApiResponseDesc {
6 pub status: u16,
7 pub description: &'static str,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct OpenApiRouteSpec {
13 pub summary: Option<&'static str>,
14 pub tag: Option<&'static str>,
15 pub responses: &'static [OpenApiResponseDesc],
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct RouteInfo {
20 pub method: &'static str,
21 pub path: &'static str,
22 pub handler: &'static str,
23 pub openapi: Option<&'static OpenApiRouteSpec>,
24}
25
26fn store() -> &'static RwLock<Vec<RouteInfo>> {
27 static STORE: OnceLock<RwLock<Vec<RouteInfo>>> = OnceLock::new();
28 STORE.get_or_init(|| RwLock::new(Vec::new()))
29}
30
31pub struct RouteRegistry;
33
34impl RouteRegistry {
35 pub fn register(method: &'static str, path: &'static str, handler: &'static str) {
37 Self::register_spec(method, path, handler, None);
38 }
39
40 pub fn register_spec(
42 method: &'static str,
43 path: &'static str,
44 handler: &'static str,
45 openapi: Option<&'static OpenApiRouteSpec>,
46 ) {
47 let mut guard = store().write().expect("route registry lock poisoned");
48 guard.push(RouteInfo {
49 method,
50 path,
51 handler,
52 openapi,
53 });
54 }
55
56 pub fn list() -> Vec<RouteInfo> {
57 let guard = store().read().expect("route registry lock poisoned");
58 guard.clone()
59 }
60
61 #[cfg(feature = "test-hooks")]
67 pub fn clear_for_tests() {
68 let mut guard = store().write().expect("route registry lock poisoned");
69 guard.clear();
70 }
71}