Skip to content
Open
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: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@

# Logs
*.log
docs/agents/

# Local Claude notes (gitignored per-repo configuration)
CLAUDE.local.md
15 changes: 2 additions & 13 deletions src/commands/endpoint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use quicknode_sdk::admin::{
UpdateEndpointRequest, UpdateEndpointStatusRequest,
};

use crate::confirm::{decide_without_prompt, prompt_yes_no, ConfirmCfg, Severity};
use crate::confirm;
use crate::context::Ctx;
use crate::errors::CliError;
use crate::time_arg;
Expand Down Expand Up @@ -266,18 +266,7 @@ async fn update(a: UpdateArgs, ctx: Ctx) -> Result<(), CliError> {
}

async fn archive(a: ArchiveArgs, ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Mild, cfg)? {
true => true,
false => prompt_yes_no(&format!("Archive endpoint {}?", a.id))?,
};
if !proceed {
return Err(CliError::Cancelled);
}
confirm::mild(&ctx, &format!("Archive endpoint {}?", a.id))?;
ctx.sdk.admin.archive_endpoint(&a.id).await?;
ctx.out.note(&format!("✓ Archived endpoint {}", a.id));
Ok(())
Expand Down
16 changes: 10 additions & 6 deletions src/commands/kv/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ pub(super) async fn set(cmd: SetCmd, ctx: Ctx) -> Result<(), CliError> {
crate::output::emit(&ctx.out, &SetsView(resp))?;
}
SetCmd::Delete { key } => {
super::confirm_mild(&ctx, &format!("Delete set {key:?}?"))?;
ctx.sdk.kvstore.delete_set(&key).await?;
ctx.out.note(&format!("✓ Deleted set {key:?}"));
let kvstore = &ctx.sdk.kvstore;
crate::destroy::single(&ctx, "set", &format!("{key:?}"), || {
kvstore.delete_set(&key)
})
.await?;
}
SetCmd::Bulk(a) => {
if a.add.is_empty() && a.delete.is_empty() {
Expand Down Expand Up @@ -165,9 +167,11 @@ pub(super) async fn list(cmd: ListCmd, ctx: Ctx) -> Result<(), CliError> {
ctx.out.note(&format!("✓ Updated list {:?}", a.key));
}
ListCmd::Delete { key } => {
super::confirm_mild(&ctx, &format!("Delete list {key:?}?"))?;
ctx.sdk.kvstore.delete_list(&key).await?;
ctx.out.note(&format!("✓ Deleted list {key:?}"));
let kvstore = &ctx.sdk.kvstore;
crate::destroy::single(&ctx, "list", &format!("{key:?}"), || {
kvstore.delete_list(&key)
})
.await?;
}
}
Ok(())
Expand Down
17 changes: 0 additions & 17 deletions src/commands/kv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::io::{IsTerminal, Read};

use clap::{Args as ClapArgs, Subcommand};

use crate::confirm::{decide_without_prompt, prompt_yes_no, ConfirmCfg, Severity};
use crate::context::Ctx;
use crate::errors::CliError;

Expand Down Expand Up @@ -114,22 +113,6 @@ pub async fn run(args: Args, ctx: Ctx) -> Result<(), CliError> {
}
}

fn confirm_mild(ctx: &Ctx, prompt: &str) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Mild, cfg)? {
true => true,
false => prompt_yes_no(prompt)?,
};
if !proceed {
return Err(CliError::Cancelled);
}
Ok(())
}

fn read_stdin() -> Result<String, CliError> {
if std::io::stdin().is_terminal() {
return Err(CliError::Arg(
Expand Down
39 changes: 5 additions & 34 deletions src/commands/stream/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use quicknode_sdk::streams::{

use super::render::{StreamView, StreamsListView, TestFilterView};
use super::{CreateArgs, ListArgs, TestFilterArgs, UpdateArgs};
use crate::confirm::{decide_without_prompt, prompt_typed, prompt_yes_no, ConfirmCfg, Severity};
use crate::context::Ctx;
use crate::destroy;
use crate::errors::CliError;

pub(super) async fn list(a: ListArgs, ctx: Ctx) -> Result<(), CliError> {
Expand Down Expand Up @@ -130,42 +130,13 @@ pub(super) async fn update(a: UpdateArgs, ctx: Ctx) -> Result<(), CliError> {
}

pub(super) async fn delete(id: &str, ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Mild, cfg)? {
true => true,
false => prompt_yes_no(&format!("Delete stream {id}?"))?,
};
if !proceed {
return Err(CliError::Cancelled);
}
ctx.sdk.streams.delete_stream(id).await?;
ctx.out.note(&format!("✓ Deleted stream {id}"));
Ok(())
let streams = &ctx.sdk.streams;
destroy::single(&ctx, "stream", id, || streams.delete_stream(id)).await
}

pub(super) async fn delete_all(ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Severe, cfg)? {
true => true,
false => prompt_typed(
"Type 'delete-all' to delete EVERY stream on the account",
"delete-all",
)?,
};
if !proceed {
return Err(CliError::Cancelled);
}
ctx.sdk.streams.delete_all_streams().await?;
ctx.out.note("✓ Deleted all streams");
Ok(())
let streams = &ctx.sdk.streams;
destroy::all(&ctx, "stream", "streams", || streams.delete_all_streams()).await
}

pub(super) async fn activate(id: &str, ctx: Ctx) -> Result<(), CliError> {
Expand Down
22 changes: 6 additions & 16 deletions src/commands/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use comfy_table::Cell;
use quicknode_sdk::admin::RenameTagRequest;
use serde::Serialize;

use crate::confirm::{decide_without_prompt, prompt_yes_no, ConfirmCfg, Severity};
use crate::context::Ctx;
use crate::destroy;
use crate::errors::CliError;
use crate::output::{new_table, set_header_bold, write_table, Render};

Expand Down Expand Up @@ -58,21 +58,11 @@ async fn rename(tag_id: i32, label: String, ctx: Ctx) -> Result<(), CliError> {
}

async fn delete(id: i32, ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Mild, cfg)? {
true => true,
false => prompt_yes_no(&format!("Delete tag {id}?"))?,
};
if !proceed {
return Err(CliError::Cancelled);
}
ctx.sdk.admin.delete_account_tag(id).await?;
ctx.out.note(&format!("✓ Deleted tag {id}"));
Ok(())
let admin = &ctx.sdk.admin;
destroy::single(&ctx, "tag", &id.to_string(), || {
admin.delete_account_tag(id)
})
.await
}

#[derive(Serialize)]
Expand Down
19 changes: 3 additions & 16 deletions src/commands/team.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use quicknode_sdk::admin::{
};
use serde::Serialize;

use crate::confirm::{decide_without_prompt, prompt_yes_no, ConfirmCfg, Severity};
use crate::context::Ctx;
use crate::destroy;
use crate::errors::CliError;
use crate::output::{new_table, opt_cell, set_header_bold, write_table, Render};

Expand Down Expand Up @@ -142,21 +142,8 @@ async fn show(id: i64, ctx: Ctx) -> Result<(), CliError> {
}

async fn delete(id: i64, ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Mild, cfg)? {
true => true,
false => prompt_yes_no(&format!("Delete team {id}?"))?,
};
if !proceed {
return Err(CliError::Cancelled);
}
ctx.sdk.admin.delete_team(id).await?;
ctx.out.note(&format!("✓ Deleted team {id}"));
Ok(())
let admin = &ctx.sdk.admin;
destroy::single(&ctx, "team", &id.to_string(), || admin.delete_team(id)).await
}

async fn endpoints(id: i64, ctx: Ctx) -> Result<(), CliError> {
Expand Down
42 changes: 8 additions & 34 deletions src/commands/webhook/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use quicknode_sdk::webhooks::{

use super::render::{WebhookView, WebhooksListView};
use super::{ActivateArgs, CreateArgs, ListArgs, TemplateKind, UpdateArgs, UpdateTemplateArgs};
use crate::confirm::{decide_without_prompt, prompt_typed, prompt_yes_no, ConfirmCfg, Severity};
use crate::context::Ctx;
use crate::destroy;
use crate::errors::CliError;

pub(super) async fn list(a: ListArgs, ctx: Ctx) -> Result<(), CliError> {
Expand Down Expand Up @@ -126,42 +126,16 @@ pub(super) async fn update_template(a: UpdateTemplateArgs, ctx: Ctx) -> Result<(
}

pub(super) async fn delete(id: &str, ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Mild, cfg)? {
true => true,
false => prompt_yes_no(&format!("Delete webhook {id}?"))?,
};
if !proceed {
return Err(CliError::Cancelled);
}
ctx.sdk.webhooks.delete_webhook(id).await?;
ctx.out.note(&format!("✓ Deleted webhook {id}"));
Ok(())
let webhooks = &ctx.sdk.webhooks;
destroy::single(&ctx, "webhook", id, || webhooks.delete_webhook(id)).await
}

pub(super) async fn delete_all(ctx: Ctx) -> Result<(), CliError> {
let cfg = ConfirmCfg::new(
ctx.global.yes_count,
ctx.global.no_input,
ctx.out.stdout_is_tty,
);
let proceed = match decide_without_prompt(Severity::Severe, cfg)? {
true => true,
false => prompt_typed(
"Type 'delete-all' to delete EVERY webhook on the account",
"delete-all",
)?,
};
if !proceed {
return Err(CliError::Cancelled);
}
ctx.sdk.webhooks.delete_all_webhooks().await?;
ctx.out.note("✓ Deleted all webhooks");
Ok(())
let webhooks = &ctx.sdk.webhooks;
destroy::all(&ctx, "webhook", "webhooks", || {
webhooks.delete_all_webhooks()
})
.await
}

pub(super) async fn activate(a: ActivateArgs, ctx: Ctx) -> Result<(), CliError> {
Expand Down
Loading
Loading