1#![warn(missing_docs)]
2
3use nargo_types::{BridgeField, BridgeType, Result, TypeBridge};
4use std::{fs, path::Path};
5use tracing::info;
6
7pub struct NargoBridge {
9 types: Vec<BridgeType>,
10}
11
12impl NargoBridge {
13 pub fn new() -> Self {
15 Self { types: Vec::new() }
16 }
17
18 pub fn register<T: TypeBridge>(&mut self) {
20 self.types.push(T::bridge_info());
21 }
22
23 pub fn generate(&self, output_path: &Path) -> Result<()> {
25 let mut ts_code = String::new();
26 ts_code.push_str("// Generated by nargo-bridge. DO NOT EDIT.\n\n");
27
28 for ty in &self.types {
29 ts_code.push_str(&format!("export interface {} {{\n", ty.name));
30 for field in &ty.fields {
31 let ts_type = self.map_to_ts(&field.ty);
32 ts_code.push_str(&format!(" {}: {};\n", field.name, ts_type));
33 }
34 ts_code.push_str("}\n\n");
35 }
36
37 if let Some(parent) = output_path.parent() {
38 fs::create_dir_all(parent)?;
39 }
40 fs::write(output_path, ts_code)?;
41 info!("Generated TS bridge to {}", output_path.display());
42 Ok(())
43 }
44
45 fn map_to_ts(&self, rust_type: &str) -> String {
46 match rust_type {
47 "String" | "&str" => "string".to_string(),
48 "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | "f32" | "f64" | "usize" => "number".to_string(),
49 "bool" => "boolean".to_string(),
50 _ if rust_type.starts_with("Vec<") => {
51 let inner = &rust_type[4..rust_type.len() - 1];
52 format!("{}[]", self.map_to_ts(inner))
53 }
54 _ if rust_type.starts_with("Option<") => {
55 let inner = &rust_type[7..rust_type.len() - 1];
56 format!("{} | null", self.map_to_ts(inner))
57 }
58 _ => rust_type.to_string(),
59 }
60 }
61}
62
63impl Default for NargoBridge {
64 fn default() -> Self {
65 Self::new()
66 }
67}