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": crate::cli_i18n::t("cli.status.ok"),
33 "pack_dir": root,
34 }))?
35 );
36 } else {
37 println!(
38 "{}",
39 crate::cli_i18n::tf("cli.new.created_pack_at", &[&root.display().to_string()])
40 );
41 }
42
43 Ok(())
44}
45
46fn write_pack_yaml(root: &Path, pack_id: &str) -> Result<()> {
47 let pack_yaml = format!(
48 r#"pack_id: {pack_id}
49version: 0.1.0
50kind: application
51publisher: Greentic
52
53components: []
54
55flows:
56 - id: main
57 file: flows/main.ygtc
58 tags: [default]
59 entrypoints: [default]
60
61dependencies: []
62
63assets: []
64"#
65 );
66 let path = root.join("pack.yaml");
67 fs::write(&path, pack_yaml).with_context(|| format!("failed to write {}", path.display()))
68}
69
70fn write_flow(root: &Path) -> Result<()> {
71 let flows_dir = root.join("flows");
72 fs::create_dir_all(&flows_dir)?;
73 let flow_path = flows_dir.join("main.ygtc");
74 const FLOW: &str = r#"id: main
75type: messaging
76nodes: {}
77"#;
78 fs::write(&flow_path, FLOW).with_context(|| format!("failed to write {}", flow_path.display()))
79}
80
81fn create_components_dir(root: &Path) -> Result<()> {
82 let components_dir = root.join("components");
83 fs::create_dir_all(&components_dir)
84 .with_context(|| format!("failed to create {}", components_dir.display()))
85}