mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Feature/fe new registry (#2647)
* bugfixes * update fe types * implement new registry types in marketplace and ui * fix marketplace types to have default params * add alt implementation toggle * merge cleanup * more cleanup and notes * fix build * cleanup sync with next/minor * add exver JS parser * parse ValidExVer to string * update types to interface * add VersionRange and comparative functions * Parse ExtendedVersion from string * add conjunction, disjunction, and inversion logic * consider flavor in satisfiedBy fn * consider prerelease for ordering * add compare fn for sorting * rename fns for consistency * refactoring * update compare fn to return null if flavors don't match * begin simplifying dependencies * under construction * wip * add dependency metadata to CurrentDependencyInfo * ditch inheritance for recursive VersionRange constructor. Recursive 'satisfiedBy' fn wip * preprocess manifest * misc fixes * use sdk version as osVersion in manifest * chore: Change the type to just validate and not generate all solutions. * add publishedAt * fix pegjs exports * integrate exver into sdk * misc fixes * complete satisfiedBy fn * refactor - use greaterThanOrEqual and lessThanOrEqual fns * fix tests * update dependency details * update types * remove interim types * rename alt implementation to flavor * cleanup os update * format exver.ts * add s9pk parsing endpoints * fix build * update to exver * exver and bug fixes * update static endpoints + cleanup * cleanup * update static proxy verification * make mocks more robust; fix dep icon fallback; cleanup * refactor alert versions and update fixtures * registry bugfixes * misc fixes * cleanup unused * convert patchdb ui seed to camelCase * update otherVersions type * change otherVersions: null to 'none' * refactor and complete feature * improve static endpoints * fix install params * mask systemd-networkd-wait-online * fix static file fetching * include non-matching versions in otherVersions * convert release notes to modal and clean up displayExver * alert for no other versions * Fix ack-instructions casing * fix indeterminate loader on service install --------- Co-authored-by: Aiden McClelland <me@drbonez.dev> Co-authored-by: Shadowy Super Coder <musashidisciple@proton.me> Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com> Co-authored-by: J H <dragondef@gmail.com> Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::pin::Pin;
|
||||
use std::process::Stdio;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
use std::time::Duration;
|
||||
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use async_trait::async_trait;
|
||||
use color_eyre::eyre::{self, eyre};
|
||||
use fd_lock_rs::FdLock;
|
||||
@@ -24,9 +27,12 @@ use tokio::fs::File;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
|
||||
use tokio::sync::{oneshot, Mutex, OwnedMutexGuard, RwLock};
|
||||
use tracing::instrument;
|
||||
use ts_rs::TS;
|
||||
use url::Url;
|
||||
|
||||
use crate::shutdown::Shutdown;
|
||||
use crate::util::io::create_file;
|
||||
use crate::util::serde::{deserialize_from_str, serialize_display};
|
||||
use crate::{Error, ErrorKind, ResultExt as _};
|
||||
pub mod actor;
|
||||
pub mod clap;
|
||||
@@ -648,3 +654,48 @@ pub fn new_guid() -> InternedString {
|
||||
&buf,
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, TS)]
|
||||
#[ts(type = "string")]
|
||||
pub enum PathOrUrl {
|
||||
Path(PathBuf),
|
||||
Url(Url),
|
||||
}
|
||||
impl FromStr for PathOrUrl {
|
||||
type Err = <PathBuf as FromStr>::Err;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if let Ok(url) = s.parse::<Url>() {
|
||||
if url.scheme() == "file" {
|
||||
Ok(Self::Path(url.path().parse()?))
|
||||
} else {
|
||||
Ok(Self::Url(url))
|
||||
}
|
||||
} else {
|
||||
Ok(Self::Path(s.parse()?))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Display for PathOrUrl {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Path(p) => write!(f, "file://{}", p.display()),
|
||||
Self::Url(u) => write!(f, "{u}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'de> Deserialize<'de> for PathOrUrl {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: ::serde::Deserializer<'de>,
|
||||
{
|
||||
deserialize_from_str(deserializer)
|
||||
}
|
||||
}
|
||||
impl Serialize for PathOrUrl {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ::serde::Serializer,
|
||||
{
|
||||
serialize_display(self, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
use core::fmt;
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use axum::extract::ws::{self, CloseFrame};
|
||||
use futures::Future;
|
||||
use futures::{Future, Stream, StreamExt};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub trait WebSocketExt {
|
||||
fn normal_close(
|
||||
self,
|
||||
msg: impl Into<Cow<'static, str>>,
|
||||
) -> impl Future<Output = Result<(), Error>>;
|
||||
msg: impl Into<Cow<'static, str>> + Send,
|
||||
) -> impl Future<Output = Result<(), Error>> + Send;
|
||||
fn close_result(
|
||||
self,
|
||||
result: Result<impl Into<Cow<'static, str>> + Send, impl fmt::Display + Send>,
|
||||
) -> impl Future<Output = Result<(), Error>> + Send;
|
||||
}
|
||||
|
||||
impl WebSocketExt for ws::WebSocket {
|
||||
async fn normal_close(mut self, msg: impl Into<Cow<'static, str>>) -> Result<(), Error> {
|
||||
async fn normal_close(mut self, msg: impl Into<Cow<'static, str>> + Send) -> Result<(), Error> {
|
||||
self.send(ws::Message::Close(Some(CloseFrame {
|
||||
code: 1000,
|
||||
reason: msg.into(),
|
||||
@@ -21,4 +27,41 @@ impl WebSocketExt for ws::WebSocket {
|
||||
.await
|
||||
.with_kind(ErrorKind::Network)
|
||||
}
|
||||
async fn close_result(
|
||||
mut self,
|
||||
result: Result<impl Into<Cow<'static, str>> + Send, impl fmt::Display + Send>,
|
||||
) -> Result<(), Error> {
|
||||
match result {
|
||||
Ok(msg) => self
|
||||
.send(ws::Message::Close(Some(CloseFrame {
|
||||
code: 1000,
|
||||
reason: msg.into(),
|
||||
})))
|
||||
.await
|
||||
.with_kind(ErrorKind::Network),
|
||||
Err(e) => self
|
||||
.send(ws::Message::Close(Some(CloseFrame {
|
||||
code: 1011,
|
||||
reason: e.to_string().into(),
|
||||
})))
|
||||
.await
|
||||
.with_kind(ErrorKind::Network),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyncBody(Mutex<axum::body::BodyDataStream>);
|
||||
impl From<axum::body::Body> for SyncBody {
|
||||
fn from(value: axum::body::Body) -> Self {
|
||||
SyncBody(Mutex::new(value.into_data_stream()))
|
||||
}
|
||||
}
|
||||
impl Stream for SyncBody {
|
||||
type Item = <axum::body::BodyDataStream as Stream>::Item;
|
||||
fn poll_next(
|
||||
self: std::pin::Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Option<Self::Item>> {
|
||||
self.0.lock().unwrap().poll_next_unpin(cx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile;
|
||||
use crate::s9pk::merkle_archive::source::ArchiveSource;
|
||||
use crate::util::io::{open_file, ParallelBlake3Writer};
|
||||
use crate::util::serde::Base16;
|
||||
use crate::util::Apply;
|
||||
use crate::util::{Apply, PathOrUrl};
|
||||
use crate::CAP_10_MiB;
|
||||
|
||||
pub fn util<C: Context>() -> ParentHandler<C> {
|
||||
@@ -45,21 +45,20 @@ pub async fn b3sum(
|
||||
}
|
||||
b3sum_source(file).await
|
||||
}
|
||||
if let Ok(url) = file.parse::<Url>() {
|
||||
if url.scheme() == "file" {
|
||||
b3sum_file(url.path(), allow_mmap).await
|
||||
} else if url.scheme() == "http" || url.scheme() == "https" {
|
||||
HttpSource::new(ctx.client.clone(), url)
|
||||
.await?
|
||||
.apply(b3sum_source)
|
||||
.await
|
||||
} else {
|
||||
return Err(Error::new(
|
||||
eyre!("unknown scheme: {}", url.scheme()),
|
||||
ErrorKind::InvalidRequest,
|
||||
));
|
||||
match file.parse::<PathOrUrl>()? {
|
||||
PathOrUrl::Path(path) => b3sum_file(path, allow_mmap).await,
|
||||
PathOrUrl::Url(url) => {
|
||||
if url.scheme() == "http" || url.scheme() == "https" {
|
||||
HttpSource::new(ctx.client.clone(), url)
|
||||
.await?
|
||||
.apply(b3sum_source)
|
||||
.await
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("unknown scheme: {}", url.scheme()),
|
||||
ErrorKind::InvalidRequest,
|
||||
))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
b3sum_file(file, allow_mmap).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use std::any::Any;
|
||||
use std::collections::VecDeque;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
|
||||
use base64::Engine;
|
||||
use clap::builder::ValueParserFactory;
|
||||
use clap::{ArgMatches, CommandFactory, FromArgMatches};
|
||||
use color_eyre::eyre::eyre;
|
||||
@@ -37,7 +39,11 @@ pub fn deserialize_from_str<
|
||||
{
|
||||
type Value = T;
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(formatter, "a parsable string")
|
||||
write!(
|
||||
formatter,
|
||||
"a string that can be parsed as a {}",
|
||||
std::any::type_name::<T>()
|
||||
)
|
||||
}
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
@@ -988,18 +994,24 @@ impl<T: AsRef<[u8]>> Serialize for Base32<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub const BASE64: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new(
|
||||
&base64::alphabet::STANDARD,
|
||||
base64::engine::GeneralPurposeConfig::new(),
|
||||
);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TS)]
|
||||
#[ts(type = "string", concrete(T = Vec<u8>))]
|
||||
pub struct Base64<T>(pub T);
|
||||
impl<T: AsRef<[u8]>> std::fmt::Display for Base64<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&base64::encode(self.0.as_ref()))
|
||||
f.write_str(&BASE64.encode(self.0.as_ref()))
|
||||
}
|
||||
}
|
||||
impl<T: TryFrom<Vec<u8>>> FromStr for Base64<T> {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
base64::decode(&s)
|
||||
BASE64
|
||||
.decode(&s)
|
||||
.with_kind(ErrorKind::Deserialization)?
|
||||
.apply(TryFrom::try_from)
|
||||
.map(Self)
|
||||
|
||||
Reference in New Issue
Block a user