// Tiny argv parser: positionals, --flag, --key value, --key=value. export interface Args { _: string[]; has(name: string): boolean; get(name: string): string | undefined; str(name: string, d: string): string; num(name: string, d: number): number; list(name: string): string[]; /** Every value of a flag given more than once (--param a=1 --param b=2), in order. */ many(name: string): string[]; } export function parseArgs(argv: string[], booleans: string[] = []): Args { const flags = new Map(); const repeated = new Map(); const set = (k: string, v: string) => { flags.set(k, v); repeated.set(k, [...(repeated.get(k) ?? []), v]); }; const _: string[] = []; const bool = new Set(['dry', 'yes', 'help', 'json', 'verbose', 'all-pages', 'apply', 'resume', 'force', 'force-unlock', 'include-drafts', ...booleans]); for (let i = 0; i < argv.length; i++) { const a = argv[i]!; if (!a.startsWith('--')) { _.push(a); continue; } const eq = a.indexOf('='); if (eq > 0) { set(a.slice(2, eq), a.slice(eq + 1)); continue; } const name = a.slice(2); const next = argv[i + 1]; if (bool.has(name) || name.startsWith('no-') || next === undefined || next.startsWith('--')) set(name, 'true'); else { set(name, next); i++; } } const get = (n: string) => flags.get(n); return { _, has: n => flags.has(n), get, str: (n, d) => get(n) ?? d, num: (n, d) => { const v = get(n); const x = v === undefined ? d : Number(v); if (Number.isNaN(x)) throw new Error(`--${n}: not a number`); return x; }, list: n => (get(n) ?? '').split(',').map(s => s.trim()).filter(Boolean), many: n => repeated.get(n) ?? [], }; }