UNPKG

deprecopilot

Version:

Automated dependency management with AI-powered codemods

332 lines (294 loc) 10.9 kB
#!/usr/bin/env node import { createRequire } from 'module' const require = createRequire(import.meta.url) const pkg = require('../package.json') import updateNotifier from 'update-notifier' import { audit } from '../dist/commands/audit.js' import { upgrade } from '../dist/commands/upgrade.js' import { fix } from '../dist/commands/fix.js' import { telemetry } from '../dist/commands/telemetry.js' import { logger } from '../dist/lib/logger.js' import inquirer from 'inquirer' updateNotifier({ pkg }).notify() const args = process.argv.slice(2) const command = args[0] function extractAIFlags(args) { const flags = {} for (const arg of args) { if (arg === '--ai') flags.ai = true if (arg === '--no-ai') flags.ai = false if (arg.startsWith('--llm-provider=')) flags.llmProvider = arg.split('=')[1] } return flags } function showHelp() { process.stdout.write(`Usage: deprecopilot <command> [options] Commands: audit Audit dependencies for outdated and vulnerable packages upgrade Upgrade dependencies with optional codemods fix Apply codemods to fix breaking changes telemetry Manage telemetry settings Global Options: --verbose, -v Enable verbose output --silent, -s Suppress all output --json Output results in JSON format --log-file=FILE Write logs to specified file --help, -h Show command help --version, -V Show version information AI Codemod Options: --ai Enable AI-driven codemod generation (default: off) --no-ai Disable AI codemods --llm-provider Specify LLM provider (default: gemini) --preview Show codemod diff preview, do not modify files Examples: deprecopilot audit deprecopilot fix --preview --ai deprecopilot upgrade lodash --ai deprecopilot telemetry status For more information, see: https://github.com/triallord/deprecopilot `) } function showAuditHelp() { process.stdout.write(`Usage: deprecopilot audit [options] Audit your project for outdated and vulnerable dependencies. Options: --json Output results in JSON format --pretty Pretty-print JSON output --strict Enable strict security auditing --verbose Show detailed information --silent Suppress output Examples: deprecopilot audit deprecopilot audit --json deprecopilot audit --strict --verbose For more information, see: https://github.com/triallord/deprecopilot/docs/cli.md `) } function showUpgradeHelp() { process.stdout.write(`Usage: deprecopilot upgrade [packages...] [options] Upgrade dependencies to newer versions with optional codemod application. Arguments: packages... Specific packages to upgrade (optional, upgrades all if not specified) Options: --ai Enable AI-driven codemod generation --no-ai Disable AI codemods --llm-provider Specify LLM provider (default: gemini) --dry-run Show what would be upgraded without making changes --yes Skip confirmation prompts --interactive Interactive mode with prompts --json Output results in JSON format --verbose Show detailed information --silent Suppress output Examples: deprecopilot upgrade lodash express deprecopilot upgrade --interactive deprecopilot upgrade lodash --ai --dry-run deprecopilot upgrade --ai --llm-provider openai For more information, see: https://github.com/triallord/deprecopilot/docs/cli.md `) } function showFixHelp() { process.stdout.write(`Usage: deprecopilot fix [options] Apply codemods to fix breaking changes from dependency upgrades. Options: --preview Show codemod diff preview, do not modify files --all Apply codemods to all upgradable dependencies --ai Enable AI-driven codemod generation --no-ai Disable AI codemods --llm-provider Specify LLM provider (default: gemini) --dry-run Show what would be changed without applying --json Output results in JSON format --verbose Show detailed information --silent Suppress output Examples: deprecopilot fix --preview deprecopilot fix --all --ai deprecopilot fix --preview --json deprecopilot fix --dry-run --ai For more information, see: https://github.com/triallord/deprecopilot/docs/cli.md `) } function showTelemetryHelp() { process.stdout.write(`Usage: deprecopilot telemetry <command> Manage telemetry settings for deprecopilot. Commands: enable Enable telemetry collection disable Disable telemetry collection status Show current telemetry status Examples: deprecopilot telemetry enable deprecopilot telemetry disable deprecopilot telemetry status Telemetry is strictly opt-in and disabled by default. See PRIVACY.md for details about data collection and usage. For more information, see: https://github.com/triallord/deprecopilot/docs/cli.md `) } async function main() { const start = Date.now() let exitCode = 0 // Parse global flags const globalFlags = { verbose: false, silent: false, json: false, logFile: null } for (const arg of args) { if (arg === '--verbose') globalFlags.verbose = true if (arg === '--silent') globalFlags.silent = true if (arg === '--json') globalFlags.json = true if (arg.startsWith('--log-file=')) globalFlags.logFile = arg.split('=')[1] } logger.setVerbosity(globalFlags) if (globalFlags.logFile) logger.setLogFile(globalFlags.logFile) // Simplified context without plugins to avoid hanging const context = { plugins: [] } // Debug: log the command being executed console.error('DEBUG: command =', command) console.error('DEBUG: args =', args) try { switch (command) { case 'audit': { if (args.includes('--help') || args.includes('-h')) { showAuditHelp() process.exit(0) } const flags = {} for (const arg of args.slice(1)) { if (arg === '--json') flags.json = true if (arg === '--pretty') flags.pretty = true if (arg === '--strict') flags.strict = true if (arg === '--verbose') flags.verbose = true if (arg === '--silent') flags.silent = true } try { const exitCode = await audit(flags, context) process.exit(exitCode) } catch (error) { console.error('DEBUG: Audit error:', error) process.exit(1) } break } case 'upgrade': { if (args.includes('--help') || args.includes('-h')) { showUpgradeHelp() process.exit(0) } if (args.includes('--interactive')) { const answers = await inquirer.prompt([ { type: 'input', name: 'package', message: 'Which package do you want to upgrade?', validate: v => v ? true : 'Package name is required', }, { type: 'confirm', name: 'ai', message: 'Use AI codemod?', default: false, }, { type: 'confirm', name: 'dryRun', message: 'Dry run (no changes)?', default: true, }, { type: 'list', name: 'output', message: 'Output format?', choices: [ { name: 'Pretty', value: 'pretty' }, { name: 'JSON', value: 'json' }, ], default: 'pretty', }, ]) const flags = { ai: answers.ai, dryRun: answers.dryRun, json: answers.output === 'json', verbose: globalFlags.verbose, silent: globalFlags.silent, } const exitCode = await upgrade([answers.package], flags, context) process.exit(exitCode) break } const upArgs = [] const flags = {} for (const arg of args.slice(1)) { if (arg === '--ai') flags.ai = true else if (arg === '--no-ai') flags.ai = false else if (arg.startsWith('--llm-provider=')) flags.llmProvider = arg.split('=')[1] else if (arg === '--dry-run') flags.dryRun = true else if (arg === '--yes') flags.yes = true else if (arg.startsWith('--test=')) flags.test = arg.slice(7) else if (arg === '--no-codemod') flags.noCodemod = true else if (arg === '--rollback') flags.rollback = true else if (arg === '--verbose') flags.verbose = true else if (arg === '--silent') flags.silent = true else if (arg === '--json') flags.json = true else upArgs.push(arg) } const exitCode = await upgrade(upArgs, flags, context) process.exit(exitCode) break } case 'fix': { if (args.includes('--help') || args.includes('-h')) { showFixHelp() process.exit(0) } const flags = {} for (const arg of args.slice(1)) { if (arg === '--json') flags.json = true if (arg === '--all') flags.all = true if (arg === '--dry-run') flags.dryRun = true if (arg === '--ai') flags.ai = true if (arg === '--no-ai') flags.ai = false if (arg.startsWith('--llm-provider=')) flags.llmProvider = arg.split('=')[1] if (arg === '--verbose') flags.verbose = true if (arg === '--silent') flags.silent = true if (arg === '--preview') flags.previewOnly = true if (arg === '--breaking-changes') flags.breakingChanges = true } await fix(flags, context) process.exit(0) break } case 'telemetry': { if (args.includes('--help') || args.includes('-h')) { showTelemetryHelp() process.exit(0) } const exitCode = await telemetry(args.slice(1)) process.exit(exitCode) break } case '--help': case '-h': { showHelp() process.exit(0) } case '--version': case '-v': { process.stdout.write(`deprecopilot version ${pkg.version}\n`) process.exit(0) } default: { if (!command) { showHelp() process.exit(1) } else { process.stdout.write(`Unknown command: ${command}\n`) showHelp() process.exit(1) } } } } catch (e) { console.error('DEBUG: Main error:', e) exitCode = 1 process.exit(exitCode) } } main()