Skip to content
Merged

0.9.7 #111

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "kinode_process_lib"
description = "A library for writing Kinode processes in Rust."
version = "0.9.6"
version = "0.9.7"
edition = "2021"
license-file = "LICENSE"
homepage = "https://kinode.org"
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# `kinode_process_lib`

Library of functions for more ergonomic [Kinode](https://github.com/kinode-dao/kinode) Rust process development.
Documentation can be found [here](https://docs.rs/kinode_process_lib).

[Documentation can be found here](https://docs.rs/kinode_process_lib).

[Crate can be found here](https://crates.io/crates/kinode_process_lib).

See the [Kinode Book](https://book.kinode.org) for a guide on how to use this library to write Kinode apps in Rust.

The major version of `kinode_process_lib` will always match the major version of Kinode OS.
Expand Down
16 changes: 8 additions & 8 deletions src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub enum EthAction {
},
}

/// Incoming `Request` containing subscription updates or errors that processes will receive.
/// Incoming [`crate::Request`] containing subscription updates or errors that processes will receive.
/// Can deserialize all incoming requests from eth:distro:sys to this type.
///
/// Will be serialized and deserialized using `serde_json::to_vec` and `serde_json::from_slice`.
Expand All @@ -54,7 +54,7 @@ pub struct EthSubError {
pub error: String,
}

/// The Response type which a process will get from requesting with an [`EthAction`] will be
/// The [`crate::Response`] type which a process will get from requesting with an [`EthAction`] will be
/// of this type, serialized and deserialized using `serde_json::to_vec`
/// and `serde_json::from_slice`.
///
Expand Down Expand Up @@ -90,7 +90,7 @@ pub enum EthError {
}

/// The action type used for configuring eth:distro:sys. Only processes which have the "root"
/// capability from eth:distro:sys can successfully send this action.
/// [`crate::Capability`] from eth:distro:sys can successfully send this action.
#[derive(Debug, Serialize, Deserialize)]
pub enum EthConfigAction {
/// Add a new provider to the list of providers.
Expand Down Expand Up @@ -126,12 +126,12 @@ pub enum EthConfigAction {
pub enum EthConfigResponse {
Ok,
/// Response from a GetProviders request.
/// Note the [`crate::kernel_types::KnsUpdate`] will only have the correct `name` field.
/// Note the [`crate::net::KnsUpdate`] will only have the correct `name` field.
/// The rest of the Update is not saved in this module.
Providers(SavedConfigs),
/// Response from a GetAccessSettings request.
AccessSettings(AccessSettings),
/// Permission denied due to missing capability
/// Permission denied due to missing [`crate::Capability`]
PermissionDenied,
/// Response from a GetState request
State {
Expand Down Expand Up @@ -194,11 +194,11 @@ impl Provider {
request_timeout,
}
}
/// Sends a request based on the specified `EthAction` and parses the response.
/// Sends a request based on the specified [`EthAction`] and parses the response.
///
/// This function constructs a request targeting the Ethereum distribution system, serializes the provided `EthAction`,
/// This function constructs a request targeting the Ethereum distribution system, serializes the provided [`EthAction`],
/// and sends it. It awaits a response with a specified timeout, then attempts to parse the response into the expected
/// type `T`. This method is generic and can be used for various Ethereum actions by specifying the appropriate `EthAction`
/// type `T`. This method is generic and can be used for various Ethereum actions by specifying the appropriate [`EthAction`]
/// and return type `T`.
pub fn send_request_and_parse_response<T: serde::de::DeserializeOwned>(
&self,
Expand Down
4 changes: 2 additions & 2 deletions src/homepage.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Request;

/// Add a new icon and/or widget to the Kinode homepage. Note that the process calling this
/// function must have the `homepage:homepage:sys` messaging capability.
/// function must have the `homepage:homepage:sys` messaging [`crate::Capability`].
///
/// This should be called upon process startup to ensure that the process is added to the homepage.
///
Expand Down Expand Up @@ -30,7 +30,7 @@ pub fn add_to_homepage(label: &str, icon: Option<&str>, path: Option<&str>, widg
}

/// Remove the caller process from the Kinode homepage. Note that the process calling this function
/// must have the `homepage:homepage:sys` messaging capability.
/// must have the `homepage:homepage:sys` messaging [`crate::Capability`].
///
/// This usually isn't necessary as processes are not persisted on homepage between boots.
pub fn remove_from_homepage() {
Expand Down
10 changes: 5 additions & 5 deletions src/http/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use std::collections::HashMap;
use std::str::FromStr;
use thiserror::Error;

/// Request type sent to the `http_client:distro:sys` service in order to open a
/// [`crate::Request`] type sent to the `http_client:distro:sys` service in order to open a
/// WebSocket connection, send a WebSocket message on an existing connection, or
/// send an HTTP request.
///
/// You will receive a Response with the format `Result<HttpClientResponse, HttpClientError>`.
/// You will receive a [`crate::Response`] with the format `Result<HttpClientResponse, HttpClientError>`.
///
/// Always serialized/deserialized as JSON.
#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -47,7 +47,7 @@ pub struct OutgoingHttpRequest {
pub headers: HashMap<String, String>,
}

/// Request that comes from an open WebSocket client connection in the
/// [`crate::Request`] that comes from an open WebSocket client connection in the
/// `http_client:distro:sys` service. Be prepared to receive these after
/// using a [`HttpClientAction::WebSocketOpen`] to open a connection.
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
Expand All @@ -61,7 +61,7 @@ pub enum HttpClientRequest {
},
}

/// Response type received from the `http_client:distro:sys` service after
/// [`crate::Response`] type received from the `http_client:distro:sys` service after
/// sending a successful [`HttpClientAction`] to it.
#[derive(Debug, Serialize, Deserialize)]
pub enum HttpClientResponse {
Expand Down Expand Up @@ -125,7 +125,7 @@ pub fn send_request(

/// Make an HTTP request using http_client and await its response.
///
/// Returns [`Response`] from the `http` crate if successful, with the body type as bytes.
/// Returns HTTP response from the `http` crate if successful, with the body type as bytes.
pub fn send_request_await_response(
method: Method,
url: url::Url,
Expand Down
83 changes: 49 additions & 34 deletions src/http/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ use crate::{
get_blob, Address, LazyLoadBlob as KiBlob, Message, Request as KiRequest,
Response as KiResponse,
};
use http::{HeaderMap, HeaderName, HeaderValue, StatusCode};
pub use http::StatusCode;
use http::{HeaderMap, HeaderName, HeaderValue};
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use thiserror::Error;

/// HTTP Request received from the `http_server:distro:sys` service as a
/// [`crate::Request`] received from the `http_server:distro:sys` service as a
/// result of either an HTTP or WebSocket binding, created via [`HttpServerAction`].
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum HttpServerRequest {
Http(IncomingHttpRequest),
/// Processes will receive this kind of request when a client connects to them.
/// If a process does not want this websocket open, they should issue a *request*
/// If a process does not want this websocket open, they should issue a [`crate::Request`]
/// containing a [`HttpServerAction::WebSocketClose`] message and this channel ID.
WebSocketOpen {
path: String,
channel_id: u32,
},
/// Processes can both SEND and RECEIVE this kind of request
/// Processes can both SEND and RECEIVE this kind of [`crate::Request`]
/// (send as [`HttpServerAction::WebSocketPush`]).
/// When received, will contain the message bytes as lazy_load_blob.
/// When received, will contain the message bytes as [`crate::LazyLoadBlob`].
WebSocketPush {
channel_id: u32,
message_type: WsMessageType,
Expand All @@ -33,7 +34,7 @@ pub enum HttpServerRequest {
}

impl HttpServerRequest {
/// Parse a byte slice into an HttpServerRequest.
/// Parse a byte slice into an [`HttpServerRequest`].
pub fn from_bytes(bytes: &[u8]) -> serde_json::Result<Self> {
serde_json::from_slice(bytes)
}
Expand Down Expand Up @@ -132,9 +133,9 @@ impl IncomingHttpRequest {

/// The possible message types for [`HttpServerRequest::WebSocketPush`].
/// Ping and Pong are limited to 125 bytes by the WebSockets protocol.
/// Text will be sent as a Text frame, with the lazy_load_blob bytes
/// Text will be sent as a Text frame, with the [`crate::LazyLoadBlob`] bytes
/// being the UTF-8 encoding of the string. Binary will be sent as a
/// Binary frame containing the unmodified lazy_load_blob bytes.
/// Binary frame containing the unmodified [`crate::LazyLoadBlob`] bytes.
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum WsMessageType {
Text,
Expand All @@ -144,26 +145,26 @@ pub enum WsMessageType {
Close,
}

/// Request type sent to `http_server:distro:sys` in order to configure it.
/// [`crate::Request`] type sent to `http_server:distro:sys` in order to configure it.
///
/// If a response is expected, all actions will return a Response
/// If a [`crate::Response`] is expected, all actions will return a [`crate::Response`]
/// with the shape `Result<(), HttpServerActionError>` serialized to JSON.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum HttpServerAction {
/// Bind expects a lazy_load_blob if and only if `cache` is TRUE. The lazy_load_blob should
/// be the static file to serve at this path.
/// Bind expects a [`crate::LazyLoadBlob`] if and only if `cache` is TRUE.
/// The [`crate::LazyLoadBlob`] should be the static file to serve at this path.
Bind {
path: String,
/// Set whether the HTTP request needs a valid login cookie, AKA, whether
/// the user needs to be logged in to access this path.
authenticated: bool,
/// Set whether requests can be fielded from anywhere, or only the loopback address.
/// Set whether [`crate::Request`]s can be fielded from anywhere, or only the loopback address.
local_only: bool,
/// Set whether to bind the lazy_load_blob statically to this path. That is, take the
/// lazy_load_blob bytes and serve them as the response to any request to this path.
/// Set whether to bind the [`crate::LazyLoadBlob`] statically to this path. That is, take the
/// [`crate::LazyLoadBlob`] bytes and serve them as the response to any request to this path.
cache: bool,
},
/// SecureBind expects a lazy_load_blob if and only if `cache` is TRUE. The lazy_load_blob should
/// SecureBind expects a [`crate::LazyLoadBlob`] if and only if `cache` is TRUE. The [`crate::LazyLoadBlob`] should
/// be the static file to serve at this path.
///
/// SecureBind is the same as Bind, except that it forces requests to be made from
Expand All @@ -174,8 +175,8 @@ pub enum HttpServerAction {
/// will require the user to be logged in separately to the general domain authentication.
SecureBind {
path: String,
/// Set whether to bind the lazy_load_blob statically to this path. That is, take the
/// lazy_load_blob bytes and serve them as the response to any request to this path.
/// Set whether to bind the [`crate::LazyLoadBlob`] statically to this path. That is, take the
/// [`crate::LazyLoadBlob`] bytes and serve them as the response to any request to this path.
cache: bool,
},
/// Unbind a previously-bound HTTP path
Expand All @@ -199,26 +200,26 @@ pub enum HttpServerAction {
},
/// Unbind a previously-bound WebSocket path
WebSocketUnbind { path: String },
/// When sent, expects a lazy_load_blob containing the WebSocket message bytes to send.
/// When sent, expects a [`crate::LazyLoadBlob`] containing the WebSocket message bytes to send.
WebSocketPush {
channel_id: u32,
message_type: WsMessageType,
},
/// When sent, expects a `lazy_load_blob` containing the WebSocket message bytes to send.
/// Modifies the `lazy_load_blob` by placing into `WebSocketExtPushData` with id taken from
/// this `KernelMessage` and `kinode_message_type` set to `desired_reply_type`.
/// When sent, expects a [`crate::LazyLoadBlob`] containing the WebSocket message bytes to send.
/// Modifies the [`crate::LazyLoadBlob`] by placing into [`HttpServerAction::WebSocketExtPushData`]` with id taken from
/// this [`KernelMessage`]` and `kinode_message_type` set to `desired_reply_type`.
WebSocketExtPushOutgoing {
channel_id: u32,
message_type: WsMessageType,
desired_reply_type: MessageType,
},
/// For communicating with the ext.
/// Kinode's http_server sends this to the ext after receiving `WebSocketExtPushOutgoing`.
/// Kinode's http_server sends this to the ext after receiving [`HttpServerAction::WebSocketExtPushOutgoing`].
/// Upon receiving reply with this type from ext, http_server parses, setting:
/// * id as given,
/// * message type as given (Request or Response),
/// * body as HttpServerRequest::WebSocketPush,
/// * blob as given.
/// * message type as given ([`crate::Request`] or [`crate::Response`]),
/// * body as [`HttpServerRequest::WebSocketPush`],
/// * [`crate::LazyLoadBlob`] as given.
WebSocketExtPushData {
id: u64,
kinode_message_type: MessageType,
Expand All @@ -230,11 +231,12 @@ pub enum HttpServerAction {

/// HTTP Response type that can be shared over Wasm boundary to apps.
/// Respond to [`IncomingHttpRequest`] with this type.
///
/// BODY is stored in the [`crate::LazyLoadBlob`] as bytes
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct HttpResponse {
pub status: u16,
pub headers: HashMap<String, String>,
// BODY is stored in the lazy_load_blob, as bytes
}

impl HttpResponse {
Expand Down Expand Up @@ -268,7 +270,7 @@ impl HttpResponse {
}
}

/// Part of the Response type issued by http_server
/// Part of the [`crate::Response`] type issued by http_server
#[derive(Clone, Debug, Error, Serialize, Deserialize)]
pub enum HttpServerError {
#[error("request could not be parsed to HttpServerAction: {req}.")]
Expand All @@ -287,7 +289,7 @@ pub enum HttpServerError {
UnexpectedResponse,
}

/// Whether the WebSocketPush is a request or a response.
/// Whether the [`HttpServerAction::WebSocketPush`] is [`crate::Request`] or [`crate::Response`].
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum MessageType {
Request,
Expand Down Expand Up @@ -1040,11 +1042,11 @@ impl HttpServer {

/// Push a WebSocket message to all channels on a given path.
pub fn ws_push_all_channels(&self, path: &str, message_type: WsMessageType, blob: KiBlob) {
if let Some(channels) = self.ws_channels.get(path) {
channels.iter().for_each(|channel_id| {
send_ws_push(*channel_id, message_type, blob.clone());
});
}
ws_push_all_channels(&self.ws_channels, path, message_type, blob);
}

pub fn get_ws_channels(&self) -> HashMap<String, HashSet<u32>> {
self.ws_channels.clone()
}
}

Expand Down Expand Up @@ -1078,6 +1080,19 @@ pub fn send_ws_push(channel_id: u32, message_type: WsMessageType, blob: KiBlob)
.unwrap()
}

pub fn ws_push_all_channels(
ws_channels: &HashMap<String, HashSet<u32>>,
path: &str,
message_type: WsMessageType,
blob: KiBlob,
) {
if let Some(channels) = ws_channels.get(path) {
channels.iter().for_each(|channel_id| {
send_ws_push(*channel_id, message_type, blob.clone());
});
}
}

/// Guess the MIME type of a file from its extension.
pub fn get_mime_type(filename: &str) -> String {
let file_path = std::path::Path::new(filename);
Expand Down
10 changes: 5 additions & 5 deletions src/kernel_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub enum KernelCommand {
/// The process that sends this command will be given messaging capabilities
/// for the new process if `public` is false.
///
/// All capabilities passed into initial_capabilities must be held by the source
/// All capabilities passed into `initial_capabilities` must be held by the source
/// of this message, or the kernel will discard them (silently for now).
InitializeProcess {
id: ProcessId,
Expand Down Expand Up @@ -273,7 +273,7 @@ impl StateError {
/// - `image`: An optional field containing a URL to an image representing the package.
/// - `external_url`: An optional field containing a URL for more information about the package. For example, a link to the github repository.
/// - `animation_url`: An optional field containing a URL to an animation or video representing the package.
/// - `properties`: A requried field containing important information about the package.
/// - `properties`: A required field containing important information about the package.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Erc721Metadata {
pub name: Option<String>,
Expand All @@ -288,15 +288,15 @@ pub struct Erc721Metadata {
/// This follows the [ERC1155](https://github.com/ethereum/ercs/blob/master/ERCS/erc-1155.md#erc-1155-metadata-uri-json-schema) metadata standard.
///
/// Fields:
/// - `package_name`: The unique name of the package, used in the `PackageId`, e.g. `package_name:publisher`.
/// - `publisher`: The KNS identity of the package publisher used in the `PackageId`, e.g. `package_name:publisher`
/// - `package_name`: The unique name of the package, used in the [`crate::PackageId`], e.g. `package_name:publisher`.
/// - `publisher`: The KNS identity of the package publisher used in the [`crate::PackageId`], e.g. `package_name:publisher`
/// - `current_version`: A string representing the current version of the package, e.g. `1.0.0`.
/// - `mirrors`: A list of NodeIds where the package can be found, providing redundancy.
/// - `code_hashes`: A map from version names to their respective SHA-256 hashes.
/// - `license`: An optional field containing the license of the package.
/// - `screenshots`: An optional field containing a list of URLs to screenshots of the package.
/// - `wit_version`: An optional field containing the version of the WIT standard that the package adheres to.
/// - `dependencies`: An optional field containing a list of `PackageId`s: API dependencies.
/// - `dependencies`: An optional field containing a list of [`crate::PackageId`]s: API dependencies.
/// - `api_includes`: An optional field containing a list of `PathBuf`s: additional files to include in the `api.zip`.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Erc721Properties {
Expand Down
Loading
Loading