fix(cli): keep progress spinners out of active TUI input

This commit is contained in:
Radek Sienkiewicz
2026-04-30 11:26:21 +02:00
parent 9cb71f7672
commit 0f8b5167be
2 changed files with 33 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from "vitest";
import { createCliProgress } from "./progress.js";
import { createCliProgress, shouldUseInteractiveProgressSpinner } from "./progress.js";
describe("cli progress", () => {
it("logs progress when non-tty and fallback=log", () => {
@@ -43,4 +43,22 @@ describe("cli progress", () => {
expect(write).not.toHaveBeenCalled();
});
it("does not use readline-backed spinners while raw TUI input is active", () => {
expect(
shouldUseInteractiveProgressSpinner({
streamIsTty: true,
stdinIsRaw: true,
}),
).toBe(false);
});
it("keeps the normal interactive spinner for regular tty commands", () => {
expect(
shouldUseInteractiveProgressSpinner({
streamIsTty: true,
stdinIsRaw: false,
}),
).toBe(true);
});
});

View File

@@ -33,6 +33,15 @@ export type ProgressTotalsUpdate = {
label?: string;
};
export function shouldUseInteractiveProgressSpinner(params: {
fallback?: ProgressOptions["fallback"];
streamIsTty?: boolean;
stdinIsRaw?: boolean;
}): boolean {
const spinnerRequested = params.fallback === undefined || params.fallback === "spinner";
return spinnerRequested && params.streamIsTty === true && params.stdinIsRaw !== true;
}
const noopReporter: ProgressReporter = {
setLabel: () => {},
setPercent: () => {},
@@ -57,7 +66,11 @@ export function createCliProgress(options: ProgressOptions): ProgressReporter {
const delayMs = typeof options.delayMs === "number" ? options.delayMs : DEFAULT_DELAY_MS;
const canOsc = isTty && supportsOscProgress(process.env, isTty);
const allowSpinner = isTty && (options.fallback === undefined || options.fallback === "spinner");
const allowSpinner = shouldUseInteractiveProgressSpinner({
fallback: options.fallback,
streamIsTty: isTty,
stdinIsRaw: process.stdin.isRaw,
});
const allowLine = isTty && options.fallback === "line";
let started = false;