skytool 0.1.0-pre.2

an experimental API client for BlueSky / ATProto
Documentation
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(()))
  }
}