mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-23 16:43:24 +03:00
app_store: fix uninstall removing listing, separate backend api, add progress update to FT
This commit is contained in:
parent
14d119f55b
commit
b8811180e2
@ -19,6 +19,8 @@ pub fn init_frontend(our: &Address) {
|
|||||||
for path in [
|
for path in [
|
||||||
"/apps",
|
"/apps",
|
||||||
"/apps/:id",
|
"/apps/:id",
|
||||||
|
"/apps/:id/download",
|
||||||
|
"/apps/:id/install",
|
||||||
"/apps/:id/caps",
|
"/apps/:id/caps",
|
||||||
"/apps/:id/mirror",
|
"/apps/:id/mirror",
|
||||||
"/apps/:id/auto-update",
|
"/apps/:id/auto-update",
|
||||||
@ -27,13 +29,7 @@ pub fn init_frontend(our: &Address) {
|
|||||||
] {
|
] {
|
||||||
bind_http_path(path, true, false).expect("failed to bind http path");
|
bind_http_path(path, true, false).expect("failed to bind http path");
|
||||||
}
|
}
|
||||||
serve_ui(
|
serve_ui(&our, "ui", true, false, vec!["/", "/app/:id", "/publish"])
|
||||||
&our,
|
|
||||||
"ui",
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
vec!["/", "/my-apps", "/app/:id", "/publish"],
|
|
||||||
)
|
|
||||||
.expect("failed to serve static UI");
|
.expect("failed to serve static UI");
|
||||||
|
|
||||||
bind_ws_path("/", true, true).expect("failed to bind ws path");
|
bind_ws_path("/", true, true).expect("failed to bind ws path");
|
||||||
@ -176,9 +172,10 @@ fn make_widget() -> String {
|
|||||||
/// - get capabilities for a specific downloaded app: GET /apps/:id/caps
|
/// - get capabilities for a specific downloaded app: GET /apps/:id/caps
|
||||||
///
|
///
|
||||||
/// - get online/offline mirrors for a listed app: GET /mirrorcheck/:node
|
/// - get online/offline mirrors for a listed app: GET /mirrorcheck/:node
|
||||||
/// - install a downloaded app, download a listed app: POST /apps/:id
|
/// - download a listed app: POST /apps/:id/download
|
||||||
|
/// - install a downloaded app: POST /apps/:id/install
|
||||||
/// - uninstall/delete a downloaded app: DELETE /apps/:id
|
/// - uninstall/delete a downloaded app: DELETE /apps/:id
|
||||||
/// - update a downloaded app: PUT /apps/:id
|
/// - update a downloaded app: PUT /apps/:id FIX
|
||||||
/// - approve capabilities for a downloaded app: POST /apps/:id/caps
|
/// - approve capabilities for a downloaded app: POST /apps/:id/caps
|
||||||
/// - start mirroring a downloaded app: PUT /apps/:id/mirror
|
/// - start mirroring a downloaded app: PUT /apps/:id/mirror
|
||||||
/// - stop mirroring a downloaded app: DELETE /apps/:id/mirror
|
/// - stop mirroring a downloaded app: DELETE /apps/:id/mirror
|
||||||
@ -312,9 +309,7 @@ fn serve_paths(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// GET detail about a specific app
|
// GET detail about a specific app
|
||||||
// install an app: POST
|
|
||||||
// update a downloaded app: PUT
|
// update a downloaded app: PUT
|
||||||
// uninstall an app: DELETE
|
|
||||||
"/apps/:id" => {
|
"/apps/:id" => {
|
||||||
let Ok(package_id) = get_package_id(url_params) else {
|
let Ok(package_id) = get_package_id(url_params) else {
|
||||||
return Ok((
|
return Ok((
|
||||||
@ -341,19 +336,32 @@ fn serve_paths(
|
|||||||
.into_bytes(),
|
.into_bytes(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Method::POST => {
|
Method::DELETE => {
|
||||||
let Some(listing) = state.packages.get(&package_id) else {
|
// uninstall an app
|
||||||
return Ok((
|
state.uninstall(&package_id)?;
|
||||||
StatusCode::NOT_FOUND,
|
Ok((
|
||||||
|
StatusCode::NO_CONTENT,
|
||||||
None,
|
None,
|
||||||
format!("App not found: {package_id}").into_bytes(),
|
format!("Uninstalled").into_bytes(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => Ok((
|
||||||
|
StatusCode::METHOD_NOT_ALLOWED,
|
||||||
|
None,
|
||||||
|
format!("Invalid method {method} for {bound_path}").into_bytes(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// PUT /apps/:id/download
|
||||||
|
// download a listed app from a mirror
|
||||||
|
"/apps/:id/download" => {
|
||||||
|
let Ok(package_id) = get_package_id(url_params) else {
|
||||||
|
return Ok((
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
None,
|
||||||
|
format!("Missing id").into_bytes(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
if listing.state.is_some() {
|
|
||||||
// install a downloaded app
|
|
||||||
crate::handle_install(state, &package_id)?;
|
|
||||||
Ok((StatusCode::CREATED, None, format!("Installed").into_bytes()))
|
|
||||||
} else {
|
|
||||||
// download a listed app
|
// download a listed app
|
||||||
let pkg_listing: &PackageListing = state
|
let pkg_listing: &PackageListing = state
|
||||||
.packages
|
.packages
|
||||||
@ -363,8 +371,7 @@ fn serve_paths(
|
|||||||
let body = crate::get_blob()
|
let body = crate::get_blob()
|
||||||
.ok_or(anyhow::anyhow!("missing blob"))?
|
.ok_or(anyhow::anyhow!("missing blob"))?
|
||||||
.bytes;
|
.bytes;
|
||||||
let body_json: serde_json::Value =
|
let body_json: serde_json::Value = serde_json::from_slice(&body).unwrap_or_default();
|
||||||
serde_json::from_slice(&body).unwrap_or_default();
|
|
||||||
let mirrors: &Vec<NodeId> = pkg_listing
|
let mirrors: &Vec<NodeId> = pkg_listing
|
||||||
.metadata
|
.metadata
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -377,13 +384,12 @@ fn serve_paths(
|
|||||||
.get("download_from")
|
.get("download_from")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.or_else(|| mirrors.first().map(|mirror| mirror.to_string()));
|
.or_else(|| mirrors.first().map(|mirror| mirror.to_string()))
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("No download_from specified!"))?;
|
||||||
|
|
||||||
// if no specific mirror specified, loop through and ping them.
|
|
||||||
if let Some(download_from) = download_from {
|
|
||||||
// TODO choose more on frontend.
|
|
||||||
let mirror = false;
|
let mirror = false;
|
||||||
let auto_update = false;
|
let auto_update = false;
|
||||||
|
// TODO choose on frontend?
|
||||||
let desired_version_hash = None;
|
let desired_version_hash = None;
|
||||||
match crate::start_download(
|
match crate::start_download(
|
||||||
state,
|
state,
|
||||||
@ -404,144 +410,24 @@ fn serve_paths(
|
|||||||
format!("Failed to download: {other:?}").into_bytes(),
|
format!("Failed to download: {other:?}").into_bytes(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let online_mirrors: Vec<NodeId> = mirrors
|
|
||||||
.iter()
|
|
||||||
.filter_map(|mirror| {
|
|
||||||
let target = Address::new(
|
|
||||||
mirror,
|
|
||||||
ProcessId::new(Some("net"), "distro", "sys"),
|
|
||||||
);
|
|
||||||
let request = Request::new().target(target).body(vec![]).send();
|
|
||||||
|
|
||||||
match request {
|
|
||||||
Ok(_) => Some(mirror.clone()),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
}
|
||||||
})
|
// POST /apps/:id/install
|
||||||
.collect();
|
// install a downloaded app
|
||||||
|
"/apps/:id/install" => {
|
||||||
println!("all mirrors: {:?}", mirrors);
|
let Ok(package_id) = get_package_id(url_params) else {
|
||||||
println!("online mirrors: {:?}", online_mirrors);
|
|
||||||
|
|
||||||
let mut failed_mirrors = Vec::new();
|
|
||||||
for online_mirror in &online_mirrors {
|
|
||||||
let mirror = true;
|
|
||||||
let auto_update = false;
|
|
||||||
let desired_version_hash = None;
|
|
||||||
match crate::start_download(
|
|
||||||
state,
|
|
||||||
package_id.clone(),
|
|
||||||
online_mirror.to_string(),
|
|
||||||
mirror,
|
|
||||||
auto_update,
|
|
||||||
desired_version_hash,
|
|
||||||
) {
|
|
||||||
DownloadResponse::Started => {
|
|
||||||
return Ok((
|
return Ok((
|
||||||
StatusCode::CREATED,
|
StatusCode::BAD_REQUEST,
|
||||||
None,
|
None,
|
||||||
format!(
|
format!("Missing id").into_bytes(),
|
||||||
"Download started from mirror: {}",
|
|
||||||
online_mirror
|
|
||||||
)
|
|
||||||
.into_bytes(),
|
|
||||||
));
|
));
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
failed_mirrors.push(online_mirror.to_string());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut failed_mirrors = Vec::new();
|
|
||||||
for online_mirror in &online_mirrors {
|
|
||||||
let mirror = true;
|
|
||||||
let auto_update = false;
|
|
||||||
let desired_version_hash = None;
|
|
||||||
match crate::start_download(
|
|
||||||
state,
|
|
||||||
package_id.clone(),
|
|
||||||
online_mirror.to_string(),
|
|
||||||
mirror,
|
|
||||||
auto_update,
|
|
||||||
desired_version_hash,
|
|
||||||
) {
|
|
||||||
DownloadResponse::Started => {
|
|
||||||
return Ok((
|
|
||||||
StatusCode::CREATED,
|
|
||||||
None,
|
|
||||||
format!(
|
|
||||||
"Download started from mirror: {}",
|
|
||||||
online_mirror
|
|
||||||
)
|
|
||||||
.into_bytes(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
failed_mirrors.push(online_mirror.to_string());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok((
|
|
||||||
StatusCode::SERVICE_UNAVAILABLE,
|
|
||||||
None,
|
|
||||||
format!(
|
|
||||||
"Failed to start download from any mirrors. Failed mirrors: {:?}",
|
|
||||||
failed_mirrors
|
|
||||||
).into_bytes(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Method::PUT => {
|
|
||||||
// update a downloaded app
|
|
||||||
let listing: &PackageListing = state
|
|
||||||
.packages
|
|
||||||
.get(&package_id)
|
|
||||||
.ok_or(anyhow::anyhow!("No package listing"))?;
|
|
||||||
let Some(ref pkg_state) = listing.state else {
|
|
||||||
return Err(anyhow::anyhow!("No package state"));
|
|
||||||
};
|
};
|
||||||
let download_from = pkg_state
|
|
||||||
.mirrored_from
|
match crate::handle_install(state, &package_id) {
|
||||||
.as_ref()
|
Ok(_) => Ok((StatusCode::CREATED, None, vec![])),
|
||||||
.ok_or(anyhow::anyhow!("No mirror for package {package_id}"))?
|
Err(e) => Ok((
|
||||||
.to_string();
|
|
||||||
match crate::start_download(
|
|
||||||
state,
|
|
||||||
package_id,
|
|
||||||
download_from,
|
|
||||||
pkg_state.mirroring,
|
|
||||||
pkg_state.auto_update,
|
|
||||||
None,
|
|
||||||
) {
|
|
||||||
DownloadResponse::Started => Ok((
|
|
||||||
StatusCode::CREATED,
|
|
||||||
None,
|
|
||||||
format!("Downloading").into_bytes(),
|
|
||||||
)),
|
|
||||||
_ => Ok((
|
|
||||||
StatusCode::SERVICE_UNAVAILABLE,
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
None,
|
None,
|
||||||
format!("Failed to download").into_bytes(),
|
e.to_string().into_bytes(),
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Method::DELETE => {
|
|
||||||
// uninstall an app
|
|
||||||
state.uninstall(&package_id)?;
|
|
||||||
Ok((
|
|
||||||
StatusCode::NO_CONTENT,
|
|
||||||
None,
|
|
||||||
format!("Uninstalled").into_bytes(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
_ => Ok((
|
|
||||||
StatusCode::METHOD_NOT_ALLOWED,
|
|
||||||
None,
|
|
||||||
format!("Invalid method {method} for {bound_path}").into_bytes(),
|
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
//! App Store:
|
//! App Store:
|
||||||
//! acts as both a local package manager and a protocol to share packages across the network.
|
//! acts as both a local package manager and a protocol to share packages across the network.
|
||||||
//! packages are apps; apps are packages. we use an onchain app listing contract to determine
|
//! packages are apps; apps are packages. we use the kimap contract to determine
|
||||||
//! what apps are available to download and what node(s) to download them from.
|
//! what apps are available to download and what node(s) to download them from.
|
||||||
//!
|
//!
|
||||||
//! once we know that list, we can request a package from a node and download it locally.
|
//! once we know that list, we can request a package from a node and download it locally.
|
||||||
@ -22,8 +22,9 @@ use ft_worker_lib::{
|
|||||||
spawn_receive_transfer, spawn_transfer, FTWorkerCommand, FTWorkerResult, FileTransferContext,
|
spawn_receive_transfer, spawn_transfer, FTWorkerCommand, FTWorkerResult, FileTransferContext,
|
||||||
};
|
};
|
||||||
use kinode_process_lib::{
|
use kinode_process_lib::{
|
||||||
await_message, call_init, eth, get_blob, http, kimap, println, vfs, Address, LazyLoadBlob,
|
await_message, call_init, eth, get_blob,
|
||||||
Message, PackageId, Request, Response,
|
http::{self, WsMessageType},
|
||||||
|
println, vfs, Address, LazyLoadBlob, Message, PackageId, Request, Response,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use state::{AppStoreLogError, PackageState, RequestedPackage, State};
|
use state::{AppStoreLogError, PackageState, RequestedPackage, State};
|
||||||
@ -53,7 +54,7 @@ pub const APP_SHARE_TIMEOUT: u64 = 120; // 120s
|
|||||||
#[cfg(not(feature = "simulation-mode"))]
|
#[cfg(not(feature = "simulation-mode"))]
|
||||||
const KIMAP_ADDRESS: &str = kimap::KIMAP_ADDRESS;
|
const KIMAP_ADDRESS: &str = kimap::KIMAP_ADDRESS;
|
||||||
#[cfg(feature = "simulation-mode")]
|
#[cfg(feature = "simulation-mode")]
|
||||||
const KIMAP_ADDRESS: &str = "0x0165878A594ca255338adfa4d48449f69242Eb8F"; // note temp kimap address!
|
const KIMAP_ADDRESS: &str = "0x0165878A594ca255338adfa4d48449f69242Eb8F";
|
||||||
|
|
||||||
#[cfg(not(feature = "simulation-mode"))]
|
#[cfg(not(feature = "simulation-mode"))]
|
||||||
const KIMAP_FIRST_BLOCK: u64 = kimap::KIMAP_FIRST_BLOCK;
|
const KIMAP_FIRST_BLOCK: u64 = kimap::KIMAP_FIRST_BLOCK;
|
||||||
@ -135,11 +136,33 @@ fn handle_message(state: &mut State, message: &Message) -> anyhow::Result<()> {
|
|||||||
let resp = handle_remote_request(state, message.source(), remote_request);
|
let resp = handle_remote_request(state, message.source(), remote_request);
|
||||||
Response::new().body(serde_json::to_vec(&resp)?).send()?;
|
Response::new().body(serde_json::to_vec(&resp)?).send()?;
|
||||||
}
|
}
|
||||||
|
Req::FTWorkerCommand(_) => {
|
||||||
|
spawn_receive_transfer(&state.our, message.body())?;
|
||||||
|
}
|
||||||
Req::FTWorkerResult(FTWorkerResult::ReceiveSuccess(name)) => {
|
Req::FTWorkerResult(FTWorkerResult::ReceiveSuccess(name)) => {
|
||||||
handle_receive_download(state, &name)?;
|
handle_receive_download(state, &name)?;
|
||||||
}
|
}
|
||||||
Req::FTWorkerCommand(_) => {
|
Req::FTWorkerResult(FTWorkerResult::ProgressUpdate {
|
||||||
spawn_receive_transfer(&state.our, message.body())?;
|
file_name,
|
||||||
|
chunks_received,
|
||||||
|
total_chunks,
|
||||||
|
}) => {
|
||||||
|
// forward progress to UI
|
||||||
|
let ws_blob = LazyLoadBlob {
|
||||||
|
mime: Some("application/json".to_string()),
|
||||||
|
bytes: serde_json::json!({
|
||||||
|
"kind": "progress",
|
||||||
|
"data": {
|
||||||
|
"file_name": file_name,
|
||||||
|
"chunks_received": chunks_received,
|
||||||
|
"total_chunks": total_chunks,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.to_string()
|
||||||
|
.as_bytes()
|
||||||
|
.to_vec(),
|
||||||
|
};
|
||||||
|
http::send_ws_push(6969, WsMessageType::Text, ws_blob);
|
||||||
}
|
}
|
||||||
Req::FTWorkerResult(r) => {
|
Req::FTWorkerResult(r) => {
|
||||||
println!("got weird ft_worker result: {r:?}");
|
println!("got weird ft_worker result: {r:?}");
|
||||||
@ -566,8 +589,12 @@ fn handle_ft_worker_result(ft_worker_result: FTWorkerResult, context: &[u8]) ->
|
|||||||
.as_secs_f64(),
|
.as_secs_f64(),
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else if let FTWorkerResult::Err(e) = ft_worker_result {
|
||||||
|
Err(anyhow::anyhow!("failed to share app: {e:?}"))
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow::anyhow!("failed to share app"))
|
Err(anyhow::anyhow!(
|
||||||
|
"failed to share app: unknown FTWorkerResult {ft_worker_result:?}"
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +353,10 @@ impl State {
|
|||||||
|
|
||||||
pub fn uninstall(&mut self, package_id: &PackageId) -> anyhow::Result<()> {
|
pub fn uninstall(&mut self, package_id: &PackageId) -> anyhow::Result<()> {
|
||||||
utils::uninstall(package_id)?;
|
utils::uninstall(package_id)?;
|
||||||
self.packages.remove(package_id);
|
let Some(listing) = self.packages.get_mut(package_id) else {
|
||||||
|
return Err(anyhow::anyhow!("package not found"));
|
||||||
|
};
|
||||||
|
listing.state = None;
|
||||||
// kinode_process_lib::set_state(&serde_json::to_vec(self)?);
|
// kinode_process_lib::set_state(&serde_json::to_vec(self)?);
|
||||||
println!("uninstalled {package_id}");
|
println!("uninstalled {package_id}");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -34,6 +34,11 @@ pub enum FTWorkerResult {
|
|||||||
SendSuccess,
|
SendSuccess,
|
||||||
/// string is name of file. bytes in blob
|
/// string is name of file. bytes in blob
|
||||||
ReceiveSuccess(String),
|
ReceiveSuccess(String),
|
||||||
|
ProgressUpdate {
|
||||||
|
file_name: String,
|
||||||
|
chunks_received: u64,
|
||||||
|
total_chunks: u64,
|
||||||
|
},
|
||||||
Err(TransferError),
|
Err(TransferError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +155,18 @@ fn handle_receive(
|
|||||||
};
|
};
|
||||||
chunks_received += 1;
|
chunks_received += 1;
|
||||||
file_bytes.extend(blob.bytes);
|
file_bytes.extend(blob.bytes);
|
||||||
|
// send progress update to parent
|
||||||
|
Request::to(parent_process.clone())
|
||||||
|
.body(
|
||||||
|
serde_json::to_vec(&FTWorkerResult::ProgressUpdate {
|
||||||
|
file_name: file_name.to_string(),
|
||||||
|
chunks_received,
|
||||||
|
total_chunks,
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.send()
|
||||||
|
.unwrap();
|
||||||
if chunks_received == total_chunks {
|
if chunks_received == total_chunks {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,15 @@ import { persist } from 'zustand/middleware'
|
|||||||
import { AppInfo, MirrorCheckFile, PackageManifest } from '../types/Apps'
|
import { AppInfo, MirrorCheckFile, PackageManifest } from '../types/Apps'
|
||||||
import { HTTP_STATUS } from '../constants/http'
|
import { HTTP_STATUS } from '../constants/http'
|
||||||
import { appId } from '../utils/app'
|
import { appId } from '../utils/app'
|
||||||
|
import KinodeClientApi from "@kinode/client-api";
|
||||||
|
import { WEBSOCKET_URL } from '../utils/ws'
|
||||||
|
|
||||||
const BASE_URL = '/main:app_store:sys'
|
const BASE_URL = '/main:app_store:sys'
|
||||||
|
|
||||||
interface AppsStore {
|
interface AppsStore {
|
||||||
apps: AppInfo[]
|
apps: AppInfo[]
|
||||||
|
ws: KinodeClientApi
|
||||||
|
downloads: Map<string, [number, number]>
|
||||||
getApps: () => Promise<void>
|
getApps: () => Promise<void>
|
||||||
getApp: (id: string) => Promise<AppInfo>
|
getApp: (id: string) => Promise<AppInfo>
|
||||||
checkMirror: (node: string) => Promise<MirrorCheckFile>
|
checkMirror: (node: string) => Promise<MirrorCheckFile>
|
||||||
@ -27,6 +31,29 @@ const useAppsStore = create<AppsStore>()(
|
|||||||
(set, get) => ({
|
(set, get) => ({
|
||||||
apps: [],
|
apps: [],
|
||||||
|
|
||||||
|
downloads: new Map(),
|
||||||
|
|
||||||
|
ws: new KinodeClientApi({
|
||||||
|
uri: WEBSOCKET_URL,
|
||||||
|
nodeId: window.our?.node,
|
||||||
|
processId: "main:app_store:sys",
|
||||||
|
onMessage: (message) => {
|
||||||
|
const data = JSON.parse(message);
|
||||||
|
console.log('we got a json message', data)
|
||||||
|
if (data.kind === 'progress') {
|
||||||
|
const appId = data.data.name.split('/').pop().split('.').shift();
|
||||||
|
set((state) => {
|
||||||
|
const newDownloads = new Map(state.downloads);
|
||||||
|
newDownloads.set(appId, [data.data.chunks_received, data.data.total_chunks]);
|
||||||
|
return { downloads: newDownloads };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onOpen: (_e) => {
|
||||||
|
console.log('open')
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
getApps: async () => {
|
getApps: async () => {
|
||||||
const res = await fetch(`${BASE_URL}/apps`)
|
const res = await fetch(`${BASE_URL}/apps`)
|
||||||
if (res.status === HTTP_STATUS.OK) {
|
if (res.status === HTTP_STATUS.OK) {
|
||||||
|
11
kinode/packages/app_store/ui/src/utils/ws.ts
Normal file
11
kinode/packages/app_store/ui/src/utils/ws.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// TODO: remove as much as possible of this..
|
||||||
|
const BASE_URL = "/main:app_store:sys/";
|
||||||
|
|
||||||
|
if (window.our) window.our.process = BASE_URL?.replace("/", "");
|
||||||
|
|
||||||
|
export const PROXY_TARGET = `${(import.meta.env.VITE_NODE_URL || `http://localhost:8080`)}${BASE_URL}`;
|
||||||
|
|
||||||
|
// This env also has BASE_URL which should match the process + package name
|
||||||
|
export const WEBSOCKET_URL = import.meta.env.DEV
|
||||||
|
? `${PROXY_TARGET.replace('http', 'ws')}`
|
||||||
|
: undefined;
|
Loading…
Reference in New Issue
Block a user