UNPKG

@necto-ai/pgit

Version:

Private file tracking with dual git repositories

432 lines 17.2 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const fs_1 = require("fs"); const path_1 = require("path"); const init_command_1 = require("./commands/init.command"); const status_command_1 = require("./commands/status.command"); const add_command_1 = require("./commands/add.command"); const commit_command_1 = require("./commands/commit.command"); const gitops_command_1 = require("./commands/gitops.command"); const cleanup_command_1 = require("./commands/cleanup.command"); const reset_command_1 = require("./commands/reset.command"); const preset_command_1 = require("./commands/preset.command"); const enhanced_error_handler_1 = require("./errors/enhanced.error-handler"); const logger_service_1 = require("./utils/logger.service"); /** * Main CLI entry point */ async function main() { // Read version from package.json let version = '1.0.0'; // fallback version try { const packageJsonPath = (0, path_1.join)(__dirname, '..', 'package.json'); const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf-8')); version = packageJson.version; } catch { logger_service_1.logger.warn('Could not read package.json for version, using fallback'); } commander_1.program .name('pgit') .description('Private Git Tracking CLI - Manage private files with dual repositories') .version(version, '-v, -V, --version', 'Output the current version') .option('--verbose', 'Show verbose output') .on('option:verbose', () => { logger_service_1.logger.setLevel(logger_service_1.LogLevel.DEBUG); logger_service_1.logger.debug('Verbose mode enabled'); }); // Initialize command commander_1.program .command('init') .description('Initialize private git tracking in current directory') .action(async (options) => { try { const initCommand = new init_command_1.InitCommand(); const result = await initCommand.execute({ verbose: options.verbose }); if (result.success) { logger_service_1.logger.success(result.message || 'Private git tracking initialized successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to initialize private git tracking'); process.exit(result.exitCode); } } catch (error) { handleError(error, 'init'); } }); // Status command commander_1.program .command('status') .description('Show status of both main and private repositories') .action(async (options) => { try { const statusCommand = new status_command_1.StatusCommand(); const result = await statusCommand.execute({ verbose: options.verbose }); if (result.success) { logger_service_1.logger.info(result.message || 'Status retrieved successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to get status'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Private status command (detailed private repo status only) commander_1.program .command('private-status') .description('Show detailed status of private repository only') .action(async (options) => { try { const statusCommand = new status_command_1.StatusCommand(); const result = await statusCommand.executePrivateOnly({ verbose: options.verbose }); if (result.success) { logger_service_1.logger.info(result.message || 'Private status retrieved successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to get private status'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Add command commander_1.program .command('add <path...>') .description('Add file(s) or directory(ies) to private tracking') .action(async (paths, options) => { try { const addCommand = new add_command_1.AddCommand(); const result = await addCommand.execute(paths, { verbose: options.verbose }); if (result.success) { logger_service_1.logger.success(result.message || 'Files added to private tracking successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to add files to private tracking'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Commit command commander_1.program .command('commit') .description('Commit changes to private repository') .option('-m, --message <message>', 'Commit message') .action(async (options) => { try { const commitCommand = new commit_command_1.CommitCommand(); const result = await commitCommand.execute(options.message, { verbose: options.verbose }); if (result.success) { logger_service_1.logger.success(result.message || 'Changes committed to private repository successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to commit changes to private repository'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Preset commands const presetCmd = commander_1.program .command('preset') .description('Manage file presets for common workflows (apply|define|undefine|list|show)'); presetCmd .command('apply <preset-name>') .description('Apply a preset by adding all its paths to private tracking') .action(async (presetName, options) => { try { const presetCommand = new preset_command_1.PresetCommand(); const result = await presetCommand.apply(presetName, { verbose: options.parent?.parent?.verbose || false, }); if (result.success) { // Success message is handled by the command itself } else { logger_service_1.logger.error(result.message || 'Failed to apply preset'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); presetCmd .command('define <preset-name> <paths...>') .description('Define a new user preset with specified paths') .option('-g, --global', 'Create a global preset (available across all projects)') .action(async (presetName, paths, options) => { try { const presetCommand = new preset_command_1.PresetCommand(); const result = await presetCommand.define(presetName, paths, { verbose: options.parent?.parent?.verbose || false, global: options.global || false, }); if (result.success) { // Success message is handled by the command itself } else { logger_service_1.logger.error(result.message || 'Failed to define preset'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); presetCmd .command('undefine <preset-name>') .description('Remove a user-defined preset') .option('-g, --global', 'Remove a global preset') .action(async (presetName, options) => { try { const presetCommand = new preset_command_1.PresetCommand(); const result = await presetCommand.undefine(presetName, { verbose: options.parent?.parent?.verbose || false, global: options.global || false, }); if (result.success) { // Success message is handled by the command itself } else { logger_service_1.logger.error(result.message || 'Failed to remove preset'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); presetCmd .command('list') .description('List all available presets') .action(async (options) => { try { const presetCommand = new preset_command_1.PresetCommand(); const result = await presetCommand.list({ verbose: options.parent?.parent?.verbose || false, }); if (!result.success) { logger_service_1.logger.error(result.message || 'Failed to list presets'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); presetCmd .command('show <preset-name>') .description('Show details about a specific preset') .action(async (presetName, options) => { try { const presetCommand = new preset_command_1.PresetCommand(); const result = await presetCommand.show(presetName, { verbose: options.parent?.parent?.verbose || false, }); if (!result.success) { logger_service_1.logger.error(result.message || 'Failed to show preset'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Git log command commander_1.program .command('log') .description('Show commit history of private repository') .option('-n, --max-count <number>', 'Limit number of commits', '10') .option('--oneline', 'Show each commit on a single line') .action(async (options) => { try { const gitOpsCommand = new gitops_command_1.GitOpsCommand(); const result = await gitOpsCommand.log({ maxCount: parseInt(options.maxCount) || 10, oneline: options.oneline, }, { verbose: options.verbose }); if (!result.success) { logger_service_1.logger.error(result.message || 'Failed to get commit history'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Git add-changes command commander_1.program .command('add-changes') .description('Stage changes in private repository') .option('-A, --all', 'Stage all changes') .action(async (options) => { try { const gitOpsCommand = new gitops_command_1.GitOpsCommand(); const result = await gitOpsCommand.addChanges(options.all, { verbose: options.verbose }); if (result.success) { logger_service_1.logger.success(result.message || 'Changes staged successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to stage changes'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Git diff command commander_1.program .command('diff') .description('Show differences in private repository') .option('--cached', 'Show staged changes') .option('--name-only', 'Show only file names') .action(async (options) => { try { const gitOpsCommand = new gitops_command_1.GitOpsCommand(); const result = await gitOpsCommand.diff({ cached: options.cached, nameOnly: options.nameOnly, }, { verbose: options.verbose }); if (!result.success) { logger_service_1.logger.error(result.message || 'Failed to get differences'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Git branch command commander_1.program .command('branch [name]') .description('List or create branches in private repository') .option('-b, --create', 'Create new branch') .action(async (name, options) => { try { const gitOpsCommand = new gitops_command_1.GitOpsCommand(); const result = await gitOpsCommand.branch(name, options.create, { verbose: options.verbose, }); if (result.success && name && options.create) { logger_service_1.logger.success(result.message || 'Branch created successfully'); } else if (!result.success) { logger_service_1.logger.error(result.message || 'Failed to perform branch operation'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Git checkout command commander_1.program .command('checkout <target>') .description('Switch branches or restore files in private repository') .action(async (target, options) => { try { const gitOpsCommand = new gitops_command_1.GitOpsCommand(); const result = await gitOpsCommand.checkout(target, { verbose: options.verbose }); if (result.success) { logger_service_1.logger.success(result.message || 'Checkout completed successfully'); } else { logger_service_1.logger.error(result.message || 'Failed to checkout'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Cleanup command commander_1.program .command('cleanup') .description('Fix and repair private git tracking system') .option('--force', 'Force cleanup operations') .action(async (options) => { try { const cleanupCommand = new cleanup_command_1.CleanupCommand(); const result = await cleanupCommand.execute(options.force, { verbose: options.verbose }); if (result.success) { logger_service_1.logger.success(result.message || 'Cleanup completed successfully'); } else { logger_service_1.logger.error(result.message || 'Cleanup completed with issues'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Reset command commander_1.program .command('reset') .description('Completely remove pgit setup and restore all tracked files to main repository') .option('--force', 'Skip confirmation prompt') .option('--dry-run', 'Show what would be done without executing') .action(async (options) => { try { const resetCommand = new reset_command_1.ResetCommand(); const result = await resetCommand.execute(options.force, { verbose: options.verbose, dryRun: options.dryRun, }); if (result.success) { logger_service_1.logger.success(result.message || 'Reset completed successfully'); } else { logger_service_1.logger.error(result.message || 'Reset failed'); process.exit(result.exitCode); } } catch (error) { handleError(error); } }); // Handle help command specially to ensure proper exit codes const args = process.argv.slice(2); if (args.includes('--help') || args.includes('-h') || (args.length === 1 && args[0] === 'help')) { commander_1.program.outputHelp(); process.exit(0); } // Global error handler - only override for actual errors, not help/version commander_1.program.exitOverride((err) => { // Allow normal exit codes for help and version commands if (err.code === 'commander.version' || err.code === 'commander.helpDisplayed') { process.exit(0); } // Force exit code 1 for other errors process.exit(1); }); // Parse command line arguments await commander_1.program.parseAsync(process.argv); } /** * Handle errors with enhanced formatting and recovery suggestions */ function handleError(error, command) { const context = enhanced_error_handler_1.EnhancedErrorHandler.createContext(command, [], process.cwd()); enhanced_error_handler_1.EnhancedErrorHandler.handleError(error, context); process.exit(1); } // Run the CLI if (require.main === module) { main().catch(handleError); } //# sourceMappingURL=cli.js.map