applyInteractive static method

Future<ApplyResult> applyInteractive(
  1. AnalysisResult analysisResult,
  2. Future<bool> promptUser(
    1. String message
    )
)

Apply specific changes interactively

Implementation

static Future<ApplyResult> applyInteractive(
  AnalysisResult analysisResult,
  Future<bool> Function(String message) promptUser,
) async {
  final changes = <DependencyChange>[];
  final appliedChanges = <String>[];

  try {
    // Create backup before making changes
    final backupCreated = await BackupService.createBackup();
    if (!backupCreated) {
      return ApplyResult(
        success: false,
        error: 'Failed to create backup',
        changes: <String>[],
      );
    }

    // Prompt for unused dependencies
    for (final dep in analysisResult.unusedDependencies) {
      final shouldRemove = await promptUser(
          '${OutputConfig.unusedIndicator} ${dep.name} — unused dependency. Remove it? [Y/n]');

      if (shouldRemove) {
        changes.add(DependencyChange(
          packageName: dep.name,
          action: ChangeAction.remove,
        ));
        appliedChanges.add('Removed unused dependency: ${dep.name}');
      }
    }

    // Prompt for misplaced dependencies
    final misplacedDeps = analysisResult.testOnlyDependencies
        .where((DependencyInfo dep) => dep.section == DependencySection.dependencies)
        .toList();

    for (final dep in misplacedDeps) {
      final shouldMove = await promptUser(
          '${OutputConfig.testOnlyIndicator} ${dep.name} — ${dep.usageDescription}. Move to dev_dependencies? [Y/n]');

      if (shouldMove) {
        changes.add(DependencyChange(
          packageName: dep.name,
          action: ChangeAction.moveToDevDependencies,
        ));
        appliedChanges.add('Moved to dev_dependencies: ${dep.name}');
      }
    }

    // Prompt for duplicate dependencies
    for (final duplicate in analysisResult.duplicates) {
      final versionInfo = duplicate.hasVersionConflict
          ? ' (versions: ${duplicate.dependenciesVersion} vs ${duplicate.devDependenciesVersion})'
          : '';

      final shouldFix = await promptUser(
          '${OutputConfig.warningEmoji} ${duplicate.name}$versionInfo — duplicate. ${duplicate.recommendationMessage}? [Y/n]');

      if (shouldFix) {
        if (duplicate.recommendedSection == DependencySection.dependencies) {
          changes.add(DependencyChange(
            packageName: duplicate.name,
            action: ChangeAction.removeFromDevDependencies,
          ));
          appliedChanges.add(
              'Removed duplicate from dev_dependencies: ${duplicate.name}');
        } else {
          changes.add(DependencyChange(
            packageName: duplicate.name,
            action: ChangeAction.removeFromDependencies,
          ));
          appliedChanges
              .add('Removed duplicate from dependencies: ${duplicate.name}');
        }
      }
    }

    // Apply changes if any
    if (changes.isNotEmpty) {
      final success = await PubspecManager.applyChanges(changes);
      if (!success) {
        // Restore backup if apply failed
        await BackupService.restoreFromBackup();
        return ApplyResult(
          success: false,
          error: 'Failed to apply changes - backup restored',
          changes: <String>[],
        );
      }
    }

    return ApplyResult(
      success: true,
      changes: appliedChanges,
      backupCreated: backupCreated,
    );
  } catch (e) {
    // Restore backup on error
    await BackupService.restoreFromBackup();
    return ApplyResult(
      success: false,
      error: 'Error applying changes: $e',
      changes: <String>[],
    );
  }
}