import { parseArgs } from "node:util"; import { z } from "zod"; import { CLIError, MuseError } from "#lib"; const Renderers = ["json", "html"] as const; const RendererSchema = z.enum(Renderers); type Renderer = z.infer; /** * A shape representing the arguments passed to the CLI */ export interface CLIArguments { inputFilePath: string; options: { write: boolean; check: boolean; outfile: string; help: boolean; minify: boolean; renderer: Renderer; watch: boolean; }; } /** * Given an array of CLI arguments, parse them into a structured object * * @param argv The arguments to parse * @returns The parsed CLI arguments * * @throws {CLIError} if the arguments are invalid */ export function parseCLIArguments(argv: string[]): CLIArguments { const { values: options, positionals: args } = parseArgs({ args: argv, options: { write: { short: "w", type: "boolean", default: false, }, check: { short: "c", type: "boolean", default: false, }, outfile: { short: "o", type: "string", default: "playbill.json", }, help: { short: "h", default: false, type: "boolean", }, minify: { short: "m", default: false, type: "boolean", }, renderer: { short: "r", default: "json", type: "string", }, watch: { default: false, type: "boolean", }, }, strict: true, allowPositionals: true, }); // -- ARG VALIDATION -- // if (options.check && options.write) { throw new CLIError("Cannot use --check and --write together"); } const parsedRenderer = RendererSchema.safeParse(options.renderer); if (!parsedRenderer.success) { throw new MuseError(`Invalid renderer: ${parsedRenderer.data}`); } return { inputFilePath: args[0] ?? "./binding.yaml", options: { write: options.write, check: options.check, outfile: options.outfile, help: options.help, minify: options.minify, renderer: parsedRenderer.data, watch: options.watch, }, }; }