Improve initialization and environment variable handling#182
Improve initialization and environment variable handling#182shhreya13 wants to merge 1 commit intoAOSSIE-Org:mainfrom
Conversation
📝 WalkthroughWalkthroughThe pull request enhances Changes
Sequence DiagramsequenceDiagram
participant Main as main()
participant EnvLoader as Environment<br/>Loader
participant Services as Supabase &<br/>Gemini
participant Repos as Repository<br/>Factory
participant Providers as Provider<br/>Setup
participant App as MaterialApp
Main->>EnvLoader: Load & validate .env
alt Validation Success
EnvLoader-->>Main: Variables loaded
Main->>Services: Initialize Supabase<br/>& Gemini
Services-->>Main: Services ready
Main->>Repos: Create repositories
Repos-->>Main: supabaseClient,<br/>patientRepository,<br/>authRepository
Main->>Providers: Setup providers with<br/>repository instances
Providers-->>Main: Providers configured
Main->>App: Run app with<br/>initialRoute & routes
App-->>Main: App launched
else Validation Fails
EnvLoader-->>Main: Missing variables
Main->>Main: Log debug message
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
patient/lib/main.dart (1)
27-34: Improve validation to identify which variable is missing and catch empty strings.The current error message doesn't specify which environment variable is missing, making debugging harder. Additionally, empty strings would pass validation but fail at runtime.
♻️ Proposed improvement for more specific validation
final supabaseUrl = dotenv.env['SUPABASE_URL']; final supabaseKey = dotenv.env['SUPABASE_ANON_KEY']; final geminiKey = dotenv.env['GEMINI_API_KEY']; // Validate env variables - if (supabaseUrl == null || supabaseKey == null || geminiKey == null) { - throw Exception("Missing environment variables in .env file"); - } + final missingVars = <String>[]; + if (supabaseUrl == null || supabaseUrl.isEmpty) { + missingVars.add('SUPABASE_URL'); + } + if (supabaseKey == null || supabaseKey.isEmpty) { + missingVars.add('SUPABASE_ANON_KEY'); + } + if (geminiKey == null || geminiKey.isEmpty) { + missingVars.add('GEMINI_API_KEY'); + } + if (missingVars.isNotEmpty) { + throw Exception("Missing or empty environment variables in .env file: ${missingVars.join(', ')}"); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@patient/lib/main.dart` around lines 27 - 34, The environment validation currently checks only for null on dotenv.env['SUPABASE_URL']/['SUPABASE_ANON_KEY']/['GEMINI_API_KEY'] (supabaseUrl, supabaseKey, geminiKey) and throws a generic Exception; change it to treat null or empty/whitespace-only strings as missing by trimming each value and collecting the names of any missing vars, then throw an Exception that lists which specific variables are missing (e.g., "Missing environment variables: SUPABASE_URL, GEMINI_API_KEY") so callers know exactly which env vars to fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@patient/lib/main.dart`:
- Around line 104-106: The catch block in main() currently only logs
initialization errors and returns, leaving the UI blank; update the catch to
call runApp() with a simple error UI so users see feedback instead of a frozen
screen. Create or use an InitializationErrorScreen (or similar) widget that
accepts the error/stack message, and in the catch (e, s) replace debugPrint(...)
with runApp(InitializationErrorScreen(error: e.toString(), stack: s.toString()))
(or wrap it in a small MaterialApp) so the app always renders a visible error
page when initialization (e.g., in main(), Supabase setup, or .env loading)
fails. Ensure you capture both exception and stack (catch (e, s)) and keep the
debugPrint but still call runApp to display the error widget.
- Around line 55-63: setupDependencyInjection currently registers
SupabasePatientRepository but not AuthRepository, causing manual instantiation
in main.dart to produce duplicate instances; update dependency_injector.dart to
register AuthRepository (mapping AuthRepository to SupabaseAuthRepository) and
then in main.dart stop creating new
SupabasePatientRepository/SupabaseAuthRepository instances and instead resolve
both repositories from getIt (e.g., getIt<PatientRepository>() and
getIt<AuthRepository>()) so providers receive the singleton instances and
chat_manager.dart's getIt<PatientRepository>() returns the same object.
---
Nitpick comments:
In `@patient/lib/main.dart`:
- Around line 27-34: The environment validation currently checks only for null
on dotenv.env['SUPABASE_URL']/['SUPABASE_ANON_KEY']/['GEMINI_API_KEY']
(supabaseUrl, supabaseKey, geminiKey) and throws a generic Exception; change it
to treat null or empty/whitespace-only strings as missing by trimming each value
and collecting the names of any missing vars, then throw an Exception that lists
which specific variables are missing (e.g., "Missing environment variables:
SUPABASE_URL, GEMINI_API_KEY") so callers know exactly which env vars to fix.
| // Setup dependency injection | ||
| setupDependencyInjection(); | ||
|
|
||
| // Create shared repositories | ||
| final supabaseClient = Supabase.instance.client; | ||
| final patientRepository = | ||
| SupabasePatientRepository(supabaseClient: supabaseClient); | ||
| final authRepository = | ||
| SupabaseAuthRepository(supabaseClient: supabaseClient); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if getIt is used elsewhere in the codebase to retrieve repositories
rg -n "getIt<" --type=dart -g '!**/dependency_injector.dart'Repository: AOSSIE-Org/NeuroTrack
Length of output: 340
🏁 Script executed:
# Find the dependency injection setup file
fd -e dart | xargs grep -l "setupDependencyInjection"Repository: AOSSIE-Org/NeuroTrack
Length of output: 208
🏁 Script executed:
# Look at main.dart more broadly to understand the context
find . -name "main.dart" -path "*/patient/*" -type fRepository: AOSSIE-Org/NeuroTrack
Length of output: 88
🏁 Script executed:
# Check the provider definitions to see how repositories are passed
rg -n "PatientRepository\|AuthRepository" --type=dart -A 3 patient/lib/main.dartRepository: AOSSIE-Org/NeuroTrack
Length of output: 47
🏁 Script executed:
# Read the dependency injector to see what gets registered
cat -n patient/lib/core/utils/dependency_injector.dartRepository: AOSSIE-Org/NeuroTrack
Length of output: 597
🏁 Script executed:
# Read main.dart to see the full context around lines 55-63 and how repositories are used
cat -n patient/lib/main.dart | head -100Repository: AOSSIE-Org/NeuroTrack
Length of output: 4065
Redundant repository instantiation creates inconsistent dependency management across the codebase.
setupDependencyInjection() registers SupabasePatientRepository as a singleton in GetIt, but lines 59-63 create new instances that are passed to providers. This results in:
- Two separate
SupabasePatientRepositoryinstances in memory - Providers use the manually created instance
chat_manager.dartusesgetIt<PatientRepository>(), retrieving a different instance- Inconsistent state management if changes occur in one instance
Update setupDependencyInjection() to also register AuthRepository, then retrieve both repositories from GetIt instead of creating them manually:
// Setup dependency injection
setupDependencyInjection();
- // Create shared repositories
- final supabaseClient = Supabase.instance.client;
- final patientRepository =
- SupabasePatientRepository(supabaseClient: supabaseClient);
- final authRepository =
- SupabaseAuthRepository(supabaseClient: supabaseClient);
+ // Retrieve shared repositories from GetIt
+ final patientRepository = getIt<PatientRepository>();
+ final authRepository = getIt<AuthRepository>();This requires updating setupDependencyInjection() in dependency_injector.dart to register AuthRepository.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@patient/lib/main.dart` around lines 55 - 63, setupDependencyInjection
currently registers SupabasePatientRepository but not AuthRepository, causing
manual instantiation in main.dart to produce duplicate instances; update
dependency_injector.dart to register AuthRepository (mapping AuthRepository to
SupabaseAuthRepository) and then in main.dart stop creating new
SupabasePatientRepository/SupabaseAuthRepository instances and instead resolve
both repositories from getIt (e.g., getIt<PatientRepository>() and
getIt<AuthRepository>()) so providers receive the singleton instances and
chat_manager.dart's getIt<PatientRepository>() returns the same object.
| } catch (e) { | ||
| debugPrint("App initialization failed: $e"); | ||
| } |
There was a problem hiding this comment.
App fails silently if initialization errors occur - no UI is shown.
If any initialization step throws (e.g., missing .env file, Supabase connection failure), the app only logs to debug console and exits the main() function without calling runApp(). The user sees a blank/frozen screen with no feedback.
The PR objective was to "prevent crashes caused by missing .env variables," but this implementation still leaves the app in an unusable state.
🐛 Proposed fix: Show an error screen to the user
} catch (e) {
debugPrint("App initialization failed: $e");
+ runApp(
+ MaterialApp(
+ home: Scaffold(
+ body: Center(
+ child: Padding(
+ padding: const EdgeInsets.all(24.0),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Icon(Icons.error_outline, size: 64, color: Colors.red),
+ const SizedBox(height: 16),
+ const Text(
+ 'Initialization Failed',
+ style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
+ ),
+ const SizedBox(height: 8),
+ Text(
+ e.toString(),
+ textAlign: TextAlign.center,
+ style: const TextStyle(color: Colors.grey),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch (e) { | |
| debugPrint("App initialization failed: $e"); | |
| } | |
| } catch (e) { | |
| debugPrint("App initialization failed: $e"); | |
| runApp( | |
| MaterialApp( | |
| home: Scaffold( | |
| body: Center( | |
| child: Padding( | |
| padding: const EdgeInsets.all(24.0), | |
| child: Column( | |
| mainAxisAlignment: MainAxisAlignment.center, | |
| children: [ | |
| const Icon(Icons.error_outline, size: 64, color: Colors.red), | |
| const SizedBox(height: 16), | |
| const Text( | |
| 'Initialization Failed', | |
| style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), | |
| ), | |
| const SizedBox(height: 8), | |
| Text( | |
| e.toString(), | |
| textAlign: TextAlign.center, | |
| style: const TextStyle(color: Colors.grey), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@patient/lib/main.dart` around lines 104 - 106, The catch block in main()
currently only logs initialization errors and returns, leaving the UI blank;
update the catch to call runApp() with a simple error UI so users see feedback
instead of a frozen screen. Create or use an InitializationErrorScreen (or
similar) widget that accepts the error/stack message, and in the catch (e, s)
replace debugPrint(...) with runApp(InitializationErrorScreen(error:
e.toString(), stack: s.toString())) (or wrap it in a small MaterialApp) so the
app always renders a visible error page when initialization (e.g., in main(),
Supabase setup, or .env loading) fails. Ensure you capture both exception and
stack (catch (e, s)) and keep the debugPrint but still call runApp to display
the error widget.
Closes #181
This PR improves the initialization process in main.dart by:
This prevents crashes caused by missing
.envvariables and improves developer experience for contributors.Summary by CodeRabbit
Release Notes
Updates
Improvements