use super::{WATCH_RESOURCE_NEXT_STEP, take_required_position, unknown_resource};
use crate::flags::{FlagScope, parse_flags};
use crate::{CliError, Command, WatchTarget};
const WATCH_LOG_FILTER_NEXT_STEP: &str =
"use logbrew logs with filters for historical data until live watch is available";
const WATCH_LOG_POSITIONAL_NEXT_STEP: &str = "use logbrew logs --severity <severity> or --search \
<text> for historical data until live watch is available";
const WATCH_ACTION_FILTER_NEXT_STEP: &str =
"use logbrew actions with filters for historical data until live watch is available";
const WATCH_ACTION_POSITIONAL_NEXT_STEP: &str =
"use logbrew actions --name <name> for historical data until live watch is available";
pub(super) fn parse_watch(args: &[String]) -> Result<Command, CliError> {
let (resource, rest) = take_required_position(args, "resource", WATCH_RESOURCE_NEXT_STEP)?;
let target = match resource.as_str() {
"logs" => WatchTarget::Logs,
"actions" | "action" | "events" | "event" => WatchTarget::Actions,
other => return Err(unknown_resource(other, WATCH_RESOURCE_NEXT_STEP)),
};
if let Some(error) = reserved_watch_tail_error(target, rest.as_slice())? {
return Err(error);
}
let flags = parse_flags(rest.as_slice(), FlagScope::Watch)?;
Ok(Command::Watch {
target,
json: flags.is_json(),
})
}
fn reserved_watch_tail_error(
target: WatchTarget,
args: &[String],
) -> Result<Option<CliError>, CliError> {
reject_duplicate_json(args)?;
for arg in args {
if arg == "--json" {
continue;
}
if let Some(flag) = historical_filter_flag(target, arg) {
return Ok(Some(CliError::UnsupportedFlag {
flag: flag.to_owned(),
command: "watch",
next: filter_next_step(target),
}));
}
if arg.starts_with('-') {
return Ok(None);
}
return Ok(Some(CliError::UnexpectedArgument {
argument: arg.to_owned(),
command: "watch",
next: positional_next_step(target),
}));
}
Ok(None)
}
fn reject_duplicate_json(args: &[String]) -> Result<(), CliError> {
let mut seen_json = false;
for arg in args {
if arg != "--json" {
continue;
}
if seen_json {
return Err(CliError::DuplicateFlag {
flag: "--json",
next: "use --json once",
});
}
seen_json = true;
}
Ok(())
}
fn historical_filter_flag(target: WatchTarget, arg: &str) -> Option<&str> {
let flag = arg.split_once('=').map_or(arg, |(name, _)| name);
match target {
WatchTarget::Logs => match flag {
"--level" | "--severity" | "--search" | "--trace" | "--trace-id" | "--project"
| "--project-id" | "--release" | "--environment" | "--env" | "--since" | "--limit" => {
Some(flag)
}
_ => None,
},
WatchTarget::Actions => match flag {
"--name" | "--user" | "--distinct-id" | "--project" | "--project-id" | "--release"
| "--environment" | "--env" | "--since" | "--limit" => Some(flag),
_ => None,
},
}
}
const fn filter_next_step(target: WatchTarget) -> &'static str {
match target {
WatchTarget::Logs => WATCH_LOG_FILTER_NEXT_STEP,
WatchTarget::Actions => WATCH_ACTION_FILTER_NEXT_STEP,
}
}
const fn positional_next_step(target: WatchTarget) -> &'static str {
match target {
WatchTarget::Logs => WATCH_LOG_POSITIONAL_NEXT_STEP,
WatchTarget::Actions => WATCH_ACTION_POSITIONAL_NEXT_STEP,
}
}