diff --git a/Cargo.lock b/Cargo.lock index 16b1c638..601233b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,7 +78,7 @@ name = "alias" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -1012,7 +1012,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -1383,7 +1383,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "url", @@ -1592,7 +1592,7 @@ name = "cat" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -1656,7 +1656,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -1675,7 +1675,7 @@ version = "0.2.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "pleco", "serde", "serde_json", @@ -1867,7 +1867,7 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" name = "contacts" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -2443,7 +2443,7 @@ name = "download" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", @@ -2455,7 +2455,7 @@ name = "downloads" version = "0.5.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -2492,7 +2492,7 @@ dependencies = [ name = "echo" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "wit-bindgen", ] @@ -2731,7 +2731,7 @@ version = "0.2.0" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -2885,7 +2885,7 @@ dependencies = [ name = "get_block" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -2950,7 +2950,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" name = "globe" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "url", @@ -3077,7 +3077,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" name = "help" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "wit-bindgen", ] @@ -3106,7 +3106,7 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" name = "hi" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -3139,7 +3139,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -3454,7 +3454,7 @@ name = "install" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", @@ -3631,7 +3631,7 @@ name = "kfetch" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "serde_json", @@ -3643,7 +3643,7 @@ name = "kill" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -3715,9 +3715,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c5b69ac1fc0cb457c7714ceb8c0a5bdbee4ee00b837f9f16ea711e902bdfe8" +version = "0.9.2" +source = "git+https://github.com/kinode-dao/process_lib.git?rev=9ac9e51#9ac9e513c0228f2dcfe8999ed4ca2c38246ee3db" dependencies = [ "alloy 0.1.4", "alloy-primitives", @@ -3738,8 +3737,9 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.2" -source = "git+https://github.com/kinode-dao/process_lib.git?rev=9ac9e51#9ac9e513c0228f2dcfe8999ed4ca2c38246ee3db" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7722aef4bff0625445fafda89a02f82ce0e16c7def6024e1317ae55a632ad331" dependencies = [ "alloy 0.1.4", "alloy-primitives", @@ -3840,7 +3840,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "hex", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "serde_json", @@ -4067,7 +4067,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "regex", "serde", "serde_json", @@ -4237,7 +4237,7 @@ dependencies = [ name = "net_diagnostics" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "wit-bindgen", @@ -4563,7 +4563,7 @@ dependencies = [ name = "peer" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "wit-bindgen", @@ -4573,7 +4573,7 @@ dependencies = [ name = "peers" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "wit-bindgen", @@ -5614,7 +5614,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "serde_json", @@ -5832,7 +5832,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "state" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -6009,7 +6009,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rand 0.8.5", "regex", "serde", @@ -6023,7 +6023,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", @@ -6280,7 +6280,7 @@ version = "0.2.0" dependencies = [ "anyhow", "clap", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -6611,7 +6611,7 @@ name = "uninstall" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", diff --git a/kinode/packages/contacts/api/contacts:sys-v0.wit b/kinode/packages/contacts/api/contacts:sys-v0.wit new file mode 100644 index 00000000..a689775b --- /dev/null +++ b/kinode/packages/contacts/api/contacts:sys-v0.wit @@ -0,0 +1,35 @@ +interface contacts { + enum capabilities { + read-name-only, + read, + add, + remove, + } + + variant contacts-request { + get-names, // requires read-names-only + get-all-contacts, // requires read + get-contact(string), // requires read + add-contact(string), // requires add + // tuple + add-field(tuple), // requires add + remove-contact(string), // requires remove + // tuple + remove-field(tuple), // requires remove + } + + variant contacts-response { + get-names(list), + get-all-contacts, // JSON all-contacts dict in blob + get-contact, // JSON contact dict in blob + add-contact, + add-field, + remove-contact, + remove-field, + } +} + +world contacts-sys-v0 { + import contacts; + include process-v0; +} diff --git a/kinode/packages/contacts/contacts/Cargo.toml b/kinode/packages/contacts/contacts/Cargo.toml index c8704114..54c6bada 100644 --- a/kinode/packages/contacts/contacts/Cargo.toml +++ b/kinode/packages/contacts/contacts/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = "0.9.1" +kinode_process_lib = "0.9.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index 1f06572e..b407bd55 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -1,40 +1,85 @@ +use crate::kinode::process::contacts::{ContactsRequest, ContactsResponse}; use kinode_process_lib::{ - await_message, call_init, eth, get_blob, homepage, http, kernel_types, net, println, Address, - LazyLoadBlob, Message, NodeId, ProcessId, Request, Response, SendError, SendErrorKind, + await_message, call_init, get_blob, get_typed_state, homepage, http, println, set_state, + Address, LazyLoadBlob, Message, NodeId, Response, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; const ICON: &str = include_str!("icon"); +#[derive(Debug, Serialize, Deserialize)] +struct Contact(HashMap); + +#[derive(Debug, Serialize, Deserialize)] +struct Contacts(HashMap); + #[derive(Debug, Serialize, Deserialize)] struct ContactsState { our: Address, + contacts: Contacts, } impl ContactsState { fn new(our: Address) -> Self { - Self { our } + get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self { + our, + contacts: Contacts(HashMap::new()), + }) + } + + fn save(&self) { + set_state(&serde_json::to_vec(&self).expect("Failed to serialize contacts state!")); + } + + fn contacts(&self) -> &Contacts { + &self.contacts + } + + fn get_contact(&self, node: NodeId) -> Option<&Contact> { + self.contacts.0.get(&node) + } + + fn add_contact(&mut self, node: NodeId) { + self.contacts.0.insert(node, Contact(HashMap::new())); + } + + fn remove_contact(&mut self, node: NodeId) { + self.contacts.0.remove(&node); + } + + fn add_field(&mut self, node: NodeId, field: String, value: serde_json::Value) { + self.contacts + .0 + .entry(node) + .or_insert_with(|| Contact(HashMap::new())) + .0 + .insert(field, value); + } + + fn remove_field(&mut self, node: NodeId, field: String) { + if let Some(contact) = self.contacts.0.get_mut(&node) { + contact.0.remove(&field); + } } } wit_bindgen::generate!({ path: "target/wit", - world: "process-v0", + world: "contacts-sys-v0", + generate_unused_types: true, + additional_derives: [PartialEq, serde::Deserialize, serde::Serialize], }); call_init!(initialize); fn initialize(our: Address) { - // add ourselves to the homepage homepage::add_to_homepage("Contacts", Some(ICON), Some("/"), None); - // Grab our state, then enter the main event loop. let mut state: ContactsState = ContactsState::new(our); let mut http_server = http::server::HttpServer::new(5); - // Serve the index.html and other UI files found in pkg/ui at the root path. - // Serving securely at `settings-sys` subdomain + // serve the frontend on a secure subdomain http_server .serve_ui( &state.our, @@ -52,8 +97,8 @@ fn initialize(our: Address) { fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServer) { loop { match await_message() { - Err(send_error) => { - println!("got send error: {send_error:?}"); + Err(_send_error) => { + // ignore send errors, local-only process continue; } Ok(Message::Request { @@ -84,44 +129,25 @@ fn handle_request( body: &[u8], state: &mut ContactsState, http_server: &mut http::server::HttpServer, -) -> SettingsResponse { +) -> Option { // source node is ALWAYS ourselves since networking is disabled if source.process == "http_server:distro:sys" { // receive HTTP requests and websocket connection messages from our server - let server_request = http_server - .parse_request(body) - .map_err(|_| SettingsError::MalformedRequest)?; + let server_request = http_server.parse_request(body).unwrap(); http_server.handle_request( server_request, - |req| { - let result = handle_http_request(state, &req); - match result { - Ok((resp, blob)) => (resp, blob), - Err(e) => { - println!("error handling HTTP request: {e}"); - ( - http::server::HttpResponse { - status: 500, - headers: HashMap::new(), - }, - Some(LazyLoadBlob { - mime: Some("application/text".to_string()), - bytes: e.to_string().as_bytes().to_vec(), - }), - ) - } - } - }, + |req| handle_http_request(state, &req), |_channel_id, _message_type, _blob| { // we don't expect websocket messages }, ); - Ok(None) + None } else { - let settings_request = serde_json::from_slice::(body) - .map_err(|_| SettingsError::MalformedRequest)?; - handle_settings_request(state, settings_request) + // let settings_request = serde_json::from_slice::(body) + // .map_err(|_| SettingsError::MalformedRequest)?; + // handle_settings_request(state, settings_request) + None } } @@ -129,163 +155,62 @@ fn handle_request( fn handle_http_request( state: &mut ContactsState, http_request: &http::server::IncomingHttpRequest, -) -> anyhow::Result<(http::server::HttpResponse, Option)> { - match http_request.method()?.as_str() { +) -> (http::server::HttpResponse, Option) { + match http_request.method().unwrap().as_str() { "GET" => { - state.fetch()?; - Ok(( + // state.fetch().unwrap(); + ( http::server::HttpResponse::new(http::StatusCode::OK) .header("Content-Type", "application/json"), Some(LazyLoadBlob::new( Some("application/json"), - serde_json::to_vec(&state)?, + serde_json::to_vec(&state).unwrap(), )), - )) + ) } "POST" => { - let Some(blob) = get_blob() else { - return Err(anyhow::anyhow!("malformed request")); - }; - let request = serde_json::from_slice::(&blob.bytes)?; - let response = handle_settings_request(state, request); - Ok(( + let blob = get_blob().unwrap(); + let request = serde_json::from_slice::(&blob.bytes).unwrap(); + let response = handle_contacts_request(state, request); + let response: Option = Some("ok".to_string()); + ( http::server::HttpResponse::new(http::StatusCode::OK) .header("Content-Type", "application/json"), match response { - Ok(Some(data)) => Some(LazyLoadBlob::new( + Some(data) => Some(LazyLoadBlob::new( Some("application/json"), - serde_json::to_vec(&data)?, - )), - Ok(None) => None, - Err(e) => Some(LazyLoadBlob::new( - Some("application/json"), - serde_json::to_vec(&e)?, + serde_json::to_vec(&data).unwrap(), )), + None => None, }, - )) + ) } // Any other method will be rejected. - _ => Ok(( + _ => ( http::server::HttpResponse::new(http::StatusCode::METHOD_NOT_ALLOWED), None, - )), + ), } } -fn handle_settings_request( - state: &mut SettingsState, - request: SettingsRequest, -) -> SettingsResponse { +fn handle_contacts_request( + state: &mut ContactsState, + request: ContactsRequest, +) -> ContactsResponse { match request { - SettingsRequest::Hi { - node, - content, - timeout, - } => { - if let Err(SendError { kind, .. }) = Request::to((&node, "net", "distro", "sys")) - .body(content.into_bytes()) - .send_and_await_response(timeout) - .unwrap() - { - match kind { - SendErrorKind::Timeout => { - println!("message to {node} timed out"); - return Err(SettingsError::HiTimeout); - } - SendErrorKind::Offline => { - println!("{node} is offline or does not exist"); - return Err(SettingsError::HiOffline); - } - } - } else { - return Ok(None); - } - } - SettingsRequest::PeerId(node) => { - // get peer info - match Request::to(("our", "net", "distro", "sys")) - .body(rmp_serde::to_vec(&net::NetAction::GetPeer(node)).unwrap()) - .send_and_await_response(30) - .unwrap() - { - Ok(msg) => match rmp_serde::from_slice::(msg.body()) { - Ok(net::NetResponse::Peer(Some(peer))) => { - println!("got peer info: {peer:?}"); - return Ok(Some(SettingsData::PeerId(peer))); - } - Ok(net::NetResponse::Peer(None)) => { - println!("peer not found"); - return Ok(None); - } - _ => { - return Err(SettingsError::KernelNonresponsive); - } - }, - Err(_) => { - return Err(SettingsError::KernelNonresponsive); - } - } - } - SettingsRequest::EthConfig(action) => { - match Request::to(("our", "eth", "distro", "sys")) - .body(serde_json::to_vec(&action).unwrap()) - .send_and_await_response(30) - .unwrap() - { - Ok(msg) => match serde_json::from_slice::(msg.body()) { - Ok(eth::EthConfigResponse::PermissionDenied) => { - return Err(SettingsError::KernelNonresponsive); - } - Ok(other) => { - println!("eth config action succeeded: {other:?}"); - } - Err(_) => { - return Err(SettingsError::KernelNonresponsive); - } - }, - Err(_) => { - return Err(SettingsError::KernelNonresponsive); - } - } - } - SettingsRequest::Shutdown => { - // shutdown the node IMMEDIATELY! - Request::to(("our", "kernel", "distro", "sys")) - .body(serde_json::to_vec(&kernel_types::KernelCommand::Shutdown).unwrap()) - .send() - .unwrap(); - } - SettingsRequest::KillProcess(pid) => { - // kill a process - if let Err(_) = Request::to(("our", "kernel", "distro", "sys")) - .body(serde_json::to_vec(&kernel_types::KernelCommand::KillProcess(pid)).unwrap()) - .send_and_await_response(30) - .unwrap() - { - return SettingsResponse::Err(SettingsError::KernelNonresponsive); - } - } - SettingsRequest::SetStylesheet(stylesheet) => { - let Ok(()) = kinode_process_lib::vfs::File { - path: "/homepage:sys/pkg/kinode.css".to_string(), - timeout: 5, - } - .write(stylesheet.as_bytes()) else { - return SettingsResponse::Err(SettingsError::KernelNonresponsive); - }; - Request::to(("our", "homepage", "homepage", "sys")) - .body( - serde_json::json!({ "SetStylesheet": stylesheet }) - .to_string() - .as_bytes(), - ) - .send() - .unwrap(); - state.stylesheet = Some(stylesheet); - return SettingsResponse::Ok(None); - } + ContactsRequest::GetNames => ContactsResponse::GetNames( + state + .contacts() + .0 + .keys() + .map(|node| node.to_string()) + .collect(), + ), + ContactsRequest::GetAllContacts => ContactsResponse::GetAllContacts, + ContactsRequest::GetContact(node) => ContactsResponse::GetContact, + ContactsRequest::AddContact(node) => ContactsResponse::AddContact, + ContactsRequest::AddField((node, field, value)) => ContactsResponse::AddField, + ContactsRequest::RemoveContact(node) => ContactsResponse::RemoveContact, + ContactsRequest::RemoveField((node, field)) => ContactsResponse::RemoveField, } - - state.fetch().map_err(|_| SettingsError::StateFetchFailed)?; - SettingsResponse::Ok(None) } diff --git a/kinode/packages/contacts/metadata.json b/kinode/packages/contacts/metadata.json index 85ee4548..c3a7a181 100644 --- a/kinode/packages/contacts/metadata.json +++ b/kinode/packages/contacts/metadata.json @@ -1,6 +1,6 @@ { "name": "Contacts", - "description": "Store and manage your contacts.", + "description": "Save and manage your Kinode OS contacts.", "image": "", "properties": { "package_name": "contacts", diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html index 38c627fa..e6dcb5ad 100644 --- a/kinode/packages/contacts/pkg/ui/index.html +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -6,13 +6,10 @@ - + -

system diagnostics & settings

+

contacts

-
-

networking diagnostics

-

-
- -
-

node info

-

-

-

-

- -
- -
-

fetch PKI data

-
- - -
-

-

ping a node

-
- - - - -
-

-
- -
-

ETH RPC providers

-
-
- - - -
-
- - - -
-
-
    -
    - -
    -

    ETH RPC settings

    -

    -
    -

    nodes allowed to connect:

    -
      -
      -
      -

      nodes banned from connecting:

      -
        -
        -
        - -
        -

        running processes

        -
          -
          - -
          -

          stylesheet editor

          - - -
          - - - +
          diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index 01ebb557..8f1376c5 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -1,16 +1,16 @@ -const APP_PATH = '/settings:settings:sys/ask'; +const APP_PATH = '/contacts:contacts:sys/'; // Fetch initial data and populate the UI function init() { - fetch(APP_PATH) + fetch(APP_PATH + 'get') .then(response => response.json()) .then(data => { populate(data); }); } -function api_call(body) { - fetch(APP_PATH, { +function api_call(path, body) { + fetch(APP_PATH + path, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -19,302 +19,19 @@ function api_call(body) { }); } -function shutdown() { - api_call("Shutdown"); - setTimeout(() => { - window.location.reload(); - }, 1000); -} - function populate(data) { - populate_node_info(data.identity); - populate_net_diagnostics(data.diagnostics); - populate_eth_rpc_providers(data.eth_rpc_providers); - populate_eth_rpc_settings(data.eth_rpc_access_settings); - populate_process_map(data.process_map); - populate_stylesheet_editor(data.stylesheet); -} - -function populate_node_info(identity) { - document.getElementById('node-name').innerText = identity.name; - document.getElementById('net-key').innerText = identity.networking_key; - if (identity.ws_routing) { - document.getElementById('ip-ports').innerText = identity.ws_routing; - } else { - document.getElementById('ip-ports').style.display = 'none'; - } - if (identity.routers) { - document.getElementById('routers').innerText = identity.routers; - } else { - document.getElementById('routers').style.display = 'none'; - } -} - -function populate_net_diagnostics(diagnostics) { - document.getElementById('diagnostics').innerText = diagnostics; -} - -function populate_eth_rpc_providers(providers) { - const ul = document.getElementById('providers'); - ul.innerHTML = ''; - providers.forEach(provider => { - const li = document.createElement('li'); - li.innerHTML = `${JSON.stringify(provider, undefined, 2)}`; - ul.appendChild(li); - }); -} - -function populate_eth_rpc_settings(settings) { - if (settings.public) { - document.getElementById('public').innerText = 'status: public'; - document.getElementById('allowed-nodes').style.display = 'none'; - } else { - document.getElementById('public').innerText = 'status: private'; - const ul = document.getElementById('allowed-nodes'); - ul.innerHTML = ''; - if (settings.allow.length === 0) { - const li = document.createElement('li'); - li.innerHTML = `
        • (none)
        • `; - ul.appendChild(li); - } else { - settings.allow.forEach(allowed_node => { - const li = document.createElement('li'); - li.innerHTML = `
        • ${allowed_node}
        • `; - ul.appendChild(li); - }); - } - } - const ul = document.getElementById('denied-nodes'); - ul.innerHTML = ''; - if (settings.deny.length === 0) { - const li = document.createElement('li'); - li.innerHTML = `
        • (none)
        • `; - ul.appendChild(li); - } else { - settings.deny.forEach(denied_node => { - const li = document.createElement('li'); - li.innerHTML = `
        • ${denied_node}
        • `; - ul.appendChild(li); - }); - } -} - -function populate_process_map(process_map) { - // apps we don't want user to kill, also runtime modules that cannot be killed - const do_not_kill = [ - 'settings:setting:sys', - 'main:app_store:sys', - 'net:distro:sys', - 'kernel:distro:sys', - 'kv:distro:sys', - 'sqlite:distro:sys', - 'eth:distro:sys', - 'vfs:distro:sys', - 'state:distro:sys', - 'kns_indexer:kns_indexer:sys', - 'http_client:distro:sys', - 'http_server:distro:sys', - 'terminal:terminal:sys', - 'timer:distro:sys', - ]; - - const ul = document.getElementById('process-map'); - ul.innerHTML = ''; - Object.entries(process_map).forEach(([id, process]) => { - const li = document.createElement('li'); - - const toggleButton = document.createElement('button'); - toggleButton.textContent = `${id}`; - toggleButton.onclick = function () { - const details = this.nextElementSibling; - details.style.display = details.style.display === 'none' ? 'block' : 'none'; - }; - li.appendChild(toggleButton); - - const detailsDiv = document.createElement('div'); - detailsDiv.style.display = 'none'; - - if (!do_not_kill.includes(id)) { - const killButton = document.createElement('button'); - killButton.className = 'kill-process'; - killButton.setAttribute('data-id', id); - killButton.textContent = 'kill'; - detailsDiv.appendChild(killButton); - } - - const publicInfo = document.createElement('p'); - publicInfo.textContent = `public: ${process.public}`; - detailsDiv.appendChild(publicInfo); - - const onExit = document.createElement('p'); - onExit.textContent = `on_exit: ${process.on_exit}`; - detailsDiv.appendChild(onExit); - - if (process.wit_version) { - const witVersion = document.createElement('p'); - witVersion.textContent = `wit_version: ${process.wit_version}`; - detailsDiv.appendChild(witVersion); - } - - if (process.wasm_bytes_handle) { - const wasmBytesHandle = document.createElement('p'); - wasmBytesHandle.textContent = `wasm_bytes_handle: ${process.wasm_bytes_handle}`; - detailsDiv.appendChild(wasmBytesHandle); - } - - const capsList = document.createElement('ul'); - process.capabilities.forEach(cap => { - const capLi = document.createElement('li'); - capLi.textContent = `${cap.issuer}(${JSON.stringify(JSON.parse(cap.params), null, 2)})`; - capsList.appendChild(capLi); - }); - detailsDiv.appendChild(capsList); - - li.appendChild(detailsDiv); - ul.appendChild(li); - }); - document.querySelectorAll('.kill-process').forEach(button => { - button.addEventListener('click', () => { - api_call({ "KillProcess": button.getAttribute('data-id') }); - }); - }); -} - -function populate_stylesheet_editor(stylesheet) { - document.getElementById('stylesheet-editor').value = stylesheet; -} - -function save_stylesheet() { - const stylesheet = document.getElementById('stylesheet-editor').value; - api_call({ "SetStylesheet": stylesheet }); + console.log(data); } // Call init to start the application init(); -// Setup event listeners -document.getElementById('shutdown').addEventListener('click', shutdown); - -document.getElementById('save-stylesheet').addEventListener('click', save_stylesheet); - -document.getElementById('get-peer-pki').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const body = { - "PeerId": data.get('peer'), - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - document.getElementById('peer-pki-response').innerText = "no pki data for peer"; - } else { - e.target.reset(); - document.getElementById('peer-pki-response').innerText = JSON.stringify(data, undefined, 2); - } - }); -}) - -document.getElementById('ping-peer').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const body = { - "Hi": { - node: data.get('peer'), - content: data.get('content'), - timeout: Number(data.get('timeout')), - } - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - e.target.reset(); - document.getElementById('peer-ping-response').innerText = "ping successful!"; - } else if (data === "HiTimeout") { - document.getElementById('peer-ping-response').innerText = "node timed out"; - } else if (data === "HiOffline") { - document.getElementById('peer-ping-response').innerText = "node is offline"; - } - }); -}) - -document.getElementById('add-eth-provider').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const rpc_url = data.get('rpc-url'); - // validate rpc url - if (!rpc_url.startsWith('wss://') && !rpc_url.startsWith('ws://')) { - alert('Invalid RPC URL'); - return; - } - const body = { - "EthConfig": { - "AddProvider": { - chain_id: Number(data.get('chain-id')), - trusted: false, - provider: { "RpcUrl": rpc_url }, - } - } - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - e.target.reset(); - return; - } else { - alert(data); - } - }); -}) - -document.getElementById('remove-eth-provider').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const body = { - "EthConfig": { - "RemoveProvider": [Number(data.get('chain-id')), data.get('rpc-url')] - } - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - e.target.reset(); - return; - } else { - alert(data); - } - }); -}) - // Setup WebSocket connection -const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; -const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/"); -ws.onmessage = event => { - const data = JSON.parse(event.data); - console.log(data); - populate(data); -}; +// const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; +// const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/"); +// ws.onmessage = event => { +// const data = JSON.parse(event.data); +// console.log(data); +// populate(data); +// };