// Plain, line-based progress output: easy to follow live and easy to tail when a long upload runs in the background // (`storebound play images > .storebound/images.log 2>&1 &`). Every line carries a timestamp and a tag. const t0 = Date.now(); const stamp = (): string => new Date().toISOString().slice(11, 19); const since = (): string => `${((Date.now() - t0) / 1000).toFixed(0)}s`; export const log = (tag: string, msg: string): void => console.log(`${stamp()} [${tag}] ${msg}`); export const warn = (tag: string, msg: string): void => console.warn(`${stamp()} [${tag}] WARN ${msg}`); export const done = (tag: string, msg: string): void => console.log(`${stamp()} [${tag}] ${msg} (${since()})`); /** "3/14 de-DE" style counters. */ export const step = (i: number, n: number, what: string): string => `${String(i).padStart(String(n).length)}/${n} ${what}`; /** Prefix of the one machine-readable result line that `storebound serve --stdio` reads from a child command. */ export const RESULT_MARK = '\u001estorebound-result '; /** * Structured result of a `--json` run. In a terminal (or a pipe) it is pretty JSON on stdout as before; under * `storebound serve` (STOREBOUND_MACHINE=1) it is one marked line, so log lines printed before it never break parsing. */ export function printJson(data: unknown): void { if (process.env.STOREBOUND_MACHINE === '1') process.stdout.write(RESULT_MARK + JSON.stringify(data) + '\n'); else console.log(JSON.stringify(data, null, 2)); }