commit c8ac67bd8351bd41e50c6a32b70d9e4859d8d15c
parent 3331a8c2ca27a15d86dbd88a5c1dd93c7c889d22
Author: triesap <triesap@radroots.dev>
Date: Mon, 19 Jan 2026 07:55:04 +0000
app-lib: add storage key helpers
- add fmt_id_from_path helper
- add fmt_id and build_storage_key helpers
- normalize storage prefixes for base paths
- add unit tests for storage helpers
Diffstat:
2 files changed, 67 insertions(+), 0 deletions(-)
diff --git a/crates/app-lib/src/lib.rs b/crates/app-lib/src/lib.rs
@@ -5,6 +5,7 @@ pub mod fetch;
pub mod geo;
pub mod path;
pub mod sleep;
+pub mod storage;
pub mod symbols;
pub use browser::{browser_platform, BrowserPlatformInfo};
@@ -12,6 +13,7 @@ pub use fetch::{fetch_json, FetchJsonError, FetchJsonErrorKind, FetchJsonResult}
pub use geo::{geop_init, geop_is_valid, AppGeolocationPoint};
pub use path::{normalize_path, sanitize_path, trim_slashes};
pub use sleep::sleep;
+pub use storage::{build_storage_key, build_storage_key_with_prefix, fmt_id, fmt_id_from_path};
pub use symbols::{
fmt_cl, value_constrain, SYMBOL_BULLET, SYMBOL_DASH, SYMBOL_DOWN, SYMBOL_PERCENT, SYMBOL_UP,
};
diff --git a/crates/app-lib/src/storage.rs b/crates/app-lib/src/storage.rs
@@ -0,0 +1,65 @@
+#![forbid(unsafe_code)]
+
+use crate::path::{normalize_path, sanitize_path, trim_slashes};
+
+pub fn fmt_id_from_path(pathname: &str, raw_id: Option<&str>) -> String {
+ let trimmed = trim_slashes(pathname);
+ let prefix = normalize_path(&trimmed);
+ let suffix = raw_id
+ .map(|id| format!("-{}", sanitize_path(id)))
+ .unwrap_or_default();
+ format!("*{prefix}{suffix}")
+}
+
+pub fn fmt_id(raw_id: Option<&str>) -> Option<String> {
+ #[cfg(target_arch = "wasm32")]
+ {
+ let window = web_sys::window()?;
+ let location = window.location();
+ let pathname = location.pathname().ok()?;
+ Some(fmt_id_from_path(&pathname, raw_id))
+ }
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ let _ = raw_id;
+ None
+ }
+}
+
+pub fn build_storage_key_with_prefix(prefix: &str, raw_id: &str, base_prefix: &str) -> String {
+ let mut output = format!("{prefix}-{}", sanitize_path(raw_id));
+ let base_prefix = normalize_path(&trim_slashes(base_prefix));
+ if base_prefix.is_empty() {
+ return output;
+ }
+ let base = format!("*{base_prefix}");
+ let base_with_dash = format!("{base}-");
+ if output.starts_with(&base_with_dash) {
+ output.replace_range(..base_with_dash.len(), "*");
+ } else if output.starts_with(&base) {
+ output.replace_range(..base.len(), "*");
+ }
+ output
+}
+
+pub fn build_storage_key(raw_id: &str, base_prefix: &str) -> Option<String> {
+ let prefix = fmt_id(None)?;
+ Some(build_storage_key_with_prefix(&prefix, raw_id, base_prefix))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{build_storage_key_with_prefix, fmt_id_from_path};
+
+ #[test]
+ fn fmt_id_from_path_formats_prefix() {
+ assert_eq!(fmt_id_from_path("/app/home", None), "*app-home");
+ assert_eq!(fmt_id_from_path("/app/home", Some("id")), "*app-home-id");
+ }
+
+ #[test]
+ fn build_storage_key_with_prefix_replaces_base_prefix() {
+ let key = build_storage_key_with_prefix("*app-home", "raw", "/app");
+ assert_eq!(key, "*home-raw");
+ }
+}