1use anyhow::{anyhow, Result};
2use loro::LoroMap;
3use std::path::Path;
4
5use crate::db;
6
7pub struct Opts<'a> {
8 pub title: Option<&'a str>,
9 pub priority: db::Priority,
10 pub effort: db::Effort,
11 pub task_type: &'a str,
12 pub desc: Option<&'a str>,
13 pub parent: Option<&'a str>,
14 pub labels: Option<&'a str>,
15 pub json: bool,
16}
17
18pub fn run(root: &Path, opts: Opts) -> Result<()> {
19 let title = opts.title.ok_or_else(|| anyhow!("title required"))?;
20 let desc = opts.desc.unwrap_or("");
21 let ts = db::now_utc();
22
23 let store = db::open(root)?;
24 let id = db::gen_id();
25
26 let parent = if let Some(raw) = opts.parent {
27 Some(db::resolve_task_id(&store, raw, false)?)
28 } else {
29 None
30 };
31
32 store.apply_and_persist(|doc| {
33 let tasks = doc.get_map("tasks");
34 let task = db::insert_task_map(&tasks, &id)?;
35
36 task.insert("title", title)?;
37 task.insert("description", desc)?;
38 task.insert("type", opts.task_type)?;
39 task.insert("priority", db::priority_label(opts.priority))?;
40 task.insert("status", db::status_label(db::Status::Open))?;
41 task.insert("effort", db::effort_label(opts.effort))?;
42 task.insert("parent", parent.as_ref().map(|p| p.as_str()).unwrap_or(""))?;
43 task.insert("created_at", ts.clone())?;
44 task.insert("updated_at", ts.clone())?;
45 task.insert("deleted_at", "")?;
46 task.insert_container("labels", LoroMap::new())?;
47 task.insert_container("blockers", LoroMap::new())?;
48 task.insert_container("logs", LoroMap::new())?;
49
50 if let Some(label_str) = opts.labels {
51 let labels = db::get_or_create_child_map(&task, "labels")?;
52 for lbl in label_str
53 .split(',')
54 .map(str::trim)
55 .filter(|l| !l.is_empty())
56 {
57 labels.insert(lbl, true)?;
58 }
59 }
60
61 Ok(())
62 })?;
63
64 let task = store
65 .get_task(&id, false)?
66 .ok_or_else(|| anyhow!("failed to reload created task"))?;
67
68 if opts.json {
69 println!("{}", serde_json::to_string(&task)?);
70 } else {
71 let c = crate::color::stdout_theme();
72 println!("{}created{} {}: {}", c.green, c.reset, task.id, task.title);
73 }
74
75 Ok(())
76}