1
2pub mod package_lock_lib {
4 use regex::Regex;
5 use serde_json::Value;
6 use std::fs;
7 use std::path::Path;
8
9 pub fn update_urls(value: &mut Value, new_url: &str) {
11 if let Value::Object(map) = value {
12 if let Some(resolved) = map.get_mut("resolved") {
13 if resolved.is_string() {
14 let old_url = resolved.as_str().unwrap();
15 let re = Regex::new(r"https?://[^/]+").unwrap();
17 let updated_url = re.replace(old_url, new_url);
19 *resolved = Value::String(updated_url.into_owned());
20 }
21 }
22 for key in map.keys().cloned().collect::<Vec<_>>() {
24 update_urls(&mut map[&key], new_url);
25 }
26 }
27 }
28
29 pub fn update_urls_in_package_lock(arg: &str) -> Result<(), Box<dyn std::error::Error>> {
32 if !Path::new("pkg.config.json").exists() {
34 return Err("pkg.config.json not found".into());
35 }
36 if !Path::new("package-lock.json").exists() {
37 return Err("package-lock.json not found".into());
38 }
39
40 let file_content = fs::read_to_string("package-lock.json")?;
42 let mut json_content: Value = serde_json::from_str(&file_content)?;
43
44 let config_content = fs::read_to_string("pkg.config.json")?;
46 let config: Value = serde_json::from_str(&config_content)?;
47
48 let new_url = if arg == "--local" {
50 config["local"].as_str().ok_or("Local URL not found in pkg.config.json")?
51 } else if arg == "--remote" {
52 config["remote"].as_str().ok_or("Remote URL not found in pkg.config.json")?
53 } else {
54 return Err("Invalid argument. Use --local or --remote.".into());
55 };
56
57 update_urls(&mut json_content, new_url);
59
60 let updated_content = serde_json::to_string_pretty(&json_content)?;
62 fs::write("package-lock.json", updated_content)?;
63 Ok(())
64 }
65
66 #[cfg(test)]
67 mod tests {
68 use super::*;
69 use serde_json::json;
70 use std::fs;
71
72 #[test]
73 fn test_update_urls_simple() {
74 let mut json = json!({
75 "resolved": "https://registry.npmjs.org/package/-/package-1.0.0.tgz"
76 });
77 update_urls(&mut json, "http://localhost:4873");
78 assert_eq!(
79 json["resolved"],
80 "http://localhost:4873/package/-/package-1.0.0.tgz"
81 );
82 }
83
84 #[test]
85 fn test_update_urls_nested() {
86 let mut json = json!({
87 "dependencies": {
88 "package": {
89 "resolved": "https://registry.npmjs.org/package/-/package-1.0.0.tgz"
90 }
91 }
92 });
93 update_urls(&mut json, "http://localhost:4873");
94 assert_eq!(
95 json["dependencies"]["package"]["resolved"],
96 "http://localhost:4873/package/-/package-1.0.0.tgz"
97 );
98 }
99
100 #[test]
101 fn test_update_urls_no_resolved_field() {
102 let mut json = json!({
103 "name": "test-package",
104 "version": "1.0.0"
105 });
106 update_urls(&mut json, "http://localhost:4873");
107 assert_eq!(json["name"], "test-package");
108 assert_eq!(json["version"], "1.0.0");
109 }
110
111 #[test]
112 fn test_update_urls_in_package_lock() {
113 let pkg_config = r#"{
115 "local": "http://localhost:4873",
116 "remote": "https://registry.npmjs.org"
117 }"#;
118 fs::write("pkg.config.json", pkg_config).unwrap();
119
120 let package_lock = r#"{
122 "dependencies": {
123 "package-a": {
124 "resolved": "https://registry.npmjs.org/package-a/-/package-a-1.0.0.tgz"
125 }
126 }
127 }"#;
128 fs::write("package-lock.json", package_lock).unwrap();
129
130 update_urls_in_package_lock("--local").unwrap();
132
133 let updated_content = fs::read_to_string("package-lock.json").unwrap();
135 assert!(updated_content.contains("http://localhost:4873"));
136 assert!(!updated_content.contains("https://registry.npmjs.org"));
137
138 fs::remove_file("pkg.config.json").unwrap();
140 fs::remove_file("package-lock.json").unwrap();
141 }
142 }
143}