use serde_json::{json, Value}; use wasm_bindgen::prelude::*; #[wasm_bindgen(js_name = compareVersions)] pub fn compare_versions(a: &str, b: &str) -> i32 { let mut av = parse_version(a); let mut bv = parse_version(b); av.resize(4, 0); bv.resize(4, 0); for index in 0..4 { if av[index] > bv[index] { return 1; } if av[index] < bv[index] { return -1; } } 0 } #[wasm_bindgen(js_name = scoreEndpointHealth)] pub fn score_endpoint_health(status: &str, latency_ms: i32, failures: i32) -> i32 { let base = match status { "ok" => 100, "degraded" => 70, "error" => 30, _ => 50, }; let latency_penalty = (latency_ms / 250).clamp(0, 30); let failure_penalty = (failures * 12).clamp(0, 48); (base - latency_penalty - failure_penalty).clamp(0, 100) } #[wasm_bindgen(js_name = normalizeReleaseManifest)] pub fn normalize_release_manifest(input: &str) -> String { let mut value: Value = serde_json::from_str(input).unwrap_or_else(|_| json!({})); if value.get("manifest_version").is_none() { value["manifest_version"] = json!(2); } if value.get("packages").is_none() { value["packages"] = json!([]); } serde_json::to_string(&value).unwrap_or_else(|_| "{}".to_string()) } #[wasm_bindgen(js_name = validateSourceCatalog)] pub fn validate_source_catalog(input: &str) -> String { let value: Value = serde_json::from_str(input).unwrap_or_else(|_| json!({})); let categories = value .get("categories") .and_then(|item| item.as_array()) .map(|items| items.len()) .unwrap_or_default(); let mut source_count = 0usize; if let Some(items) = value.get("categories").and_then(|item| item.as_array()) { for category in items { source_count += category .get("subcategories") .and_then(|item| item.as_array()) .map(|items| items.len()) .unwrap_or_default(); } } serde_json::to_string(&json!({ "ok": categories > 0, "categories": categories, "sources": source_count })).unwrap_or_else(|_| "{\"ok\":false}".to_string()) } #[wasm_bindgen(js_name = mergeLegacyMediaTypes)] pub fn merge_legacy_media_types(current: &str, legacy: &str) -> String { let current_value: Value = serde_json::from_str(current).unwrap_or_else(|_| json!({"categories":[]})); let legacy_value: Value = serde_json::from_str(legacy).unwrap_or_else(|_| json!({"categories":[]})); let mut categories = current_value .get("categories") .and_then(|item| item.as_array()) .cloned() .unwrap_or_default(); if let Some(legacy_categories) = legacy_value.get("categories").and_then(|item| item.as_array()) { for category in legacy_categories { categories.push(category.clone()); } } serde_json::to_string(&json!({ "layout_version": "2.0.0", "categories": categories })).unwrap_or_else(|_| "{\"categories\":[]}".to_string()) } fn parse_version(value: &str) -> Vec { value .split('.') .map(|part| part.parse::().unwrap_or_default()) .collect() }