Skip to main content

doido_generators/generators/
channel.rs

1use crate::generator::{GeneratedFile, Generator};
2use crate::generators::{register_module, to_pascal, to_snake};
3use doido_core::Result;
4
5/// Fallback `app/channels/mod.rs` when the app doesn't have one on disk yet.
6const CHANNELS_MOD_BASE: &str = include_str!("../../templates/new/app/channels/mod.rs");
7const CHANNELS_MOD_PATH: &str = "app/channels/mod.rs";
8
9pub struct ChannelGenerator;
10
11impl Generator for ChannelGenerator {
12    fn name(&self) -> &str {
13        "channel"
14    }
15
16    fn generate(&self, args: &[&str]) -> Result<Vec<GeneratedFile>> {
17        let name = args.first().copied().ok_or_else(|| {
18            doido_core::anyhow::anyhow!("channel generator requires a name argument")
19        })?;
20        let snake = to_snake(name);
21        let pascal = to_pascal(name);
22        let content =
23            crate::templates::get("channel/channel.rs.template").replace("{pascal}", &pascal);
24        let test = crate::templates::get("channel/channel_test.rs.template")
25            .replace("{pascal}", &pascal)
26            .replace("{snake}", &snake);
27
28        // Register the channel's module in app/channels/mod.rs.
29        let existing = std::fs::read_to_string(CHANNELS_MOD_PATH)
30            .unwrap_or_else(|_| CHANNELS_MOD_BASE.to_string());
31        let channels_mod = register_module(
32            &existing,
33            &format!("{snake}_channel"),
34            "@generated-channels",
35        );
36
37        Ok(vec![
38            GeneratedFile {
39                path: format!("app/channels/{snake}_channel.rs"),
40                content,
41            },
42            GeneratedFile {
43                path: CHANNELS_MOD_PATH.to_string(),
44                content: channels_mod,
45            },
46            GeneratedFile {
47                path: format!("tests/{snake}_channel_test.rs"),
48                content: test,
49            },
50        ])
51    }
52}