run method

  1. @override
Future<void> run()
override

Runs this command.

The return value is wrapped in a Future if necessary and returned by CommandRunner.runCommand.

Implementation

@override
Future<void> run() async {
  final headless = _headless;
  // --no-ui implies --yes (no interactive prompt in headless mode)
  final yesFlag = (argResults!['yes'] as bool) || headless;

  final projectDir = findNitroProjectRoot();
  if (projectDir == null) {
    stderr.writeln(headless ? '[nitro:error] No Nitro project found.' : '❌ No Nitro project found.');
    exit(1);
  }
  final pubspec = File(p.join(projectDir.path, 'pubspec.yaml'));
  String pluginName = 'unknown';
  for (final line in pubspec.readAsLinesSync()) {
    if (line.startsWith('name: ')) {
      pluginName = line.replaceFirst('name: ', '').trim();
      break;
    }
  }
  Directory.current = projectDir;

  // ── Preflight: detect managed content removed by manual edits ─────────────
  final issues = detectManagedContentIssues(baseDir: projectDir.path);
  if (issues.isNotEmpty) {
    stderr.writeln('');
    if (headless) {
      stderr.writeln('[nitro:warn] managed content missing from plugin files:');
      for (final issue in issues) {
        stderr.writeln('[nitro:warn]   ${issue.file}: ${issue.description}');
      }
      stderr.writeln('[nitro:info] proceeding with re-injection (--no-ui implies --yes)');
    } else {
      stderr.writeln('  \x1B[1;33m⚠  nitrogen link detected managed content missing from plugin files:\x1B[0m');
      stderr.writeln('');
      final byFile = <String, List<String>>{};
      for (final issue in issues) {
        byFile.putIfAbsent(issue.file, () => []).add(issue.description);
      }
      for (final entry in byFile.entries) {
        stderr.writeln('  \x1B[1;37m${entry.key}\x1B[0m');
        for (final desc in entry.value) {
          stderr.writeln('    \x1B[33m• $desc\x1B[0m');
        }
      }
      stderr.writeln('');
      stderr.writeln('  These sections are managed by nitrogen link.');
      stderr.writeln('  Re-running link will restore them automatically.');

      if (!yesFlag) {
        stderr.write('\n  Re-inject missing sections? [Y/n] ');
        final answer = (stdin.readLineSync() ?? '').trim().toLowerCase();
        if (answer == 'n' || answer == 'no') {
          stderr.writeln('\n  Skipped. Run `nitrogen link --yes` to suppress this prompt.');
          return;
        }
      } else {
        stderr.writeln('  (--yes flag set — proceeding without confirmation)');
      }
      stderr.writeln('');
    }
  }

  if (headless) {
    await _runHeadless(pluginName, projectDir.path);
  } else {
    final result = LinkResult();
    await runApp(LinkView(pluginName: pluginName, result: result));
    if (result.success) {
      stdout.writeln('\n  \x1B[1;32m✨ $pluginName linked\x1B[0m');
    }
  }
}