From 54a4e3400d85ea10a132450978bd893fe0fea171 Mon Sep 17 00:00:00 2001 From: samedson Date: Fri, 3 Oct 2025 15:47:24 -0400 Subject: [PATCH 1/3] Attempt to run the Firebase CLI via npx if it's not installed --- .../flutterfire_cli/lib/src/firebase.dart | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/flutterfire_cli/lib/src/firebase.dart b/packages/flutterfire_cli/lib/src/firebase.dart index f282ce69..2b5143ca 100644 --- a/packages/flutterfire_cli/lib/src/firebase.dart +++ b/packages/flutterfire_cli/lib/src/firebase.dart @@ -42,6 +42,21 @@ Future exists() async { return _existsCache = process.exitCode == 0; } +/// Check to verify npx is installed. +bool? _npxExistsCache; +Future npxExists() async { + if (_npxExistsCache != null) { + return _npxExistsCache!; + } + final process = await Process.run( + 'npx', + ['--version'], + runInShell: true, + ); + return _npxExistsCache = process.exitCode == 0; +} + + /// Tries to read the default Firebase project id from the /// .firbaserc file at the root of the dart project if it exists. Future getDefaultFirebaseProjectId() async { @@ -72,13 +87,6 @@ Future> runFirebaseCommand( String? account, String? serviceAccount, }) async { - final cliExists = await exists(); - if (!cliExists) { - throw FirebaseCommandException( - '--version', - logMissingFirebaseCli, - ); - } final workingDirectoryPath = Directory.current.path; final execArgs = [ ...commandAndArgs, @@ -87,6 +95,33 @@ Future> runFirebaseCommand( if (account != null) '--account=$account', ]; + final cliExists = await exists(); + if (!cliExists) { + // If the CLI isn't installed, we can attempt to run it via npx which will + // use the newest Firebase CLI version + final npxExists = await npxExists(); + if (!npxExists) { + throw FirebaseCommandException( + '--version', + logMissingFirebaseCli, + ); + } + final npxExecArgs = [ + 'firebase-tools@latest' + ...execArgs, + ]; + process = await Process.run( + 'npx', + execArgs, + workingDirectory: workingDirectoryPath, + environment: { + if (serviceAccount != null) + 'GOOGLE_APPLICATION_CREDENTIALS': serviceAccount, + }, + runInShell: true, + ); + } + ProcessResult process; try { process = await Process.run( From 830e1d04bef9f30a4a0f1b3b67a6342bcb3db231 Mon Sep 17 00:00:00 2001 From: samedson Date: Fri, 3 Oct 2025 15:50:44 -0400 Subject: [PATCH 2/3] Space --- packages/flutterfire_cli/lib/src/firebase.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/flutterfire_cli/lib/src/firebase.dart b/packages/flutterfire_cli/lib/src/firebase.dart index 2b5143ca..38b7ef54 100644 --- a/packages/flutterfire_cli/lib/src/firebase.dart +++ b/packages/flutterfire_cli/lib/src/firebase.dart @@ -56,7 +56,6 @@ Future npxExists() async { return _npxExistsCache = process.exitCode == 0; } - /// Tries to read the default Firebase project id from the /// .firbaserc file at the root of the dart project if it exists. Future getDefaultFirebaseProjectId() async { @@ -99,8 +98,8 @@ Future> runFirebaseCommand( if (!cliExists) { // If the CLI isn't installed, we can attempt to run it via npx which will // use the newest Firebase CLI version - final npxExists = await npxExists(); - if (!npxExists) { + final npxCliExists = await npxExists(); + if (!npxCliExists) { throw FirebaseCommandException( '--version', logMissingFirebaseCli, @@ -112,7 +111,7 @@ Future> runFirebaseCommand( ]; process = await Process.run( 'npx', - execArgs, + npxExecArgs, workingDirectory: workingDirectoryPath, environment: { if (serviceAccount != null) From 80e524ca152ded0176a52d4eca4e973334f9daf4 Mon Sep 17 00:00:00 2001 From: samedson Date: Fri, 3 Oct 2025 16:06:02 -0400 Subject: [PATCH 3/3] Better code --- packages/flutterfire_cli/lib/src/firebase.dart | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/flutterfire_cli/lib/src/firebase.dart b/packages/flutterfire_cli/lib/src/firebase.dart index 38b7ef54..e60c7772 100644 --- a/packages/flutterfire_cli/lib/src/firebase.dart +++ b/packages/flutterfire_cli/lib/src/firebase.dart @@ -87,7 +87,8 @@ Future> runFirebaseCommand( String? serviceAccount, }) async { final workingDirectoryPath = Directory.current.path; - final execArgs = [ + var command = 'firebase'; + var execArgs = [ ...commandAndArgs, '--json', if (project != null) '--project=$project', @@ -105,26 +106,17 @@ Future> runFirebaseCommand( logMissingFirebaseCli, ); } - final npxExecArgs = [ + command = 'npx' + execArgs = [ 'firebase-tools@latest' ...execArgs, ]; - process = await Process.run( - 'npx', - npxExecArgs, - workingDirectory: workingDirectoryPath, - environment: { - if (serviceAccount != null) - 'GOOGLE_APPLICATION_CREDENTIALS': serviceAccount, - }, - runInShell: true, - ); } ProcessResult process; try { process = await Process.run( - 'firebase', + command, execArgs, workingDirectory: workingDirectoryPath, environment: {