UNPKG

@marteye/studio-cli

Version:

CLI for MartEye Studio API

438 lines (419 loc) 15.6 kB
'use strict'; var commander = require('commander'); var fs = require('fs'); var path = require('path'); var os = require('os'); var child_process = require('child_process'); var chalk = require('chalk'); var inquirer = require('inquirer'); var output = require('../utils/output.js'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs); var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os); function completionCommand() { const completion = new commander.Command('completion') .description('Shell completion utilities') .addHelpText('after', ` Tab completion enables you to: - Auto-complete command names by pressing TAB - See available subcommands and options - Speed up your workflow significantly Quick Setup: $ studio completion setup # Interactive setup (recommended) Manual Setup: $ studio completion generate >> ~/.bashrc # For bash $ studio completion generate >> ~/.zshrc # For zsh After setup, restart your terminal or run: $ source ~/.bashrc # or ~/.zshrc for zsh Examples: $ studio <TAB> # Shows all commands $ studio sales <TAB> # Shows: list, get, create, update $ studio lots list --<TAB> # Shows all available options`); completion .command('setup') .description('Setup tab completion for your shell') .action(async () => { try { // Detect the current shell const shell = detectShell(); const shellRcFile = getShellRcFile(shell); if (!shellRcFile) { output.error(`Unable to determine configuration file for ${shell}`); console.log('\nManual setup instructions:'); console.log('Add the following to your shell configuration file:'); console.log(chalk.gray('eval "$(studio completion generate)"')); process.exit(1); } console.log(chalk.cyan(`Detected shell: ${shell}`)); console.log(chalk.cyan(`Configuration file: ${shellRcFile}`)); // Check if completion is already installed const rcContent = fs__namespace.existsSync(shellRcFile) ? fs__namespace.readFileSync(shellRcFile, 'utf-8') : ''; if (rcContent.includes('studio completion generate')) { output.warning('Tab completion appears to be already installed.'); const { proceed } = await inquirer.prompt([ { type: 'confirm', name: 'proceed', message: 'Do you want to reinstall it?', default: false } ]); if (!proceed) { console.log('Setup cancelled.'); return; } } // Ask for confirmation const { confirm } = await inquirer.prompt([ { type: 'confirm', name: 'confirm', message: `Add tab completion to ${shellRcFile}?`, default: true } ]); if (!confirm) { console.log('Setup cancelled.'); return; } // Add completion to shell rc file const completionScript = ` # Studio CLI tab completion eval "$(studio completion generate)" `; // Backup the original file if (fs__namespace.existsSync(shellRcFile)) { fs__namespace.copyFileSync(shellRcFile, `${shellRcFile}.backup.${Date.now()}`); console.log(chalk.gray(`Backup created: ${shellRcFile}.backup.${Date.now()}`)); } // Append to rc file fs__namespace.appendFileSync(shellRcFile, completionScript); output.success('Tab completion installed successfully!'); console.log('\n' + chalk.yellow('To activate the changes:')); console.log(chalk.white(` source ${shellRcFile}`)); console.log(chalk.gray(' or restart your terminal')); } catch (err) { output.error('Failed to setup tab completion', err.message); process.exit(1); } }); completion .command('generate') .description('Generate completion script for current shell') .action(() => { const shell = detectShell(); const script = generateCompletionScript(shell); console.log(script); }); completion .command('uninstall') .description('Remove tab completion from your shell') .action(async () => { try { const shell = detectShell(); const shellRcFile = getShellRcFile(shell); if (!shellRcFile || !fs__namespace.existsSync(shellRcFile)) { output.error('Could not find shell configuration file'); process.exit(1); } const rcContent = fs__namespace.readFileSync(shellRcFile, 'utf-8'); if (!rcContent.includes('studio completion generate')) { output.warning('Tab completion does not appear to be installed.'); return; } const { confirm } = await inquirer.prompt([ { type: 'confirm', name: 'confirm', message: `Remove tab completion from ${shellRcFile}?`, default: true } ]); if (!confirm) { console.log('Uninstall cancelled.'); return; } // Remove completion lines const lines = rcContent.split('\n'); const filteredLines = []; let skipNext = false; for (let i = 0; i < lines.length; i++) { if (lines[i].includes('Studio CLI tab completion')) { skipNext = true; continue; } if (skipNext && lines[i].includes('studio completion generate')) { skipNext = false; continue; } filteredLines.push(lines[i]); } // Backup and write fs__namespace.copyFileSync(shellRcFile, `${shellRcFile}.backup.${Date.now()}`); fs__namespace.writeFileSync(shellRcFile, filteredLines.join('\n')); output.success('Tab completion uninstalled successfully!'); console.log('\n' + chalk.yellow('Restart your terminal for changes to take effect.')); } catch (err) { output.error('Failed to uninstall tab completion', err.message); process.exit(1); } }); return completion; } function detectShell() { // Check SHELL environment variable const shellEnv = process.env.SHELL; if (shellEnv) { if (shellEnv.includes('zsh')) return 'zsh'; if (shellEnv.includes('bash')) return 'bash'; if (shellEnv.includes('fish')) return 'fish'; } // Try to detect from process try { const parentProcess = child_process.execSync('ps -p $PPID -o comm=', { encoding: 'utf-8' }).trim(); if (parentProcess.includes('zsh')) return 'zsh'; if (parentProcess.includes('bash')) return 'bash'; if (parentProcess.includes('fish')) return 'fish'; } catch { // Fallback } // Default to bash return 'bash'; } function getShellRcFile(shell) { const home = os__namespace.homedir(); switch (shell) { case 'zsh': // Check for various zsh config files in order of preference const zshFiles = ['.zshrc', '.zprofile', '.zshenv']; for (const file of zshFiles) { const filePath = path__namespace.join(home, file); if (fs__namespace.existsSync(filePath)) { return filePath; } } // Default to .zshrc if none exist return path__namespace.join(home, '.zshrc'); case 'bash': // Check for various bash config files in order of preference const bashFiles = ['.bashrc', '.bash_profile', '.profile']; for (const file of bashFiles) { const filePath = path__namespace.join(home, file); if (fs__namespace.existsSync(filePath)) { return filePath; } } // Default to .bashrc if none exist return path__namespace.join(home, '.bashrc'); case 'fish': return path__namespace.join(home, '.config', 'fish', 'config.fish'); default: return null; } } function generateCompletionScript(shell) { // Get all commands dynamically const commands = [ 'market', 'sales', 'lots', 'lot-items', 'customers', 'search', 'config', 'settings', 'adjustments', 'product-codes', 'tax-rates', 'webhooks', 'actions', 'bidder-apps', 'files', 'utils', 'completion' ]; switch (shell) { case 'bash': return ` ###-begin-studio-completions-### _studio_completions() { local cur="\${COMP_WORDS[COMP_CWORD]}" local prev="\${COMP_WORDS[COMP_CWORD-1]}" local commands="${commands.join(' ')}" # Main commands if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=($(compgen -W "$commands --help --version --api-key --format --output --query --no-color --debug" -- "$cur")) return fi # Subcommands based on main command case "$prev" in market) COMPREPLY=($(compgen -W "get" -- "$cur")) ;; sales) COMPREPLY=($(compgen -W "list get create update" -- "$cur")) ;; lots) COMPREPLY=($(compgen -W "list get create update delete" -- "$cur")) ;; customers) COMPREPLY=($(compgen -W "list get create find-by-account find-by-marteye" -- "$cur")) ;; config) COMPREPLY=($(compgen -W "init get set list use create-profile delete-profile list-profiles" -- "$cur")) ;; completion) COMPREPLY=($(compgen -W "setup generate uninstall" -- "$cur")) ;; utils) COMPREPLY=($(compgen -W "validate-eartag" -- "$cur")) ;; --format|--output) COMPREPLY=($(compgen -W "json yaml table csv" -- "$cur")) ;; esac } complete -F _studio_completions studio ###-end-studio-completions-### `; case 'zsh': return ` ###-begin-studio-completions-### if type compdef &>/dev/null; then _studio_completions() { local -a commands commands=( 'market:Market operations' 'sales:Sales operations' 'lots:Lot operations' 'lot-items:Lot item operations' 'customers:Customer operations' 'search:Search operations' 'config:Configuration management' 'settings:Market settings operations' 'adjustments:Adjustment operations' 'product-codes:Product code operations' 'tax-rates:Tax rate operations' 'webhooks:Webhook operations' 'actions:Action operations' 'bidder-apps:Bidder app operations' 'files:File operations' 'utils:Utility commands' 'completion:Shell completion utilities' ) _arguments -C \\ '1: :->cmd' \\ '2: :->subcmd' \\ '--help[Show help]' \\ '--version[Show version]' \\ '--api-key[API key]:api-key:' \\ '--format[Output format]:format:(json yaml table csv)' \\ '--output[Output format]:output:(json yaml table csv)' \\ '--query[JMESPath query]:query:' \\ '--no-color[Disable colored output]' \\ '--debug[Enable debug mode]' \\ '*::arg:->args' case "$state" in cmd) _describe 'command' commands ;; subcmd) case "$line[1]" in market) local -a market_cmds market_cmds=('get:Get market details') _describe 'market command' market_cmds ;; sales) local -a sales_cmds sales_cmds=( 'list:List sales within date range' 'get:Get specific sale details' 'create:Create a new sale' 'update:Update sale information' ) _describe 'sales command' sales_cmds ;; lots) local -a lots_cmds lots_cmds=( 'list:List lots in a sale' 'get:Get specific lot details' 'create:Create a new lot' 'update:Update lot information' 'delete:Delete a lot' ) _describe 'lots command' lots_cmds ;; customers) local -a customers_cmds customers_cmds=( 'list:List customers' 'get:Get customer details' 'create:Create new customer' 'find-by-account:Find customer by account number' 'find-by-marteye:Find customer by MartEye UID' ) _describe 'customers command' customers_cmds ;; completion) local -a completion_cmds completion_cmds=( 'setup:Setup tab completion for your shell' 'generate:Generate completion script' 'uninstall:Remove tab completion' ) _describe 'completion command' completion_cmds ;; esac ;; esac } compdef _studio_completions studio fi ###-end-studio-completions-### `; case 'fish': return ` ###-begin-studio-completions-### # Studio CLI completions for fish complete -c studio -f # Main commands ${commands.map(cmd => `complete -c studio -n "__fish_use_subcommand" -a "${cmd}"`).join('\n')} # Global options complete -c studio -l help -d "Show help" complete -c studio -l version -d "Show version" complete -c studio -l api-key -d "API key" complete -c studio -l format -a "json yaml table csv" -d "Output format" complete -c studio -l output -a "json yaml table csv" -d "Output format" complete -c studio -l query -d "JMESPath query" complete -c studio -l no-color -d "Disable colored output" complete -c studio -l debug -d "Enable debug mode" # Subcommands complete -c studio -n "__fish_seen_subcommand_from market" -a "get" -d "Get market details" complete -c studio -n "__fish_seen_subcommand_from sales" -a "list get create update" -d "Sales operations" complete -c studio -n "__fish_seen_subcommand_from lots" -a "list get create update delete" -d "Lot operations" complete -c studio -n "__fish_seen_subcommand_from customers" -a "list get create find-by-account find-by-marteye" -d "Customer operations" complete -c studio -n "__fish_seen_subcommand_from completion" -a "setup generate uninstall" -d "Completion operations" ###-end-studio-completions-### `; default: return '# Unsupported shell'; } } exports.completionCommand = completionCommand; //# sourceMappingURL=completion.js.map