use crate::input::{self, data, Input, InputData};
use crate::output::{self, Output};
use crate::patch::{self, Patch};
use serde_json::Value as JsonValue;
#[derive(Debug, thiserror::Error, miette::Diagnostic)]
#[error(transparent)]
#[remain::sorted]
pub(crate) enum Error {
Data(#[from] data::Error),
Input(#[from] input::Error),
Json(#[from] serde_json::Error),
Output(#[from] output::Error),
}
const DIFF_DATA_HELP: &str = "data for comparison";
const DIFF_DATA_LONG_HELP: &str = constcat::concat!(
DIFF_DATA_HELP,
".\n",
input::INPUT_SOURCE_LONG_HELP,
"
This will produce a patch
"
);
#[derive(Debug, Clone, clap::Parser)]
#[command(
about = "data processing tool",
long_about = "data processing tool.
Options are applied in the following order:
data -> query -> patch -> diff"
)]
#[remain::sorted]
#[rustfmt::skip]
pub(crate) struct Command {
#[arg(
env = "DIFF_DATA",
long = "diff-data",
id = "diff.data",
value_name = "SOURCE",
help_heading = "Diff Options",
help = DIFF_DATA_HELP,
long_help = DIFF_DATA_LONG_HELP,
)]
pub(crate) diff: Option<InputData>,
#[command(flatten)]
pub(crate) input: Input,
#[command(flatten)]
pub(crate) output: Output
}
impl Command {
pub(crate) async fn run(self, valkey: &crate::integrations::fred::ValkeyOptions) -> Result<Box<dyn crate::Output>, Error> {
let Command { diff, input, output } = self;
let value = match diff {
None => input.consume()?,
Some(diff) => {
let left = input.consume()?;
let right = diff.consume()?;
let patch = json_patch::diff(&left, &right);
serde_json::to_value(patch)?
}
};
output.produce(value, valkey).await?;
Ok(Box::new(()))
}
}