UNPKG

context-forge

Version:

AI orchestration platform with autonomous teams, enhancement planning, migration tools, 25+ slash commands, checkpoints & hooks. Multi-IDE: Claude, Cursor, Windsurf, Cline, Copilot

507 lines • 18.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.runMigrationPrompts = runMigrationPrompts; const inquirer_1 = __importDefault(require("inquirer")); const chalk_1 = __importDefault(require("chalk")); const migrationAnalyzer_1 = require("../../services/migrationAnalyzer"); const ideSelection_1 = require("./ideSelection"); const projectConfig_1 = require("./projectConfig"); async function runMigrationPrompts(basicAnalysis, targetStackHint, ideOverride, quickMode = false) { console.log(chalk_1.default.blue.bold('\nšŸ”„ Migration Configuration\n')); // Step 1: Basic project info const projectInfo = await getMigrationProjectInfo(basicAnalysis); // Step 2: Target stack selection const targetStack = await selectTargetStack(basicAnalysis, targetStackHint); // Step 3: Analyze migration const migrationAnalyzer = new migrationAnalyzer_1.MigrationAnalyzer(process.cwd(), targetStack); const migrationAnalysis = await migrationAnalyzer.analyzeMigration(basicAnalysis); // Step 4: Migration strategy const strategy = quickMode ? migrationAnalysis.recommendedStrategy : await selectMigrationStrategy(migrationAnalysis); // Step 5: Shared resources configuration const sharedResources = quickMode ? migrationAnalysis.sharedResources : await configureSharedResources(migrationAnalysis.sharedResources); // Step 6: Migration phases const phases = quickMode ? migrationAnalysis.suggestedPhases : await configureMigrationPhases(migrationAnalysis.suggestedPhases); // Step 7: Rollback strategy const rollbackStrategy = await migrationAnalyzer.generateRollbackStrategy(phases, sharedResources); // Step 8: IDE selection const targetIDEs = ideOverride || (await (0, ideSelection_1.ideSelection)()); // Step 9: Project configuration const config = await (0, projectConfig_1.projectConfig)(); // Step 10: Checkpoint configuration (enhanced for migration) let checkpoints = undefined; if (config.extras.checkpoints) { checkpoints = await migrationCheckpointConfig(phases); } // Build migration config const migrationConfig = { strategy, sourceStack: migrationAnalysis.sourceStack, targetStack: migrationAnalysis.targetStack, sharedResources, migrationPhases: phases, rollbackStrategy, riskLevel: migrationAnalysis.complexity.level, checkpoints: checkpoints?.triggers.map((t) => ({ phaseId: phases[0].id, // Will be mapped properly name: t.name, description: t.description, validationSteps: [], rollbackEnabled: true, requiresApproval: t.category === 'critical', })), }; return { ...projectInfo, targetIDEs, techStack: { frontend: targetStack.name, backend: targetStack.name, database: sharedResources.find((r) => r.type === 'database')?.name, }, features: [], ...config, checkpointConfig: checkpoints, migrationConfig, isRetrofit: true, }; } async function getMigrationProjectInfo(analysis) { console.log(chalk_1.default.cyan('šŸ“‹ Migration Project Information')); const { projectName, description } = await inquirer_1.default.prompt([ { type: 'input', name: 'projectName', message: 'Project name:', default: process.cwd().split('/').pop() + '-migration', validate: (input) => input.trim().length > 0 || 'Project name is required', }, { type: 'input', name: 'description', message: 'Migration description:', default: `Migration from ${analysis.techStack[0]} to new technology stack`, validate: (input) => input.trim().length > 0 || 'Description is required', }, ]); return { projectName, description, projectType: analysis.projectType.toLowerCase(), }; } async function selectTargetStack(analysis, hint) { console.log(chalk_1.default.cyan('\nšŸŽÆ Target Technology Stack')); console.log(chalk_1.default.gray(`Current stack: ${analysis.techStack.join(', ')}\n`)); if (hint.name) { const { confirmTarget } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirmTarget', message: `Migrate to ${hint.name}?`, default: true, }, ]); if (confirmTarget) { return { name: hint.name, type: 'fullstack', docs: '', dependencies: [], ...hint, }; } } // Common migration paths const migrationOptions = getMigrationOptions(analysis.techStack); const { targetStack } = await inquirer_1.default.prompt([ { type: 'list', name: 'targetStack', message: 'Select target technology stack:', choices: [...migrationOptions, { name: 'Other (specify)', value: 'other' }], }, ]); if (targetStack === 'other') { const { customStack } = await inquirer_1.default.prompt([ { type: 'input', name: 'customStack', message: 'Enter target stack name:', validate: (input) => input.trim().length > 0 || 'Stack name is required', }, ]); return { name: customStack, type: 'fullstack', docs: '', dependencies: [], }; } return { name: targetStack, type: 'fullstack', docs: '', dependencies: [], }; } function getMigrationOptions(currentStack) { const options = []; // Python migrations if (currentStack.some((s) => s.includes('Flask') || s.includes('Django'))) { options.push({ name: 'FastAPI (Modern Python async)', value: 'FastAPI' }, { name: 'Next.js (Full-stack React)', value: 'Next.js' }, { name: 'Express.js (Node.js)', value: 'Express' }); } // JavaScript migrations if (currentStack.some((s) => s.includes('Express') || s.includes('React'))) { options.push({ name: 'Next.js (Full-stack React)', value: 'Next.js' }, { name: 'Fastify (Fast Node.js)', value: 'Fastify' }, { name: 'NestJS (Enterprise Node.js)', value: 'NestJS' }); } // Legacy migrations options.push({ name: 'Next.js 15 (Latest React)', value: 'Next.js' }, { name: 'SvelteKit (Modern alternative)', value: 'SvelteKit' }, { name: 'Remix (Full-stack React)', value: 'Remix' }); return options; } async function selectMigrationStrategy(analysis) { console.log(chalk_1.default.cyan('\nšŸš€ Migration Strategy')); console.log(chalk_1.default.gray(`Recommended: ${analysis.recommendedStrategy}\n`)); const { strategy } = await inquirer_1.default.prompt([ { type: 'list', name: 'strategy', message: 'Select migration strategy:', choices: [ { name: 'Parallel Run - Both systems run simultaneously (safest)', value: 'parallel-run', }, { name: 'Incremental - Migrate features one by one', value: 'incremental', }, { name: 'Big Bang - Complete replacement at once (fastest)', value: 'big-bang', }, ], default: analysis.recommendedStrategy, }, ]); return strategy; } async function configureSharedResources(detected) { if (detected.length === 0) { return []; } console.log(chalk_1.default.cyan('\nšŸ”— Shared Resources Configuration')); console.log(chalk_1.default.gray('Detected shared resources that need special handling:\n')); detected.forEach((resource) => { const icon = resource.criticalityLevel === 'critical' ? 'šŸ”“' : resource.criticalityLevel === 'high' ? '🟔' : '🟢'; console.log(`${icon} ${resource.name} (${resource.type})`); console.log(` ${chalk_1.default.gray(resource.description)}`); }); const { confirmResources } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirmResources', message: 'Are these shared resources correct?', default: true, }, ]); if (!confirmResources) { // Allow manual configuration return await manuallyConfigureResources(detected); } // Enhance migration strategies for critical resources const enhanced = []; for (const resource of detected) { if (resource.criticalityLevel === 'critical') { console.log(chalk_1.default.yellow(`\nāš ļø Critical Resource: ${resource.name}`)); const { strategy } = await inquirer_1.default.prompt([ { type: 'input', name: 'strategy', message: 'Migration strategy for this resource:', default: resource.migrationStrategy, }, ]); enhanced.push({ ...resource, migrationStrategy: strategy, }); } else { enhanced.push(resource); } } return enhanced; } async function manuallyConfigureResources(suggested) { const resources = [...suggested]; const { addMore } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'addMore', message: 'Add additional shared resources?', default: false, }, ]); if (addMore) { let adding = true; while (adding) { const resource = await inquirer_1.default.prompt([ { type: 'list', name: 'type', message: 'Resource type:', choices: ['database', 'api', 'auth', 'storage', 'cache', 'queue'], }, { type: 'input', name: 'name', message: 'Resource name:', validate: (input) => input.trim().length > 0 || 'Name is required', }, { type: 'input', name: 'description', message: 'Description:', }, { type: 'list', name: 'criticalityLevel', message: 'Criticality level:', choices: ['low', 'medium', 'high', 'critical'], }, { type: 'input', name: 'migrationStrategy', message: 'Migration strategy:', }, ]); resources.push(resource); const { continueAdding } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'continueAdding', message: 'Add another resource?', default: false, }, ]); adding = continueAdding; } } return resources; } async function configureMigrationPhases(suggested) { console.log(chalk_1.default.cyan('\nšŸ“… Migration Phases')); console.log(chalk_1.default.gray('Suggested migration phases:\n')); suggested.forEach((phase, index) => { console.log(`${index + 1}. ${chalk_1.default.bold(phase.name)} (${phase.estimatedDuration})`); console.log(` ${chalk_1.default.gray(phase.description)}`); if (phase.rollbackPoint) { console.log(` ${chalk_1.default.green('āœ“ Rollback point')}`); } }); const { usePhases } = await inquirer_1.default.prompt([ { type: 'list', name: 'usePhases', message: 'How would you like to configure phases?', choices: [ { name: 'Use suggested phases', value: 'suggested' }, { name: 'Modify suggested phases', value: 'modify' }, { name: 'Create custom phases', value: 'custom' }, ], }, ]); switch (usePhases) { case 'suggested': return suggested; case 'modify': return await modifyPhases(suggested); case 'custom': return await createCustomPhases(); default: return suggested; } } async function modifyPhases(phases) { const modified = [...phases]; for (let i = 0; i < modified.length; i++) { const phase = modified[i]; console.log(chalk_1.default.cyan(`\nšŸ“ Phase ${i + 1}: ${phase.name}`)); const { action } = await inquirer_1.default.prompt([ { type: 'list', name: 'action', message: 'What would you like to do?', choices: [ { name: 'Keep as is', value: 'keep' }, { name: 'Modify details', value: 'modify' }, { name: 'Remove phase', value: 'remove' }, ], }, ]); if (action === 'modify') { const updates = await inquirer_1.default.prompt([ { type: 'input', name: 'name', message: 'Phase name:', default: phase.name, }, { type: 'input', name: 'estimatedDuration', message: 'Estimated duration:', default: phase.estimatedDuration, }, { type: 'confirm', name: 'rollbackPoint', message: 'Is this a rollback point?', default: phase.rollbackPoint, }, ]); modified[i] = { ...phase, ...updates, }; } else if (action === 'remove') { modified.splice(i, 1); i--; // Adjust index } } return modified; } async function createCustomPhases() { const phases = []; let addMore = true; let phaseIndex = 0; while (addMore) { console.log(chalk_1.default.cyan(`\nšŸ“‹ Phase ${phaseIndex + 1}`)); const phase = await inquirer_1.default.prompt([ { type: 'input', name: 'name', message: 'Phase name:', validate: (input) => input.trim().length > 0 || 'Name is required', }, { type: 'input', name: 'description', message: 'Description:', validate: (input) => input.trim().length > 0 || 'Description is required', }, { type: 'input', name: 'estimatedDuration', message: 'Estimated duration (e.g., "1-2 weeks"):', default: '1-2 weeks', }, { type: 'confirm', name: 'rollbackPoint', message: 'Is this a rollback point?', default: true, }, ]); phases.push({ id: `phase-${phaseIndex}`, name: phase.name, description: phase.description, estimatedDuration: phase.estimatedDuration, rollbackPoint: phase.rollbackPoint, dependencies: phaseIndex > 0 ? [`phase-${phaseIndex - 1}`] : [], criticalCheckpoints: [], risks: [], validationCriteria: [], }); const { continueAdding } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'continueAdding', message: 'Add another phase?', default: phases.length < 3, }, ]); addMore = continueAdding; phaseIndex++; } return phases; } async function migrationCheckpointConfig(phases) { console.log(chalk_1.default.cyan('\nšŸ›‘ Migration Checkpoint Configuration')); console.log(chalk_1.default.gray('Configure checkpoints for critical migration milestones\n')); const checkpointTriggers = [ { id: 'migration-start', name: 'Migration Start', description: 'Verify readiness before starting migration', category: 'critical', autoTrigger: false, conditions: ['migration', 'start', 'begin'], }, { id: 'shared-resource', name: 'Shared Resource Access', description: 'Verify shared resource connectivity', category: 'critical', autoTrigger: true, conditions: ['database', 'auth', 'shared', 'connection'], }, { id: 'phase-complete', name: 'Phase Completion', description: 'Verify phase completion before proceeding', category: 'important', autoTrigger: true, conditions: ['phase', 'complete', 'finished'], }, { id: 'rollback-point', name: 'Rollback Point', description: 'Confirm before passing rollback point', category: 'critical', autoTrigger: true, conditions: ['rollback', 'point', 'critical'], }, { id: 'go-live', name: 'Production Cutover', description: 'Final verification before production switch', category: 'critical', autoTrigger: false, conditions: ['production', 'cutover', 'go-live'], }, ]; // Add phase-specific checkpoints phases.forEach((phase) => { if (phase.rollbackPoint) { checkpointTriggers.push({ id: `${phase.id}-complete`, name: `${phase.name} Complete`, description: `Verify ${phase.name} completion`, category: 'important', autoTrigger: true, conditions: [phase.id, 'complete'], }); } }); return { enabled: true, triggers: checkpointTriggers, }; } //# sourceMappingURL=migration.js.map