import { execSync } from "node:child_process"; import search from "@inquirer/search"; import { defineCommand, arg } from "politty"; import { z } from "zod"; import { executeCommand, success, failure, silentFailure } from "../lib/command-result"; import { discoverApps, collectScripts } from "./scripts"; export const runCommand = defineCommand({ name: "run", description: "Interactively select and run an app script", args: z.object({ app: arg(z.string().optional(), { positional: true, description: "App name (interactive if omitted)", }), script: arg(z.string().optional(), { positional: true, description: "Script name (interactive if omitted)", }), }), run: (args) => { return executeCommand(async () => { const cwd = process.cwd(); const apps = discoverApps(cwd); if (apps.length === 0) { return failure("No apps found in apps/"); } let app = args.app; if (!app) { app = await search({ message: "Select app:", source: (term) => { const filtered = term ? apps.filter((a) => a.includes(term)) : apps; return filtered.map((a) => ({ name: a, value: a })); }, }); } else if (!apps.includes(app)) { return failure(`App "${app}" not found. Available: ${apps.join(", ")}`); } const scripts = collectScripts(cwd, app); if (scripts.length === 0) { return failure(`No scripts found in ${app}`); } let entry: (typeof scripts)[number]; if (args.script) { const match = scripts.find((s) => s.name === args.script || s.label === args.script); if (!match) { return failure( `Script "${args.script}" not found in ${app}. Available: ${scripts.map((s) => s.label).join(", ")}`, ); } entry = match; } else { entry = await search({ message: "Select script:", source: (term) => { const filtered = term ? scripts.filter((s) => s.label.includes(term)) : scripts; return filtered.map((s) => ({ name: s.label, value: s })); }, }); } console.log(`\nRunning: pnpm run ${entry.name} (in ${entry.cwd})\n`); try { execSync(`pnpm run ${entry.name}`, { cwd: entry.cwd, stdio: "inherit" }); return success(); } catch (err) { const exitCode = (err as { status?: number }).status ?? 1; return silentFailure(exitCode); } }); }, });