@controlplane/cli
Version:
Control Plane Corporation CLI
201 lines • 8.59 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MiscCommand = void 0;
const fs = require("fs");
const path = require("path");
const command_1 = require("./command");
const installer_1 = require("./completion/installer");
const cache_generator_1 = require("./completion/cache-generator");
const constants_1 = require("./completion/constants");
const logger_1 = require("../util/logger");
const options_1 = require("../commands/options");
const io_1 = require("../util/io");
class MiscCommand extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'misc';
this.describe = 'Miscellaneous helper commands';
}
builder(yargs) {
return yargs.demandCommand().command(new InstallCompletion().toYargs()).command(new UninstallCompletion().toYargs());
}
handle() { }
}
exports.MiscCommand = MiscCommand;
class InstallCompletion extends command_1.Command {
constructor() {
super();
this.command = 'install-completion';
this.describe = 'Install shell completion to your local profile';
this.installer = new installer_1.CompletionInstaller('cpln', 'cpln');
}
builder(yargs) {
return (0, options_1.withDebugOptions)(yargs.options({
batch: {
alias: 'b',
describe: 'Non-interactive (batch) mode',
boolean: true,
},
shell: {
describe: `Shell to install completion for (${constants_1.SUPPORTED_SHELLS.join(', ')}). Only used with --batch`,
choices: constants_1.SUPPORTED_SHELLS,
type: 'string',
},
}));
}
// Public Methods //
async handle(args) {
try {
// Get shell (either from args or prompt)
const shell = args.batch ? this.determineShell(args) : await this.promptForShell();
// Ensure cache exists and is fresh (handles fresh installs, upgrades, and repairs)
cache_generator_1.CacheGenerator.regenerateIfStale(args, shell);
// Perform installation
await this.performInstallation(shell, args);
// Show success message
this.session.out('✓ Shell completion installed successfully');
this.showReloadInstructions(shell);
}
catch (e) {
this.handleInstallationError(e);
}
}
// Private Methods //
async performInstallation(shell, args) {
const mode = args.batch ? 'batch' : 'interactive';
logger_1.logger.debug(`Installing completion for ${shell} shell in ${mode} mode`);
// Setup shell-specific requirements (pre-install)
this.ensureShellRequirements(shell);
// Install completion scripts
const path = args.batch ? this.getShellPath(shell) : undefined;
await this.installer.install(path, shell);
}
ensureShellRequirements(shell) {
if (shell === 'zsh') {
this.ensureZshCompinit();
}
}
async promptForShell() {
const detectedShell = this.detectCurrentShell();
const defaultIndex = detectedShell ? constants_1.SHELL_CHOICES.findIndex((c) => c.value === detectedShell) : 0;
const answers = await require('inquirer').prompt([
{
type: 'list',
name: 'shell',
message: 'Which shell do you use?',
choices: constants_1.SHELL_CHOICES,
default: defaultIndex,
},
]);
return answers.shell;
}
determineShell(args) {
// Use explicit arg, detected shell, or fallback to bash
const rawShell = args.shell || this.detectCurrentShell() || 'bash';
// Validate that the shell is supported
if (!constants_1.SUPPORTED_SHELLS.includes(rawShell)) {
this.session.abort({
message: `ERROR: Shell '${rawShell}' is not supported. Supported shells: ${constants_1.SUPPORTED_SHELLS.join(', ')}`,
});
}
return rawShell;
}
detectCurrentShell() {
// Try to detect from parent process (most reliable for current shell)
try {
const { execSync } = require('child_process');
const ppid = process.ppid;
const parentProcess = execSync(`ps -p ${ppid} -o comm=`, { encoding: 'utf8' }).trim();
// Extract shell name (handles paths like /bin/bash or just bash)
const shellName = parentProcess.replace(/.*\//, '').replace(/^-/, '');
if (constants_1.SUPPORTED_SHELLS.includes(shellName)) {
return shellName;
}
}
catch (_a) {
// Fall through to other detection methods
}
// Fallback to $SHELL (login shell, less reliable)
const shellEnv = process.env.SHELL;
if (!shellEnv) {
return undefined;
}
const shellName = shellEnv.replace(/.*\//, '');
if (constants_1.SUPPORTED_SHELLS.includes(shellName)) {
return shellName;
}
return undefined;
}
getShellPath(shell) {
return constants_1.SHELL_CONFIGS[shell].path;
}
ensureZshCompinit() {
const zshrcPath = path.join((0, io_1.getUserHome)(), '.zshrc');
// Create .zshrc if it doesn't exist
if (!fs.existsSync(zshrcPath)) {
fs.writeFileSync(zshrcPath, '');
logger_1.logger.debug('Created ~/.zshrc');
}
const content = fs.readFileSync(zshrcPath, 'utf8');
// Check if compinit is already setup
const hasCompinit = content.includes('compinit');
const hasAutoload = content.includes('autoload') && content.includes('compinit');
if (!hasCompinit || !hasAutoload) {
// Add compinit setup at the beginning of the file
const compInitSetup = `# Enable completion system (added by cpln)\nautoload -U compinit\ncompinit\n\n`;
fs.writeFileSync(zshrcPath, compInitSetup + content);
logger_1.logger.debug('Configured zsh completion system (compinit) in ~/.zshrc');
}
}
showReloadInstructions(shell) {
const reloadCmd = constants_1.SHELL_CONFIGS[shell].reloadCommand;
this.session.out(`\nTo activate the completion, restart your shell or run:\n ${reloadCmd}`);
}
handleInstallationError(error) {
var _a;
const errorMessage = (_a = error.message) !== null && _a !== void 0 ? _a : '';
let errorNote = 'Error installing shell completion:\n\n' + errorMessage;
if (errorMessage.includes('profile')) {
errorNote += '\n\nTry creating a default profile first, using:\n\ncpln profile login\n';
}
else {
errorNote +=
'\n\nIf the installation failed, try:\n\t1. Restarting the shell\n\t2. (on mac) Installing rosetta with:\n\n\tsoftwareupdate --install-rosetta\n';
}
this.session.err(errorNote);
process.exit(1);
}
}
class UninstallCompletion extends command_1.Command {
constructor() {
super();
this.command = 'uninstall-completion';
this.describe = 'Uninstall shell completion from your local profile';
this.installer = new installer_1.CompletionInstaller('cpln', 'cpln');
}
builder(yargs) {
return (0, options_1.withDebugOptions)(yargs);
}
async handle() {
try {
// Get the shell that was used for installation
const installedShell = cache_generator_1.CacheGenerator.getCachedShell();
logger_1.logger.debug(`Uninstalling completion (previously installed for: ${installedShell || 'unknown'})`);
// Uninstall using CompletionInstaller (removes scripts and shell config)
await this.installer.uninstall();
// Remove the cache file
cache_generator_1.CacheGenerator.deleteCache();
this.session.out('✓ Shell completion uninstalled successfully');
// Only show zsh note if it was installed for zsh
if (installedShell === 'zsh') {
this.session.out('\nNote: The zsh completion system (compinit) remains configured as other tools may use it.');
}
this.session.out('\nYou may need to restart your shell if completion is still active.');
}
catch (e) {
this.session.err('Error uninstalling shell completion');
process.exit(1);
}
}
}
//# sourceMappingURL=misc.js.map