storebound/cli/lib/table.ts
CRT 3f12452e3f TestFlight through the App Store Connect API: apple testflight status | groups | testers | what-to-test | info | distribute
Beta groups from apple.testflight.groups (created when missing, never changed), testers from a CSV in .storebound/
(masked in logs, confirmation before Apple emails invitations, --remove / --invite), What to Test per locale from the
App Store listing (whatToTest or whatsNew), Test Information and Beta App Review details, builds by exact number to
groups, Beta App Review submission behind --submit-review and a confirmation. Pure planners in cli/lib/testflight.ts,
shared CSV / table / JSON:API helpers. MCP: apple_testflight_status, _groups, _what_to_test, _info, _distribute
(internal groups only). Skill testflight.
2026-10-10 23:28:10 +08:00

16 lines
1,017 B
TypeScript

// Aligned text tables for the terminal and Markdown tables for reports. Pure.
export function textTable(head: string[], rows: (string | number)[][]): string {
const all = [head, ...rows.map(r => r.map(String))];
const w = head.map((_, i) => Math.max(...all.map(r => [...(r[i] ?? '')].length)));
const line = (r: string[]) => r.map((c, i) => c + ' '.repeat(w[i]! - [...c].length)).join(' ').trimEnd();
return [line(head), line(w.map(n => '-'.repeat(n))), ...all.slice(1).map(line)].join('\n');
}
const md = (c: string | number) => String(c).replace(/\|/g, '\\|').replace(/\n/g, ' ');
export function mdTable(head: string[], rows: (string | number)[][]): string {
return [`| ${head.map(md).join(' | ')} |`, `|${head.map(() => '---').join('|')}|`, ...rows.map(r => `| ${r.map(md).join(' | ')} |`)].join('\n');
}
/** 0.01234 -> "1.23%" */
export const pct = (x: number | null | undefined, digits = 2): string => (x === null || x === undefined || Number.isNaN(x) ? 'n/a' : `${(x * 100).toFixed(digits)}%`);