import path from "path"; import type { CheckCodeOptions } from "../checkCodeRunner"; type ParsedArgs = Record; const parseArgs = (argv: string[]): ParsedArgs => { const parsed: ParsedArgs = {}; for (let index = 0; index < argv.length; index += 1) { const item = argv[index]; if (!item.startsWith("--")) continue; const equalIndex = item.indexOf("="); const key = item.slice(2, equalIndex > 2 ? equalIndex : undefined); const inlineValue = equalIndex > 2 ? item.slice(equalIndex + 1) : undefined; const next = argv[index + 1]; const value = inlineValue ?? ( next && !next.startsWith("--") ? next : "true" ); if (inlineValue === undefined && next && !next.startsWith("--")) index += 1; (parsed[key] ||= []).push(value); } return parsed; }; const singleArg = ( args: ParsedArgs, key: string, options: { required?: boolean } = {}, ): string | undefined => { const values = args[key] || []; if (values.length > 1) throw new Error("--" + key + " may be provided only once"); const value = values[0]?.trim(); if (options.required && (!value || value === "true")) { throw new Error("--" + key + " is required"); } return value && value !== "true" ? value : undefined; }; const listArg = (args: ParsedArgs, key: string): string[] | undefined => { const values = (args[key] || []) .flatMap((value) => value.split(",")) .map((value) => value.trim()) .filter(Boolean); return values.length > 0 ? [...new Set(values)] : undefined; }; const defaultRunId = (): string => { const timestamp = new Date().toISOString().replace(/\D/g, ""); return "checkcode-" + timestamp + "-" + Math.random().toString(36).slice(2, 8); }; export const parseCheckCodeOptions = ( argv: string[], defaultRoot: string = process.cwd(), createRunId: () => string = defaultRunId, ): CheckCodeOptions => { const args = parseArgs(argv); const root = path.resolve(singleArg(args, "root") || defaultRoot); const artifactHash = singleArg(args, "artifactHash", { required: true }) as string; const options: CheckCodeOptions = { root, runId: singleArg(args, "runId") || createRunId(), artifactHash, networks: listArg(args, "network"), contracts: listArg(args, "contract"), }; const deploymentId = singleArg(args, "deploymentId"); const registryCommitId = singleArg(args, "registryCommitId"); if (Boolean(deploymentId) !== Boolean(registryCommitId)) { throw new Error("--deploymentId and --registryCommitId must be provided together"); } if (deploymentId && registryCommitId) { options.deploymentAudit = { deploymentId, registryCommitId }; } return options; };