@marteye/studio-cli
Version:
CLI for MartEye Studio API
438 lines (419 loc) • 15.6 kB
JavaScript
'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