Skip to main content

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}