1extern crate directories;
2extern crate pathdiff;
3#[macro_use]
4extern crate serde_json;
5
6use anyhow::{Result};
7use directories::BaseDirs;
8use pathdiff::diff_paths;
9use serde_json::Value;
10use std::env::current_dir;
11
12#[derive(Debug)]
13pub struct ConfigInfo {
14 deno: String,
15 deps_http: String,
16 deps_https: String,
17}
18
19impl ConfigInfo {
20 pub fn new() -> Option<ConfigInfo> {
21 let dir = BaseDirs::new();
22 if let Some(d) = dir {
23 let current_dir = current_dir().expect("failed to get current directory");
24 let cache_root = d.cache_dir();
25 let deno = diff_paths(cache_root.join("deno/lib.deno.d.ts"), ¤t_dir)
26 .unwrap()
27 .to_str()
28 .unwrap()
29 .to_string();
30 let deps = cache_root.join("deps");
31 let deps_http = diff_paths(deps.join("http/*"), ¤t_dir)
32 .unwrap()
33 .to_str()
34 .unwrap()
35 .to_string();
36 let deps_https = diff_paths(deps.join("https/*"), ¤t_dir)
37 .unwrap()
38 .to_str()
39 .unwrap()
40 .to_string();
41 Some(ConfigInfo {
42 deno,
43 deps_http,
44 deps_https,
45 })
46 } else {
47 None
48 }
49 }
50}
51
52pub fn deno_init(json_str: String, config_info: &ConfigInfo) -> Result<String> {
53 let mut v: Value;
54 if json_str != "" {
55 v = serde_json::from_str(&json_str)?;
56 } else {
57 v = json!({});
58 }
59
60 if let Value::Null = v["compilerOptions"] {
61 v.as_object_mut().unwrap().insert(
62 "compilerOptions".to_string(),
63 serde_json::to_value(json!({}))?,
64 );
65 }
66 if let Value::Null = v["compilerOptions"]["baseUrl"] {
67 v["compilerOptions"]
68 .as_object_mut()
69 .unwrap()
70 .insert("baseUrl".to_string(), serde_json::to_value(json!({}))?);
71 }
72 if let Value::Null = v["compilerOptions"]["paths"] {
73 v["compilerOptions"]
74 .as_object_mut()
75 .unwrap()
76 .insert("paths".to_string(), serde_json::to_value(json!({}))?);
77 }
78 if let Value::Null = v["compilerOptions"]["plugins"] {
79 v["compilerOptions"]
80 .as_object_mut()
81 .unwrap()
82 .insert("plugins".to_string(), serde_json::to_value(json!([]))?);
83 }
84
85 *v["compilerOptions"].get_mut("baseUrl").unwrap() = serde_json::to_value(".").unwrap();
86 v["compilerOptions"]["paths"]
87 .as_object_mut()
88 .unwrap()
89 .insert("deno".to_string(), serde_json::to_value(&config_info.deno)?);
90 println!("{:?}", &v);
91 v["compilerOptions"]["paths"]
92 .as_object_mut()
93 .unwrap()
94 .insert(
95 "http://*".to_string(),
96 serde_json::to_value(&config_info.deps_http)?,
97 );
98 v["compilerOptions"]["paths"]
99 .as_object_mut()
100 .unwrap()
101 .insert(
102 "https://*".to_string(),
103 serde_json::to_value(&config_info.deps_https)?,
104 );
105 v["compilerOptions"]["plugins"]
106 .as_array_mut()
107 .unwrap()
108 .push(json!({"name": "typescript-deno-plugin"}));
109
110 println!("{:?}", &v);
111
112 Ok(serde_json::to_string_pretty(&v).unwrap())
113}
114
115#[cfg(test)]
116fn config_gen() -> ConfigInfo {
117 ConfigInfo {
118 deno: "../../this/is/deno/path".to_string(),
119 deps_http: "../../this/is/http/path".to_string(),
120 deps_https: "../../this/is/https/path".to_string()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn empty_string_test() {
130 let config = config_gen();
131 let result = deno_init("".to_string(), &config);
132 let expected = r#"{
133 "compilerOptions": {
134 "baseUrl": ".",
135 "paths": {
136 "deno": "../../this/is/deno/path",
137 "http://*": "../../this/is/http/path",
138 "https://*": "../../this/is/https/path"
139 },
140 "plugins": [
141 {
142 "name": "typescript-deno-plugin"
143 }
144 ]
145 }
146}"#;
147 assert_eq!(expected, result.unwrap());
148 }
149
150 #[test]
151 fn no_compiler_options() {
152 let config = config_gen();
153 let test_str = r#"
154{
155 "testOption": {
156 "testA": "test",
157 "testB": [
158 "testB-A",
159 1234,
160 "testB-B",
161 "aiueo"
162 ]
163 }
164}
165"#;
166 let result = deno_init(test_str.to_string(), &config);
167 let expected = r#"{
168 "compilerOptions": {
169 "baseUrl": ".",
170 "paths": {
171 "deno": "../../this/is/deno/path",
172 "http://*": "../../this/is/http/path",
173 "https://*": "../../this/is/https/path"
174 },
175 "plugins": [
176 {
177 "name": "typescript-deno-plugin"
178 }
179 ]
180 },
181 "testOption": {
182 "testA": "test",
183 "testB": [
184 "testB-A",
185 1234,
186 "testB-B",
187 "aiueo"
188 ]
189 }
190}"#;
191 assert_eq!(expected, result.unwrap());
192 }
193
194 #[test]
195 fn mix() {
196 let config = config_gen();
197 let test_str = r#"
198{
199 "compilerOptions": {
200 "baseUrl": ".",
201 "paths": {
202 "pathA": "/path/to/path/A",
203 "pathB": "/path/to/path/B"
204 },
205 "plugins": [
206 {
207 "name": "plugin-A"
208 },
209 {
210 "name": "plugin-B"
211 }
212 ],
213 "otherOption": "aaa"
214 },
215 "testOption": {
216 "testA": "test",
217 "testB": [
218 "testB-A",
219 1234,
220 "testB-B",
221 "aiueo"
222 ]
223 }
224}
225"#;
226 let result = deno_init(test_str.to_string(), &config);
227 let expected = r#"{
228 "compilerOptions": {
229 "baseUrl": ".",
230 "otherOption": "aaa",
231 "paths": {
232 "deno": "../../this/is/deno/path",
233 "http://*": "../../this/is/http/path",
234 "https://*": "../../this/is/https/path",
235 "pathA": "/path/to/path/A",
236 "pathB": "/path/to/path/B"
237 },
238 "plugins": [
239 {
240 "name": "plugin-A"
241 },
242 {
243 "name": "plugin-B"
244 },
245 {
246 "name": "typescript-deno-plugin"
247 }
248 ]
249 },
250 "testOption": {
251 "testA": "test",
252 "testB": [
253 "testB-A",
254 1234,
255 "testB-B",
256 "aiueo"
257 ]
258 }
259}"#;
260 assert_eq!(expected, result.unwrap());
261 }
262}