Skip to main content

workflow_core/
dirs.rs

1//!
2//! Access to home and data folder (windows) when running natively or
3//! within Node.js
4//!
5
6use cfg_if::cfg_if;
7use std::path::PathBuf;
8
9/// Returns the current user's home directory, resolved natively or via Node.js
10/// (`os.homedir()`), or `None` if it cannot be determined.
11pub fn home_dir() -> Option<PathBuf> {
12    cfg_if! {
13        if #[cfg(target_arch = "wasm32")] {
14            if crate::runtime::is_node() {
15                nodejs::home_dir()
16            } else {
17                panic!("workflow_core::dirs::home_dir() is not supported on this platform (must be native of nodejs)");
18            }
19        } else {
20            dirs::home_dir()
21        }
22    }
23}
24
25/// Returns the platform-appropriate user data directory (e.g. `LOCALAPPDATA`
26/// on Windows), resolved natively or via Node.js, or `None` if undetermined.
27pub fn data_dir() -> Option<PathBuf> {
28    cfg_if! {
29        if #[cfg(target_arch = "wasm32")] {
30            if crate::runtime::is_node() {
31                nodejs::data_dir()
32            } else {
33                panic!("workflow_core::dirs::home_dir() is not supported on this platform (must be native of nodejs)");
34            }
35        } else {
36            dirs::data_dir()
37        }
38    }
39}
40
41cfg_if! {
42    if #[cfg(target_arch = "wasm32")] {
43        mod nodejs {
44            use std::path::{Path,PathBuf};
45            use wasm_bindgen::prelude::*;
46            use js_sys::Reflect;
47
48            #[wasm_bindgen]
49            extern "C" {
50                pub fn require(s: &str) -> JsValue;
51            }
52
53            static mut HOME_DIR: Option<PathBuf> = None;
54            pub fn home_dir() -> Option<PathBuf> {
55                let home_dir_ptr = &raw mut HOME_DIR;
56                unsafe {
57                    (*home_dir_ptr).get_or_insert_with(|| {
58                        Reflect::get(&require("os"), &JsValue::from_str("homedir"))
59                            .expect("Unable to get homedir")
60                            .dyn_into::<js_sys::Function>()
61                            .expect("os.homedir is not a function")
62                            .call0(&JsValue::UNDEFINED)
63                            .expect("Unable to get homedir")
64                            .as_string()
65                            .as_ref()
66                            .map(Path::new)
67                            .map(PathBuf::from)
68                            .expect("Unable to get nodejs homedir")
69                    });
70                    (*home_dir_ptr).clone()
71                }
72            }
73
74            static mut DATA_DIR: Option<PathBuf> = None;
75            pub fn data_dir() -> Option<PathBuf> {
76                let data_dir_ptr = &raw mut DATA_DIR;
77                unsafe {
78                    (*data_dir_ptr).get_or_insert_with(|| {
79                        if crate::runtime::is_windows() {
80                            crate::env::var("LOCALAPPDATA")
81                                .ok()
82                                .map(PathBuf::from)
83                                .expect("Unable to get LOCALAPPDATA")
84
85                        } else {
86                            home_dir()
87                                .expect("Unable to get nodejs data_dir (unable to get home_dir)")
88                        }
89                    });
90                    (*data_dir_ptr).clone()
91                }
92            }
93        }
94    }
95}