run method

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

Runs this command.

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

Implementation

@override
Future<int> run() async {
  final filePath = argResults!['file'] as String;
  final merge = argResults!['merge'] as bool;
  final apply = argResults!['apply'] as bool;
  final verbose = argResults!['verbose'] as bool;

  final result = OperationResult();

  try {
    stdout.writeln('Loading JSON from $filePath...');
    final json = await JsonValidator.loadJsonFile(filePath);
    final collectionMap = JsonValidator.validateObject(json, 'Root JSON');

    final importPlan = _validateImportStructure(collectionMap);

    stdout
      ..writeln('\n=== Import Plan ===')
      ..writeln('Collections: ${importPlan.length}')
      ..writeln('Mode: ${merge ? 'Merge' : 'Replace'}');

    var totalDocs = 0;
    for (final collection in importPlan) {
      stdout.writeln(
        '  ${collection.path}: ${collection.documents.length} documents'
        '${collection.idFieldName != null ? ' (ID field: ${collection.idFieldName})' : ''}',
      );
      totalDocs += collection.documents.length;
    }
    stdout.writeln('Total documents: $totalDocs');

    if (!apply) {
      stdout
        ..writeln('\n⚠️  DRY RUN MODE - No changes will be made')
        ..writeln('Use --apply to execute the operation');
      return 0;
    }

    stdout.writeln('\nConnecting to Firestore...');
    final client = await FirestoreClient.fromEnvironment();

    stdout.writeln(
      'Importing $totalDocs documents across ${importPlan.length} collections...',
    );

    for (final collection in importPlan) {
      stdout.writeln('\nCollection: ${collection.path}');

      for (var i = 0; i < collection.documents.length; i++) {
        final doc = collection.documents[i];
        String? docId;

        if (collection.idFieldName != null &&
            doc.containsKey(collection.idFieldName)) {
          docId = doc[collection.idFieldName]?.toString();
        }

        await _writeDocument(
          client: client,
          collectionPath: collection.firestorePath,
          documentId: docId,
          data: doc,
          merge: merge,
          result: result,
          index: i,
        );

        if ((i + 1) % 10 == 0 || i == collection.documents.length - 1) {
          stdout.write(
            '\r  Progress: ${i + 1}/${collection.documents.length}',
          );
        }
      }
      stdout.writeln();
    }

    result.printSummary(verbose: verbose);
    return result.hasErrors ? 1 : 0;
  } on Exception catch (e) {
    stderr.writeln('Error: $e');
    return 2;
  }
}