diff --git a/packages/flutterfire_cli/lib/src/firebase/firebase_dart_options.dart b/packages/flutterfire_cli/lib/src/firebase/firebase_dart_options.dart index 31aaa449..e579cd54 100644 --- a/packages/flutterfire_cli/lib/src/firebase/firebase_dart_options.dart +++ b/packages/flutterfire_cli/lib/src/firebase/firebase_dart_options.dart @@ -65,9 +65,15 @@ extension FirebaseDartOptions on FirebaseOptions { var jsonBody = ''; if (match != null) { jsonBody = match.namedGroup('jsonBody')!; + return FirebaseOptions.fromMap( + const JsonDecoder().convert('{$jsonBody}') as Map, + ); + } else { + // Handle new JSON format introduced in Firebase CLI v13.31.0 + // The config is now returned as direct JSON instead of JavaScript format + return FirebaseOptions.fromMap( + const JsonDecoder().convert(appSdkConfig.fileContents) as Map, + ); } - return FirebaseOptions.fromMap( - const JsonDecoder().convert('{$jsonBody}') as Map, - ); } } diff --git a/packages/flutterfire_cli/test/firebase_dart_options_test.dart b/packages/flutterfire_cli/test/firebase_dart_options_test.dart new file mode 100644 index 00000000..a03cd139 --- /dev/null +++ b/packages/flutterfire_cli/test/firebase_dart_options_test.dart @@ -0,0 +1,76 @@ +import 'package:flutterfire_cli/src/firebase.dart'; +import 'package:flutterfire_cli/src/firebase/firebase_dart_options.dart'; +import 'package:test/test.dart'; + +void main() { + group('FirebaseDartOptions', () { + group('convertConfigToOptions', () { + test('parses traditional JavaScript format correctly', () { + final config = FirebaseAppSdkConfig( + fileName: 'firebase-config.js', + fileContents: ''' +firebase.initializeApp({ + "projectId": "test-project", + "appId": "1:1234567890:web:abcdef1234567890", + "apiKey": "test-api-key", + "authDomain": "test-project.firebaseapp.com", + "messagingSenderId": "1234567890", + "measurementId": "G-ABCDEF1234" +});''', + ); + + final options = FirebaseDartOptions.convertConfigToOptions( + config, + 'test-project', + ); + + expect(options.projectId, 'test-project'); + expect(options.appId, '1:1234567890:web:abcdef1234567890'); + expect(options.apiKey, 'test-api-key'); + expect(options.messagingSenderId, '1234567890'); + expect(options.measurementId, 'G-ABCDEF1234'); + }); + + test('parses new JSON format correctly', () { + final config = FirebaseAppSdkConfig( + fileName: 'firebase-config.json', + fileContents: ''' +{ + "projectId": "test-project", + "appId": "1:1234567890:web:abcdef1234567890", + "apiKey": "test-api-key", + "authDomain": "test-project.firebaseapp.com", + "messagingSenderId": "1234567890", + "measurementId": "G-ABCDEF1234" +}''', + ); + + final options = FirebaseDartOptions.convertConfigToOptions( + config, + 'test-project', + ); + + expect(options.projectId, 'test-project'); + expect(options.appId, '1:1234567890:web:abcdef1234567890'); + expect(options.apiKey, 'test-api-key'); + expect(options.messagingSenderId, '1234567890'); + expect(options.measurementId, 'G-ABCDEF1234'); + }); + + test('throws FirebaseCommandException for invalid format', () { + final config = FirebaseAppSdkConfig( + fileName: 'invalid-config.txt', + fileContents: 'Invalid config format', + ); + + expect( + () => FirebaseDartOptions.convertConfigToOptions( + config, + 'test-project', + ), + throwsA(isA()), + ); + }); + }); + }); +} \ No newline at end of file