1#![forbid(unsafe_code)]
2
3use anyhow::{Context, Result};
4use clap::Parser;
5use std::fs;
6use std::path::{Path, PathBuf};
7
8use crate::runtime::RuntimeContext;
9
10#[derive(Debug, Parser)]
11pub struct NewArgs {
12 #[arg(long = "dir", value_name = "DIR")]
14 pub dir: PathBuf,
15 #[arg(value_name = "PACK_ID")]
17 pub pack_id: String,
18}
19
20pub async fn handle(args: NewArgs, json: bool, _runtime: &RuntimeContext) -> Result<()> {
21 let root = args.dir.canonicalize().unwrap_or_else(|_| args.dir.clone());
22 fs::create_dir_all(&root)?;
23
24 write_pack_yaml(&root, &args.pack_id)?;
25 write_flow(&root)?;
26 create_components_dir(&root)?;
27
28 if json {
29 println!(
30 "{}",
31 serde_json::to_string_pretty(&serde_json::json!({
32 "status": "ok",
33 "pack_dir": root,
34 }))?
35 );
36 } else {
37 println!("created pack at {}", root.display());
38 }
39
40 Ok(())
41}
42
43fn write_pack_yaml(root: &Path, pack_id: &str) -> Result<()> {
44 let pack_yaml = format!(
45 r#"pack_id: {pack_id}
46version: 0.1.0
47kind: application
48publisher: Greentic
49
50components: []
51
52flows:
53 - id: main
54 file: flows/main.ygtc
55 tags: [default]
56 entrypoints: [default]
57
58dependencies: []
59
60assets: []
61"#
62 );
63 let path = root.join("pack.yaml");
64 fs::write(&path, pack_yaml).with_context(|| format!("failed to write {}", path.display()))
65}
66
67fn write_flow(root: &Path) -> Result<()> {
68 let flows_dir = root.join("flows");
69 fs::create_dir_all(&flows_dir)?;
70 let flow_path = flows_dir.join("main.ygtc");
71 const FLOW: &str = r#"id: main
72type: messaging
73nodes: {}
74"#;
75 fs::write(&flow_path, FLOW).with_context(|| format!("failed to write {}", flow_path.display()))
76}
77
78fn create_components_dir(root: &Path) -> Result<()> {
79 let components_dir = root.join("components");
80 fs::create_dir_all(&components_dir)
81 .with_context(|| format!("failed to create {}", components_dir.display()))
82}