interstice_cli/
bindings.rs1use crate::{node_client::fetch_node_schema, node_registry::NodeRegistry};
2use interstice_core::IntersticeError;
3use std::path::{Path, PathBuf};
4
5pub async fn add_module_binding(
6 node_ref: &str,
7 module_name: &str,
8 project_path: &Path,
9) -> Result<PathBuf, IntersticeError> {
10 let mut registry = NodeRegistry::load()?;
11 let address = registry
12 .resolve_address(node_ref)
13 .ok_or_else(|| IntersticeError::Internal(format!("Unknown node '{}'", node_ref)))?;
14 let node_name = registry
15 .get(node_ref)
16 .map(|n| n.name.clone())
17 .unwrap_or_else(|| node_ref.to_string());
18 let (schema, handshake) = fetch_node_schema(&address, &node_name).await?;
19 registry.set_last_seen(node_ref);
20 registry.set_node_id(node_ref, handshake.node_id);
21 registry.save()?;
22
23 let module = schema
24 .modules
25 .into_iter()
26 .find(|m| m.name == module_name)
27 .ok_or_else(|| {
28 IntersticeError::Internal(format!("Module '{}' not found in node schema", module_name))
29 })?;
30
31 let bindings_dir = project_path.join("src").join("bindings");
32 std::fs::create_dir_all(&bindings_dir).map_err(|err| {
33 IntersticeError::Internal(format!("Failed to create bindings directory: {err}"))
34 })?;
35 let out_path = bindings_dir.join(format!("{}.toml", module_name));
36 let contents = module.to_public().to_toml_string().map_err(|err| {
37 IntersticeError::Internal(format!("Failed to serialize module schema: {err}"))
38 })?;
39 std::fs::write(&out_path, contents).map_err(|err| {
40 IntersticeError::Internal(format!("Failed to write module binding: {err}"))
41 })?;
42 Ok(out_path)
43}
44
45pub async fn add_node_binding(
46 node_ref: &str,
47 project_path: &Path,
48) -> Result<PathBuf, IntersticeError> {
49 let mut registry = NodeRegistry::load()?;
50 let address = registry
51 .resolve_address(node_ref)
52 .ok_or_else(|| IntersticeError::Internal(format!("Unknown node '{}'", node_ref)))?;
53 let node_name = registry
54 .get(node_ref)
55 .map(|n| n.name.clone())
56 .unwrap_or_else(|| node_ref.to_string());
57 let (schema, handshake) = fetch_node_schema(&address, &node_name).await?;
58 registry.set_last_seen(node_ref);
59 registry.set_node_id(node_ref, handshake.node_id);
60 registry.save()?;
61
62 let bindings_dir = project_path.join("src").join("bindings");
63 std::fs::create_dir_all(&bindings_dir).map_err(|err| {
64 IntersticeError::Internal(format!("Failed to create bindings directory: {err}"))
65 })?;
66 let file_name = sanitize_filename(&node_name);
67 let out_path = bindings_dir.join(format!("node_{}.toml", file_name));
68 let contents = schema.to_toml_string().map_err(|err| {
69 IntersticeError::Internal(format!("Failed to serialize node schema: {err}"))
70 })?;
71 std::fs::write(&out_path, contents)
72 .map_err(|err| IntersticeError::Internal(format!("Failed to write node binding: {err}")))?;
73 Ok(out_path)
74}
75
76fn sanitize_filename(value: &str) -> String {
77 value
78 .chars()
79 .map(|c| if c.is_ascii_alphanumeric() { c } else { '_' })
80 .collect()
81}