mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 12:54:29 +00:00
fix(cli): cloud delete --no-confirm and cloud render --no-wait (#1112)
Both flags were silently broken via the same root cause: citty parses
`--no-FOO` as a negation of the base flag `FOO`, so a flag literally
named "no-confirm" gets routed as `args.confirm=false` (not
`args["no-confirm"]=true`), and same for "no-wait".
Surfaced during the end-to-end smoke test on the just-merged stack:
- `cloud delete <id> --no-confirm` was hitting "Confirmation required"
and exiting 1 without calling the API.
- `cloud render --no-wait` was running the full poll + download flow
instead of submitting and exiting with the render_id.
Renamed the arg keys to `confirm` (default true) and `wait` (default
true) so citty's built-in negation handles the user-facing flags
correctly. Flag names stay the same; only the runtime arg keys change.
Live-tested both: delete now removes the render and a subsequent get
404s; --no-wait now returns just {render_id, status: "queued"} and
exits.
Note: a third instance of the same pattern exists in commands/add.ts
(`--no-clipboard`) and is also latently broken. Out of scope for this
fix; should be addressed alongside any audit of the CLI's interactive-
vs-noninteractive defaults.
This commit is contained in:
@@ -25,15 +25,23 @@ export default defineCommand({
|
||||
description: "Emit machine-readable JSON",
|
||||
default: false,
|
||||
},
|
||||
"no-confirm": {
|
||||
// Citty intercepts the `--no-` prefix as a negation of the base
|
||||
// flag, so a flag literally named "no-confirm" gets parsed as
|
||||
// `--confirm=false` and the `args["no-confirm"]` lookup never
|
||||
// sees `true`. Naming the flag `confirm` with `default: true` lets
|
||||
// citty's negation handle `--no-confirm` correctly — same
|
||||
// user-facing flag (`--no-confirm` to skip the prompt), correct
|
||||
// runtime semantics.
|
||||
confirm: {
|
||||
type: "boolean",
|
||||
description: "Skip the interactive confirmation prompt (required for scripts and --json)",
|
||||
default: false,
|
||||
description:
|
||||
"Prompt before deleting (default: true). Pass `--no-confirm` to skip — required for scripts and --json.",
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
// fallow-ignore-next-line complexity
|
||||
async run({ args }) {
|
||||
if (!args["no-confirm"]) {
|
||||
if (args.confirm) {
|
||||
// Don't auto-bypass the prompt just because stdin isn't a TTY
|
||||
// or `--json` was passed — both used to silently skip the
|
||||
// safety check. Force the caller to opt in via `--no-confirm`
|
||||
|
||||
@@ -141,10 +141,17 @@ export default defineCommand({
|
||||
description:
|
||||
"Public HTTPS URL of a composition zip. Mutually exclusive with --asset-id and the project dir.",
|
||||
},
|
||||
"no-wait": {
|
||||
// Citty parses `--no-FOO` as `--FOO=false`. A flag literally named
|
||||
// "no-wait" gets routed as `args.wait=false`, leaving
|
||||
// `args["no-wait"]` undefined and the early-return for
|
||||
// fire-and-forget mode unreachable. Named the arg `wait` so the
|
||||
// user-facing `--no-wait` flag works via citty's negation; the
|
||||
// run() body checks `if (!args.wait)`.
|
||||
wait: {
|
||||
type: "boolean",
|
||||
description: "Submit and exit; print the render_id to stdout",
|
||||
default: false,
|
||||
description:
|
||||
"Poll until completion and download the video (default: true). Pass `--no-wait` for fire-and-forget — submits and exits with the render_id.",
|
||||
default: true,
|
||||
},
|
||||
output: {
|
||||
type: "string",
|
||||
@@ -216,7 +223,7 @@ export default defineCommand({
|
||||
});
|
||||
|
||||
const renderId = submitted.render_id;
|
||||
if (args["no-wait"]) {
|
||||
if (!args.wait) {
|
||||
if (asJson) {
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
|
||||
Reference in New Issue
Block a user