reinhardt_admin/core/router.rs
1//! Admin router integration
2//!
3//! This module provides router integration for admin panel,
4//! generating ServerRouter from AdminSite configuration.
5//!
6//! All endpoints are registered automatically using the `.endpoint()` method
7//! with HTTP method macros from handlers module.
8
9use crate::core::AdminSite;
10use reinhardt_urls::routers::ServerRouter;
11use std::sync::Arc;
12
13/// Admin router builder
14///
15/// Builds a ServerRouter from an AdminSite with all CRUD endpoints.
16///
17/// # Examples
18///
19/// ```rust,no_run
20/// use reinhardt_admin::core::{AdminSite, admin_routes};
21///
22/// let site = AdminSite::new("My Admin");
23/// // ... register models ...
24///
25/// let router = admin_routes();
26/// ```
27pub fn admin_routes() -> ServerRouter {
28 // Server Functions are automatically registered via #[server_fn] macro
29 // No manual route registration needed - the macro generates routes at /api/server_fn/{function_name}
30 //
31 // Available Server Functions (from reinhardt-admin-server crate):
32 // - get_dashboard() -> DashboardResponse
33 // - get_list() -> ListResponse
34 // - get_detail() -> DetailResponse
35 // - create_record() -> MutationResponse
36 // - update_record() -> MutationResponse
37 // - delete_record() -> MutationResponse
38 // - bulk_delete_records() -> BulkDeleteResponse
39 // - export_data() -> ExportResponse
40 // - import_data() -> ImportResponse
41 // - get_fields() -> FieldsResponse
42 ServerRouter::new().with_namespace("admin")
43}
44
45/// Admin router builder (for backward compatibility)
46///
47/// This struct is kept for backward compatibility with existing code.
48/// New code should use `admin_routes()` function directly.
49pub struct AdminRouter {
50 site: Arc<AdminSite>,
51}
52
53impl AdminRouter {
54 /// Create a new admin router builder from Arc-wrapped site
55 pub fn from_arc(site: Arc<AdminSite>) -> Self {
56 Self { site }
57 }
58
59 /// Set favicon from file path
60 ///
61 /// # Examples
62 ///
63 /// ```rust,no_run
64 /// use reinhardt_admin::core::{AdminSite, AdminRouter};
65 /// use std::sync::Arc;
66 ///
67 /// let site = Arc::new(AdminSite::new("Admin"));
68 /// let router = AdminRouter::from_arc(site)
69 /// .with_favicon_file("static/favicon.ico")
70 /// .build();
71 /// ```
72 ///
73 /// # Panics
74 ///
75 /// Panics if the file cannot be read.
76 pub fn with_favicon_file(self, path: impl AsRef<std::path::Path>) -> Self {
77 let data = std::fs::read(path.as_ref()).expect("Failed to read favicon file");
78 self.site.set_favicon(data);
79 self
80 }
81
82 /// Set favicon from raw bytes
83 ///
84 /// # Examples
85 ///
86 /// ```rust,ignore
87 /// // Cannot run: favicon.ico file does not exist
88 /// use reinhardt_admin::core::{AdminSite, AdminRouter};
89 /// use std::sync::Arc;
90 ///
91 /// let favicon_bytes = include_bytes!("favicon.ico").to_vec();
92 /// let site = Arc::new(AdminSite::new("Admin"));
93 /// let router = AdminRouter::from_arc(site)
94 /// .with_favicon_bytes(favicon_bytes)
95 /// .build();
96 /// ```
97 pub fn with_favicon_bytes(self, data: Vec<u8>) -> Self {
98 self.site.set_favicon(data);
99 self
100 }
101
102 /// Build the ServerRouter with all admin endpoints
103 ///
104 /// Generated endpoints:
105 /// - `GET /` - Dashboard (list of registered models)
106 /// - `GET /favicon.ico` - Favicon
107 /// - `GET /{model}/` - List model instances
108 /// - `GET /{model}/{id}/` - Get model instance detail
109 /// - `POST /{model}/` - Create model instance
110 /// - `PUT /{model}/{id}/` - Update model instance
111 /// - `DELETE /{model}/{id}/` - Delete model instance
112 /// - `POST /{model}/bulk-delete/` - Bulk delete model instances
113 /// - `GET /{model}/export/` - Export model data
114 /// - `POST /{model}/import/` - Import model data
115 pub fn routes(&self) -> ServerRouter {
116 admin_routes()
117 }
118
119 /// Build the ServerRouter (alias for routes())
120 pub fn build(self) -> ServerRouter {
121 admin_routes()
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_admin_routes_creates_router() {
131 let router = admin_routes();
132 // Verify router is created with admin namespace
133 assert_eq!(router.namespace(), Some("admin"));
134 }
135
136 #[test]
137 fn test_admin_router_backward_compat() {
138 let site = Arc::new(AdminSite::new("Test Admin"));
139 let router_builder = AdminRouter::from_arc(site);
140 let router = router_builder.routes();
141 // Verify router is created
142 assert_eq!(router.namespace(), Some("admin"));
143 }
144}