UNPKG

@elsikora/setup-wizard

Version:

Setup Wizard - CLI scaffolding utility

81 lines (78 loc) 3.41 kB
#!/usr/bin/env node import { exec } from 'node:child_process'; import { promisify } from 'node:util'; /** * Implementation of the command service using Node.js child_process. * Provides functionality to execute shell commands. */ class NodeCommandService { /** CLI interface service for user interaction */ CLI_INTERFACE_SERVICE; /** * Promisified version of the exec function from child_process. * Allows for async/await usage of command execution. */ EXEC_ASYNC = promisify(exec); constructor(cliInterfaceService) { this.CLI_INTERFACE_SERVICE = cliInterfaceService; } /** * Executes a shell command. * @param command - The shell command to execute * @returns Promise that resolves when the command completes successfully * @throws Will throw an error if the command execution fails, except for npm install which offers retry options */ async execute(command) { try { await this.EXEC_ASYNC(command); } catch (error) { // Check if the failed command is npm if (command.trim().startsWith("npm install") || command.trim().startsWith("npm ci") || command.trim().startsWith("npm update") || command.trim().startsWith("npm uninstall")) { await this.handleNpmInstallFailure(command); } else { // For non-npm commands, throw the error as before throw error; } } } /** * Handles npm install command failures by offering retry options to the user. * @param originalCommand - The original npm command that failed * @returns Promise that resolves when the chosen action completes * @throws Will throw an error if the user chooses to cancel or if retried command still fails */ async handleNpmInstallFailure(originalCommand) { this.CLI_INTERFACE_SERVICE.warn("npm command exection failed."); const options = [ { label: "Retry with --force", value: "force" }, { label: "Retry with --legacy-peer-deps", value: "legacy-peer-deps" }, { label: "Cancel command execution", value: "cancel" }, ]; const choice = await this.CLI_INTERFACE_SERVICE.select("How would you like to proceed?", options); switch (choice) { case "force": { this.CLI_INTERFACE_SERVICE.info("Retrying with --force flag..."); await this.EXEC_ASYNC(`${originalCommand} --force`); this.CLI_INTERFACE_SERVICE.success("Execution completed with --force flag."); break; } case "legacy-peer-deps": { this.CLI_INTERFACE_SERVICE.info("Retrying with --legacy-peer-deps flag..."); await this.EXEC_ASYNC(`${originalCommand} --legacy-peer-deps`); this.CLI_INTERFACE_SERVICE.success("Execution completed with --legacy-peer-deps flag."); break; } case "cancel": { this.CLI_INTERFACE_SERVICE.info("Execution cancelled by user."); throw new Error("npm command execution was cancelled by user."); } default: { throw new Error("Invalid option selected."); } } } } export { NodeCommandService }; //# sourceMappingURL=node-command.service.js.map