import { z } from "incur"; import { JavaScriptRecoveryService } from "../application/javascript/JavaScriptRecoveryService.js"; import { createJavaScriptRecoveryProvider } from "../composition/javascriptRecovery.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import { logCliCommand } from "../cliLogging.js"; import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; import { withCommandCancellation } from "./commandCancellation.js"; /** Share source recovery with MCP while keeping CLI spelling at this boundary. */ export const registerJavaScriptRecoveryCommands = ( cli: CliInstance, logger: Logger, environment: Readonly>, ): void => { const service = new JavaScriptRecoveryService( createJavaScriptRecoveryProvider(environment), ); cli.command(CLI_COMMANDS.recoverJavaScriptSources, { description: "Recover readable JavaScript modules with source provenance and verified files", args: z.object({ path: z .string() .describe("Absolute UTF-8 JavaScript input; never executed"), outputDirectory: z.string().describe("Absolute absent output directory"), }), options: z.object({ extractionMode: z .enum(["structural", "heuristic", "inspection"]) .optional() .describe( "Structural boundaries, heuristic fallback, or inspection-only regions", ), rewriteLevel: z .enum(["minimal", "standard", "aggressive"]) .optional() .describe( "Upstream syntax recovery level; runtime equivalence remains unknown", ), }), run: ({ args, options }) => withCommandCancellation(async (signal) => { try { return await logCliCommand( logger, CLI_COMMANDS.recoverJavaScriptSources, async () => { const result = await service.recover( { path: args.path, output_directory: args.outputDirectory, ...(options.extractionMode === undefined ? {} : { extraction_mode: options.extractionMode }), ...(options.rewriteLevel === undefined ? {} : { rewrite_level: options.rewriteLevel }), }, { signal }, ); return result.ok ? result.value : projectAnalysisError(result.error); }, ); } finally { await service.close(); } }), }); };