parse static method

GoogleServicesConfig parse(
  1. String text, {
  2. String source = '<memory>',
})

Implementation

static GoogleServicesConfig parse(String text, {String source = '<memory>'}) {
  final Object? decoded = json.decode(text);
  if (decoded is! Map<String, Object?>) {
    throw FormatException('$source: expected a JSON object');
  }

  Map<String, Object?> obj(Map<String, Object?> from, String key) {
    final v = from[key];
    if (v is! Map<String, Object?>) {
      throw FormatException('$source: missing object "$key"');
    }
    return v;
  }

  String str(Map<String, Object?> from, String key) {
    final v = from[key];
    if (v is! String || v.isEmpty) {
      throw FormatException('$source: missing string "$key"');
    }
    return v;
  }

  final info = obj(decoded, 'project_info');

  // One project can register several apps. Without a package name to match,
  // a single client is unambiguous; more than one is not, so say so instead
  // of silently taking the first.
  final clients = decoded['client'];
  if (clients is! List || clients.isEmpty) {
    throw FormatException('$source: no "client" entries');
  }
  if (clients.length > 1) {
    throw FormatException(
      '$source: ${clients.length} clients registered; this loader needs '
      'exactly one to pick without ambiguity',
    );
  }
  final client = clients.first;
  if (client is! Map<String, Object?>) {
    throw FormatException('$source: malformed "client" entry');
  }

  final keys = client['api_key'];
  if (keys is! List || keys.isEmpty || keys.first is! Map<String, Object?>) {
    throw FormatException('$source: no "api_key" for the client');
  }

  return GoogleServicesConfig(
    appId: str(obj(client, 'client_info'), 'mobilesdk_app_id'),
    apiKey: str(keys.first as Map<String, Object?>, 'current_key'),
    projectId: str(info, 'project_id'),
    // Absent for a project with no Realtime Database, which is most of
    // them. Failing here would stop an app that never asks for one.
    databaseUrl: switch (info['firebase_url']) {
      final String v when v.isNotEmpty => v,
      _ => null,
    },
    storageBucket: info['storage_bucket'] as String?,
    messagingSenderId: info['project_number'] as String?,
  );
}