docs: document cli shared helpers

This commit is contained in:
Peter Steinberger
2026-06-03 18:23:23 -04:00
parent 90b8b41c41
commit 4f4cd2e8ae
7 changed files with 29 additions and 0 deletions
+9
View File
@@ -1,3 +1,4 @@
// Terminal progress reporter used by long-running CLI commands.
import { spinner } from "@clack/prompts";
import {
createOscProgressController,
@@ -12,6 +13,7 @@ import { theme } from "../../packages/terminal-core/src/theme.js";
import { resolveTimerTimeoutMs } from "../shared/number-coercion.js";
const DEFAULT_DELAY_MS = 0;
// Only one active progress renderer may own the terminal line at a time.
let activeProgress = 0;
type ProgressOptions = {
@@ -24,6 +26,7 @@ type ProgressOptions = {
fallback?: "spinner" | "line" | "log" | "none";
};
/** Minimal progress API exposed to CLI work callbacks. */
export type ProgressReporter = {
setLabel: (label: string) => void;
setPercent: (percent: number) => void;
@@ -31,12 +34,14 @@ export type ProgressReporter = {
done: () => void;
};
/** Completed/total progress update shape used by totals-based commands. */
export type ProgressTotalsUpdate = {
completed: number;
total: number;
label?: string;
};
/** Decide whether the interactive spinner is safe for the current terminal state. */
export function shouldUseInteractiveProgressSpinner(params: {
fallback?: ProgressOptions["fallback"];
streamIsTty?: boolean;
@@ -53,6 +58,7 @@ const noopReporter: ProgressReporter = {
done: () => {},
};
/** Create a no-op, spinner, line, log, and OSC-capable progress reporter. */
export function createCliProgress(options: ProgressOptions): ProgressReporter {
if (options.enabled === false) {
return noopReporter;
@@ -78,6 +84,7 @@ export function createCliProgress(options: ProgressOptions): ProgressReporter {
});
const allowLine = isTty && options.fallback === "line";
if (isTty && stdinIsRaw && (options.fallback === undefined || options.fallback === "spinner")) {
// Raw stdin usually means an interactive prompt owns cursor movement.
return noopReporter;
}
@@ -223,6 +230,7 @@ export function createCliProgress(options: ProgressOptions): ProgressReporter {
return { setLabel, setPercent, tick, done };
}
/** Run async work with a progress reporter that is always stopped in finally. */
export async function withProgress<T>(
options: ProgressOptions,
work: (progress: ProgressReporter) => Promise<T>,
@@ -235,6 +243,7 @@ export async function withProgress<T>(
}
}
/** Run async work with a progress reporter plus a completed/total update adapter. */
export async function withProgressTotals<T>(
options: ProgressOptions,
work: (update: (update: ProgressTotalsUpdate) => void, progress: ProgressReporter) => Promise<T>,