Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions apps/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@ npx @onequery/cli --help
onequery auth login
onequery org use <org>
onequery source list
onequery source update sentry://<key> --input credentials-patch.json
onequery source delete sentry://<key> --yes
onequery query exec --source postgres://<key> --sql "SELECT * FROM users LIMIT 10"
```

Source updates accept a partial credential document such as
`{"credentials":{"organizationSlug":"wordbricks"}}`. OneQuery retains omitted
secrets, validates and tests the merged credentials, and persists them only when
the connection test succeeds. Source deletion requires `--yes`.

## Profiles

OneQuery stores the default CLI auth session and config in `~/.onequery/auth.json`
Expand Down
24 changes: 24 additions & 0 deletions apps/cli/crates/onequery-cli/src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,30 @@ pub(crate) enum SourceSubcommand {
},
/// Show instructions or create a new source connection.
Connect(SourceConnectArgs),
/// Update one source's credentials from a JSON patch.
Update(SourceUpdateArgs),
/// Permanently delete one source.
Delete(SourceDeleteArgs),
}

#[derive(Debug, Clone, Args, Eq, PartialEq)]
pub(crate) struct SourceUpdateArgs {
/// Read {"credentials": {...}} from this file or stdin (`-`).
#[arg(long, value_hint = ValueHint::FilePath, value_name = "PATH|-")]
pub input: PathBuf,
/// Update this source.
#[arg(value_name = "SOURCE", value_parser = parse_source_reference)]
pub source: SourceReference,
}

#[derive(Debug, Clone, Args, Eq, PartialEq)]
pub(crate) struct SourceDeleteArgs {
/// Delete this source.
#[arg(value_name = "SOURCE", value_parser = parse_source_reference)]
pub source: SourceReference,
/// Confirm permanent deletion.
#[arg(long)]
pub yes: bool,
}

#[derive(Debug, Clone, Args, Eq, PartialEq)]
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/crates/onequery-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub(crate) use args::QueryValidateArgs;
pub(crate) use args::ReadArgs;
pub(crate) use args::RestoreArgs;
pub(crate) use args::SourceConnectArgs;
pub(crate) use args::SourceDeleteArgs;
pub(crate) use args::SourceSubcommand;
pub(crate) use args::SourceUpdateArgs;
pub(crate) use args::UpgradeArgs;
pub(crate) use model::Command;
pub(crate) use model::ConfigCommand;
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/crates/onequery-cli/src/cli/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ impl Command {
Self::Source(SourceSubcommand::Show { .. }) => "source show",
Self::Source(SourceSubcommand::Test { .. }) => "source test",
Self::Source(SourceSubcommand::Connect(_)) => "source connect",
Self::Source(SourceSubcommand::Update(_)) => "source update",
Self::Source(SourceSubcommand::Delete(_)) => "source delete",
Self::Query(QuerySubcommand::Execute(_)) => "query exec",
Self::Query(QuerySubcommand::Validate(_)) => "query validate",
Self::Restore(_) => "restore",
Expand Down
35 changes: 35 additions & 0 deletions apps/cli/crates/onequery-cli/src/cli_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,41 @@ fn parse_invocation_accepts_source_test_reference() {
));
}

#[test]
fn parse_invocation_accepts_source_update_input() {
let invocation = parse_invocation(&[
"onequery",
"source",
"update",
"sentry://errors",
"--input",
"patch.json",
]);

assert!(matches!(
invocation.command,
Command::Source(super::SourceSubcommand::Update(super::SourceUpdateArgs {
source,
input,
})) if source == test_source_reference("sentry://errors")
&& input == *"patch.json"
));
}

#[test]
fn parse_invocation_accepts_confirmed_source_delete() {
let invocation =
parse_invocation(&["onequery", "source", "delete", "sentry://errors", "--yes"]);

assert!(matches!(
invocation.command,
Command::Source(super::SourceSubcommand::Delete(super::SourceDeleteArgs {
source,
yes: true,
})) if source == test_source_reference("sentry://errors")
));
}

#[test]
fn parse_invocation_accepts_query_result_window_args() {
let invocation = parse_invocation(&[
Expand Down
1 change: 1 addition & 0 deletions apps/cli/crates/onequery-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod restore;
mod source;
mod source_api;
mod source_connect;
mod source_mutation;
mod source_providers;
#[cfg(test)]
pub(crate) mod test_support;
Expand Down
10 changes: 10 additions & 0 deletions apps/cli/crates/onequery-cli/src/commands/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ pub(super) async fn execute<B, T>(
return super::source_connect::execute(args, context, runtime).await;
}

if let SourceSubcommand::Update(args) = command {
return super::source_mutation::execute_update(args, context, runtime).await;
}

if let SourceSubcommand::Delete(args) = command {
return super::source_mutation::execute_delete(args, context, runtime).await;
}

let mode = match command {
SourceSubcommand::List { read } => SourceMode::List { read: read.clone() },
SourceSubcommand::Show { source_key, read } => SourceMode::Show {
Expand All @@ -150,6 +158,8 @@ pub(super) async fn execute<B, T>(
},
SourceSubcommand::Providers => unreachable!("source providers is delegated"),
SourceSubcommand::Connect(_) => unreachable!("source connect is delegated"),
SourceSubcommand::Update(_) => unreachable!("source update is delegated"),
SourceSubcommand::Delete(_) => unreachable!("source delete is delegated"),
};

let final_state = run_reducer_workflow(
Expand Down
Loading