1pub mod core;
10pub mod flow;
11pub mod router;
12pub mod server;
13pub mod ssr;
14
15#[cfg(feature = "cli")]
16pub mod cli;
17
18pub use resuma_macros::{component, island, js, layout, load, middleware, server, submit, view};
19
20pub use crate::core::{
21 combine_js, nav_link, no_serialize, portal, provide_context, provide_theme, push_slots,
22 resolve_slot, stream_chunk, stream_slot, theme_css_vars, use_computed, use_context,
23 use_debounce, use_effect, use_signal, use_store, use_task, use_theme, use_visible_task,
24 visible_task_js, with_default_slot, with_view_transition, Child, Component, Computed,
25 ContextId, Effect, FlowRequest, IntoView, NoSerialize, ReadSignal, RenderContext, RenderMode,
26 Result, ResumaError, Signal, SlotGuard, SlottedChild, Store, Theme, View, WriteSignal,
27};
28
29pub use crate::server::{
30 configure_security, register_server_action, set_action_middleware, ResumaApp, SecurityConfig,
31 ServeOptions, CSRF_FIELD, CSRF_HEADER,
32};
33
34pub use crate::ssr::{render_to_stream, render_to_string, render_view, PageOptions};
35
36pub use crate::flow::{
37 apply_layouts, current_request, discover_pages, encode_submit_result, error_page, form,
38 not_found_page, register_layout, register_loader, register_loader_cache, register_middleware,
39 register_stream_chunk, register_stream_loader, register_submit, try_use_load,
40 try_use_load_value, use_load, with_request, DiscoveredPage, FlowApp, FlowError,
41 FlowPageRegistry, FlowPwaConfig, FlowServeOptions, LoadValue, LoaderError, SubmitError,
42 SubmitValue,
43};
44
45#[cfg(feature = "cli")]
47pub fn run() -> anyhow::Result<()> {
48 crate::cli::run()
49}
50
51pub mod prelude {
52 pub use super::{
54 combine_js, component, configure_security, current_request, error_page, form, island, js,
55 layout, load, middleware, nav_link, not_found_page, portal, provide_context, provide_theme,
56 push_slots, render_to_string, render_view, resolve_slot, server, set_action_middleware,
57 stream_slot, submit, theme_css_vars, try_use_load, try_use_load_value, use_computed,
58 use_context, use_debounce, use_effect, use_load, use_signal, use_store, use_task,
59 use_theme, use_visible_task, view, with_view_transition, Child, Component, Computed,
60 Effect, FlowApp, FlowError, FlowPageRegistry, FlowRequest, FlowServeOptions, IntoView,
61 LoadValue, LoaderError, PageOptions, ReadSignal, Result, ResumaApp, ResumaError,
62 SecurityConfig, ServeOptions, Signal, SlottedChild, Store, SubmitError, Theme, View,
63 WriteSignal, CSRF_FIELD, CSRF_HEADER,
64 };
65}
66
67#[doc(hidden)]
68pub mod __private {
69 pub use crate::core::{combine_js, nav_link};
71 pub use crate::core::{
72 context::{current_context, RenderContext, RenderMode},
73 handler::{HandlerCapture, HandlerRef},
74 signal::SignalId,
75 slot::{push_slots, resolve_slot, with_default_slot, SlottedChild},
76 view::{AttrValue, Element, Fragment, Island as IslandView},
77 Child, Component, IntoView, ReadSignal, Result, ResumaError, Signal, View, WriteSignal,
78 };
79 pub use crate::flow::form as flow_form;
80 pub use crate::server::register_server_action;
81 pub use ctor;
82 pub use serde_json;
83
84 #[derive(Debug, Clone)]
85 pub enum HandlerSource {
86 Inline(String),
87 Chunk {
88 chunk: String,
89 symbol: String,
90 source: String,
91 },
92 }
93
94 #[derive(Debug, Clone)]
95 pub enum ResumeCapture {
96 Signal { name: String, id: SignalId },
97 Action(String),
98 }
99
100 pub use crate::core::view::Element as ElementType;
101
102 pub fn register_handler(
103 event: &str,
104 chunk: &str,
105 symbol: &str,
106 js_source: &str,
107 captures: Vec<ResumeCapture>,
108 actions: Vec<String>,
109 ) -> AttrValue {
110 if let Some(ctx) = current_context() {
111 ctx.register_handler(chunk, symbol, js_source);
112 for a in &actions {
113 ctx.register_action(a);
114 }
115 }
116
117 let signal_captures: Vec<HandlerCapture> = captures
118 .into_iter()
119 .filter_map(|c| match c {
120 ResumeCapture::Signal { name, id } => Some(HandlerCapture { name, id }),
121 _ => None,
122 })
123 .collect();
124
125 AttrValue::Handler(HandlerRef {
126 event: event.to_string(),
127 chunk: chunk.to_string(),
128 symbol: symbol.to_string(),
129 captures: signal_captures,
130 inline: Some(js_source.to_string()),
131 })
132 }
133
134 pub trait ElementBuilderExt {
135 fn attr_runtime(self, kv: (String, AttrValue)) -> Self;
136 }
137
138 impl ElementBuilderExt for crate::core::view::ElementBuilder {
139 fn attr_runtime(self, (name, value): (String, AttrValue)) -> Self {
140 self.attr(name, value)
141 }
142 }
143
144 pub fn render_component<C: Component>(props: C::Props) -> View {
145 C::render(props)
146 }
147
148 pub fn resolve_attr_value<T: Into<AttrValueAuto>>(value: T) -> AttrValue {
149 value.into().into_attr_value()
150 }
151
152 pub struct AttrValueAuto(AttrValue);
153
154 impl AttrValueAuto {
155 fn into_attr_value(self) -> AttrValue {
156 self.0
157 }
158 }
159
160 impl From<&str> for AttrValueAuto {
161 fn from(s: &str) -> Self {
162 Self(AttrValue::Static(s.to_string()))
163 }
164 }
165 impl From<String> for AttrValueAuto {
166 fn from(s: String) -> Self {
167 Self(AttrValue::Static(s))
168 }
169 }
170 impl From<bool> for AttrValueAuto {
171 fn from(b: bool) -> Self {
172 Self(AttrValue::Static(b.to_string()))
173 }
174 }
175 impl From<i32> for AttrValueAuto {
176 fn from(n: i32) -> Self {
177 Self(AttrValue::Static(n.to_string()))
178 }
179 }
180 impl From<i64> for AttrValueAuto {
181 fn from(n: i64) -> Self {
182 Self(AttrValue::Static(n.to_string()))
183 }
184 }
185 impl From<u32> for AttrValueAuto {
186 fn from(n: u32) -> Self {
187 Self(AttrValue::Static(n.to_string()))
188 }
189 }
190 impl From<u64> for AttrValueAuto {
191 fn from(n: u64) -> Self {
192 Self(AttrValue::Static(n.to_string()))
193 }
194 }
195 impl From<f64> for AttrValueAuto {
196 fn from(n: f64) -> Self {
197 Self(AttrValue::Static(n.to_string()))
198 }
199 }
200
201 impl<T: Clone + serde::Serialize + 'static> From<&Signal<T>> for AttrValueAuto {
202 fn from(s: &Signal<T>) -> Self {
203 Self(AttrValue::Dynamic {
204 signal: s.id(),
205 format: None,
206 })
207 }
208 }
209 impl<T: Clone + serde::Serialize + 'static> From<Signal<T>> for AttrValueAuto {
210 fn from(s: Signal<T>) -> Self {
211 Self(AttrValue::Dynamic {
212 signal: s.id(),
213 format: None,
214 })
215 }
216 }
217
218 pub fn wrap_in_island(name: &str, instance: u32, view: View) -> View {
219 if let Some(ctx) = current_context() {
220 ctx.register_island(name);
221 }
222 View::Island(IslandView {
223 chunk_id: name.to_string(),
224 instance_id: format!("{}-{}", name, instance),
225 signal_ids: Vec::new(),
226 view: Box::new(view),
227 props: serde_json::Value::Null,
228 })
229 }
230
231 pub use crate::core::view as view_mod;
232 pub use crate::core::view::ElementBuilder;
233
234 pub fn fragment(children: Vec<Child>) -> View {
235 View::fragment(children)
236 }
237
238 pub fn element(tag: &str) -> ElementBuilder {
239 View::element(tag)
240 }
241}