AtsRustCodeGenerator.cs (212)
116WriteLine("//! aspire.rs - Capability-based Aspire SDK");
117WriteLine("//! GENERATED CODE - DO NOT EDIT");
118WriteLine();
119WriteLine("use std::collections::HashMap;");
120WriteLine("use std::sync::Arc;");
121WriteLine();
122WriteLine("use serde::{Deserialize, Serialize};");
123WriteLine("use serde_json::{json, Value};");
124WriteLine();
125WriteLine("use crate::transport::{");
126WriteLine(" AspireClient, CancellationToken, Handle,");
127WriteLine(" register_callback, register_cancellation, serialize_value,");
128WriteLine("};");
129WriteLine("use crate::base::{");
130WriteLine(" HandleWrapperBase, ResourceBuilderBase, ReferenceExpression,");
131WriteLine(" AspireList, AspireDict, serialize_handle, HasHandle,");
132WriteLine("};");
133WriteLine();
143WriteLine("// ============================================================================");
144WriteLine("// Enums");
145WriteLine("// ============================================================================");
146WriteLine();
156WriteLine($"/// {enumType.Name}");
157WriteLine("#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]");
158WriteLine($"pub enum {enumName} {{");
165WriteLine($" #[default]");
168WriteLine($" #[serde(rename = \"{member}\")]");
169WriteLine($" {memberName},");
171WriteLine("}");
172WriteLine();
175WriteLine($"impl std::fmt::Display for {enumName} {{");
176WriteLine(" fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {");
177WriteLine(" match self {");
181WriteLine($" Self::{memberName} => write!(f, \"{member}\"),");
183WriteLine(" }");
184WriteLine(" }");
185WriteLine("}");
186WriteLine();
199WriteLine("// ============================================================================");
200WriteLine("// DTOs");
201WriteLine("// ============================================================================");
202WriteLine();
213WriteLine($"/// {dto.Name}");
215WriteLine(derivesDefault
218WriteLine($"pub struct {dtoName} {{");
228WriteLine($" #[serde(rename = \"{wireName}\"{alias}, skip_serializing_if = \"Option::is_none\")]");
232WriteLine($" #[serde(rename = \"{wireName}\"{alias})]");
234WriteLine($" pub {propertyName}: {propertyType},");
236WriteLine("}");
237WriteLine();
240WriteLine($"impl {dtoName} {{");
241WriteLine(" pub fn to_map(&self) -> HashMap<String, Value> {");
242WriteLine(" let mut map = HashMap::new();");
248WriteLine($" if let Some(ref v) = self.{propertyName} {{");
249WriteLine($" map.insert(\"{JsonNamingPolicy.CamelCase.ConvertName(property.Name)}\".to_string(), serde_json::to_value(v).unwrap_or(Value::Null));");
250WriteLine(" }");
254WriteLine($" map.insert(\"{JsonNamingPolicy.CamelCase.ConvertName(property.Name)}\".to_string(), serde_json::to_value(&self.{propertyName}).unwrap_or(Value::Null));");
257WriteLine(" map");
258WriteLine(" }");
259WriteLine("}");
260WriteLine();
271WriteLine("// ============================================================================");
272WriteLine("// Exported Values");
273WriteLine("// ============================================================================");
274WriteLine();
280WriteLine();
288WriteLine($"{indent}pub mod {ToSnakeCase(name)} {{");
289WriteLine($"{indent} use super::*;");
290WriteLine();
304WriteLine($"{indent}}}");
314WriteLine($"{indent}/// {valueInfo.Description}");
317WriteLine($"{indent}pub fn {ToSnakeCase(name)}() -> {returnType} {{");
318WriteLine($"{indent} serde_json::from_value::<{returnType}>(serde_json::json!({valueInfo.Value?.ToRelaxedJsonString() ?? "null"}))");
319WriteLine($"{indent} .expect(\"generated exported value should deserialize\")");
320WriteLine($"{indent}}}");
410WriteLine("// ============================================================================");
411WriteLine("// Handle Wrappers");
412WriteLine("// ============================================================================");
413WriteLine();
417WriteLine($"/// Wrapper for {handleType.TypeId}");
418WriteLine($"pub struct {handleType.StructName} {{");
419WriteLine(" handle: Handle,");
420WriteLine(" client: Arc<AspireClient>,");
421WriteLine("}");
422WriteLine();
425WriteLine($"impl HasHandle for {handleType.StructName} {{");
426WriteLine(" fn handle(&self) -> &Handle {");
427WriteLine(" &self.handle");
428WriteLine(" }");
429WriteLine("}");
430WriteLine();
433WriteLine($"impl {handleType.StructName} {{");
434WriteLine(" pub fn new(handle: Handle, client: Arc<AspireClient>) -> Self {");
435WriteLine(" Self { handle, client }");
436WriteLine(" }");
437WriteLine();
438WriteLine(" pub fn handle(&self) -> &Handle {");
439WriteLine(" &self.handle");
440WriteLine(" }");
441WriteLine();
442WriteLine(" pub fn client(&self) -> &Arc<AspireClient> {");
443WriteLine(" &self.client");
444WriteLine(" }");
454WriteLine("}");
455WriteLine();
508WriteLine();
509WriteLine($" /// {capability.Description}");
513WriteLine($" pub fn {methodName}({paramList}) -> {resultType} {{");
514WriteLine(" let mut args: HashMap<String, Value> = HashMap::new();");
515WriteLine($" args.insert(\"{targetParamName}\".to_string(), self.handle.to_json());");
522WriteLine($" let callback_id = register_callback({paramName});");
523WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::String(callback_id));");
529WriteLine($" if let Some(token) = {paramName} {{");
530WriteLine($" let token_id = register_cancellation(token, self.client.clone());");
531WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::String(token_id));");
532WriteLine(" }");
541WriteLine($" if let Some(ref v) = {paramName} {{");
542WriteLine($" args.insert(\"{parameter.Name}\".to_string(), v.handle().to_json());");
543WriteLine(" }");
547WriteLine($" args.insert(\"{parameter.Name}\".to_string(), {paramName}.handle().to_json());");
557WriteLine($" if let Some(ref v) = {paramName} {{");
558WriteLine($" args.insert(\"{parameter.Name}\".to_string(), v.handle().to_json());");
559WriteLine(" }");
563WriteLine($" args.insert(\"{parameter.Name}\".to_string(), {paramName}.handle().to_json());");
573WriteLine($" if let Some(ref v) = {paramName} {{");
574WriteLine($" let handles: Vec<Value> = v.iter().map(|item| item.handle().to_json()).collect();");
575WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::Array(handles));");
576WriteLine(" }");
580WriteLine($" let handles: Vec<Value> = {paramName}.iter().map(|item| item.handle().to_json()).collect();");
581WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::Array(handles));");
588WriteLine($" if let Some(ref v) = {paramName} {{");
589WriteLine($" args.insert(\"{parameter.Name}\".to_string(), serde_json::to_value(v).unwrap_or(Value::Null));");
590WriteLine(" }");
594WriteLine($" args.insert(\"{parameter.Name}\".to_string(), serde_json::to_value(&{paramName}).unwrap_or(Value::Null));");
598WriteLine($" let result = self.client.invoke_capability(\"{capability.CapabilityId}\", args)?;");
608WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
609WriteLine($" Ok({wrappedType}::new(handle, self.client.clone()))");
614WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
615WriteLine($" Ok(CancellationToken::new(handle, self.client.clone()))");
620WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
621WriteLine($" Ok(AspireDict::new(handle, self.client.clone()))");
626WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
627WriteLine($" Ok(AspireList::new(handle, self.client.clone()))");
633WriteLine($" let handles: Vec<Handle> = serde_json::from_value(result)?;");
634WriteLine($" Ok(handles.into_iter().map(|h| {elementType}::new(h, self.client.clone())).collect())");
638WriteLine($" Ok(serde_json::from_value(result)?)");
643WriteLine(" Ok(())");
646WriteLine(" }");
686WriteLine();
687WriteLine($" /// {capability.Description}");
691WriteLine($" pub fn {methodName}(&self) -> {fullType} {{");
692WriteLine($" {wrapperType}::with_getter(self.handle.clone(), self.client.clone(), \"{capability.CapabilityId}\")");
693WriteLine(" }");
702WriteLine("// ============================================================================");
703WriteLine("// Handle wrapper registrations");
704WriteLine("// ============================================================================");
705WriteLine();
706WriteLine("pub fn register_all_wrappers() {");
707WriteLine(" // Handle wrappers are created inline in generated code");
708WriteLine(" // This function is provided for API compatibility");
709WriteLine("}");
710WriteLine();
719WriteLine("// ============================================================================");
720WriteLine("// Connection Helpers");
721WriteLine("// ============================================================================");
722WriteLine();
723WriteLine("/// Establishes a connection to the AppHost server.");
724WriteLine("pub fn connect() -> Result<Arc<AspireClient>, Box<dyn std::error::Error>> {");
725WriteLine(" let socket_path = std::env::var(\"REMOTE_APP_HOST_SOCKET_PATH\")");
726WriteLine(" .map_err(|_| \"REMOTE_APP_HOST_SOCKET_PATH environment variable not set. Run this application using `aspire run`\")?;");
727WriteLine(" let client = Arc::new(AspireClient::new(&socket_path));");
728WriteLine(" client.connect()?;");
729WriteLine(" let auth_token = std::env::var(\"ASPIRE_REMOTE_APPHOST_TOKEN\")");
730WriteLine(" .map_err(|_| \"ASPIRE_REMOTE_APPHOST_TOKEN environment variable not set. Run this application using `aspire run`\")?;");
731WriteLine(" client.authenticate(&auth_token)?;");
732WriteLine(" Ok(client)");
733WriteLine("}");
734WriteLine();
735WriteLine($"/// Creates a new distributed application builder.");
736WriteLine($"pub fn create_builder(options: Option<CreateBuilderOptions>) -> Result<{builderStructName}, Box<dyn std::error::Error>> {{");
737WriteLine(" let client = connect()?;");
738WriteLine(" let mut resolved_options: HashMap<String, Value> = HashMap::new();");
739WriteLine(" if let Some(opts) = options {");
740WriteLine(" for (k, v) in opts.to_map() {");
741WriteLine(" resolved_options.insert(k, v);");
742WriteLine(" }");
743WriteLine(" }");
744WriteLine(" if !resolved_options.contains_key(\"args\") {");
745WriteLine(" let args: Vec<String> = std::env::args().skip(1).collect();");
746WriteLine(" resolved_options.insert(\"args\".to_string(), serde_json::to_value(args).unwrap_or(Value::Null));");
747WriteLine(" }");
748WriteLine(" if !resolved_options.contains_key(\"projectDirectory\") {");
751WriteLine(" if let Some(project_directory) = std::env::var(\"ASPIRE_PROJECT_DIRECTORY\").ok().filter(|s| !s.is_empty()) {");
752WriteLine(" resolved_options.insert(\"projectDirectory\".to_string(), Value::String(project_directory));");
753WriteLine(" } else if let Ok(pwd) = std::env::current_dir() {");
754WriteLine(" resolved_options.insert(\"projectDirectory\".to_string(), Value::String(pwd.to_string_lossy().to_string()));");
755WriteLine(" }");
756WriteLine(" }");
761WriteLine(" if !resolved_options.contains_key(\"appHostFilePath\") {");
762WriteLine(" if let Ok(app_host_file_path) = std::env::var(\"ASPIRE_APPHOST_FILEPATH\") {");
763WriteLine(" if !app_host_file_path.is_empty() {");
764WriteLine(" resolved_options.insert(\"appHostFilePath\".to_string(), Value::String(app_host_file_path));");
765WriteLine(" }");
766WriteLine(" }");
767WriteLine(" }");
768WriteLine(" let mut args: HashMap<String, Value> = HashMap::new();");
769WriteLine(" args.insert(\"argsOrOptions\".to_string(), serde_json::to_value(resolved_options).unwrap_or(Value::Null));");
770WriteLine(" let result = client.invoke_capability(\"Aspire.Hosting/createBuilder\", args)?;");
771WriteLine(" let handle: Handle = serde_json::from_value(result)?;");
772WriteLine($" Ok({builderStructName}::new(handle, client))");
773WriteLine("}");
774WriteLine();