run method
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 collectionPath = argResults!['collection'] as String;
final filePath = argResults!['file'] as String;
final idField = argResults!['id-field'] 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 array = JsonValidator.validateArray(json, 'Root JSON');
final documents = JsonValidator.validateArrayOfObjects(
array,
'Documents',
);
final collection = PathValidator.validateCollectionPath(collectionPath);
stdout
..writeln('\n=== Operation Plan ===')
..writeln('Collection: $collectionPath')
..writeln('Documents: ${documents.length}')
..writeln('Mode: ${merge ? 'Merge' : 'Replace'}');
final preview = _analyzeDocuments(documents, idField);
stdout.writeln(
'ID Strategy: ${preview.withId} with ID field, ${preview.autoId} auto-ID',
);
if (verbose) {
stdout.writeln('\nDocument preview:');
for (
var i = 0;
i < (documents.length < 5 ? documents.length : 5);
i++
) {
final doc = documents[i];
final docId = idField != null ? doc[idField]?.toString() : null;
stdout.writeln(
' [${i + 1}] ${docId ?? '(auto-ID)'}: ${doc.length} fields',
);
}
if (documents.length > 5) {
stdout.writeln(' ... and ${documents.length - 5} more');
}
}
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('Writing ${documents.length} documents...');
for (var i = 0; i < documents.length; i++) {
final doc = documents[i];
String? docId;
if (idField != null && doc.containsKey(idField)) {
docId = doc[idField]?.toString();
}
await _writeDocument(
client: client,
collection: collection,
documentId: docId,
data: doc,
merge: merge,
result: result,
index: i,
);
if ((i + 1) % 10 == 0 || i == documents.length - 1) {
stdout.write('\rProgress: ${i + 1}/${documents.length}');
}
}
stdout.writeln();
result.printSummary(verbose: verbose);
return result.hasErrors ? 1 : 0;
} on Exception catch (e) {
stderr.writeln('Error: $e');
return 2;
}
}