ferrous_actions/node/
process.rs

1use super::path::{self, Path};
2use std::collections::HashMap;
3use wasm_bindgen::JsValue;
4
5/// Returns the current working directory of the process
6pub fn cwd() -> path::Path {
7    path::Path::from(ffi::cwd())
8}
9
10/// Returns a map of all environment variables defined for the process
11pub fn get_env() -> HashMap<String, String> {
12    use js_sys::JsString;
13    use wasm_bindgen::JsCast as _;
14
15    let env = ffi::ENV.with(|v| {
16        js_sys::Object::entries(v.dyn_ref::<js_sys::Object>().expect("get_env didn't return an object"))
17            .iter()
18            .map(|o| o.dyn_into::<js_sys::Array>().expect("env entry was not an array"))
19            .map(|a| (JsString::from(a.at(0)), JsString::from(a.at(1))))
20            .map(|(k, v)| (String::from(k), String::from(v)))
21            .collect()
22    });
23    env
24}
25
26/// Set an environment variable to a specified value
27pub fn set_var(name: &str, value: &str) {
28    use js_sys::{JsString, Map, Object};
29
30    let name: JsString = name.into();
31    let value: JsString = value.into();
32    let attributes = Map::new();
33    attributes.set(&"writable".into(), &true.into());
34    attributes.set(&"enumerable".into(), &true.into());
35    attributes.set(&"configurable".into(), &true.into());
36    attributes.set(&"value".into(), value.as_ref());
37    let attributes = Object::from_entries(&attributes).expect("Failed to convert attributes map to object");
38    ffi::ENV.with(|env| Object::define_property(env, &name, &attributes));
39}
40
41/// Removes an environment variable
42pub fn remove_var(name: &str) {
43    ffi::ENV.with(|env| js_sys::Reflect::delete_property(env, &name.into()).expect("process.env wasn't an object"));
44}
45
46/// Changes the current working directory to the specified path
47pub fn chdir<P: Into<Path>>(path: P) -> Result<(), JsValue> {
48    let path = path.into();
49    ffi::chdir(&path.to_js_string())?;
50    Ok(())
51}
52
53/// Low-level bindings for node.js process functions and variables
54pub mod ffi {
55    use js_sys::{JsString, Object};
56    use wasm_bindgen::prelude::*;
57
58    #[wasm_bindgen(module = "process")]
59    extern "C" {
60        #[wasm_bindgen(thread_local_v2, js_name = "env")]
61        pub static ENV: Object;
62
63        pub fn cwd() -> JsString;
64
65        #[wasm_bindgen(catch)]
66        pub fn chdir(path: &JsString) -> Result<JsValue, JsValue>;
67    }
68}
69
70#[cfg(test)]
71mod test {
72    use wasm_bindgen_test::wasm_bindgen_test;
73
74    #[wasm_bindgen_test]
75    fn invoke_get_env() {
76        super::get_env();
77    }
78
79    #[wasm_bindgen_test]
80    async fn invoke_cwd() {
81        let cwd = super::cwd();
82        assert!(cwd.exists().await);
83    }
84}