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} {{");
225WriteLine($" #[serde(rename = \"{property.Name}\", skip_serializing_if = \"Option::is_none\")]");
229WriteLine($" #[serde(rename = \"{property.Name}\")]");
231WriteLine($" pub {propertyName}: {propertyType},");
233WriteLine("}");
234WriteLine();
237WriteLine($"impl {dtoName} {{");
238WriteLine(" pub fn to_map(&self) -> HashMap<String, Value> {");
239WriteLine(" let mut map = HashMap::new();");
245WriteLine($" if let Some(ref v) = self.{propertyName} {{");
246WriteLine($" map.insert(\"{property.Name}\".to_string(), serde_json::to_value(v).unwrap_or(Value::Null));");
247WriteLine(" }");
251WriteLine($" map.insert(\"{property.Name}\".to_string(), serde_json::to_value(&self.{propertyName}).unwrap_or(Value::Null));");
254WriteLine(" map");
255WriteLine(" }");
256WriteLine("}");
257WriteLine();
268WriteLine("// ============================================================================");
269WriteLine("// Exported Values");
270WriteLine("// ============================================================================");
271WriteLine();
277WriteLine();
285WriteLine($"{indent}pub mod {ToSnakeCase(name)} {{");
286WriteLine($"{indent} use super::*;");
287WriteLine();
301WriteLine($"{indent}}}");
311WriteLine($"{indent}/// {valueInfo.Description}");
314WriteLine($"{indent}pub fn {ToSnakeCase(name)}() -> {returnType} {{");
315WriteLine($"{indent} serde_json::from_value::<{returnType}>(serde_json::json!({valueInfo.Value?.ToRelaxedJsonString() ?? "null"}))");
316WriteLine($"{indent} .expect(\"generated exported value should deserialize\")");
317WriteLine($"{indent}}}");
407WriteLine("// ============================================================================");
408WriteLine("// Handle Wrappers");
409WriteLine("// ============================================================================");
410WriteLine();
414WriteLine($"/// Wrapper for {handleType.TypeId}");
415WriteLine($"pub struct {handleType.StructName} {{");
416WriteLine(" handle: Handle,");
417WriteLine(" client: Arc<AspireClient>,");
418WriteLine("}");
419WriteLine();
422WriteLine($"impl HasHandle for {handleType.StructName} {{");
423WriteLine(" fn handle(&self) -> &Handle {");
424WriteLine(" &self.handle");
425WriteLine(" }");
426WriteLine("}");
427WriteLine();
430WriteLine($"impl {handleType.StructName} {{");
431WriteLine(" pub fn new(handle: Handle, client: Arc<AspireClient>) -> Self {");
432WriteLine(" Self { handle, client }");
433WriteLine(" }");
434WriteLine();
435WriteLine(" pub fn handle(&self) -> &Handle {");
436WriteLine(" &self.handle");
437WriteLine(" }");
438WriteLine();
439WriteLine(" pub fn client(&self) -> &Arc<AspireClient> {");
440WriteLine(" &self.client");
441WriteLine(" }");
451WriteLine("}");
452WriteLine();
506WriteLine();
507WriteLine($" /// {capability.Description}");
511WriteLine($" pub fn {methodName}({paramList}) -> {resultType} {{");
512WriteLine(" let mut args: HashMap<String, Value> = HashMap::new();");
513WriteLine($" args.insert(\"{targetParamName}\".to_string(), self.handle.to_json());");
520WriteLine($" let callback_id = register_callback({paramName});");
521WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::String(callback_id));");
527WriteLine($" if let Some(token) = {paramName} {{");
528WriteLine($" let token_id = register_cancellation(token, self.client.clone());");
529WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::String(token_id));");
530WriteLine(" }");
539WriteLine($" if let Some(ref v) = {paramName} {{");
540WriteLine($" args.insert(\"{parameter.Name}\".to_string(), v.handle().to_json());");
541WriteLine(" }");
545WriteLine($" args.insert(\"{parameter.Name}\".to_string(), {paramName}.handle().to_json());");
555WriteLine($" if let Some(ref v) = {paramName} {{");
556WriteLine($" args.insert(\"{parameter.Name}\".to_string(), v.handle().to_json());");
557WriteLine(" }");
561WriteLine($" args.insert(\"{parameter.Name}\".to_string(), {paramName}.handle().to_json());");
571WriteLine($" if let Some(ref v) = {paramName} {{");
572WriteLine($" let handles: Vec<Value> = v.iter().map(|item| item.handle().to_json()).collect();");
573WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::Array(handles));");
574WriteLine(" }");
578WriteLine($" let handles: Vec<Value> = {paramName}.iter().map(|item| item.handle().to_json()).collect();");
579WriteLine($" args.insert(\"{parameter.Name}\".to_string(), Value::Array(handles));");
586WriteLine($" if let Some(ref v) = {paramName} {{");
587WriteLine($" args.insert(\"{parameter.Name}\".to_string(), serde_json::to_value(v).unwrap_or(Value::Null));");
588WriteLine(" }");
592WriteLine($" args.insert(\"{parameter.Name}\".to_string(), serde_json::to_value(&{paramName}).unwrap_or(Value::Null));");
596WriteLine($" let result = self.client.invoke_capability(\"{capability.CapabilityId}\", args)?;");
606WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
607WriteLine($" Ok({wrappedType}::new(handle, self.client.clone()))");
612WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
613WriteLine($" Ok(CancellationToken::new(handle, self.client.clone()))");
618WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
619WriteLine($" Ok(AspireDict::new(handle, self.client.clone()))");
624WriteLine($" let handle: Handle = serde_json::from_value(result)?;");
625WriteLine($" Ok(AspireList::new(handle, self.client.clone()))");
631WriteLine($" let handles: Vec<Handle> = serde_json::from_value(result)?;");
632WriteLine($" Ok(handles.into_iter().map(|h| {elementType}::new(h, self.client.clone())).collect())");
636WriteLine($" Ok(serde_json::from_value(result)?)");
641WriteLine(" Ok(())");
644WriteLine(" }");
684WriteLine();
685WriteLine($" /// {capability.Description}");
689WriteLine($" pub fn {methodName}(&self) -> {fullType} {{");
690WriteLine($" {wrapperType}::with_getter(self.handle.clone(), self.client.clone(), \"{capability.CapabilityId}\")");
691WriteLine(" }");
700WriteLine("// ============================================================================");
701WriteLine("// Handle wrapper registrations");
702WriteLine("// ============================================================================");
703WriteLine();
704WriteLine("pub fn register_all_wrappers() {");
705WriteLine(" // Handle wrappers are created inline in generated code");
706WriteLine(" // This function is provided for API compatibility");
707WriteLine("}");
708WriteLine();
717WriteLine("// ============================================================================");
718WriteLine("// Connection Helpers");
719WriteLine("// ============================================================================");
720WriteLine();
721WriteLine("/// Establishes a connection to the AppHost server.");
722WriteLine("pub fn connect() -> Result<Arc<AspireClient>, Box<dyn std::error::Error>> {");
723WriteLine(" let socket_path = std::env::var(\"REMOTE_APP_HOST_SOCKET_PATH\")");
724WriteLine(" .map_err(|_| \"REMOTE_APP_HOST_SOCKET_PATH environment variable not set. Run this application using `aspire run`\")?;");
725WriteLine(" let client = Arc::new(AspireClient::new(&socket_path));");
726WriteLine(" client.connect()?;");
727WriteLine(" let auth_token = std::env::var(\"ASPIRE_REMOTE_APPHOST_TOKEN\")");
728WriteLine(" .map_err(|_| \"ASPIRE_REMOTE_APPHOST_TOKEN environment variable not set. Run this application using `aspire run`\")?;");
729WriteLine(" client.authenticate(&auth_token)?;");
730WriteLine(" Ok(client)");
731WriteLine("}");
732WriteLine();
733WriteLine($"/// Creates a new distributed application builder.");
734WriteLine($"pub fn create_builder(options: Option<CreateBuilderOptions>) -> Result<{builderStructName}, Box<dyn std::error::Error>> {{");
735WriteLine(" let client = connect()?;");
736WriteLine(" let mut resolved_options: HashMap<String, Value> = HashMap::new();");
737WriteLine(" if let Some(opts) = options {");
738WriteLine(" for (k, v) in opts.to_map() {");
739WriteLine(" resolved_options.insert(k, v);");
740WriteLine(" }");
741WriteLine(" }");
742WriteLine(" if !resolved_options.contains_key(\"Args\") {");
743WriteLine(" let args: Vec<String> = std::env::args().skip(1).collect();");
744WriteLine(" resolved_options.insert(\"Args\".to_string(), serde_json::to_value(args).unwrap_or(Value::Null));");
745WriteLine(" }");
746WriteLine(" if !resolved_options.contains_key(\"ProjectDirectory\") {");
749WriteLine(" if let Some(project_directory) = std::env::var(\"ASPIRE_PROJECT_DIRECTORY\").ok().filter(|s| !s.is_empty()) {");
750WriteLine(" resolved_options.insert(\"ProjectDirectory\".to_string(), Value::String(project_directory));");
751WriteLine(" } else if let Ok(pwd) = std::env::current_dir() {");
752WriteLine(" resolved_options.insert(\"ProjectDirectory\".to_string(), Value::String(pwd.to_string_lossy().to_string()));");
753WriteLine(" }");
754WriteLine(" }");
759WriteLine(" if !resolved_options.contains_key(\"AppHostFilePath\") {");
760WriteLine(" if let Ok(app_host_file_path) = std::env::var(\"ASPIRE_APPHOST_FILEPATH\") {");
761WriteLine(" if !app_host_file_path.is_empty() {");
762WriteLine(" resolved_options.insert(\"AppHostFilePath\".to_string(), Value::String(app_host_file_path));");
763WriteLine(" }");
764WriteLine(" }");
765WriteLine(" }");
766WriteLine(" let mut args: HashMap<String, Value> = HashMap::new();");
767WriteLine(" args.insert(\"argsOrOptions\".to_string(), serde_json::to_value(resolved_options).unwrap_or(Value::Null));");
768WriteLine(" let result = client.invoke_capability(\"Aspire.Hosting/createBuilder\", args)?;");
769WriteLine(" let handle: Handle = serde_json::from_value(result)?;");
770WriteLine($" Ok({builderStructName}::new(handle, client))");
771WriteLine("}");
772WriteLine();