Skip to main content

interstice_cli/
init.rs

1use std::{io, path::Path};
2
3use interstice_core::IntersticeError;
4
5// Init module projectect structure in current directory, it should ask the project name create the directory
6// and create a template module in it. The template has the basic rust structure with the additional interstice_sdk dependency, a build.rs file filled twith the provided macro
7// and a src/lib.rs file with a template module using the interstice_module macro and a simple reducer.
8// It should also add a .cargo/config.toml to set the target to be wasm32-unknown-unknown and a Cargo.toml with the interstice_sdk dependency and the build script.
9// The command should fail if the current directory is not empty to avoid overwriting files.
10pub fn init() -> Result<(), IntersticeError> {
11    println!("Enter the project name: ");
12    let project_name = &mut String::new();
13    io::stdin()
14        .read_line(project_name)
15        .expect("Should be able to read line");
16    let project_name = project_name
17        .parse::<String>()
18        .map_err(|_| IntersticeError::Internal("Failed to read project name".into()))?
19        .trim()
20        .to_string();
21    let project_path = Path::new(&project_name);
22    if project_path.exists() {
23        return Err(IntersticeError::Internal("Directory already exists".into()));
24    }
25    std::fs::create_dir(&project_path).map_err(|err| {
26        IntersticeError::Internal(format!("Failed to create project directory: {}", err))
27    })?;
28
29    let name = project_name.to_lowercase();
30
31    // Create Cargo.toml
32    let cargo_toml_content = format!(
33        r#"[package]
34name = "{name}"
35version = "0.1.0"
36edition = "2024"
37
38[lib]
39crate-type = ["cdylib"]
40
41[dependencies]
42interstice_sdk = "0.1.0"
43
44[build-dependencies]
45interstice_sdk = "0.1.0"
46"#,
47    );
48    std::fs::write(project_path.join("Cargo.toml"), cargo_toml_content).map_err(|err| {
49        IntersticeError::Internal(format!("Failed to create Cargo.toml: {}", err))
50    })?;
51
52    // Create .cargo/config.toml
53    let cargo_config_content = r#"[build]
54target = "wasm32-unknown-unknown"
55"#;
56    std::fs::create_dir(project_path.join(".cargo")).map_err(|err| {
57        IntersticeError::Internal(format!("Failed to create .cargo directory: {}", err))
58    })?;
59    std::fs::write(
60        project_path.join(".cargo/config.toml"),
61        cargo_config_content,
62    )
63    .map_err(|err| {
64        IntersticeError::Internal(format!("Failed to create .cargo/config.toml: {}", err))
65    })?;
66
67    // Create build.rs
68    let build_rs_content = r#"fn main() {
69    interstice_sdk::bindings::generate_bindings();
70}
71"#;
72    std::fs::create_dir(project_path.join("src")).map_err(|err| {
73        IntersticeError::Internal(format!("Failed to create src directory: {}", err))
74    })?;
75    std::fs::write(project_path.join("build.rs"), build_rs_content)
76        .map_err(|err| IntersticeError::Internal(format!("Failed to create build.rs: {}", err)))?;
77
78    // Create src/lib.rs
79    let lib_content = r#"use interstice_sdk::*;
80
81interstice_module!(visibility: Public);
82
83// TABLES
84
85#[table(public)]
86#[derive(Debug)]
87pub struct Greetings {
88    #[primary_key]
89    pub id: u64,
90    pub greeting: String,
91    pub custom: TestCustomType,
92}
93
94#[interstice_type]
95#[derive(Debug, Clone)]
96pub struct TestCustomType {
97    pub val: u32,
98}
99
100// REDUCERS
101#[reducer(on = "init")]
102pub fn init(ctx: ReducerContext) {
103    ctx.log("Hello world !");
104}
105
106#[reducer]
107pub fn hello(ctx: ReducerContext, name: String) {
108    ctx.log(&format!("Saying hello to {}", name));
109    ctx.current.greetings().insert(Greetings {
110        id: 0,
111        greeting: format!("Hello, {}!", name),
112        custom: TestCustomType { val: 0 },
113    });
114}
115
116#[reducer(on = "hello.greetings.insert")]
117fn on_greeting_insert(ctx: ReducerContext, inserted_row: Greetings) {
118    ctx.log(&format!("Inserted greeting: {:?}", inserted_row));
119}"#;
120
121    std::fs::write(project_path.join("src/lib.rs"), lib_content).map_err(|err| {
122        IntersticeError::Internal(format!("Failed to create src/lib.rs: {}", err))
123    })?;
124    Ok(())
125}