Skip to main content

sms_web_tide/
lib.rs

1use sms_core::{Headers, InboundRegistry};
2use sms_web_generic::{HeaderConverter, ResponseConverter, WebhookProcessor};
3use tide::{Request, Response, Result, StatusCode};
4
5#[derive(Clone)]
6pub struct AppState {
7    pub registry: InboundRegistry,
8}
9
10/// Tide-specific header converter
11pub struct TideHeaderConverter;
12
13impl HeaderConverter for TideHeaderConverter {
14    type HeaderType = Request<AppState>;
15
16    fn to_generic_headers(req: &Self::HeaderType) -> Headers {
17        req.iter()
18            .map(|(name, values)| {
19                let value = values
20                    .iter()
21                    .map(|v| v.as_str())
22                    .collect::<Vec<_>>()
23                    .join(", ");
24                (name.as_str().to_string(), value)
25            })
26            .collect()
27    }
28}
29
30/// Tide-specific response converter
31pub struct TideResponseConverter;
32
33impl ResponseConverter for TideResponseConverter {
34    type ResponseType = Result<Response>;
35
36    fn from_webhook_response(response: sms_core::WebhookResponse) -> Self::ResponseType {
37        let status = StatusCode::try_from(response.status.as_u16())
38            .unwrap_or(StatusCode::InternalServerError);
39
40        let mut res = Response::new(status);
41        res.set_body(response.body);
42
43        // Parse content type, defaulting to application/json
44        let content_type = if response.content_type == "application/json" {
45            tide::http::mime::JSON
46        } else {
47            tide::http::mime::PLAIN
48        };
49        res.set_content_type(content_type);
50        Ok(res)
51    }
52}
53
54/// Unified webhook handler for Tide
55pub async fn unified_webhook(mut req: Request<AppState>) -> Result<Response> {
56    let provider = req.param("provider")?.to_string();
57    let body = req.body_bytes().await?;
58    let processor = WebhookProcessor::new(req.state().registry.clone());
59    let generic_headers = TideHeaderConverter::to_generic_headers(&req);
60    let response = processor.process_webhook(&provider, generic_headers, &body);
61    TideResponseConverter::from_webhook_response(response)
62}
63
64/// Helper function to configure Tide routes
65pub fn configure_routes(app: &mut tide::Server<AppState>) {
66    app.at("/webhooks/:provider").post(unified_webhook);
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn tide_types_compile() {
75        let registry = InboundRegistry::new();
76        let _state = AppState { registry };
77        // let mut app = tide::with_state(state);
78        // configure_routes(&mut app);
79    }
80}