reinhardt_pages/lib.rs
1//! Reinhardt Pages - WASM-based Frontend Framework
2//!
3//! A Django-inspired frontend framework for Reinhardt that preserves the benefits of
4//! Django templates while leveraging WebAssembly for modern interactivity.
5//!
6//! ## Features
7//!
8//! - **Fine-grained Reactivity**: Leptos/Solid.js-style Signal system with automatic dependency tracking
9//! - **Hybrid Rendering**: SSR + Client-side Hydration for optimal performance and SEO
10//! - **Django-like API**: Familiar patterns for Reinhardt developers
11//! - **Low-level Only**: Built on wasm-bindgen, web-sys, and js-sys (no high-level framework dependencies)
12//! - **Security First**: Built-in CSRF protection, XSS prevention, and session management
13//!
14//! ## Architecture
15//!
16//! This framework consists of several key modules:
17//!
18//! - [`reactive`]: Fine-grained reactivity system (Signal, Effect, Memo)
19//! - [`dom`]: DOM abstraction layer
20//! - [`builder`]: HTML element builder API
21//! - [`component`]: Component system with IntoPage trait, Head management
22//! - [`form`](mod@form): Django Form integration
23//! - [`csrf`]: CSRF protection
24//! - [`auth`]: Authentication integration
25//! - [`api`]: API client with Django QuerySet-like interface
26//! - [`server_fn`]: Server Functions (RPC)
27//! - [`ssr`]: Server-side rendering with Head support
28//! - [`hydration`]: Client-side hydration
29//! - [`router`]: Client-side routing (reinhardt-urls compatible)
30//! - [`static_resolver`]: Static file URL resolution (collectstatic support)
31//!
32//! ## Macros
33//!
34//! - [`page!`]: JSX-like macro for defining view components
35//! - [`head!`]: JSX-like macro for defining HTML head sections
36//!
37//! ## Example
38//!
39//! ### Basic Component
40//!
41//! ```ignore
42//! use reinhardt_pages::{Signal, Page, page};
43//!
44//! fn counter() -> Page {
45//! let count = Signal::new(0);
46//!
47//! page!(|| {
48//! div {
49//! p { "Count: " }
50//! button {
51//! @click: |_| count.update(|n| *n += 1),
52//! "Increment"
53//! }
54//! }
55//! })()
56//! }
57//! ```
58//!
59//! ### With Head Section
60//!
61//! ```ignore
62//! use reinhardt_pages::{head, page, Page, resolve_static};
63//!
64//! fn home_page() -> Page {
65//! let page_head = head!(|| {
66//! title { "Home - My App" }
67//! meta { name: "description", content: "Welcome to my app" }
68//! link { rel: "stylesheet", href: resolve_static("css/main.css") }
69//! });
70//!
71//! page! {
72//! #head: page_head,
73//! || {
74//! div { class: "container",
75//! h1 { "Welcome Home" }
76//! }
77//! }
78//! }()
79//! }
80//! ```
81//!
82//! ### WebSocket Integration
83//!
84//! The `use_websocket` hook provides reactive WebSocket connections:
85//!
86//! ```ignore
87//! use reinhardt_pages::reactive::hooks::{use_websocket, use_effect, UseWebSocketOptions};
88//! use reinhardt_pages::reactive::hooks::{ConnectionState, WebSocketMessage};
89//!
90//! fn chat_component() -> Page {
91//! // Establish WebSocket connection
92//! let ws = use_websocket("ws://localhost:8000/ws/chat", UseWebSocketOptions::default());
93//!
94//! // Monitor connection state reactively
95//! use_effect({
96//! let ws = ws.clone();
97//! move || {
98//! match ws.connection_state().get() {
99//! ConnectionState::Open => log!("Connected to chat"),
100//! ConnectionState::Closed => log!("Disconnected from chat"),
101//! ConnectionState::Error(e) => log!("Connection error: {}", e),
102//! _ => {}
103//! }
104//! None::<fn()>
105//! }
106//! });
107//!
108//! // Handle incoming messages
109//! use_effect({
110//! let ws = ws.clone();
111//! move || {
112//! if let Some(WebSocketMessage::Text(text)) = ws.latest_message().get() {
113//! log!("Received: {}", text);
114//! }
115//! None::<fn()>
116//! }
117//! });
118//!
119//! page!(|| {
120//! div {
121//! button {
122//! @click: move |_| {
123//! ws.send_text("Hello, server!".to_string()).ok();
124//! },
125//! "Send Message"
126//! }
127//! }
128//! })()
129//! }
130//! ```
131//!
132//! **Note**: WebSocket functionality is WASM-only. On the server side (SSR),
133//! `use_websocket` returns a no-op handle with connection state always set to `Closed`.
134
135#![warn(missing_docs)]
136
137// Re-export AST definitions from reinhardt-pages-ast
138// This is deprecated but kept for backward compatibility
139#[allow(deprecated)] // Intentional: maintaining backward compatibility with existing code
140pub use reinhardt_pages_ast as ast;
141
142// Core modules
143pub mod builder;
144pub mod callback;
145pub mod dom;
146pub mod logging;
147pub mod reactive;
148pub mod spawn;
149
150// Platform abstraction (unified types for WASM and native)
151pub mod platform;
152
153// Unified prelude for simplified imports
154pub mod prelude;
155
156// Component system
157pub mod component;
158
159// Form and security
160pub mod auth;
161pub mod csrf;
162// Static form metadata types for form! macro (WASM-compatible)
163pub mod form_generated;
164// FormComponent requires reinhardt-forms which is not WASM-compatible yet
165// For now, client-side forms should use PageElement
166#[cfg(not(target_arch = "wasm32"))]
167pub mod form;
168
169// API and communication
170pub mod api;
171pub mod server_fn;
172
173// Server-side rendering
174pub mod ssr;
175
176// Client-side hydration
177pub mod hydration;
178
179// Client-side routing
180pub mod router;
181
182// Integration modules (runtime support for special macros)
183pub mod integ;
184
185// Testing utilities (available on both WASM and server)
186// Layer 1: server_fn unit tests (server-side only)
187// Layer 2: Component + server_fn mock tests (WASM)
188// Layer 3: E2E tests (both platforms)
189pub mod testing;
190
191// Static file URL resolver
192pub mod static_resolver;
193
194// Re-export commonly used types
195pub use api::{ApiModel, ApiQuerySet, Filter, FilterOp};
196pub use auth::{AuthData, AuthError, AuthState, auth_state};
197pub use builder::{
198 attributes::{AriaAttributes, BooleanAttributes},
199 html::{
200 a, button, div, form, h1, h2, h3, img, input, li, ol, option, p, select, span, textarea, ul,
201 },
202};
203pub use callback::{Callback, IntoEventHandler, event_handler, into_event_handler};
204#[cfg(not(target_arch = "wasm32"))]
205pub use component::DummyEvent;
206pub use component::{
207 Component, Head, IntoPage, LinkTag, MetaTag, Page, PageElement, PageExt, Props, ScriptTag,
208 StyleTag,
209};
210pub use csrf::{CsrfManager, get_csrf_token};
211pub use dom::{Document, Element, EventHandle, EventType, document};
212#[cfg(not(target_arch = "wasm32"))]
213pub use form::{FormBinding, FormComponent};
214// Static form metadata types (always available, used by form! macro)
215pub use form_generated::{StaticFieldMetadata, StaticFormMetadata};
216pub use hydration::{HydrationContext, HydrationError, hydrate};
217pub use reactive::{Effect, Memo, Resource, ResourceState, Signal};
218#[cfg(target_arch = "wasm32")]
219pub use reactive::{create_resource, create_resource_with_deps};
220// Re-export Context system
221pub use reactive::{
222 Context, ContextGuard, create_context, get_context, provide_context, remove_context,
223};
224// Re-export Hooks API
225pub use reactive::{
226 ActionState, Dispatch, OptimisticState, Ref, SetState, SharedSetState, SharedSignal,
227 TransitionState, use_action_state, use_callback, use_context, use_debug_value,
228 use_deferred_value, use_effect, use_effect_event, use_id, use_layout_effect, use_memo,
229 use_optimistic, use_reducer, use_ref, use_shared_state, use_state, use_sync_external_store,
230 use_transition,
231};
232#[cfg(not(target_arch = "wasm32"))]
233pub use reinhardt_forms::{
234 Widget,
235 wasm_compat::{FieldMetadata, FormMetadata},
236};
237pub use router::{Link, PathPattern, Route, Router, RouterOutlet};
238pub use server_fn::{ServerFn, ServerFnError};
239pub use ssr::{SsrOptions, SsrRenderer, SsrState};
240pub use static_resolver::{init_static_resolver, is_initialized, resolve_static};
241
242// Re-export procedural macros
243pub use reinhardt_pages_macros::form;
244pub use reinhardt_pages_macros::head;
245pub use reinhardt_pages_macros::page;
246
247// Logging macros are automatically exported via #[macro_export]
248// Users can access them as: reinhardt_pages::debug_log!, reinhardt_pages::info_log!, etc.