use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use strum::EnumString;
#[cfg(feature = "display")]
use crossterm::style::Stylize;
#[cfg(feature = "display")]
use std::fmt::Write;
use super::deployment::DeploymentState;
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectCreateRequest {
#[cfg_attr(feature = "utoipa", schema(pattern = "^[a-z0-9-]{1,32}$"))]
pub name: String,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectResponse {
pub id: String,
pub name: String,
pub user_id: String,
pub team_id: Option<String>,
pub created_at: DateTime<Utc>,
pub compute_tier: Option<ComputeTier>,
pub deployment_state: Option<DeploymentState>,
pub uris: Vec<String>,
}
impl ProjectResponse {
#[cfg(feature = "display")]
pub fn to_string_colored(&self) -> String {
let mut s = String::new();
writeln!(&mut s, "{}", "Project info:".bold()).unwrap();
writeln!(&mut s, " Project ID: {}", self.id).unwrap();
writeln!(&mut s, " Project Name: {}", self.name).unwrap();
writeln!(&mut s, " Owner: {}", self.user_id).unwrap();
writeln!(
&mut s,
" Team: {}",
self.team_id.as_deref().unwrap_or("N/A")
)
.unwrap();
writeln!(
&mut s,
" Created: {}",
self.created_at
.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)
)
.unwrap();
writeln!(&mut s, " URIs:").unwrap();
for uri in &self.uris {
writeln!(&mut s, " - {uri}").unwrap();
}
if let Some(compute_tier) = &self.compute_tier {
writeln!(
&mut s,
" Instance size: {}",
compute_tier.to_fancy_string()
)
.unwrap_or_default();
}
s
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectListResponse {
pub projects: Vec<ProjectResponse>,
}
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectUpdateRequest {
#[cfg_attr(feature = "utoipa", schema(pattern = "^[a-z0-9-]{1,32}$"))]
pub name: Option<String>,
#[cfg_attr(feature = "utoipa", schema(pattern = "^user_[A-Z0-9]{26}$"))]
pub user_id: Option<String>,
#[cfg_attr(feature = "utoipa", schema(pattern = "^team_[A-Z0-9]{26}$"))]
pub team_id: Option<String>,
pub remove_from_team: Option<bool>,
pub config: Option<serde_json::Value>,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, EnumString)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub enum ComputeTier {
#[default]
XS,
S,
M,
L,
XL,
XXL,
#[cfg(feature = "unknown-variants")]
#[doc(hidden)]
#[typeshare(skip)]
#[serde(untagged, skip_serializing)]
#[strum(default)]
Unknown(String),
}
impl ComputeTier {
pub fn to_fancy_string(&self) -> String {
match self {
Self::XS => "Basic (0.25 vCPU, 0.5 GB RAM)".to_owned(),
Self::S => "Small (0.5 vCPU, 1 GB RAM)".to_owned(),
Self::M => "Medium (1 vCPU, 2 GB RAM)".to_owned(),
Self::L => "Large (2 vCPU, 4 GB RAM)".to_owned(),
Self::XL => "X Large (4 vCPU, 8 GB RAM)".to_owned(),
Self::XXL => "XX Large (8 vCPU, 16 GB RAM)".to_owned(),
#[cfg(feature = "unknown-variants")]
Self::Unknown(s) => format!("Unknown: {s}"),
}
}
}
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectUsageResponse {
pub build_minutes: ProjectUsageBuild,
pub vcpu: ProjectUsageVCPU,
pub daily: Vec<ProjectUsageDaily>,
}
#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectUsageBuild {
pub used: u32,
pub limit: u32,
}
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectUsageVCPU {
pub reserved_hours: f32,
pub billable_hours: f32,
}
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectUsageDaily {
pub avg_cpu_utilised: f32,
pub avg_mem_utilised: f32,
pub billable_vcpu_hours: f32,
pub build_minutes: u32,
pub isodate: chrono::NaiveDate,
pub max_cpu_reserved: f32,
pub max_mem_reserved: f32,
pub min_cpu_reserved: f32,
pub min_mem_reserved: f32,
pub reserved_vcpu_hours: f32,
pub runtime_minutes: u32,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[typeshare::typeshare]
pub struct ProjectLimitsResponse {
pub can_deploy: Option<bool>,
pub can_add_certificate: Option<bool>,
pub full_telemetry_enabled: Option<bool>,
pub max_compute_tier: Option<ComputeTier>,
}