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 {
  stdout.writeln('Generate a key in the mobile app → Settings → API Keys.');
  stdout.write('Paste your API key: ');

  // Disable echo so the key isn't visible in the terminal
  try {
    stdin.echoMode = false;
  } catch (_) {
    // echoMode not supported in all environments — continue anyway
  }

  final rawKey = stdin.readLineSync()?.trim() ?? '';

  try {
    stdin.echoMode = true;
  } catch (_) {}
  stdout.writeln('');

  if (rawKey.isEmpty) {
    AppLogger.error('No key entered.');
    exit(ExitCodes.usage);
  }

  if (!rawKey.startsWith('appflight_')) {
    AppLogger.error('Invalid format. Keys must start with "appflight_".');
    exit(ExitCodes.authRejected);
  }

  AppLogger.info('Verifying key…');
  try {
    final dio = ApiClient.instance.forKey(rawKey);
    final resp = await dio.get(Endpoints.whoami);
    final data = resp.data['data'] as Map<String, dynamic>;

    final creds = Credentials(
      apiKey: rawKey,
      uid: data['uid'] as String? ?? '',
      email: data['email'] as String? ?? '',
    );
    creds.save();

    AppLogger.success('Logged in as ${creds.email}');
  } on DioException catch (e) {
    final status = e.response?.statusCode;
    if (status == 401 || status == 403) {
      AppLogger.error('Key rejected. Check it and try again.');
      exit(ExitCodes.authRejected);
    }
    AppLogger.error('Network error: ${e.message}');
    exit(ExitCodes.usage);
  }
}