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: 2 additions & 2 deletions rust/Cargo.lock

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

2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async-trait = "0.1"
bytes = "1"
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
clap = { version = "4.5", features = ["std", "string", "derive"] }
cli-engine = { version = "0.9.5", features = ["pkce-auth"] }
cli-engine = { version = "0.10.0", features = ["pkce-auth"] }
dirs = "6"
domains-client = { path = "domains-client" }
hosting-client = { path = "hosting-client" }
Expand Down
6 changes: 3 additions & 3 deletions rust/src/api/graphql/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ pub(super) fn command() -> RuntimeCommandSpec {
TableColumn::new("summary", "Summary"),
TableColumn::new("returnType", "Return Type"),
TableColumn::new("returnFields", "Return Fields").nested(vec![
TableColumn::new("name", "Name"),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("type", "Type"),
Comment thread
jpage-godaddy marked this conversation as resolved.
TableColumn::new("description", "Description"),
]),
TableColumn::new("callRequirements", "Call Requirements").nested(vec![
TableColumn::new("name", "Name"),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("in", "In"),
TableColumn::new("required", "Required"),
TableColumn::new("type", "Type"),
TableColumn::new("description", "Description"),
]),
TableColumn::new("arguments", "Arguments").nested(vec![
TableColumn::new("name", "Name"),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("required", "Required"),
TableColumn::new("type", "Type"),
TableColumn::new("description", "Description"),
Expand Down
2 changes: 1 addition & 1 deletion rust/src/api/graphql/type_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn get_command() -> RuntimeCommandSpec {
TableColumn::new("name", "Name"),
TableColumn::new("kind", "Kind"),
TableColumn::new("fields", "Fields").nested(vec![
TableColumn::new("name", "Name"),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("type", "Type"),
Comment thread
jpage-godaddy marked this conversation as resolved.
TableColumn::new("description", "Description"),
]),
Expand Down
4 changes: 2 additions & 2 deletions rust/src/api/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,15 @@ pub(super) fn get_command() -> RuntimeCommandSpec {
TableColumn::new("path", "Path"),
TableColumn::new("summary", "Summary"),
TableColumn::new("parameters.items", "Parameters").nested(vec![
TableColumn::new("name", "Name"),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("in", "In"),
TableColumn::new("required", "Required"),
TableColumn::new("type", "Type"),
Comment thread
jpage-godaddy marked this conversation as resolved.
TableColumn::new("schemaId", "Schema ID"),
TableColumn::new("description", "Description"),
]),
TableColumn::new("responses.items", "Responses").nested(vec![
TableColumn::new("status", "Status"),
TableColumn::new("status", "Status").essential(true),
TableColumn::new("type", "Type"),
TableColumn::new("schemaId", "Schema ID"),
TableColumn::new("description", "Description"),
Expand Down
2 changes: 1 addition & 1 deletion rust/src/api/parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub(super) fn list_command() -> RuntimeCommandSpec {
parameter's full details.",
)
.with_view(vec![
TableColumn::new("name", "Name"),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("in", "In"),
TableColumn::new("required", "Required"),
TableColumn::new("type", "Type"),
Comment thread
jpage-godaddy marked this conversation as resolved.
Expand Down
2 changes: 1 addition & 1 deletion rust/src/api/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub(super) fn list_command() -> RuntimeCommandSpec {
full detail.",
)
.with_view(vec![
TableColumn::new("status", "Status"),
TableColumn::new("status", "Status").essential(true),
TableColumn::new("type", "Type"),
Comment thread
jpage-godaddy marked this conversation as resolved.
TableColumn::new("schemaId", "Schema ID"),
TableColumn::new("description", "Description"),
Expand Down
9 changes: 4 additions & 5 deletions rust/src/dns/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ fn summarize_add_outcomes(
/// `--fields all`).
fn view_columns() -> Vec<TableColumn> {
vec![
TableColumn::new("domain", "Domain"),
TableColumn::new("domain", "Domain").essential(true),
TableColumn::new("type", "Type"),
TableColumn::new("name", "Name"),
TableColumn::new("created", "Created").align(Alignment::Right),
TableColumn::new("failed", "Failed").align(Alignment::Right),
TableColumn::new("results", "Results").nested(vec![
TableColumn::new("data", "Data"),
TableColumn::new("status", "Status"),
TableColumn::new("data", "Data").essential(true),
TableColumn::new("status", "Status").essential(true),
TableColumn::new("error", "Error"),
]),
TableColumn::new("action", "Action"),
Expand Down Expand Up @@ -220,8 +220,7 @@ mod tests {
vec![("1.2.3.4".to_string(), Ok(()))],
)
.expect("all created -> success payload");
let envelope = cli_engine::Envelope::success(payload, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(payload, &view_columns());
assert!(rendered.contains("Results:"), "{rendered}");
assert!(rendered.contains("1.2.3.4"), "{rendered}");
assert!(rendered.contains("created"), "{rendered}");
Expand Down
7 changes: 3 additions & 4 deletions rust/src/dns/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ fn view_columns() -> Vec<TableColumn> {
TableColumn::new("action", "Action"),
TableColumn::new("records", "Records").nested(vec![
TableColumn::new("recordId", "Record ID"),
TableColumn::new("data", "Data"),
TableColumn::new("status", "Status"),
TableColumn::new("data", "Data").essential(true),
TableColumn::new("status", "Status").essential(true),
]),
]
}
Expand Down Expand Up @@ -392,8 +392,7 @@ mod tests {
fn dry_run_delete_preview_renders_records_as_a_nested_table() {
let existing = vec![test_record("r1", "1.2.3.4")];
let preview = dry_run_delete_preview("example.com", "A", "www", &existing);
let envelope = cli_engine::Envelope::success(preview, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(preview, &view_columns());
assert!(rendered.contains("Records:"), "{rendered}");
assert!(rendered.contains("RECORD ID"), "{rendered}");
assert!(rendered.contains("r1"), "{rendered}");
Expand Down
50 changes: 49 additions & 1 deletion rust/src/dns/list.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! `dns list` — list DNS records for a domain, with optional type/name filters.

use cli_engine::{
CliCoreError, CommandResult, CommandSpec, PaginationConfig, RuntimeCommandSpec, Tier,
Alignment, CliCoreError, CommandResult, CommandSpec, PaginationConfig, RuntimeCommandSpec,
TableColumn, Tier,
};
use serde_json::{Value, json};

Expand All @@ -28,6 +29,31 @@ struct ListArgs {
name: Option<String>,
}

/// A record is unreadable without its type/name/data, so those three are
/// `essential` — never hidden or shrunk for width, even on a narrow terminal
/// — while the rest are nice-to-haves that still yield to width pressure.
fn view_columns() -> Vec<TableColumn> {
vec![
TableColumn::new("type", "Type").essential(true),
TableColumn::new("name", "Name").essential(true),
TableColumn::new("data", "Data").essential(true),
TableColumn::new("ttl", "TTL").align(Alignment::Right),
TableColumn::new("priority", "Priority").align(Alignment::Right),
TableColumn::new("recordId", "Record ID"),
TableColumn::new("service", "Service"),
TableColumn::new("protocol", "Protocol"),
TableColumn::new("port", "Port").align(Alignment::Right),
TableColumn::new("weight", "Weight").align(Alignment::Right),
TableColumn::new("tag", "Tag"),
TableColumn::new("flag", "Flag").align(Alignment::Right),
TableColumn::new("usage", "Usage"),
TableColumn::new("selector", "Selector"),
TableColumn::new("matchingType", "Matching Type"),
TableColumn::new("certificateData", "Certificate Data").no_truncate(true),
TableColumn::new("parameters", "Parameters"),
]
}

pub(super) fn command() -> RuntimeCommandSpec {
RuntimeCommandSpec::new_typed_with_context::<ListArgs, _, _, _>(
CommandSpec::from_args::<ListArgs>("list", "List DNS records for a domain")
Expand All @@ -40,6 +66,7 @@ pub(super) fn command() -> RuntimeCommandSpec {
.with_tier(Tier::Read)
.with_default_fields("type,name,data,ttl")
.with_json_schema::<types::DnsRecord>()
.with_view(view_columns())
.with_scopes(&[DOMAINS_READ])
.with_pagination(PaginationConfig {
max_limit: 500,
Expand Down Expand Up @@ -106,6 +133,27 @@ mod tests {
);
}

/// `view_columns()` declares 17 columns — far more than fit an
/// 80-column terminal (the fixed width non-TTY test runs get) once
/// their headers are laid out side by side. Type/name/data must survive
/// that squeeze regardless, since a record is unreadable without them;
/// everything else is free to be hidden.
#[test]
fn essential_fields_survive_width_based_hiding() {
let out = build_list_output(&[a_record()]).expect("serializes");

let rendered = cli_engine::preview_human_view(out, &view_columns());

let header_line = rendered.lines().next().expect("header line");
assert!(header_line.contains("TYPE"), "{rendered}");
assert!(header_line.contains("NAME"), "{rendered}");
assert!(header_line.contains("DATA"), "{rendered}");
assert!(
rendered.contains("hidden to fit the display width"),
"fixture must actually overflow 80 columns to exercise hiding: {rendered}"
);
}

fn a_record() -> types::DnsRecord {
types::DnsRecord {
certificate_data: None,
Expand Down
4 changes: 2 additions & 2 deletions rust/src/dns/set/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ fn view_columns() -> Vec<TableColumn> {
TableColumn::new("deleted", "Deleted").align(Alignment::Right),
TableColumn::new("action", "Action"),
TableColumn::new("plan", "Plan").nested(vec![
TableColumn::new("action", "Action"),
TableColumn::new("action", "Action").essential(true),
TableColumn::new("recordId", "Record ID"),
TableColumn::new("data", "Data"),
TableColumn::new("data", "Data").essential(true),
]),
]
}
Expand Down
4 changes: 1 addition & 3 deletions rust/src/dns/set/outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,7 @@ mod tests {
&["9.9.9.9".to_string(), "8.8.8.8".to_string()],
);
let preview = dry_run_set_preview("example.com", "A", "www", &plan);
let envelope = cli_engine::Envelope::success(preview, "domain");
let rendered =
cli_engine::render_human_with_view(&envelope, Some(&super::super::view_columns()), "");
let rendered = cli_engine::preview_human_view(preview, &super::super::view_columns());
assert!(rendered.contains("Plan:"), "{rendered}");
assert!(rendered.contains("RECORD ID"), "{rendered}");
assert!(rendered.contains("replace"), "{rendered}");
Expand Down
2 changes: 1 addition & 1 deletion rust/src/domain/agreements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(super) fn command() -> RuntimeCommandSpec {
.with_view(vec![
TableColumn::new("agreementKey", "Agreement Key"),
TableColumn::new("title", "Title"),
TableColumn::new("url", "URL").no_truncate(true),
TableColumn::new("url", "URL").essential(true),
Comment thread
jpage-godaddy marked this conversation as resolved.
])
.with_json_schema::<types::V1LegalAgreement>()
.with_scopes(&[DOMAINS_READ]),
Expand Down
14 changes: 7 additions & 7 deletions rust/src/domain/available.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ fn view_columns() -> Vec<TableColumn> {
TableColumn::new("currency", "Currency"),
TableColumn::new("inventory", "Inventory"),
TableColumn::new("terms", "Terms").nested(vec![
TableColumn::new("periodLabel", "Period"),
TableColumn::new("price", "Price").align(Alignment::Right),
TableColumn::new("periodLabel", "Period").essential(true),
TableColumn::new("price", "Price")
.align(Alignment::Right)
.essential(true),
TableColumn::new("firstTermPrice", "First-Term Price").align(Alignment::Right),
TableColumn::new("renewalPrice", "Renewal Price").align(Alignment::Right),
TableColumn::new("fees", "Fees"),
TableColumn::new("fees", "Fees").essential(true),
]),
]
}
Expand Down Expand Up @@ -280,8 +282,7 @@ mod tests {
},
],
});
let envelope = cli_engine::Envelope::success(available, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(available, &view_columns());
assert!(rendered.contains("Terms:"), "{rendered}");
assert!(rendered.contains("1 year"), "{rendered}");
assert!(rendered.contains("2 years"), "{rendered}");
Expand Down Expand Up @@ -344,8 +345,7 @@ mod tests {
"definitive": true,
"inventory": "PREMIUM",
});
let envelope = cli_engine::Envelope::success(available, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(available, &view_columns());
assert!(rendered.contains("Inventory:"), "{rendered}");
assert!(rendered.contains("PREMIUM"), "{rendered}");
}
Expand Down
29 changes: 14 additions & 15 deletions rust/src/domain/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,17 @@ fn view_columns() -> Vec<TableColumn> {
TableColumn::new("irreversible", "Irreversible"),
TableColumn::new("inventory", "Inventory"),
TableColumn::new("fees", "Fees").nested(vec![
TableColumn::new("type", "Type"),
TableColumn::new("amount", "Amount").align(Alignment::Right),
TableColumn::new("currency", "Currency"),
TableColumn::new("type", "Type").essential(true),
TableColumn::new("amount", "Amount")
.align(Alignment::Right)
.essential(true),
TableColumn::new("currency", "Currency").essential(true),
]),
TableColumn::new("agreements", "Agreements"),
TableColumn::new("requiredAgreements", "Required Agreements").nested(vec![
TableColumn::new("agreementType", "Type"),
TableColumn::new("title", "Title"),
TableColumn::new("url", "URL").no_truncate(true),
TableColumn::new("url", "URL").essential(true),
Comment thread
jpage-godaddy marked this conversation as resolved.
]),
TableColumn::new("resolved", "Resolved Settings").nested(vec![
TableColumn::new("contactSource", "Contact Source"),
Expand Down Expand Up @@ -506,8 +508,7 @@ mod tests {
"period": 1,
"periodLabel": "1 year",
});
let envelope = cli_engine::Envelope::success(quote, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(quote, &view_columns());
assert!(rendered.contains("1 year"), "{rendered}");
}

Expand All @@ -517,9 +518,10 @@ mod tests {
/// `quote_to_json`, and `resolved` is `ResolvedSettings` serialized via
/// serde, whose `#[serde(rename = ...)]` attributes were cross-checked
/// for the field names used below) as nested blocks — a mismatch would
/// silently drop them from `--fields all` output. Renders a hand-built
/// envelope rather than calling `quote_to_json`, which would need a
/// live `RegistrationQuote` built through its generated builder.
/// silently drop them from `--fields all` output. Renders hand-built
/// fixture data through the view rather than calling `quote_to_json`,
/// which would need a live `RegistrationQuote` built through its
/// generated builder.
#[test]
fn quote_result_renders_required_agreements_and_resolved_as_nested_blocks() {
let quote = json!({
Expand All @@ -536,8 +538,7 @@ mod tests {
"nameServers": ["ns01.domaincontrol.com", "ns02.domaincontrol.com"],
},
});
let envelope = cli_engine::Envelope::success(quote, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(quote, &view_columns());
assert!(rendered.contains("Required Agreements:"), "{rendered}");
assert!(rendered.contains("Registration Agreement"), "{rendered}");
assert!(rendered.contains("Resolved Settings:"), "{rendered}");
Expand All @@ -560,8 +561,7 @@ mod tests {
{"type": "ONE_TIME_PREMIUM_DOMAIN_PURCHASE", "amount": "3900.00", "currency": "USD"},
],
});
let envelope = cli_engine::Envelope::success(quote, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(quote, &view_columns());
assert!(rendered.contains("Inventory:"), "{rendered}");
assert!(rendered.contains("PREMIUM"), "{rendered}");
assert!(rendered.contains("Fees:"), "{rendered}");
Expand All @@ -582,8 +582,7 @@ mod tests {
"domain": "example.com",
"available": true,
});
let envelope = cli_engine::Envelope::success(quote, "domain");
let rendered = cli_engine::render_human_with_view(&envelope, Some(&view_columns()), "");
let rendered = cli_engine::preview_human_view(quote, &view_columns());
assert!(!rendered.contains("null"), "{rendered}");
}
}
Loading
Loading