use std::path::PathBuf;
use super::Cli;
use crate::commands;
use crate::commands::kv::key::{parse_metadata, KVMetaData};
use crate::settings::{global_user::GlobalUser, toml::Manifest};
use anyhow::{anyhow, Result};
use clap::ArgGroup;
use structopt::StructOpt;
#[derive(Debug, Clone, StructOpt)]
#[structopt(rename_all = "lower")]
pub enum KvNamespace {
Create {
#[structopt(index = 1)]
binding: String,
#[structopt(name = "preview", long)]
preview: bool,
},
Delete {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(name = "force", long, short = "f")]
force: bool,
},
List,
}
#[derive(Debug, Clone, StructOpt)]
#[structopt(group = ArgGroup::with_name("namespace-specifier").required(true))]
pub struct Namespace {
#[structopt(long, short = "b", group = "namespace-specifier")]
pub binding: Option<String>,
#[structopt(long, requires = "binding")]
pub preview: bool,
#[structopt(
name = "namespace-id",
long,
short = "n",
group = "namespace-specifier"
)]
pub namespace_id: Option<String>,
}
#[derive(Debug, Clone, StructOpt)]
#[structopt(rename_all = "lower")]
pub enum KvKey {
Put {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(name = "key", index = 1)]
key: String,
#[structopt(name = "value", index = 2)]
value: String,
#[structopt(name = "expiration-ttl", short = "t", long = "ttl")]
expiration_ttl: Option<u64>,
#[structopt(name = "expiration", long, short = "x")]
expiration: Option<u64>,
#[structopt(name = "metadata", long, short = "m")]
metadata: Option<String>,
#[structopt(name = "path", long, short = "p")]
path: bool,
},
Get {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(name = "key", index = 1)]
key: String,
},
Delete {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(name = "key", index = 1)]
key: String,
#[structopt(name = "force", long, short = "f")]
force: bool,
},
List {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(name = "prefix", long, short = "p")]
prefix: Option<String>,
},
}
#[derive(Debug, Clone, StructOpt)]
#[structopt(rename_all = "lower")]
pub enum KvBulk {
Put {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(index = 1)]
path: PathBuf,
},
Delete {
#[structopt(flatten)]
namespace: Namespace,
#[structopt(index = 1)]
path: PathBuf,
#[structopt(name = "force", long, short = "f")]
force: bool,
},
}
pub fn kv_namespace(namespace: KvNamespace, cli_params: &Cli) -> Result<()> {
let user = GlobalUser::new()?;
let manifest = Manifest::new(&cli_params.config)?;
let env = cli_params.environment.as_deref();
match namespace {
KvNamespace::Create { binding, preview } => {
commands::kv::namespace::create(&manifest, preview, env, &user, &binding)
}
KvNamespace::Delete { namespace, force } => {
let target = manifest.get_target(env, namespace.preview)?;
let id = if let Some(binding) = namespace.binding {
commands::kv::get_namespace_id(&target, &binding)?
} else {
namespace
.namespace_id
.expect("Namespace ID is required if binding isn't supplied")
};
commands::kv::namespace::delete(&target, &user, &id, force)
}
KvNamespace::List => {
let target = manifest.get_target(env, false)?;
commands::kv::namespace::list(&target, &user)
}
}
}
pub fn kv_key(key: KvKey, cli_params: &Cli) -> Result<()> {
let user = GlobalUser::new()?;
let manifest = Manifest::new(&cli_params.config)?;
let env = cli_params.environment.as_deref();
let target_and_namespace = |namespace: Namespace| -> Result<(_, _)> {
let target = manifest.get_target(env, namespace.preview)?;
let namespace_id = if let Some(binding) = namespace.binding {
commands::kv::get_namespace_id(&target, &binding)?
} else {
namespace
.namespace_id
.expect("Namespace ID is required if binding isn't supplied")
};
Ok((target, namespace_id))
};
match key {
KvKey::Get { namespace, key } => {
let (target, namespace_id) = target_and_namespace(namespace)?;
commands::kv::key::get(&target, &user, &namespace_id, &key)
}
KvKey::Put {
namespace,
key,
value,
path: is_file,
expiration_ttl,
expiration,
metadata,
} => {
let (target, namespace_id) = target_and_namespace(namespace)?;
let expiration = expiration.as_ref().map(ToString::to_string);
let expiration_ttl = expiration_ttl.as_ref().map(ToString::to_string);
let metadata = parse_metadata(metadata.as_deref())
.map_err(|e| anyhow!("--metadata is not valid JSON: {}", e.to_string()))?;
commands::kv::key::put(
&target,
&user,
KVMetaData {
namespace_id,
key,
value,
is_file,
expiration,
expiration_ttl,
metadata,
},
)
}
KvKey::Delete {
namespace,
key,
force,
} => {
let (target, namespace_id) = target_and_namespace(namespace)?;
commands::kv::key::delete(&target, &user, &namespace_id, &key, force)
}
KvKey::List { namespace, prefix } => {
let (target, namespace_id) = target_and_namespace(namespace)?;
commands::kv::key::list(&target, &user, &namespace_id, prefix.as_deref())
}
}
}
pub fn kv_bulk(bulk: KvBulk, cli_params: &Cli) -> Result<()> {
let manifest = Manifest::new(&cli_params.config)?;
let user = GlobalUser::new()?;
let env = cli_params.environment.as_deref();
let target_and_namespace = |namespace: Namespace| -> Result<(_, _)> {
let target = manifest.get_target(env, namespace.preview)?;
let namespace_id = if let Some(binding) = namespace.binding {
commands::kv::get_namespace_id(&target, &binding)?
} else {
namespace
.namespace_id
.expect("Namespace ID is required if binding isn't supplied")
};
Ok((target, namespace_id))
};
match bulk {
KvBulk::Put { namespace, path } => {
let (target, namespace_id) = target_and_namespace(namespace)?;
commands::kv::bulk::put(&target, &user, &namespace_id, &path)
}
KvBulk::Delete {
namespace,
path,
force,
} => {
let (target, namespace_id) = target_and_namespace(namespace)?;
commands::kv::bulk::delete(&target, &user, &namespace_id, &path, force)
}
}
}