Ctrl K
ComunidadGuías…

scripts/database-snapshot-output.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { SnapshotProgress } from "#scripts/database-snapshot-lib.ts";
import { formatMs } from "#shared/format-units.ts";

const CLEAR_LINE = "\r\x1b[2K";
const UPDATE_INTERVAL_MS = 1_000;

export interface SnapshotOutputOptions {
  terminal: boolean;
  write: (text: string) => void;
}

export interface SnapshotProgressOutput {
  report(message: SnapshotProgress): void;
  stop(): void;
}

interface RenderedProgress {
  message: SnapshotProgress;
  renderedLine: string;
  startedAt: number;
}

interface ActiveProgress {
  progress: RenderedProgress;
  timer: number;
}

export const createSnapshotProgressOutput = ({
  terminal,
  write,
}: SnapshotOutputOptions): SnapshotProgressOutput => {
  if (!terminal) {
    return {
      report: (message) => write(`${message}\n`),
      stop: () => {},
    };
  }

  let active: ActiveProgress | null = null;

  const render = (progress: RenderedProgress): void => {
    const elapsed = Date.now() - progress.startedAt;
    const line =
      elapsed < UPDATE_INTERVAL_MS
        ? progress.message
        : `${progress.message} (${formatMs(elapsed)})`;
    if (line === progress.renderedLine) return;
    progress.renderedLine = line;
    write(`${CLEAR_LINE}${line}`);
  };

  const finish = (progress: ActiveProgress): void => {
    clearInterval(progress.timer);
    render(progress.progress);
    write("\n");
  };

  return {
    report: (message) => {
      if (active !== null) finish(active);
      const progress = {
        message,
        renderedLine: "",
        startedAt: Date.now(),
      };
      render(progress);
      active = {
        progress,
        timer: setInterval(() => render(progress), UPDATE_INTERVAL_MS),
      };
    },
    stop: () => {
      if (active === null) return;
      finish(active);
      active = null;
    },
  };
};