use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize)]
pub struct WebCodegenRequest {
pub config_path: PathBuf,
pub output_dir: PathBuf,
pub project_root: PathBuf,
pub overwrite_user_code: bool,
pub package_name: String,
pub manufacturer: String,
pub actr_name: String,
#[serde(default)]
pub version: String,
pub description: String,
pub authors: Vec<String>,
pub license: String,
pub tags: Vec<String>,
pub signaling_url: String,
pub realm_id: u32,
pub visible_in_discovery: bool,
#[serde(default)]
pub ais_endpoint: String,
#[serde(default)]
pub force_relay: bool,
pub dependencies: Vec<DependencyInfo>,
pub stun_urls: Vec<String>,
pub turn_urls: Vec<String>,
pub observability: ObservabilityInfo,
pub raw_toml: String,
pub local_services: Vec<ServiceInfo>,
pub remote_services: Vec<ServiceInfo>,
pub files: Vec<FileInfo>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DependencyInfo {
pub alias: String,
pub actr_type: Option<ActrTypeInfo>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ActrTypeInfo {
pub manufacturer: String,
pub name: String,
#[serde(default)]
pub version: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ObservabilityInfo {
pub filter_level: String,
pub tracing_enabled: bool,
pub tracing_endpoint: String,
pub tracing_service_name: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ServiceInfo {
pub name: String,
pub package: String,
pub relative_path: PathBuf,
pub methods: Vec<MethodInfo>,
pub actr_type: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MethodInfo {
pub name: String,
pub snake_name: String,
pub input_type: String,
pub output_type: String,
pub route_key: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FileInfo {
pub proto_file: PathBuf,
pub relative_path: PathBuf,
pub package: String,
pub is_local: bool,
pub declared_type_names: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WebCodegenResponse {
pub success: bool,
pub generated_files: Vec<PathBuf>,
pub errors: Vec<String>,
}
impl WebCodegenRequest {
pub fn is_service_provider_only(&self) -> bool {
!self.local_services.is_empty()
&& self.remote_services.is_empty()
&& self.dependencies.is_empty()
}
pub fn get_acl_allow_types(&self) -> Vec<String> {
let raw_table: toml::Table = self.raw_toml.parse().unwrap_or_default();
let mut types = Vec::new();
if let Some(acl) = raw_table.get("acl") {
if let Some(rules) = acl.get("rules").and_then(|r| r.as_array()) {
for rule in rules {
if let Some(rule_types) = rule.get("types").and_then(|t| t.as_array()) {
for t in rule_types {
if let Some(s) = t.as_str() {
types.push(s.to_string());
}
}
}
}
}
}
types
}
pub fn target_actr_type(&self) -> String {
if self.is_service_provider_only() {
self.get_acl_allow_types()
.first()
.cloned()
.unwrap_or_default()
} else {
self.dependencies
.first()
.and_then(|d| {
d.actr_type
.as_ref()
.map(|t| format!("{}:{}:{}", t.manufacturer, t.name, t.version))
})
.unwrap_or_default()
}
}
pub fn client_actr_type(&self) -> String {
format!("{}:{}:{}", self.manufacturer, self.actr_name, self.version)
}
pub fn wasm_module_name(&self) -> String {
to_snake_case(&self.package_name).replace('-', "_")
}
pub fn edition(&self) -> i64 {
let raw_table: toml::Table = self.raw_toml.parse().unwrap_or_default();
raw_table
.get("edition")
.and_then(|v| v.as_integer())
.unwrap_or(1)
}
pub fn exports_list(&self) -> Vec<String> {
let raw_table: toml::Table = self.raw_toml.parse().unwrap_or_default();
raw_table
.get("exports")
.and_then(|v| v.as_array())
.map(|arr| {
arr.iter()
.filter_map(|v| v.as_str().map(String::from))
.collect()
})
.unwrap_or_default()
}
pub fn platform_web(&self) -> Option<toml::Value> {
let raw_table: toml::Table = self.raw_toml.parse().unwrap_or_default();
raw_table
.get("platform")
.and_then(|v| v.get("web"))
.cloned()
}
pub fn raw_acl(&self) -> Option<toml::Value> {
let raw_table: toml::Table = self.raw_toml.parse().unwrap_or_default();
raw_table.get("acl").cloned()
}
}
fn to_snake_case(name: &str) -> String {
use heck::ToSnakeCase;
name.to_snake_case()
}