Skip to content

Commit 5c4c1b1

Browse files
committed
fix: finalization on error and empty-state hint rendering
1. command.ts: Move writeFinalization out of finally block. On error, finalize only in human mode (to close streaming table) before handleOutputError. Prevents corrupting JSON output or writing footer after process.exit(). 2. log/list.ts: When no logs were rendered (headerEmitted=false), render hint as primary text instead of muted footer. Preserves the 'No logs found.' UX from before the refactor.
1 parent 945956a commit 5c4c1b1

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

src/commands/log/list.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,14 @@ function createLogRenderer(): HumanRenderer<LogListResult> {
460460
text += table.footer();
461461
}
462462

463-
// Append hint (count, pagination, empty-state message)
464463
if (hint) {
465-
text += `${text ? "\n" : ""}${formatFooter(hint)}`;
464+
if (headerEmitted) {
465+
// Logs were rendered — show hint as a muted footer
466+
text += `${text ? "\n" : ""}${formatFooter(hint)}`;
467+
} else {
468+
// No logs rendered — show hint as primary output (e.g., "No logs found.")
469+
text += `${hint}\n`;
470+
}
466471
}
467472

468473
return text;

src/lib/command.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ export function buildCommand<
462462
// Iterate the generator using manual .next() instead of for-await-of
463463
// so we can capture the return value (done: true result). The return
464464
// value carries the final `hint` — for-await-of discards it.
465-
let hint: string | undefined;
466465
try {
467466
const generator = originalFunc.call(
468467
this,
@@ -475,15 +474,17 @@ export function buildCommand<
475474
result = await generator.next();
476475
}
477476

477+
// Generator completed successfully — finalize with hint.
478478
const returned = result.value as CommandReturn | undefined;
479-
hint = returned?.hint;
479+
writeFinalization(stdout, returned?.hint, cleanFlags.json, renderer);
480480
} catch (err) {
481+
// Finalize before error handling to close streaming state
482+
// (e.g., table footer). No hint since the generator didn't
483+
// complete. Only in human mode — JSON must not be corrupted.
484+
if (!cleanFlags.json) {
485+
writeFinalization(stdout, undefined, false, renderer);
486+
}
481487
handleOutputError(err);
482-
} finally {
483-
// Always finalize: close streaming state (e.g., table footer)
484-
// even if the generator threw. Without this, a mid-stream error
485-
// leaves partial output (e.g., table without bottom border).
486-
writeFinalization(stdout, hint, cleanFlags.json, renderer);
487488
}
488489
};
489490

0 commit comments

Comments
 (0)