sideload wip, websockets, styling, multiple todos (#2865)

* sideload wip, websockets, styling, multiple todos

* sideload

* misc backend updates

* chore: comments

* prep for license and instructions display

* comment for Matt

* s9pk updates and 040 sdk

* fix dependency error for actions

* 0.4.0-beta.1

* beta.2

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>
Co-authored-by: waterplea <alexander@inkin.ru>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
Matt Hill
2025-04-10 13:51:05 -06:00
committed by GitHub
parent ab4336cfd7
commit fc2be42418
88 changed files with 773 additions and 965 deletions

View File

@@ -197,9 +197,6 @@ pub struct LoginParams {
user_agent: Option<String>,
#[serde(default)]
ephemeral: bool,
#[serde(default)]
#[ts(type = "any")]
metadata: Value,
}
#[instrument(skip_all)]
@@ -209,7 +206,6 @@ pub async fn login_impl(
password,
user_agent,
ephemeral,
metadata,
}: LoginParams,
) -> Result<LoginRes, Error> {
let password = password.unwrap_or_default().decrypt(&ctx)?;
@@ -224,7 +220,6 @@ pub async fn login_impl(
logged_in: Utc::now(),
last_active: Utc::now(),
user_agent,
metadata,
},
)
});
@@ -240,7 +235,6 @@ pub async fn login_impl(
logged_in: Utc::now(),
last_active: Utc::now(),
user_agent,
metadata,
},
)?;
@@ -277,10 +271,7 @@ pub struct Session {
pub logged_in: DateTime<Utc>,
#[ts(type = "string")]
pub last_active: DateTime<Utc>,
#[ts(skip)]
pub user_agent: Option<String>,
#[ts(type = "any")]
pub metadata: Value,
}
#[derive(Deserialize, Serialize, TS)]
@@ -327,7 +318,6 @@ fn display_sessions(params: WithIoFormat<ListParams>, arg: SessionList) {
"LOGGED IN",
"LAST ACTIVE",
"USER AGENT",
"METADATA",
]);
for (id, session) in arg.sessions.0 {
let mut row = row![
@@ -335,7 +325,6 @@ fn display_sessions(params: WithIoFormat<ListParams>, arg: SessionList) {
&format!("{}", session.logged_in),
&format!("{}", session.last_active),
session.user_agent.as_deref().unwrap_or("N/A"),
&format!("{}", session.metadata),
];
if Some(id) == arg.current {
row.iter_mut()

View File

@@ -186,6 +186,7 @@ pub async fn remove_before(
Ok(())
})
.await
.result
}
pub async fn mark_seen(
@@ -213,6 +214,7 @@ pub async fn mark_seen(
Ok(())
})
.await
.result
}
pub async fn mark_seen_before(
@@ -240,6 +242,7 @@ pub async fn mark_seen_before(
Ok(())
})
.await
.result
}
pub async fn mark_unseen(

View File

@@ -72,7 +72,7 @@ pub struct PackageVersionInfo {
pub icon: DataUrl<'static>,
pub description: Description,
pub release_notes: String,
pub git_hash: GitHash,
pub git_hash: Option<GitHash>,
#[ts(type = "string")]
pub license: InternedString,
#[ts(type = "string")]
@@ -115,7 +115,7 @@ impl PackageVersionInfo {
icon: s9pk.icon_data_url().await?,
description: manifest.description.clone(),
release_notes: manifest.release_notes.clone(),
git_hash: manifest.git_hash.clone().or_not_found("git hash")?,
git_hash: manifest.git_hash.clone(),
license: manifest.license.clone(),
wrapper_repo: manifest.wrapper_repo.clone(),
upstream_repo: manifest.upstream_repo.clone(),
@@ -153,7 +153,7 @@ impl PackageVersionInfo {
br -> "DESCRIPTION",
&textwrap::wrap(&self.description.long, 80).join("\n")
]);
table.add_row(row![br -> "GIT HASH", AsRef::<str>::as_ref(&self.git_hash)]);
table.add_row(row![br -> "GIT HASH", self.git_hash.as_deref().unwrap_or("N/A")]);
table.add_row(row![br -> "LICENSE", &self.license]);
table.add_row(row![br -> "PACKAGE REPO", &self.wrapper_repo.to_string()]);
table.add_row(row![br -> "SERVICE REPO", &self.upstream_repo.to_string()]);

View File

@@ -1,3 +1,4 @@
use std::ops::Deref;
use std::path::Path;
use tokio::process::Command;
@@ -66,6 +67,13 @@ impl AsRef<str> for GitHash {
}
}
impl Deref for GitHash {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
// #[tokio::test]
// async fn test_githash_for_current() {
// let answer: GitHash = GitHash::from_path(std::env::current_dir().unwrap())

View File

@@ -26,7 +26,6 @@ use crate::s9pk::merkle_archive::source::{
into_dyn_read, ArchiveSource, DynFileSource, DynRead, FileSource, TmpSource,
};
use crate::s9pk::merkle_archive::{Entry, MerkleArchive};
use crate::s9pk::v2::recipe::DirRecipe;
use crate::s9pk::v2::SIG_CONTEXT;
use crate::s9pk::S9pk;
use crate::util::io::{create_file, open_file, TmpDir};
@@ -736,25 +735,34 @@ pub async fn pack(ctx: CliContext, params: PackParams) -> Result<(), Error> {
let dep_path = Path::new("dependencies").join(id);
to_insert.push((
dep_path.join("metadata.json"),
Entry::file(PackSource::Buffered(
IoFormat::Json
.to_vec(&DependencyMetadata {
title: s9pk.as_manifest().title.clone(),
})?
.into(),
Entry::file(TmpSource::new(
tmp_dir.clone(),
PackSource::Buffered(
IoFormat::Json
.to_vec(&DependencyMetadata {
title: s9pk.as_manifest().title.clone(),
})?
.into(),
),
)),
));
let icon = s9pk.icon().await?;
to_insert.push((
dep_path.join(&*icon.0),
Entry::file(PackSource::Buffered(
icon.1.expect_file()?.to_vec(icon.1.hash()).await?.into(),
Entry::file(TmpSource::new(
tmp_dir.clone(),
PackSource::Buffered(icon.1.expect_file()?.to_vec(icon.1.hash()).await?.into()),
)),
));
} else {
warn!("no s9pk specified for {id}, leaving metadata empty");
}
}
for (path, source) in to_insert {
s9pk.as_archive_mut()
.contents_mut()
.insert_path(path, source)?;
}
s9pk.validate_and_filter(None)?;

View File

@@ -5,7 +5,10 @@ use imbl_value::json;
use models::{ActionId, PackageId, ProcedureName, ReplayId};
use crate::action::{ActionInput, ActionResult};
use crate::db::model::package::{ActionRequestCondition, ActionRequestEntry, ActionRequestInput};
use crate::db::model::package::{
ActionRequestCondition, ActionRequestEntry, ActionRequestInput, ActionVisibility,
AllowedStatuses,
};
use crate::prelude::*;
use crate::rpc_continuations::Guid;
use crate::service::{Service, ServiceActor};
@@ -123,12 +126,44 @@ impl Handler<RunAction> for ServiceActor {
&mut self,
id: Guid,
RunAction {
id: action_id,
id: ref action_id,
input,
}: RunAction,
_: &BackgroundJobQueue,
) -> Self::Response {
let container = &self.0.persistent_container;
let package_id = &self.0.id;
let action = self
.0
.ctx
.db
.peek()
.await
.into_public()
.into_package_data()
.into_idx(package_id)
.or_not_found(package_id)?
.into_actions()
.into_idx(&action_id)
.or_not_found(lazy_format!("{package_id} action {action_id}"))?
.de()?;
if !matches!(&action.visibility, ActionVisibility::Enabled) {
return Err(Error::new(
eyre!("action {action_id} is disabled"),
ErrorKind::Action,
));
}
let running = container.state.borrow().running_status.as_ref().is_some();
if match action.allowed_statuses {
AllowedStatuses::OnlyRunning => !running,
AllowedStatuses::OnlyStopped => running,
_ => false,
} {
return Err(Error::new(
eyre!("service is not in allowed status for {action_id}"),
ErrorKind::Action,
));
}
let result = container
.execute::<Option<ActionResult>>(
id,
@@ -140,7 +175,6 @@ impl Handler<RunAction> for ServiceActor {
)
.await
.with_kind(ErrorKind::Action)?;
let package_id = &self.0.id;
self.0
.ctx
.db
@@ -150,7 +184,7 @@ impl Handler<RunAction> for ServiceActor {
Ok(update_requested_actions(
requested_actions,
package_id,
&action_id,
action_id,
&input,
true,
))