1use serde::{Deserialize, Serialize};
2
3pub mod token;
4
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct Autocapture {
7 #[serde(default)]
8 pub pageview: bool,
9 #[serde(default)]
10 pub spa_pageview: bool,
11 #[serde(default)]
12 pub engagement: bool,
13 #[serde(default)]
14 pub click: bool,
15 #[serde(default)]
16 pub form: bool,
17 #[serde(default)]
18 pub scroll: bool,
19}
20
21impl Default for Autocapture {
22 fn default() -> Self {
23 Self {
24 pageview: true,
25 spa_pageview: false,
26 engagement: false,
27 click: false,
28 form: false,
29 scroll: false,
30 }
31 }
32}
33
34pub fn get_sdk(
61 url: &str,
62 host: &str,
63 autocapture: Autocapture,
64 edgee_cookie: &str,
65) -> Result<String, &'static str> {
66 let content = get_sdk_content(url)?;
67 Ok(dynamize_sdk(content, host, autocapture, edgee_cookie))
68}
69
70pub fn get_sdk_for_unsafe_user(url: &str) -> Result<String, &'static str> {
71 let content = get_sdk_content(url)?;
72 Ok(content.replace("{{safe}}", "unsafe"))
73}
74
75fn get_sdk_content(url: &str) -> Result<&str, &'static str> {
76 if url.ends_with("sdk.js") {
77 return Ok(include_str!("../release/edgee.v1.7.6.js").trim());
78 }
79
80 let Some((_, part)) = url.rsplit_once("edgee.v") else {
81 return Err("Failed to read the JS SDK file");
82 };
83 let Some(part) = part.strip_suffix(".js") else {
84 return Err("Failed to read the JS SDK file");
85 };
86
87 let content = match part {
88 "1.5.0" => include_str!("../release/edgee.v1.5.0.js").trim(),
89 "1.6.2" => include_str!("../release/edgee.v1.6.2.js").trim(),
90 "1.7.3" => include_str!("../release/edgee.v1.7.3.js").trim(),
91 "1.7.4" => include_str!("../release/edgee.v1.7.4.js").trim(),
92 "1.7.5" => include_str!("../release/edgee.v1.7.5.js").trim(),
93 "1.7.6" => include_str!("../release/edgee.v1.7.6.js").trim(),
94 _ => return Err("Failed to read the JS SDK file"),
96 };
97
98 Ok(content)
99}
100
101fn dynamize_sdk(sdk: &str, host: &str, autocapture: Autocapture, edgee_cookie: &str) -> String {
102 let token = token::generate(host);
103 let mut sdk = sdk.replace("{{token}}", token.as_str());
104 sdk = sdk.replace("{{ecn}}", edgee_cookie);
105
106 if !autocapture.pageview {
107 sdk = sdk.replace("{{ac_pageview}}", "n");
108 }
109 if autocapture.spa_pageview {
110 sdk = sdk.replace("{{ac_spa_pageview}}", "y");
111 }
112 if autocapture.engagement {
113 sdk = sdk.replace("{{ac_engagement}}", "y");
114 }
115 if autocapture.click {
116 sdk = sdk.replace("{{ac_click}}", "y");
117 }
118 if autocapture.form {
119 sdk = sdk.replace("{{ac_form}}", "y");
120 }
121 if autocapture.scroll {
122 sdk = sdk.replace("{{ac_scroll}}", "y");
123 }
124 sdk.to_string()
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn retrieves_sdk_content_for_valid_url() {
133 let url = "/sdk.js";
134 let host = "example.com";
135 let result = get_sdk(url, host, Autocapture::default(), "edgee");
136 assert!(result.is_ok());
137 assert!(result.unwrap().contains("{{side}}"));
138 }
139
140 #[test]
141 fn retrieves_sdk_with_custom_edgee_cookie_name() {
142 let url = "/sdk.js";
143 let host = "example.com";
144 let result = get_sdk(url, host, Autocapture::default(), "test_edgee_cookie_name");
145 assert!(result.is_ok());
146 assert!(result.unwrap().contains("test_edgee_cookie_name"));
147 }
148
149 #[test]
150 fn retrieves_versioned_sdk_content() {
151 let url = "/edgee.v1.5.0.js";
152 let host = "example.com";
153 let result = get_sdk(url, host, Autocapture::default(), "edgee");
154 assert!(result.is_ok());
155 assert!(result.unwrap().contains("{{side}}"));
156 }
157 #[test]
158 fn returns_error_for_invalid_url_format() {
159 let url = "/invalid.js";
160 let host = "example.com";
161 let result = get_sdk(url, host, Autocapture::default(), "edgee");
162 assert!(result.is_err());
163 assert_eq!(result.unwrap_err(), "Failed to read the JS SDK file");
164 }
165
166 #[test]
167 fn returns_error_for_unsupported_version() {
168 let url = "/edgee.v2.0.0.js";
169 let host = "example.com";
170 let result = get_sdk(url, host, Autocapture::default(), "edgee");
171 assert!(result.is_err());
172 assert_eq!(result.unwrap_err(), "Failed to read the JS SDK file");
173 }
174}