export patchdb ts types from rust

This commit is contained in:
Aiden McClelland
2024-03-27 17:47:12 -06:00
parent 9cf62f03fa
commit f41f5ebebd
75 changed files with 536 additions and 634 deletions

View File

@@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet};
use chrono::{DateTime, Utc};
use emver::VersionRange;
use imbl_value::InternedString;
use models::{ActionId, DataUrl, HealthCheckId, HostId, PackageId};
use models::{ActionId, DataUrl, HealthCheckId, HostId, PackageId, ServiceInterfaceId};
use patch_db::json_ptr::JsonPointer;
use patch_db::HasModel;
use reqwest::Url;
@@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::net::host::HostInfo;
use crate::net::service_interface::ServiceInterfaceWithHostInfo;
use crate::prelude::*;
use crate::progress::FullProgress;
use crate::s9pk::manifest::Manifest;
@@ -306,14 +307,14 @@ pub enum AllowedStatuses {
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
pub struct ActionMetadata {
name: String,
description: String,
warning: Option<String>,
pub name: String,
pub description: String,
pub warning: Option<String>,
#[ts(type = "any")]
input: Value,
disabled: bool,
allowedStatuses: AllowedStatuses,
group: Option<String>,
pub input: Value,
pub disabled: bool,
pub allowed_statuses: AllowedStatuses,
pub group: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
@@ -331,10 +332,11 @@ pub struct PackageDataEntry {
#[ts(type = "string | null")]
pub last_backup: Option<DateTime<Utc>>,
pub current_dependencies: CurrentDependencies,
pub actions: BTreeMap<ActionId, ActionMetadata>,
pub service_interfaces: BTreeMap<ServiceInterfaceId, ServiceInterfaceWithHostInfo>,
pub hosts: HostInfo,
#[ts(type = "string[]")]
pub store_exposed_dependents: Vec<JsonPointer>,
pub exposed_actions: BTreeMap<ActionId, ActionMetadata>,
}
impl AsRef<PackageDataEntry> for PackageDataEntry {
fn as_ref(&self) -> &PackageDataEntry {
@@ -375,7 +377,7 @@ pub struct CurrentDependencyInfo {
pub title: String,
pub icon: DataUrl<'static>,
#[ts(type = "string")]
pub registry: Url,
pub registry_url: Url,
#[ts(type = "string")]
pub version_spec: VersionRange,
}

View File

@@ -66,10 +66,6 @@ impl Public {
selected: None,
},
unread_notification_count: 0,
connection_addresses: ConnectionAddresses {
tor: Vec::new(),
clearnet: Vec::new(),
},
password_hash: account.password.clone(),
pubkey: ssh_key::PublicKey::from(&account.ssh_key)
.to_openssh()
@@ -136,8 +132,8 @@ pub struct ServerInfo {
#[serde(default)]
pub status_info: ServerStatus,
pub wifi: WifiInfo,
#[ts(type = "number")]
pub unread_notification_count: u64,
pub connection_addresses: ConnectionAddresses,
pub password_hash: String,
pub pubkey: String,
pub ca_fingerprint: String,
@@ -199,7 +195,9 @@ pub struct ServerStatus {
#[model = "Model<Self>"]
#[ts(export)]
pub struct UpdateProgress {
#[ts(type = "number | null")]
pub size: Option<u64>,
#[ts(type = "number")]
pub downloaded: u64,
}
@@ -221,11 +219,3 @@ pub struct ServerSpecs {
pub disk: String,
pub memory: String,
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ConnectionAddresses {
pub tor: Vec<String>,
pub clearnet: Vec<String>,
}

View File

@@ -16,7 +16,7 @@ pub struct BindInfo {
impl BindInfo {
pub fn new(available_ports: &mut AvailablePorts, options: BindOptions) -> Result<Self, Error> {
let mut assigned_lan_port = None;
if options.add_ssl.is_some() || options.secure {
if options.add_ssl.is_some() || options.secure.is_some() {
assigned_lan_port = Some(available_ports.alloc()?);
}
Ok(Self {
@@ -33,7 +33,7 @@ impl BindInfo {
mut assigned_lan_port,
..
} = self;
if options.add_ssl.is_some() || options.secure {
if options.add_ssl.is_some() || options.secure.is_some() {
assigned_lan_port = if let Some(port) = assigned_lan_port.take() {
Some(port)
} else {
@@ -51,24 +51,30 @@ impl BindInfo {
}
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct Security {
pub ssl: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindOptions {
#[ts(type = "string")]
pub scheme: InternedString,
#[ts(type = "string | null")]
pub scheme: Option<InternedString>,
pub preferred_external_port: u16,
pub add_ssl: Option<AddSslOptions>,
pub secure: bool,
pub ssl: bool,
pub secure: Option<Security>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddSslOptions {
#[ts(type = "string")]
pub scheme: InternedString,
#[ts(type = "string | null")]
pub scheme: Option<InternedString>,
pub preferred_external_port: u16,
// #[serde(default)]
// pub add_x_forwarded_headers: bool, // TODO

View File

@@ -39,7 +39,7 @@ impl Host {
}
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum HostKind {

View File

@@ -7,6 +7,7 @@ pub mod host;
pub mod keys;
pub mod mdns;
pub mod net_controller;
pub mod service_interface;
pub mod ssl;
pub mod static_server;
pub mod tor;

View File

@@ -247,7 +247,7 @@ impl NetService {
None,
external,
(self.ip, *port).into(),
if bind.options.ssl {
if bind.options.secure.as_ref().map_or(false, |s| s.ssl) {
Ok(())
} else {
Err(ssl.alpn.clone())

View File

@@ -0,0 +1,115 @@
use std::net::{Ipv4Addr, Ipv6Addr};
use models::{HostId, ServiceInterfaceId};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::net::host::binding::BindOptions;
use crate::net::host::HostKind;
use crate::prelude::*;
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ServiceInterfaceWithHostInfo {
#[serde(flatten)]
pub service_interface: ServiceInterface,
pub host_info: ExportedHostInfo,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExportedHostInfo {
pub id: HostId,
pub kind: HostKind,
pub hostnames: Vec<ExportedHostnameInfo>,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")]
pub enum ExportedHostnameInfo {
Ip {
network_interface_id: String,
public: bool,
hostname: ExportedIpHostname,
},
Onion {
hostname: ExportedOnionHostname,
},
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExportedOnionHostname {
pub value: String,
pub port: Option<u16>,
pub ssl_port: Option<u16>,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")]
pub enum ExportedIpHostname {
Ipv4 {
value: Ipv4Addr,
port: Option<u16>,
ssl_port: Option<u16>,
},
Ipv6 {
value: Ipv6Addr,
port: Option<u16>,
ssl_port: Option<u16>,
},
Local {
value: String,
port: Option<u16>,
ssl_port: Option<u16>,
},
Domain {
domain: String,
subdomain: Option<String>,
port: Option<u16>,
ssl_port: Option<u16>,
},
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ServiceInterface {
pub id: ServiceInterfaceId,
pub name: String,
pub description: String,
pub has_primary: bool,
pub disabled: bool,
pub masked: bool,
pub address_info: AddressInfo,
#[serde(rename = "type")]
pub interface_type: ServiceInterfaceType,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub enum ServiceInterfaceType {
Ui,
P2p,
Api,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct AddressInfo {
pub username: Option<String>,
pub host_id: HostId,
pub bind_options: BindOptions,
pub suffix: String,
}

View File

@@ -24,7 +24,12 @@ lazy_static::lazy_static! {
#[serde(untagged)]
pub enum Progress {
Complete(bool),
Progress { done: u64, total: Option<u64> },
Progress {
#[ts(type = "number")]
done: u64,
#[ts(type = "number | null")]
total: Option<u64>,
},
}
impl Progress {
pub fn new() -> Self {

View File

@@ -11,7 +11,7 @@ use clap::Parser;
use emver::VersionRange;
use imbl::OrdMap;
use imbl_value::{json, InternedString};
use models::{ActionId, HealthCheckId, ImageId, PackageId, VolumeId};
use models::{ActionId, HealthCheckId, HostId, ImageId, PackageId, VolumeId};
use patch_db::json_ptr::JsonPointer;
use rpc_toolkit::{from_fn, from_fn_async, AnyContext, Context, Empty, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize};
@@ -25,11 +25,13 @@ use crate::db::model::package::{
use crate::disk::mount::filesystem::idmapped::IdMapped;
use crate::disk::mount::filesystem::loop_dev::LoopDev;
use crate::disk::mount::filesystem::overlayfs::OverlayGuard;
use crate::net::host::binding::BindOptions;
use crate::net::host::HostKind;
use crate::prelude::*;
use crate::s9pk::rpc::SKIP_ENV;
use crate::service::cli::ContainerCliContext;
use crate::service::ServiceActorSeed;
use crate::status::health_check::{HealthCheckResult, HealthCheckString};
use crate::status::health_check::HealthCheckResult;
use crate::status::MainStatus;
use crate::util::clap::FromStrParser;
use crate::util::{new_guid, Invoke};
@@ -185,21 +187,7 @@ struct GetServicePortForwardParams {
package_id: Option<PackageId>,
internal_port: u32,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
struct BindOptionsSecure {
ssl: bool,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
struct BindOptions {
scheme: Option<String>,
preferred_external_port: u32,
add_ssl: Option<AddSslOptions>,
secure: Option<BindOptionsSecure>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
@@ -379,7 +367,7 @@ async fn export_action(context: EffectContext, data: ExportActionParams) -> Resu
.as_package_data_mut()
.as_idx_mut(&package_id)
.or_not_found(&package_id)?
.as_exposed_actions_mut();
.as_actions_mut();
let mut value = model.de()?;
value
.insert(data.id, data.metadata)
@@ -402,7 +390,7 @@ async fn remove_action(context: EffectContext, data: RemoveActionParams) -> Resu
.as_package_data_mut()
.as_idx_mut(&package_id)
.or_not_found(&package_id)?
.as_exposed_actions_mut();
.as_actions_mut();
let mut value = model.de()?;
value.remove(&data.id).map(|_| ()).unwrap_or_default();
model.ser(&value)
@@ -447,35 +435,16 @@ async fn get_host_info(
async fn clear_bindings(context: EffectContext, _: Empty) -> Result<Value, Error> {
todo!()
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
enum BindKind {
Static,
Single,
Multi,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
struct AddSslOptions {
scheme: Option<String>,
preferred_external_port: u32,
add_x_forwarded_headers: Option<bool>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
struct BindParams {
kind: BindKind,
id: String,
internal_port: u32,
scheme: String,
preferred_external_port: u32,
add_ssl: Option<AddSslOptions>,
secure: Option<BindOptionsSecure>,
kind: HostKind,
id: HostId,
internal_port: u16,
#[serde(flatten)]
options: BindOptions,
}
async fn bind(_: AnyContext, BindParams { .. }: BindParams) -> Result<Value, Error> {
todo!()
@@ -918,19 +887,14 @@ async fn set_main_status(context: EffectContext, params: SetMainStatus) -> Resul
#[serde(rename_all = "camelCase")]
#[ts(export)]
struct SetHealth {
#[ts(type = "string")]
name: HealthCheckId,
status: HealthCheckString,
message: Option<String>,
id: HealthCheckId,
#[serde(flatten)]
result: HealthCheckResult,
}
async fn set_health(
context: EffectContext,
SetHealth {
name,
status,
message,
}: SetHealth,
SetHealth { id, result }: SetHealth,
) -> Result<Value, Error> {
let context = context.deref()?;
@@ -939,43 +903,22 @@ async fn set_health(
.ctx
.db
.mutate(move |db| {
let mut main = db
.as_public()
.as_package_data()
.as_idx(package_id)
.or_not_found(package_id)?
.as_status()
.as_main()
.de()?;
match &mut main {
&mut MainStatus::Running { ref mut health, .. }
| &mut MainStatus::BackingUp { ref mut health, .. } => {
health.remove(&name);
health.insert(
name,
match status {
HealthCheckString::Disabled => HealthCheckResult::Disabled,
HealthCheckString::Passing => HealthCheckResult::Success,
HealthCheckString::Starting => HealthCheckResult::Starting,
HealthCheckString::Warning => HealthCheckResult::Loading {
message: message.unwrap_or_default(),
},
HealthCheckString::Failure => HealthCheckResult::Failure {
error: message.unwrap_or_default(),
},
},
);
}
_ => return Ok(()),
};
db.as_public_mut()
.as_package_data_mut()
.as_idx_mut(package_id)
.or_not_found(package_id)?
.as_status_mut()
.as_main_mut()
.ser(&main)
.mutate(|main| {
match main {
&mut MainStatus::Running { ref mut health, .. }
| &mut MainStatus::BackingUp { ref mut health, .. } => {
health.insert(id, result);
}
_ => (),
}
Ok(())
})
})
.await?;
Ok(json!(()))
@@ -1100,7 +1043,7 @@ enum DependencyRequirement {
#[ts(type = "string")]
version_spec: VersionRange,
#[ts(type = "string")]
registry: Url,
registry_url: Url,
},
#[serde(rename_all = "camelCase")]
Exists {
@@ -1109,7 +1052,7 @@ enum DependencyRequirement {
#[ts(type = "string")]
version_spec: VersionRange,
#[ts(type = "string")]
registry: Url,
registry_url: Url,
},
}
// filebrowser:exists,bitcoind:running:foo+bar+baz
@@ -1119,7 +1062,7 @@ impl FromStr for DependencyRequirement {
match s.split_once(':') {
Some((id, "e")) | Some((id, "exists")) => Ok(Self::Exists {
id: id.parse()?,
registry: "".parse()?, // TODO
registry_url: "".parse()?, // TODO
version_spec: "*".parse()?, // TODO
}),
Some((id, rest)) => {
@@ -1143,14 +1086,14 @@ impl FromStr for DependencyRequirement {
Ok(Self::Running {
id: id.parse()?,
health_checks,
registry: "".parse()?, // TODO
registry_url: "".parse()?, // TODO
version_spec: "*".parse()?, // TODO
})
}
None => Ok(Self::Running {
id: s.parse()?,
health_checks: BTreeSet::new(),
registry: "".parse()?, // TODO
registry_url: "".parse()?, // TODO
version_spec: "*".parse()?, // TODO
}),
}
@@ -1186,13 +1129,13 @@ async fn set_dependencies(
.map(|dependency| match dependency {
DependencyRequirement::Exists {
id,
registry,
registry_url,
version_spec,
} => (
id,
CurrentDependencyInfo {
kind: CurrentDependencyKind::Exists,
registry,
registry_url,
version_spec,
icon: todo!(),
title: todo!(),
@@ -1201,13 +1144,13 @@ async fn set_dependencies(
DependencyRequirement::Running {
id,
health_checks,
registry,
registry_url,
version_spec,
} => (
id,
CurrentDependencyInfo {
kind: CurrentDependencyKind::Running { health_checks },
registry,
registry_url,
version_spec,
icon: todo!(),
title: todo!(),

View File

@@ -172,6 +172,8 @@ impl ServiceMap {
icon,
last_backup: None,
current_dependencies: Default::default(),
actions: Default::default(),
service_interfaces: Default::default(),
hosts: Default::default(),
store_exposed_dependents: Default::default(),
},

View File

@@ -2,35 +2,35 @@ pub use models::HealthCheckId;
use serde::{Deserialize, Serialize};
use ts_rs::TS;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")]
pub struct HealthCheckResult {
pub name: String,
#[serde(flatten)]
pub kind: HealthCheckResultKind,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "result")]
pub enum HealthCheckResult {
Success,
pub enum HealthCheckResultKind {
Success { message: String },
Disabled,
Starting,
Loading { message: String },
Failure { error: String },
Failure { message: String },
}
impl std::fmt::Display for HealthCheckResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HealthCheckResult::Success => write!(f, "Succeeded"),
HealthCheckResult::Disabled => write!(f, "Disabled"),
HealthCheckResult::Starting => write!(f, "Starting"),
HealthCheckResult::Loading { message } => write!(f, "Loading ({})", message),
HealthCheckResult::Failure { error } => write!(f, "Failed ({})", error),
let name = &self.name;
match &self.kind {
HealthCheckResultKind::Success { message } => {
write!(f, "{name}: Succeeded ({message})")
}
HealthCheckResultKind::Disabled => write!(f, "{name}: Disabled"),
HealthCheckResultKind::Starting => write!(f, "{name}: Starting"),
HealthCheckResultKind::Loading { message } => write!(f, "{name}: Loading ({message})"),
HealthCheckResultKind::Failure { message } => write!(f, "{name}: Failed ({message})"),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum HealthCheckString {
Passing,
Disabled,
Starting,
Warning,
Failure,
}