API client providers (coreApiClientProvider, tatlockApiClientProvider) now use keepAlive: true. This fixes "DioException [unknown]: null" errors on pages like /security/users where ref.read() was used without subscription. The AuthInterceptor stores a Ref that became invalid when the provider auto-disposed after a one-time read. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
64 lines
1.7 KiB
Dart
64 lines
1.7 KiB
Dart
import 'package:dio/dio.dart';
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:tatlock_ui/core/api/api_interceptors.dart';
|
|
import 'package:tatlock_ui/core/config/app_config.dart';
|
|
|
|
import 'api_client_native.dart' if (dart.library.html) 'api_client_web.dart'
|
|
as platform;
|
|
|
|
part 'api_client.g.dart';
|
|
|
|
/// Provides the Dio instance for Core API.
|
|
///
|
|
/// Uses keepAlive to prevent auto-dispose - the AuthInterceptor stores
|
|
/// a Ref that must remain valid for the lifetime of API requests.
|
|
@Riverpod(keepAlive: true)
|
|
Dio coreApiClient(Ref ref) {
|
|
final options = BaseOptions(
|
|
baseUrl: AppConfig.coreApiUrl,
|
|
connectTimeout: const Duration(seconds: 10),
|
|
receiveTimeout: const Duration(seconds: 30),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
);
|
|
|
|
final dio = platform.createDio(options);
|
|
|
|
dio.interceptors.addAll([
|
|
AuthInterceptor(ref),
|
|
LoggingInterceptor(),
|
|
ErrorInterceptor(),
|
|
]);
|
|
|
|
return dio;
|
|
}
|
|
|
|
/// Provides the Dio instance for Tatlock API.
|
|
///
|
|
/// Uses keepAlive to prevent auto-dispose - the AuthInterceptor stores
|
|
/// a Ref that must remain valid for the lifetime of API requests.
|
|
@Riverpod(keepAlive: true)
|
|
Dio tatlockApiClient(Ref ref) {
|
|
final options = BaseOptions(
|
|
baseUrl: AppConfig.tatlockApiUrl,
|
|
connectTimeout: const Duration(seconds: 10),
|
|
receiveTimeout: const Duration(minutes: 5), // Longer for LLM responses
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
);
|
|
|
|
final dio = platform.createDio(options);
|
|
|
|
dio.interceptors.addAll([
|
|
AuthInterceptor(ref),
|
|
LoggingInterceptor(),
|
|
ErrorInterceptor(),
|
|
]);
|
|
|
|
return dio;
|
|
}
|