quartz_cli/action/
body.rs

1use crate::{cli::BodyCmd as Cmd, validator, Ctx, QuartzResult};
2use std::io::Write;
3
4const POSSIBLE_EXT: [&str; 3] = ["json", "html", "xml"];
5
6#[derive(clap::Args, Debug)]
7pub struct Args {
8    /// Which extension to read body as. E.g.: quartz body --format json edit
9    #[arg(long, value_name = "EXT")]
10    format: Option<String>,
11
12    #[command(subcommand)]
13    command: crate::cli::BodyCmd,
14}
15
16pub fn cmd(ctx: &Ctx, args: Args) -> QuartzResult {
17    match args.command {
18        Cmd::Show => print(ctx),
19        Cmd::Stdin => stdin(ctx),
20        Cmd::Edit => edit(ctx, args.format)?,
21    };
22
23    Ok(())
24}
25
26pub fn print(ctx: &Ctx) {
27    let (_, mut endpoint) = ctx.require_endpoint();
28
29    if let Some(body) = endpoint.body() {
30        print!("{body}");
31    }
32}
33
34pub fn edit(ctx: &Ctx, format: Option<String>) -> QuartzResult {
35    let handle = ctx.require_handle();
36    let path = handle.dir(ctx).join("body");
37
38    let format = if format.is_some() {
39        format
40    } else {
41        let endpoint = ctx.require_endpoint_from_handle(&handle);
42
43        if let Some(content) = endpoint.headers.get("content-type") {
44            let ext = POSSIBLE_EXT.iter().find_map(|ext| {
45                if content.contains(*ext) {
46                    Some(ext.to_string())
47                } else {
48                    None
49                }
50            });
51
52            ext
53        } else {
54            None
55        }
56    };
57
58    if let Some(format) = format {
59        // We cannot validate json for now. If we do so, variable notation will fail because it can
60        // generate invalid JSON. For exemple:
61        //
62        // { "value": {{n}} }
63        //
64        // n must be a number, so we don't wrap it in quotes. This JSON before variables is
65        // invalid. A solution may or may not be done later.
66        ctx.edit_with_extension(&path, Some(&format), validator::infallible)?;
67    } else {
68        ctx.edit(&path, validator::infallible)?;
69    }
70
71    Ok(())
72}
73
74pub fn stdin(ctx: &Ctx) {
75    let handle = ctx.require_handle();
76
77    let mut input = String::new();
78    while let Ok(bytes) = std::io::stdin().read_line(&mut input) {
79        if bytes == 0 {
80            break;
81        }
82    }
83
84    if let Ok(mut file) = std::fs::OpenOptions::new()
85        .create(true)
86        .write(true)
87        .truncate(true)
88        .open(handle.dir(ctx).join("body"))
89    {
90        let _ = file.write_all(input.as_bytes());
91    }
92}