injectFirebase static method

void injectFirebase({
  1. required bool separate,
  2. String? flavor,
})

Injects Firebase initialization code into the entry point files. If separate is true, it injects into lib/main/main_<flavor>.dart. Otherwise, it injects into lib/main.dart.

Implementation

static void injectFirebase({required bool separate, String? flavor}) {
  final root = ConfigService.root;
  final config = ConfigService.load();
  final strategy = config.firebase?.strategy;
  final flavors = config.flavors;

  if (separate) {
    if (flavor == null) {
      for (final f in flavors) {
        injectFirebase(separate: true, flavor: f);
      }
      return;
    }

    final mainPath = p.join(root, 'lib/main/main_$flavor.dart');
    final file = File(mainPath);
    if (!file.existsSync()) return;

    final optionsFile = strategy == 'shared_id_single_project'
        ? 'firebase_options.dart'
        : 'firebase_options_$flavor.dart';

    final configFile = File(p.join(root, 'lib/$optionsFile'));
    if (!configFile.existsSync()) return;

    var content = file.readAsStringSync();

    // 1. Manage Imports
    if (!content.contains('firebase_core.dart')) {
      content = "import 'package:firebase_core/firebase_core.dart';\n"
          "import '../$optionsFile';\n$content";
    } else if (!content.contains(optionsFile)) {
      content = "import '../$optionsFile';\n$content";
    }

    // 2. Inject Initialization
    if (content.contains('Firebase.initializeApp')) {
      return; // Skip if already initialized
    }

    final initRegex = RegExp(
      r'^(\s*)AppConfig\.init\s*\(.*\);',
      multiLine: true,
    );
    final match = initRegex.firstMatch(content);

    if (match != null) {
      final indent = match.group(1) ?? '  ';
      final ensureInitialized =
          content.contains('WidgetsFlutterBinding.ensureInitialized()')
              ? ""
              : "${indent}WidgetsFlutterBinding.ensureInitialized();\n";
      final initBlock =
          "\n$ensureInitialized${indent}await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);";

      final mainRegex = RegExp(r'void main\s*\(\s*\)\s*(async\s*)?{');
      content = content.replaceFirst(mainRegex, 'void main() async {');
      content = content.replaceFirst(
        match.group(0)!,
        '${match.group(0)!}$initBlock',
      );
      file.writeAsStringSync(content);
    }
  } else {
    // Single Main Strategy
    final mainPath = p.join(root, 'lib/main.dart');
    final file = File(mainPath);
    if (!file.existsSync()) return;

    var content = file.readAsStringSync();

    if (strategy == 'shared_id_single_project') {
      final configFile = File(p.join(root, 'lib/firebase_options.dart'));
      if (!configFile.existsSync()) return;

      if (!content.contains('firebase_core.dart')) {
        content = "import 'package:firebase_core/firebase_core.dart';\n"
            "import 'firebase_options.dart';\n$content";
      }

      if (!content.contains('Firebase.initializeApp')) {
        final initRegex = RegExp(
          r'^(\s*)AppConfig\.init\s*\(.*\);',
          multiLine: true,
        );
        final match = initRegex.firstMatch(content);
        if (match != null) {
          final indent = match.group(1) ?? '  ';
          final ensureInitialized =
              content.contains('WidgetsFlutterBinding.ensureInitialized()')
                  ? ""
                  : "${indent}WidgetsFlutterBinding.ensureInitialized();\n";
          final initBlock =
              "\n$ensureInitialized${indent}await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);";

          final mainRegex = RegExp(r'void main\s*\(\s*\)\s*(async\s*)?{');
          content = content.replaceFirst(mainRegex, 'void main() async {');
          content = content.replaceFirst(
            match.group(0)!,
            '${match.group(0)!}$initBlock',
          );
        }
      }
    } else {
      // Multi-Options Injection (Unique ID strategies)
      final configuredFlavors = flavors.where((f) {
        return File(
          p.join(root, 'lib/firebase_options_$f.dart'),
        ).existsSync();
      }).toList();

      if (configuredFlavors.isEmpty) return;

      // Clean existing to regenerate
      content = content.replaceAll(
        RegExp(
          r'''import ['"]package:firebase_core/firebase_core\.dart['"];\n?''',
        ),
        '',
      );
      content = content.replaceAll(
        RegExp(r'''import ['"]firebase_options_.*\.dart['"] as \w+;\n?'''),
        '',
      );

      final importBuffer = StringBuffer();
      importBuffer.writeln(
        "import 'package:firebase_core/firebase_core.dart';",
      );
      for (final f in configuredFlavors) {
        importBuffer.writeln("import 'firebase_options_$f.dart' as $f;");
      }
      content = importBuffer.toString() + content.trimLeft();

      final initRegex = RegExp(
        r'await Firebase\.initializeApp\s*\([\s\S]*?\);',
      );
      String indent = '  ';
      final configInitRegex = RegExp(
        r'^(\s*)AppConfig\.init\s*\(.*\);',
        multiLine: true,
      );
      final configMatch = configInitRegex.firstMatch(content);
      if (configMatch != null) indent = configMatch.group(1) ?? '  ';

      final buffer = StringBuffer();
      buffer.writeln("await Firebase.initializeApp(");
      buffer.writeln("$indent  options: switch (flavor) {");
      for (final f in configuredFlavors) {
        buffer.writeln(
          "$indent    Flavor.$f => $f.DefaultFirebaseOptions.currentPlatform,",
        );
      }
      if (configuredFlavors.length < flavors.length) {
        buffer.writeln(
          "$indent    _ => ${configuredFlavors.first}.DefaultFirebaseOptions.currentPlatform,",
        );
      }
      buffer.writeln("$indent  },");
      buffer.write("$indent)");

      if (content.contains('Firebase.initializeApp')) {
        content = content.replaceFirst(
          initRegex,
          buffer.toString().trim() + ';',
        );
      } else if (configMatch != null) {
        final indent = configMatch.group(1) ?? '  ';
        final ensureInitialized =
            content.contains('WidgetsFlutterBinding.ensureInitialized()')
                ? ""
                : "${indent}WidgetsFlutterBinding.ensureInitialized();\n";
        final initBlock =
            "\n$ensureInitialized${indent}${buffer.toString().trim()};";
        final mainRegex = RegExp(r'void main\s*\(\s*\)\s*(async\s*)?{');
        content = content.replaceFirst(mainRegex, 'void main() async {');
        content = content.replaceFirst(
          configMatch.group(0)!,
          '${configMatch.group(0)!}$initBlock',
        );
      }
    }
    file.writeAsStringSync(content);
  }
}