import { CliArgError } from "./cli-args"; import { validateSecretName } from "./environment-contract"; /** Parse only this command's options; everything after -- belongs to the child. */ export function parseEnvironmentOptions( input: readonly string[], values: readonly string[], booleans: readonly string[] = [], ): { positional: string[]; flags: Record; child: string[]; } { const positional: string[] = []; const flags: Record = {}; let child: string[] = []; for (let i = 0; i < input.length; i++) { const arg = input[i]; if (arg === "--") { child = input.slice(i + 1); break; } if (!arg.startsWith("-")) { positional.push(arg); continue; } if (!(values.includes(arg) || booleans.includes(arg))) { throw new CliArgError( `Unknown flag: ${arg}. Use --help for supported options.`, ); } if (Object.hasOwn(flags, arg)) throw new CliArgError(`Duplicate flag: ${arg}`); if (booleans.includes(arg)) { flags[arg] = true; continue; } const value = input[++i]; if (!value || value.startsWith("-")) throw new CliArgError(`${arg} requires a value.`); flags[arg] = value; } return { positional, flags, child }; } export function isEnvironmentHelp(args: readonly string[]): boolean { const boundary = args.indexOf("--"); return ( args .slice(0, boundary < 0 ? undefined : boundary) .some((arg) => arg === "--help" || arg === "-h") || args[0] === "help" || args.length === 0 ); } export function requireEnvironmentName(value: string | undefined): string { if (!value || !/^[a-z][a-z0-9-]{0,63}$/.test(value)) { throw new CliArgError( "Environment name must use lowercase letters, numbers and hyphens (1–64 characters), beginning with a letter.", ); } return value; } export function requireSecretName(value: string | undefined): string { if (!value || !/^[A-Z][A-Z0-9_]{0,127}$/.test(value)) { throw new CliArgError( "Secret name must use uppercase letters, numbers and underscores (1–128 characters).", ); } return validateSecretName(value); } export function integerOption( value: string | boolean | undefined, name: string, fallback: number, min: number, max: number, ): number { if (value === undefined) return fallback; const parsed = Number(value); if ( typeof value !== "string" || !/^\d+$/.test(value) || !Number.isSafeInteger(parsed) || parsed < min || parsed > max ) { throw new CliArgError( `${name} must be an integer between ${min} and ${max}.`, ); } return parsed; }